ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

u-boot device_bind_common函数

2022-02-18 22:34:00  阅读:257  来源: 互联网

标签:bind boot uclass dev drv device plat uc


static int device_bind_common(struct udevice *parent, const struct driver *drv,
                  const char *name, void *plat,
                  ulong driver_data, ofnode node,
                  uint of_plat_size, struct udevice **devp)
{
    struct udevice *dev;
    struct uclass *uc;
    int size, ret = 0;
    bool auto_seq = true;
    void *ptr;

    if (CONFIG_IS_ENABLED(OF_PLATDATA_NO_BIND))
        return -ENOSYS;

    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_set_plat(dev, plat);
    dev->driver_data = driver_data;
    dev->name = name;
    dev_set_ofnode(dev, node);
    dev->parent = parent;
    dev->driver = drv;
    dev->uclass = uc;

    dev->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.
         */
        if (CONFIG_IS_ENABLED(OF_CONTROL) &&
            !CONFIG_IS_ENABLED(OF_PLATDATA)) {
            if (uc->uc_drv->name && ofnode_valid(node)) {
                if (!dev_read_alias_seq(dev, &dev->seq_)) {
                    auto_seq = false;
                    log_debug("   - seq=%d\n", dev->seq_);
                    }
            }
        }
    }
    if (auto_seq && !(uc->uc_drv->flags & DM_UC_FLAG_NO_AUTO_SEQ))
        dev->seq_ = uclass_find_next_free_seq(uc);

    /* Check if we need to allocate plat */
    if (drv->plat_auto) {
        bool alloc = !plat;

        /*
         * For of-platdata, we try use the existing data, but if
         * plat_auto is larger, we must allocate a new space
         */
        if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
            if (of_plat_size)
                dev_or_flags(dev, DM_FLAG_OF_PLATDATA);
            if (of_plat_size < drv->plat_auto)
                alloc = true;
        }
        if (alloc) {
            dev_or_flags(dev, DM_FLAG_ALLOC_PDATA);
            ptr = calloc(1, drv->plat_auto);
            if (!ptr) {
                ret = -ENOMEM;
                goto fail_alloc1;
            }

            /*
             * For of-platdata, copy the old plat into the new
             * space
             */
            if (CONFIG_IS_ENABLED(OF_PLATDATA) && plat)
                memcpy(ptr, plat, of_plat_size);
            dev_set_plat(dev, ptr);
        }
    }

    size = uc->uc_drv->per_device_plat_auto;
    if (size) {
        dev_or_flags(dev, DM_FLAG_ALLOC_UCLASS_PDATA);
        ptr = calloc(1, size);
        if (!ptr) {
            ret = -ENOMEM;
            goto fail_alloc2;
        }
        dev_set_uclass_plat(dev, ptr);
    }

    if (parent) {
        size = parent->driver->per_child_plat_auto;
        if (!size)
            size = parent->uclass->uc_drv->per_child_plat_auto;
        if (size) {
            dev_or_flags(dev, DM_FLAG_ALLOC_PARENT_PDATA);
            ptr = calloc(1, size);
            if (!ptr) {
                ret = -ENOMEM;
                goto fail_alloc3;
            }
            dev_set_parent_plat(dev, ptr);
        }
        /* put dev into parent's successor list */
        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_or_flags(dev, 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_get_flags(dev) & DM_FLAG_ALLOC_PARENT_PDATA) {
            free(dev_get_parent_plat(dev));
            dev_set_parent_plat(dev, NULL);
        }
    }
fail_alloc3:
    if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
        if (dev_get_flags(dev) & DM_FLAG_ALLOC_UCLASS_PDATA) {
            free(dev_get_uclass_plat(dev));
            dev_set_uclass_plat(dev, NULL);
        }
    }
fail_alloc2:
    if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
        if (dev_get_flags(dev) & DM_FLAG_ALLOC_PDATA) {
            free(dev_get_plat(dev));
            dev_set_plat(dev, NULL);
        }
    }
fail_alloc1:
    devres_release_all(dev);

    free(dev);

    return ret;
}

 

 

 

A:生成 udevice。

B:绑定 udevice 和 driver。

C:把设备挂到 uclass 的dev_head 链表下。

D:调用设备驱动的 bind 接口。

 

标签:bind,boot,uclass,dev,drv,device,plat,uc
来源: https://www.cnblogs.com/liujunhuasd/p/15887425.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有