前部分设备模型初始化

为了便于阅读,删掉部分代码,只留关键的过程:

static int initf_dm(void)
{
    int ret;
    ret = dm_init_and_scan(true);
    if (ret)
        return ret;
    return 0;
}

该函数调用了 dm_init_and_scan();并且传入的参数为true,uboot中对该函数的注释如下:

/**
 * dm_init_and_scan() - Initialise Driver Model structures and scan for devices
 *
 * This function initialises the roots of the driver tree and uclass trees,
 * then scans and binds available devices from platform data and the FDT.
 * This calls dm_init() to set up Driver Model structures.
 *
 * @pre_reloc_only: If true, bind only nodes with special devicetree properties,
 * or drivers with the DM_FLAG_PRE_RELOC flag. If false bind all drivers.
 * @return 0 if OK, -ve on error
 */

下面看具体的执行过程,删除参数检查等相关代码,如下图:

int dm_init_and_scan(bool pre_reloc_only)
{
   ret = dm_init(IS_ENABLED(CONFIG_OF_LIVE));
   ret = dm_scan_platdata(pre_reloc_only);
   ret = dm_extended_scan_fdt(gd->fdt_blob, pre_reloc_only);
   ret = dm_scan_other(pre_reloc_only);
}

该函数一共调用了四个函数,首先看第一个函数 dm_init(),该函数中涉及到关键的结构体struct global_data,该结构体的具体作用此处不做展开,只看结构体中和DM相关的部分

struct udevice    *dm_root;    /* Root instance for Driver Model */
    struct udevice    *dm_root_f;    /* Pre-relocation root instance */
    struct list_head uclass_root;    /* Head of core tree */

#define DM_ROOT_NON_CONST        (((gd_t *)gd)->dm_root)
    #define DM_UCLASS_ROOT_NON_CONST    (((gd_t *)gd)->uclass_root)

删除参数检查和返回值检查等代码,注释和实现过程如下:

/**
 * dm_init() - Initialise Driver Model structures
 * This function will initialize roots of driver tree and class tree.
 * This needs to be called before anything uses the DM
 * @of_live:    Enable live device tree
 * @return 0 if OK, -ve on error
 */
int dm_init(bool of_live)
{
    int ret;
    if (gd->dm_root) {
        dm_warn("Virtual root driver already exists!\n");
        return -EINVAL;
    }
    INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST);

ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);

#if CONFIG_IS_ENABLED(OF_CONTROL)
        DM_ROOT_NON_CONST->node = offset_to_ofnode(0);
#endif
    ret = device_probe(DM_ROOT_NON_CONST);
    return 0;
}

该函数又调用了device_bind_by_name()函数

/**
* device_bind_by_name: Create a device and bind it to a driver
*
* This is a helper function used to bind devices which do not use device
* tree.
*
* @parent: Pointer to device's parent
* @pre_reloc_only: If true, bind the driver only if its DM_FLAG_PRE_RELOC flag
* is set. If false bind the driver always.
* @info: Name and platdata for this device
* @devp: if non-NULL, returns a pointer to the bound device
* @return 0 if OK, -ve on error
*/
int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
           const struct driver_info *info, struct udevice **devp)
{
   struct driver *drv;
   uint platdata_size = 0;

drv = lists_driver_lookup_name(info->name);
   if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC))
       return -EPERM;

#if CONFIG_IS_ENABLED(OF_PLATDATA)
   platdata_size = info->platdata_size;
#endif
   return device_bind_common(parent, drv, info->name,
           (void *)info->platdata, 0, ofnode_null(), platdata_size,
           devp);
}

该函数最终调用了device_bind_common()函数

static int device_bind_common(struct udevice *parent, const struct driver *drv,
                  const char *name, void *platdata,
                  ulong driver_data, ofnode node,
                  uint of_platdata_size, struct udevice **devp)
{
    struct udevice *dev;
    struct uclass *uc;
    int size, ret = 0;

if (devp)
        *devp = NULL;
    if (!name)
        return -EINVAL;

ret = uclass_get(drv->id, &uc);
    if (ret) {
        debug("Missing uclass for driver %s\n", drv->name);
        return ret;
    }

dev = calloc(1, sizeof(struct udevice));
    if (!dev)
        return -ENOMEM;

INIT_LIST_HEAD(&dev->sibling_node);
    INIT_LIST_HEAD(&dev->child_head);
    INIT_LIST_HEAD(&dev->uclass_node);
#ifdef CONFIG_DEVRES
    INIT_LIST_HEAD(&dev->devres_head);
#endif
    dev->platdata = platdata;
    dev->driver_data = driver_data;
    dev->name = name;
    dev->node = node;
    dev->parent = parent;
    dev->driver = drv;
    dev->uclass = uc;

dev->seq = -1;
    dev->req_seq = -1;
    if (CONFIG_IS_ENABLED(DM_SEQ_ALIAS) &&
        (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS)) {
        /*
         * Some devices, such as a SPI bus, I2C bus and serial ports
         * are numbered using aliases.
         *
         * This is just a 'requested' sequence, and will be
         * resolved (and ->seq updated) when the device is probed.
         */
        if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
            if (uc->uc_drv->name && ofnode_valid(node))
                dev_read_alias_seq(dev, &dev->req_seq);
        } else {
            dev->req_seq = uclass_find_next_free_req_seq(drv->id);
        }
    }

if (drv->platdata_auto_alloc_size) {
        bool alloc = !platdata;

if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
            if (of_platdata_size) {
                dev->flags |= DM_FLAG_OF_PLATDATA;
                if (of_platdata_size <
                        drv->platdata_auto_alloc_size)
                    alloc = true;
            }
        }
        if (alloc) {
            dev->flags |= DM_FLAG_ALLOC_PDATA;
            dev->platdata = calloc(1,
                           drv->platdata_auto_alloc_size);
            if (!dev->platdata) {
                ret = -ENOMEM;
                goto fail_alloc1;
            }
            if (CONFIG_IS_ENABLED(OF_PLATDATA) && platdata) {
                memcpy(dev->platdata, platdata,
                       of_platdata_size);
            }
        }
    }

size = uc->uc_drv->per_device_platdata_auto_alloc_size;
    if (size) {
        dev->flags |= DM_FLAG_ALLOC_UCLASS_PDATA;
        dev->uclass_platdata = calloc(1, size);
        if (!dev->uclass_platdata) {
            ret = -ENOMEM;
            goto fail_alloc2;
        }
    }

if (parent) {
        size = parent->driver->per_child_platdata_auto_alloc_size;
        if (!size) {
            size = parent->uclass->uc_drv->
                    per_child_platdata_auto_alloc_size;
        }
        if (size) {
            dev->flags |= DM_FLAG_ALLOC_PARENT_PDATA;
            dev->parent_platdata = calloc(1, size);
            if (!dev->parent_platdata) {
                ret = -ENOMEM;
                goto fail_alloc3;
            }
        }
    }

/* put dev into parent's successor list */
    if (parent)
        list_add_tail(&dev->sibling_node, &parent->child_head);

ret = uclass_bind_device(dev);
    if (ret)
        goto fail_uclass_bind;

/* if we fail to bind we remove device from successors and free it */
    if (drv->bind) {
        ret = drv->bind(dev);
        if (ret)
            goto fail_bind;
    }
    if (parent && parent->driver->child_post_bind) {
        ret = parent->driver->child_post_bind(dev);
        if (ret)
            goto fail_child_post_bind;
    }
    if (uc->uc_drv->post_bind) {
        ret = uc->uc_drv->post_bind(dev);
        if (ret)
            goto fail_uclass_post_bind;
    }

if (parent)
        pr_debug("Bound device %s to %s\n", dev->name, parent->name);
    if (devp)
        *devp = dev;

dev->flags |= DM_FLAG_BOUND;

return 0;

fail_uclass_post_bind:
    /* There is no child unbind() method, so no clean-up required */
fail_child_post_bind:
    if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
        if (drv->unbind && drv->unbind(dev)) {
            dm_warn("unbind() method failed on dev '%s' on error path\n",
                dev->name);
        }
    }

fail_bind:
    if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
        if (uclass_unbind_device(dev)) {
            dm_warn("Failed to unbind dev '%s' on error path\n",
                dev->name);
        }
    }
fail_uclass_bind:
    if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
        list_del(&dev->sibling_node);
        if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
            free(dev->parent_platdata);
            dev->parent_platdata = NULL;
        }
    }
fail_alloc3:
    if (dev->flags & DM_FLAG_ALLOC_UCLASS_PDATA) {
        free(dev->uclass_platdata);
        dev->uclass_platdata = NULL;
    }
fail_alloc2:
    if (dev->flags & DM_FLAG_ALLOC_PDATA) {
        free(dev->platdata);
        dev->platdata = NULL;
    }
fail_alloc1:
    devres_release_all(dev);

free(dev);

return ret;
}

在dm_init()函数中,最后执行的是device_probe()函数

/**
 * device_probe() - Probe a device, activating it
 *
 * Activate a device so that it is ready for use. All its parents are probed
 * first.
 *
 * @dev: Pointer to device to probe
 * @return 0 if OK, -ve on error
 */
int device_probe(struct udevice *dev)
{
    struct power_domain pd;
    const struct driver *drv;
    int size = 0;
    int ret;
    int seq;

if (!dev)
        return -EINVAL;

if (dev->flags & DM_FLAG_ACTIVATED)
        return 0;

drv = dev->driver;
    assert(drv);

/* Allocate private data if requested and not reentered */
    if (drv->priv_auto_alloc_size && !dev->priv) {
        dev->priv = alloc_priv(drv->priv_auto_alloc_size, drv->flags);
        if (!dev->priv) {
            ret = -ENOMEM;
            goto fail;
        }
    }
    /* Allocate private data if requested and not reentered */
    size = dev->uclass->uc_drv->per_device_auto_alloc_size;
    if (size && !dev->uclass_priv) {
        dev->uclass_priv = alloc_priv(size,
                          dev->uclass->uc_drv->flags);
        if (!dev->uclass_priv) {
            ret = -ENOMEM;
            goto fail;
        }
    }

/* Ensure all parents are probed */
    if (dev->parent) {
        size = dev->parent->driver->per_child_auto_alloc_size;
        if (!size) {
            size = dev->parent->uclass->uc_drv->
                    per_child_auto_alloc_size;
        }
        if (size && !dev->parent_priv) {
            dev->parent_priv = alloc_priv(size, drv->flags);
            if (!dev->parent_priv) {
                ret = -ENOMEM;
                goto fail;
            }
        }

ret = device_probe(dev->parent);
        if (ret)
            goto fail;

/*
         * The device might have already been probed during
         * the call to device_probe() on its parent device
         * (e.g. PCI bridge devices). Test the flags again
         * so that we don't mess up the device.
         */
        if (dev->flags & DM_FLAG_ACTIVATED)
            return 0;
    }

seq = uclass_resolve_seq(dev);
    if (seq < 0) {
        ret = seq;
        goto fail;
    }
    dev->seq = seq;

dev->flags |= DM_FLAG_ACTIVATED;

/*
     * Process pinctrl for everything except the root device, and
     * continue regardless of the result of pinctrl. Don't process pinctrl
     * settings for pinctrl devices since the device may not yet be
     * probed.
     */
    if (dev->parent && device_get_uclass_id(dev) != UCLASS_PINCTRL)
        pinctrl_select_state(dev, "default");

if (dev->parent && device_get_uclass_id(dev) != UCLASS_POWER_DOMAIN) {
        if (!power_domain_get(dev, &pd))
            power_domain_on(&pd);
    }

ret = uclass_pre_probe_device(dev);
    if (ret)
        goto fail;

if (dev->parent && dev->parent->driver->child_pre_probe) {
        ret = dev->parent->driver->child_pre_probe(dev);
        if (ret)
            goto fail;
    }

if (drv->ofdata_to_platdata && dev_has_of_node(dev)) {
        ret = drv->ofdata_to_platdata(dev);
        if (ret)
            goto fail;
    }

/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
    ret = clk_set_defaults(dev);
    if (ret)
        goto fail;

if (drv->probe) {
        ret = drv->probe(dev);
        if (ret) {
            dev->flags &= ~DM_FLAG_ACTIVATED;
            goto fail;
        }
    }

ret = uclass_post_probe_device(dev);
    if (ret)
        goto fail_uclass;

if (dev->parent && device_get_uclass_id(dev) == UCLASS_PINCTRL)
        pinctrl_select_state(dev, "default");

return 0;
fail_uclass:
    if (device_remove(dev, DM_REMOVE_NORMAL)) {
        dm_warn("%s: Device '%s' failed to remove on error path\n",
            __func__, dev->name);
    }
fail:
    dev->flags &= ~DM_FLAG_ACTIVATED;

dev->seq = -1;
    device_free(dev);

return ret;
}
————————————————
版权声明:本文为CSDN博主「liuduanfei」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/A_orz_/article/details/100117065

【u-boot】u-boot中initf_dm()函数执行流程(转)的更多相关文章

  1. Django 中 admin 的执行流程

    Django 中 admin 的执行流程 1 循环加载执行所有已经注册的 app 中的 admin.py 文件 def autodiscover(): autodiscover_modules('ad ...

  2. shell中命令的执行流程

    在shell中,一个命令有3中写法: 1 可以直接写(Normal Command) 2 可以放在双引号中("Command") 3 可以放在单引号中('Comand') 这3中写 ...

  3. Springmvc中的HandlerAdaptor执行流程

    今天讲解一下在Springmvc中的HandlerAdaptor执行流程,明白这个过程,你就能画出下面的图: 接下来我们就来看看具体的实现过程吧. 1.0在DispatcherServlet中找到ge ...

  4. 深入理解java中HelloWorld的执行流程

    HelloWorld.java是我们学习java的第一个程序,简单的再也不能简单了,可是里面的原理以及执行流程大家都知道吗?最近在复习java知识,特地钻研了一番分享给大家! 贴出HelloWorld ...

  5. Linux中Shell的执行流程

    Shell执行流程 1.Printthe info of reminding 打印提示信息 2.Waitinguser for input(wait) 等待用户输入 3.Acceptthe comma ...

  6. TTCN中PTC的执行流程

    一些概念 Component(測试组件或者測试成分),TTCN接触下来最频繁的就是MTC(Main Test Component,主測试组件),在执行測试用例前,须要首先创建一个MTC.在testca ...

  7. Servlet中过滤器的执行流程

  8. lambda 函数执行流程 递归注意

  9. Shell中的函数

    一.在脚本中定义函数 与变量一样,在使用函数之前应该对函数进行定义.与其他编程类语言相比,由于没有数据类型的概念,因此也不必定义函数的类型. (1)在脚本中可以使用以下方式定义函数: function ...

随机推荐

  1. Pandas导入导出&pickle文件模块

    Pandas可以读取与存储的文件格式有很多 像csv,excel,json,html等,详细请看官方文档https://pandas.pydata.org/pandas-docs/stable/use ...

  2. libmkl 学习笔记

    libmkl 学习笔记 1.libkml下载地址为: https://github.com/libkml/libkml/releases 这里下载1.3.0版本 2.编译与安装 mkdir build ...

  3. 从ftp服务器进行批量下载,处理文件名保存时重名的问题,更改重名文件名方式为给后面加1、2、3等数字,保持后缀不变

    公司最近有一个从ftp批量下载文件的需求,但是文件名重复总会报错 没办法,自己下班后写了一个小算法 仿照桶排序的原理,实现了这个小功能,直接上代码: String[] test = {"ha ...

  4. mybatis-plus配置多数据源invalid bound statement (not found)

    mybatis-plus配置多数据源invalid bound statement (not found) 错误原因 引入mybatis-plus应该使用的依赖如下,而不是mybatis <de ...

  5. python基础知识0-5(单双向队列)

    #多项队列import collections #导入模块d = collections.deque() #deque方法d.append('1') #添加元素d.appendleft('2')d.a ...

  6. [Jenkins]初次访问Jenkins,输入密码后,页面卡在空白界面一直未加载出内容_解决方案

    问题描述 安装Jenkins,初次访问Jenkins(http://localhost:8002,端口号根据各自设置而不同,本例是8002),输入Jenkins初始化的管理密码之后,浏览器中一直卡在空 ...

  7. merge into使用方法

    此外,You cannot update a column that is referenced in the ON condition clause.,update的字段不可以是on里面的条件字段, ...

  8. Maven maven-compiler-plugin 编译问题

    问题:每次右键项目名-maven->update project 时候,项目jdk版本变了,变回1.5版本或者其他版本 解决方案一:修改maven的配置(解压目录的conf\setting.xm ...

  9. 关于登陆界面,页面没有刷新完毕,点击登陆跳转到一个接口的bug

    现象 输入完密码点击登陆就跳转到了如下的页面 分析原因: 第一:查看html页面   页面中的html  登陆用的是form表单  表单中还写了属性  action   即允许跳到某一个接口,这里是没 ...

  10. ES6入门四:对象字面量扩展与字符串模板字面量

    简洁属性与简洁方法 计算属性名与[[prototype]] super对象(暂时保留解析) 模板字面量(模板字符串) 一.简洁属性与简洁方法 ES6中为了不断优化代码,减低代码的耦合度在语法上下了很大 ...