aboutsummaryrefslogtreecommitdiff
path: root/drivers/core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/core')
-rw-r--r--drivers/core/device-remove.c23
-rw-r--r--drivers/core/device.c22
-rw-r--r--drivers/core/lists.c2
-rw-r--r--drivers/core/of_access.c40
-rw-r--r--drivers/core/ofnode.c49
-rw-r--r--drivers/core/read.c13
-rw-r--r--drivers/core/root.c52
-rw-r--r--drivers/core/uclass.c6
-rw-r--r--drivers/core/util.c28
9 files changed, 125 insertions, 110 deletions
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index ff5b28c..efdb0f2 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -10,6 +10,7 @@
#include <common.h>
#include <errno.h>
+#include <log.h>
#include <malloc.h>
#include <dm/device.h>
#include <dm/device-internal.h>
@@ -30,11 +31,14 @@ int device_chld_unbind(struct udevice *dev, struct driver *drv)
continue;
ret = device_unbind(pos);
- if (ret && !saved_ret)
+ if (ret && !saved_ret) {
+ log_warning("device '%s' failed to unbind\n",
+ pos->name);
saved_ret = ret;
+ }
}
- return saved_ret;
+ return log_ret(saved_ret);
}
int device_chld_remove(struct udevice *dev, struct driver *drv,
@@ -63,13 +67,13 @@ int device_unbind(struct udevice *dev)
int ret;
if (!dev)
- return -EINVAL;
+ return log_msg_ret("dev", -EINVAL);
if (dev->flags & DM_FLAG_ACTIVATED)
- return -EINVAL;
+ return log_msg_ret("active", -EINVAL);
if (!(dev->flags & DM_FLAG_BOUND))
- return -EINVAL;
+ return log_msg_ret("not-bound", -EINVAL);
drv = dev->driver;
assert(drv);
@@ -77,12 +81,12 @@ int device_unbind(struct udevice *dev)
if (drv->unbind) {
ret = drv->unbind(dev);
if (ret)
- return ret;
+ return log_msg_ret("unbind", ret);
}
ret = device_chld_unbind(dev, NULL);
if (ret)
- return ret;
+ return log_msg_ret("child unbind", ret);
if (dev->flags & DM_FLAG_ALLOC_PDATA) {
free(dev->platdata);
@@ -98,7 +102,7 @@ int device_unbind(struct udevice *dev)
}
ret = uclass_unbind_device(dev);
if (ret)
- return ret;
+ return log_msg_ret("uc", ret);
if (dev->parent)
list_del(&dev->sibling_node);
@@ -194,7 +198,8 @@ int device_remove(struct udevice *dev, uint flags)
}
}
- if (!(drv->flags &
+ if (!(flags & DM_REMOVE_NO_PD) &&
+ !(drv->flags &
(DM_FLAG_DEFAULT_PD_CTRL_OFF | DM_FLAG_REMOVE_WITH_PD_ON)) &&
dev != gd->cur_serial_dev)
dev_power_domain_off(dev);
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 89ea820..0157bb1 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -143,11 +143,9 @@ static int device_bind_common(struct udevice *parent, const struct driver *drv,
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)
@@ -323,6 +321,22 @@ int device_ofdata_to_platdata(struct udevice *dev)
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);
diff --git a/drivers/core/lists.c b/drivers/core/lists.c
index 68204c3..c7db14e 100644
--- a/drivers/core/lists.c
+++ b/drivers/core/lists.c
@@ -175,7 +175,7 @@ int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp,
continue;
if (pre_reloc_only) {
- if (!dm_ofnode_pre_reloc(node) &&
+ if (!ofnode_pre_reloc(node) &&
!(entry->flags & DM_FLAG_PRE_RELOC)) {
log_debug("Skipping device pre-relocation\n");
return 0;
diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c
index acd745c..c54baa1 100644
--- a/drivers/core/of_access.c
+++ b/drivers/core/of_access.c
@@ -449,21 +449,7 @@ static void *of_find_property_value_of_size(const struct device_node *np,
int of_read_u32(const struct device_node *np, const char *propname, u32 *outp)
{
- const __be32 *val;
-
- debug("%s: %s: ", __func__, propname);
- if (!np)
- return -EINVAL;
- val = of_find_property_value_of_size(np, propname, sizeof(*outp));
- if (IS_ERR(val)) {
- debug("(not found)\n");
- return PTR_ERR(val);
- }
-
- *outp = be32_to_cpup(val);
- debug("%#x (%d)\n", *outp, *outp);
-
- return 0;
+ return of_read_u32_index(np, propname, 0, outp);
}
int of_read_u32_array(const struct device_node *np, const char *propname,
@@ -485,6 +471,28 @@ int of_read_u32_array(const struct device_node *np, const char *propname,
return 0;
}
+int of_read_u32_index(const struct device_node *np, const char *propname,
+ int index, u32 *outp)
+{
+ const __be32 *val;
+
+ debug("%s: %s: ", __func__, propname);
+ if (!np)
+ return -EINVAL;
+
+ val = of_find_property_value_of_size(np, propname,
+ sizeof(*outp) * (index + 1));
+ if (IS_ERR(val)) {
+ debug("(not found)\n");
+ return PTR_ERR(val);
+ }
+
+ *outp = be32_to_cpup(val + index);
+ debug("%#x (%d)\n", *outp, *outp);
+
+ return 0;
+}
+
int of_read_u64(const struct device_node *np, const char *propname, u64 *outp)
{
const __be64 *val;
@@ -577,7 +585,7 @@ static int __of_parse_phandle_with_args(const struct device_node *np,
{
const __be32 *list, *list_end;
int rc = 0, cur_index = 0;
- uint32_t count = 0;
+ uint32_t count;
struct device_node *node = NULL;
phandle phandle;
int size;
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 96a5dd2..b0be7cb 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -18,32 +18,53 @@
int ofnode_read_u32(ofnode node, const char *propname, u32 *outp)
{
+ return ofnode_read_u32_index(node, propname, 0, outp);
+}
+
+u32 ofnode_read_u32_default(ofnode node, const char *propname, u32 def)
+{
+ assert(ofnode_valid(node));
+ ofnode_read_u32_index(node, propname, 0, &def);
+
+ return def;
+}
+
+int ofnode_read_u32_index(ofnode node, const char *propname, int index,
+ u32 *outp)
+{
+ const fdt32_t *cell;
+ int len;
+
assert(ofnode_valid(node));
debug("%s: %s: ", __func__, propname);
- if (ofnode_is_np(node)) {
- return of_read_u32(ofnode_to_np(node), propname, outp);
- } else {
- const fdt32_t *cell;
- int len;
+ if (ofnode_is_np(node))
+ return of_read_u32_index(ofnode_to_np(node), propname, index,
+ outp);
- cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
- propname, &len);
- if (!cell || len < sizeof(int)) {
- debug("(not found)\n");
- return -EINVAL;
- }
- *outp = fdt32_to_cpu(cell[0]);
+ cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
+ &len);
+ if (!cell) {
+ debug("(not found)\n");
+ return -EINVAL;
+ }
+
+ if (len < (sizeof(int) * (index + 1))) {
+ debug("(not large enough)\n");
+ return -EOVERFLOW;
}
+
+ *outp = fdt32_to_cpu(cell[index]);
debug("%#x (%d)\n", *outp, *outp);
return 0;
}
-u32 ofnode_read_u32_default(ofnode node, const char *propname, u32 def)
+u32 ofnode_read_u32_index_default(ofnode node, const char *propname, int index,
+ u32 def)
{
assert(ofnode_valid(node));
- ofnode_read_u32(node, propname, &def);
+ ofnode_read_u32_index(node, propname, index, &def);
return def;
}
diff --git a/drivers/core/read.c b/drivers/core/read.c
index 1f999b1..ce78f09 100644
--- a/drivers/core/read.c
+++ b/drivers/core/read.c
@@ -22,6 +22,19 @@ int dev_read_u32_default(const struct udevice *dev, const char *propname,
return ofnode_read_u32_default(dev_ofnode(dev), propname, def);
}
+int dev_read_u32_index(struct udevice *dev, const char *propname, int index,
+ u32 *outp)
+{
+ return ofnode_read_u32_index(dev_ofnode(dev), propname, index, outp);
+}
+
+u32 dev_read_u32_index_default(struct udevice *dev, const char *propname,
+ int index, u32 def)
+{
+ return ofnode_read_u32_index_default(dev_ofnode(dev), propname, index,
+ def);
+}
+
int dev_read_s32(const struct udevice *dev, const char *propname, s32 *outp)
{
return ofnode_read_u32(dev_ofnode(dev), propname, (u32 *)outp);
diff --git a/drivers/core/root.c b/drivers/core/root.c
index e856438..14df16c 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -203,15 +203,6 @@ static int dm_scan_fdt_live(struct udevice *parent,
int ret = 0, err;
for (np = node_parent->child; np; np = np->sibling) {
- /* "chosen" node isn't a device itself but may contain some: */
- if (!strcmp(np->name, "chosen")) {
- pr_debug("parsing subnodes of \"chosen\"\n");
-
- err = dm_scan_fdt_live(parent, np, pre_reloc_only);
- if (err && !ret)
- ret = err;
- continue;
- }
if (!of_device_is_available(np)) {
pr_debug(" - ignoring disabled device\n");
@@ -256,21 +247,6 @@ static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
offset = fdt_next_subnode(blob, offset)) {
const char *node_name = fdt_get_name(blob, offset, NULL);
- /*
- * The "chosen" and "firmware" nodes aren't devices
- * themselves but may contain some:
- */
- if (!strcmp(node_name, "chosen") ||
- !strcmp(node_name, "firmware")) {
- pr_debug("parsing subnodes of \"%s\"\n", node_name);
-
- err = dm_scan_fdt_node(parent, blob, offset,
- pre_reloc_only);
- if (err && !ret)
- ret = err;
- continue;
- }
-
if (!fdtdec_get_is_enabled(blob, offset)) {
pr_debug(" - ignoring disabled device\n");
continue;
@@ -315,7 +291,8 @@ int dm_scan_fdt(const void *blob, bool pre_reloc_only)
return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only);
}
-static int dm_scan_fdt_ofnode_path(const char *path, bool pre_reloc_only)
+static int dm_scan_fdt_ofnode_path(const void *blob, const char *path,
+ bool pre_reloc_only)
{
ofnode node;
@@ -327,13 +304,18 @@ static int dm_scan_fdt_ofnode_path(const char *path, bool pre_reloc_only)
if (of_live_active())
return dm_scan_fdt_live(gd->dm_root, node.np, pre_reloc_only);
#endif
- return dm_scan_fdt_node(gd->dm_root, gd->fdt_blob, node.of_offset,
+ return dm_scan_fdt_node(gd->dm_root, blob, node.of_offset,
pre_reloc_only);
}
int dm_extended_scan_fdt(const void *blob, bool pre_reloc_only)
{
- int ret;
+ int ret, i;
+ const char * const nodes[] = {
+ "/chosen",
+ "/clocks",
+ "/firmware"
+ };
ret = dm_scan_fdt(blob, pre_reloc_only);
if (ret) {
@@ -341,16 +323,16 @@ int dm_extended_scan_fdt(const void *blob, bool pre_reloc_only)
return ret;
}
- ret = dm_scan_fdt_ofnode_path("/clocks", pre_reloc_only);
- if (ret) {
- debug("scan for /clocks failed: %d\n", ret);
- return ret;
+ /* Some nodes aren't devices themselves but may contain some */
+ for (i = 0; i < ARRAY_SIZE(nodes); i++) {
+ ret = dm_scan_fdt_ofnode_path(blob, nodes[i], pre_reloc_only);
+ if (ret) {
+ debug("dm_scan_fdt() scan for %s failed: %d\n",
+ nodes[i], ret);
+ return ret;
+ }
}
- ret = dm_scan_fdt_ofnode_path("/firmware", pre_reloc_only);
- if (ret)
- debug("scan for /firmware failed: %d\n", ret);
-
return ret;
}
#endif
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 58b19a4..6849302 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -118,12 +118,12 @@ int uclass_destroy(struct uclass *uc)
while (!list_empty(&uc->dev_head)) {
dev = list_first_entry(&uc->dev_head, struct udevice,
uclass_node);
- ret = device_remove(dev, DM_REMOVE_NORMAL);
+ ret = device_remove(dev, DM_REMOVE_NORMAL | DM_REMOVE_NO_PD);
if (ret)
- return ret;
+ return log_msg_ret("remove", ret);
ret = device_unbind(dev);
if (ret)
- return ret;
+ return log_msg_ret("unbind", ret);
}
uc_drv = uc->uc_drv;
diff --git a/drivers/core/util.c b/drivers/core/util.c
index 69f8375..25b0d76 100644
--- a/drivers/core/util.c
+++ b/drivers/core/util.c
@@ -33,34 +33,6 @@ int list_count_items(struct list_head *head)
return count;
}
-#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
-bool dm_ofnode_pre_reloc(ofnode node)
-{
-#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD)
- /* for SPL and TPL the remaining nodes after the fdtgrep 1st pass
- * had property dm-pre-reloc or u-boot,dm-spl/tpl.
- * They are removed in final dtb (fdtgrep 2nd pass)
- */
- return true;
-#else
- if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
- return true;
- if (ofnode_read_bool(node, "u-boot,dm-pre-proper"))
- return true;
-
- /*
- * In regular builds individual spl and tpl handling both
- * count as handled pre-relocation for later second init.
- */
- if (ofnode_read_bool(node, "u-boot,dm-spl") ||
- ofnode_read_bool(node, "u-boot,dm-tpl"))
- return true;
-
- return false;
-#endif
-}
-#endif
-
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
int pci_get_devfn(struct udevice *dev)
{