return -ENODEV;
}
+int uclass_find_first_device(enum uclass_id id, struct udevice **devp)
+{
+ struct uclass *uc;
+ int ret;
+
+ *devp = NULL;
+ ret = uclass_get(id, &uc);
+ if (ret)
+ return ret;
+ if (list_empty(&uc->dev_head))
+ return 0;
+
+ *devp = list_first_entry(&uc->dev_head, struct udevice, uclass_node);
+
+ return 0;
+}
+
+int uclass_find_next_device(struct udevice **devp)
+{
+ struct udevice *dev = *devp;
+
+ *devp = NULL;
+ if (list_is_last(&dev->uclass_node, &dev->uclass->dev_head))
+ return 0;
+
+ *devp = list_entry(dev->uclass_node.next, struct udevice, uclass_node);
+
+ return 0;
+}
+
int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq,
bool find_req_seq, struct udevice **devp)
{
int uclass_first_device(enum uclass_id id, struct udevice **devp)
{
- struct uclass *uc;
struct udevice *dev;
int ret;
*devp = NULL;
- ret = uclass_get(id, &uc);
- if (ret)
- return ret;
- if (list_empty(&uc->dev_head))
- return 0;
-
- dev = list_first_entry(&uc->dev_head, struct udevice, uclass_node);
- ret = device_probe(dev);
- if (ret)
- return ret;
- *devp = dev;
-
- return 0;
+ ret = uclass_find_first_device(id, &dev);
+ return uclass_get_device_tail(dev, ret, devp);
}
int uclass_next_device(struct udevice **devp)
int ret;
*devp = NULL;
- if (list_is_last(&dev->uclass_node, &dev->uclass->dev_head))
- return 0;
-
- dev = list_entry(dev->uclass_node.next, struct udevice,
- uclass_node);
- ret = device_probe(dev);
- if (ret)
- return ret;
- *devp = dev;
-
- return 0;
+ ret = uclass_find_next_device(&dev);
+ return uclass_get_device_tail(dev, ret, devp);
}
int uclass_bind_device(struct udevice *dev)
int ret;
uc = dev->uclass;
-
list_add_tail(&dev->uclass_node, &uc->dev_head);
+ if (dev->parent) {
+ struct uclass_driver *uc_drv = dev->parent->uclass->uc_drv;
+
+ if (uc_drv->child_post_bind) {
+ ret = uc_drv->child_post_bind(dev);
+ if (ret)
+ goto err;
+ }
+ }
if (uc->uc_drv->post_bind) {
ret = uc->uc_drv->post_bind(dev);
- if (ret) {
- list_del(&dev->uclass_node);
- return ret;
- }
+ if (ret)
+ goto err;
}
return 0;
+err:
+ /* There is no need to undo the parent's post_bind call */
+ list_del(&dev->uclass_node);
+
+ return ret;
}
int uclass_unbind_device(struct udevice *dev)
return seq;
}
+int uclass_pre_probe_device(struct udevice *dev)
+{
+ struct uclass_driver *uc_drv;
+ int ret;
+
+ uc_drv = dev->uclass->uc_drv;
+ if (uc_drv->pre_probe) {
+ ret = uc_drv->pre_probe(dev);
+ if (ret)
+ return ret;
+ }
+
+ if (!dev->parent)
+ return 0;
+ uc_drv = dev->parent->uclass->uc_drv;
+ if (uc_drv->child_pre_probe)
+ return uc_drv->child_pre_probe(dev);
+
+ return 0;
+}
+
int uclass_post_probe_device(struct udevice *dev)
{
struct uclass_driver *uc_drv = dev->uclass->uc_drv;