1. spi_controller

之前我们讲解了整个SPI框架的构成和数据传输流程。现在我们深入源码分析每一部分。
首先来看一下 spi_controller,它表示一个 SoC 内部的 SPI 控制器硬件,对应物理模型的 Master。
比如一片 SoC 里面有 SPI0-3 控制器,那么对应的就是 spi_controller0-3。
源码位置:include/linux/spi/spi.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| struct spi_controller { struct device dev;
struct list_head list;
s16 bus_num; u16 num_chipselect;
u32 mode_bits; u32 bits_per_word_mask;
u32 min_speed_hz; u32 max_speed_hz;
u16 flags; #define SPI_CONTROLLER_HALF_DUPLEX BIT(0) #define SPI_CONTROLLER_NO_RX BIT(1) #define SPI_CONTROLLER_NO_TX BIT(2) #define SPI_CONTROLLER_MUST_RX BIT(3) #define SPI_CONTROLLER_MUST_TX BIT(4)
bool slave;
size_t (*max_transfer_size)(struct spi_device *spi); size_t (*max_message_size)(struct spi_device *spi);
struct mutex io_mutex; struct mutex add_lock;
int (*setup)(struct spi_device *spi); int (*transfer)(struct spi_device *spi, struct spi_message *mesg); void (*cleanup)(struct spi_device *spi);
bool queued; struct kthread_worker *kworker; struct kthread_work pump_messages; spinlock_t queue_lock; struct list_head queue; struct spi_message *cur_msg; bool busy; bool running; struct completion xfer_completion;
int (*prepare_transfer_hardware)(struct spi_controller *ctlr); int (*unprepare_transfer_hardware)(struct spi_controller *ctlr); int (*prepare_message)(struct spi_controller *ctlr, struct spi_message *message); int (*unprepare_message)(struct spi_controller *ctlr, struct spi_message *message); int (*transfer_one_message)(struct spi_controller *ctlr, struct spi_message *mesg); int (*transfer_one)(struct spi_controller *ctlr, struct spi_device *spi, struct spi_transfer *transfer); void (*set_cs)(struct spi_device *spi, bool enable); void (*handle_err)(struct spi_controller *ctlr, struct spi_message *message);
int *cs_gpios; struct gpio_desc **cs_gpiods; bool use_gpio_descriptors;
bool (*can_dma)(struct spi_controller *ctlr, struct spi_device *spi, struct spi_transfer *xfer); size_t max_dma_len; struct dma_chan *dma_tx; struct dma_chan *dma_rx; void *dummy_rx; void *dummy_tx; };
|
我们看一下源码,只看重要部分,先看最重要的。
1.1 transfer_one
1 2 3
| int (*transfer_one)(struct spi_controller *ctlr, struct spi_device *spi, struct spi_transfer *transfer);
|
表示让每个硬件完成一次传输。它不是一个固定函数,而是提供给 SPI Core 的回调接口。
那它是怎么被调用的呢?前面我们说过了,会在 SPI Core 层通过下面函数调用:
1
| controller->transfer_one()
|
SPI Core 不知道具体 SPI 控制器的寄存器结构,而是提供了上面的统一接口。具体控制器驱动会在初始化时赋值。
我们以 RK 系列为例,提供了 spi-rockchip.c,具体链接我会提供在末尾。
1 2 3 4
| static int rockchip_spi_transfer_one( struct spi_controller *ctlr, struct spi_device *spi, struct spi_transfer *xfer)
|
其中定义的属于这款 SoC 独特的 transfer_one。
在 probe 函数中会被调用:
1 2 3 4 5 6
| static int rockchip_spi_probe(struct platform_device *pdev) { struct spi_controller *ctlr;
ctlr->transfer_one = rockchip_spi_transfer_one;
}
|
以后 SPI Core 调用:
1
| ctlr->transfer_one(ctlr, spi, transfer);
|
实际上调用的是:
1
| rockchip_spi_transfer_one(ctlr, spi, transfer);
|
整个调用关系如下:

这就是整个 Linux 驱动框架里面典型的抽象层 + 回调机制,读者可以慢慢体会一下。
1.2 num_chipselect
注释上写了,我就不啰嗦了。
1.3 bus_num
对应的控制器编号。
2. spi_device
设备端,就是具体的从机设备,挂在某个 SPI 控制器上的一个外设。
源码位置:include/linux/spi/spi.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| struct spi_device { struct device dev; struct spi_controller *controller; struct spi_controller *master; u32 max_speed_hz; u8 chip_select; u8 bits_per_word; u32 mode; int irq; void *controller_state; void *controller_data; char modalias[SPI_NAME_SIZE]; const char *driver_override; int cs_gpio; struct gpio_desc *cs_gpiod; struct spi_delay word_delay; struct spi_delay cs_setup; struct spi_delay cs_hold; struct spi_delay cs_inactive; };
|
2.1 chip_select
对应片选 CS,比如设备树:
1 2 3 4 5
| imu@0 {
reg = <0>;
};
|
则 chip_select = 0。
2.2 mode
SPI 的模式,对应 CPOL + CPHA 的组合。
3. spi_driver
设备对应的驱动代码:
1 2 3 4 5 6 7
| struct spi_driver { const struct spi_device_id *id_table; int (*probe)(struct spi_device *spi); int (*remove)(struct spi_device *spi); void (*shutdown)(struct spi_device *spi); struct device_driver driver; };
|
最重要的就是 probe 函数,当 device 和 driver 匹配后会调用。
probe 函数通常完成:
1 2 3 4 5 6
| static int probe(struct spi_device *spi) { spi_setup(spi); spi_read(); register_device(); }
|
4. spi_transfer
一次连续 SPI 数据交换,是 SPI 传输的最小单位,表示一次不可分割的、连续的字节流传输。一个 spi_message 可以包含多个 spi_transfer,靠链表串联。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| struct spi_transfer { const void *tx_buf; void *rx_buf; unsigned len;
dma_addr_t tx_dma; dma_addr_t rx_dma;
unsigned tx_nbits:3; unsigned rx_nbits:3; #define SPI_NBITS_SINGLE 0x01 #define SPI_NBITS_DUAL 0x02 #define SPI_NBITS_QUAD 0x04
unsigned dummy_data:1; unsigned cs_change:1;
u8 bits_per_word;
struct spi_delay delay; struct spi_delay cs_change_delay; struct spi_delay word_delay;
u32 speed_hz;
struct list_head transfer_list; };
|
4.1 tx_buf / rx_buf / len
三件套,描述一次传输数据。
比如发送:
接收:
那么长度 len = 2。
4.2 transfer_list
链表节点,用来将多个 spi_transfer 串在一起,挂到 spi_message.transfers 上。SPI Core 在 spi_transfer_one_message() 中通过 list_for_each_entry 遍历这个链表,逐个交给 controller->transfer_one()。
5. spi_message
表示一次完整的 SPI 事件。比如先发送地址再读取数据,这两个动作组成一个 message。
源码位置:include/linux/spi/spi.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| struct spi_message { struct list_head transfers; struct spi_device *spi; unsigned is_dma_mapped:1;
void (*complete)(void *context); void *context;
unsigned frame_length; unsigned actual_length; int status;
struct list_head queue; void *state; struct list_head resources; };
|
1. transfers
将若干个 spi_transfer 通过链表串起来,控制器驱动按顺序逐个发送。
spi_message 与 spi_transfer 的关系如下:

spi_transfer 是数据传输的最小段,spi_message 将多个段组合成一次片选持续的完整事务,设备驱动通过构造 spi_message 并发起 spi_sync() / spi_async() 来完成与芯片的交互。
6. 一次 SPI 传输的数据流
整个流程我们在上一章讲解过了,这里就不多说了,回顾一下:

7. 总结
Linux SPI Framework 通过多个核心数据结构完成硬件抽象。
其中:
- spi_controller:描述 SoC 中的 SPI 控制器,负责操作具体硬件
- spi_device:描述挂载在 SPI 总线上的外设
- spi_driver:描述设备驱动,通过 probe 函数完成设备初始化
- spi_message:描述一次完整 SPI 事务
- spi_transfer:描述一次具体的数据交换
整个 SPI 框架通过这些结构体,将设备驱动和底层硬件控制解耦,使同一个设备驱动可以运行在不同 SoC 平台上。
8. 互动
- spi_controller 是什么?
- spi_device 是什么?
- spi_driver 是什么?
- spi_message 和 spi_transfer 为什么存在?
- 一次 SPI 传输在这些结构体之间如何流转?