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