uclass/udevice/drivers三者之间的关联
uclass可以理解为具有相同属性的device对外操作的接口, 它与上层接口直接通讯,其驱动为uclass_driver,给上层提供接口
udevice对具体设备的抽象,对应的驱动是driver; driver负责和硬件通讯,为uclass提供实际的操作集
udevice如何和uclass绑定:udevice对应的driver_id和uclass对应的uclass_driver_id是否匹配
hardware对应的driver绑定对应的udevice,udevice绑定uclass,uclass有其对应的uclass_driver
uclass和udevice是动态生成的
- udevice在解析fdt中的设备的时候自动生成,然后udevice找到对应的driver
- driver中保存了uclass_id, 根据它找到uclass_driver_id
- 从uclass链表中查找对应的uclass是否已经生成,若没有生成,则动态生成
- 重点是解析设备树,生成udevice, 并找到对应的driver
要分析uclass之前,首先得搞清楚两个宏U_BOOT_DRIVER及U_BOOT_DEVICE的作用:
1.U_BOOT_DRIVER及U_BOOT_DEVICE宏定义如下:
#define U_BOOT_DRIVER(__name) \
ll_entry_declare(struct driver, __name, driver)
#define U_BOOT_DEVICE(__name) \
ll_entry_declare(struct driver_info, __name, driver_info)
#define ll_entry_declare(_type, _name, _list) \
_type _u_boot_list_2_##_list##_2_##_name __aligned(4) \
__attribute__((unused, \
section(".u_boot_list_2_"#_list"_2_"#_name)))
全局数据GD中和DM相关部分
typedef struct global_data { // dts中的根节点,第一个创建的udevice struct udevice *dm_root; // relocation之前的根设备 struct udevice *dm_root_f; // uclass的链表, 挂的是有udevice的uclass struct list_head uclass_root; } gd_t;
2。通过对宏定义UCLASS_DRIVER的展开
/* Declare a new uclass_driver */
#define UCLASS_DRIVER(__name) \
ll_entry_declare(struct uclass_driver, __name, uclass)
#define ll_entry_declare(_type, _name, _list) \
_type _u_boot_list_2_##_list##_2_##_name __aligned(4) \
__attribute__((unused, \
section(".u_boot_list_2_"#_list"_2_"#_name)))
2-1
int dm_init_and_scan(bool pre_reloc_only)
{
int ret;
/*创建udevice和uclass空链表,创建根设备(root device)*/
ret = dm_init();
if (ret) {
debug("dm_init() failed: %d\n", ret);
return ret;
}
/*扫描U_BOOT_DEVICE定义的设备,与U_BOOT_DRIVER定义的driver进行查找,并绑定相应driver*/
ret = dm_scan_platdata(pre_reloc_only);
if (ret) {
debug("dm_scan_platdata() failed: %d\n", ret);
return ret;
}
if (CONFIG_IS_ENABLED(OF_CONTROL)) {
/*扫描由FDT设备树文件定义的设备,与U_BOOT_DRIVER定义的driver进行查找,并绑定相应driver*/
ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
if (ret) {
debug("dm_scan_fdt() failed: %d\n", ret);
return ret;
}
}
ret = dm_scan_other(pre_reloc_only);
if (ret)
return ret;
return 0;
}
dm_init():创建udevice和uclass空链表,创建根设备(root device)
2-2
[root.c]dm_init(); // 主要是初始化driver model的root实例(gd->dm_root和gd->uclass_root)
[device.c]device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);// 创建一个device并将其绑定到driver,这是一个帮助器函数,用于绑定不使用设备树的设备。
[list.c]lists_driver_lookup_name(“root_driver”); // 通过driver name “root_driver”遍历整个driver list,找到U_BOOT_DRIVER(root_driver)定义的driver地址
[device.c]device_bind_common(NULL, drv, “root_driver”, NULL, driver_data, node, 0, devp); // 创建udevice dm_root和uclass root,并将driver root_driver、udevice dm_root和uclass root三者进行绑定。
[uclass.c]uclass_get(drv->id, &uc); // 根据ID UCLASS_ROOT获取对应的uclass,第一次运行它不存在,所以创建它。
[uclass.c]uclass_find(); // 第一次运行无法找到对应的uclass UCLASS_ROOT。
[uclass.c]uclass_add(); //在未找到的情况下,就会在列表中创建一个新的root uclass。
[device.c]calloc(1, size); // 创建第一个udevice dm_root并初始化;
[uclass.c]uclass_bind_device(dev); // 将udevice dm_root与root uclass进行绑定,设备udevice dm_root连接到root uclass的uc->dev_head设备链表中。
[device.c]device_probe(gd->dm_root); // 探测设备udevice dm_root并激活它
/*从driver list中查找info的名字*/
/*创建udevice,绑定*/