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,綁定*/