微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM Linux 3.x的设备树(Device Tree)

ARM Linux 3.x的设备树(Device Tree)

时间:11-09 来源:互联网 点击:

  1. match[]__initconst={
  2. 490"arm,vexpress",
  3. 491"xen,xenvm",
  4. 492NULL,
  5. 493};
  6. 495DT_MACHINE_START(VEXPRESS_DT,"ARM-VersatileExpress")
  7. 496.dt_compat=v2m_dt_match,
  8. 497.smp=smp_ops(vexpress_smp_ops),
  9. 498.map_io=v2m_dt_map_io,
  10. 499.init_early=v2m_dt_init_early,
  11. 500.init_irq=v2m_dt_init_irq,
  12. 501.timer=&v2m_dt_timer,
  13. 502.init_machine=v2m_dt_init,
  14. 503.handle_irq=gic_handle_irq,
  15. 504.restart=vexpress_restart,
  16. 505MACHINE_END

Linux倡导针对多个SoC、多个电路板的通用DT machine,即一个DT machine的.dt_compat表含多个电路板.dts文件的root结点compatible属性字符串。之后,如果的电路板的初始化序列不一样,可以透过int of_machine_is_compatible(const char *compat) API判断具体的电路板是什么。

譬如arch/arm/mach-exynos/mach-exynos5-dt.c的EXYNOS5_DT machine同时兼容"samsung,exynos5250"和"samsung,exynos5440":

[cpp]view plaincopy

  1. 158staticcharconst*exynos5_dt_compat[]__initdata={
  2. 159"samsung,exynos5250",
  3. 160"samsung,exynos5440",
  4. 161NULL
  5. 162};
  6. 163
  7. 177DT_MACHINE_START(EXYNOS5_DT,"SAMSUNGEXYNOS5(FlattenedDeviceTree)")
  8. 178/*Maintainer:KukjinKim*/
  9. 179.init_irq=exynos5_init_irq,
  10. 180.smp=smp_ops(exynos_smp_ops),
  11. 181.map_io=exynos5_dt_map_io,
  12. 182.handle_irq=gic_handle_irq,
  13. 183.init_machine=exynos5_dt_machine_init,
  14. 184.init_late=exynos_init_late,
  15. 185.timer=&exynos4_timer,
  16. 186.dt_compat=exynos5_dt_compat,
  17. 187.restart=exynos5_restart,
  18. 188.reserve=exynos5_reserve,
  19. 189MACHINE_END

它的.init_machine成员函数就针对不同的machine进行了不同的分支处理:

[cpp]view plaincopy

  1. 126staticvoid__initexynos5_dt_machine_init(void)
  2. 127{
  3. 128…
  4. 149
  5. 150if(of_machine_is_compatible("samsung,exynos5250"))
  6. 151of_platform_populate(NULL,of_default_bus_match_table,
  7. 152exynos5250_auxdata_lookup,NULL);
  8. 153elseif(of_machine_is_compatible("samsung,exynos5440"))
  9. 154of_platform_populate(NULL,of_default_bus_match_table,
  10. 155exynos5440_auxdata_lookup,NULL);
  11. 156}

使用Device Tree后,驱动需要与.dts中描述的设备结点进行匹配,从而引发驱动的probe()函数执行。对于platform_driver而言,需要添加一个OF匹配表,如前文的.dts文件的"acme,a1234-i2c-bus"兼容I2C控制器结点的OF匹配表可以是:

[cpp]view plaincopy

  1. 436staticconststructof_device_ida1234_i2c_of_match[]={
  2. 437{.compatible="acme,a1234-i2c-bus",},
  3. 438{},
  4. 439};
  5. 440MODULE_DEVICE_TABLE(of,a1234_i2c_of_match);
  6. 441
  7. 442staticstructplatform_driveri2c_a1234_driver={
  8. 443.driver={
  9. 444.name="a1234-i2c-bus",
  10. 445.owner=THIS_MODULE,
  11. 449.of_match_table=a1234_i2c_of_match,
  12. 450},
  13. 451.probe=i2c_a1234_probe,
  14. 452.remove=i2c_a1234_remove,
  15. 453};
  16. 454module_platform_driver(i2c_a1234_driver);

对于I2C和SPI从设备而言,同样也可以透过of_match_table添加匹配的.dts中的相关结点的compatible属性,如sound/soc/codecs/wm8753.c中的:

[cpp]view plaincopy

  1. 1533staticconststructof_device_idwm8753_of_match[]={
  2. 1534{.compatible="wlf,wm8753",},
  3. 1535{}
  4. 1536};
  5. 1537MODULE_DEVICE_TABLE(of,wm8753_of_match);
  6. 1587staticstructspi_driverwm8753_spi_driver={
  7. 1588.driver={
  8. 1589.name="wm8753",
  9. 1590.owner=THIS_MODULE,
  10. 1591.of_match_table=wm8753_of_match,
  11. 1592},
  12. 1593.probe=wm8753_spi_probe,
  13. 1594.remove=wm8753_spi_remove,
  14. 1595};
  15. 1640staticstructi2c_driverwm8753_i2c_driver={
  16. 1641.driver={
  17. 1642.name="wm8753",
  18. 1643.owner=THIS_MODULE,
  19. 1644.of_match_table=wm8753_of_match,
  20. 1645},
  21. 1646.probe=wm8753_i2c_probe,
  22. 1647.remove=wm8753_i2c_remove,
  23. 1648.id_table=wm8753_i2c_id,
  24. 1649};

不过这边有一点需要提醒的是,I2C和SPI外设驱动和Device Tree中设备结点的compatible 属性还有一种弱式匹配方法,就是别名匹配。compatible 属性的组织形式为,,别名其实就是去掉compatible 属性中逗号前的manufacturer前缀。关于这一点,可查看drivers/spi/spi.c的源代码,函数spi_match_device()暴露了更多的细节,如果别名出现在设备spi_driver的id_table里面,或者别名与spi_driver的name字段相同,SPI设备和驱动都可以匹配上:

[cpp]view plaincopy

  1. 90staticintspi_match_device(structdevice*

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top