Device tree如何注册到sysfs

sys/firmware/devicetree/base目录下面为设备树展开成sysfs的目录和二进制属性文件,所有的node节点就是一个目录,所有的property属性就是一个二进制属性文件.

包含2个,一个是初始化、设备节点目录的创建,一个是节点属性二进制文件的创建在sysfs 中.


 相关结构体定义

struct device_node {//最终在内存中形成一个树形的设备信息
	const char *name; /* node的名称,取最后一次“/”和“@”之间子串 */
	const char *type; /*设备类型,来自节点中的device_type属性, 如果没有该属性, 则设为"NULL"*/
	phandle phandle;//u32 phandle
	const char *full_name; /* 指向该结构体结束的位置,存放node的路径全名*/
	struct fwnode_handle fwnode;

	struct	property *properties;/*指向该节点下的第一个属性,其他属性与该属性链表相接 */
	struct	property *deadprops;	/* removed properties */
	struct	device_node *parent;//parent node
	struct	device_node *child;//child
	struct	device_node *sibling;//same level node
	struct	kobject kobj;//kobj,和syfs关联接口
	unsigned long _flags;//node  flag,see flag descriptions@current file
	void	*data;
};
struct property {//node的 属性,读到内存中的属性
	char	*name;//key
	int	length;//value's length
	void	*value;//value, for key = value
	struct property *next;//下一个属性
	unsigned long _flags;
	unsigned int unique_id;
	struct bin_attribute attr;//for sys
};

 


np-->kobject 在哪里初始化的呢,在dtb-->device_node 解压中,

unflatten_dt_node---》of_node_init(np);//node sysfs init

struct kobj_type of_node_ktype = {

.release = of_node_release,

};

/* initialize a node */

extern struct kobj_type of_node_ktype;

static inline void of_node_init(struct device_node *node)

{

kobject_init(&node->kobj, &of_node_ktype);

node->fwnode.type = FWNODE_OF;

}

设备树节点目录创建和属性文件创建

start_kernel()→rest_init()→kernel_thread():kernel_init()→do_basic_setup()→driver_init()→of_core_init() 


void __init  of_core_init(void)
{
	struct device_node *np;

	/* Create the kset, and register existing nodes */
	mutex_lock(&of_mutex);
	of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);//sys/firmware/devicetree,创建目录
	if (!of_kset) {
		mutex_unlock(&of_mutex);
		pr_err("devicetree: failed to register existing nodes\n");
		return;
	}
	for_each_of_allnodes(np)
		__of_attach_node_sysfs(np);//创建节点目录和节点属性文件
	mutex_unlock(&of_mutex);

	/* Symlink in /proc as required by userspace ABI */
	if (of_root)
		proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base");
}


int __of_attach_node_sysfs(struct device_node *np)
{
	const char *name;
	struct property *pp;
	int rc;

	if (!IS_ENABLED(CONFIG_SYSFS))
		return 0;

	if (!of_kset)
		return 0;

	np->kobj.kset = of_kset;//kset 赋值
	if (!np->parent) {
		/* Nodes without parents are new top level trees */
		rc = kobject_add(&np->kobj, NULL, "%s",
				 safe_name(&of_kset->kobj, "base"));//没有父节点的情况,即叶子节点
	} else {
		name = safe_name(&np->parent->kobj, kbasename(np->full_name));
		if (!name || !name[0])
			return -EINVAL;

		rc = kobject_add(&np->kobj, &np->parent->kobj, "%s", name);//存在父节点情况
	}
	if (rc)
		return rc;

	for_each_property_of_node(np, pp)//遍历节点的属性,通过next指针
		__of_add_property_sysfs(np, pp);//属性添加到sysfs 中

	return 0;
}


int __of_add_property_sysfs(struct device_node *np, struct property *pp)---------------节点属性文件的创建
{
	int rc;

	/* Important: Don't leak passwords */
	bool secure = strncmp(pp->name, "security-", 9) == 0;

	if (!IS_ENABLED(CONFIG_SYSFS))
		return 0;

	if (!of_kset || !of_node_is_attached(np))
		return 0;

	sysfs_bin_attr_init(&pp->attr);//first step
	pp->attr.attr.name = safe_name(&np->kobj, pp->name);
	pp->attr.attr.mode = secure ? S_IRUSR : S_IRUGO;
	pp->attr.size = secure ? 0 : pp->length;
	pp->attr.read = of_node_property_read;---读节点属性函数接口

	rc = sysfs_create_bin_file(&np->kobj, &pp->attr);//second step
	WARN(rc, "error adding attribute %s to node %s\n", pp->name, np->full_name);
	return rc;
}

最后就创建成功了节点目录和节点属性文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值