0 设备树实现驱动程序的框架
上下分层,左右分离的程序设计思想
上下分层:上层leddrv.c负责注册file_operations 结构体,实现open/write等函数
下层chip_demo_gpio.c为上层提供硬件接口get_board_led_opr
左右分离:dev和drv分离设计,dev由设备树生成,与drv匹配
1 内核对设备树的处理
Linux内核将设备树中的节点转换为device_node 结构体,
对于某些device_node 结构体,会被转换为platform_device 结构体
我们不关心内核时怎么转换出platform_device 结构体的,只需了解
⚫ platform_device 中含有resource 数组, 它来自device_node 的reg, interrupts 属性;
⚫ platform_device.dev.of_node 指向device_node, 可以通过它获得其他属性
2 platform_device 与platform_driver 配对
比较对象为:
设备树生成的platform_device.dev.of_node
驱动程序中的platform_driver.driver.of_match_table数组,其结构为
比较优先级顺序,compatible -> type -> name
若成功匹配则执行driver中的.probe
LED驱动程序设备树匹配示例
2.1 修改设备树添加led 设备节点
在设备树文件根节点下添加
#define GROUP_PIN(g,p) ((g<<16) | (p))
100ask_led@0 {
compatible = "100ask,leddrv";
pin = <GROUP_PIN(3, 1)>;
};
100ask_led@1 {
compatible = "100as,leddrv";
pin = <GROUP_PIN(5, 8)>;
};
2.2 修改platform_driver 的源码
在chip_demo_gpio.c中修改下列代码
/* 查找设备树中的ask100_leds节点device_id中
* 是否有.compatible = "100as,leddrv" 这样的dev
* 若有,匹配成功,执行.probe函数 */
static const struct of_device_id ask100_leds[] = {
{ .compatible = "100as,leddrv" },
{ },
};
/* platform_driver */
static struct platform_driver chip_demo_gpio_driver = {
.probe = chip_demo_gpio_probe,
.remove = chip_demo_gpio_remove,
.driver = {
.name = "100ask_led", /*与设备树中的ask100_led节点匹配*/
.of_match_table = ask100_leds, /*.of_match_table是一个of_device_id ask100_leds[]数组,*/
/* of_match_table用于从完整设备树项查找匹配项 */
},
};
设备树驱动程序框架(以LED程序为例)