一. 简介
前面一篇文章简单分析了I.MX6U SPI 主机控制器的驱动框架,文章如下:
I.MX6ULL芯片的SPI 主机驱动框架的简单分析-CSDN博客
本文重点来说明一下,IMX6ULL芯片的SPI主机控制器的驱动中,关于SPI片选信号选择使用的软件片选的方法处理的。
这里分析IMX6ULL的 SPI主机控制器的驱动片选信号的处理,目的为了后面SPI设备驱动开发时会涉及,创建SPI节点时(在设备树中)会设置片选信号,即一个属性"cs-gpios"属性。
二. I.MX6ULL SPI 主机驱动:软件片选处理(片选信号)
经过前一篇文章的分析知道,I.MX6U 的 ECSPI 主机驱动文件为 drivers/spi/spi-imx.c。
打开(NXP官方提供)内核源码,找到spi-imx.c文件的spi_imx_probe函数中,有如下代码:
static int spi_imx_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
...............
for (i = 0; i < master->num_chipselect; i++) {
int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
if (!gpio_is_valid(cs_gpio) && mxc_platform_info)
cs_gpio = mxc_platform_info->chipselect[i];
spi_imx->chipselect[i] = cs_gpio;
if (!gpio_is_valid(cs_gpio))
continue;
ret = devm_gpio_request(&pdev->dev, spi_imx->chipselect[i],
DRIVER_NAME);
if (ret) {
dev_err(&pdev->dev, "can't get cs gpios\n");
goto out_master_put;
}
}
...............
}
可以看出,这里获取了”cs-gpio” 的节点信息。
spi-imx.c中还有如下代码:
static void spi_imx_chipselect(struct spi_device *spi, int is_active)
{
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
int gpio = spi_imx->chipselect[spi->chip_select];
int active = is_active != BITBANG_CS_INACTIVE;
int dev_is_lowactive = !(spi->mode & SPI_CS_HIGH);
if (!gpio_is_valid(gpio))
return;
gpio_set_value(gpio, dev_is_lowactive ^ active);
}
可以看出,这是SPI的片选信号相关的函数,也就是是SPI控制器的片选信号的操作。
这里调用了gpio_set_value接口,也就是拉低了SPI片选信号的电平,说明这是一个SPI软件的片选。
所以,NXP官方内核源码中,针对IMX6ULL芯片而言,SPI设备节点中 “cs-gpio”属性是软件片选!!!
因此,在编写SPI设备驱动代码时,我们可以使用 SPI节点的 “cs-gpios”属性,将其设置为普通的GPIO功能,而我们不用 “在SPI读写操作前设置片选电平拉低,之后拉高” 这个操作了(手动设置软件片选),因为,NXP官方内核源码中 SPI控制器驱动中已经做了SPI的软件片选的操作。
SPI节点中关于 “cs-gpios”属性的使用实例,可以查看 imx6qdl-sabresd.dtsi 这个设备树头文件,这个文件中的 SPI节点的 “cs-gpios”属性设置,以及 pinctrl节点中片选设置:
&ecspi1 {
fsl,spi-num-chipselects = <1>;
cs-gpios = <&gpio4 9 0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi1>;
status = "okay";
flash: m25p80@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "st,m25p32";
spi-max-frequency = <20000000>;
reg = <0>;
};
};
.............................
pinctrl_ecspi1: ecspi1grp {
fsl,pins = <
MX6QDL_PAD_KEY_COL1__ECSPI1_MISO 0x100b1
MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI 0x100b1
MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK 0x100b1
MX6QDL_PAD_KEY_ROW1__GPIO4_IO09 0x1b0b0
>;
};
可以看出,SPI1节点中 “cs-gpios”属性设置为 gpio4 9,也就是设置为了普通GPIO功能。
pinctrl节点中片选MX6QDL_PAD_KEY_ROW1__GPIO4_IO09也是设置为了普通GPIO功能。所以,这里SPI节点中的片选这种使用方式,说明这里SPI的cs-gpios属性当SPI的软件片选功能使用了。
三. SPI通信中片选信号
SPI通信时,SPI的片选信号可以作为硬件片选与软件片选,这两种方式使用。
硬件片选:如果选择使用硬件片选的方式,则在数据传输时,CS片选信号的电平硬件上会拉低。
当数据传输结束后,硬件上CS片选信号的电平拉高。
软件片选:软件片选即SPI通信过程中, CS片选信号需要在软件上做处理,也就需要嵌入式开发者在数据传输前手动(程序中)拉低CS片选信号的电平,在数据传输结束后,也需要软件拉高CS片选信号的电平。