第18章 ARM Linux设备树之二(设备树的组成和结构)

18.2.7 GPIO、时钟、pinmux连接

除了中断以外,在ARM Linux中时钟、GPIO、pinmux(引脚复用)都可以通过.dts中的节点和属性进行描述。

1.GPIO

对于GPIO控制器而言,其对应的设备节点需声明gpio-controller属性,并设置#gpio-cells的大小。譬如,对于兼容性为fsl,imx28-pinctrl的pinctrl驱动而言,其GPIO控制器的设备节点类似于:

pinctrl@80018000 {
        compatible = "fsl,imx28-pinctrl", "simple-bus";
        reg = <0x80018000 2000>;
        gpio0: gpio@0 {
                compatible = "fsl,imx28-gpio";
                interrupts = <127>;
                gpio-controller;
                #gpio-cells = <2>;
                interrupt-controller;
                #interrupt-cells = <2>;
        };
        gpio1: gpio@1 {
                compatible = "fsl,imx28-gpio";
                interrupts = <126>;
                gpio-controller;
                #gpio-cells = <2>;
                interrupt-controller;
                #interrupt-cells = <2>;
        };
        ...

};

其中,#gpio-cells为2,第1个cell为GPIO号,第2个为GPIO的极性。为0的时候是高电平有效,为1的时候则是低电平有效。使用GPIO的设备则通过定义命名xxx-gpios属性来引用GPIO控制器的设备节点,如:

sdhci@c8000400 {
        status = "okay";
        cd-gpios = <&gpio1 0>;
        wp-gpios = <&gpio2 0>;
        power-gpios = <&gpio3 0>;

        bus-width = <4>;

};

而具体的设备驱动则通过类似如下的方法来获取GPIO:

cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
power_gpio = of_get_named_gpio(np, "power-gpios", 0);

of_get_named_gpio()这个API的原型如下:

static inline int of_get_named_gpio(struct device_node *np,const char *propname, int index);

在.dts和设备驱动不关心GPIO名字的情况下,也可以直接通过of_get_gpio()获取GPIO,此函数原型为:

static inline int of_get_gpio(struct device_node *np, int index);

如对于compatible="gpio-control-nand"的基于GPIO的NAND控制器而言,在.dts中会定义多个gpio属性:

gpio-nand@1,0 {
        compatible = "gpio-control-nand";
        reg = <1 0x0000 0x2>;
        #address-cells = <1>;
        #size-cells = <1>;
        gpios = <&banka 1 0     /* rdy */
                        &banka 2 0     /* nce */
                        &banka 3 0     /* ale */
                        &banka 4 0     /* cle */
                        0              /* nwp */>;
                   partition@0 {
                           ...
                   };
};

在相应的驱动代码drivers/mtd/nand/gpio.c中是这样获取这些GPIO的:

plat->gpio_rdy = of_get_gpio(dev->of_node, 0);
plat->gpio_nce = of_get_gpio(dev->of_node, 1);
plat->gpio_ale = of_get_gpio(dev->of_node, 2);
plat->gpio_cle = of_get_gpio(dev->of_node, 3);
plat->gpio_nwp = of_get_gpio(dev->of_node, 4);

2.时钟

时钟和GPIO也是类似的,时钟控制器的节点被使用时钟的模块引用:

clocks = <&clks 138>, <&clks 140>, <&clks 141>;
clock-names = "uart", "general", "noc";

而驱动中则使用上述的clock-names属性作为clk_get()或devm_clk_get()的第二个参数来申请时钟,譬如获取第2个时钟:

devm_clk_get(&pdev->dev, "general");

<&clks 138>里的138这个index是与相应时钟驱动中clk的表的顺序对应的,很多开发者也认为这种数字出现在设备树中不太好,因此他们把clk的index作为宏定义到了arch/arm/boot/dts/include/dt-bindings/clock中。譬如include/dt-bindings/clock/imx6qdl-clock.h中存在这样的宏:

#define IMX6QDL_CLK_STEP                        16
#define IMX6QDL_CLK_PLL1_SW                  17
#define IMX6QDL_CLK_ARM                         104



猜你喜欢

转载自blog.csdn.net/xiezhi123456/article/details/80342379