diff options
Diffstat (limited to 'arch/arm/mach-snapdragon/board.c')
-rw-r--r-- | arch/arm/mach-snapdragon/board.c | 87 |
1 files changed, 76 insertions, 11 deletions
diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c index 92492c3a033..93de516d9ea 100644 --- a/arch/arm/mach-snapdragon/board.c +++ b/arch/arm/mach-snapdragon/board.c @@ -38,9 +38,18 @@ static struct mm_region rbx_mem_map[CONFIG_NR_DRAM_BANKS + 2] = { { 0 } }; struct mm_region *mem_map = rbx_mem_map; +static struct { + phys_addr_t start; + phys_size_t size; +} prevbl_ddr_banks[CONFIG_NR_DRAM_BANKS] __section(".data") = { 0 }; + int dram_init(void) { - return fdtdec_setup_mem_size_base(); + /* + * gd->ram_base / ram_size have been setup already + * in qcom_parse_memory(). + */ + return 0; } static int ddr_bank_cmp(const void *v1, const void *v2) @@ -58,21 +67,69 @@ static int ddr_bank_cmp(const void *v1, const void *v2) return (res1->start >> 24) - (res2->start >> 24); } +/* This has to be done post-relocation since gd->bd isn't preserved */ +static void qcom_configure_bi_dram(void) +{ + int i; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + gd->bd->bi_dram[i].start = prevbl_ddr_banks[i].start; + gd->bd->bi_dram[i].size = prevbl_ddr_banks[i].size; + } +} + int dram_init_banksize(void) { - int ret; + qcom_configure_bi_dram(); - ret = fdtdec_setup_memory_banksize(); - if (ret < 0) - return ret; + return 0; +} - if (CONFIG_NR_DRAM_BANKS < 2) - return 0; +static void qcom_parse_memory(void) +{ + ofnode node; + const fdt64_t *memory; + int memsize; + phys_addr_t ram_end = 0; + int i, j, banks; + + node = ofnode_path("/memory"); + if (!ofnode_valid(node)) { + log_err("No memory node found in device tree!\n"); + return; + } + memory = ofnode_read_prop(node, "reg", &memsize); + if (!memory) { + log_err("No memory configuration was provided by the previous bootloader!\n"); + return; + } + + banks = min(memsize / (2 * sizeof(u64)), (ulong)CONFIG_NR_DRAM_BANKS); + + if (memsize / sizeof(u64) > CONFIG_NR_DRAM_BANKS * 2) + log_err("Provided more than the max of %d memory banks\n", CONFIG_NR_DRAM_BANKS); + + if (banks > CONFIG_NR_DRAM_BANKS) + log_err("Provided more memory banks than we can handle\n"); + + for (i = 0, j = 0; i < banks * 2; i += 2, j++) { + prevbl_ddr_banks[j].start = get_unaligned_be64(&memory[i]); + prevbl_ddr_banks[j].size = get_unaligned_be64(&memory[i + 1]); + /* SM8650 boards sometimes have empty regions! */ + if (!prevbl_ddr_banks[j].size) { + j--; + continue; + } + ram_end = max(ram_end, prevbl_ddr_banks[j].start + prevbl_ddr_banks[j].size); + } /* Sort our RAM banks -_- */ - qsort(gd->bd->bi_dram, CONFIG_NR_DRAM_BANKS, sizeof(gd->bd->bi_dram[0]), ddr_bank_cmp); + qsort(prevbl_ddr_banks, banks, sizeof(prevbl_ddr_banks[0]), ddr_bank_cmp); - return 0; + gd->ram_base = prevbl_ddr_banks[0].start; + gd->ram_size = ram_end - gd->ram_base; + debug("ram_base = %#011lx, ram_size = %#011llx, ram_end = %#011llx\n", + gd->ram_base, gd->ram_size, ram_end); } static void show_psci_version(void) @@ -110,11 +167,19 @@ void *board_fdt_blob_setup(int *err) if (internal_valid) { debug("Using built in FDT\n"); - return (void *)gd->fdt_blob; } else { debug("Using external FDT\n"); - return (void *)fdt; + /* So we can use it before returning */ + gd->fdt_blob = fdt; } + + /* + * Parse the /memory node while we're here, + * this makes it easy to do other things early. + */ + qcom_parse_memory(); + + return (void *)gd->fdt_blob; } void reset_cpu(void) |