dm: core: Access device ofnode through functions
[platform/kernel/u-boot.git] / drivers / core / device.c
index 4b3dcb3..6a9bee0 100644 (file)
 DECLARE_GLOBAL_DATA_PTR;
 
 static int device_bind_common(struct udevice *parent, const struct driver *drv,
-                             const char *name, void *platdata,
+                             const char *name, void *plat,
                              ulong driver_data, ofnode node,
-                             uint of_platdata_size, struct udevice **devp)
+                             uint of_plat_size, struct udevice **devp)
 {
        struct udevice *dev;
        struct uclass *uc;
        int size, ret = 0;
+       bool auto_seq = true;
+       void *ptr;
 
        if (devp)
                *devp = NULL;
@@ -63,88 +65,79 @@ static int device_bind_common(struct udevice *parent, const struct driver *drv,
 #ifdef CONFIG_DEVRES
        INIT_LIST_HEAD(&dev->devres_head);
 #endif
-       dev->platdata = platdata;
+       dev_set_plat(dev, plat);
        dev->driver_data = driver_data;
        dev->name = name;
-       dev->node = node;
+       dev_set_ofnode(dev, node);
        dev->parent = parent;
        dev->driver = drv;
        dev->uclass = uc;
 
-       dev->seq = -1;
-       dev->req_seq = -1;
+       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.
-                *
-                * 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);
-#if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
-                       if (dev->req_seq == -1)
-                               dev->req_seq =
-                                       uclass_find_next_free_req_seq(drv->id);
-#endif
-               } else {
-                       dev->req_seq = uclass_find_next_free_req_seq(drv->id);
+                       if (uc->uc_drv->name && ofnode_valid(node)) {
+                               if (!dev_read_alias_seq(dev, &dev->seq_))
+                                       auto_seq = false;
+                       }
                }
        }
+       if (auto_seq && !(uc->uc_drv->flags & DM_UC_FLAG_NO_AUTO_SEQ))
+               dev->seq_ = uclass_find_next_free_seq(uc);
 
-       if (drv->platdata_auto_alloc_size) {
-               bool alloc = !platdata;
+       if (drv->plat_auto) {
+               bool alloc = !plat;
 
                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)
+                       if (of_plat_size) {
+                               dev_or_flags(dev, DM_FLAG_OF_PLATDATA);
+                               if (of_plat_size < drv->plat_auto)
                                        alloc = true;
                        }
                }
                if (alloc) {
-                       dev->flags |= DM_FLAG_ALLOC_PDATA;
-                       dev->platdata = calloc(1,
-                                              drv->platdata_auto_alloc_size);
-                       if (!dev->platdata) {
+                       dev_or_flags(dev, DM_FLAG_ALLOC_PDATA);
+                       ptr = calloc(1, drv->plat_auto);
+                       if (!ptr) {
                                ret = -ENOMEM;
                                goto fail_alloc1;
                        }
-                       if (CONFIG_IS_ENABLED(OF_PLATDATA) && platdata) {
-                               memcpy(dev->platdata, platdata,
-                                      of_platdata_size);
-                       }
+                       if (CONFIG_IS_ENABLED(OF_PLATDATA) && plat)
+                               memcpy(ptr, plat, of_plat_size);
+                       dev_set_plat(dev, ptr);
                }
        }
 
-       size = uc->uc_drv->per_device_platdata_auto_alloc_size;
+       size = uc->uc_drv->per_device_plat_auto;
        if (size) {
-               dev->flags |= DM_FLAG_ALLOC_UCLASS_PDATA;
-               dev->uclass_platdata = calloc(1, size);
-               if (!dev->uclass_platdata) {
+               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_platdata_auto_alloc_size;
+               size = parent->driver->per_child_plat_auto;
                if (!size) {
-                       size = parent->uclass->uc_drv->
-                                       per_child_platdata_auto_alloc_size;
+                       size = parent->uclass->uc_drv->per_child_plat_auto;
                }
                if (size) {
-                       dev->flags |= DM_FLAG_ALLOC_PARENT_PDATA;
-                       dev->parent_platdata = calloc(1, size);
-                       if (!dev->parent_platdata) {
+                       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);
@@ -176,7 +169,7 @@ static int device_bind_common(struct udevice *parent, const struct driver *drv,
        if (devp)
                *devp = dev;
 
-       dev->flags |= DM_FLAG_BOUND;
+       dev_or_flags(dev, DM_FLAG_BOUND);
 
        return 0;
 
@@ -200,20 +193,20 @@ fail_bind:
 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;
+               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 (dev->flags & DM_FLAG_ALLOC_UCLASS_PDATA) {
-               free(dev->uclass_platdata);
-               dev->uclass_platdata = NULL;
+       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 (dev->flags & DM_FLAG_ALLOC_PDATA) {
-               free(dev->platdata);
-               dev->platdata = NULL;
+       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);
@@ -233,18 +226,10 @@ int device_bind_with_driver_data(struct udevice *parent,
 }
 
 int device_bind(struct udevice *parent, const struct driver *drv,
-               const char *name, void *platdata, int of_offset,
+               const char *name, void *plat, ofnode node,
                struct udevice **devp)
 {
-       return device_bind_common(parent, drv, name, platdata, 0,
-                                 offset_to_ofnode(of_offset), 0, devp);
-}
-
-int device_bind_ofnode(struct udevice *parent, const struct driver *drv,
-                      const char *name, void *platdata, ofnode node,
-                      struct udevice **devp)
-{
-       return device_bind_common(parent, drv, name, platdata, 0, node, 0,
+       return device_bind_common(parent, drv, name, plat, 0, node, 0,
                                  devp);
 }
 
@@ -252,7 +237,7 @@ 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;
+       uint plat_size = 0;
        int ret;
 
        drv = lists_driver_lookup_name(info->name);
@@ -262,11 +247,10 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
                return -EPERM;
 
 #if CONFIG_IS_ENABLED(OF_PLATDATA)
-       platdata_size = info->platdata_size;
+       plat_size = info->plat_size;
 #endif
-       ret = device_bind_common(parent, drv, info->name,
-                                (void *)info->platdata, 0, ofnode_null(),
-                                platdata_size, devp);
+       ret = device_bind_common(parent, drv, info->name, (void *)info->plat, 0,
+                                ofnode_null(), plat_size, devp);
        if (ret)
                return ret;
 
@@ -339,21 +323,68 @@ static void *alloc_priv(int size, uint flags)
        return priv;
 }
 
-int device_ofdata_to_platdata(struct udevice *dev)
+/**
+ * device_alloc_priv() - Allocate priv/plat data required by the device
+ *
+ * @dev: Device to process
+ * @return 0 if OK, -ENOMEM if out of memory
+ */
+static int device_alloc_priv(struct udevice *dev)
+{
+       const struct driver *drv;
+       void *ptr;
+       int size;
+
+       drv = dev->driver;
+       assert(drv);
+
+       /* Allocate private data if requested and not reentered */
+       if (drv->priv_auto && !dev_get_priv(dev)) {
+               ptr = alloc_priv(drv->priv_auto, drv->flags);
+               if (!ptr)
+                       return -ENOMEM;
+               dev_set_priv(dev, ptr);
+       }
+
+       /* Allocate private data if requested and not reentered */
+       size = dev->uclass->uc_drv->per_device_auto;
+       if (size && !dev_get_uclass_priv(dev)) {
+               ptr = alloc_priv(size, dev->uclass->uc_drv->flags);
+               if (!ptr)
+                       return -ENOMEM;
+               dev_set_uclass_priv(dev, ptr);
+       }
+
+       /* Allocate parent data for this child */
+       if (dev->parent) {
+               size = dev->parent->driver->per_child_auto;
+               if (!size)
+                       size = dev->parent->uclass->uc_drv->per_child_auto;
+               if (size && !dev_get_parent_priv(dev)) {
+                       ptr = alloc_priv(size, drv->flags);
+                       if (!ptr)
+                               return -ENOMEM;
+                       dev_set_parent_priv(dev, ptr);
+               }
+       }
+
+       return 0;
+}
+
+int device_of_to_plat(struct udevice *dev)
 {
        const struct driver *drv;
-       int size = 0;
        int ret;
 
        if (!dev)
                return -EINVAL;
 
-       if (dev->flags & DM_FLAG_PLATDATA_VALID)
+       if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID)
                return 0;
 
        /* Ensure all parents have ofdata */
        if (dev->parent) {
-               ret = device_ofdata_to_platdata(dev->parent);
+               ret = device_of_to_plat(dev->parent);
                if (ret)
                        goto fail;
 
@@ -363,56 +394,25 @@ int device_ofdata_to_platdata(struct udevice *dev)
                 * (e.g. PCI bridge devices). Test the flags again
                 * so that we don't mess up the device.
                 */
-               if (dev->flags & DM_FLAG_PLATDATA_VALID)
+               if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID)
                        return 0;
        }
 
+       ret = device_alloc_priv(dev);
+       if (ret)
+               goto fail;
+
        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;
-               }
-       }
-
-       /* Allocate parent data for this child */
-       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;
-                       }
-               }
-       }
-
-       if (drv->ofdata_to_platdata &&
-           (CONFIG_IS_ENABLED(OF_PLATDATA) || dev_has_of_node(dev))) {
-               ret = drv->ofdata_to_platdata(dev);
+       if (drv->of_to_plat &&
+           (CONFIG_IS_ENABLED(OF_PLATDATA) || dev_has_ofnode(dev))) {
+               ret = drv->of_to_plat(dev);
                if (ret)
                        goto fail;
        }
 
-       dev->flags |= DM_FLAG_PLATDATA_VALID;
+       dev_or_flags(dev, DM_FLAG_PLATDATA_VALID);
 
        return 0;
 fail:
@@ -425,18 +425,17 @@ int device_probe(struct udevice *dev)
 {
        const struct driver *drv;
        int ret;
-       int seq;
 
        if (!dev)
                return -EINVAL;
 
-       if (dev->flags & DM_FLAG_ACTIVATED)
+       if (dev_get_flags(dev) & DM_FLAG_ACTIVATED)
                return 0;
 
        drv = dev->driver;
        assert(drv);
 
-       ret = device_ofdata_to_platdata(dev);
+       ret = device_of_to_plat(dev);
        if (ret)
                goto fail;
 
@@ -452,18 +451,11 @@ int device_probe(struct udevice *dev)
                 * (e.g. PCI bridge devices). Test the flags again
                 * so that we don't mess up the device.
                 */
-               if (dev->flags & DM_FLAG_ACTIVATED)
+               if (dev_get_flags(dev) & 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;
+       dev_or_flags(dev, DM_FLAG_ACTIVATED);
 
        /*
         * Process pinctrl for everything except the root device, and
@@ -493,7 +485,7 @@ int device_probe(struct udevice *dev)
        }
 
        /* Only handle devices that have a valid ofnode */
-       if (dev_of_valid(dev)) {
+       if (dev_has_ofnode(dev)) {
                /*
                 * Process 'assigned-{clocks/clock-parents/clock-rates}'
                 * properties
@@ -523,42 +515,41 @@ fail_uclass:
                        __func__, dev->name);
        }
 fail:
-       dev->flags &= ~DM_FLAG_ACTIVATED;
+       dev_bic_flags(dev, DM_FLAG_ACTIVATED);
 
-       dev->seq = -1;
        device_free(dev);
 
        return ret;
 }
 
-void *dev_get_platdata(const struct udevice *dev)
+void *dev_get_plat(const struct udevice *dev)
 {
        if (!dev) {
                dm_warn("%s: null device\n", __func__);
                return NULL;
        }
 
-       return dev->platdata;
+       return dev->plat_;
 }
 
-void *dev_get_parent_platdata(const struct udevice *dev)
+void *dev_get_parent_plat(const struct udevice *dev)
 {
        if (!dev) {
                dm_warn("%s: null device\n", __func__);
                return NULL;
        }
 
-       return dev->parent_platdata;
+       return dev->parent_plat_;
 }
 
-void *dev_get_uclass_platdata(const struct udevice *dev)
+void *dev_get_uclass_plat(const struct udevice *dev)
 {
        if (!dev) {
                dm_warn("%s: null device\n", __func__);
                return NULL;
        }
 
-       return dev->uclass_platdata;
+       return dev->uclass_plat_;
 }
 
 void *dev_get_priv(const struct udevice *dev)
@@ -568,7 +559,7 @@ void *dev_get_priv(const struct udevice *dev)
                return NULL;
        }
 
-       return dev->priv;
+       return dev->priv_;
 }
 
 void *dev_get_uclass_priv(const struct udevice *dev)
@@ -578,7 +569,7 @@ void *dev_get_uclass_priv(const struct udevice *dev)
                return NULL;
        }
 
-       return dev->uclass_priv;
+       return dev->uclass_priv_;
 }
 
 void *dev_get_parent_priv(const struct udevice *dev)
@@ -588,7 +579,7 @@ void *dev_get_parent_priv(const struct udevice *dev)
                return NULL;
        }
 
-       return dev->parent_priv;
+       return dev->parent_priv_;
 }
 
 static int device_get_device_tail(struct udevice *dev, int ret,
@@ -659,18 +650,15 @@ int device_get_child_count(const struct udevice *parent)
        return count;
 }
 
-int device_find_child_by_seq(const struct udevice *parent, int seq_or_req_seq,
-                            bool find_req_seq, struct udevice **devp)
+int device_find_child_by_seq(const struct udevice *parent, int seq,
+                            struct udevice **devp)
 {
        struct udevice *dev;
 
        *devp = NULL;
-       if (seq_or_req_seq == -1)
-               return -ENODEV;
 
        list_for_each_entry(dev, &parent->child_head, sibling_node) {
-               if ((find_req_seq ? dev->req_seq : dev->seq) ==
-                               seq_or_req_seq) {
+               if (dev->seq_ == seq) {
                        *devp = dev;
                        return 0;
                }
@@ -686,14 +674,8 @@ int device_get_child_by_seq(const struct udevice *parent, int seq,
        int ret;
 
        *devp = NULL;
-       ret = device_find_child_by_seq(parent, seq, false, &dev);
-       if (ret == -ENODEV) {
-               /*
-                * We didn't find it in probed devices. See if there is one
-                * that will request this seq if probed.
-                */
-               ret = device_find_child_by_seq(parent, seq, true, &dev);
-       }
+       ret = device_find_child_by_seq(parent, seq, &dev);
+
        return device_get_device_tail(dev, ret, devp);
 }
 
@@ -895,7 +877,7 @@ int device_first_child_ofdata_err(struct udevice *parent, struct udevice **devp)
        if (!dev)
                return -ENODEV;
 
-       ret = device_ofdata_to_platdata(dev);
+       ret = device_of_to_plat(dev);
        if (ret)
                return ret;
 
@@ -913,7 +895,7 @@ int device_next_child_ofdata_err(struct udevice **devp)
        if (!dev)
                return -ENODEV;
 
-       ret = device_ofdata_to_platdata(dev);
+       ret = device_of_to_plat(dev);
        if (ret)
                return ret;
 
@@ -983,7 +965,7 @@ bool device_is_last_sibling(const struct udevice *dev)
 
 void device_set_name_alloced(struct udevice *dev)
 {
-       dev->flags |= DM_FLAG_NAME_ALLOCED;
+       dev_or_flags(dev, DM_FLAG_NAME_ALLOCED);
 }
 
 int device_set_name(struct udevice *dev, const char *name)
@@ -997,6 +979,36 @@ int device_set_name(struct udevice *dev, const char *name)
        return 0;
 }
 
+void dev_set_priv(struct udevice *dev, void *priv)
+{
+       dev->priv_ = priv;
+}
+
+void dev_set_parent_priv(struct udevice *dev, void *parent_priv)
+{
+       dev->parent_priv_ = parent_priv;
+}
+
+void dev_set_uclass_priv(struct udevice *dev, void *uclass_priv)
+{
+       dev->uclass_priv_ = uclass_priv;
+}
+
+void dev_set_plat(struct udevice *dev, void *plat)
+{
+       dev->plat_ = plat;
+}
+
+void dev_set_parent_plat(struct udevice *dev, void *parent_plat)
+{
+       dev->parent_plat_ = parent_plat;
+}
+
+void dev_set_uclass_plat(struct udevice *dev, void *uclass_plat)
+{
+       dev->uclass_plat_ = uclass_plat;
+}
+
 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
 bool device_is_compatible(const struct udevice *dev, const char *compat)
 {