Linux 驱动之 SPI 子系统

Linux SPI 驱动框架

对于 SPI 的驱动框架与 I2C 是大致一致的,也分为两层,控制器驱动程序层叫 spi_controller ,主要提供 transfer 函数,进行 spi 协议的收发。

另一层是设备驱动层,基于 spi_bus_type,在 driver 里则使用 spi_read、spi_writer 等函数,最终也会调用到 controller->transfer 函数进行发送接收。

数据结构

整体数据结构如下:原图

  • spi_controller 结构体用于描述一个 spi 控制器,可以类比 iic 的 i2c_adapt。
  • spi_device 结构体用于描述一个 spi 设备,可以类比于 i2c_client 结构体。

spi_device 结构里有个 mode 很重要下面是其详细描述,SPI 模式主要有两个特征:

  • CPOL:这是时钟极性:
    • 0:初始时钟状态为低电平,第一个时钟边沿是上升沿
    • 1:初始时钟状态为高电平,第一个时钟边沿是下降沿
  • CPHA:这是时钟相位,选择在哪个边沿采样数据:
    • 0:数据在下降沿锁存,输出在上升沿改变
    • 1:数据在上升沿锁存,并在下降沿输出

这有四种 SPI 模式,如下:

  • spi_driver 用于驱动 spi 设备,可以类比 i2c_driver 结构体。
  • spi_message 用于描述 spi 传输的消息,由多个 spi_transfer 段组成,可以类比 i2c_message 结构体。
  • spi_transfer 代表一个读写缓冲对,包含接收缓冲区及发送缓冲区,其实,spi_transfer 的发送是通过构建 spi_message 实现,通过将 spi_transfer 中的链 transfer_list 链接到 spi_message 中的 transfers,再以 spi_message 形势向底层发送数据。

实现

关于 spi 的实现其实也是分为 controller 和设备及设备驱动这三部分,controller 一般由 soc 厂商编写好了驱动通过 spi_register_controller 向内核注册一个 controller 设备并挂载在 spi_bus 总线下,而 device 和 device_driver 的实现根 platform 或 iic 的实现也是大同小异,这里不做详细的分析了,感兴趣的可以查看内核源码。

参考文献

https://www.wikiwand.com/zh-cn/%E5%BA%8F%E5%88%97%E5%91%A8%E9%82%8A%E4%BB%8B%E9%9D%A2
https://blog.csdn.net/lizuobin2/article/details/51735963
https://blog.csdn.net/zhoutaopower/article/details/99866773
《Linux 设备驱动开发》