内核对设备树的处理
从源代码文件 dts
文件开始,设备树的处理过程如下:
拆解
dts
在 PC 机上被编译为dtb
文件;u-boot
把dtb
文件传给内核;- 内核解析
dtb
文件,把每一个节点都转换为device_node
结构体; - 对于某些
device_node
结构体,会被转换为platform_device
结构体;
dtb 中每一个节点都被转换为 device_node 结构体
根节点被保存在全局变量 of_root
中,从 of_root
开始可以访问到任意节点。
哪些设备树节点会被转换为 platform_device
- 根节点下含有
compatile
属性的子节点 - 含有特定
compatile
属性节点的子节点
如果一个节点的compatile
属性,它的值是这4者之一:“simple-bus”, “simplemfd”,,“isa”,“arm,amba-bus”,
那么它的子节点(需含compatile
属性)也可以转换为platform_device
。 - 总线
I2C
、SPI
节点下的子节点:不转换为platform_device
某个总线下到子节点,应该交给对应的总线驱动程序来处理,他们不应该转换为platform_device
。
怎么转换为 platform_device
内核处理设备树的函数调用过程,这里就不去分析了;只总结结论:
platform_device
中含有resource
数组,它来自device_node
的reg, iinterrupts
属性;platform_device.dev.of_node
指向device_node
,可以通过它获取其他属性。
platform_device 与 platform_driver 是如何匹配的?
从设备树转换得到 platform_device
会被注册进内核里,以后当我们每注册一个platform_driver
时,它就会两两确定能否匹配,如果能配对成功就调用 platform_driver
的 probe
函数。
复习一下以前的 匹配规则
-
最先比较:是否强制选择某个
driver
比较platform_device.driver_override
和platform_driver.name
,可以设置platform_device
的driver_override
,强制选择某个platform_driver
-
然后比较:设备树信息
比较:platform_device.dev.of_node
和platform_driver.of_match_table
。由设备树节点转换得来的
platform_device
中,含有一个结构体of_node
它的类型如下:
如果一个platform_driver
支持设备树,它的platform_driver.driver.of_match_table
是一个数组,类型如下:
使用设备树信息来判断 dev 和 drv 是否配对时,
首先,如果 of_match_table 中含有 compatible 值,就跟 dev 的 compatile 属性比较,若一致则成功,否则返回失败;
其次,如果 of_match_table 中含有 type 值,就跟 dev 的 device_type 属性比较,若一致则成功,否则返回失败;
最后,如果 of_match_table 中含有 name 值,就跟 dev 的 name 属性比较,若一致则成功,否则返回失败。
而设备树中建议不再使用 devcie_type 和 name 属性,所以基本上只使用设备节点的compatible 属性来寻找匹配的 platform_driver。
-
接下来比较
platform_device_id
比较platform_device.name
和platform_driver.id_table[i].name
,id_table
中可能有多项。
platform_driver.id_table
是platform_device_id
指针,表示该drv
支持若干个device
,它里面列出各个device
的{.name, .driver_data}
,其中的name
表示该drv
支持的设备的名字,driver_data
是提供给改device
的私有数据。 -
最后比较
platform_device.name
和platform_driver.driver.name
platform_driver.id_table
可能为空,这时可以根据platform_driver.driver.name
来寻找同名的platform_device
。
总结成一张图: