设备树(Device Tree)
设备树介绍:
设备树是一个描述设备硬件资源的文件,该文件是由节点组成的树形结构。如下:
/ {
node1 {
a-string-property = "A string";
a-string-list-property = "first string", "second string";
// hex is implied in byte arrays. no '0x' prefix is required
a-byte-data-property = [01 23 34 56];
child-node1 {
first-child-property;
second-child-property = <1>;
a-string-property = "Hello, world";
};
child-node2 {
};
};
node2 {
an-empty-property;
a-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */
child-node1 {
};
};
};
① “/”是根节点,node1和node2,是其子节点;
② “child-node1” 和 “child-node2”,是node1的子节点;
③ a-string-property,是字符串属性;
④ a-string-list-property,字符串列表属性;
⑤ a-byte-data-property,是字节数据属性;
节点与属性:
节点的定义:
[label:][@unit-address] {
properties;
child-node {
[...]
};
};
常见属性:
compatible,用来匹配驱动,一般有"供应商,产品"
#address-cells,决定子节点reg属性的地址cell数,cell是u32
#size-cells,决定子节点reg属性的地址长度cell数,cell是u32
reg,一般为设备寄存器地址及范围,如
设备树实例:
添加LED节点:
$ vim arch/arm/boot/dts/exynos4412-fs4412.dts
fs4412-led {
compatible = "farsight,fs4412-led";
reg = <0x114001E0 0x8>;
};
$ cd ../../../..
$ make dtbs
$ cp arch/arm/boot/dts/exynos4412-fs4412.dtb /tftpboot
代码:
1 #include
2 #include
3 #include
4 #include
5 #include
6
7 #define GPF3CON 0x0
8 #define GPF3DAT 0x4
9
10
11 void __iomem *led_va;
12 int led_probe(struct platform_device *pdev)
13 {
14 unsigned int regval;
15 struct resource *res;
16
17 printk("led probe\n");
18 /* 1. 获取资源,中断或者内存 */
19 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
20 if (!res) {
21 printk("get platform resource failure\n");
22 return -EINVAL;
23 }
24
25 /* 2. 内存映射,并初始化设备 */
26 led_va = ioremap(res->start, resource_size(res)); /* 内存映射得到虚拟地址 */
27 regval = readl(led_va + GPF3CON); /* (led_va + GPF3CON) 寄存器的虚拟地址*/
28 regval &= ~(0xf<<20); /* GPFCON[23:20]清零 */
29 regval |= 0x1<<20; /* 配置GPF3_5引脚功能为输出 */
30 writel(regval, led_va + GPF3CON);
31 regval = readl(led_va + GPF3DAT);
32 regval |= 0x1<<5; /* 控制GPF3_5输出高电平 */
33 writel(regval, led_va + GPF3DAT);
34 return 0; /* 0表示成功,<0表示失败 */
35 }
36
37 int led_remove(struct platform_device *pdev)
38 {
39 unsigned int regval;
40 printk("led remove\n");
41 regval = readl(led_va + GPF3CON); /* (led_va + GPF3CON) 寄存器的虚拟地址*/
42 regval &= ~(0xf<<20); /* GPFCON[23:20]清零 */
43 writel(regval, led_va + GPF3CON);
44 iounmap(led_va);
45 return 0;
46 }
47
48 /* 用来匹配平台设备的列表 */
49 const struct of_device_id of_device_table[] = {
50 {.compatible = "farsight,fs4412-led"},
51 {}
52 };
53
54 struct platform_driver pdrv = {
55 .probe = led_probe,
56 .remove = led_remove,
57 .driver = {
58 .owner = THIS_MODULE,
59 .name = "fs4412-led",
60 .of_match_table = of_match_ptr(of_device_table),
61 },
62 };
63
64 static int hello_init(void)
65 {
66 printk("Hello, Kernel!\n");
67 return platform_driver_register(&pdrv);
68 }
69
70 static void hello_exit(void)
71 {
72 printk("Goodbye, Kernel!\n");
73 platform_driver_unregister(&pdrv);
74 }
75
76 module_init(hello_init); /* 声明模块加载函数 */
77 module_exit(hello_exit); /* 声明模块卸载函数 */
78
79 MODULE_LICENSE("GPL"); /* 声明模块遵守的开源协议 */
80 MODULE_AUTHOR("zhufeng "); /* 模块作者 */
81 MODULE_DESCRIPTION("hello module"); /* 模块描述信息 */