Linux驱动程序--SPI设备
硬件平台: am335x
内核版本:linux-3.8.13
编译器版本: arm-linux-gnueabihf-gcc
1.注册驱动程序
// 设备匹配列表
static const struct of_device_id spidev_dt_ids[] = {
{ .compatible = "oroct,uart" },
{},
};
// spi驱动结构
static struct spi_driver spidev_spi_driver = {
.driver = {
.name = "oroct_spi", // 这个名子不重要了
.of_match_table = of_match_ptr(spidev_dt_ids),
},
.probe = spidev_probe, // 探测函数
.remove = spidev_remove, // 移除函数
};
static int __init hnsw_spidev_init(void)
{
int ret;
// 注册SPI驱动程序
ret = spi_register_driver(&spidev_spi_driver);
pr_info("spi_register_driver.ret = %d\r\n",ret);
return ret;
}
static void __exit hnsw_spidev_exit(void)
{
// 注销SPI驱动
spi_unregister_driver(&spidev_spi_driver);
}
module_init(hnsw_spidev_init);
module_exit(hnsw_spidev_exit);
2.添加代码树
&spi1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mcspi1_pins>;
// 之前添加的spidev设备
spidev@0 {
status = "okay";
compatible = "rohm,dh2228fv";
spi-max-frequency=<24000000>;
reg = <0>;
};
// 在这里添加新的spi接口的设备
spiuart@1 {
status = "okay";
compatible = "oroct,uart";
spi-max-frequency=<24000000>;
reg = <1>; // 片选线SPI_nCS1
};
3.设备探测函数
static int spidev_probe(struct spi_device *spi)
{
}
SPI收发处理
static void spidev_complete(void *arg)
{
complete(arg);
}
/* spi收发 */
static ssize_t
spidev_sync(struct spidev_data *spidev, struct spi_message *message)
{
DECLARE_COMPLETION_ONSTACK(done);
int status;
message->complete = spidev_complete; // 消息结束回调函数
message->context = &done;
spin_lock_irq(&spidev->spi_lock);
if (spidev->spi == NULL) {
status = -ESHUTDOWN;
}
else {
status = spi_async(spidev->spi, message); // 这一句才是干货
}
spin_unlock_irq(&spidev->spi_lock);
if (status == 0) {
wait_for_completion(&done);
status = message->status;
if (status == 0)
status = message->actual_length;
}
return status;
}
//----------------------------------------------------------
/* spi发送操作 */
static inline ssize_t
spidev_sync_write(struct spidev_data* spidev, void* buff, int len)
{
struct spi_transfer t = {
.tx_buf = buff, // 发送缓存
.len = len,
};
// 标准的SPI收发流程
struct spi_message m;
spi_message_init(&m);
spi_message_add_tail(&t, &m);
return spidev_sync(spidev, &m);
}
/* spi接收操作 */
static inline ssize_t
spidev_sync_read(struct spidev_data* spidev, void* buff, int len)
{
struct spi_transfer t = {
.rx_buf = buff, // 接收缓存
.len = len,
};
// 标准的SPI收发流程
struct spi_message m;
spi_message_init(&m);
spi_message_add_tail(&t, &m);
return spidev_sync(spidev,&m);
}