当前位置:   article > 正文

Linux设备树学习1 - DTS文件格式

dts文件

一. 设备树简介

        Linux设备树,英文称为Devicetree,设备树的源文件称为DTS。设备树是用于描述系统的硬件资源。例如在Linux2.x时,我们写驱动程序需要在代码中写死我们需要使用的GPIO等资源,但是当硬件改板或是开发另一款设备时,GPIO有所改动时,我们就要修改驱动源码了,这样修改有可能会遗漏,特别GPIO改动太大时。Linux3.x内核出现设备树时,我们就可以在可以在一个设备树文件中把GPIO资源都修改好,不仅提高了效率,而且也避免了出错。

二. DTS文件

1. DTS文件类型

        设备树文件有两种文件,以.dts和.dtsi结尾的文件。dtsi文件通常是用来描述CPU所支持的外设 ,dts文件通常是用来描述具体单板的硬件资源使用。所以dtsi文件是用来被dts文件包含的。它们的关系类似于C语言中的.c和.h文件的关系。

2. DTS文件布局

  1. [label:] node-name[@unit-address] {
  2. [properties definitions]
  3. [child nodes]
  4. };

dtsi示例代码:

  1. / {
  2. #address-cells = <1>;
  3. #size-cells = <1>;
  4. compatible = "ralink,mtk7620n-soc";
  5. cpus {
  6. cpu@0 {
  7. compatible = "mips,mips24KEc";
  8. };
  9. };
  10. chosen {
  11. bootargs = "console=ttyS0,57600";
  12. };
  13. cpuintc: cpuintc@0 {
  14. #address-cells = <0>;
  15. #interrupt-cells = <1>;
  16. interrupt-controller;
  17. compatible = "mti,cpu-interrupt-controller";
  18. };
  19. palmbus@10000000 {
  20. compatible = "palmbus";
  21. reg = <0x10000000 0x200000>;
  22. ranges = <0x0 0x10000000 0x1FFFFF>;
  23. #address-cells = <1>;
  24. #size-cells = <1>;
  25. sysc@0 {
  26. compatible = "ralink,mt7620a-sysc", "ralink,rt3050-sysc";
  27. reg = <0x0 0x100>;
  28. };
  29. timer@100 {
  30. compatible = "ralink,mt7620a-timer", "ralink,rt2880-timer";
  31. reg = <0x100 0x20>;
  32. interrupt-parent = <&intc>;
  33. interrupts = <1>;
  34. };
  35. watchdog@120 {
  36. compatible = "ralink,mt7620a-wdt", "ralink,rt2880-wdt";
  37. reg = <0x120 0x10>;
  38. resets = <&rstctrl 8>;
  39. reset-names = "wdt";
  40. interrupt-parent = <&intc>;
  41. interrupts = <1>;
  42. };
  43. intc: intc@200 {
  44. compatible = "ralink,mt7620a-intc", "ralink,rt2880-intc";
  45. reg = <0x200 0x100>;
  46. resets = <&rstctrl 19>;
  47. reset-names = "intc";
  48. interrupt-controller;
  49. #interrupt-cells = <1>;
  50. interrupt-parent = <&cpuintc>;
  51. interrupts = <2>;
  52. };
  53. memc@300 {
  54. compatible = "ralink,mt7620a-memc", "ralink,rt3050-memc";
  55. reg = <0x300 0x100>;
  56. resets = <&rstctrl 20>;
  57. reset-names = "mc";
  58. interrupt-parent = <&intc>;
  59. interrupts = <3>;
  60. };
  61. gpio0: gpio@600 {
  62. compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio";
  63. reg = <0x600 0x34>;
  64. resets = <&rstctrl 13>;
  65. reset-names = "pio";
  66. interrupt-parent = <&intc>;
  67. interrupts = <6>;
  68. gpio-controller;
  69. #gpio-cells = <2>;
  70. ralink,gpio-base = <0>;
  71. ralink,num-gpios = <24>;
  72. ralink,register-map = [ 00 04 08 0c
  73. 20 24 28 2c
  74. 30 34 ];
  75. };
  76. gpio1: gpio@638 {
  77. compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio";
  78. reg = <0x638 0x24>;
  79. interrupt-parent = <&intc>;
  80. interrupts = <6>;
  81. gpio-controller;
  82. #gpio-cells = <2>;
  83. ralink,gpio-base = <24>;
  84. ralink,num-gpios = <16>;
  85. ralink,register-map = [ 00 04 08 0c
  86. 10 14 18 1c
  87. 20 24 ];
  88. #status = "disabled";
  89. status = "okay";
  90. };
  91. gpio2: gpio@660 {
  92. compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio";
  93. reg = <0x660 0x24>;
  94. interrupt-parent = <&intc>;
  95. interrupts = <6>;
  96. gpio-controller;
  97. #gpio-cells = <2>;
  98. ralink,gpio-base = <40>;
  99. ralink,num-gpios = <32>;
  100. ralink,register-map = [ 00 04 08 0c
  101. 10 14 18 1c
  102. 20 24 ];
  103. status = "disabled";
  104. };
  105. gpio3: gpio@688 {
  106. compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio";
  107. reg = <0x688 0x24>;
  108. interrupt-parent = <&intc>;
  109. interrupts = <6>;
  110. gpio-controller;
  111. #gpio-cells = <2>;
  112. ralink,gpio-base = <72>;
  113. ralink,num-gpios = <1>;
  114. ralink,register-map = [ 00 04 08 0c
  115. 10 14 18 1c
  116. 20 24 ];
  117. status = "disabled";
  118. };
  119. i2c: i2c@900 {
  120. compatible = "ralink,rt2880-i2c";
  121. reg = <0x900 0x100>;
  122. resets = <&rstctrl 16>;
  123. reset-names = "i2c";
  124. #address-cells = <1>;
  125. #size-cells = <0>;
  126. pinctrl-names = "default";
  127. pinctrl-0 = <&i2c_pins>;
  128. };
  129. spi@b00 {
  130. compatible = "ralink,mt7620a-spi", "ralink,rt2880-spi";
  131. reg = <0xb00 0x100>;
  132. resets = <&rstctrl 18>;
  133. reset-names = "spi";
  134. #address-cells = <1>;
  135. #size-cells = <1>;
  136. pinctrl-names = "default";
  137. pinctrl-0 = <&spi_pins>;
  138. };
  139. uartlite@c00 {
  140. compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a";
  141. reg = <0xc00 0x100>;
  142. resets = <&rstctrl 19>;
  143. reset-names = "uartl";
  144. interrupt-parent = <&intc>;
  145. interrupts = <12>;
  146. reg-shift = <2>;
  147. pinctrl-names = "default";
  148. pinctrl-0 = <&uartlite_pins>;
  149. };
  150. systick@d00 {
  151. compatible = "ralink,mt7620a-systick", "ralink,cevt-systick";
  152. reg = <0xd00 0x10>;
  153. resets = <&rstctrl 28>;
  154. reset-names = "intc";
  155. interrupt-parent = <&cpuintc>;
  156. interrupts = <7>;
  157. };
  158. };
  159. pinctrl {
  160. compatible = "ralink,rt2880-pinmux";
  161. pinctrl-names = "default";
  162. pinctrl-0 = <&state_default>;
  163. state_default: pinctrl0 {
  164. };
  165. spi_pins: spi {
  166. spi {
  167. ralink,group = "spi";
  168. ralink,function = "spi";
  169. };
  170. };
  171. uartlite_pins: uartlite {
  172. uart {
  173. ralink,group = "uartlite";
  174. ralink,function = "uartlite";
  175. };
  176. };
  177. };
  178. rstctrl: rstctrl {
  179. compatible = "ralink,mt7620a-reset", "ralink,rt2880-reset";
  180. #reset-cells = <1>;
  181. };
  182. usbphy: usbphy {
  183. compatible = "ralink,mt7620a-usbphy";
  184. #phy-cells = <1>;
  185. resets = <&rstctrl 22 &rstctrl 25>;
  186. reset-names = "host", "device";
  187. };
  188. ethernet@10100000 {
  189. compatible = "ralink,mt7620a-eth";
  190. reg = <0x10100000 10000>;
  191. #address-cells = <1>;
  192. #size-cells = <0>;
  193. interrupt-parent = <&cpuintc>;
  194. interrupts = <5>;
  195. resets = <&rstctrl 21 &rstctrl 23>;
  196. reset-names = "fe", "esw";
  197. mdio-bus {
  198. #address-cells = <1>;
  199. #size-cells = <0>;
  200. status = "disabled";
  201. };
  202. };
  203. gsw@10110000 {
  204. compatible = "ralink,mt7620a-gsw";
  205. reg = <0x10110000 8000>;
  206. resets = <&rstctrl 23>;
  207. reset-names = "esw";
  208. interrupt-parent = <&intc>;
  209. interrupts = <17>;
  210. ralink,port4 = "gmac";
  211. };
  212. ehci@101c0000 {
  213. compatible = "ralink,rt3xxx-ehci";
  214. reg = <0x101c0000 0x1000>;
  215. interrupt-parent = <&intc>;
  216. interrupts = <18>;
  217. phys = <&usbphy 1>;
  218. phy-names = "usb";
  219. status = "disabled";
  220. };
  221. ohci@101c1000 {
  222. compatible = "ralink,rt3xxx-ohci";
  223. reg = <0x101c1000 0x1000>;
  224. phys = <&usbphy 1>;
  225. phy-names = "usb";
  226. interrupt-parent = <&intc>;
  227. interrupts = <18>;
  228. status = "disabled";
  229. };
  230. wmac@10180000 {
  231. compatible = "ralink,rt7620-wmac", "ralink,rt2880-wmac";
  232. reg = <0x10180000 40000>;
  233. interrupt-parent = <&cpuintc>;
  234. interrupts = <6>;
  235. ralink,eeprom = "soc_wmac.eeprom";
  236. };
  237. };

dts文件示例:

  1. /dts-v1/;
  2. /include/ "mt7620n.dtsi"
  3. / {
  4. compatible = "mediatek,hiwooya", "ralink,mt7620n-soc";
  5. model = "Wooya IOT Smart 7620";
  6. palmbus@10000000 {
  7. gpio0: gpio@600 {
  8. status = "okay";
  9. };
  10. gpio2: gpio@660 {
  11. status = "okay";
  12. };
  13. gpio3: gpio@688 {
  14. status = "okay";
  15. };
  16. spi@b00 {
  17. status = "okay";
  18. m25p80@0 {
  19. #address-cells = <1>;
  20. #size-cells = <1>;
  21. compatible = "mx25l12805d";
  22. reg = <0 0>;
  23. linux,modalias = "m25p80", "w25q128";
  24. spi-max-frequency = <10000000>;
  25. partition@0 {
  26. label = "u-boot";
  27. reg = <0x0 0x30000>;
  28. read-only;
  29. };
  30. partition@30000 {
  31. label = "u-boot-env";
  32. reg = <0x30000 0x10000>;
  33. read-only;
  34. };
  35. factory: partition@40000 {
  36. label = "factory";
  37. reg = <0x40000 0x10000>;
  38. read-only;
  39. };
  40. partition@50000 {
  41. label = "firmware";
  42. reg = <0x50000 0xdb0000>;
  43. };
  44. partition@ff0000 {
  45. label = "config";
  46. reg = <0xe00000 0x100000>;
  47. };
  48. };
  49. };
  50. };
  51. lte-leds {
  52. compatible = "gpio-leds";
  53. red-led {
  54. label = "red";
  55. gpios = <&gpio0 7 1>;
  56. linux,default-trigger = "none";
  57. };
  58. green-led {
  59. label = "green";
  60. gpios = <&gpio0 1 1>;
  61. };
  62. blue-led {
  63. label = "blue";
  64. gpios = <&gpio1 14 1>;
  65. linux,default-trigger = "none";
  66. };
  67. l1 {
  68. label = "led1";
  69. gpios = <&gpio2 6 1>;
  70. linux,default-trigger = "none";
  71. };
  72. l2 {
  73. label = "led2";
  74. gpios = <&gpio2 11 1>;
  75. linux,default-trigger = "none";
  76. };
  77. l3 {
  78. label = "led3";
  79. gpios = <&gpio2 10 1>;
  80. linux,default-trigger = "none";
  81. };
  82. l4 {
  83. label = "led4";
  84. gpios = <&gpio2 19 1>;
  85. linux,default-trigger = "none";
  86. };
  87. };
  88. gpio-keys-polled {
  89. compatible = "gpio-keys-polled";
  90. #address-cells = <1>;
  91. #size-cells = <0>;
  92. poll-interval = <20>;
  93. reset {
  94. label = "reset";
  95. gpios = <&gpio1 13 1>;
  96. linux,code = <0x198>;
  97. };
  98. };
  99. ehci@101c0000 {
  100. status = "okay";
  101. };
  102. ohci@101c1000 {
  103. status = "okay";
  104. };
  105. ethernet@10100000 {
  106. mtd-mac-address = <&factory 0x4>;
  107. ralink,port-map = "llllw";
  108. };
  109. wmac@10180000 {
  110. ralink,mtd-eeprom = <&factory 0>;
  111. };
  112. pinctrl {
  113. state_default: pinctrl0 {
  114. default {
  115. ralink,group = "pa", "spi refclk", "wdt", "uartf", "nd_sd";
  116. ralink,function = "gpio";
  117. };
  118. i2c_pins: i2c_pins {
  119. i2c_pins {
  120. ralink,group = "i2c";
  121. ralink,function = "i2c";
  122. };
  123. };
  124. };
  125. };
  126. };

        从上面设备的设备树代码来看,设备树dts文件需要指定dts的版本号(/dts-v1/;),包含了什么dtsi文件(/include/ "mt7620n.dtsi"),以/开始的根节点和节点名开始的子节点。简化代码如下

  1. /dts-v1/;
  2. /include/ "mt7620n.dtsi"
  3. / {
  4. compatible = "mediatek,hiwooya", "ralink,mt7620n-soc";
  5. model = "Wooya IOT Smart 7620";
  6. palmbus@10000000 {
  7. ........
  8. };
  9. lte-leds {
  10. compatible = "gpio-leds";
  11. red-led {
  12. ........
  13. };
  14. };
  15. gpio-keys-polled {
  16. compatible = "gpio-keys-polled";
  17. ........
  18. };
  19. ohci@101c1000 {
  20. status = "okay";
  21. };
  22. };

        从上面代码可以看出设备树的节点是以node-name@unit-address { }组成,node-name一般以字母数字等ASCII码组成,根节点是一种特殊节点。有些节点带有unit-address,而有些没有,节点都有一个compatible属性等。接下来详细介绍。        

三. DTS设备节点属性介绍

1. compatible

        compatible可以包含一个或者多个字符串,中间以逗号隔开。主要用来指定驱动代码设备的型号名称。当驱动代码中的名称和设备树的某个节点compatible属性名称一样,驱动代码则调用probe函数。示例如下:

compatible = "fsl,mpc8641", "ns16550";

2. model

        主要用来指定产商的设备型号。示例如下

model = "fsl,MPC8349EMITX";

3. phandle

        phandle属性指定一个设备树中唯一的数字标识。带有phandle属性的节点可以被其他节点引用,示例如下

  1. pic@10000000 {
  2. phandle = <1>;
  3. interrupt-controller;
  4. };
  5. another-device-node {
  6. interrupt-parent = <1>;
  7. };

4. status

        status属性指示设备的可操作的状态,可用的状态如下:

okay :表示设备可以操作

disabled :表示设备当前不可操作,但未来可能可以操作

fail :表示设备不可操作,检测到严重的错误,如果不修复无法操作。

fail-sss :和fail的含义类型

5. #address-cells和#size-cells

        #address-cells和#size-cells属性可用于任何在设备树层次结构中拥有子节点的设备节点,并描述子设备节点应该如何被寻址。#address-cells属性定义了该节点的子节点中的reg属性该用几个u32类型的数字编码其地址字段。#size-cells则定义了reg属性的size字段需要使用的u32类型的数字的数量。#address-cells和#size-cells都不从父节点那继承,需要明确的定义。示例如下

  1. soc {
  2. #address-cells = <1>;
  3. #size-cells = <1>;
  4. serial {
  5. compatible = "ns16550";
  6. reg = <0x4600 0x100>;
  7. clock-frequency = <0>;
  8. interrupts = <0xA 0x8>;
  9. interrupt-parent = <&ipic>;
  10. };
  11. };

6. reg

        reg属性描述了在父总线定义的地址空间中设备资源的地址。通常表示寄存器映射在内存中的起始地址和长度,或者CPU寄存器地址的真实地址。

        当寄存器在内存中有两段地址时,reg需要指定两对#address-cells和#size-cells,示例如下

reg = <0x3000 0x20 0xFE00 0x100>;

7. ranges

        以后补充

8. dma-ranges

        以后补充

四. DTS设备节点类型介绍

1. 根节点(/)

        设备树有一个根节点,其余节点都是子节点,根节点使用/表示,示意代码如下

  1. / {
  2. };

2. /aliases

        aliases节点是用来定义一个设备节点的别名的,aliases节点应该在设备树的根节点中使用。

aliases的属性名是需要指定的别名,属性值是设备树中某个节点的完整路径,示例如下

  1. aliases {
  2. serial0 = "/simple-bus@fe000000/serial@llc500";
  3. ethernet0 = "/simple-bus@fe000000/ethernet@31c000";
  4. };

3. /memory

       memory节点是用于描述系统的物理内存的的布局的,如果系统有多个地址范围的内存,则多个memory节点需要创建,或者在reg节点中指定多个范围。示例如下

  1. memory@0 {
  2. device_type = "memory";
  3. reg = <0x000000000 0x00000000 0x00000000 0x80000000
  4. 0x000000001 0x00000000 0x00000001 0x00000000>;
  5. };
  1. memory@0 {
  2. device_type = "memory";
  3. reg = <0x000000000 0x00000000 0x00000000 0x80000000>;
  4. };
  5. memory@100000000 {
  6. device_type = "memory";
  7. reg = <0x000000001 0x00000000 0x00000001 0x00000000>;
  8. };

4. /chosen

        chosen节点不用来描述一个真实的设备,而是描述设备的启动和运行参数,例如bootargs,示例如下

  1. chosen {
  2. bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200";
  3. };

5. /cpus

        后面补充

6. /cpus/cpu*

        后面补充

五. 总结

        本文主要介绍了设备树的格式布局,属性名,设备节点名的使用。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/712739
推荐阅读
相关标签
  

闽ICP备14008679号