dtb如何转换到platform_device

news2024/11/19 19:37:53

分2步,第一步是首先转换为device_node,第二步device_node转换为platform_device。


第一步 

/**
 * unflatten_device_tree - create tree of device_nodes from flat blob
 *
 * unflattens the device-tree passed by the firmware, creating the
 * tree of struct device_node. It also fills the "name" and "type"
 * pointers of the nodes so the normal device-tree walking functions
 * can be used.
 */
void __init  unflatten_device_tree(void)//dtb-->内存设备树结构
{
	__unflatten_device_tree(initial_boot_params, &of_root,
				early_init_dt_alloc_memory_arch);

	/* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */
	of_alias_scan(early_init_dt_alloc_memory_arch);
}

执行后,of_root 是设备树的根 。

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
};


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
	unsigned long _flags;//node  flag,see flag descriptions@current file
	void	*data;
};

第二步:

设备树的device_node到platform_device转换中,必须满足以下条件:

  • 一般情况下,只对设备树中根的一级子节点进行转换,也就是多级子节点(子节点的子节点)并不处理。但是存在一种特殊情况,就是当某个根子节点的compatible属性为"simple-bus"、"simple-mfd"、"isa"、"arm,amba-bus"时,当前节点中的一级子节点将会被转换成platform_device节点。
  • 节点中必须有compatible属性。

 arch_initcall_sync(arm64_device_init);---以常见的arm64平台

static int __init arm64_device_init(void)
{
	of_iommu_init();
	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);//device_node--->platform
	return 0;
}
/**
 * of_platform_populate() - Populate platform_devices from device tree data
 * @root: parent of the first level to probe or NULL for the root of the tree
 * @matches: match table, NULL to use the default
 * @lookup: auxdata table for matching id and platform_data with device nodes
 * @parent: parent to hook devices from, NULL for toplevel
 *
 * Similar to of_platform_bus_probe(), this function walks the device tree
 * and creates devices from nodes.  It differs in that it follows the modern
 * convention of requiring all device nodes to have a 'compatible' property,
 * and it is suitable for creating devices which are children of the root
 * node (of_platform_bus_probe will only create children of the root which
 * are selected by the @matches argument).
 *
 * New board support should be using this function instead of
 * of_platform_bus_probe().
 *
 * Returns 0 on success, < 0 on failure.
 */
int of_platform_populate(struct device_node *root,
			const struct of_device_id *matches,
			const struct of_dev_auxdata *lookup,
			struct device *parent)//populate platform_devices from device tree data
{
	struct device_node *child;
	int rc = 0;

	root = root ? of_node_get(root) : of_find_node_by_path("/");
	if (!root)
		return -EINVAL;

	for_each_child_of_node(root, child) {/* 为根节点下面的每一个节点创建platform_device结构体 */
		rc = of_platform_bus_create(child, matches, lookup, parent, true);
		if (rc)
			break;
	}
	of_node_set_flag(root, OF_POPULATED_BUS);//set 已填充 flag

	of_node_put(root);
	return rc;
}
**
 * of_platform_bus_create() - Create a device for a node and its children.
 * @bus: device node of the bus to instantiate
 * @matches: match table for bus nodes
 * @lookup: auxdata table for matching id and platform_data with device nodes
 * @parent: parent for new device, or NULL for top level.
 * @strict: require compatible property
 *
 * Creates a platform_device for the provided device_node, and optionally
 * recursively create devices for all the child nodes.
 */
static int of_platform_bus_create(struct device_node *bus,
				  const struct of_device_id *matches,
				  const struct of_dev_auxdata *lookup,
				  struct device *parent, bool strict)
{
	const struct of_dev_auxdata *auxdata;
	struct device_node *child;
	struct platform_device *dev;
	const char *bus_id = NULL;
	void *platform_data = NULL;
	int rc = 0;

	/* Make sure it has a compatible property */
	if (strict && (!of_get_property(bus, "compatible", NULL))) {/* 只有包含"compatible"属性的node节点才会生成相应的platform_device结构体 */
		pr_debug("%s() - skipping %s, no compatible prop\n",
			 __func__, bus->full_name);
		return 0;
	}

	auxdata = of_dev_lookup(lookup, bus);
	if (auxdata) {
		bus_id = auxdata->name;
		platform_data = auxdata->platform_data;
	}

	if (of_device_is_compatible(bus, "arm,primecell")) {
		/*
		 * Don't return an error here to keep compatibility with older
		 * device tree files.
		 */
		of_amba_device_create(bus, bus_id, platform_data, parent);
		return 0;
	}
	
	/* 针对节点下面得到status = "ok" 或者status = "okay"或者不存在status属性的节点分配内存并填充platform_device结构体 */
	dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent);//platform_data一般是null
	if (!dev || !of_match_node(matches, bus))
		return 0;

	for_each_child_of_node(bus, child) {
		pr_debug("   create child: %s\n", child->full_name);
		rc = of_platform_bus_create(child, matches, lookup, &dev->dev, strict);//父节点下的子设备节点创建
		if (rc) {
			of_node_put(child);
			break;
		}
	}
	of_node_set_flag(bus, OF_POPULATED_BUS);
	return rc;
}


const struct of_device_id of_default_bus_match_table[] = {
    { .compatible = "simple-bus", },
    { .compatible = "simple-mfd", },
#ifdef CONFIG_ARM_AMBA
    { .compatible = "arm,amba-bus", },
#endif /* CONFIG_ARM_AMBA */
    {} /* Empty terminated list */
}; 

对于dts中定义的device node,只有其所属的parent node所属的compatible属性和调用of_platform_populate时传入的of_device_id(红色)相互匹配,则说明如果当前的device node只要包含有compatible属性就会被创建为platform device,其他不会帮你自动创建,需要自己写代码创建

/**
 * of_platform_device_create_pdata - Alloc, initialize and register an of_device
 * @np: pointer to node to create device for
 * @bus_id: name to assign device
 * @platform_data: pointer to populate platform_data pointer with
 * @parent: Linux device model parent device.
 *
 * Returns pointer to created platform device, or NULL if a device was not
 * registered.  Unavailable devices will not get registered.
 */
static struct platform_device *of_platform_device_create_pdata(
					struct device_node *np,
					const char *bus_id,
					void *platform_data,
					struct device *parent)
{
	struct platform_device *dev;

	if (!of_device_is_available(np) ||  //status ok,okay,或者没写
	    of_node_test_and_set_flag(np, OF_POPULATED))
		return NULL;

	dev = of_device_alloc(np, bus_id, parent);// Allocate and initialize an of platform_device
	if (!dev)
		goto err_clear_flag;

	dev->dev.bus = &platform_bus_type;//关键,platform device所在总线是platform bus
	dev->dev.platform_data = platform_data;
	of_dma_configure(&dev->dev, dev->dev.of_node);
	of_msi_configure(&dev->dev, dev->dev.of_node);

	if (of_device_add(dev) != 0) {
		of_dma_deconfigure(&dev->dev);
		platform_device_put(dev);
		goto err_clear_flag;
	}

	return dev;

err_clear_flag:
	of_node_clear_flag(np, OF_POPULATED);
	return NULL;
}
/**
 * of_device_alloc - Allocate and initialize an of_device
 * @np: device node to assign to device
 * @bus_id: Name to assign to the device.  May be null to use default name.
 * @parent: Parent device.
 */
struct platform_device *of_device_alloc(struct device_node *np,
				  const char *bus_id,
				  struct device *parent)
{
	struct platform_device *dev;
	int rc, i, num_reg = 0, num_irq;
	struct resource *res, temp_res;

	dev = platform_device_alloc("", -1);
	if (!dev)
		return NULL;

	/* count the io and irq resources */
	while (of_address_to_resource(np, num_reg, &temp_res) == 0)//统计reg属性的数量
		num_reg++;
	num_irq = of_irq_count(np);//统计中断irq属性的数量

	/* Populate the resource table */
	if (num_irq || num_reg) {
		res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);//根据num_irq和num_reg的数量申请相应的struct resource内存空间
		if (!res) {
			platform_device_put(dev);
			return NULL;
		}

		dev->num_resources = num_reg + num_irq;
		dev->resource = res;
		for (i = 0; i < num_reg; i++, res++) {
			rc = of_address_to_resource(np, i, res);//dts reg-->res.start,end,name(reg-name),flags
			WARN_ON(rc);
		}
		if (of_irq_to_resource_table(np, res, num_irq) != num_irq)
			pr_debug("not all legacy IRQ resources mapped for %s\n",
				 np->name);
	}

	dev->dev.of_node = of_node_get(np);//关联设备树节点和设备之间的指针,以后就可以platform来找到node节点和它的属性信息
	dev->dev.parent = parent ? : &platform_bus;

	if (bus_id)
		dev_set_name(&dev->dev, "%s", bus_id);
	else
		of_device_make_bus_id(&dev->dev);

	return dev;
}

 

/**
 * platform_device_alloc - create a platform device
 * @name: base name of the device we're adding
 * @id: instance id
 *
 * Create a platform device object which can have other objects attached
 * to it, and which will have attached objects freed when it is released.
 */
struct platform_device *platform_device_alloc(const char *name, int id)
{
	struct platform_object *pa;

	pa = kzalloc(sizeof(*pa) + strlen(name) + 1, GFP_KERNEL);//this,1 is \0
	if (pa) {
		strcpy(pa->name, name);
		pa->pdev.name = pa->name;
		pa->pdev.id = id;
		device_initialize(&pa->pdev.dev);//设备初始化
		pa->pdev.dev.release = platform_device_release;
		arch_setup_pdev_archdata(&pa->pdev);
	}

	return pa ? &pa->pdev : NULL;
}

 

struct  platform_device {
	const char	*name;
	int		id;
	bool		id_auto;
	struct device	dev;//dev.of_node代表dts节点
	u32		num_resources;//reg + irq
	struct resource	*resource;//设备资源资源,中断,reg

	const struct platform_device_id	*id_entry;
	char *driver_override; /* Driver name to force a match */

	/* MFD cell pointer */
	struct mfd_cell *mfd_cell;

	/* arch specific additions */
	struct pdev_archdata	archdata;
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/82075.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mysql常用索引

1.普通索引 navicat中为NORMAL 语句为 ADD INDEX //采用普通索引的方式可以大大提高数据库的工作效率 2.唯一索引 navicat中为NORMAL 语句为 ADD UNIQUE INDEX //采用唯一索引的方式可以大大提高数据库的工作效率、并且数据无重复 3.主键索引 navicat中为主键 语句为 AD…

ALSA系统简析

一 音频架构 如图所示 是 嵌入式系统的音频连接 音频编解码器将数字音频信号 转换成 扬声器播放所需要的模拟声音信号。而通过麦克风时&#xff0c;则执行相反的过程。 数字音频信号通过 PCM技术对模拟信号以某个比特率采样得到的&#xff0c;编解码器的任务就是以支持的PCM…

非零基础自学计算机操作系统 第1章 操作系统概述 1.4 操作系统的分类 1.4.1 多道批处理操作系统 1.4.2 分时操作系统

非零基础自学计算机操作系统 文章目录非零基础自学计算机操作系统第1章 操作系统概述1.4 操作系统的分类1.4.1 多道批处理操作系统1.4.2 分时操作系统第1章 操作系统概述 1.4 操作系统的分类 按照操作系统的功能可将其分为以下几类&#xff1a;多道批处理操作系统、分时操作系…

力扣(LeetCode)143. 重排链表(C++)

模拟 五步做完 : ①遍历链表&#xff0c;得到链表长度 ②找到中间结点 ③反转链表后半段的结点指向 ④重排链表 ⑤尾结点的指向置空 初始链表 L0→L1→…→Ln−1→LnL0 → L1 → … → Ln - 1 → LnL0→L1→…→Ln−1→Ln 重排链表 L0→Ln→L1→Ln−1→L2→Ln−2→…L0 → Ln…

MongoDB数据库 —— 图形化工具

在前面通过使用MongoDB在命令窗口操作数据库&#xff0c;而MySQL数据库也同样可以在命令窗口使用sql语句操作数据库&#xff0c;在安装数据库的时候提到可以安装这个图形化工具的&#xff0c;为了节省安装时间和卡顿选择后续安装MongoDB图形化工具&#xff0c;在MySQL数据中同样…

[附源码]JAVA毕业设计疫情防控期间人员档案追演示录像上(系统+LW)

[附源码]JAVA毕业设计疫情防控期间人员档案追演示录像上&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#x…

Spring Cloud Zuul网关的介绍及使用

Zuul 是 Netflix OSS 中的一员&#xff0c;是一个基于 JVM 路由和服务端的负载均衡器。提供路由、监控、弹性、安全等方面的服务框架。Zuul 能够与 Eureka、Ribbon、Hystrix 等组件配合使用。 Zuul 的核心是过滤器&#xff0c;通过这些过滤器我们可以扩展出很多功能&#xff0…

猿如意中的【Linux命令查询】工具详情介绍

一、工具名称 Linux命令查询 二、下载安装渠道 Linux命令查询通过CSDN官方开发的【猿如意】客户端进行下载安装。 2.1 什么是猿如意&#xff1f; 猿如意是一款面向开发者的辅助开发工具箱&#xff0c;包含了效率工具、开发工具下载&#xff0c;教程文档&#xff0c;代码片段…

R语言动态可视化:制作历史全球平均温度的累积动态折线图动画gif视频图

在某些情况下&#xff0c;你可能希望通过在每帧中添加数据并保留先前添加的数据来进行动画处理。最近我们被客户要求撰写关于动态可视化的研究报告&#xff0c;包括一些图形和统计输出。 现在&#xff0c;我们将通过制作点线图的动画来探索。 以下是制作图表静态版本的代码&a…

如何打造一个高效可用的组织知识库

作者 | 唐三 在管理改进活动中&#xff0c;衡量一个企业管理改进成功与否的一个重要指标就是组织知识库的构建和使用。 组织知识库是一个学习型组织在项目操作过程中所积累的无形资产&#xff0c;同时组织过程资产的累积程度是衡量一个项目组织管理体系成熟度的重要指标&#…

阿里云ECS安装VirtualBox

文章目录virtualbox repovirtualbox repo适配阿里云的OS修改virtualbox repo成功下载安装报错安装 libvpxvirtualbox repo [virtualbox] nameOracle Linux / RHEL / CentOS-$releasever / $basearch - VirtualBox baseurlhttp://download.virtualbox.org/virtualbox/rpm/rhel/…

C#开发——Winform中ToolTip闪烁的解决方案

1、背景 首先要知道在何种情况下需要用tooltip控件&#xff0c;使用场景应该是&#xff1a;鼠标移入某个控件区域&#xff0c;显示tooltip的提示&#xff1b;移出后隐藏该提示。 采用的比较多的方式是&#xff0c;对该控件的MouseMove和MouseLeave事件进行处理。 至于为什么不是…

【产品人卫朋】华为销售体系 | 销售管理:LTC流程体系详解

LTC 是华为的三大主流程之一&#xff0c;从线索发现开始&#xff0c;直至收回现金&#xff0c;从而实现端到端地拉通。 三大主流程分别是&#xff1a; 其他流程可以参考之前文章&#xff1a; 华为IPD流程 华为ITR流程 继续今天的内容&#xff0c;在不同的流程环节卷入不同的…

[1.2.0新功能系列:一] Apache Doris 1.2.0 版本 Light Schema Change

在 1.2.0 新版本中&#xff0c;对数据表的加减列操作&#xff0c;不再需要同步更改数据文件&#xff0c;仅需在 FE 中更新元数据即可&#xff0c;从而实现毫秒级的 Schema Change 操作&#xff0c;且存在导入任务时效率的提升更为显著。与此同时&#xff0c;使得 Apache Doris …

干货 | Dubbo 接口测试原理及多种方法实践总结

1、什么是 Dubbo&#xff1f; Dubbo 最开始是应用于淘宝网&#xff0c;由阿里巴巴开源的一款优秀的高性能服务框架&#xff0c;由 Java 开发&#xff0c;后来贡献给了 Apache 开源基金会组织。 下面以官网的一个说明来了解一下架构的演变过程&#xff0c;从而了解 Dubbo 的诞…

【RNN:并行场景和纹理学习】

Infrared and visible image fusion via parallel scene and texture learning &#xff08;基于并行场景和纹理学习的红外与可见光图像融合&#xff09; 本文提出了一种基于并行场景和纹理学习的红外和可见光图像融合方法。我们的主要目标是部署深度神经网络的两个分支&…

登临科技加入飞桨硬件生态共创计划,共推AI应用规模化落地

近日&#xff0c;上海登临科技有限公司与飞桨签署硬件生态共创计划合作协议&#xff0c;正式加入由飞桨发起的硬件生态共创计划。当前双方的合作主要基于登临科技自主创新的通用GPU系列产品——Goldwasser&#xff08;高凛&#xff09;。 上海登临科技有限公司 高性能、通用…

松耦合式的权限控制设计,自定义权限表达式yyds!

背景 企业应用系统逐渐增多后&#xff0c;各系统单独管理各自的用户数据容易形成信息孤岛&#xff0c;分散的用户管理模式阻碍了企业应用向平台化演进&#xff0c;为降低企业系统设计开发、集成成本&#xff0c;打通技术闭环完善系统设计实现流程、优化提升系统设计实现的整体…

电子元器件行业如何做好库存管理优化?试试数商云B2B电商系统!

我们知道&#xff0c;企业的库存管理对企业各个部门的成本核算业务有着直接的影响&#xff0c;因此&#xff0c;优化企业库存管理对于企业的整体发展十分重要。对于电子元器件行业来说&#xff0c;许多中小规模的电子元器件分销商&#xff0c;由于早期缺乏管理经验&#xff0c;…

活体深度方向模型

🍿*★,*:.☆欢迎您/$:*.★* 🍿 不断的利用 输入 不断的对比新的输入 查询暂时的记忆模块 查询后交互方法 之后得到新的输入 查询不到变使用 模型进行预测 交互 这样方能实现自我更新 自我 记忆 自我维护 不断个更新 设计