linux内核SPI总线驱动分析

1、SPI概述

SPI是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口,SPI

是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线。通信方式为主

从式通常是1个主设备、1个或多个从设备。SDI(数据输入),SDO(数据输出),SCLK(时钟),

CS(片选)。

2、Linux SPI 驱动总体架构

SPI的驱动架构可以分为如下层次:SPI核心层、SPI控制器驱动层、SPI设备驱动层。

2.1、SPI核心层

SPI核心层是Linux 内核SPI的核心部分,提供了核心数据结构的定义、SPI控制器驱动和
设备驱动的注册和注销接口。向下屏蔽 了物理总线 的差异,向上提供了统一的接口,以便设备
驱动通过总线控制器进行数据读写。

2.2、SPI控制器驱动层

SPI控制器驱动层,每种平台都有属于自己的控制器驱动。它的职责是为系统中每条SPI
总线提 供具体的读写方法。在物理上, 每个SPI控制器可以连接若干个SPI从设备。
系统开机时,控制器驱动首先被加载。一个控制器驱动用于一条特定的SPI总线的读写,
一个控制器驱动可以用
struct spi_master 来描述。
数据结构struct spi_master
struct spi_master {
struct device dev;
s16 bus_num;
u16 num_chipselect;
int
(*setup) (struct spi_device *spi);
int
(*transfer) (struct spi_device *spi, struct spi_message *mesg);
void (*cleanup)(struct spi_device *spi);
};
bus_num表示控制器对应的总线号。
num_chipselect表示控制器可以支持多少个SPI设备。
setup函数用于设置控制器相关的工作时钟、传输模式等。
transfer函数是实现SPI总线读写方法的函数,实现数据的双向传输。

cleanup函数为控制器驱动注销时调用,针对驱动初始化时申请的一些内核资源进行清理恢
复工作。

2.3、SPI设备驱动层

SPI设备驱动层为用户接口层,其为用户提供了通过SPI总线访问具体设备的接口。
SPI设备驱动层可以用两个数据结构来描述,struct spi_driver 和 struct spi_device
  1. struct spi_driver {  
  2.     int         (*probe)(struct spi_device *spi);  
  3.     int         (*remove)(struct spi_device *spi);  
  4.     void            (*shutdown)(struct spi_device *spi);  
  5.     int         (*suspend)(struct spi_device *spi, pm_message_t mesg);  
  6.     int         (*resume)(struct spi_device *spi);  
  7.     struct device_driver    driver;  
  8. }; 
driver是为device服务的,spi_driver注册时会扫描spi bus上的设备,设备和驱动通过
名字 进行匹配绑定。
probe函数用于驱动和设备匹配时被调用。SPI通信是通过消息队列,而不像i2c通过
与从 设备对话方式来实现 数据交互。
  1. struct spi_device {  
  2.     struct device         dev;  
  3.     struct spi_master   *master;  
  4.     u32                      max_speed_hz;  
  5.     u8                       chip_select;  
  6.     u8                       mode;    
  7.     u8                       bits_per_word;  
  8.     int                       irq;  
  9.     void                    *controller_state;  
  10.     void                    *controller_data;  
  11.     char                    modalias[32];   
  12. }; 
通常spi_device对应SPI bus上某个特定的spi设备。并且spi_device封装了一个
spi_master结 构体。spi_device包含了该spi 设备特定的私有属性,比如它的最大频率,
片选,输入输出模 式等等。

spi_device的板信息用spi_board_info结构体来描述:
struct spi_board_info {
      char modalias[SPI_NAME_SIZE];
        const void*      platform_data;
void*               controller_data;
int                   irq;
u32                 max_speed_hz;
u16                 bus_num;
u16                 chip_select;
      u8                mode;
};
这个结构体记录了SPI外设使用的主机控制器序号、片选信号、数据比特率、SPI传输方式等

spi_board_info结构体通过spi_register_board_info函数注册到链表board_list上。

2.4枚举过程

drivers/spi/spi.c:
    spi_register_board_info
        /* 对于每一个spi_master,调用spi_match_master_to_boardinfo */
        list_for_each_entry(master, &spi_master_list, list)
            spi_match_master_to_boardinfo
            /* board_info里含有bus_num, 如果某个spi_master的bus_num跟它一样
             * 则创建一个新的spi_device
             */
                    if (master->bus_num == bi->busnum)
                        spi_new_device
                            spi_alloc_device
                            /* 记录bi信息, 比如片选,MODE,MAX HZ */    
                            spi_add_device /* 根据名字找到spi_driver, 调用它的probe函数 */
                                spi_setup(spi);

                                device_add  /* 会绑定到一个spi_driver */


2.5数据收发过程

    spi_write
        spi_message_init(&m);
        初始化一个spi_message  /* 一个不可打断的SPI传输过程: cs=0,传数据,cs=1 */
                               /* 一个spi_message由多个spi_transfer组成 */
        spi_message_add_tail(&t, &m);  /* spi_transfe是SPI上传输的单方向1个或多个字节 */
        spi_sync(spi, &m);  /* 启动传输并等待完成 */
    

2.6 spi_driver如何调用spi_controller

    spi_sync
        __spi_sync(spi, message, 0);
            spi_async_locked
                __spi_async
                    master->transfer(spi, message);
            wait_for_completion

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值