1237c3637SMasahiro Yamada /*
2237c3637SMasahiro Yamada * (C) Copyright 2010,2011
3237c3637SMasahiro Yamada * NVIDIA Corporation <www.nvidia.com>
4237c3637SMasahiro Yamada *
5237c3637SMasahiro Yamada * SPDX-License-Identifier: GPL-2.0+
6237c3637SMasahiro Yamada */
7237c3637SMasahiro Yamada
8237c3637SMasahiro Yamada #include <common.h>
9237c3637SMasahiro Yamada #include <dm.h>
10237c3637SMasahiro Yamada #include <errno.h>
11237c3637SMasahiro Yamada #include <ns16550.h>
1203bc3f18SSimon Glass #include <usb.h>
13237c3637SMasahiro Yamada #include <asm/io.h>
14237c3637SMasahiro Yamada #include <asm/arch-tegra/ap.h>
15237c3637SMasahiro Yamada #include <asm/arch-tegra/board.h>
16237c3637SMasahiro Yamada #include <asm/arch-tegra/clk_rst.h>
17237c3637SMasahiro Yamada #include <asm/arch-tegra/pmc.h>
18237c3637SMasahiro Yamada #include <asm/arch-tegra/sys_proto.h>
19237c3637SMasahiro Yamada #include <asm/arch-tegra/uart.h>
20237c3637SMasahiro Yamada #include <asm/arch-tegra/warmboot.h>
21871d78edSAlexandre Courbot #include <asm/arch-tegra/gpu.h>
2203bc3f18SSimon Glass #include <asm/arch-tegra/usb.h>
2303bc3f18SSimon Glass #include <asm/arch-tegra/xusb-padctl.h>
2403bc3f18SSimon Glass #include <asm/arch/clock.h>
2503bc3f18SSimon Glass #include <asm/arch/funcmux.h>
2603bc3f18SSimon Glass #include <asm/arch/pinmux.h>
2703bc3f18SSimon Glass #include <asm/arch/pmu.h>
2803bc3f18SSimon Glass #include <asm/arch/tegra.h>
29237c3637SMasahiro Yamada #ifdef CONFIG_TEGRA_CLOCK_SCALING
30237c3637SMasahiro Yamada #include <asm/arch/emc.h>
31237c3637SMasahiro Yamada #endif
32237c3637SMasahiro Yamada #include "emc.h"
33237c3637SMasahiro Yamada
34237c3637SMasahiro Yamada DECLARE_GLOBAL_DATA_PTR;
35237c3637SMasahiro Yamada
36237c3637SMasahiro Yamada #ifdef CONFIG_SPL_BUILD
37237c3637SMasahiro Yamada /* TODO(sjg@chromium.org): Remove once SPL supports device tree */
38237c3637SMasahiro Yamada U_BOOT_DEVICE(tegra_gpios) = {
39237c3637SMasahiro Yamada "gpio_tegra"
40237c3637SMasahiro Yamada };
41237c3637SMasahiro Yamada #endif
42237c3637SMasahiro Yamada
pinmux_init(void)43237c3637SMasahiro Yamada __weak void pinmux_init(void) {}
pin_mux_usb(void)44237c3637SMasahiro Yamada __weak void pin_mux_usb(void) {}
pin_mux_spi(void)45237c3637SMasahiro Yamada __weak void pin_mux_spi(void) {}
pin_mux_mmc(void)46c0be77dbSStephen Warren __weak void pin_mux_mmc(void) {}
gpio_early_init_uart(void)47237c3637SMasahiro Yamada __weak void gpio_early_init_uart(void) {}
pin_mux_display(void)48237c3637SMasahiro Yamada __weak void pin_mux_display(void) {}
start_cpu_fan(void)4966999892STom Warren __weak void start_cpu_fan(void) {}
50237c3637SMasahiro Yamada
51237c3637SMasahiro Yamada #if defined(CONFIG_TEGRA_NAND)
pin_mux_nand(void)52237c3637SMasahiro Yamada __weak void pin_mux_nand(void)
53237c3637SMasahiro Yamada {
54237c3637SMasahiro Yamada funcmux_select(PERIPH_ID_NDFLASH, FUNCMUX_DEFAULT);
55237c3637SMasahiro Yamada }
56237c3637SMasahiro Yamada #endif
57237c3637SMasahiro Yamada
58237c3637SMasahiro Yamada /*
59237c3637SMasahiro Yamada * Routine: power_det_init
60237c3637SMasahiro Yamada * Description: turn off power detects
61237c3637SMasahiro Yamada */
power_det_init(void)62237c3637SMasahiro Yamada static void power_det_init(void)
63237c3637SMasahiro Yamada {
64237c3637SMasahiro Yamada #if defined(CONFIG_TEGRA20)
65237c3637SMasahiro Yamada struct pmc_ctlr *const pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
66237c3637SMasahiro Yamada
67237c3637SMasahiro Yamada /* turn off power detects */
68237c3637SMasahiro Yamada writel(0, &pmc->pmc_pwr_det_latch);
69237c3637SMasahiro Yamada writel(0, &pmc->pmc_pwr_det);
70237c3637SMasahiro Yamada #endif
71237c3637SMasahiro Yamada }
72237c3637SMasahiro Yamada
tegra_board_id(void)73237c3637SMasahiro Yamada __weak int tegra_board_id(void)
74237c3637SMasahiro Yamada {
75237c3637SMasahiro Yamada return -1;
76237c3637SMasahiro Yamada }
77237c3637SMasahiro Yamada
78237c3637SMasahiro Yamada #ifdef CONFIG_DISPLAY_BOARDINFO
checkboard(void)79237c3637SMasahiro Yamada int checkboard(void)
80237c3637SMasahiro Yamada {
81237c3637SMasahiro Yamada int board_id = tegra_board_id();
82237c3637SMasahiro Yamada
83237c3637SMasahiro Yamada printf("Board: %s", CONFIG_TEGRA_BOARD_STRING);
84237c3637SMasahiro Yamada if (board_id != -1)
85237c3637SMasahiro Yamada printf(", ID: %d\n", board_id);
86237c3637SMasahiro Yamada printf("\n");
87237c3637SMasahiro Yamada
88237c3637SMasahiro Yamada return 0;
89237c3637SMasahiro Yamada }
90237c3637SMasahiro Yamada #endif /* CONFIG_DISPLAY_BOARDINFO */
91237c3637SMasahiro Yamada
tegra_lcd_pmic_init(int board_it)92237c3637SMasahiro Yamada __weak int tegra_lcd_pmic_init(int board_it)
93237c3637SMasahiro Yamada {
94237c3637SMasahiro Yamada return 0;
95237c3637SMasahiro Yamada }
96237c3637SMasahiro Yamada
nvidia_board_init(void)97c96d709fSSimon Glass __weak int nvidia_board_init(void)
98c96d709fSSimon Glass {
99c96d709fSSimon Glass return 0;
100c96d709fSSimon Glass }
101c96d709fSSimon Glass
102237c3637SMasahiro Yamada /*
103237c3637SMasahiro Yamada * Routine: board_init
104237c3637SMasahiro Yamada * Description: Early hardware init.
105237c3637SMasahiro Yamada */
board_init(void)106237c3637SMasahiro Yamada int board_init(void)
107237c3637SMasahiro Yamada {
108237c3637SMasahiro Yamada __maybe_unused int err;
109237c3637SMasahiro Yamada __maybe_unused int board_id;
110237c3637SMasahiro Yamada
111237c3637SMasahiro Yamada /* Do clocks and UART first so that printf() works */
112237c3637SMasahiro Yamada clock_init();
113237c3637SMasahiro Yamada clock_verify();
114237c3637SMasahiro Yamada
115eca676bdSAlexandre Courbot tegra_gpu_config();
116871d78edSAlexandre Courbot
117237c3637SMasahiro Yamada #ifdef CONFIG_TEGRA_SPI
118237c3637SMasahiro Yamada pin_mux_spi();
119237c3637SMasahiro Yamada #endif
120237c3637SMasahiro Yamada
1211d2c0506SMasahiro Yamada #ifdef CONFIG_MMC_SDHCI_TEGRA
122c0be77dbSStephen Warren pin_mux_mmc();
123c0be77dbSStephen Warren #endif
124c0be77dbSStephen Warren
1253f2997a4SSimon Glass /* Init is handled automatically in the driver-model case */
126e007633bSSimon Glass #if defined(CONFIG_DM_VIDEO)
127237c3637SMasahiro Yamada pin_mux_display();
128135a87efSSimon Glass #endif
129237c3637SMasahiro Yamada /* boot param addr */
130237c3637SMasahiro Yamada gd->bd->bi_boot_params = (NV_PA_SDRAM_BASE + 0x100);
131237c3637SMasahiro Yamada
132237c3637SMasahiro Yamada power_det_init();
133237c3637SMasahiro Yamada
134237c3637SMasahiro Yamada #ifdef CONFIG_SYS_I2C_TEGRA
135237c3637SMasahiro Yamada # ifdef CONFIG_TEGRA_PMU
136237c3637SMasahiro Yamada if (pmu_set_nominal())
137237c3637SMasahiro Yamada debug("Failed to select nominal voltages\n");
138237c3637SMasahiro Yamada # ifdef CONFIG_TEGRA_CLOCK_SCALING
139237c3637SMasahiro Yamada err = board_emc_init();
140237c3637SMasahiro Yamada if (err)
141237c3637SMasahiro Yamada debug("Memory controller init failed: %d\n", err);
142237c3637SMasahiro Yamada # endif
143237c3637SMasahiro Yamada # endif /* CONFIG_TEGRA_PMU */
144237c3637SMasahiro Yamada #endif /* CONFIG_SYS_I2C_TEGRA */
145237c3637SMasahiro Yamada
146237c3637SMasahiro Yamada #ifdef CONFIG_USB_EHCI_TEGRA
147237c3637SMasahiro Yamada pin_mux_usb();
148534f9d3fSSimon Glass #endif
149237c3637SMasahiro Yamada
150e007633bSSimon Glass #if defined(CONFIG_DM_VIDEO)
151237c3637SMasahiro Yamada board_id = tegra_board_id();
152237c3637SMasahiro Yamada err = tegra_lcd_pmic_init(board_id);
15350d8c4a4SSimon Glass if (err) {
15450d8c4a4SSimon Glass debug("Failed to set up LCD PMIC\n");
155237c3637SMasahiro Yamada return err;
15650d8c4a4SSimon Glass }
157135a87efSSimon Glass #endif
158237c3637SMasahiro Yamada
159237c3637SMasahiro Yamada #ifdef CONFIG_TEGRA_NAND
160237c3637SMasahiro Yamada pin_mux_nand();
161237c3637SMasahiro Yamada #endif
162237c3637SMasahiro Yamada
163be789092SSimon Glass tegra_xusb_padctl_init();
164237c3637SMasahiro Yamada
165237c3637SMasahiro Yamada #ifdef CONFIG_TEGRA_LP0
166237c3637SMasahiro Yamada /* save Sdram params to PMC 2, 4, and 24 for WB0 */
167237c3637SMasahiro Yamada warmboot_save_sdram_params();
168237c3637SMasahiro Yamada
169237c3637SMasahiro Yamada /* prepare the WB code to LP0 location */
170237c3637SMasahiro Yamada warmboot_prepare_code(TEGRA_LP0_ADDR, TEGRA_LP0_SIZE);
171237c3637SMasahiro Yamada #endif
172c96d709fSSimon Glass return nvidia_board_init();
173237c3637SMasahiro Yamada }
174237c3637SMasahiro Yamada
175237c3637SMasahiro Yamada #ifdef CONFIG_BOARD_EARLY_INIT_F
__gpio_early_init(void)176237c3637SMasahiro Yamada static void __gpio_early_init(void)
177237c3637SMasahiro Yamada {
178237c3637SMasahiro Yamada }
179237c3637SMasahiro Yamada
180237c3637SMasahiro Yamada void gpio_early_init(void) __attribute__((weak, alias("__gpio_early_init")));
181237c3637SMasahiro Yamada
board_early_init_f(void)182237c3637SMasahiro Yamada int board_early_init_f(void)
183237c3637SMasahiro Yamada {
18446864cc8SSimon Glass if (!clock_early_init_done())
18546864cc8SSimon Glass clock_early_init();
18646864cc8SSimon Glass
187dd8204deSStephen Warren #if defined(CONFIG_TEGRA_DISCONNECT_UDC_ON_BOOT)
188dd8204deSStephen Warren #define USBCMD_FS2 (1 << 15)
189dd8204deSStephen Warren {
190dd8204deSStephen Warren struct usb_ctlr *usbctlr = (struct usb_ctlr *)0x7d000000;
191dd8204deSStephen Warren writel(USBCMD_FS2, &usbctlr->usb_cmd);
192dd8204deSStephen Warren }
193dd8204deSStephen Warren #endif
194dd8204deSStephen Warren
195aa441877SThierry Reding /* Do any special system timer/TSC setup */
196aa441877SThierry Reding #if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE)
197aa441877SThierry Reding if (!tegra_cpu_is_non_secure())
198aa441877SThierry Reding #endif
199aa441877SThierry Reding arch_timer_init();
200aa441877SThierry Reding
201237c3637SMasahiro Yamada pinmux_init();
202237c3637SMasahiro Yamada board_init_uart_f();
203237c3637SMasahiro Yamada
204237c3637SMasahiro Yamada /* Initialize periph GPIOs */
205237c3637SMasahiro Yamada gpio_early_init();
206237c3637SMasahiro Yamada gpio_early_init_uart();
207237c3637SMasahiro Yamada
208237c3637SMasahiro Yamada return 0;
209237c3637SMasahiro Yamada }
210237c3637SMasahiro Yamada #endif /* EARLY_INIT */
211237c3637SMasahiro Yamada
board_late_init(void)212237c3637SMasahiro Yamada int board_late_init(void)
213237c3637SMasahiro Yamada {
214237c3637SMasahiro Yamada #if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE)
215237c3637SMasahiro Yamada if (tegra_cpu_is_non_secure()) {
216237c3637SMasahiro Yamada printf("CPU is in NS mode\n");
217*382bee57SSimon Glass env_set("cpu_ns_mode", "1");
218237c3637SMasahiro Yamada } else {
219*382bee57SSimon Glass env_set("cpu_ns_mode", "");
220237c3637SMasahiro Yamada }
221237c3637SMasahiro Yamada #endif
22266999892STom Warren start_cpu_fan();
22366999892STom Warren
224237c3637SMasahiro Yamada return 0;
225237c3637SMasahiro Yamada }
226237c3637SMasahiro Yamada
227bbc1b99eSStephen Warren /*
228bbc1b99eSStephen Warren * In some SW environments, a memory carve-out exists to house a secure
229bbc1b99eSStephen Warren * monitor, a trusted OS, and/or various statically allocated media buffers.
230bbc1b99eSStephen Warren *
231bbc1b99eSStephen Warren * This carveout exists at the highest possible address that is within a
232bbc1b99eSStephen Warren * 32-bit physical address space.
233bbc1b99eSStephen Warren *
234bbc1b99eSStephen Warren * This function returns the total size of this carve-out. At present, the
235bbc1b99eSStephen Warren * returned value is hard-coded for simplicity. In the future, it may be
236bbc1b99eSStephen Warren * possible to determine the carve-out size:
237bbc1b99eSStephen Warren * - By querying some run-time information source, such as:
238bbc1b99eSStephen Warren * - A structure passed to U-Boot by earlier boot software.
239bbc1b99eSStephen Warren * - SoC registers.
240bbc1b99eSStephen Warren * - A call into the secure monitor.
241bbc1b99eSStephen Warren * - In the per-board U-Boot configuration header, based on knowledge of the
242bbc1b99eSStephen Warren * SW environment that U-Boot is being built for.
243bbc1b99eSStephen Warren *
244bbc1b99eSStephen Warren * For now, we support two configurations in U-Boot:
245bbc1b99eSStephen Warren * - 32-bit ports without any form of carve-out.
246bbc1b99eSStephen Warren * - 64 bit ports which are assumed to use a carve-out of a conservatively
247bbc1b99eSStephen Warren * hard-coded size.
248bbc1b99eSStephen Warren */
carveout_size(void)249bbc1b99eSStephen Warren static ulong carveout_size(void)
250bbc1b99eSStephen Warren {
25100f782a9SThierry Reding #ifdef CONFIG_ARM64
252bbc1b99eSStephen Warren return SZ_512M;
253bbc1b99eSStephen Warren #else
254bbc1b99eSStephen Warren return 0;
255bbc1b99eSStephen Warren #endif
256bbc1b99eSStephen Warren }
257bbc1b99eSStephen Warren
258bbc1b99eSStephen Warren /*
259bbc1b99eSStephen Warren * Determine the amount of usable RAM below 4GiB, taking into account any
260bbc1b99eSStephen Warren * carve-out that may be assigned.
261bbc1b99eSStephen Warren */
usable_ram_size_below_4g(void)262bbc1b99eSStephen Warren static ulong usable_ram_size_below_4g(void)
263bbc1b99eSStephen Warren {
264bbc1b99eSStephen Warren ulong total_size_below_4g;
265bbc1b99eSStephen Warren ulong usable_size_below_4g;
266bbc1b99eSStephen Warren
267bbc1b99eSStephen Warren /*
268bbc1b99eSStephen Warren * The total size of RAM below 4GiB is the lesser address of:
269bbc1b99eSStephen Warren * (a) 2GiB itself (RAM starts at 2GiB, and 4GiB - 2GiB == 2GiB).
270bbc1b99eSStephen Warren * (b) The size RAM physically present in the system.
271bbc1b99eSStephen Warren */
272bbc1b99eSStephen Warren if (gd->ram_size < SZ_2G)
273bbc1b99eSStephen Warren total_size_below_4g = gd->ram_size;
274bbc1b99eSStephen Warren else
275bbc1b99eSStephen Warren total_size_below_4g = SZ_2G;
276bbc1b99eSStephen Warren
277bbc1b99eSStephen Warren /* Calculate usable RAM by subtracting out any carve-out size */
278bbc1b99eSStephen Warren usable_size_below_4g = total_size_below_4g - carveout_size();
279bbc1b99eSStephen Warren
280bbc1b99eSStephen Warren return usable_size_below_4g;
281bbc1b99eSStephen Warren }
282bbc1b99eSStephen Warren
283bbc1b99eSStephen Warren /*
284bbc1b99eSStephen Warren * Represent all available RAM in either one or two banks.
285bbc1b99eSStephen Warren *
286bbc1b99eSStephen Warren * The first bank describes any usable RAM below 4GiB.
287bbc1b99eSStephen Warren * The second bank describes any RAM above 4GiB.
288bbc1b99eSStephen Warren *
289bbc1b99eSStephen Warren * This split is driven by the following requirements:
290bbc1b99eSStephen Warren * - The NVIDIA L4T kernel requires separate entries in the DT /memory/reg
291bbc1b99eSStephen Warren * property for memory below and above the 4GiB boundary. The layout of that
292bbc1b99eSStephen Warren * DT property is directly driven by the entries in the U-Boot bank array.
293bbc1b99eSStephen Warren * - The potential existence of a carve-out at the end of RAM below 4GiB can
294bbc1b99eSStephen Warren * only be represented using multiple banks.
295bbc1b99eSStephen Warren *
296bbc1b99eSStephen Warren * Explicitly removing the carve-out RAM from the bank entries makes the RAM
297bbc1b99eSStephen Warren * layout a bit more obvious, e.g. when running "bdinfo" at the U-Boot
298bbc1b99eSStephen Warren * command-line.
299bbc1b99eSStephen Warren *
300bbc1b99eSStephen Warren * This does mean that the DT U-Boot passes to the Linux kernel will not
301bbc1b99eSStephen Warren * include this RAM in /memory/reg at all. An alternative would be to include
302bbc1b99eSStephen Warren * all RAM in the U-Boot banks (and hence DT), and add a /memreserve/ node
303bbc1b99eSStephen Warren * into DT to stop the kernel from using the RAM. IIUC, I don't /think/ the
304bbc1b99eSStephen Warren * Linux kernel will ever need to access any RAM in* the carve-out via a CPU
305bbc1b99eSStephen Warren * mapping, so either way is acceptable.
306bbc1b99eSStephen Warren *
307bbc1b99eSStephen Warren * On 32-bit systems, we never define a bank for RAM above 4GiB, since the
308bbc1b99eSStephen Warren * start address of that bank cannot be represented in the 32-bit .size
309bbc1b99eSStephen Warren * field.
310bbc1b99eSStephen Warren */
dram_init_banksize(void)31176b00acaSSimon Glass int dram_init_banksize(void)
312bbc1b99eSStephen Warren {
313bbc1b99eSStephen Warren gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
314bbc1b99eSStephen Warren gd->bd->bi_dram[0].size = usable_ram_size_below_4g();
315bbc1b99eSStephen Warren
316e81ca884SSimon Glass #ifdef CONFIG_PCI
317e81ca884SSimon Glass gd->pci_ram_top = gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size;
318e81ca884SSimon Glass #endif
319e81ca884SSimon Glass
320bbc1b99eSStephen Warren #ifdef CONFIG_PHYS_64BIT
321bbc1b99eSStephen Warren if (gd->ram_size > SZ_2G) {
322bbc1b99eSStephen Warren gd->bd->bi_dram[1].start = 0x100000000;
323bbc1b99eSStephen Warren gd->bd->bi_dram[1].size = gd->ram_size - SZ_2G;
324bbc1b99eSStephen Warren } else
325bbc1b99eSStephen Warren #endif
326bbc1b99eSStephen Warren {
327bbc1b99eSStephen Warren gd->bd->bi_dram[1].start = 0;
328bbc1b99eSStephen Warren gd->bd->bi_dram[1].size = 0;
329bbc1b99eSStephen Warren }
33076b00acaSSimon Glass
33176b00acaSSimon Glass return 0;
332bbc1b99eSStephen Warren }
333bbc1b99eSStephen Warren
33400f782a9SThierry Reding /*
33500f782a9SThierry Reding * Most hardware on 64-bit Tegra is still restricted to DMA to the lower
33600f782a9SThierry Reding * 32-bits of the physical address space. Cap the maximum usable RAM area
33700f782a9SThierry Reding * at 4 GiB to avoid DMA buffers from being allocated beyond the 32-bit
338bbc1b99eSStephen Warren * boundary that most devices can address. Also, don't let U-Boot use any
339bbc1b99eSStephen Warren * carve-out, as mentioned above.
340424afc0aSStephen Warren *
341bbc1b99eSStephen Warren * This function is called before dram_init_banksize(), so we can't simply
342bbc1b99eSStephen Warren * return gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size.
34300f782a9SThierry Reding */
board_get_usable_ram_top(ulong total_size)34400f782a9SThierry Reding ulong board_get_usable_ram_top(ulong total_size)
34500f782a9SThierry Reding {
346bbc1b99eSStephen Warren return CONFIG_SYS_SDRAM_BASE + usable_ram_size_below_4g();
34700f782a9SThierry Reding }
348