diff options
author | Masahiro Yamada <yamada.masahiro@socionext.com> | 2016-03-29 20:18:45 +0900 |
---|---|---|
committer | Masahiro Yamada <yamada.masahiro@socionext.com> | 2016-04-01 00:59:47 +0900 |
commit | ac2a1030e3aba3deba7f5c3f6d3c4faf6e9506f8 (patch) | |
tree | 03c809a5c8d0aca5e96619ee5e1a87f3c14b0023 /arch/arm/mach-uniphier | |
parent | 15826e7e701baeeb404cabe4578dbd5aed21ea78 (diff) |
ARM: uniphier: adjust dram_init() and dram_init_banksize() for ARM64
Currently, these functions assume #address-cells and #size-cells are
both one. Fix them to support 64bit DTB.
Also, I am fixing a buffer overrun bug while I am here. The array
size of gd->bd->bd_dram is CONFIG_NR_DRAM_BANKS. The number of
iteration in the loop should be limited by that CONFIG.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Diffstat (limited to 'arch/arm/mach-uniphier')
-rw-r--r-- | arch/arm/mach-uniphier/dram_init.c | 45 |
1 files changed, 35 insertions, 10 deletions
diff --git a/arch/arm/mach-uniphier/dram_init.c b/arch/arm/mach-uniphier/dram_init.c index cffdfc9841..815f2433f3 100644 --- a/arch/arm/mach-uniphier/dram_init.c +++ b/arch/arm/mach-uniphier/dram_init.c @@ -23,14 +23,25 @@ static const void *get_memory_reg_prop(const void *fdt, int *lenp) int dram_init(void) { + const void *fdt = gd->fdt_blob; const fdt32_t *val; - int len; + int ac, sc, len; - val = get_memory_reg_prop(gd->fdt_blob, &len); - if (len < sizeof(*val)) + ac = fdt_address_cells(fdt, 0); + sc = fdt_size_cells(fdt, 0); + if (ac < 0 || sc < 1 || sc > 2) { + printf("invalid address/size cells\n"); return -EINVAL; + } + + val = get_memory_reg_prop(fdt, &len); + if (len / sizeof(*val) < ac + sc) + return -EINVAL; + + val += ac; - gd->ram_size = fdt32_to_cpu(*(val + 1)); + gd->ram_size = sc == 2 ? fdt64_to_cpu(*(fdt64_t *)val) : + fdt32_to_cpu(*val); debug("DRAM size = %08lx\n", (unsigned long)gd->ram_size); @@ -39,19 +50,33 @@ int dram_init(void) void dram_init_banksize(void) { + const void *fdt = gd->fdt_blob; const fdt32_t *val; - int len, i; + int ac, sc, cells, len, i; - val = get_memory_reg_prop(gd->fdt_blob, &len); + val = get_memory_reg_prop(fdt, &len); if (len < 0) return; + ac = fdt_address_cells(fdt, 0); + sc = fdt_size_cells(fdt, 0); + if (ac < 1 || sc > 2 || sc < 1 || sc > 2) { + printf("invalid address/size cells\n"); + return; + } + + cells = ac + sc; + len /= sizeof(*val); - len /= 2; - for (i = 0; i < len; i++) { - gd->bd->bi_dram[i].start = fdt32_to_cpu(*val++); - gd->bd->bi_dram[i].size = fdt32_to_cpu(*val++); + for (i = 0; i < CONFIG_NR_DRAM_BANKS && len >= cells; + i++, len -= cells) { + gd->bd->bi_dram[i].start = ac == 2 ? + fdt64_to_cpu(*(fdt64_t *)val) : fdt32_to_cpu(*val); + val += ac; + gd->bd->bi_dram[i].size = sc == 2 ? + fdt64_to_cpu(*(fdt64_t *)val) : fdt32_to_cpu(*val); + val += sc; debug("DRAM bank %d: start = %08lx, size = %08lx\n", i, (unsigned long)gd->bd->bi_dram[i].start, |