#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>
goto fail_alloc3;
}
}
- }
-
- /* 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)
return priv;
}
-int device_probe(struct udevice *dev)
+int device_ofdata_to_platdata(struct udevice *dev)
{
const struct driver *drv;
int size = 0;
int ret;
- int seq;
if (!dev)
return -EINVAL;
- if (dev->flags & DM_FLAG_ACTIVATED)
+ if (dev->flags & DM_FLAG_PLATDATA_VALID)
return 0;
+ /* Ensure all parents have ofdata */
+ if (dev->parent) {
+ ret = device_ofdata_to_platdata(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->flags & DM_FLAG_PLATDATA_VALID)
+ return 0;
+ }
+
drv = dev->driver;
assert(drv);
}
}
- /* Ensure all parents are probed */
+ /* Allocate parent data for this child */
if (dev->parent) {
size = dev->parent->driver->per_child_auto_alloc_size;
if (!size) {
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;
+ }
+
+ dev->flags |= DM_FLAG_PLATDATA_VALID;
+
+ return 0;
+fail:
+ device_free(dev);
+
+ return ret;
+}
+
+int device_probe(struct udevice *dev)
+{
+ const struct driver *drv;
+ int ret;
+ int seq;
+
+ if (!dev)
+ return -EINVAL;
+
+ if (dev->flags & DM_FLAG_ACTIVATED)
+ return 0;
+ drv = dev->driver;
+ assert(drv);
+
+ ret = device_ofdata_to_platdata(dev);
+ if (ret)
+ goto fail;
+
+ /* Ensure all parents are probed */
+ if (dev->parent) {
ret = device_probe(dev->parent);
if (ret)
goto fail;
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 (drv->probe) {
ret = drv->probe(dev);
- if (ret) {
- dev->flags &= ~DM_FLAG_ACTIVATED;
+ if (ret)
goto fail;
- }
}
ret = uclass_post_probe_device(dev);
}
#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;
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;
return count;
}
-int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq,
+int device_find_child_by_seq(const struct udevice *parent, int seq_or_req_seq,
bool find_req_seq, struct udevice **devp)
{
struct udevice *dev;
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;
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;
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;
return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
}
-int device_find_first_child(struct udevice *parent, struct udevice **devp)
+int device_find_first_child(const struct udevice *parent, struct udevice **devp)
{
if (list_empty(&parent->child_head)) {
*devp = NULL;
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)
{
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)
{
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;
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_ofdata_to_platdata(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_ofdata_to_platdata(dev);
+ if (ret)
+ return ret;
+
+ *devp = dev;
+
+ return 0;
+}
+
struct udevice *dev_get_parent(const struct udevice *child)
{
return child->parent;
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;
return false;
}
-bool device_is_last_sibling(struct udevice *dev)
+bool device_is_last_sibling(const struct udevice *dev)
{
struct udevice *parent = dev->parent;
}
#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);
}