platform_device的生成过程
来源:互联网 发布:涤纶网络丝织带 编辑:程序博客网 时间:2024/04/26 05:28
kernel在引入dts前后,platform_device的生成方式是不同的。在引入设备树之前,platform_device变量是静态定义的。而引入设备树之后,kernel通过解析设备节点的信息生成platform_device。一、引入dts之前 add a platform-level deviceint platform_device_register(struct platform_device *pdev){ device_initialize(&pdev->dev); arch_setup_pdev_archdata(pdev); return platform_device_add(pdev);} add a platform device to device hierarchy This is part 2 of platform_device_register(), though may be called separately _iff_ pdev was allocated by platform_device_alloc().int platform_device_add(struct platform_device *pdev){ int i, ret; if (!pdev) return -EINVAL; if (!pdev->dev.parent) pdev->dev.parent = &platform_bus; pdev->dev.bus = &platform_bus_type; switch (pdev->id) { default: dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); break; case PLATFORM_DEVID_NONE: dev_set_name(&pdev->dev, "%s", pdev->name); break; case PLATFORM_DEVID_AUTO: /* * Automatically allocated device ID. We mark it as such so * that we remember it must be freed, and we append a suffix * to avoid namespace collision with explicit IDs. */ ret = ida_simple_get(&platform_devid_ida, 0, 0, GFP_KERNEL); if (ret < 0) goto err_out; pdev->id = ret; pdev->id_auto = true; dev_set_name(&pdev->dev, "%s.%d.auto", pdev->name, pdev->id); break; } for (i = 0; i < pdev->num_resources; i++) { struct resource *p, *r = &pdev->resource[i]; if (r->name == NULL) r->name = dev_name(&pdev->dev); p = r->parent; if (!p) { if (resource_type(r) == IORESOURCE_MEM) p = &iomem_resource; else if (resource_type(r) == IORESOURCE_IO) p = &ioport_resource; } if (p && insert_resource(p, r)) { dev_err(&pdev->dev, "failed to claim resource %d\n", i); ret = -EBUSY; goto failed; } } pr_debug("Registering platform device '%s'. Parent at %s\n", dev_name(&pdev->dev), dev_name(pdev->dev.parent)); ret = device_add(&pdev->dev); if (ret == 0) return ret; failed: if (pdev->id_auto) { ida_simple_remove(&platform_devid_ida, pdev->id); pdev->id = PLATFORM_DEVID_AUTO; } while (--i >= 0) { struct resource *r = &pdev->resource[i]; if (r->parent) release_resource(r); } err_out: return ret;}该函数最终会调用device_add添加设备二、引入设备树之后引入设备树之后,主要是通过解析设备树节点生成platform_device。kernel中有两个阶段会生成platform_device:第一阶段是在kernel初始化解析设备树时,kernel会为所有包含compatible属性名的第一级node创建platform_device。如果第一级node的compatible属性值为“simple-bus”、“simple-mfd”或者"arm,amba-bus",kernel会继续为当前node的包含compatible属性的节点创建platform_device。一般SOC直接子设备节点对应的platform_device会被生成,而间接子节点对应的platform_device不会生成。第二阶段是生成第一阶段中未满足match要求的间接子节点对应的platform_device。通常是在父节点设备驱动的probe函数中遍历子节点生成对应的platform_device。(1)第一阶段通过调用of_platform_populate解析设备树//Populate platform_devices from device tree dataint of_platform_populate(struct device_node *root, const struct of_device_id *matches, const struct of_dev_auxdata *lookup, struct device *parent){ 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) { rc = of_platform_bus_create(child, matches, lookup, parent, true); if (rc) { of_node_put(child); break; } } of_node_set_flag(root, OF_POPULATED_BUS); of_node_put(root); return rc;}kernel中有个of_platform_bus_probe函数,该函数和of_platform_populate有点类似,在新的board中最好使用of_platform_populate来代替of_platform_bus_probe函数。Create a device for a node and its children.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))) { 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; } dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent); 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;}Alloc, initialize and register an of_devicestatic 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) || of_node_test_and_set_flag(np, OF_POPULATED)) return NULL; dev = of_device_alloc(np, bus_id, parent); if (!dev) goto err_clear_flag; dev->dev.bus = &platform_bus_type; 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_platform_device_create_pdata函数真正完成了创建platform_device的工作。调用它的函数主要是做一些准备工作,如查找设备节点、检查兼容性等。int of_device_add(struct platform_device *ofdev){ BUG_ON(ofdev->dev.of_node == NULL); /* name and id have to be set so that the platform bus doesn't get * confused on matching */ ofdev->name = dev_name(&ofdev->dev); ofdev->id = -1; /* * If this device has not binding numa node in devicetree, that is * of_node_to_nid returns NUMA_NO_NODE. device_add will assume that this * device is on the same node as the parent. */ set_dev_node(&ofdev->dev, of_node_to_nid(ofdev->dev.of_node)); return device_add(&ofdev->dev);}(2)第二阶段在父设备节点的驱动probe函数中调用of_platform_device_create生成子设备节点对应的platforma_device。 struct platform_device *of_platform_device_create(struct device_node *np, const char *bus_id, struct device *parent){ return of_platform_device_create_pdata(np, bus_id, NULL, parent);}上述函数实际上调用of_platform_device_create_pdata完成生成platforma_device的工作的。
阅读全文
0 0
- platform_device的生成过程
- platform_device的注册过程分析
- Linux内核---17.platform_device的添加过程
- 3.x版本内核中platform_device的生成
- 3.x版本内核中platform_device的生成
- platform总线注册过程及platform_driver与platform_device的匹配
- platform总线注册过程及platform_driver与platform_device的匹配
- platform总线注册过程及platform_driver与platform_device的匹配
- platform总线注册过程及platform_driver与platform_device的匹配
- [0]uart platform_device 初始化过程
- spi的platform_device
- platform_device
- platform_device
- platform_device
- platform_device
- platform_device
- platform_device和platform_driver的注册过程,及probe函数何时调用的分析
- platform_device和platform_driver的注册过程,及probe函数何时调用的分析
- NestedScrollView嵌套RecyclerView滑动卡顿解决方案
- com.spotify:docker-maven-plugin 报localhost:2375 Connection refused 错误正确解决方法
- 如何避免成为一个油腻的中年猥琐男
- numpy中shape函数的一些用法
- CSS基础学习
- platform_device的生成过程
- 关于Spring Cloud的核心特性
- 三阶幻方
- c++学习记录17--虚函数和纯虚函数
- openstack手动修改虚拟机状态
- 大型网站是怎样解决多用户高并发访问
- 组合View
- SQL语言——alter table
- leetcode 78|90. Subsets 1|2