138771996SKever Yang /* 238771996SKever Yang * (C) Copyright 2017 Rockchip Electronics Co., Ltd. 338771996SKever Yang * 438771996SKever Yang * SPDX-License-Identifier: GPL-2.0+ 538771996SKever Yang */ 62208cd92SJoseph Chen 738771996SKever Yang #include <common.h> 850d35c45SJoseph Chen #include <amp.h> 9ac5d8aa9SJoseph Chen #include <android_bootloader.h> 10ac5d8aa9SJoseph Chen #include <android_image.h> 1186f870d6SJoseph Chen #include <bidram.h> 120ed06f16SJoseph Chen #include <boot_rkimg.h> 130ed06f16SJoseph Chen #include <cli.h> 142208cd92SJoseph Chen #include <clk.h> 152208cd92SJoseph Chen #include <console.h> 16575777c5SKever Yang #include <debug_uart.h> 172208cd92SJoseph Chen #include <dm.h> 182208cd92SJoseph Chen #include <dvfs.h> 192208cd92SJoseph Chen #include <io-domain.h> 2003fd0d5bSJoseph Chen #include <image.h> 217397b961SJoseph Chen #include <key.h> 2286f870d6SJoseph Chen #include <memblk.h> 232208cd92SJoseph Chen #include <misc.h> 242208cd92SJoseph Chen #include <of_live.h> 25459f5cb0SJason Zhu #include <mtd_blk.h> 2638771996SKever Yang #include <ram.h> 272208cd92SJoseph Chen #include <rockchip_debugger.h> 2838771996SKever Yang #include <syscon.h> 296929f85bSJoseph Chen #include <sysmem.h> 302208cd92SJoseph Chen #include <video_rockchip.h> 3138771996SKever Yang #include <asm/io.h> 3238771996SKever Yang #include <asm/gpio.h> 333e45175eSJoseph Chen #include <dm/uclass-internal.h> 342208cd92SJoseph Chen #include <dm/root.h> 352208cd92SJoseph Chen #include <power/charge_display.h> 362208cd92SJoseph Chen #include <power/regulator.h> 3703fd0d5bSJoseph Chen #include <optee_include/OpteeClientInterface.h> 38396e3049SElon Zhang #include <optee_include/OpteeClientApiLib.h> 39c29dd8c4SJoseph Chen #include <optee_include/tee_api_defines.h> 402208cd92SJoseph Chen #include <asm/arch/boot_mode.h> 4138771996SKever Yang #include <asm/arch/clock.h> 4260ea26bdSJoseph Chen #include <asm/arch/cpu.h> 43c664909eSJoseph Chen #include <asm/arch/hotkey.h> 446929f85bSJoseph Chen #include <asm/arch/param.h> 452208cd92SJoseph Chen #include <asm/arch/periph.h> 462208cd92SJoseph Chen #include <asm/arch/resource_img.h> 472208cd92SJoseph Chen #include <asm/arch/rk_atags.h> 482208cd92SJoseph Chen #include <asm/arch/vendor.h> 49efeef7e5SWenping Zhang #ifdef CONFIG_ROCKCHIP_EINK_DISPLAY 50efeef7e5SWenping Zhang #include <rk_eink.h> 51efeef7e5SWenping Zhang #endif 5238771996SKever Yang DECLARE_GLOBAL_DATA_PTR; 5338771996SKever Yang 5438771996SKever Yang __weak int rk_board_late_init(void) 5538771996SKever Yang { 5638771996SKever Yang return 0; 5738771996SKever Yang } 5838771996SKever Yang 5938ce6261SJoseph Chen __weak int rk_board_fdt_fixup(void *blob) 6038ce6261SJoseph Chen { 6138ce6261SJoseph Chen return 0; 6238ce6261SJoseph Chen } 6338ce6261SJoseph Chen 64efdbac34SFinley Xiao __weak int soc_clk_dump(void) 65efdbac34SFinley Xiao { 66efdbac34SFinley Xiao return 0; 67efdbac34SFinley Xiao } 68efdbac34SFinley Xiao 69058e5d94SFinley Xiao __weak int set_armclk_rate(void) 70058e5d94SFinley Xiao { 71058e5d94SFinley Xiao return 0; 72058e5d94SFinley Xiao } 73058e5d94SFinley Xiao 742208cd92SJoseph Chen __weak int rk_board_init(void) 752208cd92SJoseph Chen { 762208cd92SJoseph Chen return 0; 772208cd92SJoseph Chen } 782208cd92SJoseph Chen 792208cd92SJoseph Chen /* 802208cd92SJoseph Chen * define serialno max length, the max length is 512 Bytes 812208cd92SJoseph Chen * The remaining bytes are used to ensure that the first 512 bytes 822208cd92SJoseph Chen * are valid when executing 'env_set("serial#", value)'. 832208cd92SJoseph Chen */ 842208cd92SJoseph Chen #define VENDOR_SN_MAX 513 852208cd92SJoseph Chen #define CPUID_LEN 0x10 862208cd92SJoseph Chen #define CPUID_OFF 0x07 872208cd92SJoseph Chen 882e32f666SDavid Wu #define MAX_ETHERNET 0x2 892e32f666SDavid Wu 902208cd92SJoseph Chen static int rockchip_set_ethaddr(void) 912208cd92SJoseph Chen { 922208cd92SJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 932e32f666SDavid Wu char buf[ARP_HLEN_ASCII + 1], mac[16]; 942e32f666SDavid Wu u8 ethaddr[ARP_HLEN * MAX_ETHERNET] = {0}; 952e32f666SDavid Wu int ret, i; 962cde40a1SDavid Wu bool need_write = false, randomed = false; 972208cd92SJoseph Chen 982208cd92SJoseph Chen ret = vendor_storage_read(VENDOR_LAN_MAC_ID, ethaddr, sizeof(ethaddr)); 992e32f666SDavid Wu for (i = 0; i < MAX_ETHERNET; i++) { 1002e32f666SDavid Wu if (ret <= 0 || !is_valid_ethaddr(ðaddr[i * ARP_HLEN])) { 1012cde40a1SDavid Wu if (!randomed) { 1022e32f666SDavid Wu net_random_ethaddr(ðaddr[i * ARP_HLEN]); 1032cde40a1SDavid Wu randomed = true; 1042cde40a1SDavid Wu } else { 1052cde40a1SDavid Wu if (i > 0) { 1062cde40a1SDavid Wu memcpy(ðaddr[i * ARP_HLEN], 1072cde40a1SDavid Wu ðaddr[(i - 1) * ARP_HLEN], 1082cde40a1SDavid Wu ARP_HLEN); 1092cde40a1SDavid Wu ethaddr[i * ARP_HLEN] |= 0x02; 1102cde40a1SDavid Wu ethaddr[i * ARP_HLEN] += (i << 2); 1112cde40a1SDavid Wu } 1122cde40a1SDavid Wu } 1132cde40a1SDavid Wu 1142e32f666SDavid Wu need_write = true; 1152e32f666SDavid Wu } 1162e32f666SDavid Wu 1172e32f666SDavid Wu if (is_valid_ethaddr(ðaddr[i * ARP_HLEN])) { 1182e32f666SDavid Wu sprintf(buf, "%pM", ðaddr[i * ARP_HLEN]); 1192e32f666SDavid Wu if (i == 0) 1202e32f666SDavid Wu memcpy(mac, "ethaddr", sizeof("ethaddr")); 1212e32f666SDavid Wu else 1222e32f666SDavid Wu sprintf(mac, "eth%daddr", i); 1232e32f666SDavid Wu env_set(mac, buf); 1242e32f666SDavid Wu } 1252e32f666SDavid Wu } 1262e32f666SDavid Wu 1272e32f666SDavid Wu if (need_write) { 1282e32f666SDavid Wu ret = vendor_storage_write(VENDOR_LAN_MAC_ID, 1292e32f666SDavid Wu ethaddr, sizeof(ethaddr)); 1302e32f666SDavid Wu if (ret < 0) 1312e32f666SDavid Wu printf("%s: vendor_storage_write failed %d\n", 1322e32f666SDavid Wu __func__, ret); 1332208cd92SJoseph Chen } 1342208cd92SJoseph Chen #endif 1352e32f666SDavid Wu 1362208cd92SJoseph Chen return 0; 1372208cd92SJoseph Chen } 1382208cd92SJoseph Chen 1392208cd92SJoseph Chen static int rockchip_set_serialno(void) 1402208cd92SJoseph Chen { 1412208cd92SJoseph Chen u8 low[CPUID_LEN / 2], high[CPUID_LEN / 2]; 1422208cd92SJoseph Chen u8 cpuid[CPUID_LEN] = {0}; 1432208cd92SJoseph Chen char serialno_str[VENDOR_SN_MAX]; 1442208cd92SJoseph Chen int ret = 0, i; 1452208cd92SJoseph Chen u64 serialno; 1462208cd92SJoseph Chen 1472208cd92SJoseph Chen /* Read serial number from vendor storage part */ 1482208cd92SJoseph Chen memset(serialno_str, 0, VENDOR_SN_MAX); 1492208cd92SJoseph Chen 1502208cd92SJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 1512208cd92SJoseph Chen ret = vendor_storage_read(VENDOR_SN_ID, serialno_str, (VENDOR_SN_MAX-1)); 1522208cd92SJoseph Chen if (ret > 0) { 153df197bd2SJason Zhu i = strlen(serialno_str); 154df197bd2SJason Zhu for (; i > 0; i--) { 155df197bd2SJason Zhu if ((serialno_str[i] >= 'a' && serialno_str[i] <= 'z') || 156df197bd2SJason Zhu (serialno_str[i] >= 'A' && serialno_str[i] <= 'Z') || 157df197bd2SJason Zhu (serialno_str[i] >= '0' && serialno_str[i] <= '9')) 158df197bd2SJason Zhu break; 159df197bd2SJason Zhu } 160df197bd2SJason Zhu 161df197bd2SJason Zhu serialno_str[i + 1] = 0x0; 1622208cd92SJoseph Chen env_set("serial#", serialno_str); 1632208cd92SJoseph Chen } else { 1642208cd92SJoseph Chen #endif 165d3cb8b06SSugar Zhang #if defined(CONFIG_ROCKCHIP_EFUSE) || defined(CONFIG_ROCKCHIP_OTP) 1662208cd92SJoseph Chen struct udevice *dev; 1672208cd92SJoseph Chen 1682208cd92SJoseph Chen /* retrieve the device */ 169d3cb8b06SSugar Zhang if (IS_ENABLED(CONFIG_ROCKCHIP_EFUSE)) 1702208cd92SJoseph Chen ret = uclass_get_device_by_driver(UCLASS_MISC, 1712208cd92SJoseph Chen DM_GET_DRIVER(rockchip_efuse), 1722208cd92SJoseph Chen &dev); 173d3cb8b06SSugar Zhang else 174d3cb8b06SSugar Zhang ret = uclass_get_device_by_driver(UCLASS_MISC, 175d3cb8b06SSugar Zhang DM_GET_DRIVER(rockchip_otp), 176d3cb8b06SSugar Zhang &dev); 177d3cb8b06SSugar Zhang 1782208cd92SJoseph Chen if (ret) { 179d3cb8b06SSugar Zhang printf("%s: could not find efuse/otp device\n", __func__); 1802208cd92SJoseph Chen return ret; 1812208cd92SJoseph Chen } 1822208cd92SJoseph Chen 1832208cd92SJoseph Chen /* read the cpu_id range from the efuses */ 1842208cd92SJoseph Chen ret = misc_read(dev, CPUID_OFF, &cpuid, sizeof(cpuid)); 1852208cd92SJoseph Chen if (ret) { 186d3cb8b06SSugar Zhang printf("%s: read cpuid from efuse/otp failed, ret=%d\n", 1872208cd92SJoseph Chen __func__, ret); 1882208cd92SJoseph Chen return ret; 1892208cd92SJoseph Chen } 1902208cd92SJoseph Chen #else 1912208cd92SJoseph Chen /* generate random cpuid */ 1922208cd92SJoseph Chen for (i = 0; i < CPUID_LEN; i++) 1932208cd92SJoseph Chen cpuid[i] = (u8)(rand()); 1942208cd92SJoseph Chen #endif 1952208cd92SJoseph Chen /* Generate the serial number based on CPU ID */ 1962208cd92SJoseph Chen for (i = 0; i < 8; i++) { 1972208cd92SJoseph Chen low[i] = cpuid[1 + (i << 1)]; 1982208cd92SJoseph Chen high[i] = cpuid[i << 1]; 1992208cd92SJoseph Chen } 2002208cd92SJoseph Chen 2012208cd92SJoseph Chen serialno = crc32_no_comp(0, low, 8); 2022208cd92SJoseph Chen serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32; 2032208cd92SJoseph Chen snprintf(serialno_str, sizeof(serialno_str), "%llx", serialno); 2042208cd92SJoseph Chen 2052208cd92SJoseph Chen env_set("serial#", serialno_str); 2062208cd92SJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 2072208cd92SJoseph Chen } 2082208cd92SJoseph Chen #endif 2092208cd92SJoseph Chen 2102208cd92SJoseph Chen return ret; 2112208cd92SJoseph Chen } 2122208cd92SJoseph Chen 2132208cd92SJoseph Chen #if defined(CONFIG_USB_FUNCTION_FASTBOOT) 2142208cd92SJoseph Chen int fb_set_reboot_flag(void) 2152208cd92SJoseph Chen { 2162208cd92SJoseph Chen printf("Setting reboot to fastboot flag ...\n"); 2172208cd92SJoseph Chen writel(BOOT_FASTBOOT, CONFIG_ROCKCHIP_BOOT_MODE_REG); 2182208cd92SJoseph Chen 2192208cd92SJoseph Chen return 0; 2202208cd92SJoseph Chen } 2212208cd92SJoseph Chen #endif 2222208cd92SJoseph Chen 2230ed06f16SJoseph Chen #ifdef CONFIG_ROCKCHIP_USB_BOOT 2240ed06f16SJoseph Chen static int boot_from_udisk(void) 2250ed06f16SJoseph Chen { 2260ed06f16SJoseph Chen struct blk_desc *desc; 2270ed06f16SJoseph Chen char *devtype; 2280ed06f16SJoseph Chen char *devnum; 2290ed06f16SJoseph Chen 2300ed06f16SJoseph Chen devtype = env_get("devtype"); 2310ed06f16SJoseph Chen devnum = env_get("devnum"); 2320ed06f16SJoseph Chen 2330ed06f16SJoseph Chen /* Booting priority: mmc1 > udisk */ 2340ed06f16SJoseph Chen if (!strcmp(devtype, "mmc") && !strcmp(devnum, "1")) 2350ed06f16SJoseph Chen return 0; 2360ed06f16SJoseph Chen 2370ed06f16SJoseph Chen if (!run_command("usb start", -1)) { 2380ed06f16SJoseph Chen desc = blk_get_devnum_by_type(IF_TYPE_USB, 0); 2390ed06f16SJoseph Chen if (!desc) { 2400ed06f16SJoseph Chen printf("No usb device found\n"); 2410ed06f16SJoseph Chen return -ENODEV; 2420ed06f16SJoseph Chen } 2430ed06f16SJoseph Chen 2440ed06f16SJoseph Chen if (!run_command("rkimgtest usb 0", -1)) { 2450ed06f16SJoseph Chen rockchip_set_bootdev(desc); 2460ed06f16SJoseph Chen env_set("devtype", "usb"); 2470ed06f16SJoseph Chen env_set("devnum", "0"); 2480ed06f16SJoseph Chen printf("Boot from usb 0\n"); 2490ed06f16SJoseph Chen } else { 2500ed06f16SJoseph Chen printf("No usb dev 0 found\n"); 2510ed06f16SJoseph Chen return -ENODEV; 2520ed06f16SJoseph Chen } 2530ed06f16SJoseph Chen } 2540ed06f16SJoseph Chen 2550ed06f16SJoseph Chen return 0; 2560ed06f16SJoseph Chen } 2570ed06f16SJoseph Chen #endif 2580ed06f16SJoseph Chen 259c6f0e819SJoseph Chen static void env_fixup(void) 260c6f0e819SJoseph Chen { 261c6f0e819SJoseph Chen struct memblock mem; 262c6f0e819SJoseph Chen ulong u_addr_r; 263c6f0e819SJoseph Chen phys_size_t end; 264c6f0e819SJoseph Chen char *addr_r; 265c6f0e819SJoseph Chen 266c6f0e819SJoseph Chen #ifdef ENV_MEM_LAYOUT_SETTINGS1 267c6f0e819SJoseph Chen const char *env_addr0[] = { 268c6f0e819SJoseph Chen "scriptaddr", "pxefile_addr_r", 269c6f0e819SJoseph Chen "fdt_addr_r", "kernel_addr_r", "ramdisk_addr_r", 270c6f0e819SJoseph Chen }; 271c6f0e819SJoseph Chen const char *env_addr1[] = { 272c6f0e819SJoseph Chen "scriptaddr1", "pxefile_addr1_r", 273c6f0e819SJoseph Chen "fdt_addr1_r", "kernel_addr1_r", "ramdisk_addr1_r", 274c6f0e819SJoseph Chen }; 275c6f0e819SJoseph Chen int i; 276c6f0e819SJoseph Chen 277c6f0e819SJoseph Chen /* 128M is a typical ram size for most platform, so as default here */ 278c6f0e819SJoseph Chen if (gd->ram_size <= SZ_128M) { 279c6f0e819SJoseph Chen /* Replace orignal xxx_addr_r */ 280c6f0e819SJoseph Chen for (i = 0; i < ARRAY_SIZE(env_addr1); i++) { 281c6f0e819SJoseph Chen addr_r = env_get(env_addr1[i]); 282c6f0e819SJoseph Chen if (addr_r) 283c6f0e819SJoseph Chen env_set(env_addr0[i], addr_r); 284c6f0e819SJoseph Chen } 285c6f0e819SJoseph Chen } 286c6f0e819SJoseph Chen #endif 2874175c722SJoseph Chen /* If BL32 is disabled, move kernel to lower address. */ 288c6f0e819SJoseph Chen if (!(gd->flags & GD_FLG_BL32_ENABLED)) { 289c6f0e819SJoseph Chen addr_r = env_get("kernel_addr_no_bl32_r"); 290c6f0e819SJoseph Chen if (addr_r) 291c6f0e819SJoseph Chen env_set("kernel_addr_r", addr_r); 2924175c722SJoseph Chen 2934175c722SJoseph Chen /* 2944175c722SJoseph Chen * 0x0a200000 and 0x08400000 are rockchip traditional address 2954175c722SJoseph Chen * of BL32 and ramdisk: 2964175c722SJoseph Chen * 2974175c722SJoseph Chen * |------------|------------| 2984175c722SJoseph Chen * | BL32 | ramdisk | 2994175c722SJoseph Chen * |------------|------------| 3004175c722SJoseph Chen * 3014175c722SJoseph Chen * Move ramdisk to BL32 address to fix sysmem alloc failed 3024175c722SJoseph Chen * issue on the board with critical memory(ie. 256MB). 3034175c722SJoseph Chen */ 3044175c722SJoseph Chen if (gd->ram_size > SZ_128M && gd->ram_size <= SZ_256M) { 3054175c722SJoseph Chen u_addr_r = env_get_ulong("ramdisk_addr_r", 16, 0); 3064175c722SJoseph Chen if (u_addr_r == 0x0a200000) 3074175c722SJoseph Chen env_set("ramdisk_addr_r", "0x08400000"); 3084175c722SJoseph Chen } 3094175c722SJoseph Chen 3104175c722SJoseph Chen /* If BL32 is enlarged, move ramdisk right behind it */ 311c6f0e819SJoseph Chen } else { 312c6f0e819SJoseph Chen mem = param_parse_optee_mem(); 313c6f0e819SJoseph Chen end = mem.base + mem.size; 314c6f0e819SJoseph Chen u_addr_r = env_get_ulong("ramdisk_addr_r", 16, 0); 315c6f0e819SJoseph Chen if (u_addr_r >= mem.base && u_addr_r < end) 316c6f0e819SJoseph Chen env_set_hex("ramdisk_addr_r", end); 317c6f0e819SJoseph Chen } 318c6f0e819SJoseph Chen } 319c6f0e819SJoseph Chen 32083c9bd4bSJoseph Chen static void cmdline_handle(void) 32183c9bd4bSJoseph Chen { 32283c9bd4bSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 32383c9bd4bSJoseph Chen struct tag *t; 32483c9bd4bSJoseph Chen 32583c9bd4bSJoseph Chen t = atags_get_tag(ATAG_PUB_KEY); 32683c9bd4bSJoseph Chen if (t) { 32783c9bd4bSJoseph Chen /* Pass if efuse/otp programmed */ 32883c9bd4bSJoseph Chen if (t->u.pub_key.flag == PUBKEY_FUSE_PROGRAMMED) 32983c9bd4bSJoseph Chen env_update("bootargs", "fuse.programmed=1"); 33083c9bd4bSJoseph Chen else 33183c9bd4bSJoseph Chen env_update("bootargs", "fuse.programmed=0"); 33283c9bd4bSJoseph Chen } 33383c9bd4bSJoseph Chen #endif 33483c9bd4bSJoseph Chen } 33583c9bd4bSJoseph Chen 33638771996SKever Yang int board_late_init(void) 33738771996SKever Yang { 3382549364dSlanshh rockchip_set_ethaddr(); 339fc1a5563SJason Zhu rockchip_set_serialno(); 340d04ada6cSJoseph Chen setup_download_mode(); 34138771996SKever Yang #if (CONFIG_ROCKCHIP_BOOT_MODE_REG > 0) 34238771996SKever Yang setup_boot_mode(); 34338771996SKever Yang #endif 3440ed06f16SJoseph Chen #ifdef CONFIG_ROCKCHIP_USB_BOOT 3450ed06f16SJoseph Chen boot_from_udisk(); 3460ed06f16SJoseph Chen #endif 34738771996SKever Yang #ifdef CONFIG_DM_CHARGE_DISPLAY 34838771996SKever Yang charge_display(); 34938771996SKever Yang #endif 35038771996SKever Yang #ifdef CONFIG_DRM_ROCKCHIP 35138771996SKever Yang rockchip_show_logo(); 35238771996SKever Yang #endif 353efeef7e5SWenping Zhang #ifdef CONFIG_ROCKCHIP_EINK_DISPLAY 354efeef7e5SWenping Zhang rockchip_eink_show_uboot_logo(); 355efeef7e5SWenping Zhang #endif 356c6f0e819SJoseph Chen env_fixup(); 357efdbac34SFinley Xiao soc_clk_dump(); 35883c9bd4bSJoseph Chen cmdline_handle(); 359efdbac34SFinley Xiao 36038771996SKever Yang return rk_board_late_init(); 36138771996SKever Yang } 36238771996SKever Yang 363a7940145SJoseph Chen static void early_download(void) 364644804edSJoseph Chen { 3657397b961SJoseph Chen #if defined(CONFIG_PWRKEY_DNL_TRIGGER_NUM) && \ 3667397b961SJoseph Chen (CONFIG_PWRKEY_DNL_TRIGGER_NUM > 0) 3677397b961SJoseph Chen if (pwrkey_download_init()) 3687397b961SJoseph Chen printf("Pwrkey download init failed\n"); 3697397b961SJoseph Chen #endif 3707397b961SJoseph Chen 371644804edSJoseph Chen #if (CONFIG_ROCKCHIP_BOOT_MODE_REG > 0) 372c664909eSJoseph Chen if (is_hotkey(HK_BROM_DNL)) { 373644804edSJoseph Chen printf("Enter bootrom download..."); 374363411a1SJoseph Chen flushc(); 375644804edSJoseph Chen writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG); 376644804edSJoseph Chen do_reset(NULL, 0, 0, NULL); 377644804edSJoseph Chen printf("failed!\n"); 378644804edSJoseph Chen } 379644804edSJoseph Chen #endif 380644804edSJoseph Chen } 381644804edSJoseph Chen 3825d5f363eSJoseph Chen static void board_debug_init(void) 3835d5f363eSJoseph Chen { 38493586e70SJoseph Chen if (!gd->serial.using_pre_serial && 38593586e70SJoseph Chen !(gd->flags & GD_FLG_DISABLE_CONSOLE)) 3867abb254dSJoseph Chen debug_uart_init(); 38746f61401SJoseph Chen 38846f61401SJoseph Chen if (tstc()) { 38946f61401SJoseph Chen gd->console_evt = getc(); 39046f61401SJoseph Chen if (gd->console_evt <= 0x1a) /* 'z' */ 39146f61401SJoseph Chen printf("Hotkey: ctrl+%c\n", gd->console_evt + 'a' - 1); 39246f61401SJoseph Chen } 3939889a0e0SJoseph Chen 3949889a0e0SJoseph Chen if (IS_ENABLED(CONFIG_CONSOLE_DISABLE_CLI)) 39525047d3fSJoseph Chen printf("Cmd interface: disabled\n"); 3965d5f363eSJoseph Chen } 3975d5f363eSJoseph Chen 398459f5cb0SJason Zhu #ifdef CONFIG_MTD_BLK 399459f5cb0SJason Zhu static void board_mtd_blk_map_partitions(void) 400459f5cb0SJason Zhu { 401459f5cb0SJason Zhu struct blk_desc *dev_desc; 402459f5cb0SJason Zhu 403459f5cb0SJason Zhu dev_desc = rockchip_get_bootdev(); 404459f5cb0SJason Zhu if (dev_desc) 405459f5cb0SJason Zhu mtd_blk_map_partitions(dev_desc); 406459f5cb0SJason Zhu } 407459f5cb0SJason Zhu #endif 408459f5cb0SJason Zhu 40938771996SKever Yang int board_init(void) 41038771996SKever Yang { 4115d5f363eSJoseph Chen board_debug_init(); 412ebb6c439SYouMin Chen 413f0aa8c5dSJason Zhu #ifdef DEBUG 414f0aa8c5dSJason Zhu soc_clk_dump(); 415f0aa8c5dSJason Zhu #endif 416f0aa8c5dSJason Zhu 417f8aaa2c2SKever Yang #ifdef CONFIG_USING_KERNEL_DTB 418459f5cb0SJason Zhu #ifdef CONFIG_MTD_BLK 419459f5cb0SJason Zhu board_mtd_blk_map_partitions(); 420459f5cb0SJason Zhu #endif 421f8aaa2c2SKever Yang init_kernel_dtb(); 422f8aaa2c2SKever Yang #endif 423a7940145SJoseph Chen early_download(); 4247397b961SJoseph Chen 4259f8e13d3SFinley Xiao /* 4269f8e13d3SFinley Xiao * pmucru isn't referenced on some platforms, so pmucru driver can't 4279f8e13d3SFinley Xiao * probe that the "assigned-clocks" is unused. 4289f8e13d3SFinley Xiao */ 4299f8e13d3SFinley Xiao clks_probe(); 43038771996SKever Yang #ifdef CONFIG_DM_REGULATOR 431dba9c9e5SJoseph Chen if (regulators_enable_boot_on(is_hotkey(HK_REGULATOR))) 4322208cd92SJoseph Chen debug("%s: Can't enable boot on regulator\n", __func__); 43338771996SKever Yang #endif 434dae20286SJianqun Xu 435dae20286SJianqun Xu #ifdef CONFIG_ROCKCHIP_IO_DOMAIN 436dae20286SJianqun Xu io_domain_init(); 437dae20286SJianqun Xu #endif 438dae20286SJianqun Xu 439058e5d94SFinley Xiao set_armclk_rate(); 44038771996SKever Yang 4413acf4edfSJoseph Chen #ifdef CONFIG_DM_DVFS 4423acf4edfSJoseph Chen dvfs_init(true); 4433acf4edfSJoseph Chen #endif 4443acf4edfSJoseph Chen 44538771996SKever Yang return rk_board_init(); 44638771996SKever Yang } 44738771996SKever Yang 448c563adc7SJoseph Chen int interrupt_debugger_init(void) 449c563adc7SJoseph Chen { 450c563adc7SJoseph Chen #ifdef CONFIG_ROCKCHIP_DEBUGGER 4512208cd92SJoseph Chen return rockchip_debugger_init(); 4522208cd92SJoseph Chen #else 4532208cd92SJoseph Chen return 0; 454c563adc7SJoseph Chen #endif 455c563adc7SJoseph Chen } 456c563adc7SJoseph Chen 457e09b1e4aSJoseph Chen int board_fdt_fixup(void *blob) 458e09b1e4aSJoseph Chen { 4592208cd92SJoseph Chen /* Common fixup for DRM */ 460e09b1e4aSJoseph Chen #ifdef CONFIG_DRM_ROCKCHIP 461e09b1e4aSJoseph Chen rockchip_display_fixup(blob); 462e09b1e4aSJoseph Chen #endif 463e09b1e4aSJoseph Chen 46438ce6261SJoseph Chen return rk_board_fdt_fixup(blob); 465e09b1e4aSJoseph Chen } 466e09b1e4aSJoseph Chen 467102dfafcSElon Zhang #if defined(CONFIG_ARM64_BOOT_AARCH32) || !defined(CONFIG_ARM64) 468e3fbd280SJoseph Chen /* 469f1d65189SJoseph Chen * Common for OP-TEE: 470396e3049SElon Zhang * 64-bit & 32-bit mode: share memory dcache is always enabled; 471e3fbd280SJoseph Chen * 472f1d65189SJoseph Chen * Common for U-Boot: 473e3fbd280SJoseph Chen * 64-bit mode: MMU table is static defined in rkxxx.c file, all memory 474e3fbd280SJoseph Chen * regions are mapped. That's good to match OP-TEE MMU policy. 475e3fbd280SJoseph Chen * 476e3fbd280SJoseph Chen * 32-bit mode: MMU table is setup according to gd->bd->bi_dram[..] where 477e3fbd280SJoseph Chen * the OP-TEE region has been reserved, so it can not be 478102dfafcSElon Zhang * mapped(i.e. dcache is disabled). That's *NOT* good to match 479e3fbd280SJoseph Chen * OP-TEE MMU policy. 480e3fbd280SJoseph Chen * 481e3fbd280SJoseph Chen * For the data coherence when communication between U-Boot and OP-TEE, U-Boot 482e3fbd280SJoseph Chen * should follow OP-TEE MMU policy. 483e3fbd280SJoseph Chen * 484396e3049SElon Zhang * So 32-bit mode U-Boot should map OP-TEE share memory as dcache enabled. 485e3fbd280SJoseph Chen */ 486e3fbd280SJoseph Chen int board_initr_caches_fixup(void) 487e3fbd280SJoseph Chen { 488396e3049SElon Zhang #ifdef CONFIG_OPTEE_CLIENT 489e3fbd280SJoseph Chen struct memblock mem; 490e3fbd280SJoseph Chen 491396e3049SElon Zhang mem.base = 0; 492396e3049SElon Zhang mem.size = 0; 493396e3049SElon Zhang 494396e3049SElon Zhang optee_get_shm_config(&mem.base, &mem.size); 495e3fbd280SJoseph Chen if (mem.size) 496e3fbd280SJoseph Chen mmu_set_region_dcache_behaviour(mem.base, mem.size, 497e3fbd280SJoseph Chen DCACHE_WRITEBACK); 498396e3049SElon Zhang #endif 499e3fbd280SJoseph Chen return 0; 500e3fbd280SJoseph Chen } 501e3fbd280SJoseph Chen #endif 502e3fbd280SJoseph Chen 503665be4b0SJoseph Chen void arch_preboot_os(uint32_t bootm_state) 504665be4b0SJoseph Chen { 505665be4b0SJoseph Chen if (bootm_state & BOOTM_STATE_OS_PREP) 506665be4b0SJoseph Chen hotkey_run(HK_CLI_OS_PRE); 507665be4b0SJoseph Chen } 508665be4b0SJoseph Chen 50938771996SKever Yang void enable_caches(void) 51038771996SKever Yang { 511567735c8SJoseph Chen icache_enable(); 51238771996SKever Yang dcache_enable(); 51338771996SKever Yang } 51438771996SKever Yang 5152dc2d048SJoseph Chen #ifdef CONFIG_LMB 5162c6a058bSJoseph Chen /* 5172c6a058bSJoseph Chen * Using last bi_dram[...] to initialize "bootm_low" and "bootm_mapsize". 5182c6a058bSJoseph Chen * This makes lmb_alloc_base() always alloc from tail of sdram. 5192c6a058bSJoseph Chen * If we don't assign it, bi_dram[0] is used by default and it may cause 5202c6a058bSJoseph Chen * lmb_alloc_base() fail when bi_dram[0] range is small. 5212c6a058bSJoseph Chen */ 5222c6a058bSJoseph Chen void board_lmb_reserve(struct lmb *lmb) 5232c6a058bSJoseph Chen { 5242c6a058bSJoseph Chen char bootm_mapsize[32]; 5252208cd92SJoseph Chen char bootm_low[32]; 5262208cd92SJoseph Chen u64 start, size; 5272c6a058bSJoseph Chen int i; 5282c6a058bSJoseph Chen 5292c6a058bSJoseph Chen for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 5302c6a058bSJoseph Chen if (!gd->bd->bi_dram[i].size) 5312c6a058bSJoseph Chen break; 5322c6a058bSJoseph Chen } 5332c6a058bSJoseph Chen 5342c6a058bSJoseph Chen start = gd->bd->bi_dram[i - 1].start; 5352c6a058bSJoseph Chen size = gd->bd->bi_dram[i - 1].size; 5362c6a058bSJoseph Chen 5372c6a058bSJoseph Chen /* 5382dc2d048SJoseph Chen * 32-bit kernel: ramdisk/fdt shouldn't be loaded to highmem area(768MB+), 5392dc2d048SJoseph Chen * otherwise "Unable to handle kernel paging request at virtual address ...". 5402dc2d048SJoseph Chen * 5412dc2d048SJoseph Chen * So that we hope limit highest address at 768M, but there comes the the 5422dc2d048SJoseph Chen * problem: ramdisk is a compressed image and it expands after descompress, 5432dc2d048SJoseph Chen * so it accesses 768MB+ and brings the above "Unable to handle kernel ...". 5442dc2d048SJoseph Chen * 5452dc2d048SJoseph Chen * We make a appointment that the highest memory address is 512MB, it 5462dc2d048SJoseph Chen * makes lmb alloc safer. 5472c6a058bSJoseph Chen */ 5482dc2d048SJoseph Chen #ifndef CONFIG_ARM64 5492dc2d048SJoseph Chen if (start >= ((u64)CONFIG_SYS_SDRAM_BASE + SZ_512M)) { 5502c6a058bSJoseph Chen start = gd->bd->bi_dram[i - 2].start; 5512c6a058bSJoseph Chen size = gd->bd->bi_dram[i - 2].size; 5522c6a058bSJoseph Chen } 5532c6a058bSJoseph Chen 5542dc2d048SJoseph Chen if ((start + size) > ((u64)CONFIG_SYS_SDRAM_BASE + SZ_512M)) 5552dc2d048SJoseph Chen size = (u64)CONFIG_SYS_SDRAM_BASE + SZ_512M - start; 5562c6a058bSJoseph Chen #endif 5572c6a058bSJoseph Chen sprintf(bootm_low, "0x%llx", start); 5582c6a058bSJoseph Chen sprintf(bootm_mapsize, "0x%llx", size); 5592c6a058bSJoseph Chen env_set("bootm_low", bootm_low); 5602c6a058bSJoseph Chen env_set("bootm_mapsize", bootm_mapsize); 5612c6a058bSJoseph Chen } 5622dc2d048SJoseph Chen #endif 5632c6a058bSJoseph Chen 56486f870d6SJoseph Chen #ifdef CONFIG_BIDRAM 56586f870d6SJoseph Chen int board_bidram_reserve(struct bidram *bidram) 56686f870d6SJoseph Chen { 56786f870d6SJoseph Chen struct memblock mem; 56886f870d6SJoseph Chen int ret; 56986f870d6SJoseph Chen 57086f870d6SJoseph Chen /* ATF */ 57186f870d6SJoseph Chen mem = param_parse_atf_mem(); 572c01d4489SJoseph Chen ret = bidram_reserve(MEM_ATF, mem.base, mem.size); 57386f870d6SJoseph Chen if (ret) 57486f870d6SJoseph Chen return ret; 57586f870d6SJoseph Chen 57686f870d6SJoseph Chen /* PSTORE/ATAGS/SHM */ 57786f870d6SJoseph Chen mem = param_parse_common_resv_mem(); 578c01d4489SJoseph Chen ret = bidram_reserve(MEM_SHM, mem.base, mem.size); 57986f870d6SJoseph Chen if (ret) 58086f870d6SJoseph Chen return ret; 58186f870d6SJoseph Chen 58286f870d6SJoseph Chen /* OP-TEE */ 58386f870d6SJoseph Chen mem = param_parse_optee_mem(); 584c01d4489SJoseph Chen ret = bidram_reserve(MEM_OPTEE, mem.base, mem.size); 58586f870d6SJoseph Chen if (ret) 58686f870d6SJoseph Chen return ret; 58786f870d6SJoseph Chen 58886f870d6SJoseph Chen return 0; 58986f870d6SJoseph Chen } 59086f870d6SJoseph Chen 59186f870d6SJoseph Chen parse_fn_t board_bidram_parse_fn(void) 59286f870d6SJoseph Chen { 59386f870d6SJoseph Chen return param_parse_ddr_mem; 59486f870d6SJoseph Chen } 59586f870d6SJoseph Chen #endif 59686f870d6SJoseph Chen 59750d35c45SJoseph Chen #ifdef CONFIG_ROCKCHIP_AMP 59850d35c45SJoseph Chen void cpu_secondary_init_r(void) 59950d35c45SJoseph Chen { 60050d35c45SJoseph Chen amp_cpus_on(); 60150d35c45SJoseph Chen } 60250d35c45SJoseph Chen #endif 60350d35c45SJoseph Chen 60493586e70SJoseph Chen int board_init_f_boot_flags(void) 60593586e70SJoseph Chen { 60693586e70SJoseph Chen int boot_flags = 0; 60793586e70SJoseph Chen 60893586e70SJoseph Chen /* pre-loader serial */ 6094892a977SJoseph Chen #if defined(CONFIG_ROCKCHIP_PRELOADER_SERIAL) && \ 6104892a977SJoseph Chen defined(CONFIG_ROCKCHIP_PRELOADER_ATAGS) 61193586e70SJoseph Chen struct tag *t; 612064eb493SJoseph Chen 61393586e70SJoseph Chen t = atags_get_tag(ATAG_SERIAL); 614064eb493SJoseph Chen if (t) { 61593586e70SJoseph Chen gd->serial.using_pre_serial = 1; 61693586e70SJoseph Chen gd->serial.enable = t->u.serial.enable; 617064eb493SJoseph Chen gd->serial.baudrate = t->u.serial.baudrate; 6187abb254dSJoseph Chen gd->serial.addr = t->u.serial.addr; 619064eb493SJoseph Chen gd->serial.id = t->u.serial.id; 62093586e70SJoseph Chen gd->baudrate = CONFIG_BAUDRATE; 62193586e70SJoseph Chen if (!t->u.serial.enable) 62293586e70SJoseph Chen boot_flags |= GD_FLG_DISABLE_CONSOLE; 62393586e70SJoseph Chen debug("preloader: enable=%d, addr=0x%lx, baudrate=%d, id=%d\n", 62493586e70SJoseph Chen gd->serial.enable, gd->serial.addr, 62593586e70SJoseph Chen gd->serial.baudrate, gd->serial.id); 62693586e70SJoseph Chen } else 627064eb493SJoseph Chen #endif 62893586e70SJoseph Chen { 62993586e70SJoseph Chen gd->baudrate = CONFIG_BAUDRATE; 63093586e70SJoseph Chen gd->serial.baudrate = CONFIG_BAUDRATE; 63193586e70SJoseph Chen gd->serial.addr = CONFIG_DEBUG_UART_BASE; 63293586e70SJoseph Chen } 63393586e70SJoseph Chen 63493586e70SJoseph Chen /* The highest priority to turn off (override) console */ 63593586e70SJoseph Chen #if defined(CONFIG_DISABLE_CONSOLE) 63693586e70SJoseph Chen boot_flags |= GD_FLG_DISABLE_CONSOLE; 63793586e70SJoseph Chen #endif 63893586e70SJoseph Chen 63993586e70SJoseph Chen return boot_flags; 64093586e70SJoseph Chen } 641064eb493SJoseph Chen 64238771996SKever Yang #if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG) 6436f7b6465SFrank Wang #include <fdt_support.h> 64438771996SKever Yang #include <usb.h> 64538771996SKever Yang #include <usb/dwc2_udc.h> 64638771996SKever Yang 64738771996SKever Yang static struct dwc2_plat_otg_data otg_data = { 64838771996SKever Yang .rx_fifo_sz = 512, 64938771996SKever Yang .np_tx_fifo_sz = 16, 65038771996SKever Yang .tx_fifo_sz = 128, 65138771996SKever Yang }; 65238771996SKever Yang 65338771996SKever Yang int board_usb_init(int index, enum usb_init_type init) 65438771996SKever Yang { 65538771996SKever Yang const void *blob = gd->fdt_blob; 6562208cd92SJoseph Chen const fdt32_t *reg; 6572208cd92SJoseph Chen fdt_addr_t addr; 6582208cd92SJoseph Chen int node; 65938771996SKever Yang 66038771996SKever Yang /* find the usb_otg node */ 661294ad617SWilliam Wu node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc2"); 66238771996SKever Yang 663294ad617SWilliam Wu retry: 664294ad617SWilliam Wu if (node > 0) { 665294ad617SWilliam Wu reg = fdt_getprop(blob, node, "reg", NULL); 666294ad617SWilliam Wu if (!reg) 667294ad617SWilliam Wu return -EINVAL; 668294ad617SWilliam Wu 669294ad617SWilliam Wu addr = fdt_translate_address(blob, node, reg); 670294ad617SWilliam Wu if (addr == OF_BAD_ADDR) { 671294ad617SWilliam Wu pr_err("Not found usb_otg address\n"); 672294ad617SWilliam Wu return -EINVAL; 67338771996SKever Yang } 67438771996SKever Yang 675294ad617SWilliam Wu #if defined(CONFIG_ROCKCHIP_RK3288) 676294ad617SWilliam Wu if (addr != 0xff580000) { 67738771996SKever Yang node = fdt_node_offset_by_compatible(blob, node, 67838771996SKever Yang "snps,dwc2"); 679294ad617SWilliam Wu goto retry; 68038771996SKever Yang } 681294ad617SWilliam Wu #endif 682294ad617SWilliam Wu } else { 683e7b5bb3cSWilliam Wu /* 684e7b5bb3cSWilliam Wu * With kernel dtb support, rk3288 dwc2 otg node 685e7b5bb3cSWilliam Wu * use the rockchip legacy dwc2 driver "dwc_otg_310" 686e0b87408SJoseph Chen * with the compatible "rockchip,rk3288_usb20_otg", 687e0b87408SJoseph Chen * and rk3368 also use the "dwc_otg_310" driver with 688e0b87408SJoseph Chen * the compatible "rockchip,rk3368-usb". 689e7b5bb3cSWilliam Wu */ 690e0b87408SJoseph Chen #if defined(CONFIG_ROCKCHIP_RK3288) 691e7b5bb3cSWilliam Wu node = fdt_node_offset_by_compatible(blob, -1, 692e7b5bb3cSWilliam Wu "rockchip,rk3288_usb20_otg"); 693e0b87408SJoseph Chen #elif defined(CONFIG_ROCKCHIP_RK3368) 694e0b87408SJoseph Chen node = fdt_node_offset_by_compatible(blob, -1, 695e0b87408SJoseph Chen "rockchip,rk3368-usb"); 696e0b87408SJoseph Chen #endif 697e7b5bb3cSWilliam Wu if (node > 0) { 698294ad617SWilliam Wu goto retry; 699e7b5bb3cSWilliam Wu } else { 700e7b5bb3cSWilliam Wu pr_err("Not found usb_otg device\n"); 70138771996SKever Yang return -ENODEV; 70238771996SKever Yang } 703e7b5bb3cSWilliam Wu } 7046f7b6465SFrank Wang 7056f7b6465SFrank Wang otg_data.regs_otg = (uintptr_t)addr; 70638771996SKever Yang 70738771996SKever Yang return dwc2_udc_probe(&otg_data); 70838771996SKever Yang } 70938771996SKever Yang 71038771996SKever Yang int board_usb_cleanup(int index, enum usb_init_type init) 71138771996SKever Yang { 71238771996SKever Yang return 0; 71338771996SKever Yang } 71438771996SKever Yang #endif 71585cad72dSJoseph Chen 71685cad72dSJoseph Chen static void bootm_no_reloc(void) 71785cad72dSJoseph Chen { 71885cad72dSJoseph Chen char *ramdisk_high; 71985cad72dSJoseph Chen char *fdt_high; 72085cad72dSJoseph Chen 72185cad72dSJoseph Chen if (!env_get_yesno("bootm-no-reloc")) 72285cad72dSJoseph Chen return; 72385cad72dSJoseph Chen 72485cad72dSJoseph Chen ramdisk_high = env_get("initrd_high"); 72585cad72dSJoseph Chen fdt_high = env_get("fdt_high"); 72685cad72dSJoseph Chen 72785cad72dSJoseph Chen if (!fdt_high) { 72885cad72dSJoseph Chen env_set_hex("fdt_high", -1UL); 72985cad72dSJoseph Chen printf("Fdt "); 73085cad72dSJoseph Chen } 73185cad72dSJoseph Chen 73285cad72dSJoseph Chen if (!ramdisk_high) { 73385cad72dSJoseph Chen env_set_hex("initrd_high", -1UL); 73485cad72dSJoseph Chen printf("Ramdisk "); 73585cad72dSJoseph Chen } 73685cad72dSJoseph Chen 73785cad72dSJoseph Chen if (!fdt_high || !ramdisk_high) 73885cad72dSJoseph Chen printf("skip relocation\n"); 73985cad72dSJoseph Chen } 74085cad72dSJoseph Chen 74185cad72dSJoseph Chen int bootm_board_start(void) 74285cad72dSJoseph Chen { 74385cad72dSJoseph Chen /* 74485cad72dSJoseph Chen * print console record data 74585cad72dSJoseph Chen * 74685cad72dSJoseph Chen * On some rockchip platforms, uart debug and sdmmc pin are multiplex. 74785cad72dSJoseph Chen * If boot from sdmmc mode, the console data would be record in buffer, 74885cad72dSJoseph Chen * we switch to uart debug function in order to print it after loading 74985cad72dSJoseph Chen * images. 75085cad72dSJoseph Chen */ 75185cad72dSJoseph Chen #if defined(CONFIG_CONSOLE_RECORD) 75285cad72dSJoseph Chen if (!strcmp("mmc", env_get("devtype")) && 75385cad72dSJoseph Chen !strcmp("1", env_get("devnum"))) { 75485cad72dSJoseph Chen printf("IOMUX: sdmmc => uart debug"); 75585cad72dSJoseph Chen pinctrl_select_state(gd->cur_serial_dev, "default"); 75685cad72dSJoseph Chen console_record_print_purge(); 75785cad72dSJoseph Chen } 75885cad72dSJoseph Chen #endif 75985cad72dSJoseph Chen /* disable bootm relcation to save boot time */ 76085cad72dSJoseph Chen bootm_no_reloc(); 76185cad72dSJoseph Chen 76285cad72dSJoseph Chen /* sysmem */ 76385cad72dSJoseph Chen hotkey_run(HK_SYSMEM); 76485cad72dSJoseph Chen sysmem_overflow_check(); 76585cad72dSJoseph Chen 76685cad72dSJoseph Chen return 0; 76785cad72dSJoseph Chen } 768ac5d8aa9SJoseph Chen 769ac5d8aa9SJoseph Chen /* 770ac5d8aa9SJoseph Chen * Implement it to support CLI command: 771ac5d8aa9SJoseph Chen * - Android: bootm [aosp addr] 772ac5d8aa9SJoseph Chen * - FIT: bootm [fit addr] 773ac5d8aa9SJoseph Chen * - uImage: bootm [uimage addr] 774ac5d8aa9SJoseph Chen * 775ac5d8aa9SJoseph Chen * Purpose: 776ac5d8aa9SJoseph Chen * - The original bootm command args require fdt addr on AOSP, 777ac5d8aa9SJoseph Chen * which is not flexible on rockchip boot/recovery.img. 778ac5d8aa9SJoseph Chen * - Take Android/FIT/uImage image into sysmem management to avoid image 779ac5d8aa9SJoseph Chen * memory overlap. 780ac5d8aa9SJoseph Chen */ 781ac5d8aa9SJoseph Chen #if defined(CONFIG_ANDROID_BOOTLOADER) || \ 782ac5d8aa9SJoseph Chen defined(CONFIG_ROCKCHIP_FIT_IMAGE) || \ 783ac5d8aa9SJoseph Chen defined(CONFIG_ROCKCHIP_UIMAGE) 784ac5d8aa9SJoseph Chen int board_do_bootm(int argc, char * const argv[]) 785ac5d8aa9SJoseph Chen { 786ac5d8aa9SJoseph Chen int format; 787ac5d8aa9SJoseph Chen void *img; 788ac5d8aa9SJoseph Chen 789ac5d8aa9SJoseph Chen if (argc != 2) 790ac5d8aa9SJoseph Chen return 0; 791ac5d8aa9SJoseph Chen 792ac5d8aa9SJoseph Chen img = (void *)simple_strtoul(argv[1], NULL, 16); 793ac5d8aa9SJoseph Chen format = (genimg_get_format(img)); 794ac5d8aa9SJoseph Chen 795ac5d8aa9SJoseph Chen /* Android */ 796ac5d8aa9SJoseph Chen #ifdef CONFIG_ANDROID_BOOT_IMAGE 797ac5d8aa9SJoseph Chen if (format == IMAGE_FORMAT_ANDROID) { 798ac5d8aa9SJoseph Chen struct andr_img_hdr *hdr; 799ac5d8aa9SJoseph Chen ulong load_addr; 800ac5d8aa9SJoseph Chen ulong size; 801ac5d8aa9SJoseph Chen int ret; 802ac5d8aa9SJoseph Chen 803ac5d8aa9SJoseph Chen hdr = (struct andr_img_hdr *)img; 804ac5d8aa9SJoseph Chen printf("BOOTM: transferring to board Android\n"); 805ac5d8aa9SJoseph Chen 806ac5d8aa9SJoseph Chen #ifdef CONFIG_USING_KERNEL_DTB 807ac5d8aa9SJoseph Chen sysmem_free((phys_addr_t)gd->fdt_blob); 808ac5d8aa9SJoseph Chen /* erase magic */ 809ac5d8aa9SJoseph Chen fdt_set_magic((void *)gd->fdt_blob, ~0); 810ac5d8aa9SJoseph Chen gd->fdt_blob = NULL; 811ac5d8aa9SJoseph Chen #endif 812ac5d8aa9SJoseph Chen load_addr = env_get_ulong("kernel_addr_r", 16, 0); 813ac5d8aa9SJoseph Chen load_addr -= hdr->page_size; 814ac5d8aa9SJoseph Chen size = android_image_get_end(hdr) - (ulong)hdr; 815ac5d8aa9SJoseph Chen 816ac5d8aa9SJoseph Chen if (!sysmem_alloc_base(MEM_ANDROID, (ulong)hdr, size)) 817ac5d8aa9SJoseph Chen return -ENOMEM; 818ac5d8aa9SJoseph Chen 819ac5d8aa9SJoseph Chen ret = android_image_memcpy_separate(hdr, &load_addr); 820ac5d8aa9SJoseph Chen if (ret) { 821ac5d8aa9SJoseph Chen printf("board do bootm failed, ret=%d\n", ret); 822ac5d8aa9SJoseph Chen return ret; 823ac5d8aa9SJoseph Chen } 824ac5d8aa9SJoseph Chen 825ac5d8aa9SJoseph Chen return android_bootloader_boot_kernel(load_addr); 826ac5d8aa9SJoseph Chen } 827ac5d8aa9SJoseph Chen #endif 828ac5d8aa9SJoseph Chen 829ac5d8aa9SJoseph Chen /* FIT */ 830ac5d8aa9SJoseph Chen #if IMAGE_ENABLE_FIT 831ac5d8aa9SJoseph Chen if (format == IMAGE_FORMAT_FIT) { 832ac5d8aa9SJoseph Chen char boot_cmd[64]; 833ac5d8aa9SJoseph Chen 834ac5d8aa9SJoseph Chen printf("BOOTM: transferring to board FIT\n"); 835ac5d8aa9SJoseph Chen snprintf(boot_cmd, sizeof(boot_cmd), "boot_fit %s", argv[1]); 836ac5d8aa9SJoseph Chen return run_command(boot_cmd, 0); 837ac5d8aa9SJoseph Chen } 838ac5d8aa9SJoseph Chen #endif 839ac5d8aa9SJoseph Chen 840ac5d8aa9SJoseph Chen /* uImage */ 841ac5d8aa9SJoseph Chen #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 842ac5d8aa9SJoseph Chen if (format == IMAGE_FORMAT_LEGACY && 843ac5d8aa9SJoseph Chen image_get_type(img) == IH_TYPE_MULTI) { 844ac5d8aa9SJoseph Chen char boot_cmd[64]; 845ac5d8aa9SJoseph Chen 846ac5d8aa9SJoseph Chen printf("BOOTM: transferring to board uImage\n"); 847ac5d8aa9SJoseph Chen snprintf(boot_cmd, sizeof(boot_cmd), "boot_uimage %s", argv[1]); 848ac5d8aa9SJoseph Chen return run_command(boot_cmd, 0); 849ac5d8aa9SJoseph Chen } 850ac5d8aa9SJoseph Chen #endif 851ac5d8aa9SJoseph Chen 852ac5d8aa9SJoseph Chen return 0; 853ac5d8aa9SJoseph Chen } 854ac5d8aa9SJoseph Chen #endif 8554ab50248SJoseph Chen 8564ab50248SJoseph Chen void autoboot_command_fail_handle(void) 8574ab50248SJoseph Chen { 8584ab50248SJoseph Chen #ifdef CONFIG_AVB_VBMETA_PUBLIC_KEY_VALIDATE 8594ab50248SJoseph Chen #ifdef CONFIG_ANDROID_AB 8604ab50248SJoseph Chen run_command("fastboot usb 0;", 0); /* use fastboot to ative slot */ 8614ab50248SJoseph Chen #else 8624ab50248SJoseph Chen run_command("rockusb 0 ${devtype} ${devnum}", 0); 8634ab50248SJoseph Chen run_command("fastboot usb 0;", 0); 8644ab50248SJoseph Chen #endif 8654ab50248SJoseph Chen #endif 8664ab50248SJoseph Chen } 867346c39b3SJoseph Chen 868c29dd8c4SJoseph Chen #ifdef CONFIG_FIT_ROLLBACK_PROTECT 869c29dd8c4SJoseph Chen 870c29dd8c4SJoseph Chen #define FIT_ROLLBACK_INDEX_LOCATION 0x66697472 /* "fitr" */ 871c29dd8c4SJoseph Chen 872c29dd8c4SJoseph Chen int fit_read_otp_rollback_index(uint32_t fit_index, uint32_t *otp_index) 873c29dd8c4SJoseph Chen { 874c29dd8c4SJoseph Chen #ifdef CONFIG_OPTEE_CLIENT 875c29dd8c4SJoseph Chen u64 index; 876c29dd8c4SJoseph Chen int ret; 877c29dd8c4SJoseph Chen 878c29dd8c4SJoseph Chen ret = trusty_read_rollback_index(FIT_ROLLBACK_INDEX_LOCATION, &index); 879c29dd8c4SJoseph Chen if (ret) { 880c29dd8c4SJoseph Chen if (ret != TEE_ERROR_ITEM_NOT_FOUND) 881c29dd8c4SJoseph Chen return ret; 882c29dd8c4SJoseph Chen 883*ee7b0fb8SJason Zhu index = 0; 884c29dd8c4SJoseph Chen printf("Initial otp index as %d\n", fit_index); 885bcec4579SZain Wang } 886*ee7b0fb8SJason Zhu 887*ee7b0fb8SJason Zhu *otp_index = (uint32_t)index; 888c29dd8c4SJoseph Chen #else 889c29dd8c4SJoseph Chen *otp_index = 0; 890c29dd8c4SJoseph Chen #endif 891c29dd8c4SJoseph Chen 892c29dd8c4SJoseph Chen return 0; 893c29dd8c4SJoseph Chen } 894c29dd8c4SJoseph Chen 895c29dd8c4SJoseph Chen static int fit_write_trusty_rollback_index(u32 trusty_index) 896c29dd8c4SJoseph Chen { 897c29dd8c4SJoseph Chen if (!trusty_index) 898c29dd8c4SJoseph Chen return 0; 899c29dd8c4SJoseph Chen 9008d26d4b3SJoseph Chen return trusty_write_rollback_index(FIT_ROLLBACK_INDEX_LOCATION, 901c29dd8c4SJoseph Chen (u64)trusty_index); 902c29dd8c4SJoseph Chen } 903c29dd8c4SJoseph Chen #endif 904c29dd8c4SJoseph Chen 905189c0d68SJoseph Chen void board_quiesce_devices(void *images) 906189c0d68SJoseph Chen { 907189c0d68SJoseph Chen hotkey_run(HK_CMDLINE); 908189c0d68SJoseph Chen hotkey_run(HK_CLI_OS_GO); 909189c0d68SJoseph Chen 910189c0d68SJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 911189c0d68SJoseph Chen /* Destroy atags makes next warm boot safer */ 912189c0d68SJoseph Chen atags_destroy(); 913189c0d68SJoseph Chen #endif 914189c0d68SJoseph Chen 915189c0d68SJoseph Chen #ifdef CONFIG_FIT_ROLLBACK_PROTECT 9168d26d4b3SJoseph Chen int ret; 9178d26d4b3SJoseph Chen 9188d26d4b3SJoseph Chen ret = fit_write_trusty_rollback_index(gd->rollback_index); 9198d26d4b3SJoseph Chen if (ret) { 9208d26d4b3SJoseph Chen panic("Failed to write fit rollback index %d, ret=%d", 9218d26d4b3SJoseph Chen gd->rollback_index, ret); 9228d26d4b3SJoseph Chen } 923189c0d68SJoseph Chen #endif 924a5401a9dSJoseph Chen 925a5401a9dSJoseph Chen #ifdef CONFIG_ROCKCHIP_HW_DECOMPRESS 926a5401a9dSJoseph Chen misc_decompress_cleanup(); 927a5401a9dSJoseph Chen #endif 928189c0d68SJoseph Chen } 929