aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSimon Glass2018-06-11 13:07:18 -0600
committerSimon Glass2018-07-09 09:11:00 -0600
commit964cadc445f1437e63f1d2b4fffd233ac053c6e6 (patch)
treee753eaf7147763c8d2a7aa8f20ab086c7a36c863 /drivers
parent5e0a7341cdda182f310624d5c336fb48be04a703 (diff)
dm: core: Add a function to decode a memory region
Add a way to decode a memory region, including the memory type (sram or sdram) and its start address and size. Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/core/of_extra.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/drivers/core/of_extra.c b/drivers/core/of_extra.c
index 3243caa5d12..aa48917dddf 100644
--- a/drivers/core/of_extra.c
+++ b/drivers/core/of_extra.c
@@ -34,3 +34,84 @@ int ofnode_read_fmap_entry(ofnode node, struct fmap_entry *entry)
return 0;
}
+
+int ofnode_decode_region(ofnode node, const char *prop_name, fdt_addr_t *basep,
+ fdt_size_t *sizep)
+{
+ const fdt_addr_t *cell;
+ int len;
+
+ debug("%s: %s: %s\n", __func__, ofnode_get_name(node), prop_name);
+ cell = ofnode_get_property(node, prop_name, &len);
+ if (!cell || (len < sizeof(fdt_addr_t) * 2)) {
+ debug("cell=%p, len=%d\n", cell, len);
+ return -1;
+ }
+
+ *basep = fdt_addr_to_cpu(*cell);
+ *sizep = fdt_size_to_cpu(cell[1]);
+ debug("%s: base=%08lx, size=%lx\n", __func__, (ulong)*basep,
+ (ulong)*sizep);
+
+ return 0;
+}
+
+int ofnode_decode_memory_region(ofnode config_node, const char *mem_type,
+ const char *suffix, fdt_addr_t *basep,
+ fdt_size_t *sizep)
+{
+ char prop_name[50];
+ const char *mem;
+ fdt_size_t size, offset_size;
+ fdt_addr_t base, offset;
+ ofnode node;
+
+ if (!ofnode_valid(config_node)) {
+ config_node = ofnode_path("/config");
+ if (!ofnode_valid(config_node)) {
+ debug("%s: Cannot find /config node\n", __func__);
+ return -ENOENT;
+ }
+ }
+ if (!suffix)
+ suffix = "";
+
+ snprintf(prop_name, sizeof(prop_name), "%s-memory%s", mem_type,
+ suffix);
+ mem = ofnode_read_string(config_node, prop_name);
+ if (!mem) {
+ debug("%s: No memory type for '%s', using /memory\n", __func__,
+ prop_name);
+ mem = "/memory";
+ }
+
+ node = ofnode_path(mem);
+ if (!ofnode_valid(node)) {
+ debug("%s: Failed to find node '%s'\n", __func__, mem);
+ return -ENOENT;
+ }
+
+ /*
+ * Not strictly correct - the memory may have multiple banks. We just
+ * use the first
+ */
+ if (ofnode_decode_region(node, "reg", &base, &size)) {
+ debug("%s: Failed to decode memory region %s\n", __func__,
+ mem);
+ return -EINVAL;
+ }
+
+ snprintf(prop_name, sizeof(prop_name), "%s-offset%s", mem_type,
+ suffix);
+ if (ofnode_decode_region(config_node, prop_name, &offset,
+ &offset_size)) {
+ debug("%s: Failed to decode memory region '%s'\n", __func__,
+ prop_name);
+ return -EINVAL;
+ }
+
+ *basep = base + offset;
+ *sizep = offset_size;
+
+ return 0;
+}