--- /dev/null
+/* 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
# (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
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
#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>
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
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();
+++ /dev/null
-// 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();
-}
#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>
__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)
}
#endif
start_cpu_fan();
+ cboot_late_init();
return 0;
}
*/
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();
*/
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();
}
* 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
* 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);
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");
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
}
{
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;
}
/*
- * 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;
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();
/*
*/
set_fdt_addr();
/* Ignore errors here; not all cases care about Ethernet addresses */
- set_ethaddr_from_nvtboot();
+ set_ethaddr_from_cboot();
return 0;
}
/* 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>
*/
#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)
#
# 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
+++ /dev/null
-// 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;
-}
#include <i2c.h>
#include "../p2571/max77620_init.h"
-int tegra_board_init(void)
+void pin_mux_mmc(void)
{
struct udevice *dev;
uchar val;
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;
return 0;
}
+#endif