;of_platform_default_populate-->;\n of_platform_populate-->;\n/**\n * of_platform_populate() - Populate platform_devices from device tree data\n * @root: parent of the first level to probe or NULL for the root of the tree\n * @matches: match table, NULL to use the default\n * @lookup: auxdata table for matching id and platform_data with device nodes\n * @parent: parent to hook devices from, NULL for toplevel\n *\n * Similar to of_platform_bus_probe(), this function walks the device tree\n * and creates devices from nodes. It differs in that it follows the modern\n * convention of requiring all device nodes to have a \'compatible\' property,\n * and it is suitable for creating devices which are children of the root\n * node (of_platform_bus_probe will only create children of the root which\n * are selected by the @matches argument).\n *\n * New board support should be using this function instead of\n * of_platform_bus_probe().\n *\n * Returns 0 on success, <; 0 on failure.\n */\nint of_platform_populate(struct device_node *root,\n const struct of_device_id *matches,\n const struct of_dev_auxdata *lookup,\n struct device *parent)\n{\n struct device_node *child;\n int rc = 0;\n\n root = root ? of_node_get(root) : of_find_node_by_path(\"/\"); >;>;>;>;>;>;>; 使用 of_find_node_by_path(\"/\") 查找设备树的根节点\n if (!root)\n return -EINVAL;\n\n pr_debug(\"%s()\\n\", __func__);\n pr_debug(\" starting at: %s\\n\", root->;full_name);\n\n for_each_child_of_node(root, child) { >;>;>;>;>; 宏遍历 root 的每一个子节点。每个子节点表示设备树中的一个设备节点\n rc = of_platform_bus_create(child, matches, lookup, parent, true);\n >;>;>;>;>;>;>; 对每一个子节点调用 of_platform_bus_create() 函数,将设备节点转换为 platform_device,并注册到平台总线 (platform_bus) 上\n if (rc) {\n of_node_put(child);\n break;\n }\n }\n of_node_set_flag(root, OF_POPULATED_BUS);\n //>;>;>;>;>;在所有子节点被处理后,of_platform_populate 会标记该设备节点为 OF_POPULATED_BUS。这表示这个总线已经被成功地填充了(即设备树的节点已经被转换并注册为设备)\n of_node_put(root);\n return rc;\n}\n\n```\n1. **驱动与设备的匹配**:\n###
注\n\n当然,也不是全部的节点都是挂在bus上的,比如下面三个节点:\n\n以memory节点为例子,这部分的处理可以参考setup_arch->;setup_machine_fd->;early_init_dt_scan_nodes->;of_scan_flat_dt->;early_init_dt_scan_memory\n\n```\nLinux-4.9.88\\Linux-4.9.88\\drivers\\of\\fdt.c:\n/**\n * early_init_dt_scan_memory - Look for an parse memory nodes\n */\nint __init early_init_dt_scan_memory(unsigned long node, const char *uname,\n int depth, void *data)\n//node: 当前扫描的设备节点的地址。\n//uname: 当前节点的名称。\n//depth: 当前节点的深度(树的层级)。\n//data: 额外的数据(这里未使用)\n{\n const char *type = of_get_flat_dt_prop(node, \"device_type\", NULL); ——————获取当前节点的 device_type 属性,以确定该节点是否是内存节点\n const __be32 *reg, *endp;\n int l;\n \n /* We are scanning \"memory\" nodes only */\n if (type == NULL) {\n /*\n * The longtrail doesn\'t have a device_type on the\n * /memory node, so look for the node called /memory@0.\n */\n if (!IS_ENABLED(CONFIG_PPC32) || depth != 1 || strcmp(uname, \"memory@0\") != 0)\n return 0;\n } else if (strcmp(type, \"memory\") != 0)\n return 0;\n\n reg = of_get_flat_dt_prop(node, \"linux,usable-memory\", &l); ——————函数获取节点的内存属性\n if (reg == NULL)\n reg = of_get_flat_dt_prop(node, \"reg\", &l);\n if (reg == NULL)\n return 0;\n\n endp = reg + (l / sizeof(__be32));\n\n pr_debug(\"memory scan node %s, reg size %d,\\n\", uname, l);\n\n while ((endp - reg) >;= (dt_root_addr_cells + dt_root_size_cells)) { ————————遍历内存节点\n u64 base, size;\n\n base = dt_mem_next_cell(dt_root_addr_cells, ®);————————内存的起始地址\n size = dt_mem_next_cell(dt_root_size_cells, ®);————————大小\n\n if (size == 0)\n continue;\n pr_debug(\" - %llx , %llx\\n\", (unsigned long long)base,\n (unsigned long long)size);\n\n early_init_dt_add_memory_arch(base, size); ——————将内存信息添加到系统架构中\n }\n\n return 0;\n}\n函数通过解析设备树中的 memory 节点,提取出内存的基地址和大小\n然后调用 early_init_dt_add_memory_arch 函数将这些内存区域添加到内核的内存管理系统中。\n\n```\n\n##
2. drivers/base/platform.c和drivers/of/platform.c\n\ndrivers/base/platform.c:这个文件处理 平台设备(platform devices) 和 平台驱动(platform drivers) 的通用实现,与设备树无关。\n\n```\nplatform_device_register(): 注册一个平台设备。 \nplatform_driver_register(): 注册一个平台驱动程序。\nplatform_match(): 匹配平台设备与驱动。\n\n```\n\n平台设备模型允许开发者通过 `struct platform_device` 和 `struct platform_driver` 定义设备和驱动程序,分别对应于硬件设备和管理设备的驱动程序。`drivers/base/platform.c` 适用于 **不依赖于设备树** 的系统,或者那些通过直接编程静态平台设备的系统。典型的例子包括不使用设备树的嵌入式系统或者通过代码硬编码设备和资源的平台设备。\n\n---\n\n\ndrivers/of/platform.c:这个文件处理的是基于 设备树(Device Tree, DT) 的平台设备及驱动的实现,与设备树相关联。\n\n```\nof_platform_bus_probe(): 解析设备树,扫描指定总线的子节点,注册这些设备到总线上。\nof_platform_device_create(): 根据设备树的节点创建一个平台设备。\nof_platform_populate(): 扫描设备树的根节点,将所有与某个总线相关的设备节点创建为 platform_device,并注册到总线上。\n\n```\n\n设备树通常包含嵌入式系统中设备的详细描述,包括硬件资源和属性。`drivers/of/platform.c` 的任务就是将这些描述从设备树转换成内核中的 `platform_device`,这样驱动程序就可以通过 `platform_driver` 来匹配和管理它们。`drivers/of/platform.c` 适用于 **基于设备树** 的系统,特别是现代的 ARM 平台和其他依赖设备树来描述硬件布局的系统。在这些系统中,硬件的详细信息通常由设备树提供,而不是通过静态代码硬编码在内核中。\n\n---\n\n\n对于drivers/base/platform.c中的platform_device_register(),其实用的不多,更多的是用form_driver_register()来注册一个驱动,至于platfrom_device其实更多的是交由drivers/of/platform.c中的of_platform_populate去创建,毕竟现在对于硬件资源的指定更多依赖于设备树,很少自己去.c文件去指定然后手动注册。\n -->