u-boot uclass_add函数

/**
 * uclass_add() - Create new uclass in list
 * @id: Id number to create
 * @ucp: Returns pointer to uclass, or NULL on error
 * @return 0 on success, -ve on error
 *
 * The new uclass is added to the list. There must be only one uclass for
 * each id.
 */
static int uclass_add(enum uclass_id id, struct uclass **ucp)
{
    struct uclass_driver *uc_drv;
    struct uclass *uc;
    int ret;

    *ucp = NULL;
//查找驱动程序是否存在 uc_drv
= lists_uclass_lookup(id); if (!uc_drv) { debug("Cannot find uclass for id %d: please add the UCLASS_DRIVER() declaration for this UCLASS_... id\n", id); /* * Use a strange error to make this case easier to find. When * a uclass is not available it can prevent driver model from * starting up and this failure is otherwise hard to debug. */ return -EPFNOSUPPORT; }
//分配空间给uclass
/**
 * struct uclass - a U-Boot drive class, collecting together similar drivers
 *
 * A uclass provides an interface to a particular function, which is
 * implemented by one or more drivers. Every driver belongs to a uclass even
 * if it is the only driver in that uclass. An example uclass is GPIO, which
 * provides the ability to change read inputs, set and clear outputs, etc.
 * There may be drivers for on-chip SoC GPIO banks, I2C GPIO expanders and
 * PMIC IO lines, all made available in a unified way through the uclass.
 *
 * @priv_: Private data for this uclass (do not access outside driver model)
 * @uc_drv: The driver for the uclass itself, not to be confused with a
 * 'struct driver'
 * @dev_head: List of devices in this uclass (devices are attached to their
 * uclass when their bind method is called)
 * @sibling_node: Next uclass in the linked list of uclasses
 */
struct uclass {
    void *priv_;
    struct uclass_driver *uc_drv;
    struct list_head dev_head;
    struct list_head sibling_node;
};


    uc = calloc(1, sizeof(*uc));
    if (!uc)
        return -ENOMEM;
//驱动程序的私有数据是否存在,添加priv_.
if (uc_drv->priv_auto) { void *ptr; ptr = calloc(1, uc_drv->priv_auto); if (!ptr) { ret = -ENOMEM; goto fail_mem; } uclass_set_priv(uc, ptr); }
//设置uclass的驱动程序 uc
->uc_drv = uc_drv;
//建立uclass链表 INIT_LIST_HEAD(
&uc->sibling_node); INIT_LIST_HEAD(&uc->dev_head); list_add(&uc->sibling_node, DM_UCLASS_ROOT_NON_CONST); //调用uclass driver驱动程序的初始化,函数的输入参数为uclass指针 if (uc_drv->init) { ret = uc_drv->init(uc); if (ret) goto fail; } //返回分配的uclass *ucp = uc; return 0;
//失败处理 fail:
if (uc_drv->priv_auto) { free(uclass_get_priv(uc)); uclass_set_priv(uc, NULL); } list_del(&uc->sibling_node); fail_mem: free(uc); return ret; }
/**
 * struct uclass_driver - Driver for the uclass
 *
 * A uclass_driver provides a consistent interface to a set of related
 * drivers.
 *
 * @name: Name of uclass driver
 * @id: ID number of this uclass
 * @post_bind: Called after a new device is bound to this uclass
 * @pre_unbind: Called before a device is unbound from this uclass
 * @pre_probe: Called before a new device is probed
 * @post_probe: Called after a new device is probed
 * @pre_remove: Called before a device is removed
 * @child_post_bind: Called after a child is bound to a device in this uclass
 * @child_pre_probe: Called before a child in this uclass is probed
 * @child_post_probe: Called after a child in this uclass is probed
 * @init: Called to set up the uclass
 * @destroy: Called to destroy the uclass
 * @priv_auto: If non-zero this is the size of the private data
 * to be allocated in the uclass's ->priv pointer. If zero, then the uclass
 * driver is responsible for allocating any data required.
 * @per_device_auto: Each device can hold private data owned
 * by the uclass. If required this will be automatically allocated if this
 * value is non-zero.
 * @per_device_plat_auto: Each device can hold platform data
 * owned by the uclass as 'dev->uclass_plat'. If the value is non-zero,
 * then this will be automatically allocated.
 * @per_child_auto: Each child device (of a parent in this
 * uclass) can hold parent data for the device/uclass. This value is only
 * used as a fallback if this member is 0 in the driver.
 * @per_child_plat_auto: A bus likes to store information about
 * its children. If non-zero this is the size of this data, to be allocated
 * in the child device's parent_plat pointer. This value is only used as
 * a fallback if this member is 0 in the driver.
 * @flags: Flags for this uclass (DM_UC_...)
 */
struct uclass_driver {
    const char *name;
    enum uclass_id id;
    int (*post_bind)(struct udevice *dev);
    int (*pre_unbind)(struct udevice *dev);
    int (*pre_probe)(struct udevice *dev);
    int (*post_probe)(struct udevice *dev);
    int (*pre_remove)(struct udevice *dev);
    int (*child_post_bind)(struct udevice *dev);
    int (*child_pre_probe)(struct udevice *dev);
    int (*child_post_probe)(struct udevice *dev);
    int (*init)(struct uclass *class);
    int (*destroy)(struct uclass *class);
    int priv_auto;
    int per_device_auto;
    int per_device_plat_auto;
    int per_child_auto;
    int per_child_plat_auto;
    uint32_t flags;
};

 

posted @ 2022-02-19 12:32  liujunhuasd  阅读(91)  评论(0编辑  收藏  举报