138771996SKever Yang /*
238771996SKever Yang * (C) Copyright 2018 Rockchip Electronics Co., Ltd
338771996SKever Yang *
438771996SKever Yang * SPDX-License-Identifier: GPL-2.0+
538771996SKever Yang */
638771996SKever Yang
738771996SKever Yang #include <common.h>
8de77dbbbSJoseph Chen #include <version.h>
94484e03eSJoseph Chen #include <boot_rkimg.h>
1038771996SKever Yang #include <debug_uart.h>
1138771996SKever Yang #include <dm.h>
12*b6bda7d5SXuhui Lin #include <envf.h>
132323b257SJason Zhu #include <key.h>
14f0daa6c1SJason Zhu #include <led.h>
15a5373663SJason Zhu #include <misc.h>
16*b6bda7d5SXuhui Lin #include <mtd_blk.h>
1738771996SKever Yang #include <ram.h>
1838771996SKever Yang #include <spl.h>
19*b6bda7d5SXuhui Lin #include <spl_ab.h>
206afcbf88SJoseph Chen #include <optee_include/OpteeClientInterface.h>
21c90ee5c7SJason Zhu #include <power/fuel_gauge.h>
2238771996SKever Yang #include <asm/arch/bootrom.h>
2310dd5e8cSJason Zhu #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
2410dd5e8cSJason Zhu #include <asm/arch/rk_atags.h>
2510dd5e8cSJason Zhu #endif
264c8e468bSKever Yang #include <asm/arch/pcie_ep_boot.h>
27e1f97ec3SYouMin Chen #include <asm/arch/sdram.h>
282323b257SJason Zhu #include <asm/arch/boot_mode.h>
2952f7b21dSZhihuan He #include <asm/arch-rockchip/sys_proto.h>
3038771996SKever Yang #include <asm/io.h>
31ad771a9cSHuibin Hong #include <asm/arch/param.h>
3244f37eaaSXuhui Lin #include <asm/arch/rk_hwid.h>
33*b6bda7d5SXuhui Lin #include <asm/arch/rk_meta.h>
3438771996SKever Yang
3538771996SKever Yang DECLARE_GLOBAL_DATA_PTR;
3638771996SKever Yang
board_return_to_bootrom(void)3738771996SKever Yang void board_return_to_bootrom(void)
3838771996SKever Yang {
3938771996SKever Yang back_to_bootrom(BROM_BOOT_NEXTSTAGE);
4038771996SKever Yang }
4138771996SKever Yang
4238771996SKever Yang __weak const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = {
4338771996SKever Yang };
4438771996SKever Yang
spl_rk_board_prepare_for_jump(struct spl_image_info * spl_image)4552c8858eSJoseph Chen __weak void spl_rk_board_prepare_for_jump(struct spl_image_info *spl_image)
4652c8858eSJoseph Chen {
4752c8858eSJoseph Chen }
4852c8858eSJoseph Chen
board_spl_was_booted_from(void)4938771996SKever Yang const char *board_spl_was_booted_from(void)
5038771996SKever Yang {
5138771996SKever Yang u32 bootdevice_brom_id = readl(BROM_BOOTSOURCE_ID_ADDR);
5238771996SKever Yang const char *bootdevice_ofpath = NULL;
5338771996SKever Yang
54b2b4c2f5SYifeng Zhao if ((bootdevice_brom_id & BROM_DOWNLOAD_MASK) == BROM_DOWNLOAD_MASK)
55b2b4c2f5SYifeng Zhao bootdevice_brom_id = BROM_BOOTSOURCE_USB;
56b2b4c2f5SYifeng Zhao
57b2b4c2f5SYifeng Zhao bootdevice_brom_id = bootdevice_brom_id & BROM_BOOTSOURCE_MASK;
5838771996SKever Yang if (bootdevice_brom_id < ARRAY_SIZE(boot_devices))
5938771996SKever Yang bootdevice_ofpath = boot_devices[bootdevice_brom_id];
6038771996SKever Yang
6138771996SKever Yang if (bootdevice_ofpath)
6238771996SKever Yang debug("%s: brom_bootdevice_id %x maps to '%s'\n",
6338771996SKever Yang __func__, bootdevice_brom_id, bootdevice_ofpath);
6438771996SKever Yang else
6538771996SKever Yang debug("%s: failed to resolve brom_bootdevice_id %x\n",
6638771996SKever Yang __func__, bootdevice_brom_id);
6738771996SKever Yang
6838771996SKever Yang return bootdevice_ofpath;
6938771996SKever Yang }
7038771996SKever Yang
spl_boot_device(void)7138771996SKever Yang u32 spl_boot_device(void)
7238771996SKever Yang {
7338771996SKever Yang u32 boot_device = BOOT_DEVICE_MMC1;
7438771996SKever Yang
7538771996SKever Yang #if defined(CONFIG_TARGET_CHROMEBOOK_JERRY) || \
7638771996SKever Yang defined(CONFIG_TARGET_CHROMEBIT_MICKEY) || \
7738771996SKever Yang defined(CONFIG_TARGET_CHROMEBOOK_MINNIE)
7838771996SKever Yang return BOOT_DEVICE_SPI;
7938771996SKever Yang #endif
8038771996SKever Yang if (CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM))
8138771996SKever Yang return BOOT_DEVICE_BOOTROM;
8238771996SKever Yang
8338771996SKever Yang return boot_device;
8438771996SKever Yang }
8538771996SKever Yang
spl_boot_mode(const u32 boot_device)8638771996SKever Yang u32 spl_boot_mode(const u32 boot_device)
8738771996SKever Yang {
8838771996SKever Yang return MMCSD_MODE_RAW;
8938771996SKever Yang }
9038771996SKever Yang
rockchip_stimer_init(void)9138771996SKever Yang __weak void rockchip_stimer_init(void)
9238771996SKever Yang {
93d74e8763SKever Yang /* If Timer already enabled, don't re-init it */
94d74e8763SKever Yang u32 reg = readl(CONFIG_ROCKCHIP_STIMER_BASE + 0x10);
95d74e8763SKever Yang if ( reg & 0x1 )
96d74e8763SKever Yang return;
9713ceb2afSXuhui Lin #ifdef COUNTER_FREQUENCY
98a09afa08SKever Yang #ifndef CONFIG_ARM64
99a09afa08SKever Yang asm volatile("mcr p15, 0, %0, c14, c0, 0"
100a09afa08SKever Yang : : "r"(COUNTER_FREQUENCY));
101a09afa08SKever Yang #endif
10213ceb2afSXuhui Lin #endif
10338771996SKever Yang writel(0, CONFIG_ROCKCHIP_STIMER_BASE + 0x10);
10438771996SKever Yang writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE);
10538771996SKever Yang writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE + 4);
10638771996SKever Yang writel(1, CONFIG_ROCKCHIP_STIMER_BASE + 0x10);
10738771996SKever Yang }
10838771996SKever Yang
arch_cpu_init(void)10938771996SKever Yang __weak int arch_cpu_init(void)
11038771996SKever Yang {
11138771996SKever Yang return 0;
11238771996SKever Yang }
11338771996SKever Yang
rk_board_init_f(void)11438771996SKever Yang __weak int rk_board_init_f(void)
11538771996SKever Yang {
11638771996SKever Yang return 0;
11738771996SKever Yang }
11838771996SKever Yang
119e62c13b9SZhihuan He #ifndef CONFIG_SPL_LIBGENERIC_SUPPORT
udelay(unsigned long usec)120e62c13b9SZhihuan He void udelay(unsigned long usec)
121e62c13b9SZhihuan He {
122e62c13b9SZhihuan He __udelay(usec);
123e62c13b9SZhihuan He }
124e62c13b9SZhihuan He
hang(void)125e62c13b9SZhihuan He void hang(void)
126e62c13b9SZhihuan He {
127e62c13b9SZhihuan He bootstage_error(BOOTSTAGE_ID_NEED_RESET);
128e62c13b9SZhihuan He for (;;)
129e62c13b9SZhihuan He ;
130e62c13b9SZhihuan He }
131e62c13b9SZhihuan He
132e62c13b9SZhihuan He /**
133e62c13b9SZhihuan He * memset - Fill a region of memory with the given value
134e62c13b9SZhihuan He * @s: Pointer to the start of the area.
135e62c13b9SZhihuan He * @c: The byte to fill the area with
136e62c13b9SZhihuan He * @count: The size of the area.
137e62c13b9SZhihuan He *
138e62c13b9SZhihuan He * Do not use memset() to access IO space, use memset_io() instead.
139e62c13b9SZhihuan He */
memset(void * s,int c,size_t count)140e62c13b9SZhihuan He void *memset(void *s, int c, size_t count)
141e62c13b9SZhihuan He {
142e62c13b9SZhihuan He unsigned long *sl = (unsigned long *)s;
143e62c13b9SZhihuan He char *s8;
144e62c13b9SZhihuan He
145e62c13b9SZhihuan He #if !CONFIG_IS_ENABLED(TINY_MEMSET)
146e62c13b9SZhihuan He unsigned long cl = 0;
147e62c13b9SZhihuan He int i;
148e62c13b9SZhihuan He
149e62c13b9SZhihuan He /* do it one word at a time (32 bits or 64 bits) while possible */
150e62c13b9SZhihuan He if (((ulong)s & (sizeof(*sl) - 1)) == 0) {
151e62c13b9SZhihuan He for (i = 0; i < sizeof(*sl); i++) {
152e62c13b9SZhihuan He cl <<= 8;
153e62c13b9SZhihuan He cl |= c & 0xff;
154e62c13b9SZhihuan He }
155e62c13b9SZhihuan He while (count >= sizeof(*sl)) {
156e62c13b9SZhihuan He *sl++ = cl;
157e62c13b9SZhihuan He count -= sizeof(*sl);
158e62c13b9SZhihuan He }
159e62c13b9SZhihuan He }
160e62c13b9SZhihuan He #endif /* fill 8 bits at a time */
161e62c13b9SZhihuan He s8 = (char *)sl;
162e62c13b9SZhihuan He while (count--)
163e62c13b9SZhihuan He *s8++ = c;
164e62c13b9SZhihuan He
165e62c13b9SZhihuan He return s;
166e62c13b9SZhihuan He }
167e62c13b9SZhihuan He #endif
168e62c13b9SZhihuan He
1694fcb4a04SJoseph Chen #ifdef CONFIG_SPL_DM_RESET
brom_download(void)1704fcb4a04SJoseph Chen static void brom_download(void)
1714fcb4a04SJoseph Chen {
172b1f7fc03SXuhui Lin if (gd->console_evt == 0x02) {
1734fcb4a04SJoseph Chen printf("ctrl+b: Bootrom download!\n");
1744fcb4a04SJoseph Chen writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG);
1754fcb4a04SJoseph Chen do_reset(NULL, 0, 0, NULL);
1764fcb4a04SJoseph Chen }
1774fcb4a04SJoseph Chen }
1784fcb4a04SJoseph Chen #endif
1794fcb4a04SJoseph Chen
spl_hotkey_init(void)180b1f7fc03SXuhui Lin static void spl_hotkey_init(void)
181b1f7fc03SXuhui Lin {
182b1f7fc03SXuhui Lin /* If disable console, skip getting uart reg */
183b1f7fc03SXuhui Lin if (!gd || gd->flags & GD_FLG_DISABLE_CONSOLE)
184b1f7fc03SXuhui Lin return;
185b1f7fc03SXuhui Lin if (!gd->have_console)
186b1f7fc03SXuhui Lin return;
187b1f7fc03SXuhui Lin
188b1f7fc03SXuhui Lin /* serial uclass only exists when enable CONFIG_SPL_FRAMEWORK */
189b1f7fc03SXuhui Lin #ifdef CONFIG_SPL_FRAMEWORK
190b1f7fc03SXuhui Lin if (serial_tstc()) {
191b1f7fc03SXuhui Lin gd->console_evt = serial_getc();
192b1f7fc03SXuhui Lin #else
193b1f7fc03SXuhui Lin if (debug_uart_tstc()) {
194b1f7fc03SXuhui Lin gd->console_evt = debug_uart_getc();
195b1f7fc03SXuhui Lin #endif
196b1f7fc03SXuhui Lin if (gd->console_evt <= 0x1a) /* 'z' */
197b1f7fc03SXuhui Lin printf("SPL Hotkey: ctrl+%c\n",
198b1f7fc03SXuhui Lin gd->console_evt + 'a' - 1);
199b1f7fc03SXuhui Lin }
200b1f7fc03SXuhui Lin
201b1f7fc03SXuhui Lin return;
202b1f7fc03SXuhui Lin }
203b1f7fc03SXuhui Lin
20438771996SKever Yang void board_init_f(ulong dummy)
20538771996SKever Yang {
20638771996SKever Yang #ifdef CONFIG_SPL_FRAMEWORK
20738771996SKever Yang int ret;
20838771996SKever Yang #if !defined(CONFIG_SUPPORT_TPL)
20938771996SKever Yang struct udevice *dev;
21038771996SKever Yang #endif
21138771996SKever Yang #endif
2127d536d43SJoseph Chen gd->flags = dummy;
213a09afa08SKever Yang rockchip_stimer_init();
21438771996SKever Yang #define EARLY_UART
21538771996SKever Yang #if defined(EARLY_UART) && defined(CONFIG_DEBUG_UART)
21638771996SKever Yang /*
21738771996SKever Yang * Debug UART can be used from here if required:
21838771996SKever Yang *
21938771996SKever Yang * debug_uart_init();
22038771996SKever Yang * printch('a');
22138771996SKever Yang * printhex8(0x1234);
22238771996SKever Yang * printascii("string");
22338771996SKever Yang */
22481e837faSJoseph Chen if (!gd->serial.using_pre_serial &&
22581e837faSJoseph Chen !(gd->flags & GD_FLG_DISABLE_CONSOLE))
22638771996SKever Yang debug_uart_init();
22738771996SKever Yang printascii("U-Boot SPL board init");
22838771996SKever Yang #endif
229e220d757SJoseph Chen gd->sys_start_tick = get_ticks();
2304c8e468bSKever Yang #ifdef CONFIG_SPL_PCIE_EP_SUPPORT
2314c8e468bSKever Yang rockchip_pcie_ep_init();
2324c8e468bSKever Yang #endif
23338771996SKever Yang #ifdef CONFIG_SPL_FRAMEWORK
23438771996SKever Yang ret = spl_early_init();
23538771996SKever Yang if (ret) {
23638771996SKever Yang printf("spl_early_init() failed: %d\n", ret);
23738771996SKever Yang hang();
23838771996SKever Yang }
23938771996SKever Yang #if !defined(CONFIG_SUPPORT_TPL)
24038771996SKever Yang debug("\nspl:init dram\n");
24138771996SKever Yang ret = uclass_get_device(UCLASS_RAM, 0, &dev);
24238771996SKever Yang if (ret) {
24338771996SKever Yang printf("DRAM init failed: %d\n", ret);
24438771996SKever Yang return;
24538771996SKever Yang }
24638771996SKever Yang #endif
24738771996SKever Yang preloader_console_init();
24838771996SKever Yang #else
24938771996SKever Yang /* Some SoCs like rk3036 does not use any frame work */
25038771996SKever Yang sdram_init();
25138771996SKever Yang #endif
252b1f7fc03SXuhui Lin /* Get hotkey and store in gd */
253b1f7fc03SXuhui Lin spl_hotkey_init();
2544fcb4a04SJoseph Chen #ifdef CONFIG_SPL_DM_RESET
2554fcb4a04SJoseph Chen brom_download();
2564fcb4a04SJoseph Chen #endif
257ddc9405dSKever Yang arch_cpu_init();
25838771996SKever Yang rk_board_init_f();
2596f80b298SXuhui Lin #if defined(CONFIG_SPL_RAM_DEVICE) && defined(CONFIG_SPL_PCIE_EP_SUPPORT)
2604c8e468bSKever Yang rockchip_pcie_ep_get_firmware();
2614c8e468bSKever Yang #endif
26238771996SKever Yang #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT)
26338771996SKever Yang back_to_bootrom(BROM_BOOT_NEXTSTAGE);
26438771996SKever Yang #endif
26538771996SKever Yang
26638771996SKever Yang }
26738771996SKever Yang
26838771996SKever Yang #ifdef CONFIG_SPL_LOAD_FIT
26938771996SKever Yang int board_fit_config_name_match(const char *name)
27038771996SKever Yang {
27138771996SKever Yang /* Just empty function now - can't decide what to choose */
27238771996SKever Yang debug("%s: %s\n", __func__, name);
27338771996SKever Yang
27438771996SKever Yang return 0;
27538771996SKever Yang }
27638771996SKever Yang #endif
27738771996SKever Yang
27893586e70SJoseph Chen int board_init_f_boot_flags(void)
27993586e70SJoseph Chen {
28093586e70SJoseph Chen int boot_flags = 0;
28193586e70SJoseph Chen
28213ceb2afSXuhui Lin #ifdef CONFIG_ARM64
28313ceb2afSXuhui Lin asm volatile("mrs %0, cntfrq_el0" : "=r" (gd->arch.timer_rate_hz));
28413ceb2afSXuhui Lin #else
28513ceb2afSXuhui Lin asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (gd->arch.timer_rate_hz));
28613ceb2afSXuhui Lin #endif
28713ceb2afSXuhui Lin
288dfe45d3eSJoseph Chen #if CONFIG_IS_ENABLED(FPGA_ROCKCHIP)
2899f68846bSJoseph Chen arch_fpga_init();
2909f68846bSJoseph Chen #endif
291ad771a9cSHuibin Hong #ifdef CONFIG_PSTORE
292ad771a9cSHuibin Hong param_parse_pstore();
293ad771a9cSHuibin Hong #endif
29493586e70SJoseph Chen /* pre-loader serial */
29593586e70SJoseph Chen #if defined(CONFIG_ROCKCHIP_PRELOADER_SERIAL) && \
29693586e70SJoseph Chen defined(CONFIG_ROCKCHIP_PRELOADER_ATAGS)
29793586e70SJoseph Chen struct tag *t;
29893586e70SJoseph Chen
29993586e70SJoseph Chen t = atags_get_tag(ATAG_SERIAL);
30093586e70SJoseph Chen if (t) {
30193586e70SJoseph Chen gd->serial.using_pre_serial = 1;
30293586e70SJoseph Chen gd->serial.enable = t->u.serial.enable;
30393586e70SJoseph Chen gd->serial.baudrate = t->u.serial.baudrate;
30493586e70SJoseph Chen gd->serial.addr = t->u.serial.addr;
30593586e70SJoseph Chen gd->serial.id = t->u.serial.id;
30693586e70SJoseph Chen gd->baudrate = t->u.serial.baudrate;
30793586e70SJoseph Chen if (!t->u.serial.enable)
30893586e70SJoseph Chen boot_flags |= GD_FLG_DISABLE_CONSOLE;
30993586e70SJoseph Chen debug("preloader: enable=%d, addr=0x%x, baudrate=%d, id=%d\n",
31093586e70SJoseph Chen t->u.serial.enable, (u32)t->u.serial.addr,
31193586e70SJoseph Chen t->u.serial.baudrate, t->u.serial.id);
31293586e70SJoseph Chen } else
31393586e70SJoseph Chen #endif
31493586e70SJoseph Chen {
31593586e70SJoseph Chen gd->baudrate = CONFIG_BAUDRATE;
31693586e70SJoseph Chen gd->serial.baudrate = CONFIG_BAUDRATE;
31793586e70SJoseph Chen gd->serial.addr = CONFIG_DEBUG_UART_BASE;
31893586e70SJoseph Chen }
31993586e70SJoseph Chen
32093586e70SJoseph Chen /* The highest priority to turn off (override) console */
32193586e70SJoseph Chen #if defined(CONFIG_DISABLE_CONSOLE)
32293586e70SJoseph Chen boot_flags |= GD_FLG_DISABLE_CONSOLE;
32393586e70SJoseph Chen #endif
32493586e70SJoseph Chen
32593586e70SJoseph Chen return boot_flags;
32693586e70SJoseph Chen }
32793586e70SJoseph Chen
32838771996SKever Yang #ifdef CONFIG_SPL_BOARD_INIT
32938771996SKever Yang __weak int rk_spl_board_init(void)
33038771996SKever Yang {
33138771996SKever Yang return 0;
33238771996SKever Yang }
33338771996SKever Yang
33438771996SKever Yang static int setup_led(void)
33538771996SKever Yang {
33638771996SKever Yang #ifdef CONFIG_SPL_LED
33738771996SKever Yang struct udevice *dev;
33838771996SKever Yang char *led_name;
33938771996SKever Yang int ret;
34038771996SKever Yang
34138771996SKever Yang led_name = fdtdec_get_config_string(gd->fdt_blob, "u-boot,boot-led");
34238771996SKever Yang if (!led_name)
34338771996SKever Yang return 0;
34438771996SKever Yang ret = led_get_by_label(led_name, &dev);
34538771996SKever Yang if (ret) {
34638771996SKever Yang debug("%s: get=%d\n", __func__, ret);
34738771996SKever Yang return ret;
34838771996SKever Yang }
349f0daa6c1SJason Zhu ret = led_set_state(dev, LEDST_ON);
35038771996SKever Yang if (ret)
35138771996SKever Yang return ret;
35238771996SKever Yang #endif
35338771996SKever Yang
35438771996SKever Yang return 0;
35538771996SKever Yang }
35638771996SKever Yang
35738771996SKever Yang void spl_board_init(void)
35838771996SKever Yang {
35938771996SKever Yang int ret;
36038771996SKever Yang
36138771996SKever Yang ret = setup_led();
36238771996SKever Yang
36338771996SKever Yang if (ret) {
36438771996SKever Yang debug("LED ret=%d\n", ret);
36538771996SKever Yang hang();
36638771996SKever Yang }
36738771996SKever Yang
36838771996SKever Yang rk_spl_board_init();
36938771996SKever Yang #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM)
37038771996SKever Yang back_to_bootrom(BROM_BOOT_NEXTSTAGE);
37138771996SKever Yang #endif
37238771996SKever Yang return;
37338771996SKever Yang }
37438771996SKever Yang #endif
37510dd5e8cSJason Zhu
3762323b257SJason Zhu #ifdef CONFIG_SPL_KERNEL_BOOT
3772323b257SJason Zhu static int spl_rockchip_dnl_key_pressed(void)
3782323b257SJason Zhu {
37952387546SJoseph Chen #if defined(CONFIG_SPL_INPUT)
38052387546SJoseph Chen return key_read(KEY_VOLUMEUP);
3812323b257SJason Zhu #else
38252387546SJoseph Chen return 0;
3832323b257SJason Zhu #endif
3842323b257SJason Zhu }
3852323b257SJason Zhu
386c90ee5c7SJason Zhu #ifdef CONFIG_SPL_DM_FUEL_GAUGE
387c90ee5c7SJason Zhu bool spl_is_low_power(void)
388c90ee5c7SJason Zhu {
389c90ee5c7SJason Zhu struct udevice *dev;
390c90ee5c7SJason Zhu int ret, voltage;
391c90ee5c7SJason Zhu
392c90ee5c7SJason Zhu ret = uclass_get_device(UCLASS_FG, 0, &dev);
393c90ee5c7SJason Zhu if (ret) {
394c90ee5c7SJason Zhu debug("Get charge display failed, ret=%d\n", ret);
395c90ee5c7SJason Zhu return false;
396c90ee5c7SJason Zhu }
397c90ee5c7SJason Zhu
398c90ee5c7SJason Zhu voltage = fuel_gauge_get_voltage(dev);
399c90ee5c7SJason Zhu if (voltage >= CONFIG_SPL_POWER_LOW_VOLTAGE_THRESHOLD)
400c90ee5c7SJason Zhu return false;
401c90ee5c7SJason Zhu
402c90ee5c7SJason Zhu return true;
403c90ee5c7SJason Zhu }
404c90ee5c7SJason Zhu #endif
405c90ee5c7SJason Zhu
4062323b257SJason Zhu void spl_next_stage(struct spl_image_info *spl)
4072323b257SJason Zhu {
408c07b486eSXuhui Lin const char *reason[] = { "Recovery key", "Ctrl+c", "LowPwr", "Other" };
4092323b257SJason Zhu uint32_t reg_boot_mode;
410c5d340afSXuhui Lin int i = 0;
4112323b257SJason Zhu
4122323b257SJason Zhu if (spl_rockchip_dnl_key_pressed()) {
413c5d340afSXuhui Lin i = 0;
4142323b257SJason Zhu spl->next_stage = SPL_NEXT_STAGE_UBOOT;
415c5d340afSXuhui Lin goto out;
4162323b257SJason Zhu }
417c5d340afSXuhui Lin
418c5d340afSXuhui Lin if (gd->console_evt == 0x03) {
419c5d340afSXuhui Lin i = 1;
420c5d340afSXuhui Lin spl->next_stage = SPL_NEXT_STAGE_UBOOT;
421c5d340afSXuhui Lin goto out;
422c5d340afSXuhui Lin }
423c5d340afSXuhui Lin
424c90ee5c7SJason Zhu #ifdef CONFIG_SPL_DM_FUEL_GAUGE
425c90ee5c7SJason Zhu if (spl_is_low_power()) {
426c5d340afSXuhui Lin i = 2;
427c90ee5c7SJason Zhu spl->next_stage = SPL_NEXT_STAGE_UBOOT;
428c5d340afSXuhui Lin goto out;
429c90ee5c7SJason Zhu }
430c90ee5c7SJason Zhu #endif
4312323b257SJason Zhu
4322323b257SJason Zhu reg_boot_mode = readl((void *)CONFIG_ROCKCHIP_BOOT_MODE_REG);
4332323b257SJason Zhu switch (reg_boot_mode) {
434c07b486eSXuhui Lin case BOOT_LOADER:
435c07b486eSXuhui Lin case BOOT_FASTBOOT:
436c07b486eSXuhui Lin case BOOT_CHARGING:
437c07b486eSXuhui Lin case BOOT_UMS:
438c07b486eSXuhui Lin case BOOT_DFU:
439c5d340afSXuhui Lin i = 3;
4402323b257SJason Zhu spl->next_stage = SPL_NEXT_STAGE_UBOOT;
441bff96653SXuhui Lin break;
442c07b486eSXuhui Lin default:
443c07b486eSXuhui Lin spl->next_stage = SPL_NEXT_STAGE_KERNEL;
4442323b257SJason Zhu }
445c5d340afSXuhui Lin
446c5d340afSXuhui Lin out:
447c5d340afSXuhui Lin if (spl->next_stage == SPL_NEXT_STAGE_UBOOT)
448c5d340afSXuhui Lin printf("Enter uboot reason: %s\n", reason[i]);
449c5d340afSXuhui Lin
450c5d340afSXuhui Lin return;
451c5d340afSXuhui Lin }
4526afcbf88SJoseph Chen
4534484e03eSJoseph Chen const char *spl_kernel_partition(struct spl_image_info *spl,
4544484e03eSJoseph Chen struct spl_load_info *info)
4554484e03eSJoseph Chen {
4564484e03eSJoseph Chen struct bootloader_message *bmsg = NULL;
4574484e03eSJoseph Chen u32 boot_mode;
4584484e03eSJoseph Chen int ret, cnt;
4594484e03eSJoseph Chen u32 sector = 0;
4604484e03eSJoseph Chen
4614484e03eSJoseph Chen #ifdef CONFIG_SPL_LIBDISK_SUPPORT
4624484e03eSJoseph Chen disk_partition_t part_info;
4634484e03eSJoseph Chen
4644484e03eSJoseph Chen ret = part_get_info_by_name(info->dev, PART_MISC, &part_info);
4654484e03eSJoseph Chen if (ret >= 0)
4664484e03eSJoseph Chen sector = part_info.start;
4674484e03eSJoseph Chen #else
4684484e03eSJoseph Chen sector = CONFIG_SPL_MISC_SECTOR;
4694484e03eSJoseph Chen #endif
4704484e03eSJoseph Chen if (sector) {
4714484e03eSJoseph Chen cnt = DIV_ROUND_UP(sizeof(*bmsg), info->bl_len);
4724484e03eSJoseph Chen bmsg = memalign(ARCH_DMA_MINALIGN, cnt * info->bl_len);
4734484e03eSJoseph Chen ret = info->read(info, sector + BCB_MESSAGE_BLK_OFFSET,
4744484e03eSJoseph Chen cnt, bmsg);
4754484e03eSJoseph Chen if (ret == cnt && !strcmp(bmsg->command, "boot-recovery")) {
4764484e03eSJoseph Chen free(bmsg);
4774484e03eSJoseph Chen return PART_RECOVERY;
4784484e03eSJoseph Chen } else {
4794484e03eSJoseph Chen free(bmsg);
4804484e03eSJoseph Chen }
4814484e03eSJoseph Chen }
4824484e03eSJoseph Chen
4834484e03eSJoseph Chen boot_mode = readl((void *)CONFIG_ROCKCHIP_BOOT_MODE_REG);
4844484e03eSJoseph Chen
4854484e03eSJoseph Chen return (boot_mode == BOOT_RECOVERY) ? PART_RECOVERY : PART_BOOT;
4864484e03eSJoseph Chen }
4870d7b3963SXuhui Lin
488b37add71SXuhui Lin __weak void spl_fdt_fixup_memory(struct spl_image_info *spl_image)
4890d7b3963SXuhui Lin {
4900d7b3963SXuhui Lin void *blob = spl_image->fdt_addr;
4910d7b3963SXuhui Lin struct tag *t;
4920d7b3963SXuhui Lin u64 start[CONFIG_NR_DRAM_BANKS];
4930d7b3963SXuhui Lin u64 size[CONFIG_NR_DRAM_BANKS];
4940d7b3963SXuhui Lin int i, count, err;
4950d7b3963SXuhui Lin
4960d7b3963SXuhui Lin err = fdt_check_header(blob);
4970d7b3963SXuhui Lin if (err < 0) {
4980d7b3963SXuhui Lin printf("Invalid dtb\n");
4990d7b3963SXuhui Lin return;
5000d7b3963SXuhui Lin }
5010d7b3963SXuhui Lin
5020d7b3963SXuhui Lin /* Fixup memory node based on ddr_mem atags */
5030d7b3963SXuhui Lin t = atags_get_tag(ATAG_DDR_MEM);
5040d7b3963SXuhui Lin if (t && t->u.ddr_mem.count) {
5050d7b3963SXuhui Lin count = t->u.ddr_mem.count;
5060d7b3963SXuhui Lin for (i = 0; i < count; i++) {
5070d7b3963SXuhui Lin start[i] = t->u.ddr_mem.bank[i];
5080d7b3963SXuhui Lin size[i] = t->u.ddr_mem.bank[i + count];
509be1263cbSXuhui Lin #ifdef SPL_RESV_MEM_SIZE
510be1263cbSXuhui Lin if ((start[i] == CONFIG_SYS_SDRAM_BASE) &&
511be1263cbSXuhui Lin (start[i] + size[i] > CONFIG_SYS_SDRAM_BASE + SPL_RESV_MEM_SIZE))
512be1263cbSXuhui Lin start[i] += SPL_RESV_MEM_SIZE;
513be1263cbSXuhui Lin #endif
5140d7b3963SXuhui Lin if (size[i] == 0)
5150d7b3963SXuhui Lin continue;
5160d7b3963SXuhui Lin debug("Adding bank: 0x%08llx - 0x%08llx (size: 0x%08llx)\n",
5170d7b3963SXuhui Lin start[i], start[i] + size[i], size[i]);
5180d7b3963SXuhui Lin }
5195c9a04ecSXuhui Lin
5205c9a04ecSXuhui Lin fdt_increase_size(blob, 512);
5215c9a04ecSXuhui Lin
5220d7b3963SXuhui Lin err = fdt_fixup_memory_banks(blob, start, size, count);
5230d7b3963SXuhui Lin if (err < 0) {
5240d7b3963SXuhui Lin printf("Fixup kernel dtb memory node failed: %s\n", fdt_strerror(err));
5250d7b3963SXuhui Lin return;
5260d7b3963SXuhui Lin }
5270d7b3963SXuhui Lin }
5280d7b3963SXuhui Lin
5290d7b3963SXuhui Lin return;
5300d7b3963SXuhui Lin }
53144f37eaaSXuhui Lin
53244f37eaaSXuhui Lin #if defined(CONFIG_SPL_ROCKCHIP_HWID_DTB)
53344f37eaaSXuhui Lin int spl_find_hwid_dtb(const char *fdt_name)
53444f37eaaSXuhui Lin {
53544f37eaaSXuhui Lin hwid_init_data();
53644f37eaaSXuhui Lin
53744f37eaaSXuhui Lin return hwid_dtb_is_available(fdt_name);
53844f37eaaSXuhui Lin }
53944f37eaaSXuhui Lin #endif
540*b6bda7d5SXuhui Lin
541*b6bda7d5SXuhui Lin int spl_fdt_chosen_bootargs(struct spl_load_info *info, void *fdt)
542*b6bda7d5SXuhui Lin {
543*b6bda7d5SXuhui Lin __maybe_unused struct blk_desc *desc = info->dev;
544*b6bda7d5SXuhui Lin
545*b6bda7d5SXuhui Lin #ifdef CONFIG_SPL_AB
546*b6bda7d5SXuhui Lin char slot_suffix[3] = {0};
547*b6bda7d5SXuhui Lin
548*b6bda7d5SXuhui Lin if (!spl_get_current_slot(desc, "misc", slot_suffix))
549*b6bda7d5SXuhui Lin spl_ab_bootargs_append_slot(fdt, slot_suffix);
550*b6bda7d5SXuhui Lin #endif
551*b6bda7d5SXuhui Lin
552*b6bda7d5SXuhui Lin #ifdef CONFIG_SPL_ENVF
553*b6bda7d5SXuhui Lin char *part_type[] = { "mtdparts", "blkdevparts" };
554*b6bda7d5SXuhui Lin char *env = NULL;
555*b6bda7d5SXuhui Lin char *part_list;
556*b6bda7d5SXuhui Lin int id = 0, ret = 0;
557*b6bda7d5SXuhui Lin
558*b6bda7d5SXuhui Lin env = envf_get(desc, part_type[id]);
559*b6bda7d5SXuhui Lin if (!env)
560*b6bda7d5SXuhui Lin env = envf_get(desc, part_type[++id]);
561*b6bda7d5SXuhui Lin if (env) {
562*b6bda7d5SXuhui Lin if (!strstr(env, part_type[id])) {
563*b6bda7d5SXuhui Lin part_list = calloc(1, strlen(env) + strlen(part_type[id]) + 2);
564*b6bda7d5SXuhui Lin if (part_list) {
565*b6bda7d5SXuhui Lin strcat(part_list, part_type[id]);
566*b6bda7d5SXuhui Lin strcat(part_list, "=");
567*b6bda7d5SXuhui Lin strcat(part_list, env);
568*b6bda7d5SXuhui Lin }
569*b6bda7d5SXuhui Lin } else {
570*b6bda7d5SXuhui Lin part_list = env;
571*b6bda7d5SXuhui Lin }
572*b6bda7d5SXuhui Lin ret = fdt_bootargs_append(fdt, part_list);
573*b6bda7d5SXuhui Lin if (ret) {
574*b6bda7d5SXuhui Lin printf("Append parts info to bootargs fail");
575*b6bda7d5SXuhui Lin return ret;
576*b6bda7d5SXuhui Lin }
577*b6bda7d5SXuhui Lin debug("## parts: %s\n\n", part_list);
578*b6bda7d5SXuhui Lin
579*b6bda7d5SXuhui Lin env = envf_get(desc, "sys_bootargs");
580*b6bda7d5SXuhui Lin env = env + strlen("sys_bootargs=");
581*b6bda7d5SXuhui Lin if (env) {
582*b6bda7d5SXuhui Lin ret = fdt_bootargs_append(fdt, env);
583*b6bda7d5SXuhui Lin if (ret) {
584*b6bda7d5SXuhui Lin printf("Append sys_bootargs to bootargs fail");
585*b6bda7d5SXuhui Lin return ret;
586*b6bda7d5SXuhui Lin }
587*b6bda7d5SXuhui Lin debug("## sys_bootargs: %s\n\n", env);
588*b6bda7d5SXuhui Lin }
589*b6bda7d5SXuhui Lin }
590*b6bda7d5SXuhui Lin #endif
591*b6bda7d5SXuhui Lin #ifdef CONFIG_MTD_BLK
592*b6bda7d5SXuhui Lin if (!env && desc->if_type == IF_TYPE_MTD) {
593*b6bda7d5SXuhui Lin char *mtd_par_info = mtd_part_parse(desc);
594*b6bda7d5SXuhui Lin
595*b6bda7d5SXuhui Lin ret = fdt_bootargs_append(fdt, mtd_par_info);
596*b6bda7d5SXuhui Lin if (ret) {
597*b6bda7d5SXuhui Lin printf("Append mtdparts info to bootargs fail");
598*b6bda7d5SXuhui Lin return ret;
599*b6bda7d5SXuhui Lin }
600*b6bda7d5SXuhui Lin debug("## mtdparts: %s\n\n", mtd_par_info);
601*b6bda7d5SXuhui Lin }
602*b6bda7d5SXuhui Lin #endif
603*b6bda7d5SXuhui Lin #ifdef CONFIG_ROCKCHIP_META
604*b6bda7d5SXuhui Lin rk_meta_bootargs_append(fdt);
605*b6bda7d5SXuhui Lin #endif
606*b6bda7d5SXuhui Lin
607*b6bda7d5SXuhui Lin return 0;
608*b6bda7d5SXuhui Lin }
6094484e03eSJoseph Chen #endif
6104484e03eSJoseph Chen
6110d7b3963SXuhui Lin void spl_perform_fixups(struct spl_image_info *spl_image)
6120d7b3963SXuhui Lin {
6130d7b3963SXuhui Lin #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
6140d7b3963SXuhui Lin atags_set_bootdev_by_spl_bootdevice(spl_image->boot_device);
6150d7b3963SXuhui Lin #ifdef BUILD_SPL_TAG
6160d7b3963SXuhui Lin atags_set_shared_fwver(FW_SPL, "spl-"BUILD_SPL_TAG);
6170d7b3963SXuhui Lin #endif
6180d7b3963SXuhui Lin #endif
6190d7b3963SXuhui Lin #if defined(CONFIG_SPL_KERNEL_BOOT)
6200d7b3963SXuhui Lin if (spl_image->next_stage == SPL_NEXT_STAGE_KERNEL)
6210d7b3963SXuhui Lin spl_fdt_fixup_memory(spl_image);
6220d7b3963SXuhui Lin #endif
6230d7b3963SXuhui Lin return;
6240d7b3963SXuhui Lin }
6250d7b3963SXuhui Lin
626cead3ab8SJason Zhu void spl_hang_reset(void)
627cead3ab8SJason Zhu {
628cead3ab8SJason Zhu printf("# Reset the board to bootrom #\n");
629cead3ab8SJason Zhu #if defined(CONFIG_SPL_SYSRESET) && defined(CONFIG_SPL_DRIVERS_MISC_SUPPORT)
6305ead1aa0SJoseph Chen /* reset is available after dm setup */
6315ead1aa0SJoseph Chen if (gd->flags & GD_FLG_SPL_EARLY_INIT) {
632cead3ab8SJason Zhu writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG);
633cead3ab8SJason Zhu do_reset(NULL, 0, 0, NULL);
6345ead1aa0SJoseph Chen }
635cead3ab8SJason Zhu #endif
636cead3ab8SJason Zhu }
637a5373663SJason Zhu
638cf13b784SJoseph Chen #ifdef CONFIG_SPL_FIT_ROLLBACK_PROTECT
639cf13b784SJoseph Chen int fit_read_otp_rollback_index(uint32_t fit_index, uint32_t *otp_index)
640cf13b784SJoseph Chen {
641cf13b784SJoseph Chen int ret = 0;
642cf13b784SJoseph Chen
643cf13b784SJoseph Chen *otp_index = 0;
644299f09a0SJason Zhu #if defined(CONFIG_SPL_ROCKCHIP_SECURE_OTP)
645cf13b784SJoseph Chen struct udevice *dev;
646cf13b784SJoseph Chen u32 index, i, otp_version;
647cf13b784SJoseph Chen u32 bit_count;
648cf13b784SJoseph Chen
649cf13b784SJoseph Chen dev = misc_otp_get_device(OTP_S);
650cf13b784SJoseph Chen if (!dev)
651cf13b784SJoseph Chen return -ENODEV;
652cf13b784SJoseph Chen
653cf13b784SJoseph Chen otp_version = 0;
654cf13b784SJoseph Chen for (i = 0; i < OTP_UBOOT_ROLLBACK_WORDS; i++) {
655bf39446fSJason Zhu if (misc_otp_read(dev, OTP_UBOOT_ROLLBACK_OFFSET + i * 4,
656cf13b784SJoseph Chen &index,
657cf13b784SJoseph Chen 4)) {
658cf13b784SJoseph Chen printf("Can't read rollback index\n");
659cf13b784SJoseph Chen return -EIO;
660cf13b784SJoseph Chen }
661bf39446fSJason Zhu
662cf13b784SJoseph Chen bit_count = fls(index);
663cf13b784SJoseph Chen otp_version += bit_count;
664cf13b784SJoseph Chen }
665cf13b784SJoseph Chen *otp_index = otp_version;
666cf13b784SJoseph Chen #endif
667cf13b784SJoseph Chen
668cf13b784SJoseph Chen return ret;
669cf13b784SJoseph Chen }
670cf13b784SJoseph Chen
671cf13b784SJoseph Chen static int fit_write_otp_rollback_index(u32 fit_index)
672cf13b784SJoseph Chen {
673299f09a0SJason Zhu #if defined(CONFIG_SPL_ROCKCHIP_SECURE_OTP)
674cf13b784SJoseph Chen struct udevice *dev;
675cf13b784SJoseph Chen u32 index, i, otp_index;
676cf13b784SJoseph Chen
677d5989feaSJoseph Chen if (!fit_index)
678d5989feaSJoseph Chen return 0;
679d5989feaSJoseph Chen
680d5989feaSJoseph Chen if (fit_index > OTP_UBOOT_ROLLBACK_WORDS * 32)
681cf13b784SJoseph Chen return -EINVAL;
682cf13b784SJoseph Chen
683cf13b784SJoseph Chen dev = misc_otp_get_device(OTP_S);
684cf13b784SJoseph Chen if (!dev)
685cf13b784SJoseph Chen return -ENODEV;
686cf13b784SJoseph Chen
687cf13b784SJoseph Chen if (fit_read_otp_rollback_index(fit_index, &otp_index))
688cf13b784SJoseph Chen return -EIO;
689cf13b784SJoseph Chen
690cf13b784SJoseph Chen if (otp_index < fit_index) {
691cf13b784SJoseph Chen /* Write new SW version to otp */
692cf13b784SJoseph Chen for (i = 0; i < OTP_UBOOT_ROLLBACK_WORDS; i++) {
693bf39446fSJason Zhu /*
694bf39446fSJason Zhu * If fit_index is equal to 0, then execute 0xffffffff >> 32.
695bf39446fSJason Zhu * But the operand can only be 0 - 31. The "0xffffffff >> 32" is
696bf39446fSJason Zhu * actually be "0xffffffff >> 0".
697bf39446fSJason Zhu */
698bf39446fSJason Zhu if (!fit_index)
699bf39446fSJason Zhu break;
700cf13b784SJoseph Chen /* convert to base-1 representation */
701cf13b784SJoseph Chen index = 0xffffffff >> (OTP_ALL_ONES_NUM_BITS -
702cf13b784SJoseph Chen min(fit_index, (u32)OTP_ALL_ONES_NUM_BITS));
703cf13b784SJoseph Chen fit_index -= min(fit_index,
704cf13b784SJoseph Chen (u32)OTP_ALL_ONES_NUM_BITS);
705cf13b784SJoseph Chen if (index) {
706bf39446fSJason Zhu if (misc_otp_write(dev, OTP_UBOOT_ROLLBACK_OFFSET + i * 4,
707cf13b784SJoseph Chen &index,
708cf13b784SJoseph Chen 4)) {
709cf13b784SJoseph Chen printf("Can't write rollback index\n");
710cf13b784SJoseph Chen return -EIO;
711cf13b784SJoseph Chen }
712cf13b784SJoseph Chen }
713cf13b784SJoseph Chen }
714cf13b784SJoseph Chen }
715cf13b784SJoseph Chen #endif
716cf13b784SJoseph Chen
717cf13b784SJoseph Chen return 0;
718cf13b784SJoseph Chen }
719cf13b784SJoseph Chen #endif
720cf13b784SJoseph Chen
721ed5a55baSJoseph Chen int spl_board_prepare_for_jump(struct spl_image_info *spl_image)
722ed5a55baSJoseph Chen {
723cf13b784SJoseph Chen #ifdef CONFIG_SPL_FIT_ROLLBACK_PROTECT
7248d26d4b3SJoseph Chen int ret;
7258d26d4b3SJoseph Chen
7268d26d4b3SJoseph Chen ret = fit_write_otp_rollback_index(gd->rollback_index);
7278d26d4b3SJoseph Chen if (ret) {
7288d26d4b3SJoseph Chen panic("Failed to write fit rollback index %d, ret=%d",
7298d26d4b3SJoseph Chen gd->rollback_index, ret);
7308d26d4b3SJoseph Chen }
731ed5a55baSJoseph Chen #endif
732a5401a9dSJoseph Chen
733a5401a9dSJoseph Chen #ifdef CONFIG_SPL_ROCKCHIP_HW_DECOMPRESS
734a5401a9dSJoseph Chen misc_decompress_cleanup();
735a5401a9dSJoseph Chen #endif
73652c8858eSJoseph Chen spl_rk_board_prepare_for_jump(spl_image);
73752c8858eSJoseph Chen
738ed5a55baSJoseph Chen return 0;
739ed5a55baSJoseph Chen }
740