&spi1 , spi1 = &spi1; status = "okay"

转载于 :  http://blog.rongpmcu.com/linuxqu-dong-ji-chu-xi-lie-linux-spiqu-dong-kuang-jia-fen-xi-xu/

 

inux驱动基础系列--linux spi驱动框架分析(续)

spi设备树相关信息

  如之前的文章里所述,控制器的device和spi device都是通过platform_add_devicespi_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 < 0spi_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,否则反之。

posted on 2017-03-21 23:13  Red_Point  阅读(1168)  评论(0编辑  收藏  举报

导航