summaryrefslogtreecommitdiff
path: root/drivers/core
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2020-04-16 20:45:03 +0300
committerTom Rini <trini@konsulko.com>2020-04-16 20:45:03 +0300
commitf51b4bcf61c9aa7994138a4a417488c1fbdb47cd (patch)
tree4f536d0892be1359f2cf02bfe366b56bef83bf28 /drivers/core
parentdba0a6ae1907bbff3ebda06e4874d006f10db1bb (diff)
parentb0dcc87106464c3fc019e3771378a092fd32ebdb (diff)
downloadu-boot-f51b4bcf61c9aa7994138a4a417488c1fbdb47cd.tar.xz
Merge tag 'dm-pull-10apr20-take2' of git://git.denx.de/u-boot-dm
Functions for reading indexed values from device tree Enhancements to 'dm' command Log test enhancements and syslog driver DM change to read parent ofdata before children Minor fixes
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 ff5b28cb6a..efdb0f2905 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 89ea820d48..0157bb1fe0 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 68204c303f..c7db14ed56 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 acd745c121..c54baa140a 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 96a5dd20bd..b0be7cbe19 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 1f999b1b31..ce78f09d28 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 e85643819e..14df16c280 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 58b19a4210..6849302936 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 69f83755f0..25b0d76f43 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)
{