diff options
author | Masahiro Yamada <yamada.m@jp.panasonic.com> | 2014-04-18 17:41:03 +0900 |
---|---|---|
committer | Tom Rini <trini@ti.com> | 2014-06-19 11:18:51 -0400 |
commit | 739a01ed8e02c3b79a0f059d34b749bfab1a30df (patch) | |
tree | 79dd718c9fa35727729b67d33fc61330ecf3efac /common/fdt_support.c | |
parent | f89d482fe5a95db637190cd49e1954588995d881 (diff) | |
download | u-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/fdt_support.c')
-rw-r--r-- | common/fdt_support.c | 42 |
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) { |