summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/tegra186/nvtboot_mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/tegra186/nvtboot_mem.c')
-rw-r--r--arch/arm/mach-tegra/tegra186/nvtboot_mem.c78
1 files changed, 53 insertions, 25 deletions
diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_mem.c b/arch/arm/mach-tegra/tegra186/nvtboot_mem.c
index 33e331f4ca8..2ca59747d4c 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