109f455dcSMasahiro Yamada /*
27aaa5a60STom Warren * (C) Copyright 2010-2015
309f455dcSMasahiro Yamada * NVIDIA Corporation <www.nvidia.com>
409f455dcSMasahiro Yamada *
509f455dcSMasahiro Yamada * SPDX-License-Identifier: GPL-2.0+
609f455dcSMasahiro Yamada */
709f455dcSMasahiro Yamada
809f455dcSMasahiro Yamada #include <common.h>
91874626bSThomas Chou #include <dm.h>
101874626bSThomas Chou #include <ns16550.h>
11537e9673SSimon Glass #include <spl.h>
1209f455dcSMasahiro Yamada #include <asm/io.h>
1309f455dcSMasahiro Yamada #include <asm/arch/clock.h>
1409f455dcSMasahiro Yamada #include <asm/arch/funcmux.h>
1509f455dcSMasahiro Yamada #include <asm/arch/mc.h>
1609f455dcSMasahiro Yamada #include <asm/arch/tegra.h>
1773c38934SStephen Warren #include <asm/arch-tegra/ap.h>
1809f455dcSMasahiro Yamada #include <asm/arch-tegra/board.h>
1909f455dcSMasahiro Yamada #include <asm/arch-tegra/pmc.h>
2009f455dcSMasahiro Yamada #include <asm/arch-tegra/sys_proto.h>
2109f455dcSMasahiro Yamada #include <asm/arch-tegra/warmboot.h>
2209f455dcSMasahiro Yamada
23659a0755STom Warren void save_boot_params_ret(void);
24659a0755STom Warren
2509f455dcSMasahiro Yamada DECLARE_GLOBAL_DATA_PTR;
2609f455dcSMasahiro Yamada
2709f455dcSMasahiro Yamada enum {
2809f455dcSMasahiro Yamada /* UARTs which we can enable */
2909f455dcSMasahiro Yamada UARTA = 1 << 0,
3009f455dcSMasahiro Yamada UARTB = 1 << 1,
3109f455dcSMasahiro Yamada UARTC = 1 << 2,
3209f455dcSMasahiro Yamada UARTD = 1 << 3,
3309f455dcSMasahiro Yamada UARTE = 1 << 4,
3409f455dcSMasahiro Yamada UART_COUNT = 5,
3509f455dcSMasahiro Yamada };
3609f455dcSMasahiro Yamada
37537e9673SSimon Glass static bool from_spl __attribute__ ((section(".data")));
38537e9673SSimon Glass
39537e9673SSimon Glass #ifndef CONFIG_SPL_BUILD
save_boot_params(u32 r0,u32 r1,u32 r2,u32 r3)40537e9673SSimon Glass void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3)
41537e9673SSimon Glass {
42537e9673SSimon Glass from_spl = r0 != UBOOT_NOT_LOADED_FROM_SPL;
43537e9673SSimon Glass save_boot_params_ret();
44537e9673SSimon Glass }
45537e9673SSimon Glass #endif
46537e9673SSimon Glass
spl_was_boot_source(void)47537e9673SSimon Glass bool spl_was_boot_source(void)
48537e9673SSimon Glass {
49537e9673SSimon Glass return from_spl;
50537e9673SSimon Glass }
51537e9673SSimon Glass
5273c38934SStephen Warren #if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE)
5373c38934SStephen Warren #if !defined(CONFIG_TEGRA124)
5473c38934SStephen Warren #error tegra_cpu_is_non_secure has only been validated on Tegra124
5573c38934SStephen Warren #endif
tegra_cpu_is_non_secure(void)5673c38934SStephen Warren bool tegra_cpu_is_non_secure(void)
5773c38934SStephen Warren {
5873c38934SStephen Warren /*
5973c38934SStephen Warren * This register reads 0xffffffff in non-secure mode. This register
6073c38934SStephen Warren * only implements bits 31:20, so the lower bits will always read 0 in
6173c38934SStephen Warren * secure mode. Thus, the lower bits are an indicator for secure vs.
6273c38934SStephen Warren * non-secure mode.
6373c38934SStephen Warren */
6473c38934SStephen Warren struct mc_ctlr *mc = (struct mc_ctlr *)NV_PA_MC_BASE;
6573c38934SStephen Warren uint32_t mc_s_cfg0 = readl(&mc->mc_security_cfg0);
6673c38934SStephen Warren return (mc_s_cfg0 & 1) == 1;
6773c38934SStephen Warren }
6873c38934SStephen Warren #endif
6973c38934SStephen Warren
7009f455dcSMasahiro Yamada /* Read the RAM size directly from the memory controller */
query_sdram_size(void)71a5fc3d0bSStephen Warren static phys_size_t query_sdram_size(void)
7209f455dcSMasahiro Yamada {
7309f455dcSMasahiro Yamada struct mc_ctlr *const mc = (struct mc_ctlr *)NV_PA_MC_BASE;
74a5fc3d0bSStephen Warren u32 emem_cfg;
75a5fc3d0bSStephen Warren phys_size_t size_bytes;
7609f455dcSMasahiro Yamada
773a2cab51SStephen Warren emem_cfg = readl(&mc->mc_emem_cfg);
7809f455dcSMasahiro Yamada #if defined(CONFIG_TEGRA20)
793a2cab51SStephen Warren debug("mc->mc_emem_cfg (MEM_SIZE_KB) = 0x%08x\n", emem_cfg);
803a2cab51SStephen Warren size_bytes = get_ram_size((void *)PHYS_SDRAM_1, emem_cfg * 1024);
8109f455dcSMasahiro Yamada #else
823a2cab51SStephen Warren debug("mc->mc_emem_cfg (MEM_SIZE_MB) = 0x%08x\n", emem_cfg);
83a5fc3d0bSStephen Warren #ifndef CONFIG_PHYS_64BIT
8456519c4fSStephen Warren /*
8556519c4fSStephen Warren * If >=4GB RAM is present, the byte RAM size won't fit into 32-bits
8656519c4fSStephen Warren * and will wrap. Clip the reported size to the maximum that a 32-bit
8756519c4fSStephen Warren * variable can represent (rounded to a page).
8856519c4fSStephen Warren */
8956519c4fSStephen Warren if (emem_cfg >= 4096) {
9056519c4fSStephen Warren size_bytes = U32_MAX & ~(0x1000 - 1);
91a5fc3d0bSStephen Warren } else
92a5fc3d0bSStephen Warren #endif
93a5fc3d0bSStephen Warren {
9456519c4fSStephen Warren /* RAM size EMC is programmed to. */
95a5fc3d0bSStephen Warren size_bytes = (phys_size_t)emem_cfg * 1024 * 1024;
96a5fc3d0bSStephen Warren #ifndef CONFIG_ARM64
9756519c4fSStephen Warren /*
9856519c4fSStephen Warren * If all RAM fits within 32-bits, it can be accessed without
9956519c4fSStephen Warren * LPAE, so go test the RAM size. Otherwise, we can't access
10056519c4fSStephen Warren * all the RAM, and get_ram_size() would get confused, so
10156519c4fSStephen Warren * avoid using it. There's no reason we should need this
10256519c4fSStephen Warren * validation step anyway.
10356519c4fSStephen Warren */
10456519c4fSStephen Warren if (emem_cfg <= (0 - PHYS_SDRAM_1) / (1024 * 1024))
10556519c4fSStephen Warren size_bytes = get_ram_size((void *)PHYS_SDRAM_1,
10656519c4fSStephen Warren size_bytes);
107a5fc3d0bSStephen Warren #endif
10856519c4fSStephen Warren }
10909f455dcSMasahiro Yamada #endif
11009f455dcSMasahiro Yamada
11109f455dcSMasahiro Yamada #if defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA114)
11209f455dcSMasahiro Yamada /* External memory limited to 2047 MB due to IROM/HI-VEC */
1133a2cab51SStephen Warren if (size_bytes == SZ_2G)
1143a2cab51SStephen Warren size_bytes -= SZ_1M;
11509f455dcSMasahiro Yamada #endif
11609f455dcSMasahiro Yamada
1173a2cab51SStephen Warren return size_bytes;
11809f455dcSMasahiro Yamada }
11909f455dcSMasahiro Yamada
dram_init(void)12009f455dcSMasahiro Yamada int dram_init(void)
12109f455dcSMasahiro Yamada {
12209f455dcSMasahiro Yamada /* We do not initialise DRAM here. We just query the size */
12309f455dcSMasahiro Yamada gd->ram_size = query_sdram_size();
12409f455dcSMasahiro Yamada return 0;
12509f455dcSMasahiro Yamada }
12609f455dcSMasahiro Yamada
12709f455dcSMasahiro Yamada static int uart_configs[] = {
12809f455dcSMasahiro Yamada #if defined(CONFIG_TEGRA20)
12909f455dcSMasahiro Yamada #if defined(CONFIG_TEGRA_UARTA_UAA_UAB)
13009f455dcSMasahiro Yamada FUNCMUX_UART1_UAA_UAB,
13109f455dcSMasahiro Yamada #elif defined(CONFIG_TEGRA_UARTA_GPU)
13209f455dcSMasahiro Yamada FUNCMUX_UART1_GPU,
13309f455dcSMasahiro Yamada #elif defined(CONFIG_TEGRA_UARTA_SDIO1)
13409f455dcSMasahiro Yamada FUNCMUX_UART1_SDIO1,
13509f455dcSMasahiro Yamada #else
13609f455dcSMasahiro Yamada FUNCMUX_UART1_IRRX_IRTX,
13709f455dcSMasahiro Yamada #endif
13809f455dcSMasahiro Yamada FUNCMUX_UART2_UAD,
13909f455dcSMasahiro Yamada -1,
14009f455dcSMasahiro Yamada FUNCMUX_UART4_GMC,
14109f455dcSMasahiro Yamada -1,
14209f455dcSMasahiro Yamada #elif defined(CONFIG_TEGRA30)
14309f455dcSMasahiro Yamada FUNCMUX_UART1_ULPI, /* UARTA */
14409f455dcSMasahiro Yamada -1,
14509f455dcSMasahiro Yamada -1,
14609f455dcSMasahiro Yamada -1,
14709f455dcSMasahiro Yamada -1,
14809f455dcSMasahiro Yamada #elif defined(CONFIG_TEGRA114)
14909f455dcSMasahiro Yamada -1,
15009f455dcSMasahiro Yamada -1,
15109f455dcSMasahiro Yamada -1,
15209f455dcSMasahiro Yamada FUNCMUX_UART4_GMI, /* UARTD */
15309f455dcSMasahiro Yamada -1,
1547aaa5a60STom Warren #elif defined(CONFIG_TEGRA124)
15509f455dcSMasahiro Yamada FUNCMUX_UART1_KBC, /* UARTA */
15609f455dcSMasahiro Yamada -1,
15709f455dcSMasahiro Yamada -1,
15809f455dcSMasahiro Yamada FUNCMUX_UART4_GPIO, /* UARTD */
15909f455dcSMasahiro Yamada -1,
1607aaa5a60STom Warren #else /* Tegra210 */
1617aaa5a60STom Warren FUNCMUX_UART1_UART1, /* UARTA */
1627aaa5a60STom Warren -1,
1637aaa5a60STom Warren -1,
1647aaa5a60STom Warren FUNCMUX_UART4_UART4, /* UARTD */
1657aaa5a60STom Warren -1,
16609f455dcSMasahiro Yamada #endif
16709f455dcSMasahiro Yamada };
16809f455dcSMasahiro Yamada
16909f455dcSMasahiro Yamada /**
17009f455dcSMasahiro Yamada * Set up the specified uarts
17109f455dcSMasahiro Yamada *
17209f455dcSMasahiro Yamada * @param uarts_ids Mask containing UARTs to init (UARTx)
17309f455dcSMasahiro Yamada */
setup_uarts(int uart_ids)17409f455dcSMasahiro Yamada static void setup_uarts(int uart_ids)
17509f455dcSMasahiro Yamada {
17609f455dcSMasahiro Yamada static enum periph_id id_for_uart[] = {
17709f455dcSMasahiro Yamada PERIPH_ID_UART1,
17809f455dcSMasahiro Yamada PERIPH_ID_UART2,
17909f455dcSMasahiro Yamada PERIPH_ID_UART3,
18009f455dcSMasahiro Yamada PERIPH_ID_UART4,
18109f455dcSMasahiro Yamada PERIPH_ID_UART5,
18209f455dcSMasahiro Yamada };
18309f455dcSMasahiro Yamada size_t i;
18409f455dcSMasahiro Yamada
18509f455dcSMasahiro Yamada for (i = 0; i < UART_COUNT; i++) {
18609f455dcSMasahiro Yamada if (uart_ids & (1 << i)) {
18709f455dcSMasahiro Yamada enum periph_id id = id_for_uart[i];
18809f455dcSMasahiro Yamada
18909f455dcSMasahiro Yamada funcmux_select(id, uart_configs[i]);
19009f455dcSMasahiro Yamada clock_ll_start_uart(id);
19109f455dcSMasahiro Yamada }
19209f455dcSMasahiro Yamada }
19309f455dcSMasahiro Yamada }
19409f455dcSMasahiro Yamada
board_init_uart_f(void)19509f455dcSMasahiro Yamada void board_init_uart_f(void)
19609f455dcSMasahiro Yamada {
19709f455dcSMasahiro Yamada int uart_ids = 0; /* bit mask of which UART ids to enable */
19809f455dcSMasahiro Yamada
19909f455dcSMasahiro Yamada #ifdef CONFIG_TEGRA_ENABLE_UARTA
20009f455dcSMasahiro Yamada uart_ids |= UARTA;
20109f455dcSMasahiro Yamada #endif
20209f455dcSMasahiro Yamada #ifdef CONFIG_TEGRA_ENABLE_UARTB
20309f455dcSMasahiro Yamada uart_ids |= UARTB;
20409f455dcSMasahiro Yamada #endif
20509f455dcSMasahiro Yamada #ifdef CONFIG_TEGRA_ENABLE_UARTC
20609f455dcSMasahiro Yamada uart_ids |= UARTC;
20709f455dcSMasahiro Yamada #endif
20809f455dcSMasahiro Yamada #ifdef CONFIG_TEGRA_ENABLE_UARTD
20909f455dcSMasahiro Yamada uart_ids |= UARTD;
21009f455dcSMasahiro Yamada #endif
21109f455dcSMasahiro Yamada #ifdef CONFIG_TEGRA_ENABLE_UARTE
21209f455dcSMasahiro Yamada uart_ids |= UARTE;
21309f455dcSMasahiro Yamada #endif
21409f455dcSMasahiro Yamada setup_uarts(uart_ids);
21509f455dcSMasahiro Yamada }
21609f455dcSMasahiro Yamada
217878a3ed9SSimon Glass #if !CONFIG_IS_ENABLED(OF_CONTROL)
2181874626bSThomas Chou static struct ns16550_platdata ns16550_com1_pdata = {
2191874626bSThomas Chou .base = CONFIG_SYS_NS16550_COM1,
2201874626bSThomas Chou .reg_shift = 2,
2211874626bSThomas Chou .clock = CONFIG_SYS_NS16550_CLK,
222*17fa0326SHeiko Schocher .fcr = UART_FCR_DEFVAL,
2231874626bSThomas Chou };
2241874626bSThomas Chou
2251874626bSThomas Chou U_BOOT_DEVICE(ns16550_com1) = {
2261874626bSThomas Chou "ns16550_serial", &ns16550_com1_pdata
2271874626bSThomas Chou };
2281874626bSThomas Chou #endif
2291874626bSThomas Chou
23032b3234fSThierry Reding #if !defined(CONFIG_SYS_DCACHE_OFF) && !defined(CONFIG_ARM64)
enable_caches(void)23109f455dcSMasahiro Yamada void enable_caches(void)
23209f455dcSMasahiro Yamada {
23309f455dcSMasahiro Yamada /* Enable D-cache. I-cache is already enabled in start.S */
23409f455dcSMasahiro Yamada dcache_enable();
23509f455dcSMasahiro Yamada }
23609f455dcSMasahiro Yamada #endif
237