linux内核设备树api,设备树详解(链接很好,作者嵌入式Linux见解深刻)

设备树详解http://blog.csdn.net/qq_28992301/article/details/53321610

设备树详解

在Linux3.x版本后,arch/arm/plat-xxx和arch/arm/mach-xxx中,描述板级细节的代码(比如platform_device、i2c_board_info等)被大量取消,取而代之的是设备树,其目录位于arch/arm/boot/dts

U-boot引导内核流程分析 第6节。只要内核知晓了dtb文件的地址,那么驱动就可以通过一些API任意获取设备树的内部信息

这里以pcf8523驱动为例,只要驱动中的of_match_table 中的compatible 值和设备节点中的compatible 相匹配,那么probe函数就会被触发。不仅i2c是这样,platform、spi等都是这个原理

/*定义的of_match_table*/

static const struct of_device_id pcf8523_of_match[] = {

{ .compatible = "nxp,pcf8523" },

{ }

};

/*driver 结构体中的of_match_table*/

static struct i2c_driver pcf8523_driver = {

.driver = {

.name = DRIVER_NAME,

.owner = THIS_MODULE,

.of_match_table = of_match_ptr(pcf8523_of_match),

},

.probe = pcf8523_probe,

.id_table = pcf8523_id,

};1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

compatible = "pcf8523";,显然相对于驱动id_table中的"nxp,pcf8523",他遗漏了nxp字段,但是驱动却仍然可以匹配上,因为别名匹配对compatible中字符串里第二个字段敏感

4.常见属性的设置与获取

当修改或编写驱动时,常常需要修改gpio、时钟、中断等等参数,以前都是在mach-xxx中的device设置的,现在则要在节点里设置,然后驱动用特殊的API来获取

int of_device_is_compatible(const struct device_node *device, const char

*name)来判断当前节点是否包含指定的compatible(兼容性)

gpio的设置与获取

/*imx6dl.dtsi中gpio1控制器的定义节点*/

gpio1: gpio@0209c000 {

compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";

reg = <0x0209c000 0x4000>;

interrupts = <0 66 IRQ_TYPE_LEVEL_HIGH>,

<0 67 IRQ_TYPE_LEVEL_HIGH>;

gpio-controller;

#gpio-cells = <2>;

interrupt-controller;

#interrupt-cells = <2>;

};

/*imx6qdl-sabreauto.dtsi中某个设备节点*/

max7310_reset: max7310-reset {

compatible = "gpio-reset";

reset-gpios = ;

reset-delay-us = <1>;

#reset-cells = <0>;

};1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

xxx-gpios(xxx我们可以随便起),这样驱动才能通过特定API从识别该属性,并转换成具体的gpio号

reset-gpios = ;这格式是什么意思呢?&gpio1

15引用了gpio1节点,故此处含义为gpio1_15这个引脚;最后一个参数1则代表低电平有效,0则为高电平有效。至于gpio1_15具体对应哪个引脚,在imx6的手册上都有详细描述

#gpio-cells = <2>;,所以才有两个参数;某些soc的gpio节点中会设置为#gpio-cells

= <1>;,那么可以不写最后一个参数

xxx-gpios相同;最后一个是编号index,当节点中有n个同名的xxx-gpios时,可以通过它来获取特定的那个gpio,同一节点中gpio同名情况很少存在,所以我们都把index设为0

gpio = of_get_named_gpio(node, "reset-gpios", index);1

在dts和驱动都不关心gpio名字的情况下,也可直接通过以下接口来获取gpio号,这个时候编号index就十分重要了,可以指定拿取节点的第index个gpio属性

gpio = of_get_gpio(node, index);1

中断的设置与获取

假设某设备节点需要一个gpio中断

/*先确定中断所在的组*/

interrupt-parent = ;

/*表示中断,GPIO6中的第8个IO,2为触发类型,下降沿触发*/

interrupts = <8 2>;1

2

3

4

5

6

中断号 =irq_of_parse_and_map(node, index)函数返回值来得到中断号

自定义属性的设置与获取

所谓的自定义属性,有点类似于老内核中的platform_data,我们在设备节点中可以随意添加自定义属性,比如下面这个节点里面的属性都是我们自己定义的

reg_3p3v: 3p3v {

compatible = "regulator-fixed";

regulator-name = "3P3V";

regulator-min-microvolt = <3300000>;

regulator-max-microvolt = <3300000>;

regulator-always-on;

};1

2

3

4

5

6

7

针对32位整形的属性,比如上面的regulator-min-microvolt,可以利用下面这个API来获取属性值,第一个参数是节点,第二个参数是属性名字,第三个是输出型参数(把读出来的值放进去)

of_property_read_u32(node, "regulator-min-microvolt", &microvolt);1

类似的读取数值的API还有:

int of_property_read_u8(const struct device_node *np, const char *propname, u8 *out_value)

int of_property_read_u16(const struct device_node *np, const char *propname, u16 *out_value)1

2

3

4

下列API可检查节点中某个属性是否存在,存在则返回true,不存在则返回false

bool of_property_read_bool(const struct device_node *np, const char *propname)1

当节点中存在字符串时,可以像下面那样读取,比如我们读取前面reg_3p3v节点中的字符串

of_property_read_string(node, "regulator-name", &string)1

当节点中存在数组时,可以像下面那样读取

/*带有数组的某个节点*/

L2: cache-controller@1e00a000 {

compatible = "arm,pl310-cache";

arm,data-latency = <1 1 1>;

arm,tag-latency = <1 1 1>;

};

/*驱动中使用API来读取数组, &data为输出型参数*/

of_property_read_u32_array(node, "arm,pl310-cache", &data, ARRAY_SIZE(data));

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值