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

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

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

3. Device Tree引发的BSP和驱动变更

有了Device Tree后,大量的板级信息都不再需要,譬如过去经常在arch/arm/plat-xxx和arch/arm/mach-xxx实施的如下事情:
1. 注册platform_device,绑定resource,即内存、IRQ等板级信息。

透过Device Tree后,形如

[cpp]view plaincopy

  1. 90staticstructresourcexxx_resources[]={
  2. 91[0]={
  3. 92.start=…,
  4. 93.end=…,
  5. 94.flags=IORESOURCE_MEM,
  6. 95},
  7. 96[1]={
  8. 97.start=…,
  9. 98.end=…,
  10. 99.flags=IORESOURCE_IRQ,
  11. 100},
  12. 101};
  13. 102
  14. 103staticstructplatform_devicexxx_device={
  15. 104.name="xxx",
  16. 105.id=-1,
  17. 106.dev={
  18. 107.platform_data=&xxx_data,
  19. 108},
  20. 109.resource=xxx_resources,
  21. 110.num_resources=ARRAY_SIZE(xxx_resources),
  22. 111};

之类的platform_device代码都不再需要,其中platform_device会由kernel自动展开。而这些resource实际来源于.dts中设备结点的reg、interrupts属性。典型地,大多数总线都与“simple_bus”兼容,而在SoC对应的machine的.init_machine成员函数中,调用of_platform_bus_probe(NULL, xxx_of_bus_ids, NULL);即可自动展开所有的platform_device。譬如,假设我们有个XXX SoC,则可在arch/arm/mach-xxx/的板文件中透过如下方式展开.dts中的设备结点对应的platform_device:

[cpp]view plaincopy

  1. 18staticstructof_device_idxxx_of_bus_ids[]__initdata={
  2. 19{.compatible="simple-bus",},
  3. 20{},
  4. 21};
  5. 22
  6. 23void__initxxx_mach_init(void)
  7. 24{
  8. 25of_platform_bus_probe(NULL,xxx_of_bus_ids,NULL);
  9. 26}
  10. 32
  11. 33#ifdefCONFIG_ARCH_XXX
  12. 38
  13. 39DT_MACHINE_START(XXX_DT,"GenericXXX(FlattenedDeviceTree)")
  14. 41…
  15. 45.init_machine=xxx_mach_init,
  16. 46…
  17. 49MACHINE_END
  18. 50#endif


2.注册i2c_board_info,指定IRQ等板级信息。

形如

[cpp]view plaincopy

  1. 145staticstructi2c_board_info__initdataafeb9260_i2c_devices[]={
  2. 146{
  3. 147I2C_BOARD_INFO("tlv320aic23",0x1a),
  4. 148},{
  5. 149I2C_BOARD_INFO("fm3130",0x68),
  6. 150},{
  7. 151I2C_BOARD_INFO("24c64",0x50),
  8. 152},
  9. 153};

之类的i2c_board_info代码,目前不再需要出现,现在只需要把tlv320aic23、fm3130、24c64这些设备结点填充作为相应的I2C controller结点的子结点即可,类似于前面的

[cpp]view plaincopy

  1. i2c@1,0{
  2. compatible="acme,a1234-i2c-bus";
  3. rtc@58{
  4. compatible="maxim,ds1338";
  5. reg=<58>;
  6. interrupts=<73>;
  7. };
  8. };

Device Tree中的I2C client会透过I2C host驱动的probe()函数中调用of_i2c_register_devices(&i2c_dev->adapter);被自动展开。

3. 注册spi_board_info,指定IRQ等板级信息。

形如

[cpp]view plaincopy

  1. 79staticstructspi_board_infoafeb9260_spi_devices[]={
  2. 80{/*DataFlashchip*/
  3. 81.modalias="mtd_dataflash",
  4. 82.chip_select=1,
  5. 83.max_speed_hz=15*1000*1000,
  6. 84.bus_num=0,
  7. 85},
  8. 86};

之类的spi_board_info代码,目前不再需要出现,与I2C类似,现在只需要把mtd_dataflash之类的结点,作为SPI控制器的子结点即可,SPI host驱动的probe函数透过spi_register_master()注册master的时候,会自动展开依附于它的slave。

4.多个针对不同电路板的machine,以及相关的callback。

过去,ARM Linux针对不同的电路板会建立由MACHINE_START和MACHINE_END包围起来的针对这个machine的一系列callback,譬如:

[cpp]view plaincopy

  1. 373MACHINE_START(VEXPRESS,"ARM-VersatileExpress")
  2. 374.atag_offset=0x100,
  3. 375.smp=smp_ops(vexpress_smp_ops),
  4. 376.map_io=v2m_map_io,
  5. 377.init_early=v2m_init_early,
  6. 378.init_irq=v2m_init_irq,
  7. 379.timer=&v2m_timer,
  8. 380.handle_irq=gic_handle_irq,
  9. 381.init_machine=v2m_init,
  10. 382.restart=vexpress_restart,
  11. 383MACHINE_END

这些不同的machine会有不同的MACHINE ID,Uboot在启动Linux内核时会将MACHINE ID存放在r1寄存器,Linux启动时会匹配Bootloader传递的MACHINE ID和MACHINE_START声明的MACHINE ID,然后执行相应machine的一系列初始化函数。

引入Device Tree之后,MACHINE_START变更为DT_MACHINE_START,其中含有一个.dt_compat成员,用于表明相关的machine与.dts中root结点的compatible属性兼容关系。如果Bootloader传递给内核的Device Tree中root结点的compatible属性出现在某machine的.dt_compat表中,相关的machine就与对应的Device Tree匹配,从而引发这一machine的一系列初始化函数被执行。

[cpp]view plaincopy

  1. 489staticconstchar*constv2m_dt_

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

网站地图

Top