ARM Linux 设备树

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_39655765/article/details/80330445

关于Linux 设备树

0. DTS、DTC和DTB

  ① DTS,位于arch/arm/boot/dts/
  ② DTC,将.dts编译为.dtb的工具,源码位于scripts/dtc/
  ③ DTB (Device Tree Big large object),.dts的被DTC编译后得二进制文件。

1. 兼容属性

/*                    具体     -->      抽象    */
compatible = "manufacturer, model", "manufacturer2,model2"... ;
  • 用于板与DT_MACHINE_START 或者 设备与驱动 的匹配。

2. 设备节点命名

/*设备类型@内存基地址或总线地址
   |        |                 */
<name>[@<unit_addr>] { 
    ...
};
  • “< >”表示必须有; “[ ]”表示可选;

3. label命名

<设备类型><index> :
  • 其他节点通过&label来访问该节点,进行引用或者修改属性的值

  • “< >”表示必须有;

4. 地址编码

reg = <addr_1 len_1 addr_2 len_2 ...>;
/*       |      |_______________
         |                     |
父节点#address-cells=<n> 和  #size-cells=<n>  决定其单元数 */

子 —> 父地址转换表:ranges = <child_addr parent_addr map_len
                            child_addr1 parent_addr1 map_len1
                            ... >;

5. 中断连接

  ① 中断控制器:

interrupt-controller;   /* 表明身份 */
#interrupt-cells = <n>; /* 指示连接此中断控制器之设备的中断属性cells个数 */  

  ② 开启中断的设备:

interrupt-parent = <&int_ctrl_label>;   /* 指示所依附的中断控制器 */
interrupt = < x ... >, <y ... >;    /* 中断控制器#interrupt-cells决定cell个数,逗号隔开多个中断号 */
interrupt-name = "x_name","y_name", ... ;    /* 给特定中断号起名 */
  • index获取中断号:int platform_get_irq(struct platform_device *dev, unsigned int num);
  • 中断名获得中断号:int platform_get_irq_byname(struct platform_device *dev, const char *name);

6. GPIO、时钟、pinmux的连接

6.1 GPIO

  ① GPIO控制器:

gpio-controller;   /* 表明身份 */
#gpio-cells = <n>; /* 连接此GPIO控制器之设备的xxx-gpios属性cells个数 */  

  ② 使用GPIO的设备:

xxx-gpios = <&ctrl_label n ...>; /* 所依附的gpio控制器之#gpio-cells决定cells个数 */
  • 使用xxx-gpios获得gpio口:static inline int of_get_named_gpio(struct device_node *np, const char *propname, int index)
  • 设备只有一个gpio属性时,不关心GPIO名字获得gpio口:static inline int of_get_gpio(struct device_node *np, int index)

6.2 时钟

  ① 外部时钟

clock-frequency = <n>;      /* 表明外部时钟之频率 */
clock-output-names = "xxx"; /* 外部时钟导出名字到设备驱动 */
#clock-cells = <0>;         /* 规定引用此节点之设备的clocks属性的cells个数 */

  ② 时钟控制器

clocks: clock-controller@n {
    ...
    clock-names = "xxx", "yyy"; /* 定义属性clocks中时钟之名 */
    clocks = <&xxx>, <&yyy>;    /* 引用外部时钟节点定义属性clocks */
    #clock-cells = <n>;         /* 规定引用此节点之设备的clocks属性的cells个数 */
    ...
};

  ③ 使用时钟的设备

/*      长度为时钟控制器#clock-cells
                  +--^--+            */
clocks = <&clocks n1 ...>, <&clocks n2 ...>, ...; /* 引用时钟控制器节点来定义属性clocks */
clock-names = "iii", "jjj", ...;    /* 定义属性clocks中时钟之名 */
  • clock-name定义的名字获得时钟:struct clk *clk_get(struct device *dev, const char *con_id)

6.3 pinmux

  ① pinmux引脚群

xxx: yyy {
    vendor_name,pins = "pin_name1", "pin_name2", ...;
    vendor_name,pin-function = <n>;   /* 引脚功能设置 */
    vendor_name,pin-pud = <n>;        /* 引脚支路电阻上下拉或不接设置 */
    vendor_name,pin-drv = <n>;        /* 引脚电流驱动能力等级设置 */
};

  ② 设备使用引脚群

pinctrl-names = "default";
pinctrl-0 = <&xxx>;     /* 引用引脚群xxx */

参考文献

  [1] 宋宝华. Linux设备驱动开发详解[M].北京:机械工业出版社,2015

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页