ARM Linux 3.x的设备树(Device Tree)
来源:互联网 发布:htpc 软件 遥控 编辑:程序博客网 时间:2024/04/29 07:38
宋宝华 Barry Song <21cnbao@gmail.com>
1. ARM Device Tree起源
- CPU的数量和类别
- 内存基地址和大小
- 总线和桥
- 外设连接
- 中断控制器和中断使用情况
- GPIO控制器和GPIO使用情况
- Clock控制器和Clock使用情况
2. Device Tree组成和结构
DTS (device tree source)
/ { node1 { a-string-property = "A string"; a-string-list-property = "first string", "second string"; a-byte-data-property = [0x01 0x23 0x34 0x56]; 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 { }; };};
/ { compatible = "acme,coyotes-revenge"; #address-cells = <1>; #size-cells = <1>; interrupt-parent = <&intc>; cpus { #address-cells = <1>; #size-cells = <0>; cpu@0 { compatible = "arm,cortex-a9"; reg = <0>; }; cpu@1 { compatible = "arm,cortex-a9"; reg = <1>; }; }; serial@101f0000 { compatible = "arm,pl011"; reg = <0x101f0000 0x1000 >; interrupts = < 1 0 >; }; serial@101f2000 { compatible = "arm,pl011"; reg = <0x101f2000 0x1000 >; interrupts = < 2 0 >; }; gpio@101f3000 { compatible = "arm,pl061"; reg = <0x101f3000 0x1000 0x101f4000 0x0010>; interrupts = < 3 0 >; }; intc: interrupt-controller@10140000 { compatible = "arm,pl190"; reg = <0x10140000 0x1000 >; interrupt-controller; #interrupt-cells = <2>; }; spi@10115000 { compatible = "arm,pl022"; reg = <0x10115000 0x1000 >; interrupts = < 4 0 >; }; external-bus { #address-cells = <2> #size-cells = <1>; ranges = <0 0 0x10100000 0x10000 // Chipselect 1, Ethernet 1 0 0x10160000 0x10000 // Chipselect 2, i2c controller 2 0 0x30000000 0x1000000>; // Chipselect 3, NOR Flash ethernet@0,0 { compatible = "smc,smc91c111"; reg = <0 0 0x1000>; interrupts = < 5 2 >; }; i2c@1,0 { compatible = "acme,a1234-i2c-bus"; #address-cells = <1>; #size-cells = <0>; reg = <1 0 0x1000>; interrupts = < 6 2 >; rtc@58 { compatible = "maxim,ds1338"; reg = <58>; interrupts = < 7 3 >; }; }; flash@2,0 { compatible = "samsung,k8f1315ebm", "cfi-flash"; reg = <2 0 0x4000000>; }; };};
flash@0,00000000 { compatible = "arm,vexpress-flash", "cfi-flash"; reg = <0 0x00000000 0x04000000>, <1 0x00000000 0x04000000>; bank-width = <4>; };
- reg
- #address-cells
- #size-cells
ranges = <0 0 0x10100000 0x10000 // Chipselect 1, Ethernet 1 0 0x10160000 0x10000 // Chipselect 2, i2c controller 2 0 0x30000000 0x1000000>; // Chipselect 3, NOR Flash
01 The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI02 interrupts.0304 The 2nd cell contains the interrupt number for the interrupt type.05 SPI interrupts are in the range [0-987]. PPI interrupts are in the06 range [0-15].0708 The 3rd cell is the flags, encoded as follows:09 bits[3:0] trigger type and level flags.10 1 = low-to-high edge triggered11 2 = high-to-low edge triggered12 4 = active high level-sensitive13 8 = active low level-sensitive14 bits[15:8] PPI interrupt cpu mask. Each bit corresponds to each of15 the 8 possible cpus attached to the GIC. A bit set to '1' indicated16 the interrupt is wired to that CPU. Only valid for PPI interrupts.
DTC (device tree compiler)
dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \ vexpress-v2p-ca9.dtb \ vexpress-v2p-ca15-tc1.dtb \ vexpress-v2p-ca15_a7.dtb \ xenvm-4.2.dtb
Device Tree Blob (.dtb)
Binding
Bootloader
3. Device Tree引发的BSP和驱动变更
90 static struct resource xxx_resources[] = {91 [0] = {92 .start = …,93 .end = …,94 .flags = IORESOURCE_MEM,95 },96 [1] = {97 .start = …,98 .end = …,99 .flags = IORESOURCE_IRQ,100 },101 };102103 static struct platform_device xxx_device = {104 .name = "xxx",105 .id = -1,106 .dev = {107 .platform_data = &xxx_data,108 },109 .resource = xxx_resources,110 .num_resources = ARRAY_SIZE(xxx_resources),111 };
18 static struct of_device_id xxx_of_bus_ids[] __initdata = {19 { .compatible = "simple-bus", },20 {},21 };2223 void __init xxx_mach_init(void)24 {25 of_platform_bus_probe(NULL, xxx_of_bus_ids, NULL);26 }3233 #ifdef CONFIG_ARCH_XXX3839 DT_MACHINE_START(XXX_DT, "Generic XXX (Flattened Device Tree)")41 …45 .init_machine = xxx_mach_init,46 …49 MACHINE_END50 #endif
145 static struct i2c_board_info __initdata afeb9260_i2c_devices[] = {146 {147 I2C_BOARD_INFO("tlv320aic23", 0x1a),148 }, {149 I2C_BOARD_INFO("fm3130", 0x68),150 }, {151 I2C_BOARD_INFO("24c64", 0x50),152 },153 };
i2c@1,0 { compatible = "acme,a1234-i2c-bus"; … rtc@58 { compatible = "maxim,ds1338"; reg = <58>; interrupts = < 7 3 >; }; };
79 static struct spi_board_info afeb9260_spi_devices[] = {80 { /* DataFlash chip */81 .modalias = "mtd_dataflash",82 .chip_select = 1,83 .max_speed_hz = 15 * 1000 * 1000,84 .bus_num = 0,85 },86 };
373 MACHINE_START(VEXPRESS, "ARM-Versatile Express")374 .atag_offset = 0x100,375 .smp = smp_ops(vexpress_smp_ops),376 .map_io = v2m_map_io,377 .init_early = v2m_init_early,378 .init_irq = v2m_init_irq,379 .timer = &v2m_timer,380 .handle_irq = gic_handle_irq,381 .init_machine = v2m_init,382 .restart = vexpress_restart,383 MACHINE_END
489 static const char * const v2m_dt_match[] __initconst = {490 "arm,vexpress",491 "xen,xenvm",492 NULL,493 };495 DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")496 .dt_compat = v2m_dt_match,497 .smp = smp_ops(vexpress_smp_ops),498 .map_io = v2m_dt_map_io,499 .init_early = v2m_dt_init_early,500 .init_irq = v2m_dt_init_irq,501 .timer = &v2m_dt_timer,502 .init_machine = v2m_dt_init,503 .handle_irq = gic_handle_irq,504 .restart = vexpress_restart,505 MACHINE_END
158 static char const *exynos5_dt_compat[] __initdata = {159 "samsung,exynos5250",160 "samsung,exynos5440",161 NULL162 };163177 DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")178 /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */179 .init_irq = exynos5_init_irq,180 .smp = smp_ops(exynos_smp_ops),181 .map_io = exynos5_dt_map_io,182 .handle_irq = gic_handle_irq,183 .init_machine = exynos5_dt_machine_init,184 .init_late = exynos_init_late,185 .timer = &exynos4_timer,186 .dt_compat = exynos5_dt_compat,187 .restart = exynos5_restart,188 .reserve = exynos5_reserve,189 MACHINE_END
126 static void __init exynos5_dt_machine_init(void)127 {128 …149150 if (of_machine_is_compatible("samsung,exynos5250"))151 of_platform_populate(NULL, of_default_bus_match_table,152 exynos5250_auxdata_lookup, NULL);153 else if (of_machine_is_compatible("samsung,exynos5440"))154 of_platform_populate(NULL, of_default_bus_match_table,155 exynos5440_auxdata_lookup, NULL);156 }
436 static const struct of_device_id a1234_i2c_of_match[] = {437 { .compatible = "acme,a1234-i2c-bus ", },438 {},439 };440 MODULE_DEVICE_TABLE(of, a1234_i2c_of_match);441442 static struct platform_driver i2c_a1234_driver = {443 .driver = {444 .name = "a1234-i2c-bus ",445 .owner = THIS_MODULE,449 .of_match_table = a1234_i2c_of_match,450 },451 .probe = i2c_a1234_probe,452 .remove = i2c_a1234_remove,453 };454 module_platform_driver(i2c_a1234_driver);
1533 static const struct of_device_id wm8753_of_match[] = {1534 { .compatible = "wlf,wm8753", },1535 { }1536 };1537 MODULE_DEVICE_TABLE(of, wm8753_of_match);1587 static struct spi_driver wm8753_spi_driver = {1588 .driver = {1589 .name = "wm8753",1590 .owner = THIS_MODULE,1591 .of_match_table = wm8753_of_match,1592 },1593 .probe = wm8753_spi_probe,1594 .remove = wm8753_spi_remove,1595 };1640 static struct i2c_driver wm8753_i2c_driver = {1641 .driver = {1642 .name = "wm8753",1643 .owner = THIS_MODULE,1644 .of_match_table = wm8753_of_match,1645 },1646 .probe = wm8753_i2c_probe,1647 .remove = wm8753_i2c_remove,1648 .id_table = wm8753_i2c_id,1649 };
90 static int spi_match_device(struct device *dev, struct device_driver *drv)91 {92 const struct spi_device *spi = to_spi_device(dev);93 const struct spi_driver *sdrv = to_spi_driver(drv);9495 /* Attempt an OF style match */96 if (of_driver_match_device(dev, drv))97 return 1;9899 /* Then try ACPI */100 if (acpi_driver_match_device(dev, drv))101 return 1;102103 if (sdrv->id_table)104 return !!spi_match_id(sdrv->id_table, spi);105106 return strcmp(spi->modalias, drv->name) == 0;107 }71 static const struct spi_device_id *spi_match_id(const struct spi_device_id *id,72 const struct spi_device *sdev)73 {74 while (id->name[0]) {75 if (!strcmp(sdev->modalias, id->name))76 return id;77 id++;78 }79 return NULL;80 }
4. 常用OF API
1682 if (of_device_is_compatible(np, "sirf,marco-pinctrl"))1683 is_marco = 1;struct device_node *of_find_compatible_node(struct device_node *from,
534 of_property_read_u32_array(np, "arm,data-latency",535 data, ARRAY_SIZE(data));
137 L2: cache-controller@1e00a000 {138 compatible = "arm,pl310-cache";139 reg = <0x1e00a000 0x1000>;140 interrupts = <0 43 4>;141 cache-level = <2>;142 arm,data-latency = <1 1 1>;143 arm,tag-latency = <1 1 1>;144 }
513 static inline int of_property_read_u8(const struct device_node *np,514 const char *propname,515 u8 *out_value)516 {517 return of_property_read_u8_array(np, propname, out_value, 1);518 }519520 static inline int of_property_read_u16(const struct device_node *np,521 const char *propname,522 u16 *out_value)523 {524 return of_property_read_u16_array(np, propname, out_value, 1);525 }526527 static inline int of_property_read_u32(const struct device_node *np,528 const char *propname,529 u32 *out_value)530 {531 return of_property_read_u32_array(np, propname, out_value, 1);532 }
int of_property_read_string(struct device_node *np, const char
1759 const char *of_clk_get_parent_name(struct device_node *np, int index)1760 {1761 struct of_phandle_args clkspec;1762 const char *clk_name;1763 int rc;17641765 if (index < 0)1766 return NULL;17671768 rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,1769 &clkspec);1770 if (rc)1771 return NULL;17721773 if (of_property_read_string_index(clkspec.np, "clock-output-names",1774 clkspec.args_count ? clkspec.args[0] : 0,1775 &clk_name) < 0)1776 clk_name = clkspec.np->name;17771778 of_node_put(clkspec.np);1779 return clk_name;1780 }1781 EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
static inline bool of_property_read_bool(const struct device_node *np,
5. 总结
0 0
- ARM Linux 3.x的设备树(Device Tree)
- ARM Linux 3.x的设备树(Device Tree)
- ARM Linux 3.x的设备树(Device Tree)
- ARM Linux 3.x的设备树(Device Tree)
- ARM Linux 3.x的设备树(Device Tree)
- ARM Linux 3.x的设备树(Device Tree)
- ARM Linux 3.x的设备树(Device Tree)
- ARM Linux 3.x的设备树(Device Tree)
- ARM Linux 3.x的设备树(Device Tree)
- ARM Linux 3.x的设备树(Device Tree)
- ARM Linux 3.x的设备树(Device Tree)
- ARM Linux 3.x的设备树(Device Tree)
- ARM Linux 3.x的设备树(Device Tree)
- ARM Linux 3.x的设备树(Device Tree)
- ARM Linux 3.x的设备树(Device Tree)
- ARM Linux 3.x的设备树(Device Tree)
- ARM Linux 3.x的设备树(Device Tree)
- ARM Linux 3.x的设备树(Device Tree)
- 第二次选拔——ZOJ
- machine learning 的测试数据
- 十七周周赛A——Parallelepiped
- 最小物联网系统设计——给Laravel添加测试
- 反向代理服务器的工作原理
- ARM Linux 3.x的设备树(Device Tree)
- JDK版本Java SE、Java EE、Java ME的区别
- Android配置文件里面可以开启的所有权限
- JAVA中使用File类批量重命名文件及java.io.File的常见用法
- Qt4.8.Xlinux编译出现 :/usr/include/linux/futex.h:96: 错误:‘u32’ 在此作用域中尚未声明
- 哪里有英语,哪里有欢乐
- linux下cocos2d-x 2.2.1编译过程中的问题
- c++继承中的内存布局 .
- TinyOS 2.1.1 安装续使用apt-get的方式得到的tinyos在编译MSP430处理器的时候会出现问题