diff options
author | Michael Pratt <mpratt@chromium.org> | 2018-06-11 13:07:09 -0600 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2018-07-09 09:11:00 -0600 |
commit | 90c08fa038451d6d7b7d8711bfd829b61d64c490 (patch) | |
tree | 7cfd0d58221ae95037dea8e435ef8b55ea2898d4 /lib | |
parent | 8c5d4fd0ec222701598a27b26ab7265d4cee45a3 (diff) | |
download | u-boot-90c08fa038451d6d7b7d8711bfd829b61d64c490.zip u-boot-90c08fa038451d6d7b7d8711bfd829b61d64c490.tar.gz u-boot-90c08fa038451d6d7b7d8711bfd829b61d64c490.tar.bz2 |
fdt: Add device tree memory bindings
Support a default memory bank, specified in reg, as well as
board-specific memory banks in subtree board-id nodes.
This allows memory information to be provided in the device tree,
rather than hard-coded in, which will make it simpler to handle
similar devices with different memory banks, as the board-id values
or masks can be used to match devices.
Signed-off-by: Michael Pratt <mpratt@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/fdtdec.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/lib/fdtdec.c b/lib/fdtdec.c index f4e8dbf..fc92082 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -11,6 +11,7 @@ #include <errno.h> #include <fdtdec.h> #include <fdt_support.h> +#include <inttypes.h> #include <linux/libfdt.h> #include <serial.h> #include <asm/sections.h> @@ -1350,4 +1351,112 @@ int fdtdec_setup(void) return fdtdec_prepare_fdt(); } +#ifdef CONFIG_NR_DRAM_BANKS +int fdtdec_decode_ram_size(const void *blob, const char *area, int board_id, + phys_addr_t *basep, phys_size_t *sizep, bd_t *bd) +{ + int addr_cells, size_cells; + const u32 *cell, *end; + u64 total_size, size, addr; + int node, child; + bool auto_size; + int bank; + int len; + + debug("%s: board_id=%d\n", __func__, board_id); + if (!area) + area = "/memory"; + node = fdt_path_offset(blob, area); + if (node < 0) { + debug("No %s node found\n", area); + return -ENOENT; + } + + cell = fdt_getprop(blob, node, "reg", &len); + if (!cell) { + debug("No reg property found\n"); + return -ENOENT; + } + + addr_cells = fdt_address_cells(blob, node); + size_cells = fdt_size_cells(blob, node); + + /* Check the board id and mask */ + for (child = fdt_first_subnode(blob, node); + child >= 0; + child = fdt_next_subnode(blob, child)) { + int match_mask, match_value; + + match_mask = fdtdec_get_int(blob, child, "match-mask", -1); + match_value = fdtdec_get_int(blob, child, "match-value", -1); + + if (match_value >= 0 && + ((board_id & match_mask) == match_value)) { + /* Found matching mask */ + debug("Found matching mask %d\n", match_mask); + node = child; + cell = fdt_getprop(blob, node, "reg", &len); + if (!cell) { + debug("No memory-banks property found\n"); + return -EINVAL; + } + break; + } + } + /* Note: if no matching subnode was found we use the parent node */ + + if (bd) { + memset(bd->bi_dram, '\0', sizeof(bd->bi_dram[0]) * + CONFIG_NR_DRAM_BANKS); + } + + auto_size = fdtdec_get_bool(blob, node, "auto-size"); + + total_size = 0; + end = cell + len / 4 - addr_cells - size_cells; + debug("cell at %p, end %p\n", cell, end); + for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { + if (cell > end) + break; + addr = 0; + if (addr_cells == 2) + addr += (u64)fdt32_to_cpu(*cell++) << 32UL; + addr += fdt32_to_cpu(*cell++); + if (bd) + bd->bi_dram[bank].start = addr; + if (basep && !bank) + *basep = (phys_addr_t)addr; + + size = 0; + if (size_cells == 2) + size += (u64)fdt32_to_cpu(*cell++) << 32UL; + size += fdt32_to_cpu(*cell++); + + if (auto_size) { + u64 new_size; + + debug("Auto-sizing %" PRIx64 ", size %" PRIx64 ": ", + addr, size); + new_size = get_ram_size((long *)(uintptr_t)addr, size); + if (new_size == size) { + debug("OK\n"); + } else { + debug("sized to %" PRIx64 "\n", new_size); + size = new_size; + } + } + + if (bd) + bd->bi_dram[bank].size = size; + total_size += size; + } + + debug("Memory size %" PRIu64 "\n", total_size); + if (sizep) + *sizep = (phys_size_t)total_size; + + return 0; +} +#endif /* CONFIG_NR_DRAM_BANKS */ + #endif /* !USE_HOSTCC */ |