前言
曾经有大神跟我说Linux驱动的本质是读写寄存器,我不以为然,直到后来我认真理解了Linux的设备树机制 ……
节点
根节点的定义,以/
开头,它可以跨多个文件定义
1 | / { |
SOC信息描述,以RK3399 SOC为例
1 | model = "Rockchip RK3399 Excavator Board (Linux Opensource)"; |
普通的节点定义,不带标签意味着它不需要在别处引用
1 | gpio-keys { |
带标签是为了在别处能够访问,格式:标签名: 节点名
,后面跟一个括号{ … };
1 | /* 标签名: 节点名 */ |
通常使用&标签名
来引用一个节点,引用一个节点意味着追加、补充这个节点的配置信息
1 | /* 追加、补充这个节点的配置信息 */ |
匹配信息,用compatible
表示,这个相当于节点的身份信息
1 | compatible = "gpio-keys"; |
寄存器
寄存器定义格式:<高32位地址 低32位地址 高32位长度 低32位长度>,由于RK3399是64位处理器的缘故,address-cells
为1代表4个字节
1 | i2c0: i2c@ff3c0000 { |
时钟源
一般可选多个时钟源,看外设的需要,i2c需要2个时钟源:一个给SCL,一个提供寄存器访问,时钟源信息一般在./include/dt-bindings/clock/rk3399-cru.h
里边给出,clocks
和clock-names
是按顺序匹配的
1 | clocks = <&pmucru SCLK_I2C0_PMU>, <&pmucru PCLK_I2C0_PMU>; |
中断
中断配置存在头文件当中:include/dt-bindings/interrupt-controller/arm-gic.h和include/dt-bindings/interrupt-controller/irq.h
1 | interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH 0>; |
GPIO
RK3399 GPIO0表示第0个bank的GPIO,第0个bank的GPIO索引:0-31,分为A、B、C、D四组,以下对应的是GPIO0_B4
管脚:B代表1,1x8+4=12
1 | gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; |
以下对应的是GPIO4_C6
管脚:C代表2,2x8+6=22
1 | gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>; |
引脚
引脚复用(也就是说一个引脚它可能是GPIO,也可以是USART_RXD,或者是I2C_SCL)
1 | pinctrl-names = "default"; |
补充定义pinctrl
1 | &pinctrl { |
IO复用需要通过标签名方式来引用,以下代码的sdmmc-pwrseq、lsm330_a、lsm330_g … 是分类的作用
功能模块 | 节点标签 | 引脚位置 | 复用功能 | 电气属性 |
---|---|---|---|---|
SD卡电源控制 | sdcard_enable_h |
GPIO1_B4 (Bank1, Pin20) | RK_FUNC_GPIO |
无上下拉 (none ) |
加速度计 | lsm330a_irq_gpio |
GPIO1_B6 (Bank1, Pin22) | RK_FUNC_GPIO |
无上下拉 (none ) |
陀螺仪 | lsm330g_irq_gpio |
GPIO1_B8 (Bank1, Pin24) | RK_FUNC_GPIO |
无上下拉 (none ) |
磁力计 | ak8963_irq_gpio |
GPIO1_A0 (Bank1, Pin0) | RK_FUNC_GPIO |
无上下拉 (none ) |
光传感器 | cm3218_irq_gpio |
GPIO4_D0 (Bank4, Pin24) | RK_FUNC_GPIO |
上拉 (pull_up ) |
LED控制 | led1_ctl |
GPIO0_B4 (Bank0, Pin12) | RK_FUNC_GPIO |
上拉 (pull_up ) |
蜂鸣器 | beep_gpio |
GPIO4_C6 (Bank4, Pin22) | RK_FUNC_GPIO |
上拉 (pull_up ) |
触摸屏 | gt911_gpio |
GPIO1_A9 (Bank1, Pin9) | RK_FUNC_GPIO |
上拉 (pull_up ) |
GPIO1_B4 (Bank1, Pin20) | RK_FUNC_GPIO |
上拉 (pull_up ) |
||
LCD面板 | lcd_panel_reset |
GPIO4_D6 (Bank4, Pin30) | RK_FUNC_GPIO |
无上下拉 (none ) |
lcd_panel_pwr_en |
GPIO3_D0 (Bank3, Pin16) | RK_FUNC_GPIO |
下拉 (pull_down ) |
|
lcd_panel_lcd_en |
GPIO1_A4 (Bank1, Pin4) | RK_FUNC_GPIO |
下拉 (pull_down ) |
节点状态
用status字段表示:一般有okay和disabled两种状态
1 | status = "disabled"; |
答疑
- 引用节点的话可以改变原有的内容吗?还是只能新增:补充和新增
- RK3399的GPIO映射关系:参考上面
GPIO
小结:一个BANK(0-31)分为A、B、C、D四组 - 根节点可以放在多个文件之中吗?:可以的
术语
- dtc:device tree compiler,设备树编译工具
- dts:device tree source,设备树源文件
- dtsi:device tree source include,设备树头文件
- dtb:device tree blob,设备树文件(二进制)