linux内核中的SPI
介绍spi基本协议,以及在linux内核中spi驱动程序框架。
0、说明
介绍spi基本协议,以及在linux内核中spi驱动程序框架。
SPI驱动基于标准了总线设备驱动模型,因此本文仅示意分析SPI框架,驱动实现细节按照总线设备驱动模型来实现,不做过多分析。
1、SPI基础
硬件连接
在一些flash中经常使用SPI协议,如下,SPI一般有四个线:
- 片选CS
- 时钟SCK
- 主输出从输入:SIMO
- 主输入从输出:SOMI
根据引脚推断,有片选引脚,所以说一条SPI总线上可以挂多个设备,哪个CS被选中,则哪个设备活跃。同时有数据输入和输出引脚,因此是全双工。
四种模式
根据SCK没数据时候的状态,以及上升下降沿采样,可以分为四种模式,SPI0-3。使用SPI进行通信的时候,需要根据具体的从设备手册,确定是支持哪些模式。
2、内核中的spi驱动
架构
内核中SPI遵循总线设备驱动模型。因此驱动包含几个部分,总线的注册,控制器的注册及设备创建,驱动的注册。即总线设备驱动模型。
通过config增加SPI支持后,SPI总线被注册进内核,spi_init调用bus_register。
每个CPU有自己的SPI控制器,在设备树中描述,同时在设备树SPI控制器节点下存在该控制器下连接的设备。由控制器驱动直接创建出spi_device,spi_new_device。
那么最后只差一个spi_driver。spidev.c是一个通用的驱动,调用spi_register_driver注册驱动。
围绕以下结构体:
spi_bus_type(总线)、spi_master(控制器)、spi_device(设备)、spi_driver(驱动)
在总线设备驱动模型框架下,追踪以上结构体分配、设置过程就是SPI的框架实现。
设备树控制器描述
ecspi1: ecspi@02008000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
reg = <0x02008000 0x4000>;
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_ECSPI1>,
<&clks IMX6UL_CLK_ECSPI1>;
clock-names = "ipg", "per";
dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
dma-names = "rx", "tx";
status = "disabled";
};
&ecspi1 {
fsl,spi-num-chipselects = <1>;
cs-gpios = <&gpio4 26 0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi1_1 &pinctrl_ecspi1_cs_1>;
status = "okay";
flash: n25q032@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "st,n25q032";
spi-max-frequency = <20000000>;
reg = <0>;
};
};
总线驱动
控制器驱动
设备驱动
更多推荐
所有评论(0)