1. 程式人生 > >android 驅動(6)---DTS 分析

android 驅動(6)---DTS 分析

1. dts和dtsi完成的功能

 1 uart5: [email protected] {
 2     compatible = "fsl,imx6sx-uart",
 3                 "fsl,imx6q-uart", "fsl,imx21-uart";
 4     reg = <0x021f4000 0x4000>;
 5     interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
 6     clocks = <&clks IMX6SX_CLK_UART_IPG>,
 7             <&clks IMX6SX_CLK_UART_SERIAL>;
 8     clock-names = "ipg", "per";
 9     dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
10     dma-names = "rx", "tx";
11     status = "disabled";
12 };

以上這段程式碼更多出現在*.dtsi中

一般會在*.dtsi中將晶片的外設介面資源都做定義,

如uart5作為該外設的label,[email protected]作為裝置的名稱,node-name只是裝置型別,uart1/uart2/uart3等可以都是serial名稱,而@後面則跟著裝置暫存器起始地址。

compatible預設屬性,

reg暫存器地址和長度,該uart5節點的父節點為aips2,在父節點中指明#address-cells = <1>;#size-cells = <1>;這決定了子節點欄位長度address為1, length為1. 所以reg格式為reg = <0x021f4000 0x4000>;

interrupts對應的中斷號和中斷出發方式,uart5的父節點為aips2,而aips2的父節點為soc,soc節點定義了interrupt-parent = <&intc>;給出了節點所依附的中斷控制器,如果節點沒有指定interrupt-parent,那麼就從父節點繼承,所以該uart5節點繼承了soc的中斷控制器,即intc. 而intc節點的#interrupt-cells = <3>;所以就有了該節點中interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;三個欄位,具體這三個欄位的含義可以參考晶片文件的描述。其中GIC_SPI定義在include/dt-bindings/interrupt-controller/arm-gic.h值為0,  

clock外設時鐘,在include/dt-bindings/clock/imx6sx-clock.h,指定裝置工作時鐘

status一般會設為disabled。

1 &uart5 {
2     pinctrl-names = "default";
3     pinctrl-0 = <&pinctrl_uart5>;
4     fsl,uart-has-rtscts;
5     status = "okay";
6 };

以上這段程式碼更多出現在*.dts中

在*.dts中如果想對該裝置進行操作,需要進行override,至少status需要從disabled設定為okay, 當然也有可能需要對compatible屬性進行重寫(為了和自己的driver匹配),另外需要使用&label首先引用該裝置,使用pinctrl-names和pinctrl-0進行引腳的配置,當然這裡可能出現多組引腳的配置,如下程式碼:

複製程式碼

 1 &usdhc3 {
 2     pinctrl-names = "default", "state_100mhz", "state_200mhz";
 3     pinctrl-0 = <&pinctrl_usdhc3>;
 4     pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
 5     pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
 6     bus-width = <8>;
 7     cd-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>;
 8     wp-gpios = <&gpio2 15 GPIO_ACTIVE_HIGH>;
 9     keep-power-in-suspend;
10     enable-sdio-wakeup;
11     vmmc-supply = <&vcc_sd3>;
12     status = "okay";
13 };

複製程式碼

而這裡面的pinctrl-0對應的pinctrl_usdhc3內容如下:

複製程式碼

 1 pinctrl_usdhc3: usdhc3grp {
 2     fsl,pins = <
 3         MX6SX_PAD_SD3_CMD__USDHC3_CMD        0x17069
 4         MX6SX_PAD_SD3_CLK__USDHC3_CLK        0x10071
 5         MX6SX_PAD_SD3_DATA0__USDHC3_DATA0    0x17069
 6         MX6SX_PAD_SD3_DATA1__USDHC3_DATA1    0x17069
 7         MX6SX_PAD_SD3_DATA2__USDHC3_DATA2    0x17069
 8         MX6SX_PAD_SD3_DATA3__USDHC3_DATA3    0x17069
 9         MX6SX_PAD_SD3_DATA4__USDHC3_DATA4    0x17069
10         MX6SX_PAD_SD3_DATA5__USDHC3_DATA5    0x17069
11         MX6SX_PAD_SD3_DATA6__USDHC3_DATA6    0x17069
12         MX6SX_PAD_SD3_DATA7__USDHC3_DATA7    0x17069
13         MX6SX_PAD_KEY_COL0__GPIO2_IO_10        0x17059 /* CD */
14         MX6SX_PAD_KEY_ROW0__GPIO2_IO_15        0x17059 /* WP */
15         >;
16 };

複製程式碼

 這種pinctrl的設定可參照/Documentation/devicetree/bindinsg/pinctrl下示例程式碼

2. 通常會碰到的實際問題

到此,問題出現了:

1. 當寫一個按鍵驅動,應該如何在*.dts或者*.dtsi中操作?

2. 當在串列埠driver中需要使用到某個pin腳作為普通輸出IO,該如何操作?

3. 當在串列埠driver中需要使用某個muxpin腳作為ADC或者其他服用功能該如何操作?

4. 當在串列埠driver中有可能想使能某個功能而不想寫定在driver程式碼中,該如何操作?

5. 當想向driver中傳入一個常數如做delay延時操作等等,該如何操作?

解答

1. 當寫一個按鍵驅動,應該如何在*.dts或者*.dtsi中操作?

複製程式碼

 1 gpio-keys {
 2     compatible = "gpio-keys";
 3     pinctrl-names = "default";
 4     pinctrl-0 = <&pinctrl_gpio_keys>;
 5 
 6     volume-up {
 7         label = "Volume Up";
 8         gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
 9         linux,code = <KEY_VOLUMEUP>;
10     };
11 
12     volume-down {
13         label = "Volume Down";
14         gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
15         linux,code = <KEY_VOLUMEDOWN>;
16     };
17 };

複製程式碼

1 pinctrl_gpio_keys: gpio_keysgrp {
2     fsl,pins = <
3         MX6SX_PAD_CSI_DATA04__GPIO1_IO_18 0x17059
4         MX6SX_PAD_CSI_DATA05__GPIO1_IO_19 0x17059
5         >;
6 };

2. 當在串列埠driver中需要使用到某個pin腳作為普通輸出IO,該如何操作?

複製程式碼

1 sii902x_reset: sii902x-reset {
2     compatible = "gpio-reset";
3     reset-gpios = <&gpio3 27 1>;
4     reset-delay-us = <100000>;
5     #reset-cells = <0>;
6     status = "disabled";
7 };

複製程式碼

最簡單的不需要pinctrl來進行pin腳的設定,為什麼???

3. 當在串列埠driver中需要使用某個muxpin腳作為ADC或者其他服用功能該如何操作?

這個問題其實上面有提到,就像上述的多個pin-names和多個pinctrl在後面的pinctrl中配置這個複用的管腳即可。

4. 當在串列埠driver中有可能想使能某個功能而不想寫定在driver程式碼中,該如何操作?

複製程式碼

1 &uart5 { 
2     pinctrl-names = "default";
3     pinctrl-0 = <&pinctrl_uart5>;
4     fsl,uart-has-rtscts;
5     status = "okay";
6 
7 };

只需要在driver中使用of函式讀取此屬性,如果有此欄位,可以使能某些操作;如果沒有就失能某些操作。

5. 當想向driver中傳入一個常數如做delay延時操作等等,該如何操作?

1 &usdhc3 { 2 pinctrl-names = "default", "state_100mhz", "state_200mhz"; 3 pinctrl-0 = <&pinctrl_usdhc3>; 4 pinctrl-1 = <&pinctrl_usdhc3_100mhz>; 5 pinctrl-2 = <&pinctrl_usdhc3_200mhz>; 6 bus-width = <8>; 7 cd-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>; 8 wp-gpios = <&gpio2 15 GPIO_ACTIVE_HIGH>; 9 keep-power-in-suspend; 10 enable-sdio-wakeup; 11 vmmc-supply = <&vcc_sd3>; 12 status = "okay"; 13 };