• (DT系列六)devicetree中数据和 struct device有什么关系


    devicetree中数据和structdevice有什么关系

    总体来说,devicetree与structdevice的关系应该还是在其生成platformdevice的时候,一直传递的structdevice *parent参数。下面先把其源码中传递过程描述如下(仍以At91rm9200为例):

     

    1,

    DT_MACHINE_START(at91sam_dt,"Atmel AT91SAM (Device Tree)")

    /*Maintainer: Atmel */

    .timer =&at91sam926x_timer,

    .map_io =at91_map_io,

    .init_early =at91_dt_initialize,

    .init_irq =at91_dt_init_irq,

    .init_machine =at91_dt_device_init,

    .dt_compat =at91_dt_board_compat,

    MACHINE_END

     

    2,

    staticvoid __init at91_dt_device_init(void)

    {

    of_platform_populate(NULL,of_default_bus_match_table, NULL, NULL);

    }

     

    3,

    /**

    *of_platform_populate() - Populate platform_devices from device treedata

    *@root: parent of the first level to probe or NULL for the root of thetree

    *@matches: match table, NULL to use the default

    *@parent: parent to hook devicesfrom, NULL for toplevel

    *

    *Similar to of_platform_bus_probe(), this function walks the devicetree

    *and creates devices from nodes. It differs in that it follows themodern

    *convention of requiring all device nodes to have a 'compatible'property,

    *and it is suitable for creating devices which are children of theroot

    *node (of_platform_bus_probe will only create children of the rootwhich

    *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.

    */

    //从devicetree数据中populateplatform devices。

    intof_platform_populate(structdevice_node *root,

    conststruct of_device_id *matches,

    conststruct of_dev_auxdata *lookup,

    structdevice *parent)

    {

    structdevice_node *child;

    intrc = 0;

     

    root= root ? of_node_get(root) : of_find_node_by_path("/");

    if(!root)

    return-EINVAL;

     

    for_each_child_of_node(root,child) {

    //生成platformdevice

    rc= of_platform_bus_create(child,matches, lookup, parent,true);

    if(rc)

    break;

    }

     

    of_node_put(root);

    returnrc;

    }

     

    4,

    /**

    *of_platform_bus_create() - Create a device for a node and itschildren.

    *@bus: device node of the bus to instantiate

    *@matches: match table for bus nodes

    *@lookup: auxdata table for matching id and platform_data with devicenodes

    *@parent: parent for new device, or NULL for top level.

    *@strict: require compatible property

    *

    *Creates a platform_device for the provided device_node, andoptionally

    *recursively create devices for all the child nodes.

    */

    //为节点和其孩子节点生成一个设备文件。

    staticint of_platform_bus_create(structdevice_node *bus,

    const struct of_device_id *matches,

    const struct of_dev_auxdata *lookup,

    struct device *parent, boolstrict)

    {

    conststruct of_dev_auxdata *auxdata;

    structdevice_node *child;

    structplatform_device *dev;

    constchar *bus_id = NULL;

    void*platform_data = NULL;

    intrc = 0;

     

    /*Make sure it has a compatible property */

    if(strict && (!of_get_property(bus, "compatible",NULL))) {

    pr_debug("%s()- skipping %s, no compatible prop ",

    __func__, bus->full_name);

    return0;

    }

     

    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")) {

    of_amba_device_create(bus,bus_id, platform_data, parent);

    return0;

    }

     

    dev= of_platform_device_create_pdata(bus,bus_id, platform_data, parent);

    if(!dev || !of_match_node(matches, bus))

    return0;

     

    for_each_child_of_node(bus,child) {

    pr_debug(" create child: %s ", child->full_name);

    rc= of_platform_bus_create(child, matches, lookup, &dev->dev,strict);

    if(rc) {

    of_node_put(child);

    break;

    }

    }

    returnrc;

    }

    代码在这儿分了两步走:4.1和4.2。

     

    4.1

    staticstruct amba_device *of_amba_device_create(structdevice_node *node,

    const char *bus_id,

    void *platform_data,

    struct device *parent)

    {

    structamba_device *dev;

    constvoid *prop;

    inti, ret;

     

    pr_debug("Creatingamba device %s ", node->full_name);

     

    if(!of_device_is_available(node))

    returnNULL;

     

    dev= amba_device_alloc(NULL, 0, 0);

    if(!dev)

    returnNULL;

     

    /*setup generic device info */

    dev->dev.coherent_dma_mask= ~0;

    dev->dev.of_node= of_node_get(node);

    dev->dev.parent= parent;

    dev->dev.platform_data= platform_data;

    …...

    }

    4.2

    /**

    *of_platform_device_create_pdata - Alloc, initialize and register anof_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 parentdevice.

    *

    *Returns pointer to created platform device, or NULL if a device wasnot

    *registered. Unavailable devices will not get registered.

    */

    //分配内存,初始化和注册一个of_device

    structplatform_device *of_platform_device_create_pdata(

    structdevice_node *np,

    constchar *bus_id,

    void*platform_data,

    structdevice *parent)

    {

    structplatform_device *dev;

     

    if(!of_device_is_available(np))

    returnNULL;

     

    dev= of_device_alloc(np,bus_id, parent);

     

    …...

    returndev;

    }

     

    4.2.1

    /**

    *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 defaultname.

    *@parent: Parent device.

    */

    //分配内存和初始化of_device

    structplatform_device *of_device_alloc(structdevice_node *np,

    const char *bus_id,

    struct device *parent)

    {

    structplatform_device *dev;

    intrc, i, num_reg = 0, num_irq;

    structresource *res, temp_res;

     

    dev= platform_device_alloc("", -1);

    if(!dev)

    returnNULL;

     

    /*count the io and irq resources */

    if(of_can_translate_address(np))

    while(of_address_to_resource(np, num_reg, &temp_res) == 0)

    num_reg++;

    num_irq= of_irq_count(np);

     

    /*Populate the resource table */

    if(num_irq || num_reg) {

    res= kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);

    if(!res) {

    platform_device_put(dev);

    returnNULL;

    }

     

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

    WARN_ON(rc);

    }

    WARN_ON(of_irq_to_resource_table(np,res, num_irq) != num_irq);

    }

     

    dev->dev.of_node= of_node_get(np);

    #ifdefined(CONFIG_MICROBLAZE)

    dev->dev.dma_mask= &dev->archdata.dma_mask;

    #endif

    dev->dev.parent= parent;

     

    if(bus_id)

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

    else

    of_device_make_bus_id(&dev->dev);

     

    returndev;

    }

     

    总的分析:parent参数开始初始化为NULL,其中一直没有赋值,直到最后赋值给platformdevice的dev.parent属性。其中关系耐人寻味。

  • 相关阅读:
    解决在PDF文档中复制代码报错问题
    JAVA高级复习泛型
    SpringBoot高级监听原理
    SpringBoot整合其它框架整合Junit
    SpringBoot高级监控
    JAVA基础复习异常处理
    SpringBoot 整合 webservice 示例
    关于ScrollView的子View无法布满屏幕的问题
    Android开发中头疼的R文件问题
    博客园美化[SimpleMemory主题+tctip插件]
  • 原文地址:https://www.cnblogs.com/biglucky/p/4057499.html
Copyright © 2020-2023  润新知