diff options
-rw-r--r-- | arch/arm/mach-tegra/arm64-mmu.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra186/nvtboot_mem.c | 78 |
2 files changed, 55 insertions, 26 deletions
diff --git a/arch/arm/mach-tegra/arm64-mmu.c b/arch/arm/mach-tegra/arm64-mmu.c index a79a5192e0..3a126bdec4 100644 --- a/arch/arm/mach-tegra/arm64-mmu.c +++ b/arch/arm/mach-tegra/arm64-mmu.c @@ -12,7 +12,8 @@ #include <asm/system.h> #include <asm/armv8/mmu.h> -static struct mm_region tegra_mem_map[] = { +/* size: IO + NR_DRAM_BANKS + terminator */ +struct mm_region tegra_mem_map[1 + CONFIG_NR_DRAM_BANKS + 1] = { { .virt = 0x0UL, .phys = 0x0UL, diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_mem.c b/arch/arm/mach-tegra/tegra186/nvtboot_mem.c index 33e331f4ca..2ca59747d4 100644 --- a/arch/arm/mach-tegra/tegra186/nvtboot_mem.c +++ b/arch/arm/mach-tegra/tegra186/nvtboot_mem.c @@ -8,6 +8,7 @@ #include <fdt_support.h> #include <fdtdec.h> #include <asm/arch/tegra.h> +#include <asm/armv8/mmu.h> #define SZ_4G 0x100000000ULL @@ -28,6 +29,7 @@ DECLARE_GLOBAL_DATA_PTR; extern unsigned long nvtboot_boot_x0; +extern struct mm_region tegra_mem_map[]; /* * These variables are written to before relocation, and hence cannot be @@ -36,12 +38,6 @@ extern unsigned long nvtboot_boot_x0; * also has the nice side-effect of the content being valid after relocation. */ -/* A parsed version of /memory/reg from the DTB passed to U-Boot in x0 */ -static struct { - u64 start; - u64 size; -} ram_banks[CONFIG_NR_DRAM_BANKS] __attribute__((section(".data"))); - /* The number of valid entries in ram_banks[] */ static int ram_bank_count __attribute__((section(".data"))); @@ -62,8 +58,6 @@ int dram_init(void) int node, len, i; const u32 *prop; - memset(ram_banks, 0, sizeof(ram_banks)); - na = fdtdec_get_uint(nvtboot_blob, 0, "#address-cells", 2); ns = fdtdec_get_uint(nvtboot_blob, 0, "#size-cells", 2); @@ -81,36 +75,70 @@ int dram_init(void) /* Calculate the true # of base/size pairs to read */ len /= 4; /* Convert bytes to number of cells */ len /= (na + ns); /* Convert cells to number of banks */ - if (len > ARRAY_SIZE(ram_banks)) - len = ARRAY_SIZE(ram_banks); - ram_bank_count = len; + if (len > CONFIG_NR_DRAM_BANKS) + len = CONFIG_NR_DRAM_BANKS; + /* Parse the /memory node, and save useful entries */ gd->ram_size = 0; - for (i = 0; i < ram_bank_count; i++) { - u64 bank_end, usable_bank_size; + ram_bank_count = 0; + for (i = 0; i < len; i++) { + u64 bank_start, bank_end, bank_size, usable_bank_size; - ram_banks[i].start = fdt_read_number(prop, na); + /* Extract raw memory region data from DTB */ + bank_start = fdt_read_number(prop, na); prop += na; - ram_banks[i].size = fdt_read_number(prop, ns); + bank_size = fdt_read_number(prop, ns); prop += ns; - gd->ram_size += ram_banks[i].size; - debug("Bank %d: start: %llx size: %llx\n", i, - ram_banks[i].start, ram_banks[i].size); - - bank_end = ram_banks[i].start + ram_banks[i].size; - debug(" end %llx\n", bank_end); + gd->ram_size += bank_size; + bank_end = bank_start + bank_size; + debug("Bank %d: %llx..%llx (+%llx)\n", i, + bank_start, bank_end, bank_size); + + /* + * Align the bank to MMU section size. This is not strictly + * necessary, since the translation table construction code + * handles page granularity without issue. However, aligning + * the MMU entries reduces the size and number of levels in the + * page table, so is worth it. + */ + bank_start = ROUND(bank_start, SZ_2M); + bank_end = bank_end & ~(SZ_2M - 1); + bank_size = bank_end - bank_start; + debug(" aligned: %llx..%llx (+%llx)\n", + bank_start, bank_end, bank_size); + if (bank_end <= bank_start) + continue; + + /* Record data used to create MMU translation tables */ + ram_bank_count++; + /* Index below is deliberately 1-based to skip MMIO entry */ + tegra_mem_map[ram_bank_count].virt = bank_start; + tegra_mem_map[ram_bank_count].phys = bank_start; + tegra_mem_map[ram_bank_count].size = bank_size; + tegra_mem_map[ram_bank_count].attrs = + PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE; + + /* Determine best bank to relocate U-Boot into */ if (bank_end > SZ_4G) bank_end = SZ_4G; debug(" end %llx (usable)\n", bank_end); - usable_bank_size = bank_end - ram_banks[i].start; + usable_bank_size = bank_end - bank_start; debug(" size %llx (usable)\n", usable_bank_size); if ((usable_bank_size >= MIN_USABLE_RAM_SIZE) && (bank_end > ram_top)) { ram_top = bank_end; - region_base = ram_banks[i].start; + region_base = bank_start; debug("ram top now %llx\n", ram_top); } } + + /* Ensure memory map contains the desired sentinel entry */ + tegra_mem_map[ram_bank_count + 1].virt = 0; + tegra_mem_map[ram_bank_count + 1].phys = 0; + tegra_mem_map[ram_bank_count + 1].size = 0; + tegra_mem_map[ram_bank_count + 1].attrs = 0; + + /* Error out if a relocation target couldn't be found */ if (!ram_top) { pr_err("Can't find a usable RAM top"); hang(); @@ -129,8 +157,8 @@ int dram_init_banksize(void) } for (i = 0; i < ram_bank_count; i++) { - gd->bd->bi_dram[i].start = ram_banks[i].start; - gd->bd->bi_dram[i].size = ram_banks[i].size; + gd->bd->bi_dram[i].start = tegra_mem_map[1 + i].virt; + gd->bd->bi_dram[i].size = tegra_mem_map[1 + i].size; } #ifdef CONFIG_PCI |