ARM: tegra: Unify Tegra186 builds
Tegra186 build are currently dealt with in very special ways, which is
because Tegra186 is fundamentally different in many respects. It is no
longer necessary to do many of the low-level programming because early
boot firmware will already have taken care of it.
Unfortunately, separating Tegra186 builds from the rest in this way
makes it difficult to share code with prior generations of Tegra. With
all of the low-level programming code behind Kconfig guards, the build
for Tegra186 can again be unified.
As a side-effect, and partial reason for this change, other Tegra SoC
generations can now make use of the code that deals with taking over a
boot from earlier bootloaders. This used to be nvtboot, but has been
replaced by cboot nowadays. Rename the files and functions related to
this to avoid confusion. The implemented protocols are unchanged.
Signed-off-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Tom Warren <twarren@nvidia.com>
diff --git a/arch/arm/include/asm/arch-tegra/cboot.h b/arch/arm/include/asm/arch-tegra/cboot.h
new file mode 100644
index 0000000..b3441ec
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra/cboot.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2019 NVIDIA Corporation. All rights reserved.
+ */
+
+#ifndef _TEGRA_CBOOT_H_
+#define _TEGRA_CBOOT_H_
+
+#ifdef CONFIG_ARM64
+extern unsigned long cboot_boot_x0;
+
+void cboot_save_boot_params(unsigned long x0, unsigned long x1,
+ unsigned long x2, unsigned long x3);
+int cboot_dram_init(void);
+int cboot_dram_init_banksize(void);
+ulong cboot_get_usable_ram_top(ulong total_size);
+#else
+static inline void cboot_save_boot_params(unsigned long x0, unsigned long x1,
+ unsigned long x2, unsigned long x3)
+{
+}
+
+static inline int cboot_dram_init(void)
+{
+ return -ENOSYS;
+}
+
+static inline int cboot_dram_init_banksize(void)
+{
+ return -ENOSYS;
+}
+
+static inline ulong cboot_get_usable_ram_top(ulong total_size)
+{
+ return 0;
+}
+#endif
+
+#endif
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index f8bc65a..41ba674 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_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 42baf97..abcae15 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 @@
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 @@
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 80b5570..0000000
--- 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 ce1c934..bbc487a 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 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 @@
}
#endif
start_cpu_fan();
+ cboot_late_init();
return 0;
}
@@ -337,6 +340,15 @@
*/
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 @@
*/
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/cboot.c b/arch/arm/mach-tegra/cboot.c
new file mode 100644
index 0000000..3ebf7b0
--- /dev/null
+++ b/arch/arm/mach-tegra/cboot.c
@@ -0,0 +1,498 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2016-2018, NVIDIA CORPORATION.
+ */
+
+#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>
+
+/*
+ * 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
+ * calculate the load address of various binaries. To keep track of multiple
+ * allocations, some writable list of RAM banks must be used. tegra_mem_map[]
+ * is used for this purpose to avoid making yet another copy of the list of RAM
+ * banks. This is safe because tegra_mem_map[] is only used once during very
+ * early boot to create U-Boot's page tables, long before this code runs. If
+ * this assumption becomes invalid later, we can just fix the code to copy the
+ * list of RAM banks into some private data structure before running.
+ */
+
+static char *gen_varname(const char *var, const char *ext)
+{
+ size_t len_var = strlen(var);
+ size_t len_ext = strlen(ext);
+ size_t len = len_var + len_ext + 1;
+ char *varext = malloc(len);
+
+ if (!varext)
+ return 0;
+ strcpy(varext, var);
+ strcpy(varext + len_var, ext);
+ return varext;
+}
+
+static void mark_ram_allocated(int bank, u64 allocated_start, u64 allocated_end)
+{
+ u64 bank_start = tegra_mem_map[bank].virt;
+ u64 bank_size = tegra_mem_map[bank].size;
+ u64 bank_end = bank_start + bank_size;
+ bool keep_front = allocated_start != bank_start;
+ bool keep_tail = allocated_end != bank_end;
+
+ if (keep_front && keep_tail) {
+ /*
+ * There are CONFIG_NR_DRAM_BANKS DRAM entries in the array,
+ * starting at index 1 (index 0 is MMIO). So, we are at DRAM
+ * entry "bank" not "bank - 1" as for a typical 0-base array.
+ * The number of remaining DRAM entries is therefore
+ * "CONFIG_NR_DRAM_BANKS - bank". We want to duplicate the
+ * current entry and shift up the remaining entries, dropping
+ * the last one. Thus, we must copy one fewer entry than the
+ * number remaining.
+ */
+ memmove(&tegra_mem_map[bank + 1], &tegra_mem_map[bank],
+ CONFIG_NR_DRAM_BANKS - bank - 1);
+ tegra_mem_map[bank].size = allocated_start - bank_start;
+ bank++;
+ tegra_mem_map[bank].virt = allocated_end;
+ tegra_mem_map[bank].phys = allocated_end;
+ tegra_mem_map[bank].size = bank_end - allocated_end;
+ } else if (keep_front) {
+ tegra_mem_map[bank].size = allocated_start - bank_start;
+ } else if (keep_tail) {
+ tegra_mem_map[bank].virt = allocated_end;
+ tegra_mem_map[bank].phys = allocated_end;
+ tegra_mem_map[bank].size = bank_end - allocated_end;
+ } else {
+ /*
+ * We could move all subsequent banks down in the array but
+ * that's not necessary for subsequent allocations to work, so
+ * we skip doing so.
+ */
+ tegra_mem_map[bank].size = 0;
+ }
+}
+
+static void reserve_ram(u64 start, u64 size)
+{
+ int bank;
+ u64 end = start + size;
+
+ for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
+ u64 bank_start = tegra_mem_map[bank].virt;
+ u64 bank_size = tegra_mem_map[bank].size;
+ u64 bank_end = bank_start + bank_size;
+
+ if (end <= bank_start || start > bank_end)
+ continue;
+ mark_ram_allocated(bank, start, end);
+ break;
+ }
+}
+
+static u64 alloc_ram(u64 size, u64 align, u64 offset)
+{
+ int bank;
+
+ for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
+ u64 bank_start = tegra_mem_map[bank].virt;
+ u64 bank_size = tegra_mem_map[bank].size;
+ u64 bank_end = bank_start + bank_size;
+ u64 allocated = ROUND(bank_start, align) + offset;
+ u64 allocated_end = allocated + size;
+
+ if (allocated_end > bank_end)
+ continue;
+ mark_ram_allocated(bank, allocated, allocated_end);
+ return allocated;
+ }
+ return 0;
+}
+
+static void set_calculated_aliases(char *aliases, u64 address)
+{
+ char *tmp, *alias;
+ int err;
+
+ aliases = strdup(aliases);
+ if (!aliases) {
+ pr_err("strdup(aliases) failed");
+ return;
+ }
+
+ tmp = aliases;
+ while (true) {
+ alias = strsep(&tmp, " ");
+ if (!alias)
+ break;
+ debug("%s: alias: %s\n", __func__, alias);
+ err = env_set_hex(alias, address);
+ if (err)
+ pr_err("Could not set %s\n", alias);
+ }
+
+ free(aliases);
+}
+
+static void set_calculated_env_var(const char *var)
+{
+ char *var_size;
+ char *var_align;
+ char *var_offset;
+ char *var_aliases;
+ u64 size;
+ u64 align;
+ u64 offset;
+ char *aliases;
+ u64 address;
+ int err;
+
+ var_size = gen_varname(var, "_size");
+ if (!var_size)
+ return;
+ var_align = gen_varname(var, "_align");
+ if (!var_align)
+ goto out_free_var_size;
+ var_offset = gen_varname(var, "_offset");
+ if (!var_offset)
+ goto out_free_var_align;
+ var_aliases = gen_varname(var, "_aliases");
+ if (!var_aliases)
+ goto out_free_var_offset;
+
+ size = env_get_hex(var_size, 0);
+ if (!size) {
+ pr_err("%s not set or zero\n", var_size);
+ goto out_free_var_aliases;
+ }
+ align = env_get_hex(var_align, 1);
+ /* Handle extant variables, but with a value of 0 */
+ if (!align)
+ align = 1;
+ offset = env_get_hex(var_offset, 0);
+ aliases = env_get(var_aliases);
+
+ debug("%s: Calc var %s; size=%llx, align=%llx, offset=%llx\n",
+ __func__, var, size, align, offset);
+ if (aliases)
+ debug("%s: Aliases: %s\n", __func__, aliases);
+
+ address = alloc_ram(size, align, offset);
+ if (!address) {
+ pr_err("Could not allocate %s\n", var);
+ goto out_free_var_aliases;
+ }
+ debug("%s: Address %llx\n", __func__, address);
+
+ err = env_set_hex(var, address);
+ if (err)
+ pr_err("Could not set %s\n", var);
+ if (aliases)
+ set_calculated_aliases(aliases, address);
+
+out_free_var_aliases:
+ free(var_aliases);
+out_free_var_offset:
+ free(var_offset);
+out_free_var_align:
+ free(var_align);
+out_free_var_size:
+ free(var_size);
+}
+
+#ifdef DEBUG
+static void dump_ram_banks(void)
+{
+ int bank;
+
+ for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
+ u64 bank_start = tegra_mem_map[bank].virt;
+ u64 bank_size = tegra_mem_map[bank].size;
+ u64 bank_end = bank_start + bank_size;
+
+ if (!bank_size)
+ continue;
+ printf("%d: %010llx..%010llx (+%010llx)\n", bank - 1,
+ bank_start, bank_end, bank_size);
+ }
+}
+#endif
+
+static void set_calculated_env_vars(void)
+{
+ char *vars, *tmp, *var;
+
+#ifdef DEBUG
+ printf("RAM banks before any calculated env. var.s:\n");
+ dump_ram_banks();
+#endif
+
+ reserve_ram(cboot_boot_x0, fdt_totalsize(cboot_boot_x0));
+
+#ifdef DEBUG
+ printf("RAM after reserving cboot DTB:\n");
+ dump_ram_banks();
+#endif
+
+ vars = env_get("calculated_vars");
+ if (!vars) {
+ debug("%s: No env var calculated_vars\n", __func__);
+ return;
+ }
+
+ vars = strdup(vars);
+ if (!vars) {
+ pr_err("strdup(calculated_vars) failed");
+ return;
+ }
+
+ tmp = vars;
+ while (true) {
+ var = strsep(&tmp, " ");
+ if (!var)
+ break;
+ debug("%s: var: %s\n", __func__, var);
+ set_calculated_env_var(var);
+#ifdef DEBUG
+ printf("RAM banks after allocating %s:\n", var);
+ dump_ram_banks();
+#endif
+ }
+
+ free(vars);
+}
+
+static int set_fdt_addr(void)
+{
+ int ret;
+
+ 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;
+ }
+
+ return 0;
+}
+
+/*
+ * 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_cboot(void)
+{
+ const void *cboot_blob = (void *)cboot_boot_x0;
+ int ret, node, len;
+ const u32 *prop;
+
+ /* Already a valid address in the environment? If so, keep it */
+ if (env_get("ethaddr"))
+ return 0;
+
+ node = fdt_path_offset(cboot_blob, "/chosen");
+ if (node < 0) {
+ printf("Can't find /chosen node in cboot DTB\n");
+ return node;
+ }
+ prop = fdt_getprop(cboot_blob, node, "nvidia,ether-mac", &len);
+ if (!prop) {
+ 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 cboot DTB: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+int cboot_late_init(void)
+{
+ set_calculated_env_vars();
+ /*
+ * Ignore errors here; the value may not be used depending on
+ * extlinux.conf or boot script content.
+ */
+ set_fdt_addr();
+ /* Ignore errors here; not all cases care about Ethernet addresses */
+ set_ethaddr_from_cboot();
+
+ return 0;
+}
diff --git a/arch/arm/mach-tegra/cboot_ll.S b/arch/arm/mach-tegra/cboot_ll.S
new file mode 100644
index 0000000..4c9ddac
--- /dev/null
+++ b/arch/arm/mach-tegra/cboot_ll.S
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Save cboot-related boot-time CPU state
+ *
+ * (C) Copyright 2015-2016 NVIDIA Corporation <www.nvidia.com>
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+
+.align 8
+.globl cboot_boot_x0
+cboot_boot_x0:
+ .dword 0
+
+ENTRY(cboot_save_boot_params)
+ adr x8, cboot_boot_x0
+ str x0, [x8]
+ b save_boot_params_ret
+ENDPROC(cboot_save_boot_params)
diff --git a/arch/arm/mach-tegra/tegra186/Makefile b/arch/arm/mach-tegra/tegra186/Makefile
index 56f3378..3a24050 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_board.c b/arch/arm/mach-tegra/tegra186/nvtboot_board.c
deleted file mode 100644
index 83c0e93..0000000
--- a/arch/arm/mach-tegra/tegra186/nvtboot_board.c
+++ /dev/null
@@ -1,332 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 2016-2018, NVIDIA CORPORATION.
- */
-
-#include <stdlib.h>
-#include <common.h>
-#include <fdt_support.h>
-#include <fdtdec.h>
-#include <asm/arch/tegra.h>
-#include <asm/armv8/mmu.h>
-
-extern unsigned long nvtboot_boot_x0;
-
-/*
- * The following few functions run late during the boot process and dynamically
- * calculate the load address of various binaries. To keep track of multiple
- * allocations, some writable list of RAM banks must be used. tegra_mem_map[]
- * is used for this purpose to avoid making yet another copy of the list of RAM
- * banks. This is safe because tegra_mem_map[] is only used once during very
- * early boot to create U-Boot's page tables, long before this code runs. If
- * this assumption becomes invalid later, we can just fix the code to copy the
- * 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);
- size_t len_ext = strlen(ext);
- size_t len = len_var + len_ext + 1;
- char *varext = malloc(len);
-
- if (!varext)
- return 0;
- strcpy(varext, var);
- strcpy(varext + len_var, ext);
- return varext;
-}
-
-static void mark_ram_allocated(int bank, u64 allocated_start, u64 allocated_end)
-{
- u64 bank_start = tegra_mem_map[bank].virt;
- u64 bank_size = tegra_mem_map[bank].size;
- u64 bank_end = bank_start + bank_size;
- bool keep_front = allocated_start != bank_start;
- bool keep_tail = allocated_end != bank_end;
-
- if (keep_front && keep_tail) {
- /*
- * There are CONFIG_NR_DRAM_BANKS DRAM entries in the array,
- * starting at index 1 (index 0 is MMIO). So, we are at DRAM
- * entry "bank" not "bank - 1" as for a typical 0-base array.
- * The number of remaining DRAM entries is therefore
- * "CONFIG_NR_DRAM_BANKS - bank". We want to duplicate the
- * current entry and shift up the remaining entries, dropping
- * the last one. Thus, we must copy one fewer entry than the
- * number remaining.
- */
- memmove(&tegra_mem_map[bank + 1], &tegra_mem_map[bank],
- CONFIG_NR_DRAM_BANKS - bank - 1);
- tegra_mem_map[bank].size = allocated_start - bank_start;
- bank++;
- tegra_mem_map[bank].virt = allocated_end;
- tegra_mem_map[bank].phys = allocated_end;
- tegra_mem_map[bank].size = bank_end - allocated_end;
- } else if (keep_front) {
- tegra_mem_map[bank].size = allocated_start - bank_start;
- } else if (keep_tail) {
- tegra_mem_map[bank].virt = allocated_end;
- tegra_mem_map[bank].phys = allocated_end;
- tegra_mem_map[bank].size = bank_end - allocated_end;
- } else {
- /*
- * We could move all subsequent banks down in the array but
- * that's not necessary for subsequent allocations to work, so
- * we skip doing so.
- */
- tegra_mem_map[bank].size = 0;
- }
-}
-
-static void reserve_ram(u64 start, u64 size)
-{
- int bank;
- u64 end = start + size;
-
- for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
- u64 bank_start = tegra_mem_map[bank].virt;
- u64 bank_size = tegra_mem_map[bank].size;
- u64 bank_end = bank_start + bank_size;
-
- if (end <= bank_start || start > bank_end)
- continue;
- mark_ram_allocated(bank, start, end);
- break;
- }
-}
-
-static u64 alloc_ram(u64 size, u64 align, u64 offset)
-{
- int bank;
-
- for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
- u64 bank_start = tegra_mem_map[bank].virt;
- u64 bank_size = tegra_mem_map[bank].size;
- u64 bank_end = bank_start + bank_size;
- u64 allocated = ROUND(bank_start, align) + offset;
- u64 allocated_end = allocated + size;
-
- if (allocated_end > bank_end)
- continue;
- mark_ram_allocated(bank, allocated, allocated_end);
- return allocated;
- }
- return 0;
-}
-
-static void set_calculated_aliases(char *aliases, u64 address)
-{
- char *tmp, *alias;
- int err;
-
- aliases = strdup(aliases);
- if (!aliases) {
- pr_err("strdup(aliases) failed");
- return;
- }
-
- tmp = aliases;
- while (true) {
- alias = strsep(&tmp, " ");
- if (!alias)
- break;
- debug("%s: alias: %s\n", __func__, alias);
- err = env_set_hex(alias, address);
- if (err)
- pr_err("Could not set %s\n", alias);
- }
-
- free(aliases);
-}
-
-static void set_calculated_env_var(const char *var)
-{
- char *var_size;
- char *var_align;
- char *var_offset;
- char *var_aliases;
- u64 size;
- u64 align;
- u64 offset;
- char *aliases;
- u64 address;
- int err;
-
- var_size = gen_varname(var, "_size");
- if (!var_size)
- return;
- var_align = gen_varname(var, "_align");
- if (!var_align)
- goto out_free_var_size;
- var_offset = gen_varname(var, "_offset");
- if (!var_offset)
- goto out_free_var_align;
- var_aliases = gen_varname(var, "_aliases");
- if (!var_aliases)
- goto out_free_var_offset;
-
- size = env_get_hex(var_size, 0);
- if (!size) {
- pr_err("%s not set or zero\n", var_size);
- goto out_free_var_aliases;
- }
- align = env_get_hex(var_align, 1);
- /* Handle extant variables, but with a value of 0 */
- if (!align)
- align = 1;
- offset = env_get_hex(var_offset, 0);
- aliases = env_get(var_aliases);
-
- debug("%s: Calc var %s; size=%llx, align=%llx, offset=%llx\n",
- __func__, var, size, align, offset);
- if (aliases)
- debug("%s: Aliases: %s\n", __func__, aliases);
-
- address = alloc_ram(size, align, offset);
- if (!address) {
- pr_err("Could not allocate %s\n", var);
- goto out_free_var_aliases;
- }
- debug("%s: Address %llx\n", __func__, address);
-
- err = env_set_hex(var, address);
- if (err)
- pr_err("Could not set %s\n", var);
- if (aliases)
- set_calculated_aliases(aliases, address);
-
-out_free_var_aliases:
- free(var_aliases);
-out_free_var_offset:
- free(var_offset);
-out_free_var_align:
- free(var_align);
-out_free_var_size:
- free(var_size);
-}
-
-#ifdef DEBUG
-static void dump_ram_banks(void)
-{
- int bank;
-
- for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
- u64 bank_start = tegra_mem_map[bank].virt;
- u64 bank_size = tegra_mem_map[bank].size;
- u64 bank_end = bank_start + bank_size;
-
- if (!bank_size)
- continue;
- printf("%d: %010llx..%010llx (+%010llx)\n", bank - 1,
- bank_start, bank_end, bank_size);
- }
-}
-#endif
-
-static void set_calculated_env_vars(void)
-{
- char *vars, *tmp, *var;
-
-#ifdef DEBUG
- printf("RAM banks before any calculated env. var.s:\n");
- dump_ram_banks();
-#endif
-
- reserve_ram(nvtboot_boot_x0, fdt_totalsize(nvtboot_boot_x0));
-
-#ifdef DEBUG
- printf("RAM after reserving cboot DTB:\n");
- dump_ram_banks();
-#endif
-
- vars = env_get("calculated_vars");
- if (!vars) {
- debug("%s: No env var calculated_vars\n", __func__);
- return;
- }
-
- vars = strdup(vars);
- if (!vars) {
- pr_err("strdup(calculated_vars) failed");
- return;
- }
-
- tmp = vars;
- while (true) {
- var = strsep(&tmp, " ");
- if (!var)
- break;
- debug("%s: var: %s\n", __func__, var);
- set_calculated_env_var(var);
-#ifdef DEBUG
- printf("RAM banks affter allocating %s:\n", var);
- dump_ram_banks();
-#endif
- }
-
- free(vars);
-}
-
-static int set_fdt_addr(void)
-{
- int ret;
-
- ret = env_set_hex("fdt_addr", nvtboot_boot_x0);
- if (ret) {
- printf("Failed to set fdt_addr to point at DTB: %d\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-/*
- * Attempt to use /chosen/nvidia,ether-mac in the nvtboot DTB to U-Boot's
- * ethaddr environment variable if possible.
- */
-static int set_ethaddr_from_nvtboot(void)
-{
- const void *nvtboot_blob = (void *)nvtboot_boot_x0;
- int ret, node, len;
- const u32 *prop;
-
- /* Already a valid address in the environment? If so, keep it */
- if (env_get("ethaddr"))
- return 0;
-
- node = fdt_path_offset(nvtboot_blob, "/chosen");
- if (node < 0) {
- printf("Can't find /chosen node in nvtboot DTB\n");
- return node;
- }
- prop = fdt_getprop(nvtboot_blob, node, "nvidia,ether-mac", &len);
- if (!prop) {
- printf("Can't find nvidia,ether-mac property in nvtboot DTB\n");
- return -ENOENT;
- }
-
- ret = env_set("ethaddr", (void *)prop);
- if (ret) {
- printf("Failed to set ethaddr from nvtboot DTB: %d\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-int tegra_soc_board_init_late(void)
-{
- set_calculated_env_vars();
- /*
- * Ignore errors here; the value may not be used depending on
- * extlinux.conf or boot script content.
- */
- set_fdt_addr();
- /* Ignore errors here; not all cases care about Ethernet addresses */
- set_ethaddr_from_nvtboot();
-
- return 0;
-}
diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_ll.S b/arch/arm/mach-tegra/tegra186/nvtboot_ll.S
deleted file mode 100644
index aa7a863..0000000
--- a/arch/arm/mach-tegra/tegra186/nvtboot_ll.S
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Save nvtboot-related boot-time CPU state
- *
- * (C) Copyright 2015-2016 NVIDIA Corporation <www.nvidia.com>
- */
-
-#include <config.h>
-#include <linux/linkage.h>
-
-.align 8
-.globl nvtboot_boot_x0
-nvtboot_boot_x0:
- .dword 0
-
-ENTRY(save_boot_params)
- adr x8, nvtboot_boot_x0
- str x0, [x8]
- b save_boot_params_ret
-ENDPROC(save_boot_params)
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 6214282..0000000
--- 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;
-}
diff --git a/board/nvidia/p2771-0000/p2771-0000.c b/board/nvidia/p2771-0000/p2771-0000.c
index 496e8a0..6f88010 100644
--- a/board/nvidia/p2771-0000/p2771-0000.c
+++ b/board/nvidia/p2771-0000/p2771-0000.c
@@ -7,7 +7,7 @@
#include <i2c.h>
#include "../p2571/max77620_init.h"
-int tegra_board_init(void)
+void pin_mux_mmc(void)
{
struct udevice *dev;
uchar val;
@@ -18,19 +18,18 @@
ret = i2c_get_chip_for_busnum(0, MAX77620_I2C_ADDR_7BIT, 1, &dev);
if (ret) {
printf("%s: Cannot find MAX77620 I2C chip\n", __func__);
- return ret;
+ return;
}
/* 0xF2 for 3.3v, enabled: bit7:6 = 11 = enable, bit5:0 = voltage */
val = 0xF2;
ret = dm_i2c_write(dev, MAX77620_CNFG1_L3_REG, &val, 1);
if (ret) {
printf("i2c_write 0 0x3c 0x27 failed: %d\n", ret);
- return ret;
+ return;
}
-
- return 0;
}
+#ifdef CONFIG_PCI_TEGRA
int tegra_pcie_board_init(void)
{
struct udevice *dev;
@@ -52,3 +51,4 @@
return 0;
}
+#endif