xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/spl.c (revision cf13b784384f1f05c8a3a49a76e67e5e77e96caa)
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>
838771996SKever Yang #include <debug_uart.h>
938771996SKever Yang #include <dm.h>
102323b257SJason Zhu #include <key.h>
11a5373663SJason Zhu #include <misc.h>
1238771996SKever Yang #include <ram.h>
1338771996SKever Yang #include <spl.h>
146afcbf88SJoseph Chen #include <optee_include/OpteeClientInterface.h>
1538771996SKever Yang #include <asm/arch/bootrom.h>
1610dd5e8cSJason Zhu #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
1710dd5e8cSJason Zhu #include <asm/arch/rk_atags.h>
1810dd5e8cSJason Zhu #endif
19e1f97ec3SYouMin Chen #include <asm/arch/sdram.h>
202323b257SJason Zhu #include <asm/arch/boot_mode.h>
2152f7b21dSZhihuan He #include <asm/arch-rockchip/sys_proto.h>
2238771996SKever Yang #include <asm/io.h>
2338771996SKever Yang 
2438771996SKever Yang DECLARE_GLOBAL_DATA_PTR;
2538771996SKever Yang 
2638771996SKever Yang void board_return_to_bootrom(void)
2738771996SKever Yang {
2838771996SKever Yang 	back_to_bootrom(BROM_BOOT_NEXTSTAGE);
2938771996SKever Yang }
3038771996SKever Yang 
3138771996SKever Yang __weak const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = {
3238771996SKever Yang };
3338771996SKever Yang 
3438771996SKever Yang const char *board_spl_was_booted_from(void)
3538771996SKever Yang {
3638771996SKever Yang 	u32  bootdevice_brom_id = readl(BROM_BOOTSOURCE_ID_ADDR);
3738771996SKever Yang 	const char *bootdevice_ofpath = NULL;
3838771996SKever Yang 
3938771996SKever Yang 	if (bootdevice_brom_id < ARRAY_SIZE(boot_devices))
4038771996SKever Yang 		bootdevice_ofpath = boot_devices[bootdevice_brom_id];
4138771996SKever Yang 
4238771996SKever Yang 	if (bootdevice_ofpath)
4338771996SKever Yang 		debug("%s: brom_bootdevice_id %x maps to '%s'\n",
4438771996SKever Yang 		      __func__, bootdevice_brom_id, bootdevice_ofpath);
4538771996SKever Yang 	else
4638771996SKever Yang 		debug("%s: failed to resolve brom_bootdevice_id %x\n",
4738771996SKever Yang 		      __func__, bootdevice_brom_id);
4838771996SKever Yang 
4938771996SKever Yang 	return bootdevice_ofpath;
5038771996SKever Yang }
5138771996SKever Yang 
5238771996SKever Yang u32 spl_boot_device(void)
5338771996SKever Yang {
5438771996SKever Yang 	u32 boot_device = BOOT_DEVICE_MMC1;
5538771996SKever Yang 
5638771996SKever Yang #if defined(CONFIG_TARGET_CHROMEBOOK_JERRY) || \
5738771996SKever Yang 		defined(CONFIG_TARGET_CHROMEBIT_MICKEY) || \
5838771996SKever Yang 		defined(CONFIG_TARGET_CHROMEBOOK_MINNIE)
5938771996SKever Yang 	return BOOT_DEVICE_SPI;
6038771996SKever Yang #endif
6138771996SKever Yang 	if (CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM))
6238771996SKever Yang 		return BOOT_DEVICE_BOOTROM;
6338771996SKever Yang 
6438771996SKever Yang 	return boot_device;
6538771996SKever Yang }
6638771996SKever Yang 
6738771996SKever Yang u32 spl_boot_mode(const u32 boot_device)
6838771996SKever Yang {
6938771996SKever Yang 	return MMCSD_MODE_RAW;
7038771996SKever Yang }
7138771996SKever Yang 
7238771996SKever Yang __weak void rockchip_stimer_init(void)
7338771996SKever Yang {
74d74e8763SKever Yang 	/* If Timer already enabled, don't re-init it */
75d74e8763SKever Yang 	u32 reg = readl(CONFIG_ROCKCHIP_STIMER_BASE + 0x10);
76d74e8763SKever Yang 	if ( reg & 0x1 )
77d74e8763SKever Yang 		return;
78a09afa08SKever Yang #ifndef CONFIG_ARM64
79a09afa08SKever Yang 	asm volatile("mcr p15, 0, %0, c14, c0, 0"
80a09afa08SKever Yang 		     : : "r"(COUNTER_FREQUENCY));
81a09afa08SKever Yang #endif
8238771996SKever Yang 	writel(0, CONFIG_ROCKCHIP_STIMER_BASE + 0x10);
8338771996SKever Yang 	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE);
8438771996SKever Yang 	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE + 4);
8538771996SKever Yang 	writel(1, CONFIG_ROCKCHIP_STIMER_BASE + 0x10);
8638771996SKever Yang }
8738771996SKever Yang 
8838771996SKever Yang __weak int arch_cpu_init(void)
8938771996SKever Yang {
9038771996SKever Yang 	return 0;
9138771996SKever Yang }
9238771996SKever Yang 
9338771996SKever Yang __weak int rk_board_init_f(void)
9438771996SKever Yang {
9538771996SKever Yang 	return 0;
9638771996SKever Yang }
9738771996SKever Yang 
98e62c13b9SZhihuan He #ifndef CONFIG_SPL_LIBGENERIC_SUPPORT
99e62c13b9SZhihuan He void udelay(unsigned long usec)
100e62c13b9SZhihuan He {
101e62c13b9SZhihuan He 	__udelay(usec);
102e62c13b9SZhihuan He }
103e62c13b9SZhihuan He 
104e62c13b9SZhihuan He void hang(void)
105e62c13b9SZhihuan He {
106e62c13b9SZhihuan He 	bootstage_error(BOOTSTAGE_ID_NEED_RESET);
107e62c13b9SZhihuan He 	for (;;)
108e62c13b9SZhihuan He 		;
109e62c13b9SZhihuan He }
110e62c13b9SZhihuan He 
111e62c13b9SZhihuan He /**
112e62c13b9SZhihuan He  * memset - Fill a region of memory with the given value
113e62c13b9SZhihuan He  * @s: Pointer to the start of the area.
114e62c13b9SZhihuan He  * @c: The byte to fill the area with
115e62c13b9SZhihuan He  * @count: The size of the area.
116e62c13b9SZhihuan He  *
117e62c13b9SZhihuan He  * Do not use memset() to access IO space, use memset_io() instead.
118e62c13b9SZhihuan He  */
119e62c13b9SZhihuan He void *memset(void *s, int c, size_t count)
120e62c13b9SZhihuan He {
121e62c13b9SZhihuan He 	unsigned long *sl = (unsigned long *)s;
122e62c13b9SZhihuan He 	char *s8;
123e62c13b9SZhihuan He 
124e62c13b9SZhihuan He #if !CONFIG_IS_ENABLED(TINY_MEMSET)
125e62c13b9SZhihuan He 	unsigned long cl = 0;
126e62c13b9SZhihuan He 	int i;
127e62c13b9SZhihuan He 
128e62c13b9SZhihuan He 	/* do it one word at a time (32 bits or 64 bits) while possible */
129e62c13b9SZhihuan He 	if (((ulong)s & (sizeof(*sl) - 1)) == 0) {
130e62c13b9SZhihuan He 		for (i = 0; i < sizeof(*sl); i++) {
131e62c13b9SZhihuan He 			cl <<= 8;
132e62c13b9SZhihuan He 			cl |= c & 0xff;
133e62c13b9SZhihuan He 		}
134e62c13b9SZhihuan He 		while (count >= sizeof(*sl)) {
135e62c13b9SZhihuan He 			*sl++ = cl;
136e62c13b9SZhihuan He 			count -= sizeof(*sl);
137e62c13b9SZhihuan He 		}
138e62c13b9SZhihuan He 	}
139e62c13b9SZhihuan He #endif /* fill 8 bits at a time */
140e62c13b9SZhihuan He 	s8 = (char *)sl;
141e62c13b9SZhihuan He 	while (count--)
142e62c13b9SZhihuan He 		*s8++ = c;
143e62c13b9SZhihuan He 
144e62c13b9SZhihuan He 	return s;
145e62c13b9SZhihuan He }
146e62c13b9SZhihuan He #endif
147e62c13b9SZhihuan He 
14838771996SKever Yang void board_init_f(ulong dummy)
14938771996SKever Yang {
15038771996SKever Yang #ifdef CONFIG_SPL_FRAMEWORK
15138771996SKever Yang 	int ret;
15238771996SKever Yang #if !defined(CONFIG_SUPPORT_TPL)
15338771996SKever Yang 	struct udevice *dev;
15438771996SKever Yang #endif
15538771996SKever Yang #endif
15638771996SKever Yang 
157a09afa08SKever Yang 	rockchip_stimer_init();
15838771996SKever Yang #define EARLY_UART
15938771996SKever Yang #if defined(EARLY_UART) && defined(CONFIG_DEBUG_UART)
16038771996SKever Yang 	/*
16138771996SKever Yang 	 * Debug UART can be used from here if required:
16238771996SKever Yang 	 *
16338771996SKever Yang 	 * debug_uart_init();
16438771996SKever Yang 	 * printch('a');
16538771996SKever Yang 	 * printhex8(0x1234);
16638771996SKever Yang 	 * printascii("string");
16738771996SKever Yang 	 */
16838771996SKever Yang 	debug_uart_init();
16938771996SKever Yang 	printascii("U-Boot SPL board init");
17038771996SKever Yang #endif
17138771996SKever Yang 
17238771996SKever Yang #ifdef CONFIG_SPL_FRAMEWORK
17338771996SKever Yang 	ret = spl_early_init();
17438771996SKever Yang 	if (ret) {
17538771996SKever Yang 		printf("spl_early_init() failed: %d\n", ret);
17638771996SKever Yang 		hang();
17738771996SKever Yang 	}
17838771996SKever Yang #if !defined(CONFIG_SUPPORT_TPL)
17938771996SKever Yang 	debug("\nspl:init dram\n");
18038771996SKever Yang 	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
18138771996SKever Yang 	if (ret) {
18238771996SKever Yang 		printf("DRAM init failed: %d\n", ret);
18338771996SKever Yang 		return;
18438771996SKever Yang 	}
18538771996SKever Yang #endif
18638771996SKever Yang 	preloader_console_init();
18738771996SKever Yang #else
18838771996SKever Yang 	/* Some SoCs like rk3036 does not use any frame work */
18938771996SKever Yang 	sdram_init();
19038771996SKever Yang #endif
19138771996SKever Yang 
192ddc9405dSKever Yang 	arch_cpu_init();
19338771996SKever Yang 	rk_board_init_f();
19438771996SKever Yang #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT)
19538771996SKever Yang 	back_to_bootrom(BROM_BOOT_NEXTSTAGE);
19638771996SKever Yang #endif
19738771996SKever Yang 
19838771996SKever Yang }
19938771996SKever Yang 
20038771996SKever Yang #ifdef CONFIG_SPL_LOAD_FIT
20138771996SKever Yang int board_fit_config_name_match(const char *name)
20238771996SKever Yang {
20338771996SKever Yang 	/* Just empty function now - can't decide what to choose */
20438771996SKever Yang 	debug("%s: %s\n", __func__, name);
20538771996SKever Yang 
20638771996SKever Yang 	return 0;
20738771996SKever Yang }
20838771996SKever Yang #endif
20938771996SKever Yang 
21038771996SKever Yang #ifdef CONFIG_SPL_BOARD_INIT
21138771996SKever Yang __weak int rk_spl_board_init(void)
21238771996SKever Yang {
21338771996SKever Yang 	return 0;
21438771996SKever Yang }
21538771996SKever Yang 
21638771996SKever Yang static int setup_led(void)
21738771996SKever Yang {
21838771996SKever Yang #ifdef CONFIG_SPL_LED
21938771996SKever Yang 	struct udevice *dev;
22038771996SKever Yang 	char *led_name;
22138771996SKever Yang 	int ret;
22238771996SKever Yang 
22338771996SKever Yang 	led_name = fdtdec_get_config_string(gd->fdt_blob, "u-boot,boot-led");
22438771996SKever Yang 	if (!led_name)
22538771996SKever Yang 		return 0;
22638771996SKever Yang 	ret = led_get_by_label(led_name, &dev);
22738771996SKever Yang 	if (ret) {
22838771996SKever Yang 		debug("%s: get=%d\n", __func__, ret);
22938771996SKever Yang 		return ret;
23038771996SKever Yang 	}
23138771996SKever Yang 	ret = led_set_on(dev, 1);
23238771996SKever Yang 	if (ret)
23338771996SKever Yang 		return ret;
23438771996SKever Yang #endif
23538771996SKever Yang 
23638771996SKever Yang 	return 0;
23738771996SKever Yang }
23838771996SKever Yang 
23938771996SKever Yang void spl_board_init(void)
24038771996SKever Yang {
24138771996SKever Yang 	int ret;
24238771996SKever Yang 
24338771996SKever Yang 	ret = setup_led();
24438771996SKever Yang 
24538771996SKever Yang 	if (ret) {
24638771996SKever Yang 		debug("LED ret=%d\n", ret);
24738771996SKever Yang 		hang();
24838771996SKever Yang 	}
24938771996SKever Yang 
25038771996SKever Yang 	rk_spl_board_init();
25138771996SKever Yang #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM)
25238771996SKever Yang 	back_to_bootrom(BROM_BOOT_NEXTSTAGE);
25338771996SKever Yang #endif
25438771996SKever Yang 	return;
25538771996SKever Yang }
25638771996SKever Yang #endif
25710dd5e8cSJason Zhu 
25810dd5e8cSJason Zhu void spl_perform_fixups(struct spl_image_info *spl_image)
25910dd5e8cSJason Zhu {
26010dd5e8cSJason Zhu #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
26110dd5e8cSJason Zhu 	atags_set_bootdev_by_spl_bootdevice(spl_image->boot_device);
26210dd5e8cSJason Zhu #endif
26310dd5e8cSJason Zhu 	return;
26410dd5e8cSJason Zhu }
26510dd5e8cSJason Zhu 
2662323b257SJason Zhu #ifdef CONFIG_SPL_KERNEL_BOOT
2672323b257SJason Zhu static int spl_rockchip_dnl_key_pressed(void)
2682323b257SJason Zhu {
26952387546SJoseph Chen #if defined(CONFIG_SPL_INPUT)
27052387546SJoseph Chen 	return key_read(KEY_VOLUMEUP);
2712323b257SJason Zhu #else
27252387546SJoseph Chen 	return 0;
2732323b257SJason Zhu #endif
2742323b257SJason Zhu }
2752323b257SJason Zhu 
2762323b257SJason Zhu void spl_next_stage(struct spl_image_info *spl)
2772323b257SJason Zhu {
2782323b257SJason Zhu 	uint32_t reg_boot_mode;
2792323b257SJason Zhu 
2802323b257SJason Zhu 	if (spl_rockchip_dnl_key_pressed()) {
2812323b257SJason Zhu 		spl->next_stage = SPL_NEXT_STAGE_UBOOT;
2822323b257SJason Zhu 		return;
2832323b257SJason Zhu 	}
2842323b257SJason Zhu 
2852323b257SJason Zhu 	reg_boot_mode = readl((void *)CONFIG_ROCKCHIP_BOOT_MODE_REG);
2862323b257SJason Zhu 	switch (reg_boot_mode) {
287747423edSJason Zhu 	case BOOT_COLD:
2882323b257SJason Zhu 	case BOOT_PANIC:
2892323b257SJason Zhu 	case BOOT_WATCHDOG:
2902323b257SJason Zhu 	case BOOT_NORMAL:
2912323b257SJason Zhu 		spl->next_stage = SPL_NEXT_STAGE_KERNEL;
2922323b257SJason Zhu 		break;
2932323b257SJason Zhu 	default:
2942323b257SJason Zhu 		spl->next_stage = SPL_NEXT_STAGE_UBOOT;
2952323b257SJason Zhu 	}
2962323b257SJason Zhu }
2972323b257SJason Zhu #endif
2986afcbf88SJoseph Chen 
299cead3ab8SJason Zhu void spl_hang_reset(void)
300cead3ab8SJason Zhu {
301cead3ab8SJason Zhu 	printf("# Reset the board to bootrom #\n");
302cead3ab8SJason Zhu #if defined(CONFIG_SPL_SYSRESET) && defined(CONFIG_SPL_DRIVERS_MISC_SUPPORT)
303cead3ab8SJason Zhu 	writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG);
304cead3ab8SJason Zhu 	do_reset(NULL, 0, 0, NULL);
305cead3ab8SJason Zhu #endif
306cead3ab8SJason Zhu }
307a5373663SJason Zhu 
308*cf13b784SJoseph Chen #ifdef CONFIG_SPL_FIT_ROLLBACK_PROTECT
309*cf13b784SJoseph Chen int fit_read_otp_rollback_index(uint32_t fit_index, uint32_t *otp_index)
310*cf13b784SJoseph Chen {
311*cf13b784SJoseph Chen 	int ret = 0;
312*cf13b784SJoseph Chen 
313*cf13b784SJoseph Chen 	*otp_index = 0;
314*cf13b784SJoseph Chen #if defined(CONFIG_SPL_ROCKCHIP_SECURE_OTP_V2)
315*cf13b784SJoseph Chen 	struct udevice *dev;
316*cf13b784SJoseph Chen 	u32 index, i, otp_version;
317*cf13b784SJoseph Chen 	u32 bit_count;
318*cf13b784SJoseph Chen 
319*cf13b784SJoseph Chen 	dev = misc_otp_get_device(OTP_S);
320*cf13b784SJoseph Chen 	if (!dev)
321*cf13b784SJoseph Chen 		return -ENODEV;
322*cf13b784SJoseph Chen 
323*cf13b784SJoseph Chen 	otp_version = 0;
324*cf13b784SJoseph Chen 	for (i = 0; i < OTP_UBOOT_ROLLBACK_WORDS; i++) {
325*cf13b784SJoseph Chen 		if (misc_otp_read(dev, 4 *
326*cf13b784SJoseph Chen 		    (OTP_UBOOT_ROLLBACK_OFFSET + i),
327*cf13b784SJoseph Chen 		    &index,
328*cf13b784SJoseph Chen 		    4)) {
329*cf13b784SJoseph Chen 			printf("Can't read rollback index\n");
330*cf13b784SJoseph Chen 			return -EIO;
331*cf13b784SJoseph Chen 		}
332*cf13b784SJoseph Chen 		bit_count = fls(index);
333*cf13b784SJoseph Chen 		otp_version += bit_count;
334*cf13b784SJoseph Chen 	}
335*cf13b784SJoseph Chen 	*otp_index = otp_version;
336*cf13b784SJoseph Chen #endif
337*cf13b784SJoseph Chen 
338*cf13b784SJoseph Chen 	return ret;
339*cf13b784SJoseph Chen }
340*cf13b784SJoseph Chen 
341*cf13b784SJoseph Chen static int fit_write_otp_rollback_index(u32 fit_index)
342*cf13b784SJoseph Chen {
343*cf13b784SJoseph Chen #if defined(CONFIG_SPL_ROCKCHIP_SECURE_OTP_V2)
344*cf13b784SJoseph Chen 	struct udevice *dev;
345*cf13b784SJoseph Chen 	u32 index, i, otp_index;
346*cf13b784SJoseph Chen 
347*cf13b784SJoseph Chen 	if (!fit_index || fit_index > OTP_UBOOT_ROLLBACK_WORDS * 32)
348*cf13b784SJoseph Chen 		return -EINVAL;
349*cf13b784SJoseph Chen 
350*cf13b784SJoseph Chen 	dev = misc_otp_get_device(OTP_S);
351*cf13b784SJoseph Chen 	if (!dev)
352*cf13b784SJoseph Chen 		return -ENODEV;
353*cf13b784SJoseph Chen 
354*cf13b784SJoseph Chen 	if (fit_read_otp_rollback_index(fit_index, &otp_index))
355*cf13b784SJoseph Chen 		return -EIO;
356*cf13b784SJoseph Chen 
357*cf13b784SJoseph Chen 	if (otp_index < fit_index) {
358*cf13b784SJoseph Chen 		/* Write new SW version to otp */
359*cf13b784SJoseph Chen 		for (i = 0; i < OTP_UBOOT_ROLLBACK_WORDS; i++) {
360*cf13b784SJoseph Chen 			/* convert to base-1 representation */
361*cf13b784SJoseph Chen 			index = 0xffffffff >> (OTP_ALL_ONES_NUM_BITS -
362*cf13b784SJoseph Chen 				min(fit_index, (u32)OTP_ALL_ONES_NUM_BITS));
363*cf13b784SJoseph Chen 			fit_index -= min(fit_index,
364*cf13b784SJoseph Chen 					  (u32)OTP_ALL_ONES_NUM_BITS);
365*cf13b784SJoseph Chen 			if (index) {
366*cf13b784SJoseph Chen 				if (misc_otp_write(dev, 4 *
367*cf13b784SJoseph Chen 				    (OTP_UBOOT_ROLLBACK_OFFSET + i),
368*cf13b784SJoseph Chen 				    &index,
369*cf13b784SJoseph Chen 				    4)) {
370*cf13b784SJoseph Chen 					printf("Can't write rollback index\n");
371*cf13b784SJoseph Chen 					return -EIO;
372*cf13b784SJoseph Chen 				}
373*cf13b784SJoseph Chen 			}
374*cf13b784SJoseph Chen 		}
375*cf13b784SJoseph Chen 	}
376*cf13b784SJoseph Chen #endif
377*cf13b784SJoseph Chen 
378*cf13b784SJoseph Chen 	return 0;
379*cf13b784SJoseph Chen }
380*cf13b784SJoseph Chen #endif
381*cf13b784SJoseph Chen 
382ed5a55baSJoseph Chen int spl_board_prepare_for_jump(struct spl_image_info *spl_image)
383ed5a55baSJoseph Chen {
384*cf13b784SJoseph Chen #ifdef CONFIG_SPL_FIT_ROLLBACK_PROTECT
385*cf13b784SJoseph Chen 	return fit_write_otp_rollback_index(gd->rollback_index);
386ed5a55baSJoseph Chen #endif
387ed5a55baSJoseph Chen 	return 0;
388ed5a55baSJoseph Chen }
389