summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorMasahiro Yamada <yamada.m@jp.panasonic.com>2014-04-18 17:41:03 +0900
committerTom Rini <trini@ti.com>2014-06-19 11:18:51 -0400
commit739a01ed8e02c3b79a0f059d34b749bfab1a30df (patch)
tree79dd718c9fa35727729b67d33fc61330ecf3efac /common
parentf89d482fe5a95db637190cd49e1954588995d881 (diff)
downloadu-boot-imx-739a01ed8e02c3b79a0f059d34b749bfab1a30df.zip
u-boot-imx-739a01ed8e02c3b79a0f059d34b749bfab1a30df.tar.gz
u-boot-imx-739a01ed8e02c3b79a0f059d34b749bfab1a30df.tar.bz2
fdt_support: fix an endian bug of fdt_fixup_memory_banks
Data written to DTB must be converted to big endian order. It is usually done by using cpu_to_fdt32(), cpu_to_fdt64(), etc. fdt_fixup_memory_banks() invoked write_cell(), which always swaps byte order. It means the function only worked on little endian architectures. This commit adds and uses a new helper function, fdt_pack_reg(), which works on both big endian and little endian architrectures. Signed-off-by: Masahiro Yamada <yamada.m@jp.panasonic.com> Acked-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'common')
-rw-r--r--common/fdt_support.c42
1 files changed, 30 insertions, 12 deletions
diff --git a/common/fdt_support.c b/common/fdt_support.c
index fe85a8b..ae714e7 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -380,6 +380,34 @@ void do_fixup_by_compat_u32(void *fdt, const char *compat,
do_fixup_by_compat(fdt, compat, prop, &tmp, 4, create);
}
+/*
+ * fdt_pack_reg - pack address and size array into the "reg"-suitable stream
+ */
+static int fdt_pack_reg(const void *fdt, void *buf, uint64_t *address,
+ uint64_t *size, int n)
+{
+ int i;
+ int address_len = get_cells_len(fdt, "#address-cells");
+ int size_len = get_cells_len(fdt, "#size-cells");
+ char *p = buf;
+
+ for (i = 0; i < n; i++) {
+ if (address_len == 8)
+ *(fdt64_t *)p = cpu_to_fdt64(address[i]);
+ else
+ *(fdt32_t *)p = cpu_to_fdt32(address[i]);
+ p += address_len;
+
+ if (size_len == 8)
+ *(fdt64_t *)p = cpu_to_fdt64(size[i]);
+ else
+ *(fdt32_t *)p = cpu_to_fdt32(size[i]);
+ p += size_len;
+ }
+
+ return p - (char *)buf;
+}
+
#ifdef CONFIG_NR_DRAM_BANKS
#define MEMORY_BANKS_MAX CONFIG_NR_DRAM_BANKS
#else
@@ -388,9 +416,8 @@ void do_fixup_by_compat_u32(void *fdt, const char *compat,
int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks)
{
int err, nodeoffset;
- int addr_cell_len, size_cell_len, len;
+ int len;
u8 tmp[MEMORY_BANKS_MAX * 16]; /* Up to 64-bit address + 64-bit size */
- int bank;
if (banks > MEMORY_BANKS_MAX) {
printf("%s: num banks %d exceeds hardcoded limit %d."
@@ -418,16 +445,7 @@ int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks)
return err;
}
- addr_cell_len = get_cells_len(blob, "#address-cells");
- size_cell_len = get_cells_len(blob, "#size-cells");
-
- for (bank = 0, len = 0; bank < banks; bank++) {
- write_cell(tmp + len, start[bank], addr_cell_len);
- len += addr_cell_len;
-
- write_cell(tmp + len, size[bank], size_cell_len);
- len += size_cell_len;
- }
+ len = fdt_pack_reg(blob, tmp, start, size, banks);
err = fdt_setprop(blob, nodeoffset, "reg", tmp, len);
if (err < 0) {