前言
這篇文章是對linux驅動基礎系列--linux spi驅動框架分析的補充,主要是添加了最新的linux內核里設備樹相關內容。
spi設備樹相關信息
如之前的文章里所述,控制器的device和spi device都是通過platform_add_device
和spi_register_board_info
注冊到內核的驅動模式中的。而最新的方式是通過設備樹來實現的。以arm為例,設備樹文件一般存放在arch/arm/boot/dts下,不同的平台對應不同的文件,以xilinx zynq平台為例,最頂層的文件為zynq-zturn.dts,它包含了zynq-7000.dtsi。在zynq-7000.dtsi中,有兩個節點用於對該soc的spi控制器的描述:
spi0: spi@e0006000 {
compatible = "xlnx,zynq-spi-r1p6";
reg = <0xe0006000 0x1000>;
status = "disabled";
interrupt-parent = <&intc>;
interrupts = <0 26 4>;
clocks = <&clkc 25>, <&clkc 34>;
clock-names = "ref_clk", "pclk";
#address-cells = <1>;
#size-cells = <0>;
};
spi1: spi@e0007000 {
compatible = "xlnx,zynq-spi-r1p6";
reg = <0xe0007000 0x1000>;
status = "disabled";
interrupt-parent = <&intc>;
interrupts = <0 49 4>;
clocks = <&clkc 26>, <&clkc 35>;
clock-names = "ref_clk", "pclk";
#address-cells = <1>;
#size-cells = <0>;
};
當我們項目中用到spi1控制器時,我們只需要在zynq-7000.dtsi中添加節點:
&spi1 {
status = "okay";
num-cs = <4>;
xxx@0 {
compatible = "yyy";
reg = <0x0>;
spi-max-frequency = <50000000>;
spi-cpol;
spi-cpha;
spi-cs-high;
};
};
然后在aliases節點中添加alias,如
aliases {
ethernet0 = &gem0;
serial0 = &uart1;
serial1 = &uart0;
spi1 = &spi1;
};
上面的status = "okay"用於使能該控制器,num-cs = <4>;用於指定最多支持4個片選,xxx可以修改為自己期望的名字,compatible字段的yyy需要替換成spi驅動對應的字串,spi-max-frequency用於設置支持的最大頻率,reg用於設置該spi設備對應的片選,這個和硬件有關,spi-cpol和spi-cpha字段用於設置時鍾極性和時鍾相位,更加詳細的意思參考Documentation/devicetree/bindings/spi/spi-bus.txt。spi-bus.txt里所描述的屬性的解析位於drivers/spi/spi.c中,在控制器驅動調用spi_register_master
注冊的時候處理。下面以為什么需要在aliases中添加spi1=&spi1為例子說明下解析的過程。
在spi_register_master
中,如果檢測到master->bus_num < 0
(spi_alloc_master
分配的時候就設置為-1了)且存在設備節點,那么就用of_alias_get_id
從alias節點中提取該spi節點對應的編號作為總線號,也就是說,上面的添加會導致該控制器對應的spi總線號為1了,如果不加,那么內核通過atomic_dec_return(&dyn_bus_id)
自動分配一個。
if ((master->bus_num < 0) && master->dev.of_node)
master->bus_num = of_alias_get_id(master->dev.of_node, "spi");
/* convention: dynamically assigned bus IDs count down from the max */
if (master->bus_num < 0) {
/* FIXME switch to an IDR based scheme, something like
* I2C now uses, so we can't run out of "dynamic" IDs
*/
master->bus_num = atomic_dec_return(&dyn_bus_id);
dynamic = 1;
}
最后再講下spi-cs-high屬性,在spi-bus.txt中描述如下:
- spi-cs-high - (optional) Empty property indicating device requires
chip select active high
如果設置了該屬性,那么在每次需要讀寫spi前,控制器的回調set_cs
參數enable為true,讀寫spi完成后,控制器的回調set_cs
參數enable為false,否則反之。
完!
2016年10月