当前位置:   article > 正文

Linux SPI 驱动分析(1)— 结构框架_spi transfer

spi transfer

目录

1、总线互联拓扑结构

1.1、硬件拓扑

1.2、软件抽象

2、SPI 软件驱动层次

3、数据结构

3.1、spi_controller (spi_master)

3.2、spi_device

3.3、spi_driver

3.4、spi_board_info

3.5、spi_transfer

3.6、spi_message

3.7、数据结构之间的关系

4、对外接口 APIs


 

SPI 属于高速串行全双工的接口,在 SoC 中广泛存在,关于更多 SPI 的内容可以参考《STM32F103ZET6 — SPI》,这里介绍了关于 SPI 的一些基本内容。

本章主要分析 Linux SPI 驱动框架部分。

SPI 和 platform 一样(Linux设备模型(5) — platform bus/device/driver),属于总线的一类,所以他们类似,不过 SPI 有他自己的框架,我们依然从数据结构和相关的 API 入手,着重分析 SPI 相关的架构。

Linux SPI 驱动结构中,将 SPI 相关的驱动分为了几部分:

1、SPI 主机以及主机驱动:SoC 的 SPI Controller 部分的驱动

2、SPI 外设驱动描述:比如 SPI Flash 驱动

3、SPI 从设备描述:比如 SPI Flash 设备

4、SPI 传输层描述:spi_transfer 和 spi_message 组成

 

1、总线互联拓扑结构

1.1、硬件拓扑

首先需要明确的是,硬件上来说,对于一款 SoC 来说,一般的,都会集成不止一路 SPI Controller(比如,SPI_0/SPI_1/SPI_2),用于控制不同的外设;而 SPI 是一种总线规范,每一路 SPI 都可以接 N 个不同的外设,通过 CS 片选信号,来选择具体与哪一个连接到这个 SPI 总线的设备通信;总线拓扑结构如下:

1.2、软件抽象

软件上,对硬件进行了合理的抽象:

1、spi_master(spi_controller):对 SoC 的 SPI 控制器的抽象

2、spi_bus_type:spi 的 bus_type,代表了硬件上的 SPI Bus

3、spi_device:spi 从设备

4、spi_driver:spi 具体设备的驱动

 

2、SPI 软件驱动层次

首先需要明确的一点是,SPI 主机控制器部分是整个 SPI 系统的核心存在,它并不属于 SPI 下的 bus、device、drvier 这一组结构,因为他并不是挂接到 bus 上的 device,更不是对应挂接在 bus 上 device 的 driver,而是相对独立的一个存在,所以 SPI 控制器部分,是连接到 platform 下的,并执行 platform 的 probe;

注:这里可能会不好理解,因为做过单片机的朋友都知道,单片机上的 SPI 驱动,其实就是按照时序去配置寄存器,其实就是对 SPI 控制器的操作,这就是单片机上的 driver,在 Linux driver 结构下,这个 driver 并不单单的指代对控制器的寄存器配置的过程,而是将其抽象到了一个 deivce 对应到一个实际 driver 的这个角度。所以在这里,主机控制器的抽象其实在内核中是属于一个单独的 device,所以你可以把它挂接到 platform_device 上,并套用 platform 这套东西;

可以看到结构如上图所示,比如一个 SPI Flash 它就属于 spi_device 的范畴,针对这个 SPI Flash 的驱动具体业务,就属于 spi_driver 的范畴,而 SPI 主机控制器,只是提供了一组操作的通道,可以属于 platform device 的范畴。

 

3、数据结构

3.1、spi_controller (spi_master)

Linux driver 中,最新的内核代码中使用 spi_controller (以前是 spi_master 结构)来描述一个 SPI 的控制器,为了兼容以前的代码,直接:

#define spi_master            spi_controller

所以我们直接看最新的定义 spi_controller,他在 include/linux/spi/spi.h

  1. struct spi_controller {
  2. struct device dev;
  3. struct list_head list;
  4. /* other than negative (== assign one dynamically), bus_num is fully
  5. * board-specific. usually that simplifies to being SOC-specific.
  6. * example: one SOC has three SPI controllers, numbered 0..2,
  7. * and one board's schematics might show it using SPI-2. software
  8. * would normally use bus_num=2 for that controller.
  9. */
  10. s16 bus_num;
  11. /* chipselects will be integral to many controllers; some others
  12. * might use board-specific GPIOs.
  13. */
  14. u16 num_chipselect;
  15. /* some SPI controllers pose alignment requirements on DMAable
  16. * buffers; let protocol drivers know about these requirements.
  17. */
  18. u16 dma_alignment;
  19. /* spi_device.mode flags understood by this controller driver */
  20. u16 mode_bits;
  21. /* bitmask of supported bits_per_word for transfers */
  22. u32 bits_per_word_mask;
  23. #define SPI_BPW_MASK(bits) BIT((bits) - 1)
  24. #define SPI_BIT_MASK(bits) (((bits) == 32) ? ~0U : (BIT(bits) - 1))
  25. #define SPI_BPW_RANGE_MASK(min, max) (SPI_BIT_MASK(max) - SPI_BIT_MASK(min - 1))
  26. /* limits on transfer speed */
  27. u32 min_speed_hz;
  28. u32 max_speed_hz;
  29. /* other constraints relevant to this driver */
  30. u16 flags;
  31. #define SPI_CONTROLLER_HALF_DUPLEX BIT(0) /* can't do full duplex */
  32. #define SPI_CONTROLLER_NO_RX BIT(1) /* can't do buffer read */
  33. #define SPI_CONTROLLER_NO_TX BIT(2) /* can't do buffer write */
  34. #define SPI_CONTROLLER_MUST_RX BIT(3) /* requires rx */
  35. #define SPI_CONTROLLER_MUST_TX BIT(4) /* requires tx */
  36. #define SPI_MASTER_GPIO_SS BIT(5) /* GPIO CS must select slave */
  37. /* flag indicating this is an SPI slave controller */
  38. bool slave;
  39. /*
  40. * on some hardware transfer / message size may be constrained
  41. * the limit may depend on device transfer settings
  42. */
  43. size_t (*max_transfer_size)(struct spi_device *spi);
  44. size_t (*max_message_size)(struct spi_device *spi);
  45. /* I/O mutex */
  46. struct mutex io_mutex;
  47. /* lock and mutex for SPI bus locking */
  48. spinlock_t bus_lock_spinlock;
  49. struct mutex bus_lock_mutex;
  50. /* flag indicating that the SPI bus is locked for exclusive use */
  51. bool bus_lock_flag;
  52. /* Setup mode and clock, etc (spi driver may call many times).
  53. *
  54. * IMPORTANT: this may be called when transfers to another
  55. * device are active. DO NOT UPDATE SHARED REGISTERS in ways
  56. * which could break those transfers.
  57. */
  58. int (*setup)(struct spi_device *spi);
  59. /* bidirectional bulk transfers
  60. *
  61. * + The transfer() method may not sleep; its main role is
  62. * just to add the message to the queue.
  63. * + For now there's no remove-from-queue operation, or
  64. * any other request management
  65. * + To a given spi_device, message queueing is pure fifo
  66. *
  67. * + The controller's main job is to process its message queue,
  68. * selecting a chip (for masters), then transferring data
  69. * + If there are multiple spi_device children, the i/o queue
  70. * arbitration algorithm is unspecified (round robin, fifo,
  71. * priority, reservations, preemption, etc)
  72. *
  73. * + Chipselect stays active during the entire message
  74. * (unless modified by spi_transfer.cs_change != 0).
  75. * + The message transfers use clock and SPI mode parameters
  76. * previously established by setup() for this device
  77. */
  78. int (*transfer)(struct spi_device *spi,
  79. struct spi_message *mesg);
  80. /* called on release() to free memory provided by spi_controller */
  81. void (*cleanup)(struct spi_device *spi);
  82. /*
  83. * Used to enable core support for DMA handling, if can_dma()
  84. * exists and returns true then the transfer will be mapped
  85. * prior to transfer_one() being called. The driver should
  86. * not modify or store xfer and dma_tx and dma_rx must be set
  87. * while the device is prepared.
  88. */
  89. bool (*can_dma)(struct spi_controller *ctlr,
  90. struct spi_device *spi,
  91. struct spi_transfer *xfer);
  92. /*
  93. * These hooks are for drivers that want to use the generic
  94. * controller transfer queueing mechanism. If these are used, the
  95. * transfer() function above must NOT be specified by the driver.
  96. * Over time we expect SPI drivers to be phased over to this API.
  97. */
  98. bool queued;
  99. struct kthread_worker kworker;
  100. struct task_struct *kworker_task;
  101. struct kthread_work pump_messages;
  102. spinlock_t queue_lock;
  103. struct list_head queue;
  104. struct spi_message *cur_msg;
  105. bool idling;
  106. bool busy;
  107. bool running;
  108. bool rt;
  109. bool auto_runtime_pm;
  110. bool cur_msg_prepared;
  111. bool cur_msg_mapped;
  112. struct completion xfer_completion;
  113. size_t max_dma_len;
  114. int (*prepare_transfer_hardware)(struct spi_controller *ctlr);
  115. int (*transfer_one_message)(struct spi_controller *ctlr,
  116. struct spi_message *mesg);
  117. int (*unprepare_transfer_hardware)(struct spi_controller *ctlr);
  118. int (*prepare_message)(struct spi_controller *ctlr,
  119. struct spi_message *message);
  120. int (*unprepare_message)(struct spi_controller *ctlr,
  121. struct spi_message *message);
  122. int (*slave_abort)(struct spi_controller *ctlr);
  123. /*
  124. * These hooks are for drivers that use a generic implementation
  125. * of transfer_one_message() provied by the core.
  126. */
  127. void (*set_cs)(struct spi_device *spi, bool enable);
  128. int (*transfer_one)(struct spi_controller *ctlr, struct spi_device *spi,
  129. struct spi_transfer *transfer);
  130. void (*handle_err)(struct spi_controller *ctlr,
  131. struct spi_message *message);
  132. /* Optimized handlers for SPI memory-like operations. */
  133. const struct spi_controller_mem_ops *mem_ops;
  134. /* gpio chip select */
  135. int *cs_gpios;
  136. /* statistics */
  137. struct spi_statistics statistics;
  138. /* DMA channels for use with core dmaengine helpers */
  139. struct dma_chan *dma_tx;
  140. struct dma_chan *dma_rx;
  141. /* dummy data for full duplex devices */
  142. void *dummy_rx;
  143. void *dummy_tx;
  144. int (*fw_translate_cs)(struct spi_controller *ctlr, unsigned cs);
  145. };

源码中,注释写的非常详细,我们根据结构体的注释能够大致的知道他的含义,这里仅仅看几个关键的成员,其他成员用到的时候,加以解释:

dev:spi_controller 是一个 device,所以包含了一个 device 的实例,设备模型使用

list:链接到全局的 spi_controller list

bus_num:spi bus 的编号,比如某 SoC有3个 SPI 控制,那么这个结构描述的是第几个

num_chipselect:片选数量,决定该控制器下面挂接多少个SPI设备,从设备的片选号不能大于这个数量

mode_bits:SPI 控制器支持的 slave 的模式

min_speed_hz/max_speed_hz:最大最小速率

slave:是否是 slave

(*setup):主要设置SPI控制器和工作方式、clock等

(*transfer):添加消息到队列的方法。这个函数不可睡眠。它的职责是安排发生的传送并且调用注册的回调函 complete()。这个不同的控制器要具体实现,传输数据最后都要调用这个函数

(*cleanup):在spidev_release函数中被调用,spidev_release被登记为spi dev的release函数

 

3.2、spi_device

spi_device 用于描述一个挂接到 SPI 总线上的一个设备,他的结构是:

  1. struct spi_device {
  2. struct device dev;
  3. struct spi_controller *controller;
  4. struct spi_controller *master; /* compatibility layer */
  5. u32 max_speed_hz;
  6. u8 chip_select;
  7. u8 bits_per_word;
  8. u16 mode;
  9. #define SPI_CPHA 0x01 /* clock phase */
  10. #define SPI_CPOL 0x02 /* clock polarity */
  11. #define SPI_MODE_0 (0|0) /* (original MicroWire) */
  12. #define SPI_MODE_1 (0|SPI_CPHA)
  13. #define SPI_MODE_2 (SPI_CPOL|0)
  14. #define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
  15. #define SPI_CS_HIGH 0x04 /* chipselect active high? */
  16. #define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */
  17. #define SPI_3WIRE 0x10 /* SI/SO signals shared */
  18. #define SPI_LOOP 0x20 /* loopback mode */
  19. #define SPI_NO_CS 0x40 /* 1 dev/bus, no chipselect */
  20. #define SPI_READY 0x80 /* slave pulls low to pause */
  21. #define SPI_TX_DUAL 0x100 /* transmit with 2 wires */
  22. #define SPI_TX_QUAD 0x200 /* transmit with 4 wires */
  23. #define SPI_RX_DUAL 0x400 /* receive with 2 wires */
  24. #define SPI_RX_QUAD 0x800 /* receive with 4 wires */
  25. #define SPI_CS_WORD 0x1000 /* toggle cs after each word */
  26. int irq;
  27. void *controller_state;
  28. void *controller_data;
  29. char modalias[SPI_NAME_SIZE];
  30. const char *driver_override;
  31. int cs_gpio; /* chip select gpio */
  32. /* the statistics */
  33. struct spi_statistics statistics;
  34. /*
  35. * likely need more hooks for more protocol options affecting how
  36. * the controller talks to each chip, like:
  37. * - memory packing (12 bit samples into low bits, others zeroed)
  38. * - priority
  39. * - chipselect delays
  40. * - ...
  41. */
  42. };

他的成员相对 spi_controller 要少很多:

dev:device 结构,设备模型使用

controller:这个 spi device 挂在那个 SPI Controller 下

max_speed_hz:通讯时钟最大频率

chip_select:片选号,每个 master 支持多个 spi_device

mode:SPI device 的模式,时钟极性和时钟相位

bits_per_word:每个通信字的字长的比特数,默认是 8

irq:使用到的中断号

modalias:设备驱动的名字

由于一个SPI总线上可以有多个SPI设备,因此需要片选号来区分它们,SPI控制器根据片选号来选择不同的片选线,从而实现每次只同一个设备通信。

spi_device的mode成员有两个比特位含义很重要。SPI_CPHA选择对数据线采样的时机,0选择每个时钟周期的第一个沿跳变时采样数据,1选择第二个时钟沿采样数据;SPI_CPOL选择每个时钟周期开始的极性,0表示时钟以低电平开始,1选择高电平开始。这两个比特有四种组合,对应SPI_MODE_0~SPI_MODE_3。

另一个比较重要的成员是bits_per_word。这个成员指定每次读写的字长,单位是比特。虽然大部分SPI接口的字长是8或者16,仍然会有一些特殊的例子。需要说明的是,如果这个成员为零的话,默认使用8作为字长。
最后一个成员并不是设备的名字,而是需要绑定的驱动的名字。

 

3.3、spi_driver

spi_driver 代表一个驱动,他也挂接到了 spi bus 上,与对应的 spi_device 结构进行匹配后调用 probe,他的定义是:

  1. struct spi_driver {
  2. const struct spi_device_id *id_table;
  3. int (*probe)(struct spi_device *spi);
  4. int (*remove)(struct spi_device *spi);
  5. void (*shutdown)(struct spi_device *spi);
  6. struct device_driver driver;
  7. };

可以看到,其实就是最简单的成员,他并不提供任何与硬件的实际交互

 

3.4、spi_board_info

spi_device 的板信息用 spi_board_info 结构体描述,该结构体记录着SPI外设使用的主机控制器序号、片选序号、数据比特率、SPI传输模式(即CPOL、CPHA)等。ARM Linux3.x之后的内核在改为设备树之后,不再需要在arch/arm/mach-xxx中编码SPI的板级信息了,而倾向于在SPI控制器节点下填写子节点

如果定义了这个结构,然后在调用他的 register,并会分配并新建一个对应 spi_device,他的结构如下:

  1. struct spi_board_info {
  2. /* the device name and module name are coupled, like platform_bus;
  3. * "modalias" is normally the driver name.
  4. *
  5. * platform_data goes to spi_device.dev.platform_data,
  6. * controller_data goes to spi_device.controller_data,
  7. * device properties are copied and attached to spi_device,
  8. * irq is copied too
  9. */
  10. char modalias[SPI_NAME_SIZE];
  11. const void *platform_data;
  12. const struct property_entry *properties;
  13. void *controller_data;
  14. int irq;
  15. /* slower signaling on noisy or low voltage boards */
  16. u32 max_speed_hz;
  17. /* bus_num is board specific and matches the bus_num of some
  18. * spi_controller that will probably be registered later.
  19. *
  20. * chip_select reflects how this chip is wired to that master;
  21. * it's less than num_chipselect.
  22. */
  23. u16 bus_num;
  24. u16 chip_select;
  25. /* mode becomes spi_device.mode, and is essential for chips
  26. * where the default of SPI_CS_HIGH = 0 is wrong.
  27. */
  28. u16 mode;
  29. /* ... may need additional spi_device chip config data here.
  30. * avoid stuff protocol drivers can set; but include stuff
  31. * needed to behave without being bound to a driver:
  32. * - quirks like clock rate mattering when not selected
  33. */
  34. };

他成员的内容几乎和 spi_device 一致,不再多说;

 

3.5、spi_transfer

spi_transfer 代表一个读写缓冲对,包含接收缓冲区及发送缓冲区,其实,spi_transfer的发送是通过构建spi_message实现,通过将spi_transfer中的链表transfer_list链接到spi_message中的transfers,再以spi_message形势向底层发送数据。每个spi_transfer都可以对传输的一些参数进行设置,使得master controller按照它要求的参数进行数据发送

  1. struct spi_transfer {
  2. /* it's ok if tx_buf == rx_buf (right?)
  3. * for MicroWire, one buffer must be null
  4. * buffers must work with dma_*map_single() calls, unless
  5. * spi_message.is_dma_mapped reports a pre-existing mapping
  6. */
  7. const void *tx_buf;
  8. void *rx_buf;
  9. unsigned len;
  10. dma_addr_t tx_dma;
  11. dma_addr_t rx_dma;
  12. struct sg_table tx_sg;
  13. struct sg_table rx_sg;
  14. unsigned cs_change:1;
  15. unsigned tx_nbits:3;
  16. unsigned rx_nbits:3;
  17. #define SPI_NBITS_SINGLE 0x01 /* 1bit transfer */
  18. #define SPI_NBITS_DUAL 0x02 /* 2bits transfer */
  19. #define SPI_NBITS_QUAD 0x04 /* 4bits transfer */
  20. u8 bits_per_word;
  21. u16 delay_usecs;
  22. u32 speed_hz;
  23. u16 word_delay;
  24. struct list_head transfer_list;
  25. };

tx_buf:发送缓冲区,要写入设备的数据(必须是dma_safe),或者为NULL

rx_buf:接收缓冲区,要读取的数据缓冲(必须是dma_safe),或者为NULL

len:缓冲区长度,tx和rx的大小(字节数)。这里不是指它的和,而是各自的长度,它们总是相等的

tx_dma:如果spi_message.is_dma_mapped是真,这个是tx的dma地址

rx_dma:如果spi_message.is_dma_mapped是真,这个是rx的dma地址

cs_change:1 :当前spi_transfer发送完成之后重新片选。影响此次传输之后的片选。指示本次transfer结束之后是否要重新片选并调用setup改变设置。这个标志可以减少系统开销

bits_per_word:每个字长的比特数,0代表使用spi_device中的默认值 8

delay_usecs:发送完成一个spi_transfer后延时时间,此次传输结束和片选改变之间的延时,之后就会启动另一个传输或者结束整个消息

speed_hz:通信时钟。如果是0,使用默认值

transfer_list:用于链接到spi_message,用来连接的双向链接节点

控制器驱动会先写入tx 的数据,然后读取同样长度的数据。长度指示是 len

如果tx_buff是空指针,填充rx_buff的时候会输出0(为了产生接收的时钟),如果rx_buff是NULL,接收到的数据将被丢弃

只有 len 长度的数据会被输出和接收

 

3.6、spi_message

spi_message 代表 spi 消息,由多个spi_transfer段组成。
spi_message用来原子的执行spi_transfer表示的一串数组传输请求。
这个传输队列是原子的,这意味着在这个消息完成之前不会有其它消息占用总线。
消息的执行总是按照FIFO的顺序。
向底层提交spi_message的代码要负责管理它的内存空间。未显示初始化的内存需要使用0来初始化。

  1. struct spi_message {
  2. struct list_head transfers;
  3. struct spi_device *spi;
  4. unsigned is_dma_mapped:1;
  5. /* REVISIT: we might want a flag affecting the behavior of the
  6. * last transfer ... allowing things like "read 16 bit length L"
  7. * immediately followed by "read L bytes". Basically imposing
  8. * a specific message scheduling algorithm.
  9. *
  10. * Some controller drivers (message-at-a-time queue processing)
  11. * could provide that as their default scheduling algorithm. But
  12. * others (with multi-message pipelines) could need a flag to
  13. * tell them about such special cases.
  14. */
  15. /* completion is reported through a callback */
  16. void (*complete)(void *context);
  17. void *context;
  18. unsigned frame_length;
  19. unsigned actual_length;
  20. int status;
  21. /* for optional use by whatever driver currently owns the
  22. * spi_message ... between calls to spi_async and then later
  23. * complete(), that's the spi_controller controller driver.
  24. */
  25. struct list_head queue;
  26. void *state;
  27. /* list of spi_res reources when the spi message is processed */
  28. struct list_head resources;
  29. };

transfer:这个 mesage 含的 transfer 链表

spi:传输的目标设备

is_dma_mapped:spi_transfer 中 tx_dma 和 rx_dma 是否已经 mapped

complete:数据传输完成的回调函数

context:提供给complete的可选参数

actual_length:spi_message已经传输了的字节数

status:出错与否,错误时返回 errorcode

queue 、state:供controller驱动内部使用

spi_message:描述一次完整的传输,即cs信号从高->底->高的传输

spi_transfer:多个 spi_transfer 够成一个 spi_message
 

 

3.7、数据结构之间的关系

上面的数据结构,基本上组成了 SPI 框架的内容,在软件层次上我们将 SPI Controller,Bus,Driver,Slave Device 结构抽象为如下:

在数据发送的结构部分,内核将其抽象如下:

 

4、对外接口 APIs

数据结构理清楚了,暂时把 SPI Framework 看成一个黑盒子,先关心到底怎么用这个 SPI Framework,首先来看看他提供出来的接口 APIs,后面我们再来打开黑盒看看!

SPI Framework 提供的所有 APIs,几乎都可以在 include/linux/spi/spi.h 中找到,主要都是围绕着数据结构进行的,我们按照使用的流程来一步一步看看;首先先从定义注册 SPI Controller 开始入手;

 

1、分配 spi_controller (spi_master)

struct spi_controller *spi_alloc_master(struct device *host, unsigned int size)

这个接口用于分配并返回一个 spi_controller (spi_master)结构,前面也说过,SPI 控制器部分,可以挂接到 platform 上,所以这个 API 的使用场景是 SoC 的 spi 控制器 probe 的时候,调用 spi_alloc_master 来获得一个 spi_controller,并根据 SoC 自身的资源情况,来填充 spi_controller 下的各个成员。

注意:这里传入的 *host 便是 xxx_spi_probe(struct platform_device *pdev) 中的 &pdev->dev 部分,后面的 size,可以指的是私有的数据,并且包含了 spi_controller 的实例;

 

2、注册 spi_controller (spi_master)

  1. int spi_register_controller(struct spi_controller *ctlr);
  2. int spi_register_master(struct spi_controller *ctlr);

在第一步的 probe 中,将分配好并且已经完成了必要初始化的 spi_controller 结构注册到内核。在这个函数中,其实是进行了一些必要的设备模型的操作和钩子函数的 check,通过后,挂接到全局的 spi_controller_list 链表上。

这里需要注意一下,由于 SoC 一般存在多个 SPI Controller,所以在资源定义的时候(不管是 DTS 还是 platform_device),这个 probe 会被调用多次,所有的 spi_controller 都挂到了 spi_controller_list 链表上。

 

3、分配 spi_device

分配一个并简单初始化 spi_device

struct spi_device *spi_alloc_device(struct spi_controller *ctlr);

 

4、添加 spi_device

将 spi_device 添加的 device 系统

int spi_add_device(struct spi_device *spi);

 

5、分配并添加 spi_device

这个接口是上面两个接口的结合,往指定的 spi_controller 上添加一个 spi_borad_info:

  1. struct spi_device *spi_new_device(struct spi_controller *ctlr,
  2. struct spi_board_info *chip);

 

6、注册 spi_driver

  1. #define spi_register_driver(driver) \
  2. __spi_register_driver(THIS_MODULE, driver)

往 SPI BUS 上添加一个 driver

 

7、初始化 spi_message

void spi_message_init(struct spi_message *m);

用于传输之前,进行 spi_message 结构的初始化

 

8、添加 transfer 到指定的 spi_message

void spi_message_add_tail(struct spi_transfer *t, struct spi_message *m);

将希望传输的 transfer 到指定的已经完成初始化的 spi_message;

 

9、初始化一个 spi_message 并添加 N 个 transfer

  1. void spi_message_init_with_transfers(struct spi_message *m,
  2. struct spi_transfer *xfers, unsigned int num_xfers)

这个接口是上面两个的合并版本,初始化一个 spi_message,并将 num_xfers 个 xfers 挂接到 spi_message 上;

 

10、分配 1个 spi_message 和 N 个其下的 spi_transfer

struct spi_message *spi_message_alloc(unsigned ntrans, gfp_t flags);

这个接口也是一个高级版本,先分配 1 个 spi_message 和 ntrans 个 spi_transfer,并对其进行初始化,将 spi_transfer 全部挂接到 spi_message;

 

11、控制器 setup

int spi_setup(struct spi_device *spi);

根据与 spi_device 的属性,setup 我们的 SPI Controller 的 mode 和 clock rate

 

12、异步传输数据

  1. int spi_async(struct spi_device *spi, struct spi_message *message);
  2. int spi_async_locked(struct spi_device *spi, struct spi_message *message);

往 spi_device 提价 spi_message 的数据

因为是异步的,一提交就立马返回了,这也就是说需要同步机制(complete 就是了)。他确保不会睡眠,使用 spinlock,可安全的在中断 handler 或其他不可休眠的代码中调用。

使用 spi_async() 需要注意的是,在complete()未返回前不要轻易访问你一提交的 spi_transfer 中的buffer。也不能释放SPI系统正在使用的buffer。一旦你的complete返回了,这些buffer就又是你的了。

 

13、同步传输数据

  1. int spi_sync(struct spi_device *spi, struct spi_message *message);
  2. int spi_sync_locked(struct spi_device *spi, struct spi_message *message);

同步数据传输,完成后返回,也就是说,允许睡眠,使用的是 mutex 锁,返回后,可立即访问 buffer

 

14、添加若干 spi_transfer 并同步传输

  1. int spi_sync_transfer(struct spi_device *spi, struct spi_transfer *xfers,
  2. unsigned int num_xfers);

这个是前面同步传输的高级版本,往一个 spi_message 中添加已经初始化好的 num_xfers 个 spi_transfer,并嗲用 spi_sync ,往 指定的 spi_device 进行数据传输,返回 0,代表完成;允许睡眠

 

15、同步写一次数据

int spi_write(struct spi_device *spi, const void *buf, size_t len);

向指定的 spi 设备,同步写一个长为 len 的 buf 数据,注意,这里是往一个 spi_message 中填充一个 spi_transter

 

15、同步读一次

int spi_read(struct spi_device *spi, const void *buf, size_t len);

向指定的 spi 设备,同步读一个长为 len 的 buf 数据,注意,这里是往一个 spi_message 中填充一个 spi_transter

 

16、同步写一次同时读一次

  1. /* this copies txbuf and rxbuf data; for small transfers only! */
  2. int spi_write_then_read(struct spi_device *spi,
  3. const void *txbuf, unsigned n_tx,
  4. void *rxbuf, unsigned n_rx);

SPI 是全双工的,这个接口是向指定的 spi 设备写入 n_tx 个数据,同时读取 n_rx 数据,接口调用允许睡眠。

注:看注释知道,这个只为小型读写专用

 

17、同步写一个 8-bits 命令,读 8-bits 状态

  1. /**
  2. * spi_w8r8 - SPI synchronous 8 bit write followed by 8 bit read
  3. * @spi: device with which data will be exchanged
  4. * @cmd: command to be written before data is read back
  5. * Context: can sleep
  6. *
  7. * Callable only from contexts that can sleep.
  8. *
  9. * Return: the (unsigned) eight bit number returned by the
  10. * device, or else a negative error code.
  11. */
  12. ssize_t spi_w8r8(struct spi_device *spi, u8 cmd);

这个接口,有点带专用性,比如你有一个 SPI Flash,他支持使用 SPI 命令配置 SPI Flash,并返回 SPI Flash 状态码的话,那么就可以使用这个接口,这个接口其实是封装了 spi_write_then_read 接口,将 cmd 写入 SPI,将 rx 的 buffer (比如 SPI Flash 收到配置 cmd 后,通过 SPI 传输了一个状态码到 SoC)返回。

 

17、同步写一个 8-bits 命令,读 16-bits 状态

  1. /**
  2. * spi_w8r16 - SPI synchronous 8 bit write followed by 16 bit read
  3. * @spi: device with which data will be exchanged
  4. * @cmd: command to be written before data is read back
  5. * Context: can sleep
  6. *
  7. * The number is returned in wire-order, which is at least sometimes
  8. * big-endian.
  9. *
  10. * Callable only from contexts that can sleep.
  11. *
  12. * Return: the (unsigned) sixteen bit number returned by the
  13. * device, or else a negative error code.
  14. */
  15. ssize_t spi_w8r16(struct spi_device *spi, u8 cmd);

这个接口和上面一个类似,只不过返回的是 2 个 Bytes,也就是针对对方要返回 16bits 状态的情况,不再多说。

 

参考文献:

https://blog.csdn.net/wuhzossibility/article/details/7832438

https://www.jianshu.com/p/60d2d5849db9

http://emb.hqyj.com/Column/Column367.htm

https://blog.csdn.net/yaolanshu_june/article/details/52356138

https://www.linuxidc.com/Linux/2012-07/64942.htm

https://www.linuxidc.com/Linux/2012-07/64942p2.htm

https://www.linuxidc.com/Linux/2012-07/64942p3.htm

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/712314
推荐阅读
相关标签
  

闽ICP备14008679号