7.10.5. 设计说明
7.10.5.1. 源码说明
相关模块 |
源码路径 |
---|---|
SPI subsystem |
linux-5.10/drivers/spi/ |
Driver |
linux-5.10/drivers/spi/ |
7.10.5.2. 模块架构
由于使用 SPI 的外设较多,内核中通过 SPI 子系统来支持各种 SPI 外设,整体架构如上图所示,包括:
ZX SPI 驱动
SPI Core
SPI-MEM
面向内核的 API
面向用户空间的接口(SPIDEV)
由于 SPI 传输需要使用 DMA,因此 DMA 子系统是一个相关模块。
7.10.5.3. 关键流程
7.10.5.3.1. 初始化
aic_spi_probe();
|-> irq = platform_get_irq(pdev, 0);
|-> ctlr = spi_alloc_master(&pdev->dev, sizeof(struct aic_spi));
|-> platform_set_drvdata(pdev, ctlr);
|-> aicspi->dma_rx = dma_request_slave_channel(aicspi->dev, "rx");
|-> aicspi->dma_tx = dma_request_slave_channel(aicspi->dev, "tx");
|-> request_irq(aicspi->irq, aic_spi_handle_irq, 0, aicspi->dev_name, aicspi);
|-> spi_register_controller(ctlr);
7.10.5.3.2. 中断流程
SPI 控制器驱动中的中断处理并不复杂,当中断发生时,首先在 irq handler 中读取相关状态寄存器, 然后判断如何处理:
static irqreturn_t aic_spi_handle_irq(int irq, void *dev_id)
{
...
spi_ctlr_pending_irq_clr(status, base_addr);
/* master mode, Transfer Complete Interrupt */
if (status & ISR_BIT_TC) {
...
spi_ctlr_irq_disable(ISR_BIT_TC | ISR_BIT_ERRS, base_addr);
spi_finalize_current_transfer(aicspi->ctlr); // 传输完成,通知调用者
...
return IRQ_HANDLED;
} else if (status & ISR_BIT_ERRS) {
...
spi_ctlr_irq_disable(ISR_BIT_TC | ISR_BIT_ERRS, base_addr);
spi_ctlr_soft_reset(base_addr); // 传输出错,reset 控制器
spi_finalize_current_transfer(aicspi->ctlr);
...
return IRQ_HANDLED;
}
...
return IRQ_NONE;
}
7.10.5.4. 数据结构
enum spi_mode_type {
SINGLE_HALF_DUPLEX_RX,
SINGLE_HALF_DUPLEX_TX,
SINGLE_FULL_DUPLEX_RX_TX,
DUAL_HALF_DUPLEX_RX,
DUAL_HALF_DUPLEX_TX,
QUAD_HALF_DUPLEX_RX,
QUAD_HALF_DUPLEX_TX,
MODE_TYPE_NULL,
};
设备数据结构。
struct aic_spi {
struct device *dev; // 设备指针
struct spi_controller *ctlr; // SPI CORE 的控制器指针
void __iomem *base_addr; // 映射后的 SPI 控制器地址
struct clk *mclk; // SPI 控制器的时钟
struct reset_control *rst; // SPI 控制器的复位
struct dma_chan *dma_rx; // SPI 控制器的接收 DMA Channel
struct dma_chan *dma_tx; // SPI 控制器的发送 DMA Channel
dma_addr_t dma_addr_rx; // SPI 控制器 RX FIFO 地址
dma_addr_t dma_addr_tx; // SPI 控制器 TX FIFO 地址
enum spi_mode_type mode_type;
unsigned int irq; // 中断号
char dev_name[48];
spinlock_t lock;
};
7.10.5.5. 接口设计
7.10.5.5.1. aic_spi_setup
函数原型 |
int aic_spi_setup(struct spi_device *spi) |
功能说明 |
SPI 设备的传输位宽、模式的检查和配置 |
参数定义 |
struct spi_device *spi
SPI 设备指针
|
返回值 |
0: 成功
其他: 失败
|
注意事项 |
7.10.5.5.2. aic_spi_set_cs
函数原型 |
void aic_spi_set_cs(struct spi_device *spi, bool cs_high) |
功能说明 |
设置 SPI 设备的片选信号 |
参数定义 |
struct spi_device *spi
SPI 设备指针
bool cs_high
是否选择该设备
|
返回值 |
无
|
注意事项 |
7.10.5.5.3. aic_spi_max_transfer_size
函数原型 |
size_t aic_spi_max_transfer_size(struct spi_device *spi) |
功能说明 |
SPI CORE 获取当前 SPI 控制器单次最大可传输的数据长度 |
参数定义 |
struct spi_device *spi
SPI 设备指针
|
返回值 |
单次可传输的数据长度
|
注意事项 |
7.10.5.5.4. aic_spi_transfer_one
函数原型 |
int aic_spi_transfer_one(struct spi_controller *ctlr,struct spi_device *spi, struct spi_transfer *t) |
功能说明 |
执行一次传输 |
参数定义 |
struct spi_controller *ctlr
SPI 控制器指针
struct spi_device *spi
SPI 设备指针
struct spi_transfer *t
单次 SPI 传输结构体指针
|
返回值 |
0: 成功
其他: 失败
|
注意事项 |