dm: Use driver_info index instead of pointer
[platform/kernel/u-boot.git] / drivers / core / device.c
index 2d6c667..4b3dcb3 100644 (file)
@@ -82,7 +82,8 @@ static int device_bind_common(struct udevice *parent, const struct driver *drv,
                 * 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 (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)
@@ -248,10 +249,11 @@ int device_bind_ofnode(struct udevice *parent, const struct driver *drv,
 }
 
 int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
-                       struct driver_info *info, struct udevice **devp)
+                       const struct driver_info *info, struct udevice **devp)
 {
        struct driver *drv;
        uint platdata_size = 0;
+       int ret;
 
        drv = lists_driver_lookup_name(info->name);
        if (!drv)
@@ -262,9 +264,35 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
 #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);
+       ret = device_bind_common(parent, drv, info->name,
+                                (void *)info->platdata, 0, ofnode_null(),
+                                platdata_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)
@@ -729,6 +757,34 @@ int device_get_global_by_ofnode(ofnode ofnode, struct udevice **devp)
        return device_get_device_tail(dev, dev ? 0 : -ENOENT, 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)) {