dm: core: Access device ofnode through functions
[platform/kernel/u-boot.git] / drivers / core / device.c
index ce66c72..6a9bee0 100644 (file)
@@ -9,11 +9,14 @@
  */
 
 #include <common.h>
+#include <cpu_func.h>
+#include <log.h>
 #include <asm/io.h>
 #include <clk.h>
 #include <fdtdec.h>
 #include <fdt_support.h>
 #include <malloc.h>
+#include <asm/cache.h>
 #include <dm/device.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
 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;
@@ -60,88 +65,83 @@ 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);
-               } else {
-                       dev->req_seq = uclass_find_next_free_req_seq(drv->id);
+               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;
+                       }
                }
        }
+       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 */
-       if (parent)
+               /* put dev into parent's successor list */
                list_add_tail(&dev->sibling_node, &parent->child_head);
+       }
 
        ret = uclass_bind_device(dev);
        if (ret)
@@ -169,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;
 
@@ -193,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);
@@ -226,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);
 }
 
@@ -245,7 +237,8 @@ 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);
        if (!drv)
@@ -254,11 +247,36 @@ 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
-       return 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;
+
+       return ret;
+}
+
+int device_reparent(struct udevice *dev, struct udevice *new_parent)
+{
+       struct udevice *pos, *n;
+
+       assert(dev);
+       assert(new_parent);
+
+       list_for_each_entry_safe(pos, n, &dev->parent->child_head,
+                                sibling_node) {
+               if (pos->driver != dev->driver)
+                       continue;
+
+               list_del(&dev->sibling_node);
+               list_add_tail(&dev->sibling_node, &new_parent->child_head);
+               dev->parent = new_parent;
+
+               break;
+       }
+
+       return 0;
 }
 
 static void *alloc_priv(int size, uint flags)
@@ -305,57 +323,124 @@ static void *alloc_priv(int size, uint flags)
        return priv;
 }
 
-int device_probe(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)
 {
-       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)
+       if (dev_get_flags(dev) & DM_FLAG_PLATDATA_VALID)
                return 0;
 
+       /* Ensure all parents have ofdata */
+       if (dev->parent) {
+               ret = device_of_to_plat(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_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;
+       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_or_flags(dev, DM_FLAG_PLATDATA_VALID);
+
+       return 0;
+fail:
+       device_free(dev);
+
+       return ret;
+}
+
+int device_probe(struct udevice *dev)
+{
+       const struct driver *drv;
+       int ret;
+
+       if (!dev)
+               return -EINVAL;
+
+       if (dev_get_flags(dev) & DM_FLAG_ACTIVATED)
+               return 0;
+
+       drv = dev->driver;
+       assert(drv);
+
+       ret = device_of_to_plat(dev);
+       if (ret)
+               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;
@@ -366,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
@@ -389,9 +467,11 @@ int device_probe(struct udevice *dev)
                pinctrl_select_state(dev, "default");
 
        if (CONFIG_IS_ENABLED(POWER_DOMAIN) && dev->parent &&
-           device_get_uclass_id(dev) != UCLASS_POWER_DOMAIN) {
-               if (!power_domain_get(dev, &pd))
-                       power_domain_on(&pd);
+           (device_get_uclass_id(dev) != UCLASS_POWER_DOMAIN) &&
+           !(drv->flags & DM_FLAG_DEFAULT_PD_CTRL_OFF)) {
+               ret = dev_power_domain_on(dev);
+               if (ret)
+                       goto fail;
        }
 
        ret = uclass_pre_probe_device(dev);
@@ -404,30 +484,21 @@ int device_probe(struct udevice *dev)
                        goto fail;
        }
 
-       if (drv->ofdata_to_platdata &&
-           (CONFIG_IS_ENABLED(OF_PLATDATA) || dev_has_of_node(dev))) {
-               ret = drv->ofdata_to_platdata(dev);
-               if (ret)
-                       goto fail;
-       }
-
        /* 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
                 */
-               ret = clk_set_defaults(dev);
+               ret = clk_set_defaults(dev, 0);
                if (ret)
                        goto fail;
        }
 
        if (drv->probe) {
                ret = drv->probe(dev);
-               if (ret) {
-                       dev->flags &= ~DM_FLAG_ACTIVATED;
+               if (ret)
                        goto fail;
-               }
        }
 
        ret = uclass_post_probe_device(dev);
@@ -444,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)
@@ -489,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)
@@ -499,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)
@@ -509,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,
@@ -556,7 +626,8 @@ static int device_find_by_ofnode(ofnode node, struct udevice **devp)
 }
 #endif
 
-int device_get_child(struct udevice *parent, int index, struct udevice **devp)
+int device_get_child(const struct udevice *parent, int index,
+                    struct udevice **devp)
 {
        struct udevice *dev;
 
@@ -568,7 +639,7 @@ int device_get_child(struct udevice *parent, int index, struct udevice **devp)
        return -ENODEV;
 }
 
-int device_get_child_count(struct udevice *parent)
+int device_get_child_count(const struct udevice *parent)
 {
        struct udevice *dev;
        int count = 0;
@@ -579,18 +650,15 @@ int device_get_child_count(struct udevice *parent)
        return count;
 }
 
-int device_find_child_by_seq(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;
                }
@@ -599,25 +667,19 @@ int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq,
        return -ENODEV;
 }
 
-int device_get_child_by_seq(struct udevice *parent, int seq,
+int device_get_child_by_seq(const struct udevice *parent, int seq,
                            struct udevice **devp)
 {
        struct udevice *dev;
        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);
 }
 
-int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
+int device_find_child_by_of_offset(const struct udevice *parent, int of_offset,
                                   struct udevice **devp)
 {
        struct udevice *dev;
@@ -634,7 +696,7 @@ int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
        return -ENODEV;
 }
 
-int device_get_child_by_of_offset(struct udevice *parent, int node,
+int device_get_child_by_of_offset(const struct udevice *parent, int node,
                                  struct udevice **devp)
 {
        struct udevice *dev;
@@ -677,7 +739,35 @@ int device_get_global_by_ofnode(ofnode ofnode, struct udevice **devp)
        return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
 }
 
-int device_find_first_child(struct udevice *parent, struct udevice **devp)
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+int device_get_by_driver_info(const struct driver_info *info,
+                             struct udevice **devp)
+{
+       struct driver_info *info_base =
+               ll_entry_start(struct driver_info, driver_info);
+       int idx = info - info_base;
+       struct driver_rt *drt = gd_dm_driver_rt() + idx;
+       struct udevice *dev;
+
+       dev = drt->dev;
+       *devp = NULL;
+
+       return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
+}
+
+int device_get_by_driver_info_idx(uint idx, struct udevice **devp)
+{
+       struct driver_rt *drt = gd_dm_driver_rt() + idx;
+       struct udevice *dev;
+
+       dev = drt->dev;
+       *devp = NULL;
+
+       return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
+}
+#endif
+
+int device_find_first_child(const struct udevice *parent, struct udevice **devp)
 {
        if (list_empty(&parent->child_head)) {
                *devp = NULL;
@@ -704,7 +794,7 @@ int device_find_next_child(struct udevice **devp)
        return 0;
 }
 
-int device_find_first_inactive_child(struct udevice *parent,
+int device_find_first_inactive_child(const struct udevice *parent,
                                     enum uclass_id uclass_id,
                                     struct udevice **devp)
 {
@@ -722,7 +812,7 @@ int device_find_first_inactive_child(struct udevice *parent,
        return -ENODEV;
 }
 
-int device_find_first_child_by_uclass(struct udevice *parent,
+int device_find_first_child_by_uclass(const struct udevice *parent,
                                      enum uclass_id uclass_id,
                                      struct udevice **devp)
 {
@@ -739,7 +829,7 @@ int device_find_first_child_by_uclass(struct udevice *parent,
        return -ENODEV;
 }
 
-int device_find_child_by_name(struct udevice *parent, const char *name,
+int device_find_child_by_name(const struct udevice *parent, const char *name,
                              struct udevice **devp)
 {
        struct udevice *dev;
@@ -756,6 +846,64 @@ int device_find_child_by_name(struct udevice *parent, const char *name,
        return -ENODEV;
 }
 
+int device_first_child_err(struct udevice *parent, struct udevice **devp)
+{
+       struct udevice *dev;
+
+       device_find_first_child(parent, &dev);
+       if (!dev)
+               return -ENODEV;
+
+       return device_get_device_tail(dev, 0, devp);
+}
+
+int device_next_child_err(struct udevice **devp)
+{
+       struct udevice *dev = *devp;
+
+       device_find_next_child(&dev);
+       if (!dev)
+               return -ENODEV;
+
+       return device_get_device_tail(dev, 0, devp);
+}
+
+int device_first_child_ofdata_err(struct udevice *parent, struct udevice **devp)
+{
+       struct udevice *dev;
+       int ret;
+
+       device_find_first_child(parent, &dev);
+       if (!dev)
+               return -ENODEV;
+
+       ret = device_of_to_plat(dev);
+       if (ret)
+               return ret;
+
+       *devp = dev;
+
+       return 0;
+}
+
+int device_next_child_ofdata_err(struct udevice **devp)
+{
+       struct udevice *dev = *devp;
+       int ret;
+
+       device_find_next_child(&dev);
+       if (!dev)
+               return -ENODEV;
+
+       ret = device_of_to_plat(dev);
+       if (ret)
+               return ret;
+
+       *devp = dev;
+
+       return 0;
+}
+
 struct udevice *dev_get_parent(const struct udevice *child)
 {
        return child->parent;
@@ -792,7 +940,7 @@ bool device_has_children(const struct udevice *dev)
        return !list_empty(&dev->child_head);
 }
 
-bool device_has_active_children(struct udevice *dev)
+bool device_has_active_children(const struct udevice *dev)
 {
        struct udevice *child;
 
@@ -806,7 +954,7 @@ bool device_has_active_children(struct udevice *dev)
        return false;
 }
 
-bool device_is_last_sibling(struct udevice *dev)
+bool device_is_last_sibling(const struct udevice *dev)
 {
        struct udevice *parent = dev->parent;
 
@@ -817,7 +965,7 @@ bool device_is_last_sibling(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)
@@ -831,8 +979,38 @@ 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(struct udevice *dev, const char *compat)
+bool device_is_compatible(const struct udevice *dev, const char *compat)
 {
        return ofnode_device_is_compatible(dev_ofnode(dev), compat);
 }