diff options
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r-- | arch/arm/mach-tegra/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board.c | 23 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board186.c | 32 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board2.c | 21 | ||||
-rw-r--r-- | arch/arm/mach-tegra/cboot.c (renamed from arch/arm/mach-tegra/tegra186/nvtboot_board.c) | 200 | ||||
-rw-r--r-- | arch/arm/mach-tegra/cboot_ll.S (renamed from arch/arm/mach-tegra/tegra186/nvtboot_ll.S) | 12 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra186/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra186/nvtboot_mem.c | 172 |
8 files changed, 234 insertions, 234 deletions
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index f8bc65aa8b..41ba674edf 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -5,7 +5,6 @@ # (C) Copyright 2000-2008 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. -ifndef CONFIG_TEGRA186 ifdef CONFIG_SPL_BUILD obj-y += spl.o obj-y += cpu.o @@ -20,9 +19,8 @@ obj-$(CONFIG_TEGRA_CLKRST) += clock.o obj-$(CONFIG_TEGRA_PINCTRL) += pinmux-common.o obj-$(CONFIG_TEGRA_PMC) += powergate.o obj-y += xusb-padctl-dummy.o -endif -obj-$(CONFIG_ARM64) += arm64-mmu.o +obj-$(CONFIG_ARM64) += arm64-mmu.o cboot_ll.o cboot.o obj-y += dt-setup.o obj-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o obj-$(CONFIG_TEGRA_GPU) += gpu.o diff --git a/arch/arm/mach-tegra/board.c b/arch/arm/mach-tegra/board.c index 42baf975ec..abcae15ea3 100644 --- a/arch/arm/mach-tegra/board.c +++ b/arch/arm/mach-tegra/board.c @@ -21,6 +21,7 @@ #include <asm/arch/tegra.h> #include <asm/arch-tegra/ap.h> #include <asm/arch-tegra/board.h> +#include <asm/arch-tegra/cboot.h> #include <asm/arch-tegra/pmc.h> #include <asm/arch-tegra/sys_proto.h> #include <asm/arch-tegra/warmboot.h> @@ -46,6 +47,21 @@ void save_boot_params(unsigned long r0, unsigned long r1, unsigned long r2, unsigned long r3) { from_spl = r0 != UBOOT_NOT_LOADED_FROM_SPL; + + /* + * The logic for this is somewhat indirect. The purpose of the marker + * (UBOOT_NOT_LOADED_FROM_SPL) is in fact used to determine if U-Boot + * was loaded from a read-only instance of itself, which is something + * that can happen in secure boot setups. So basically the presence + * of the marker is an indication that U-Boot was loaded by one such + * special variant of U-Boot. Conversely, the absence of the marker + * indicates that this instance of U-Boot was loaded by something + * other than a special U-Boot. This could be SPL, but it could just + * as well be one of any number of other first stage bootloaders. + */ + if (from_spl) + cboot_save_boot_params(r0, r1, r2, r3); + save_boot_params_ret(); } #endif @@ -127,6 +143,13 @@ static phys_size_t query_sdram_size(void) int dram_init(void) { + int err; + + /* try to initialize DRAM from cboot DTB first */ + err = cboot_dram_init(); + if (err == 0) + return 0; + #if IS_ENABLED(CONFIG_TEGRA_MC) /* We do not initialise DRAM here. We just query the size */ gd->ram_size = query_sdram_size(); diff --git a/arch/arm/mach-tegra/board186.c b/arch/arm/mach-tegra/board186.c deleted file mode 100644 index 80b55707e9..0000000000 --- a/arch/arm/mach-tegra/board186.c +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 2016, NVIDIA CORPORATION. - */ - -#include <common.h> -#include <asm/arch/tegra.h> - -int board_early_init_f(void) -{ - return 0; -} - -__weak int tegra_board_init(void) -{ - return 0; -} - -int board_init(void) -{ - return tegra_board_init(); -} - -__weak int tegra_soc_board_init_late(void) -{ - return 0; -} - -int board_late_init(void) -{ - return tegra_soc_board_init_late(); -} diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c index ce1c934695..bbc487aa3b 100644 --- a/arch/arm/mach-tegra/board2.c +++ b/arch/arm/mach-tegra/board2.c @@ -13,6 +13,7 @@ #include <asm/io.h> #include <asm/arch-tegra/ap.h> #include <asm/arch-tegra/board.h> +#include <asm/arch-tegra/cboot.h> #include <asm/arch-tegra/clk_rst.h> #include <asm/arch-tegra/pmc.h> #include <asm/arch-tegra/pmu.h> @@ -51,6 +52,7 @@ __weak void pin_mux_mmc(void) {} __weak void gpio_early_init_uart(void) {} __weak void pin_mux_display(void) {} __weak void start_cpu_fan(void) {} +__weak void cboot_late_init(void) {} #if defined(CONFIG_TEGRA_NAND) __weak void pin_mux_nand(void) @@ -243,6 +245,7 @@ int board_late_init(void) } #endif start_cpu_fan(); + cboot_late_init(); return 0; } @@ -337,6 +340,15 @@ static ulong usable_ram_size_below_4g(void) */ int dram_init_banksize(void) { + int err; + + /* try to compute DRAM bank size based on cboot DTB first */ + err = cboot_dram_init_banksize(); + if (err == 0) + return err; + + /* fall back to default DRAM bank size computation */ + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; gd->bd->bi_dram[0].size = usable_ram_size_below_4g(); @@ -370,5 +382,14 @@ int dram_init_banksize(void) */ ulong board_get_usable_ram_top(ulong total_size) { + ulong ram_top; + + /* try to get top of usable RAM based on cboot DTB first */ + ram_top = cboot_get_usable_ram_top(total_size); + if (ram_top > 0) + return ram_top; + + /* fall back to default usable RAM computation */ + return CONFIG_SYS_SDRAM_BASE + usable_ram_size_below_4g(); } diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_board.c b/arch/arm/mach-tegra/cboot.c index 83c0e931ea..3ebf7b0555 100644 --- a/arch/arm/mach-tegra/tegra186/nvtboot_board.c +++ b/arch/arm/mach-tegra/cboot.c @@ -3,14 +3,182 @@ * Copyright (c) 2016-2018, NVIDIA CORPORATION. */ -#include <stdlib.h> #include <common.h> #include <fdt_support.h> #include <fdtdec.h> +#include <stdlib.h> + +#include <linux/sizes.h> + #include <asm/arch/tegra.h> +#include <asm/arch-tegra/cboot.h> #include <asm/armv8/mmu.h> -extern unsigned long nvtboot_boot_x0; +/* + * Size of a region that's large enough to hold the relocated U-Boot and all + * other allocations made around it (stack, heap, page tables, etc.) + * In practice, running "bdinfo" at the shell prompt, the stack reaches about + * 5MB from the address selected for ram_top as of the time of writing, + * so a 16MB region should be plenty. + */ +#define MIN_USABLE_RAM_SIZE SZ_16M +/* + * The amount of space we expect to require for stack usage. Used to validate + * that all reservations fit into the region selected for the relocation target + */ +#define MIN_USABLE_STACK_SIZE SZ_1M + +DECLARE_GLOBAL_DATA_PTR; + +extern struct mm_region tegra_mem_map[]; + +/* + * These variables are written to before relocation, and hence cannot be + * in.bss, since .bss overlaps the DTB that's appended to the U-Boot binary. + * The section attribute forces this into .data and avoids this issue. This + * also has the nice side-effect of the content being valid after relocation. + */ + +/* The number of valid entries in ram_banks[] */ +static int ram_bank_count __attribute__((section(".data"))); + +/* + * The usable top-of-RAM for U-Boot. This is both: + * a) Below 4GB to avoid issues with peripherals that use 32-bit addressing. + * b) At the end of a region that has enough space to hold the relocated U-Boot + * and all other allocations made around it (stack, heap, page tables, etc.) + */ +static u64 ram_top __attribute__((section(".data"))); +/* The base address of the region of RAM that ends at ram_top */ +static u64 region_base __attribute__((section(".data"))); + +int cboot_dram_init(void) +{ + unsigned int na, ns; + const void *cboot_blob = (void *)cboot_boot_x0; + int node, len, i; + const u32 *prop; + + if (!cboot_blob) + return -EINVAL; + + na = fdtdec_get_uint(cboot_blob, 0, "#address-cells", 2); + ns = fdtdec_get_uint(cboot_blob, 0, "#size-cells", 2); + + node = fdt_path_offset(cboot_blob, "/memory"); + if (node < 0) { + pr_err("Can't find /memory node in cboot DTB"); + hang(); + } + prop = fdt_getprop(cboot_blob, node, "reg", &len); + if (!prop) { + pr_err("Can't find /memory/reg property in cboot DTB"); + hang(); + } + + /* 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 > CONFIG_NR_DRAM_BANKS) + len = CONFIG_NR_DRAM_BANKS; + + /* Parse the /memory node, and save useful entries */ + gd->ram_size = 0; + ram_bank_count = 0; + for (i = 0; i < len; i++) { + u64 bank_start, bank_end, bank_size, usable_bank_size; + + /* Extract raw memory region data from DTB */ + bank_start = fdt_read_number(prop, na); + prop += na; + bank_size = fdt_read_number(prop, ns); + prop += ns; + 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 - 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 = 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(); + } + + return 0; +} + +int cboot_dram_init_banksize(void) +{ + int i; + + if (ram_bank_count == 0) + return -EINVAL; + + if ((gd->start_addr_sp - region_base) < MIN_USABLE_STACK_SIZE) { + pr_err("Reservations exceed chosen region size"); + hang(); + } + + for (i = 0; i < ram_bank_count; i++) { + 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 + gd->pci_ram_top = ram_top; +#endif + + return 0; +} + +ulong cboot_get_usable_ram_top(ulong total_size) +{ + return ram_top; +} /* * The following few functions run late during the boot process and dynamically @@ -23,8 +191,6 @@ extern unsigned long nvtboot_boot_x0; * list of RAM banks into some private data structure before running. */ -extern struct mm_region tegra_mem_map[]; - static char *gen_varname(const char *var, const char *ext) { size_t len_var = strlen(var); @@ -235,7 +401,7 @@ static void set_calculated_env_vars(void) dump_ram_banks(); #endif - reserve_ram(nvtboot_boot_x0, fdt_totalsize(nvtboot_boot_x0)); + reserve_ram(cboot_boot_x0, fdt_totalsize(cboot_boot_x0)); #ifdef DEBUG printf("RAM after reserving cboot DTB:\n"); @@ -262,7 +428,7 @@ static void set_calculated_env_vars(void) debug("%s: var: %s\n", __func__, var); set_calculated_env_var(var); #ifdef DEBUG - printf("RAM banks affter allocating %s:\n", var); + printf("RAM banks after allocating %s:\n", var); dump_ram_banks(); #endif } @@ -274,7 +440,7 @@ static int set_fdt_addr(void) { int ret; - ret = env_set_hex("fdt_addr", nvtboot_boot_x0); + ret = env_set_hex("fdt_addr", cboot_boot_x0); if (ret) { printf("Failed to set fdt_addr to point at DTB: %d\n", ret); return ret; @@ -284,12 +450,12 @@ static int set_fdt_addr(void) } /* - * Attempt to use /chosen/nvidia,ether-mac in the nvtboot DTB to U-Boot's + * Attempt to use /chosen/nvidia,ether-mac in the cboot DTB to U-Boot's * ethaddr environment variable if possible. */ -static int set_ethaddr_from_nvtboot(void) +static int set_ethaddr_from_cboot(void) { - const void *nvtboot_blob = (void *)nvtboot_boot_x0; + const void *cboot_blob = (void *)cboot_boot_x0; int ret, node, len; const u32 *prop; @@ -297,27 +463,27 @@ static int set_ethaddr_from_nvtboot(void) if (env_get("ethaddr")) return 0; - node = fdt_path_offset(nvtboot_blob, "/chosen"); + node = fdt_path_offset(cboot_blob, "/chosen"); if (node < 0) { - printf("Can't find /chosen node in nvtboot DTB\n"); + printf("Can't find /chosen node in cboot DTB\n"); return node; } - prop = fdt_getprop(nvtboot_blob, node, "nvidia,ether-mac", &len); + prop = fdt_getprop(cboot_blob, node, "nvidia,ether-mac", &len); if (!prop) { - printf("Can't find nvidia,ether-mac property in nvtboot DTB\n"); + printf("Can't find nvidia,ether-mac property in cboot DTB\n"); return -ENOENT; } ret = env_set("ethaddr", (void *)prop); if (ret) { - printf("Failed to set ethaddr from nvtboot DTB: %d\n", ret); + printf("Failed to set ethaddr from cboot DTB: %d\n", ret); return ret; } return 0; } -int tegra_soc_board_init_late(void) +int cboot_late_init(void) { set_calculated_env_vars(); /* @@ -326,7 +492,7 @@ int tegra_soc_board_init_late(void) */ set_fdt_addr(); /* Ignore errors here; not all cases care about Ethernet addresses */ - set_ethaddr_from_nvtboot(); + set_ethaddr_from_cboot(); return 0; } diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_ll.S b/arch/arm/mach-tegra/cboot_ll.S index aa7a863d97..4c9ddacc2b 100644 --- a/arch/arm/mach-tegra/tegra186/nvtboot_ll.S +++ b/arch/arm/mach-tegra/cboot_ll.S @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Save nvtboot-related boot-time CPU state + * Save cboot-related boot-time CPU state * * (C) Copyright 2015-2016 NVIDIA Corporation <www.nvidia.com> */ @@ -9,12 +9,12 @@ #include <linux/linkage.h> .align 8 -.globl nvtboot_boot_x0 -nvtboot_boot_x0: +.globl cboot_boot_x0 +cboot_boot_x0: .dword 0 -ENTRY(save_boot_params) - adr x8, nvtboot_boot_x0 +ENTRY(cboot_save_boot_params) + adr x8, cboot_boot_x0 str x0, [x8] b save_boot_params_ret -ENDPROC(save_boot_params) +ENDPROC(cboot_save_boot_params) diff --git a/arch/arm/mach-tegra/tegra186/Makefile b/arch/arm/mach-tegra/tegra186/Makefile index 56f3378ece..3a24050277 100644 --- a/arch/arm/mach-tegra/tegra186/Makefile +++ b/arch/arm/mach-tegra/tegra186/Makefile @@ -2,8 +2,4 @@ # # SPDX-License-Identifier: GPL-2.0 -obj-y += ../board186.o obj-y += cache.o -obj-y += nvtboot_board.o -obj-y += nvtboot_ll.o -obj-y += nvtboot_mem.o diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_mem.c b/arch/arm/mach-tegra/tegra186/nvtboot_mem.c deleted file mode 100644 index 62142821a5..0000000000 --- a/arch/arm/mach-tegra/tegra186/nvtboot_mem.c +++ /dev/null @@ -1,172 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 2016-2018, NVIDIA CORPORATION. - */ - -#include <common.h> -#include <fdt_support.h> -#include <fdtdec.h> -#include <linux/sizes.h> -#include <asm/arch/tegra.h> -#include <asm/armv8/mmu.h> - -/* - * Size of a region that's large enough to hold the relocated U-Boot and all - * other allocations made around it (stack, heap, page tables, etc.) - * In practice, running "bdinfo" at the shell prompt, the stack reaches about - * 5MB from the address selected for ram_top as of the time of writing, - * so a 16MB region should be plenty. - */ -#define MIN_USABLE_RAM_SIZE SZ_16M -/* - * The amount of space we expect to require for stack usage. Used to validate - * that all reservations fit into the region selected for the relocation target - */ -#define MIN_USABLE_STACK_SIZE SZ_1M - -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 - * in.bss, since .bss overlaps the DTB that's appended to the U-Boot binary. - * The section attribute forces this into .data and avoids this issue. This - * also has the nice side-effect of the content being valid after relocation. - */ - -/* The number of valid entries in ram_banks[] */ -static int ram_bank_count __attribute__((section(".data"))); - -/* - * The usable top-of-RAM for U-Boot. This is both: - * a) Below 4GB to avoid issues with peripherals that use 32-bit addressing. - * b) At the end of a region that has enough space to hold the relocated U-Boot - * and all other allocations made around it (stack, heap, page tables, etc.) - */ -static u64 ram_top __attribute__((section(".data"))); -/* The base address of the region of RAM that ends at ram_top */ -static u64 region_base __attribute__((section(".data"))); - -int dram_init(void) -{ - unsigned int na, ns; - const void *nvtboot_blob = (void *)nvtboot_boot_x0; - int node, len, i; - const u32 *prop; - - na = fdtdec_get_uint(nvtboot_blob, 0, "#address-cells", 2); - ns = fdtdec_get_uint(nvtboot_blob, 0, "#size-cells", 2); - - node = fdt_path_offset(nvtboot_blob, "/memory"); - if (node < 0) { - pr_err("Can't find /memory node in nvtboot DTB"); - hang(); - } - prop = fdt_getprop(nvtboot_blob, node, "reg", &len); - if (!prop) { - pr_err("Can't find /memory/reg property in nvtboot DTB"); - hang(); - } - - /* 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 > CONFIG_NR_DRAM_BANKS) - len = CONFIG_NR_DRAM_BANKS; - - /* Parse the /memory node, and save useful entries */ - gd->ram_size = 0; - ram_bank_count = 0; - for (i = 0; i < len; i++) { - u64 bank_start, bank_end, bank_size, usable_bank_size; - - /* Extract raw memory region data from DTB */ - bank_start = fdt_read_number(prop, na); - prop += na; - bank_size = fdt_read_number(prop, ns); - prop += ns; - 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 - 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 = 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(); - } - - return 0; -} - -int dram_init_banksize(void) -{ - int i; - - if ((gd->start_addr_sp - region_base) < MIN_USABLE_STACK_SIZE) { - pr_err("Reservations exceed chosen region size"); - hang(); - } - - for (i = 0; i < ram_bank_count; i++) { - 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 - gd->pci_ram_top = ram_top; -#endif - - return 0; -} - -ulong board_get_usable_ram_top(ulong total_size) -{ - return ram_top; -} |