/* * (C) Copyright 2010,2011,2015,2017,2019 * NVIDIA Corporation * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_TEGRA_CLOCK_SCALING #include #endif #include #ifdef CONFIG_USB_EHCI_TEGRA #include #endif #ifdef CONFIG_TEGRA_MMC #include #include #endif #include #include #include #include #include "emc.h" #ifdef CONFIG_TEGRA210 #include "tegra210/cboot.h" #endif DECLARE_GLOBAL_DATA_PTR; #ifdef CONFIG_SPL_BUILD /* TODO(sjg@chromium.org): Remove once SPL supports device tree */ U_BOOT_DEVICE(tegra_gpios) = { "gpio_tegra" }; #endif __weak void pinmux_init(void) {} __weak void pin_mux_usb(void) {} __weak void pin_mux_spi(void) {} __weak void gpio_early_init_uart(void) {} __weak void pin_mux_display(void) {} __weak void start_cpu_fan(void) {} #if defined(CONFIG_TEGRA_NAND) __weak void pin_mux_nand(void) { funcmux_select(PERIPH_ID_NDFLASH, FUNCMUX_DEFAULT); } #endif /* * Routine: power_det_init * Description: turn off power detects */ static void power_det_init(void) { #if defined(CONFIG_TEGRA20) struct pmc_ctlr *const pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; /* turn off power detects */ writel(0, &pmc->pmc_pwr_det_latch); writel(0, &pmc->pmc_pwr_det); #endif } __weak int tegra_board_id(void) { return -1; } #ifdef CONFIG_DISPLAY_BOARDINFO int checkboard(void) { int board_id = tegra_board_id(); printf("Board: %s", CONFIG_TEGRA_BOARD_STRING); if (board_id != -1) printf(", ID: %d\n", board_id); printf("\n"); return 0; } #endif /* CONFIG_DISPLAY_BOARDINFO */ __weak int tegra_lcd_pmic_init(int board_it) { return 0; } __weak int nvidia_board_init(void) { return 0; } /* * Routine: board_init * Description: Early hardware init. */ int board_init(void) { __maybe_unused int err; __maybe_unused int board_id; /* Do clocks and UART first so that printf() works */ clock_init(); clock_verify(); tegra_gpu_config(); #ifdef CONFIG_TEGRA_SPI pin_mux_spi(); #endif /* Init is handled automatically in the driver-model case */ #if defined(CONFIG_DM_VIDEO) pin_mux_display(); #endif /* boot param addr */ gd->bd->bi_boot_params = (NV_PA_SDRAM_BASE + 0x100); power_det_init(); #ifdef CONFIG_SYS_I2C_TEGRA # ifdef CONFIG_TEGRA_PMU if (pmu_set_nominal()) debug("Failed to select nominal voltages\n"); # ifdef CONFIG_TEGRA_CLOCK_SCALING err = board_emc_init(); if (err) debug("Memory controller init failed: %d\n", err); # endif # endif /* CONFIG_TEGRA_PMU */ #ifdef CONFIG_AS3722_POWER err = as3722_init(NULL); if (err && err != -ENODEV) return err; #endif #endif /* CONFIG_SYS_I2C_TEGRA */ #ifdef CONFIG_USB_EHCI_TEGRA pin_mux_usb(); #endif #if defined(CONFIG_DM_VIDEO) board_id = tegra_board_id(); err = tegra_lcd_pmic_init(board_id); if (err) return err; #endif #ifdef CONFIG_TEGRA_NAND pin_mux_nand(); #endif tegra_xusb_padctl_init(gd->fdt_blob); #ifdef CONFIG_TEGRA_LP0 /* save Sdram params to PMC 2, 4, and 24 for WB0 */ warmboot_save_sdram_params(); /* prepare the WB code to LP0 location */ warmboot_prepare_code(TEGRA_LP0_ADDR, TEGRA_LP0_SIZE); #endif return nvidia_board_init(); } void board_cleanup_before_linux(void) { /* power down UPHY PLL */ tegra_xusb_padctl_exit(); } #ifdef CONFIG_BOARD_EARLY_INIT_F static void __gpio_early_init(void) { } void gpio_early_init(void) __attribute__((weak, alias("__gpio_early_init"))); int board_early_init_f(void) { #if defined(CONFIG_TEGRA_DISCONNECT_UDC_ON_BOOT) #define USBCMD_FS2 (1 << 15) { struct usb_ctlr *usbctlr = (struct usb_ctlr *)0x7d000000; writel(USBCMD_FS2, &usbctlr->usb_cmd); } #endif /* Do any special system timer/TSC setup */ #if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE) if (!tegra_cpu_is_non_secure()) #endif arch_timer_init(); #if defined(CONFIG_DISABLE_SDMMC1_EARLY) /* * Turn off (reset/disable) SDMMC1 on Porg here, before GPIO INIT. * We do this because earlier bootloaders have enabled power to * SDMMC1 on Porg/Nano, and toggling power-gpio (PZ3) in * pinmux_init() results in power being back-driven into the * SD-card and SDMMC1 HW, which is 'bad' as per HW. * * From the HW team: "LDO2 from the PMIC has already been set for 3.3v in * nvtboot/CBoot on Porg (for SD-card boot). So when U-Boot's GPIO_INIT * table sets PZ3 to OUT0 as per the pinmux spreadsheet, it turns off * the loadswitch. When PZ3 is 0 and not driving, essentially the SD card * voltage turns off. Since the SDCard voltage is no longer there, the * SDMMC CLK/DAT lines are backdriving into what essentially is a powered- * off SDCard, that's why the voltage drops from 3.3V to 1.6V-ish" * * Note that this can probably be removed when we change over to storing * all BL components on QSPI on Porg/Nano, and U-Boot then becomes the * first one to turn on SDMMC1 power. Another fix would be to have CBoot * disable power/gate SDMMC1 off before handing off to U-Boot/kernel. */ reset_set_enable(PERIPH_ID_SDMMC1, 1); clock_set_enable(PERIPH_ID_SDMMC1, 0); #endif /* CONFIG_DISABLE_SDMMC1_EARLY */ pinmux_init(); board_init_uart_f(); /* Initialize periph GPIOs */ gpio_early_init(); gpio_early_init_uart(); return 0; } #endif /* EARLY_INIT */ int board_late_init(void) { #if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE) if (tegra_cpu_is_non_secure()) { printf("CPU is in NS mode\n"); setenv("cpu_ns_mode", "1"); } else { setenv("cpu_ns_mode", ""); } #endif start_cpu_fan(); #if defined(CONFIG_TEGRA210) cboot_init_late(); #endif return 0; } #if defined(CONFIG_TEGRA_MMC) __weak void pin_mux_mmc(void) { } /* this is a weak define that we are overriding */ int board_mmc_init(bd_t *bd) { debug("%s called\n", __func__); /* Enable muxes, etc. for SDMMC controllers */ pin_mux_mmc(); debug("%s: init MMC\n", __func__); tegra_mmc_init(); return 0; } void pad_init_mmc(struct mmc_host *host) { #if defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA210) enum periph_id id = host->mmc_id; u32 val; u16 clk_con; int timeout; debug("%s: sdmmc address = %p, id = %d\n", __func__, host->reg, id); /* Set the pad drive strength for SDMMC1 or 3 only */ if (id != PERIPH_ID_SDMMC1 && id != PERIPH_ID_SDMMC3) { debug("%s: settings are only valid for SDMMC1/SDMMC3!\n", __func__); return; } val = readl(&host->reg->sdmemcmppadctl); val &= 0xFFFFFFF0; val |= MEMCOMP_PADCTRL_VREF; writel(val, &host->reg->sdmemcmppadctl); debug("%s: SD_MEM_COMP_PAD_CTL = 0x%08X\n", __func__, val); /* Disable SD Clock Enable before running auto-cal as per TRM */ clk_con = readw(&host->reg->clkcon); debug("%s: CLOCK_CONTROL = 0x%04X\n", __func__, clk_con); clk_con &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; writew(clk_con, &host->reg->clkcon); val = readl(&host->reg->autocalcfg); val &= 0xFFFF0000; val |= AUTO_CAL_PU_OFFSET | AUTO_CAL_PD_OFFSET; writel(val, &host->reg->autocalcfg); val |= AUTO_CAL_START | AUTO_CAL_ENABLE; writel(val, &host->reg->autocalcfg); debug("%s: AUTO_CAL_CFG = 0x%08X\n", __func__, val); udelay(1); timeout = 100; /* 10 mSec max (100*100uS) */ do { val = readl(&host->reg->autocalsts); udelay(100); } while ((val & AUTO_CAL_ACTIVE) && --timeout); val = readl(&host->reg->autocalsts); debug("%s: Final AUTO_CAL_STATUS = 0x%08X, timeout = %d\n", __func__, val, timeout); /* Re-enable SD Clock Enable when auto-cal is done */ clk_con |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; writew(clk_con, &host->reg->clkcon); clk_con = readw(&host->reg->clkcon); debug("%s: final CLOCK_CONTROL = 0x%04X\n", __func__, clk_con); if (timeout == 0) { printf("%s: Warning: Autocal timed out!\n", __func__); /* TBD: Set CFG2TMC_SDMMC1_PAD_CAL_DRV* regs here */ } #if defined(CONFIG_TEGRA210) u32 tap_value, trim_value; /* Set tap/trim values for SDMMC1/3 @ <48MHz here */ val = readl(&host->reg->venspictl); /* aka VENDOR_SYS_SW_CNTL */ val &= IO_TRIM_BYPASS_MASK; if (id == PERIPH_ID_SDMMC1) { tap_value = 4; /* default */ if (val) tap_value = 3; trim_value = 2; } else { /* SDMMC3 */ tap_value = 3; trim_value = 3; } val = readl(&host->reg->venclkctl); val &= ~TRIM_VAL_MASK; val |= (trim_value << TRIM_VAL_SHIFT); val &= ~TAP_VAL_MASK; val |= (tap_value << TAP_VAL_SHIFT); writel(val, &host->reg->venclkctl); debug("%s: VENDOR_CLOCK_CNTRL = 0x%08X\n", __func__, val); #endif /* T210 */ #endif /* T30/T210 */ } #endif /* MMC */ #ifndef CONFIG_TEGRA210 /* * In some SW environments, a memory carve-out exists to house a secure * monitor, a trusted OS, and/or various statically allocated media buffers. * * This carveout exists at the highest possible address that is within a * 32-bit physical address space. * * This function returns the total size of this carve-out. At present, the * returned value is hard-coded for simplicity. In the future, it may be * possible to determine the carve-out size: * - By querying some run-time information source, such as: * - A structure passed to U-Boot by earlier boot software. * - SoC registers. * - A call into the secure monitor. * - In the per-board U-Boot configuration header, based on knowledge of the * SW environment that U-Boot is being built for. * * For now, we support two configurations in U-Boot: * - 32-bit ports without any form of carve-out. * - 64 bit ports which are assumed to use a carve-out of a conservatively * hard-coded size. */ static ulong carveout_size(void) { #ifdef CONFIG_ARM64 return SZ_512M; #else return 0; #endif } /* * Determine the amount of usable RAM below 4GiB, taking into account any * carve-out that may be assigned. */ static ulong usable_ram_size_below_4g(void) { ulong total_size_below_4g; ulong usable_size_below_4g; /* * The total size of RAM below 4GiB is the lesser address of: * (a) 2GiB itself (RAM starts at 2GiB, and 4GiB - 2GiB == 2GiB). * (b) The size RAM physically present in the system. */ if (gd->ram_size < SZ_2G) total_size_below_4g = gd->ram_size; else total_size_below_4g = SZ_2G; /* Calculate usable RAM by subtracting out any carve-out size */ usable_size_below_4g = total_size_below_4g - carveout_size(); return usable_size_below_4g; } /* * Represent all available RAM in either one or two banks. * * The first bank describes any usable RAM below 4GiB. * The second bank describes any RAM above 4GiB. * * This split is driven by the following requirements: * - The NVIDIA L4T kernel requires separate entries in the DT /memory/reg * property for memory below and above the 4GiB boundary. The layout of that * DT property is directly driven by the entries in the U-Boot bank array. * - The potential existence of a carve-out at the end of RAM below 4GiB can * only be represented using multiple banks. * * Explicitly removing the carve-out RAM from the bank entries makes the RAM * layout a bit more obvious, e.g. when running "bdinfo" at the U-Boot * command-line. * * This does mean that the DT U-Boot passes to the Linux kernel will not * include this RAM in /memory/reg at all. An alternative would be to include * all RAM in the U-Boot banks (and hence DT), and add a /memreserve/ node * into DT to stop the kernel from using the RAM. IIUC, I don't /think/ the * Linux kernel will ever need to access any RAM in* the carve-out via a CPU * mapping, so either way is acceptable. * * On 32-bit systems, we never define a bank for RAM above 4GiB, since the * start address of that bank cannot be represented in the 32-bit .size * field. */ void dram_init_banksize(void) { gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; gd->bd->bi_dram[0].size = usable_ram_size_below_4g(); #ifdef CONFIG_PCI gd->pci_ram_top = gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size; #endif #ifdef CONFIG_PHYS_64BIT if (gd->ram_size > SZ_2G) { gd->bd->bi_dram[1].start = 0x100000000; gd->bd->bi_dram[1].size = gd->ram_size - SZ_2G; } else #endif { gd->bd->bi_dram[1].start = 0; gd->bd->bi_dram[1].size = 0; } } /* * Most hardware on 64-bit Tegra is still restricted to DMA to the lower * 32-bits of the physical address space. Cap the maximum usable RAM area * at 4 GiB to avoid DMA buffers from being allocated beyond the 32-bit * boundary that most devices can address. Also, don't let U-Boot use any * carve-out, as mentioned above. * * This function is called before dram_init_banksize(), so we can't simply * return gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size. */ ulong board_get_usable_ram_top(ulong total_size) { return CONFIG_SYS_SDRAM_BASE + usable_ram_size_below_4g(); } #endif