u-boot 驱动模型分析

U-Boot驱动模型

1、 CONFIG_DM

typedef struct global_data {
...
#ifdef CONFIG_DM
	struct udevice	*dm_root;	/* Root instance for Driver Model */
	struct udevice	*dm_root_f;	/* Pre-relocation root instance */
	struct list_head uclass_root;	/* Head of core tree */
#endif
...
}

dm_root:DM模型的根设备
dm_root_f:重定向前的根设备
uclass_root:uclass链表的头

2 、uclass

struct uclass {
	void *priv;								//uclass的私有数据
	struct uclass_driver *uc_drv;			//uclass类的操作函数集合
	struct list_head dev_head;				//该uclass的所有设备
	struct list_head sibling_node;			//下一个uclass的节点
};

uclass:来管理该类型下的所有设备,并且有对应的uclass_driver驱动。
uclass是uboot自动生成的,并且不是所有uclass都会生成,
有对应uclass_driver并且有被udevice匹配到的uclass才会生成。
所有生成的uclass都会被挂载gd->uclass_root链表上。

3、uclass_driver

struct uclass_driver {
    const char *name; // 该uclass_driver的命令
    enum uclass_id id; // 对应的uclass id
/* 以下函数指针主要是调用时机的区别 */
    int (*post_bind)(struct udevice *dev); // 在udevice被绑定到该uclass之后调用
    int (*pre_unbind)(struct udevice *dev); // 在udevice被解绑出该uclass之前调用
    int (*pre_probe)(struct udevice *dev); // 在该uclass的一个udevice进行probe之前调用
    int (*post_probe)(struct udevice *dev); // 在该uclass的一个udevice进行probe之后调用
    int (*pre_remove)(struct udevice *dev);// 在该uclass的一个udevice进行remove之前调用
    int (*child_post_bind)(struct udevice *dev); // 在该uclass的一个udevice的一个子设备被绑定到该udevice之后调用
    int (*child_pre_probe)(struct udevice *dev); // 在该uclass的一个udevice的一个子设备进行probe之前调用
    int (*init)(struct uclass *class); // 安装该uclass的时候调用
    int (*destroy)(struct uclass *class); // 销毁该uclass的时候调用
    int priv_auto_alloc_size; // 需要为对应的uclass分配多少私有数据
    int per_device_auto_alloc_size; //
    int per_device_platdata_auto_alloc_size; //
    int per_child_auto_alloc_size; //
    int per_child_platdata_auto_alloc_size;  //
    const void *ops; //操作集合
    uint32_t flags;   // 标识为
};

uclass_driver主要通过UCLASS_DRIVER来定义
其定义之后都被存放在了段._u_boot_list_2_uclass_2_pinctrl

UCLASS_DRIVER(pinctrl) = {
	.id = UCLASS_PINCTRL,
	.post_bind = pinctrl_post_bind,
	.flags = DM_UC_FLAG_SEQ_ALIAS,
	.name = "pinctrl",
};

4、udevice

struct udevice {
	const struct driver *driver;		//device 对应的driver
	const char *name;					//device 的名称
	void *platdata;
	void *parent_platdata;
	void *uclass_platdata;
	ofnode node;						//设备树节点
	ulong driver_data;
	struct udevice *parent;				//父设备
	void *priv;							// 私有数据的指针
	struct uclass *uclass;				//驱动所属的uclass
	void *uclass_priv;
	void *parent_priv;
	struct list_head uclass_node;   //挂到uclass上
	struct list_head child_head;
	
};

udevice是最基础的一个设备单元
将udevice连接到对应的uclass中,uclass主要用来管理着同一类的驱动
udevice 由U_BOOT_DEVICE定义,存在段
.u_boot_list_2_driver_info_1

5、driver


struct driver {
	char *name;							//驱动名称
	enum uclass_id id;					//驱动所对应的uclass_id	
	const struct udevice_id *of_match;	//匹配函数
	int (*bind)(struct udevice *dev);	//绑定函数
	int (*probe)(struct udevice *dev);	//注册函数
	int (*remove)(struct udevice *dev);
	
	
};

driver对象,主要通过U_BOOT_DRIVER来定义

定义之后都被存放在了段.u_boot_list_2_driver_2_xxx
driver的头 :.u_boot_list_2_driver_1

6、总结

uclass:作为udevice的一个属性,主要用来管理某个驱动类的所有的设备。

uclass_driver:uclass的驱动程序,主要将uclass管理的设备和驱动实现绑定、注册,移除等操作。

udevice与driver的绑定:通过驱动的of_match和compatible属性来配对,绑定。

udevice与uclass的绑定:udevice内的driver下的uclass_id,

来与uclass对应的uclass_driver的uclass_id进行匹配。

uclass与uclass_driver的绑定:已知udevice内的driver下的uclass_id,创建uclass的同时,
通过uclass_id找到对应的uclass_driver对象,然后将uclass_driver绑定到uclass上!

例子 :

在u_boot_list_2_driver_2_xxx段查找"**root_driver**",并创建其uclass和udevice,二者进行绑定
#define DM_ROOT_NON_CONST		(((gd_t *)gd)->dm_root)
dm_init()
 ->drv = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);//root_info.name = "root_driver",
	-> drv = lists_driver_lookup_name(info->name);
	->return device_bind_common(parent, drv, info->name,
			(void *)info->platdata, 0, ofnode_null(), platdata_size,
			devp);//devp为DM_ROOT_NON_CONST
		struct uclass *uc;
		uclass_get(drv->id, &uc);
		dev = calloc(1, sizeof(struct udevice));
		dev->driver = drv;
		dev->uclass = uc;
		->uclass_bind_device(dev);
			uc = dev->uclass;
		 ->list_add_tail(&dev->uclass_node, &uc->dev_head);
		*devp = dev;//gd->dm_root = udevice(.name = "root_driver")

 ->device_probe(DM_ROOT_NON_CONST);//对root_driver进行probe,为空
	U_BOOT_DRIVER(root_driver) = {
	.name	= "root_driver",
	.id	= UCLASS_ROOT,
	};

;/从平台设备扫描udevice(U_BOOT_DEVICE定义)和uclass ,头为.u_boot_list_2_driver_info_1
dm_scan_platdata(pre_reloc_only);
//为空 
 .u_boot_list_2_driver_info_1
                0x00000000ff92d280        0x0 drivers/built-in.o
 .u_boot_list_2_driver_info_3


;/从设备树扫描udevice
dm_extended_scan_fdt(gd->fdt_blob, pre_reloc_only);
//parent 为gd->dm_root
 ->dm_scan_fdt_node(struct udevice *parent, const void *blob,)
	->lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp,
		struct driver *driver = ll_entry_start(struct driver, driver);
		//driver的头 :.u_boot_list_2_driver_1进入扫描U_BOOT_DRIVER定义的driver
		for (entry = driver; entry != driver + n_ents; entry++) {
		ret = driver_check_compatible(entry->of_match, &id,
						  compat);
		//将设备树中的"compatible"属性与driver的of_match属性进行匹配
		ret = device_bind_with_driver_data(parent, entry, name,
						   id->data, node, &dev); //绑定
			->device_bind_common(parent, drv, name, NULL, driver_data, node,  0, devp);
				 



你可能感兴趣的:(Linux,linux,驱动开发)