|
@@ -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
|