dtb如何转换到platform_device

article/2025/10/25 1:08: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;//keyint	length;//value's lengthvoid	*value;//value, for key = valuestruct 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 phandleconst char *full_name; /* 指向该结构体结束的位置,存放node的路径全名*/struct fwnode_handle fwnode;struct	property *properties;/*指向该节点下的第一个属性,其他属性与该属性链表相接 */struct	property *deadprops;	/* removed properties */struct	device_node *parent;//parent nodestruct	device_node *child;//childstruct	device_node *sibling;//same level nodestruct	kobject kobj;//kobjunsigned long _flags;//node  flag,see flag descriptions@current filevoid	*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--->platformreturn 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 已填充 flagof_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一般是nullif (!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_deviceif (!dev)goto err_clear_flag;dev->dev.bus = &platform_bus_type;//关键,platform device所在总线是platform busdev->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),flagsWARN_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);elseof_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 \0if (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 + irqstruct resource	*resource;//设备资源资源,中断,regconst 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://chatgpt.dhexx.cn/article/89kByBqM.shtml

相关文章

U-Boot 之一 零基础编译 U-Boot 过程详解、Image 镜像介绍及使用说明、DTB 文件使用说明

最近&#xff0c;工作重心要从裸机开发转移到嵌入式 Linux 系统开发&#xff0c;在之前的博文 Linux 之八 完整嵌入式 Linux 环境、&#xff08;交叉&#xff09;编译工具链、CPU 体系架构、嵌入式系统构建工具 中详细介绍了嵌入式 Linux 环境&#xff0c;接下来就是实际动手学…

dts、dtb的那些事儿

笔者最近在支持新的案子&#xff0c;过于忙碌&#xff0c;好久没更新了&#xff0c;勿怪。 1、设备树大变革故事 2011年3月17日的ARM Linux邮件列表有封邮件“this whole ARM thing is a fucking pain in the ass”引起了轩然大波&#xff0c;原来是我们的Linux之父Linus Torv…

DBT工具简介

What is DBT 在将数据加载到集中式数据仓库之前&#xff0c;必须对其进行清理、保持一致并根据需要进行组合。换句话说&#xff0c;必须转换数据&#xff0c;这就是我们所谓的 ETL&#xff08;提取、转换、加载&#xff09;和 ELT 中的“T”。 这是挖掘数据价值的关键一步。 而…

4.2uboot对设备树的支持——dtb的修改原理

本节说明在uboot中修改dtb的原理。 在uboot中&#xff0c;有一些命令支持对dtb文件进行修改。 当我们想要修改dtb文件时&#xff0c;可以直接修改dts文件&#xff0c;然后编译dts文件生成新的dtb文件&#xff0c;再将新的dtb文件载入设备。 或者&#xff0c;我们也可以在ubo…

DBT是什么

关于DBT DBT 是一种数据转换工作流&#xff0c;可帮助您完成更多工作&#xff0c;同时产生更高质量的结果。您可以使用 dbt 来模块化和集中分析代码&#xff0c;同时还为数据团队提供软件工程工作流中常见的护栏。在将数据模型安全部署到生产环境之前&#xff0c;通过监控和可见…

2.1设备树的规范(dts和dtb)——DTS格式

本节学习设备树的规范。 使用设备树时&#xff0c;需要编写dts文件&#xff0c;然后使用dtc编译dts文件&#xff0c;生成dtb文件。 所以本节分为两部分&#xff0c;第一部分讲解dts格式&#xff0c;第二部分讲解dtb格式。 首先看一下dts文件的布局。 DTS文件布局&#xff0…

关于EMUELC适配各种机型,DTB如何修改教程

很多爱好者留言&#xff0c;都想问关于EMUELC的dtb适配机型问题&#xff0c;这里我就出一个教程&#xff0c;如何修改dtb&#xff0c;然后去适配自己的机型&#xff0c;然后启动 。这里我只是提供方法&#xff0c;具体的调试是需要原理图进行配置。 首先&#xff0c;不管是aml…

DTBO简介

1、DTBO简介 设备树 (DT) 是用于描述“不可发现”硬件的命名节点和属性构成的一种数据结构。操作系统&#xff08;例如在 Android 中使用的 Linux 内核&#xff09;会使用 DT 来支持 Android 设备使用的各种硬件配置。硬件供应商会提供自己的 DT 源文件&#xff0c;接下来…

【DTB/DTBO 分区介绍】

如果你的 DTB/DTBO 位于专属的分区&#xff08;例如 dtb 和 dtbo 分区&#xff09;中&#xff0c;请使用以下表格结构和头文件格式&#xff1a; 数据结构 dt_table_header 仅适用于 dtb/dtbo 分区&#xff1b;您不能在kernel( image.gz) 末尾处附加此格式。如果您有一个 DTB/D…

2.2设备树的规范(dts和dtb)——DTB格式

本节讲述设备树的dtb格式。 上节讲述了dts格式。回顾上节&#xff0c;在dts文件和dtsi文件中&#xff0c;可以使用C语言的define和include&#xff0c;使用方法和作用也同C语言相同。 编写dts文件后&#xff0c;需要使用dtc工具将dts文件编译成dtb文件。dtc工具可以检查dts文…

「设备树」dtb给内核的两种工作模式

一&#xff0c;传递dtb给内核 对于传统bootloader提供两种工作模式&#xff1a;一是启动加载模式&#xff08;start loading&#xff09;&#xff0c;一是下载模式&#xff08;downloading&#xff09; 工作在启动加载模式时&#xff0c;bootloader会自动执行bootcmd命令&#…

设备树_dtb文件分析

前言&#xff1a;我之前的原计划是没有打算写设备树dtb文件分析&#xff0c;但是情势所迫啊&#xff01;&#xff0c;学习还是要一步一步来的。 在前面的章节提到过.dts文件以文本方式对系统设备树进行描述&#xff0c;经过Device Tree Compiler(dtc)将dts文件转换成二进制文件…

Linux设备树学习2 - DTB文件格式

一. DTB文件简介 DTB文件是由DTS文件通过dtc命令编译生成的二进制文件。DTS文件不能直接被内核解析&#xff0c;需要编译成DTB文件才可以直接被内核识别并解析使用的。 二. DTB文件内容布局 从上图可以看出&#xff0c;DTB由四个部分组成&#xff0c;分别是struct fdt_header&a…

setUserVisibleHint-- fragment真正的onResume和onPause方法

这个情况仅适合与多个fragment之间切换时统计&#xff0c;而非activity和fragment同时交互&#xff0c;因当时项目为首页4个fargment时长统计&#xff0c;因此适合&#xff0c;经下面网友评论指出&#xff0c;特在这里写出此问题&#xff0c;因最近项目较忙&#xff0c;具体情况…

onCreate与onStart区别,onStart与onResume区别

http://www.cnblogs.com/kofi1122/archive/2011/04/10/2011772.html Activity生命周期之我见 关于Activity生命周期的文章很多&#xff0c;而且大部分也说得很详细&#xff0c;所以作为关于这方面的内容我本来不想多说&#xff0c;但是大家可能跟我之前一样&#xff0c;在看这方…

Flutter BaseWidget 实现onResume、onPause()

熟读唐诗三百首&#xff0c;不会作诗也会吟。——孙洙 最近用Flutter开发的项目算是完成了开发到上线第一阶段了。任何一个项目开始了&#xff0c;若想追求的是更好&#xff0c;那么就需要下功夫对项目用户体验和代码效率深入的研究了。作为用户和产品经理、老板、UI、不懂技术…

Activity生命周期中onStart()和onResume()的区别

Activity生命周期中onStart()和onResume()的区别 在讲onStart()和onResume()的区别之前&#xff0c;必须清楚Activity的四种状态&#xff1a; 1.Running状态&#xff1a;一个新的Activity的启动入栈后&#xff0c;它在屏幕最前端&#xff0c;处于栈的最顶端&#xff0c;此时它…

android Activity的onPause()与onResume()

官方文档地址&#xff1a;http://www.android-doc.com/training/basics/activity-lifecycle/pausing.html#Resume Pause和Resume一个Activity 在一般的app使用中&#xff0c;前台的activity一般是会被视觉组件所遮住的&#xff0c;这就会导致activity的pause。举个例子&#x…

android中onResume、onPause等方法

程序正常启动&#xff1a;onCreate()->onStart()->onResume(); 正常退出&#xff1a;onPause()->onStop()->onDestory() 程序按back 退出&#xff1a; onPause()->onStop()->onDestory(),再进入&#xff1a;onCreate()->onStart()->onResume(); 程序按…

OnStart()方法和OnResume()方法的区别

文章目录 一、Activity的生命周期简述在讲onStart()和onResume()的区别之前&#xff0c;必须清楚Activity的四种状态&#xff1a; 二、OnStart()和OnResume()方法的区别区别&#xff1a; 总结 一、Activity的生命周期简述 在讲onStart()和onResume()的区别之前&#xff0c;必须…