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> 8de77dbbbSJoseph Chen #include <version.h> 9d055d2cdSJoseph Chen #include <abuf.h> 1050d35c45SJoseph Chen #include <amp.h> 110f44aebdSJason Zhu #include <android_ab.h> 12ac5d8aa9SJoseph Chen #include <android_bootloader.h> 13ac5d8aa9SJoseph Chen #include <android_image.h> 1486f870d6SJoseph Chen #include <bidram.h> 150ed06f16SJoseph Chen #include <boot_rkimg.h> 160ed06f16SJoseph Chen #include <cli.h> 172208cd92SJoseph Chen #include <clk.h> 182208cd92SJoseph Chen #include <console.h> 19575777c5SKever Yang #include <debug_uart.h> 202208cd92SJoseph Chen #include <dm.h> 212208cd92SJoseph Chen #include <dvfs.h> 2267bee0b5SXiao Ya peng #include <fdt_support.h> 232208cd92SJoseph Chen #include <io-domain.h> 2403fd0d5bSJoseph Chen #include <image.h> 257397b961SJoseph Chen #include <key.h> 2686f870d6SJoseph Chen #include <memblk.h> 272208cd92SJoseph Chen #include <misc.h> 282208cd92SJoseph Chen #include <of_live.h> 29459f5cb0SJason Zhu #include <mtd_blk.h> 3038771996SKever Yang #include <ram.h> 31d055d2cdSJoseph Chen #include <rng.h> 322208cd92SJoseph Chen #include <rockchip_debugger.h> 3338771996SKever Yang #include <syscon.h> 346929f85bSJoseph Chen #include <sysmem.h> 352208cd92SJoseph Chen #include <video_rockchip.h> 361761a533SJoseph Chen #include <xbc.h> 3738771996SKever Yang #include <asm/io.h> 3838771996SKever Yang #include <asm/gpio.h> 39c9c15fdcSJason Zhu #include <android_avb/rk_avb_ops_user.h> 403e45175eSJoseph Chen #include <dm/uclass-internal.h> 412208cd92SJoseph Chen #include <dm/root.h> 422208cd92SJoseph Chen #include <power/charge_display.h> 432208cd92SJoseph Chen #include <power/regulator.h> 4403fd0d5bSJoseph Chen #include <optee_include/OpteeClientInterface.h> 45396e3049SElon Zhang #include <optee_include/OpteeClientApiLib.h> 46c29dd8c4SJoseph Chen #include <optee_include/tee_api_defines.h> 472208cd92SJoseph Chen #include <asm/arch/boot_mode.h> 4838771996SKever Yang #include <asm/arch/clock.h> 4960ea26bdSJoseph Chen #include <asm/arch/cpu.h> 50c664909eSJoseph Chen #include <asm/arch/hotkey.h> 516929f85bSJoseph Chen #include <asm/arch/param.h> 522208cd92SJoseph Chen #include <asm/arch/periph.h> 532208cd92SJoseph Chen #include <asm/arch/resource_img.h> 542208cd92SJoseph Chen #include <asm/arch/rk_atags.h> 552208cd92SJoseph Chen #include <asm/arch/vendor.h> 56efeef7e5SWenping Zhang #ifdef CONFIG_ROCKCHIP_EINK_DISPLAY 57efeef7e5SWenping Zhang #include <rk_eink.h> 58efeef7e5SWenping Zhang #endif 59b3372aa6SHuibin Hong #ifdef CONFIG_ROCKCHIP_MINIDUMP 60b3372aa6SHuibin Hong #include <rk_mini_dump.h> 61b3372aa6SHuibin Hong #endif 6238771996SKever Yang 634f7cc6a5SJoseph Chen #ifdef CONFIG_ARM64 644f7cc6a5SJoseph Chen static ulong orig_images_ep; 654f7cc6a5SJoseph Chen #endif 664f7cc6a5SJoseph Chen 6738771996SKever Yang __weak int rk_board_late_init(void) 6838771996SKever Yang { 6938771996SKever Yang return 0; 7038771996SKever Yang } 7138771996SKever Yang 7238ce6261SJoseph Chen __weak int rk_board_fdt_fixup(void *blob) 7338ce6261SJoseph Chen { 7438ce6261SJoseph Chen return 0; 7538ce6261SJoseph Chen } 7638ce6261SJoseph Chen 7720a45088SJoseph Chen __weak int rk_board_dm_fdt_fixup(void *blob) 7820a45088SJoseph Chen { 7920a45088SJoseph Chen return 0; 8020a45088SJoseph Chen } 8120a45088SJoseph Chen 82efdbac34SFinley Xiao __weak int soc_clk_dump(void) 83efdbac34SFinley Xiao { 84efdbac34SFinley Xiao return 0; 85efdbac34SFinley Xiao } 86efdbac34SFinley Xiao 87058e5d94SFinley Xiao __weak int set_armclk_rate(void) 88058e5d94SFinley Xiao { 89058e5d94SFinley Xiao return 0; 90058e5d94SFinley Xiao } 91058e5d94SFinley Xiao 922208cd92SJoseph Chen __weak int rk_board_init(void) 932208cd92SJoseph Chen { 942208cd92SJoseph Chen return 0; 952208cd92SJoseph Chen } 962208cd92SJoseph Chen 97c9a034c4SJoseph Chen #ifdef CONFIG_ROCKCHIP_SET_ETHADDR 982208cd92SJoseph Chen /* 992208cd92SJoseph Chen * define serialno max length, the max length is 512 Bytes 1002208cd92SJoseph Chen * The remaining bytes are used to ensure that the first 512 bytes 1012208cd92SJoseph Chen * are valid when executing 'env_set("serial#", value)'. 1022208cd92SJoseph Chen */ 1032208cd92SJoseph Chen #define VENDOR_SN_MAX 513 1042208cd92SJoseph Chen #define CPUID_LEN 0x10 1052208cd92SJoseph Chen 1062e32f666SDavid Wu #define MAX_ETHERNET 0x2 1072e32f666SDavid Wu 1082208cd92SJoseph Chen static int rockchip_set_ethaddr(void) 1092208cd92SJoseph Chen { 1106d9793cfSJoseph Chen __maybe_unused bool need_write = false; 1116d9793cfSJoseph Chen bool randomed = false; 1122e32f666SDavid Wu char buf[ARP_HLEN_ASCII + 1], mac[16]; 1132e32f666SDavid Wu u8 ethaddr[ARP_HLEN * MAX_ETHERNET] = {0}; 1146d9793cfSJoseph Chen int i, ret = -EINVAL; 1152208cd92SJoseph Chen 1166d9793cfSJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 11700fc4eeeSYifeng Zhao ret = vendor_storage_read(LAN_MAC_ID, ethaddr, sizeof(ethaddr)); 1186d9793cfSJoseph Chen #endif 1192e32f666SDavid Wu for (i = 0; i < MAX_ETHERNET; i++) { 1202e32f666SDavid Wu if (ret <= 0 || !is_valid_ethaddr(ðaddr[i * ARP_HLEN])) { 1212cde40a1SDavid Wu if (!randomed) { 1222e32f666SDavid Wu net_random_ethaddr(ðaddr[i * ARP_HLEN]); 1232cde40a1SDavid Wu randomed = true; 1242cde40a1SDavid Wu } else { 1252cde40a1SDavid Wu if (i > 0) { 1262cde40a1SDavid Wu memcpy(ðaddr[i * ARP_HLEN], 1272cde40a1SDavid Wu ðaddr[(i - 1) * ARP_HLEN], 1282cde40a1SDavid Wu ARP_HLEN); 1292cde40a1SDavid Wu ethaddr[i * ARP_HLEN] |= 0x02; 1302cde40a1SDavid Wu ethaddr[i * ARP_HLEN] += (i << 2); 1312cde40a1SDavid Wu } 1322cde40a1SDavid Wu } 1332cde40a1SDavid Wu 1342e32f666SDavid Wu need_write = true; 1352e32f666SDavid Wu } 1362e32f666SDavid Wu 1372e32f666SDavid Wu if (is_valid_ethaddr(ðaddr[i * ARP_HLEN])) { 138c1c7e89dSJianqun Xu snprintf(buf, ARP_HLEN_ASCII + 1, "%pM", ðaddr[i * ARP_HLEN]); 1392e32f666SDavid Wu if (i == 0) 1402e32f666SDavid Wu memcpy(mac, "ethaddr", sizeof("ethaddr")); 1412e32f666SDavid Wu else 1422e32f666SDavid Wu sprintf(mac, "eth%daddr", i); 1432e32f666SDavid Wu env_set(mac, buf); 1442e32f666SDavid Wu } 1452e32f666SDavid Wu } 1462e32f666SDavid Wu 1476d9793cfSJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 1482e32f666SDavid Wu if (need_write) { 14900fc4eeeSYifeng Zhao ret = vendor_storage_write(LAN_MAC_ID, 1502e32f666SDavid Wu ethaddr, sizeof(ethaddr)); 1512e32f666SDavid Wu if (ret < 0) 1522e32f666SDavid Wu printf("%s: vendor_storage_write failed %d\n", 1532e32f666SDavid Wu __func__, ret); 1542208cd92SJoseph Chen } 1552208cd92SJoseph Chen #endif 1562208cd92SJoseph Chen return 0; 1572208cd92SJoseph Chen } 158c9a034c4SJoseph Chen #endif 1592208cd92SJoseph Chen 160c9a034c4SJoseph Chen #ifdef CONFIG_ROCKCHIP_SET_SN 1612208cd92SJoseph Chen static int rockchip_set_serialno(void) 1622208cd92SJoseph Chen { 1632208cd92SJoseph Chen u8 low[CPUID_LEN / 2], high[CPUID_LEN / 2]; 1642208cd92SJoseph Chen u8 cpuid[CPUID_LEN] = {0}; 1652208cd92SJoseph Chen char serialno_str[VENDOR_SN_MAX]; 1662208cd92SJoseph Chen int ret = 0, i; 1672208cd92SJoseph Chen u64 serialno; 1682208cd92SJoseph Chen 1692208cd92SJoseph Chen /* Read serial number from vendor storage part */ 1702208cd92SJoseph Chen memset(serialno_str, 0, VENDOR_SN_MAX); 1712208cd92SJoseph Chen 1722208cd92SJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 17380b41b17SJon Lin int j; 17480b41b17SJon Lin 17500fc4eeeSYifeng Zhao ret = vendor_storage_read(SN_ID, serialno_str, (VENDOR_SN_MAX-1)); 1762208cd92SJoseph Chen if (ret > 0) { 17780b41b17SJon Lin j = strlen(serialno_str); 17880b41b17SJon Lin for (i = 0; i < j; i++) { 179df197bd2SJason Zhu if ((serialno_str[i] >= 'a' && serialno_str[i] <= 'z') || 180df197bd2SJason Zhu (serialno_str[i] >= 'A' && serialno_str[i] <= 'Z') || 1817157beb3SJianwei Zheng (serialno_str[i] >= '0' && serialno_str[i] <= '9')) { 182d20d7c0cSJason Zhu continue; 1837157beb3SJianwei Zheng } else { 1847157beb3SJianwei Zheng if (i > 0) 1857157beb3SJianwei Zheng serialno_str[i] = 0x0; 186df197bd2SJason Zhu break; 187df197bd2SJason Zhu } 1887157beb3SJianwei Zheng } 189df197bd2SJason Zhu 190fa7e137dSJoseph Chen /* valid character count > 0 */ 191fa7e137dSJoseph Chen if (i > 0) { 192df197bd2SJason Zhu serialno_str[i + 1] = 0x0; 1932208cd92SJoseph Chen env_set("serial#", serialno_str); 194fa7e137dSJoseph Chen } 195fa7e137dSJoseph Chen } 1962208cd92SJoseph Chen #endif 197fa7e137dSJoseph Chen if (!env_get("serial#")) { 198d3cb8b06SSugar Zhang #if defined(CONFIG_ROCKCHIP_EFUSE) || defined(CONFIG_ROCKCHIP_OTP) 1992208cd92SJoseph Chen struct udevice *dev; 2002208cd92SJoseph Chen 2012208cd92SJoseph Chen /* retrieve the device */ 202d3cb8b06SSugar Zhang if (IS_ENABLED(CONFIG_ROCKCHIP_EFUSE)) 2032208cd92SJoseph Chen ret = uclass_get_device_by_driver(UCLASS_MISC, 2042208cd92SJoseph Chen DM_GET_DRIVER(rockchip_efuse), 2052208cd92SJoseph Chen &dev); 206d3cb8b06SSugar Zhang else 207d3cb8b06SSugar Zhang ret = uclass_get_device_by_driver(UCLASS_MISC, 208d3cb8b06SSugar Zhang DM_GET_DRIVER(rockchip_otp), 209d3cb8b06SSugar Zhang &dev); 210d3cb8b06SSugar Zhang 2112208cd92SJoseph Chen if (ret) { 212d3cb8b06SSugar Zhang printf("%s: could not find efuse/otp device\n", __func__); 2132208cd92SJoseph Chen return ret; 2142208cd92SJoseph Chen } 2152208cd92SJoseph Chen 2162208cd92SJoseph Chen /* read the cpu_id range from the efuses */ 21791411fc1SSugar Zhang ret = misc_read(dev, CFG_CPUID_OFFSET, &cpuid, sizeof(cpuid)); 2182208cd92SJoseph Chen if (ret) { 219d3cb8b06SSugar Zhang printf("%s: read cpuid from efuse/otp failed, ret=%d\n", 2202208cd92SJoseph Chen __func__, ret); 2212208cd92SJoseph Chen return ret; 2222208cd92SJoseph Chen } 2232208cd92SJoseph Chen #else 2242208cd92SJoseph Chen /* generate random cpuid */ 2252208cd92SJoseph Chen for (i = 0; i < CPUID_LEN; i++) 2262208cd92SJoseph Chen cpuid[i] = (u8)(rand()); 2272208cd92SJoseph Chen #endif 2282208cd92SJoseph Chen /* Generate the serial number based on CPU ID */ 2292208cd92SJoseph Chen for (i = 0; i < 8; i++) { 2302208cd92SJoseph Chen low[i] = cpuid[1 + (i << 1)]; 2312208cd92SJoseph Chen high[i] = cpuid[i << 1]; 2322208cd92SJoseph Chen } 2332208cd92SJoseph Chen 2342208cd92SJoseph Chen serialno = crc32_no_comp(0, low, 8); 2352208cd92SJoseph Chen serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32; 2362208cd92SJoseph Chen snprintf(serialno_str, sizeof(serialno_str), "%llx", serialno); 2372208cd92SJoseph Chen 2382208cd92SJoseph Chen env_set("serial#", serialno_str); 2392208cd92SJoseph Chen } 2402208cd92SJoseph Chen 2412208cd92SJoseph Chen return ret; 2422208cd92SJoseph Chen } 243c9a034c4SJoseph Chen #endif 244c9a034c4SJoseph Chen 2452208cd92SJoseph Chen #if defined(CONFIG_USB_FUNCTION_FASTBOOT) 2462208cd92SJoseph Chen int fb_set_reboot_flag(void) 2472208cd92SJoseph Chen { 2482208cd92SJoseph Chen printf("Setting reboot to fastboot flag ...\n"); 2492208cd92SJoseph Chen writel(BOOT_FASTBOOT, CONFIG_ROCKCHIP_BOOT_MODE_REG); 2502208cd92SJoseph Chen 2512208cd92SJoseph Chen return 0; 2522208cd92SJoseph Chen } 2532208cd92SJoseph Chen #endif 2542208cd92SJoseph Chen 2550ed06f16SJoseph Chen #ifdef CONFIG_ROCKCHIP_USB_BOOT 2560ed06f16SJoseph Chen static int boot_from_udisk(void) 2570ed06f16SJoseph Chen { 2580ed06f16SJoseph Chen struct blk_desc *desc; 25983be1580SJoseph Chen struct udevice *dev; 26083be1580SJoseph Chen int devnum = -1; 26183be1580SJoseph Chen char buf[32]; 2620ed06f16SJoseph Chen 2630ed06f16SJoseph Chen /* Booting priority: mmc1 > udisk */ 26483be1580SJoseph Chen if (!strcmp(env_get("devtype"), "mmc") && !strcmp(env_get("devnum"), "1")) 2650ed06f16SJoseph Chen return 0; 2660ed06f16SJoseph Chen 2670ed06f16SJoseph Chen if (!run_command("usb start", -1)) { 26883be1580SJoseph Chen for (blk_first_device(IF_TYPE_USB, &dev); 26983be1580SJoseph Chen dev; 27083be1580SJoseph Chen blk_next_device(&dev)) { 27183be1580SJoseph Chen desc = dev_get_uclass_platdata(dev); 27283be1580SJoseph Chen printf("Scanning usb %d ...\n", desc->devnum); 27383be1580SJoseph Chen if (desc->type == DEV_TYPE_UNKNOWN) 27483be1580SJoseph Chen continue; 27583be1580SJoseph Chen 27683be1580SJoseph Chen if (desc->lba > 0L && desc->blksz > 0L) { 27783be1580SJoseph Chen devnum = desc->devnum; 27883be1580SJoseph Chen break; 27983be1580SJoseph Chen } 28083be1580SJoseph Chen } 28183be1580SJoseph Chen if (devnum < 0) { 28283be1580SJoseph Chen printf("No usb mass storage found\n"); 2830ed06f16SJoseph Chen return -ENODEV; 2840ed06f16SJoseph Chen } 2850ed06f16SJoseph Chen 28683be1580SJoseph Chen desc = blk_get_devnum_by_type(IF_TYPE_USB, devnum); 28783be1580SJoseph Chen if (!desc) { 28883be1580SJoseph Chen printf("No usb %d found\n", devnum); 28983be1580SJoseph Chen return -ENODEV; 29083be1580SJoseph Chen } 29183be1580SJoseph Chen 29283be1580SJoseph Chen snprintf(buf, 32, "rkimgtest usb %d", devnum); 29383be1580SJoseph Chen if (!run_command(buf, -1)) { 29483be1580SJoseph Chen snprintf(buf, 32, "%d", devnum); 2950ed06f16SJoseph Chen rockchip_set_bootdev(desc); 2960ed06f16SJoseph Chen env_set("devtype", "usb"); 29783be1580SJoseph Chen env_set("devnum", buf); 29883be1580SJoseph Chen printf("=== Booting from usb %d ===\n", devnum); 2990ed06f16SJoseph Chen } else { 30083be1580SJoseph Chen printf("No available udisk image on usb %d\n", devnum); 3010ed06f16SJoseph Chen return -ENODEV; 3020ed06f16SJoseph Chen } 3030ed06f16SJoseph Chen } 3040ed06f16SJoseph Chen 3050ed06f16SJoseph Chen return 0; 3060ed06f16SJoseph Chen } 3070ed06f16SJoseph Chen #endif 3080ed06f16SJoseph Chen 309c6f0e819SJoseph Chen static void env_fixup(void) 310c6f0e819SJoseph Chen { 311c6f0e819SJoseph Chen struct memblock mem; 312c6f0e819SJoseph Chen ulong u_addr_r; 313c6f0e819SJoseph Chen phys_size_t end; 314c6f0e819SJoseph Chen char *addr_r; 315c6f0e819SJoseph Chen 316c6f0e819SJoseph Chen #ifdef ENV_MEM_LAYOUT_SETTINGS1 317c6f0e819SJoseph Chen const char *env_addr0[] = { 318c6f0e819SJoseph Chen "scriptaddr", "pxefile_addr_r", 319c6f0e819SJoseph Chen "fdt_addr_r", "kernel_addr_r", "ramdisk_addr_r", 320c6f0e819SJoseph Chen }; 321c6f0e819SJoseph Chen const char *env_addr1[] = { 322c6f0e819SJoseph Chen "scriptaddr1", "pxefile_addr1_r", 323c6f0e819SJoseph Chen "fdt_addr1_r", "kernel_addr1_r", "ramdisk_addr1_r", 324c6f0e819SJoseph Chen }; 325c6f0e819SJoseph Chen int i; 326c6f0e819SJoseph Chen 327c6f0e819SJoseph Chen /* 128M is a typical ram size for most platform, so as default here */ 328c6f0e819SJoseph Chen if (gd->ram_size <= SZ_128M) { 329c6f0e819SJoseph Chen /* Replace orignal xxx_addr_r */ 330c6f0e819SJoseph Chen for (i = 0; i < ARRAY_SIZE(env_addr1); i++) { 331c6f0e819SJoseph Chen addr_r = env_get(env_addr1[i]); 332c6f0e819SJoseph Chen if (addr_r) 333c6f0e819SJoseph Chen env_set(env_addr0[i], addr_r); 334c6f0e819SJoseph Chen } 335c6f0e819SJoseph Chen } 336c6f0e819SJoseph Chen #endif 33749e18ddbSJoseph Chen /* No BL32 ? */ 338c6f0e819SJoseph Chen if (!(gd->flags & GD_FLG_BL32_ENABLED)) { 33949e18ddbSJoseph Chen /* 34049e18ddbSJoseph Chen * [1] Move kernel to lower address if possible. 34149e18ddbSJoseph Chen */ 34249e18ddbSJoseph Chen addr_r = env_get("kernel_addr_no_low_bl32_r"); 343c6f0e819SJoseph Chen if (addr_r) 344c6f0e819SJoseph Chen env_set("kernel_addr_r", addr_r); 3454175c722SJoseph Chen 3464175c722SJoseph Chen /* 34749e18ddbSJoseph Chen * [2] Move ramdisk at BL32 position if need. 34849e18ddbSJoseph Chen * 3494175c722SJoseph Chen * 0x0a200000 and 0x08400000 are rockchip traditional address 3504175c722SJoseph Chen * of BL32 and ramdisk: 3514175c722SJoseph Chen * 3524175c722SJoseph Chen * |------------|------------| 3534175c722SJoseph Chen * | BL32 | ramdisk | 3544175c722SJoseph Chen * |------------|------------| 3554175c722SJoseph Chen * 3564175c722SJoseph Chen * Move ramdisk to BL32 address to fix sysmem alloc failed 3574175c722SJoseph Chen * issue on the board with critical memory(ie. 256MB). 3584175c722SJoseph Chen */ 3594175c722SJoseph Chen if (gd->ram_size > SZ_128M && gd->ram_size <= SZ_256M) { 3604175c722SJoseph Chen u_addr_r = env_get_ulong("ramdisk_addr_r", 16, 0); 3614175c722SJoseph Chen if (u_addr_r == 0x0a200000) 3624175c722SJoseph Chen env_set("ramdisk_addr_r", "0x08400000"); 3634175c722SJoseph Chen } 364c6f0e819SJoseph Chen } else { 365c6f0e819SJoseph Chen mem = param_parse_optee_mem(); 36649e18ddbSJoseph Chen 36749e18ddbSJoseph Chen /* 36849e18ddbSJoseph Chen * [1] Move kernel forward if possible. 36949e18ddbSJoseph Chen */ 37049e18ddbSJoseph Chen if (mem.base > SZ_128M) { 37149e18ddbSJoseph Chen addr_r = env_get("kernel_addr_no_low_bl32_r"); 37249e18ddbSJoseph Chen if (addr_r) 37349e18ddbSJoseph Chen env_set("kernel_addr_r", addr_r); 37449e18ddbSJoseph Chen } 37549e18ddbSJoseph Chen 37649e18ddbSJoseph Chen /* 37749e18ddbSJoseph Chen * [2] Move ramdisk backward if optee enlarge. 37849e18ddbSJoseph Chen */ 379c6f0e819SJoseph Chen end = mem.base + mem.size; 380c6f0e819SJoseph Chen u_addr_r = env_get_ulong("ramdisk_addr_r", 16, 0); 381c6f0e819SJoseph Chen if (u_addr_r >= mem.base && u_addr_r < end) 382c6f0e819SJoseph Chen env_set_hex("ramdisk_addr_r", end); 383c6f0e819SJoseph Chen } 384c6f0e819SJoseph Chen } 385c6f0e819SJoseph Chen 38683c9bd4bSJoseph Chen static void cmdline_handle(void) 38783c9bd4bSJoseph Chen { 38860f07e75SJoseph Chen struct blk_desc *dev_desc; 38983be1580SJoseph Chen int if_type; 39083be1580SJoseph Chen int devnum; 39160f07e75SJoseph Chen 392045d3eaaSJoseph Chen param_parse_pubkey_fuse_programmed(); 39383c9bd4bSJoseph Chen 39460f07e75SJoseph Chen dev_desc = rockchip_get_bootdev(); 39560f07e75SJoseph Chen if (!dev_desc) 39660f07e75SJoseph Chen return; 39760f07e75SJoseph Chen 398692d3098SJoseph Chen /* 3993d2521fcSJoseph Chen * 1. From rk356x, the sd/udisk recovery update flag was moved from 400692d3098SJoseph Chen * IDB to Android BCB. 4013d2521fcSJoseph Chen * 4023d2521fcSJoseph Chen * 2. Udisk is init at the late boot_from_udisk(), but 4033d2521fcSJoseph Chen * rockchip_get_boot_mode() actually only read once, 4043d2521fcSJoseph Chen * we need to update boot mode according to udisk BCB. 405692d3098SJoseph Chen */ 40683be1580SJoseph Chen if_type = dev_desc->if_type; 40783be1580SJoseph Chen devnum = dev_desc->devnum; 40883be1580SJoseph Chen if ((if_type == IF_TYPE_MMC && devnum == 1) || (if_type == IF_TYPE_USB)) { 409706ec1d4SJoseph Chen if (get_bcb_recovery_msg() == BCB_MSG_RECOVERY_RK_FWUPDATE) { 41083be1580SJoseph Chen if (if_type == IF_TYPE_MMC && devnum == 1) { 41160f07e75SJoseph Chen env_update("bootargs", "sdfwupdate"); 41283be1580SJoseph Chen } else if (if_type == IF_TYPE_USB) { 41360f07e75SJoseph Chen env_update("bootargs", "usbfwupdate"); 4143d2521fcSJoseph Chen env_set("reboot_mode", "recovery-usb"); 4153d2521fcSJoseph Chen } 4163d2521fcSJoseph Chen } else { 41783be1580SJoseph Chen if (if_type == IF_TYPE_USB) 4183d2521fcSJoseph Chen env_set("reboot_mode", "normal"); 4193d2521fcSJoseph Chen } 42060f07e75SJoseph Chen } 4218af25352SZorro Liu 4228af25352SZorro Liu if (rockchip_get_boot_mode() == BOOT_MODE_QUIESCENT) 4238af25352SZorro Liu env_update("bootargs", "androidboot.quiescent=1 pwm_bl.quiescent=1"); 42483c9bd4bSJoseph Chen } 42583c9bd4bSJoseph Chen 426a03ccd5bSJoseph Chen static void scan_run_cmd(void) 427a03ccd5bSJoseph Chen { 428a03ccd5bSJoseph Chen char *config = CONFIG_ROCKCHIP_CMD; 429a03ccd5bSJoseph Chen char *cmd, *key; 430a03ccd5bSJoseph Chen 431a03ccd5bSJoseph Chen key = strchr(config, ' '); 432a03ccd5bSJoseph Chen if (!key) 433a03ccd5bSJoseph Chen return; 434a03ccd5bSJoseph Chen 435a03ccd5bSJoseph Chen cmd = strdup(config); 436a03ccd5bSJoseph Chen cmd[key - config] = 0; 437a03ccd5bSJoseph Chen key++; 438a03ccd5bSJoseph Chen 439a03ccd5bSJoseph Chen if (!strcmp(key, "-")) { 440a03ccd5bSJoseph Chen run_command(cmd, 0); 441a03ccd5bSJoseph Chen } else { 442a03ccd5bSJoseph Chen #ifdef CONFIG_DM_KEY 443a03ccd5bSJoseph Chen ulong map; 444a03ccd5bSJoseph Chen 445a03ccd5bSJoseph Chen map = simple_strtoul(key, NULL, 10); 446a03ccd5bSJoseph Chen if (key_is_pressed(key_read(map))) { 447a03ccd5bSJoseph Chen printf("## Key<%ld> pressed... run cmd '%s'\n", map, cmd); 448a03ccd5bSJoseph Chen run_command(cmd, 0); 449a03ccd5bSJoseph Chen } 450a03ccd5bSJoseph Chen #endif 451a03ccd5bSJoseph Chen } 452a03ccd5bSJoseph Chen } 453a03ccd5bSJoseph Chen 45438771996SKever Yang int board_late_init(void) 45538771996SKever Yang { 456c9a034c4SJoseph Chen #ifdef CONFIG_ROCKCHIP_SET_ETHADDR 4572549364dSlanshh rockchip_set_ethaddr(); 458c9a034c4SJoseph Chen #endif 459c9a034c4SJoseph Chen #ifdef CONFIG_ROCKCHIP_SET_SN 460fc1a5563SJason Zhu rockchip_set_serialno(); 461c9a034c4SJoseph Chen #endif 462d04ada6cSJoseph Chen setup_download_mode(); 463a03ccd5bSJoseph Chen scan_run_cmd(); 4640ed06f16SJoseph Chen #ifdef CONFIG_ROCKCHIP_USB_BOOT 4650ed06f16SJoseph Chen boot_from_udisk(); 4660ed06f16SJoseph Chen #endif 46738771996SKever Yang #ifdef CONFIG_DM_CHARGE_DISPLAY 46838771996SKever Yang charge_display(); 46938771996SKever Yang #endif 470b3372aa6SHuibin Hong 471b3372aa6SHuibin Hong #ifdef CONFIG_ROCKCHIP_MINIDUMP 472b3372aa6SHuibin Hong rk_minidump_init(); 473b3372aa6SHuibin Hong #endif 474b3372aa6SHuibin Hong 47538771996SKever Yang #ifdef CONFIG_DRM_ROCKCHIP 4768af25352SZorro Liu if (rockchip_get_boot_mode() != BOOT_MODE_QUIESCENT) 47738771996SKever Yang rockchip_show_logo(); 47838771996SKever Yang #endif 479efeef7e5SWenping Zhang #ifdef CONFIG_ROCKCHIP_EINK_DISPLAY 480efeef7e5SWenping Zhang rockchip_eink_show_uboot_logo(); 481efeef7e5SWenping Zhang #endif 48291ed07e5SJoseph Chen #if (CONFIG_ROCKCHIP_BOOT_MODE_REG > 0) 48391ed07e5SJoseph Chen setup_boot_mode(); 48491ed07e5SJoseph Chen #endif 485c6f0e819SJoseph Chen env_fixup(); 486efdbac34SFinley Xiao soc_clk_dump(); 48783c9bd4bSJoseph Chen cmdline_handle(); 48875ac0a02SJoseph Chen #ifdef CONFIG_AMP 48975ac0a02SJoseph Chen amp_cpus_on(); 49075ac0a02SJoseph Chen #endif 49138771996SKever Yang return rk_board_late_init(); 49238771996SKever Yang } 49338771996SKever Yang 494a7940145SJoseph Chen static void early_download(void) 495644804edSJoseph Chen { 4967397b961SJoseph Chen #if defined(CONFIG_PWRKEY_DNL_TRIGGER_NUM) && \ 4977397b961SJoseph Chen (CONFIG_PWRKEY_DNL_TRIGGER_NUM > 0) 4987397b961SJoseph Chen if (pwrkey_download_init()) 4997397b961SJoseph Chen printf("Pwrkey download init failed\n"); 5007397b961SJoseph Chen #endif 5017397b961SJoseph Chen 502644804edSJoseph Chen #if (CONFIG_ROCKCHIP_BOOT_MODE_REG > 0) 503c664909eSJoseph Chen if (is_hotkey(HK_BROM_DNL)) { 504644804edSJoseph Chen printf("Enter bootrom download..."); 505363411a1SJoseph Chen flushc(); 506644804edSJoseph Chen writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG); 507644804edSJoseph Chen do_reset(NULL, 0, 0, NULL); 508644804edSJoseph Chen printf("failed!\n"); 509644804edSJoseph Chen } 510644804edSJoseph Chen #endif 511644804edSJoseph Chen } 512644804edSJoseph Chen 5135d5f363eSJoseph Chen static void board_debug_init(void) 5145d5f363eSJoseph Chen { 51593586e70SJoseph Chen if (!gd->serial.using_pre_serial && 51693586e70SJoseph Chen !(gd->flags & GD_FLG_DISABLE_CONSOLE)) 5177abb254dSJoseph Chen debug_uart_init(); 51846f61401SJoseph Chen 51946f61401SJoseph Chen if (tstc()) { 52046f61401SJoseph Chen gd->console_evt = getc(); 52146f61401SJoseph Chen if (gd->console_evt <= 0x1a) /* 'z' */ 52246f61401SJoseph Chen printf("Hotkey: ctrl+%c\n", gd->console_evt + 'a' - 1); 52346f61401SJoseph Chen } 5249889a0e0SJoseph Chen 5259889a0e0SJoseph Chen if (IS_ENABLED(CONFIG_CONSOLE_DISABLE_CLI)) 52625047d3fSJoseph Chen printf("Cmd interface: disabled\n"); 5275d5f363eSJoseph Chen } 5285d5f363eSJoseph Chen 52938771996SKever Yang int board_init(void) 53038771996SKever Yang { 5315d5f363eSJoseph Chen board_debug_init(); 532f0aa8c5dSJason Zhu #ifdef DEBUG 533f0aa8c5dSJason Zhu soc_clk_dump(); 534f0aa8c5dSJason Zhu #endif 535e8086feaSJoseph Chen #ifdef CONFIG_OPTEE_CLIENT 5360c794d33SHisping Lin optee_client_init(); 537e8086feaSJoseph Chen #endif 538e8086feaSJoseph Chen #ifdef CONFIG_USING_KERNEL_DTB 539f8aaa2c2SKever Yang init_kernel_dtb(); 540f8aaa2c2SKever Yang #endif 541a7940145SJoseph Chen early_download(); 5427397b961SJoseph Chen 5439f8e13d3SFinley Xiao clks_probe(); 54438771996SKever Yang #ifdef CONFIG_DM_REGULATOR 545e8086feaSJoseph Chen regulators_enable_boot_on(is_hotkey(HK_REGULATOR)); 54638771996SKever Yang #endif 547dae20286SJianqun Xu #ifdef CONFIG_ROCKCHIP_IO_DOMAIN 548dae20286SJianqun Xu io_domain_init(); 549dae20286SJianqun Xu #endif 550058e5d94SFinley Xiao set_armclk_rate(); 5513acf4edfSJoseph Chen #ifdef CONFIG_DM_DVFS 5523acf4edfSJoseph Chen dvfs_init(true); 5533acf4edfSJoseph Chen #endif 5540f44aebdSJason Zhu #ifdef CONFIG_ANDROID_AB 5550f44aebdSJason Zhu if (ab_decrease_tries()) 5560f44aebdSJason Zhu printf("Decrease ab tries count fail!\n"); 5570f44aebdSJason Zhu #endif 55838771996SKever Yang return rk_board_init(); 55938771996SKever Yang } 56038771996SKever Yang 561c563adc7SJoseph Chen int interrupt_debugger_init(void) 562c563adc7SJoseph Chen { 563c563adc7SJoseph Chen #ifdef CONFIG_ROCKCHIP_DEBUGGER 5642208cd92SJoseph Chen return rockchip_debugger_init(); 5652208cd92SJoseph Chen #else 5662208cd92SJoseph Chen return 0; 567c563adc7SJoseph Chen #endif 568c563adc7SJoseph Chen } 569c563adc7SJoseph Chen 570b87fc700SJoseph Chen #ifdef CONFIG_SANITY_CPU_SWAP 571b87fc700SJoseph Chen static void sanity_cpu_swap(void *blob) 572b87fc700SJoseph Chen { 573b87fc700SJoseph Chen int cpus_offset; 574b87fc700SJoseph Chen int noffset; 575b87fc700SJoseph Chen ulong mpidr; 576b87fc700SJoseph Chen ulong reg; 577b87fc700SJoseph Chen 578b87fc700SJoseph Chen cpus_offset = fdt_path_offset(blob, "/cpus"); 579b87fc700SJoseph Chen if (cpus_offset < 0) 580b87fc700SJoseph Chen return; 581b87fc700SJoseph Chen 582b87fc700SJoseph Chen for (noffset = fdt_first_subnode(blob, cpus_offset); 583b87fc700SJoseph Chen noffset >= 0; 584b87fc700SJoseph Chen noffset = fdt_next_subnode(blob, noffset)) { 585b87fc700SJoseph Chen const struct fdt_property *prop; 586b87fc700SJoseph Chen int len; 587b87fc700SJoseph Chen 588b87fc700SJoseph Chen prop = fdt_get_property(blob, noffset, "device_type", &len); 589b87fc700SJoseph Chen if (!prop) 590b87fc700SJoseph Chen continue; 591b87fc700SJoseph Chen if (len < 4) 592b87fc700SJoseph Chen continue; 593b87fc700SJoseph Chen if (strcmp(prop->data, "cpu")) 594b87fc700SJoseph Chen continue; 595b87fc700SJoseph Chen 596b87fc700SJoseph Chen /* only sanity first cpu */ 597b87fc700SJoseph Chen reg = (ulong)fdtdec_get_addr_size_auto_parent(blob, cpus_offset, noffset, 598b87fc700SJoseph Chen "reg", 0, NULL, false); 599b87fc700SJoseph Chen mpidr = read_mpidr() & 0xfff; 600b87fc700SJoseph Chen if ((mpidr & reg) != reg) { 601b87fc700SJoseph Chen printf("CPU swap error: Loader and Kernel firmware mismatch! " 602b87fc700SJoseph Chen "Current cpu0 \"reg\" is 0x%lx but kernel dtb requires 0x%lx\n", 603b87fc700SJoseph Chen mpidr, reg); 604b87fc700SJoseph Chen run_command("download", 0); 605b87fc700SJoseph Chen } 606b87fc700SJoseph Chen return; 607b87fc700SJoseph Chen } 608b87fc700SJoseph Chen } 609b87fc700SJoseph Chen #endif 610b87fc700SJoseph Chen 611e09b1e4aSJoseph Chen int board_fdt_fixup(void *blob) 612e09b1e4aSJoseph Chen { 613b87fc700SJoseph Chen #ifdef CONFIG_SANITY_CPU_SWAP 614b87fc700SJoseph Chen sanity_cpu_swap(blob); 615b87fc700SJoseph Chen #endif 61620a45088SJoseph Chen /* 61720a45088SJoseph Chen * Device's platdata points to orignal fdt blob property, 61820a45088SJoseph Chen * access DM device before any fdt fixup. 61920a45088SJoseph Chen */ 62020a45088SJoseph Chen rk_board_dm_fdt_fixup(blob); 62120a45088SJoseph Chen 6222208cd92SJoseph Chen /* Common fixup for DRM */ 623e09b1e4aSJoseph Chen #ifdef CONFIG_DRM_ROCKCHIP 624e09b1e4aSJoseph Chen rockchip_display_fixup(blob); 625e09b1e4aSJoseph Chen #endif 626e09b1e4aSJoseph Chen 6272a217cf1SYifeng Zhao #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 6282a217cf1SYifeng Zhao vendor_storage_fixup(blob); 6292a217cf1SYifeng Zhao #endif 6302a217cf1SYifeng Zhao 63138ce6261SJoseph Chen return rk_board_fdt_fixup(blob); 632e09b1e4aSJoseph Chen } 633e09b1e4aSJoseph Chen 634102dfafcSElon Zhang #if defined(CONFIG_ARM64_BOOT_AARCH32) || !defined(CONFIG_ARM64) 635e3fbd280SJoseph Chen /* 636f1d65189SJoseph Chen * Common for OP-TEE: 637396e3049SElon Zhang * 64-bit & 32-bit mode: share memory dcache is always enabled; 638e3fbd280SJoseph Chen * 639f1d65189SJoseph Chen * Common for U-Boot: 640e3fbd280SJoseph Chen * 64-bit mode: MMU table is static defined in rkxxx.c file, all memory 641e3fbd280SJoseph Chen * regions are mapped. That's good to match OP-TEE MMU policy. 642e3fbd280SJoseph Chen * 643e3fbd280SJoseph Chen * 32-bit mode: MMU table is setup according to gd->bd->bi_dram[..] where 644e3fbd280SJoseph Chen * the OP-TEE region has been reserved, so it can not be 645102dfafcSElon Zhang * mapped(i.e. dcache is disabled). That's *NOT* good to match 646e3fbd280SJoseph Chen * OP-TEE MMU policy. 647e3fbd280SJoseph Chen * 648e3fbd280SJoseph Chen * For the data coherence when communication between U-Boot and OP-TEE, U-Boot 649e3fbd280SJoseph Chen * should follow OP-TEE MMU policy. 650e3fbd280SJoseph Chen * 651396e3049SElon Zhang * So 32-bit mode U-Boot should map OP-TEE share memory as dcache enabled. 652e3fbd280SJoseph Chen */ 653e3fbd280SJoseph Chen int board_initr_caches_fixup(void) 654e3fbd280SJoseph Chen { 655396e3049SElon Zhang #ifdef CONFIG_OPTEE_CLIENT 656e3fbd280SJoseph Chen struct memblock mem; 657e3fbd280SJoseph Chen 658396e3049SElon Zhang mem.base = 0; 659396e3049SElon Zhang mem.size = 0; 660396e3049SElon Zhang 661396e3049SElon Zhang optee_get_shm_config(&mem.base, &mem.size); 662e3fbd280SJoseph Chen if (mem.size) 663e3fbd280SJoseph Chen mmu_set_region_dcache_behaviour(mem.base, mem.size, 664e3fbd280SJoseph Chen DCACHE_WRITEBACK); 665396e3049SElon Zhang #endif 666e3fbd280SJoseph Chen return 0; 667e3fbd280SJoseph Chen } 668e3fbd280SJoseph Chen #endif 669e3fbd280SJoseph Chen 6704353cdc4SJoseph Chen void arch_preboot_os(uint32_t bootm_state, bootm_headers_t *images) 671665be4b0SJoseph Chen { 6724353cdc4SJoseph Chen if (!(bootm_state & BOOTM_STATE_OS_PREP)) 6734353cdc4SJoseph Chen return; 6744353cdc4SJoseph Chen 6754353cdc4SJoseph Chen #ifdef CONFIG_ARM64 6764353cdc4SJoseph Chen u8 *data = (void *)images->ep; 6774353cdc4SJoseph Chen 6784353cdc4SJoseph Chen /* 6794353cdc4SJoseph Chen * Fix kernel 5.10 arm64 boot warning: 6804353cdc4SJoseph Chen * "[Firmware Bug]: Kernel image misaligned at boot, please fix your bootloader!" 6814353cdc4SJoseph Chen * 6824353cdc4SJoseph Chen * kernel: 5.10 commit 120dc60d0bdb ("arm64: get rid of TEXT_OFFSET") 6834353cdc4SJoseph Chen * arm64 kernel version: 684c3515b67SJoseph Chen * data[10] == 0x00 if kernel version >= 5.10: N*2MB align 685c3515b67SJoseph Chen * data[10] == 0x08 if kernel version < 5.10: N*2MB + 0x80000(TEXT_OFFSET) 6864353cdc4SJoseph Chen * 6874353cdc4SJoseph Chen * Why fix here? 6884353cdc4SJoseph Chen * 1. this is the common and final path for any boot command. 6894353cdc4SJoseph Chen * 2. don't influence original boot flow, just fix it exactly before 6904353cdc4SJoseph Chen * jumping kernel. 691b627269dSJoseph Chen * 692b627269dSJoseph Chen * But relocation is in board_quiesce_devices() until all decompress 693b627269dSJoseph Chen * done, mainly for saving boot time. 6944353cdc4SJoseph Chen */ 6954f7cc6a5SJoseph Chen 6964f7cc6a5SJoseph Chen orig_images_ep = images->ep; 6974f7cc6a5SJoseph Chen 6984353cdc4SJoseph Chen if (data[10] == 0x00) { 699b627269dSJoseph Chen if (round_down(images->ep, SZ_2M) != images->ep) 700b627269dSJoseph Chen images->ep = round_down(images->ep, SZ_2M); 701a4625d53SJoseph Chen } else { 702b627269dSJoseph Chen if (IS_ALIGNED(images->ep, SZ_2M)) 703b627269dSJoseph Chen images->ep += 0x80000; 7044353cdc4SJoseph Chen } 7054353cdc4SJoseph Chen #endif 706665be4b0SJoseph Chen hotkey_run(HK_CLI_OS_PRE); 707665be4b0SJoseph Chen } 708665be4b0SJoseph Chen 70938771996SKever Yang void enable_caches(void) 71038771996SKever Yang { 711567735c8SJoseph Chen icache_enable(); 71238771996SKever Yang dcache_enable(); 71338771996SKever Yang } 71438771996SKever Yang 7152dc2d048SJoseph Chen #ifdef CONFIG_LMB 7162c6a058bSJoseph Chen /* 7172c6a058bSJoseph Chen * Using last bi_dram[...] to initialize "bootm_low" and "bootm_mapsize". 7182c6a058bSJoseph Chen * This makes lmb_alloc_base() always alloc from tail of sdram. 7192c6a058bSJoseph Chen * If we don't assign it, bi_dram[0] is used by default and it may cause 7202c6a058bSJoseph Chen * lmb_alloc_base() fail when bi_dram[0] range is small. 7212c6a058bSJoseph Chen */ 7222c6a058bSJoseph Chen void board_lmb_reserve(struct lmb *lmb) 7232c6a058bSJoseph Chen { 7242c6a058bSJoseph Chen char bootm_mapsize[32]; 7252208cd92SJoseph Chen char bootm_low[32]; 7262208cd92SJoseph Chen u64 start, size; 7272c6a058bSJoseph Chen int i; 7282c6a058bSJoseph Chen 7292c6a058bSJoseph Chen for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 7302c6a058bSJoseph Chen if (!gd->bd->bi_dram[i].size) 7312c6a058bSJoseph Chen break; 7322c6a058bSJoseph Chen } 7332c6a058bSJoseph Chen 7342c6a058bSJoseph Chen start = gd->bd->bi_dram[i - 1].start; 7352c6a058bSJoseph Chen size = gd->bd->bi_dram[i - 1].size; 7362c6a058bSJoseph Chen 7372c6a058bSJoseph Chen /* 7382dc2d048SJoseph Chen * 32-bit kernel: ramdisk/fdt shouldn't be loaded to highmem area(768MB+), 7392dc2d048SJoseph Chen * otherwise "Unable to handle kernel paging request at virtual address ...". 7402dc2d048SJoseph Chen * 7412dc2d048SJoseph Chen * So that we hope limit highest address at 768M, but there comes the the 7422dc2d048SJoseph Chen * problem: ramdisk is a compressed image and it expands after descompress, 7432dc2d048SJoseph Chen * so it accesses 768MB+ and brings the above "Unable to handle kernel ...". 7442dc2d048SJoseph Chen * 7452dc2d048SJoseph Chen * We make a appointment that the highest memory address is 512MB, it 7462dc2d048SJoseph Chen * makes lmb alloc safer. 7472c6a058bSJoseph Chen */ 7482dc2d048SJoseph Chen #ifndef CONFIG_ARM64 7492dc2d048SJoseph Chen if (start >= ((u64)CONFIG_SYS_SDRAM_BASE + SZ_512M)) { 7502c6a058bSJoseph Chen start = gd->bd->bi_dram[i - 2].start; 7512c6a058bSJoseph Chen size = gd->bd->bi_dram[i - 2].size; 7522c6a058bSJoseph Chen } 7532c6a058bSJoseph Chen 7542dc2d048SJoseph Chen if ((start + size) > ((u64)CONFIG_SYS_SDRAM_BASE + SZ_512M)) 7552dc2d048SJoseph Chen size = (u64)CONFIG_SYS_SDRAM_BASE + SZ_512M - start; 7562c6a058bSJoseph Chen #endif 7572c6a058bSJoseph Chen sprintf(bootm_low, "0x%llx", start); 7582c6a058bSJoseph Chen sprintf(bootm_mapsize, "0x%llx", size); 7592c6a058bSJoseph Chen env_set("bootm_low", bootm_low); 7602c6a058bSJoseph Chen env_set("bootm_mapsize", bootm_mapsize); 7612c6a058bSJoseph Chen } 7622dc2d048SJoseph Chen #endif 7632c6a058bSJoseph Chen 76486f870d6SJoseph Chen #ifdef CONFIG_BIDRAM 76586f870d6SJoseph Chen int board_bidram_reserve(struct bidram *bidram) 76686f870d6SJoseph Chen { 76786f870d6SJoseph Chen struct memblock mem; 76886f870d6SJoseph Chen int ret; 76986f870d6SJoseph Chen 77086f870d6SJoseph Chen /* ATF */ 77186f870d6SJoseph Chen mem = param_parse_atf_mem(); 772c01d4489SJoseph Chen ret = bidram_reserve(MEM_ATF, mem.base, mem.size); 77386f870d6SJoseph Chen if (ret) 77486f870d6SJoseph Chen return ret; 77586f870d6SJoseph Chen 77686f870d6SJoseph Chen /* PSTORE/ATAGS/SHM */ 77786f870d6SJoseph Chen mem = param_parse_common_resv_mem(); 778c01d4489SJoseph Chen ret = bidram_reserve(MEM_SHM, mem.base, mem.size); 77986f870d6SJoseph Chen if (ret) 78086f870d6SJoseph Chen return ret; 78186f870d6SJoseph Chen 78286f870d6SJoseph Chen /* OP-TEE */ 78386f870d6SJoseph Chen mem = param_parse_optee_mem(); 784c01d4489SJoseph Chen ret = bidram_reserve(MEM_OPTEE, mem.base, mem.size); 78586f870d6SJoseph Chen if (ret) 78686f870d6SJoseph Chen return ret; 78786f870d6SJoseph Chen 78886f870d6SJoseph Chen return 0; 78986f870d6SJoseph Chen } 79086f870d6SJoseph Chen 7915b879fbfSJoseph Chen #ifdef CONFIG_SYSMEM 792b3a6659cSJoseph Chen int board_sysmem_reserve(struct sysmem *sysmem) 793b3a6659cSJoseph Chen { 794b3a6659cSJoseph Chen #ifdef CONFIG_SKIP_RELOCATE_UBOOT 795b3a6659cSJoseph Chen if (!sysmem_alloc_base_by_name("NO-RELOC-CODE", 796b3a6659cSJoseph Chen CONFIG_SYS_TEXT_BASE, SZ_2M)) { 797b3a6659cSJoseph Chen printf("Failed to reserve sysmem for U-Boot code\n"); 798b3a6659cSJoseph Chen return -ENOMEM; 799b3a6659cSJoseph Chen } 800b3a6659cSJoseph Chen #endif 801b3a6659cSJoseph Chen return 0; 802b3a6659cSJoseph Chen } 8035b879fbfSJoseph Chen #endif 804b3a6659cSJoseph Chen 80586f870d6SJoseph Chen parse_fn_t board_bidram_parse_fn(void) 80686f870d6SJoseph Chen { 80786f870d6SJoseph Chen return param_parse_ddr_mem; 80886f870d6SJoseph Chen } 80986f870d6SJoseph Chen #endif 81086f870d6SJoseph Chen 81193586e70SJoseph Chen int board_init_f_boot_flags(void) 81293586e70SJoseph Chen { 81393586e70SJoseph Chen int boot_flags = 0; 81493586e70SJoseph Chen 815*dfe45d3eSJoseph Chen #if CONFIG_IS_ENABLED(FPGA_ROCKCHIP) 81683f9654dSJoseph Chen arch_fpga_init(); 8179f68846bSJoseph Chen #endif 818ad771a9cSHuibin Hong #ifdef CONFIG_PSTORE 819ad771a9cSHuibin Hong param_parse_pstore(); 820ad771a9cSHuibin Hong #endif 8219d10124aSJoseph Chen param_parse_pre_serial(&boot_flags); 82293586e70SJoseph Chen 82393586e70SJoseph Chen /* The highest priority to turn off (override) console */ 82493586e70SJoseph Chen #if defined(CONFIG_DISABLE_CONSOLE) 82593586e70SJoseph Chen boot_flags |= GD_FLG_DISABLE_CONSOLE; 82693586e70SJoseph Chen #endif 82793586e70SJoseph Chen 82893586e70SJoseph Chen return boot_flags; 82993586e70SJoseph Chen } 830064eb493SJoseph Chen 831ef57bc49SFrank Wang #if defined(CONFIG_USB_GADGET) 83238771996SKever Yang #include <usb.h> 833ef57bc49SFrank Wang #if defined(CONFIG_USB_GADGET_DWC2_OTG) 834ef57bc49SFrank Wang #include <fdt_support.h> 83538771996SKever Yang #include <usb/dwc2_udc.h> 83638771996SKever Yang 83738771996SKever Yang static struct dwc2_plat_otg_data otg_data = { 83838771996SKever Yang .rx_fifo_sz = 512, 83938771996SKever Yang .np_tx_fifo_sz = 16, 84038771996SKever Yang .tx_fifo_sz = 128, 84138771996SKever Yang }; 84238771996SKever Yang 84338771996SKever Yang int board_usb_init(int index, enum usb_init_type init) 84438771996SKever Yang { 84538771996SKever Yang const void *blob = gd->fdt_blob; 8462208cd92SJoseph Chen const fdt32_t *reg; 8472208cd92SJoseph Chen fdt_addr_t addr; 8482208cd92SJoseph Chen int node; 84938771996SKever Yang 85038771996SKever Yang /* find the usb_otg node */ 851294ad617SWilliam Wu node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc2"); 85238771996SKever Yang 853294ad617SWilliam Wu retry: 854294ad617SWilliam Wu if (node > 0) { 855294ad617SWilliam Wu reg = fdt_getprop(blob, node, "reg", NULL); 856294ad617SWilliam Wu if (!reg) 857294ad617SWilliam Wu return -EINVAL; 858294ad617SWilliam Wu 859294ad617SWilliam Wu addr = fdt_translate_address(blob, node, reg); 860294ad617SWilliam Wu if (addr == OF_BAD_ADDR) { 861294ad617SWilliam Wu pr_err("Not found usb_otg address\n"); 862294ad617SWilliam Wu return -EINVAL; 86338771996SKever Yang } 86438771996SKever Yang 865294ad617SWilliam Wu #if defined(CONFIG_ROCKCHIP_RK3288) 866294ad617SWilliam Wu if (addr != 0xff580000) { 86738771996SKever Yang node = fdt_node_offset_by_compatible(blob, node, 86838771996SKever Yang "snps,dwc2"); 869294ad617SWilliam Wu goto retry; 87038771996SKever Yang } 871294ad617SWilliam Wu #endif 872294ad617SWilliam Wu } else { 873e7b5bb3cSWilliam Wu /* 874e7b5bb3cSWilliam Wu * With kernel dtb support, rk3288 dwc2 otg node 875e7b5bb3cSWilliam Wu * use the rockchip legacy dwc2 driver "dwc_otg_310" 876e0b87408SJoseph Chen * with the compatible "rockchip,rk3288_usb20_otg", 877e0b87408SJoseph Chen * and rk3368 also use the "dwc_otg_310" driver with 878e0b87408SJoseph Chen * the compatible "rockchip,rk3368-usb". 879e7b5bb3cSWilliam Wu */ 880e0b87408SJoseph Chen #if defined(CONFIG_ROCKCHIP_RK3288) 881e7b5bb3cSWilliam Wu node = fdt_node_offset_by_compatible(blob, -1, 882e7b5bb3cSWilliam Wu "rockchip,rk3288_usb20_otg"); 883e0b87408SJoseph Chen #elif defined(CONFIG_ROCKCHIP_RK3368) 884e0b87408SJoseph Chen node = fdt_node_offset_by_compatible(blob, -1, 885e0b87408SJoseph Chen "rockchip,rk3368-usb"); 886e0b87408SJoseph Chen #endif 887e7b5bb3cSWilliam Wu if (node > 0) { 888294ad617SWilliam Wu goto retry; 889e7b5bb3cSWilliam Wu } else { 890e7b5bb3cSWilliam Wu pr_err("Not found usb_otg device\n"); 89138771996SKever Yang return -ENODEV; 89238771996SKever Yang } 893e7b5bb3cSWilliam Wu } 8946f7b6465SFrank Wang 8956f7b6465SFrank Wang otg_data.regs_otg = (uintptr_t)addr; 89638771996SKever Yang 89738771996SKever Yang return dwc2_udc_probe(&otg_data); 89838771996SKever Yang } 89938771996SKever Yang 90038771996SKever Yang int board_usb_cleanup(int index, enum usb_init_type init) 90138771996SKever Yang { 90238771996SKever Yang return 0; 90338771996SKever Yang } 904ef57bc49SFrank Wang #elif defined(CONFIG_USB_DWC3_GADGET) /* CONFIG_USB_GADGET_DWC2_OTG */ 905ef57bc49SFrank Wang #include <dwc3-uboot.h> 906ef57bc49SFrank Wang 907ef57bc49SFrank Wang int board_usb_cleanup(int index, enum usb_init_type init) 908ef57bc49SFrank Wang { 909ef57bc49SFrank Wang dwc3_uboot_exit(index); 910ef57bc49SFrank Wang return 0; 911ef57bc49SFrank Wang } 912ef57bc49SFrank Wang 913ef57bc49SFrank Wang #endif /* CONFIG_USB_DWC3_GADGET */ 914ef57bc49SFrank Wang #endif /* CONFIG_USB_GADGET */ 91585cad72dSJoseph Chen 91685cad72dSJoseph Chen static void bootm_no_reloc(void) 91785cad72dSJoseph Chen { 91885cad72dSJoseph Chen char *ramdisk_high; 91985cad72dSJoseph Chen char *fdt_high; 92085cad72dSJoseph Chen 92185cad72dSJoseph Chen if (!env_get_yesno("bootm-no-reloc")) 92285cad72dSJoseph Chen return; 92385cad72dSJoseph Chen 92485cad72dSJoseph Chen ramdisk_high = env_get("initrd_high"); 92585cad72dSJoseph Chen fdt_high = env_get("fdt_high"); 92685cad72dSJoseph Chen 92785cad72dSJoseph Chen if (!fdt_high) { 92885cad72dSJoseph Chen env_set_hex("fdt_high", -1UL); 92985cad72dSJoseph Chen printf("Fdt "); 93085cad72dSJoseph Chen } 93185cad72dSJoseph Chen 93285cad72dSJoseph Chen if (!ramdisk_high) { 93385cad72dSJoseph Chen env_set_hex("initrd_high", -1UL); 93485cad72dSJoseph Chen printf("Ramdisk "); 93585cad72dSJoseph Chen } 93685cad72dSJoseph Chen 93785cad72dSJoseph Chen if (!fdt_high || !ramdisk_high) 93885cad72dSJoseph Chen printf("skip relocation\n"); 93985cad72dSJoseph Chen } 94085cad72dSJoseph Chen 94185cad72dSJoseph Chen int bootm_board_start(void) 94285cad72dSJoseph Chen { 94385cad72dSJoseph Chen /* 94485cad72dSJoseph Chen * print console record data 94585cad72dSJoseph Chen * 94685cad72dSJoseph Chen * On some rockchip platforms, uart debug and sdmmc pin are multiplex. 94785cad72dSJoseph Chen * If boot from sdmmc mode, the console data would be record in buffer, 94885cad72dSJoseph Chen * we switch to uart debug function in order to print it after loading 94985cad72dSJoseph Chen * images. 95085cad72dSJoseph Chen */ 95171a3b718SJoseph Chen #if 0 95285cad72dSJoseph Chen if (!strcmp("mmc", env_get("devtype")) && 95385cad72dSJoseph Chen !strcmp("1", env_get("devnum"))) { 95485cad72dSJoseph Chen printf("IOMUX: sdmmc => uart debug"); 95585cad72dSJoseph Chen pinctrl_select_state(gd->cur_serial_dev, "default"); 95685cad72dSJoseph Chen console_record_print_purge(); 95785cad72dSJoseph Chen } 95885cad72dSJoseph Chen #endif 95985cad72dSJoseph Chen /* disable bootm relcation to save boot time */ 96085cad72dSJoseph Chen bootm_no_reloc(); 96185cad72dSJoseph Chen 962a18cd24eSJoseph Chen /* PCBA test needs more permission */ 963a18cd24eSJoseph Chen if (get_bcb_recovery_msg() == BCB_MSG_RECOVERY_PCBA) 964a18cd24eSJoseph Chen env_update("bootargs", "androidboot.selinux=permissive"); 965a18cd24eSJoseph Chen 96685cad72dSJoseph Chen /* sysmem */ 96785cad72dSJoseph Chen hotkey_run(HK_SYSMEM); 96885cad72dSJoseph Chen sysmem_overflow_check(); 96985cad72dSJoseph Chen 97085cad72dSJoseph Chen return 0; 97185cad72dSJoseph Chen } 972ac5d8aa9SJoseph Chen 9737bcb4b0dSJoseph Chen int bootm_image_populate_dtb(void *img) 9747bcb4b0dSJoseph Chen { 9757bcb4b0dSJoseph Chen if ((gd->flags & GD_FLG_KDTB_READY) && !gd->fdt_blob_kern) 9767bcb4b0dSJoseph Chen sysmem_free((phys_addr_t)gd->fdt_blob); 9777bcb4b0dSJoseph Chen else 9787bcb4b0dSJoseph Chen gd->fdt_blob = (void *)env_get_ulong("fdt_addr_r", 16, 0); 9797bcb4b0dSJoseph Chen 98025a706d2SJoseph Chen return rockchip_ram_read_dtb_file(img, (void *)gd->fdt_blob); 9817bcb4b0dSJoseph Chen } 9827bcb4b0dSJoseph Chen 983ac5d8aa9SJoseph Chen /* 984ac5d8aa9SJoseph Chen * Implement it to support CLI command: 985ac5d8aa9SJoseph Chen * - Android: bootm [aosp addr] 986ac5d8aa9SJoseph Chen * - FIT: bootm [fit addr] 987ac5d8aa9SJoseph Chen * - uImage: bootm [uimage addr] 988ac5d8aa9SJoseph Chen * 989ac5d8aa9SJoseph Chen * Purpose: 990ac5d8aa9SJoseph Chen * - The original bootm command args require fdt addr on AOSP, 991ac5d8aa9SJoseph Chen * which is not flexible on rockchip boot/recovery.img. 992ac5d8aa9SJoseph Chen * - Take Android/FIT/uImage image into sysmem management to avoid image 993ac5d8aa9SJoseph Chen * memory overlap. 994ac5d8aa9SJoseph Chen */ 995ac5d8aa9SJoseph Chen #if defined(CONFIG_ANDROID_BOOTLOADER) || \ 996ac5d8aa9SJoseph Chen defined(CONFIG_ROCKCHIP_FIT_IMAGE) || \ 997ac5d8aa9SJoseph Chen defined(CONFIG_ROCKCHIP_UIMAGE) 998ac5d8aa9SJoseph Chen int board_do_bootm(int argc, char * const argv[]) 999ac5d8aa9SJoseph Chen { 1000ac5d8aa9SJoseph Chen int format; 1001ac5d8aa9SJoseph Chen void *img; 1002ac5d8aa9SJoseph Chen 1003c3515b67SJoseph Chen /* only 'bootm' full image goes further */ 1004ac5d8aa9SJoseph Chen if (argc != 2) 1005ac5d8aa9SJoseph Chen return 0; 1006ac5d8aa9SJoseph Chen 1007ac5d8aa9SJoseph Chen img = (void *)simple_strtoul(argv[1], NULL, 16); 1008ac5d8aa9SJoseph Chen format = (genimg_get_format(img)); 1009ac5d8aa9SJoseph Chen 1010ac5d8aa9SJoseph Chen /* Android */ 1011ac5d8aa9SJoseph Chen #ifdef CONFIG_ANDROID_BOOT_IMAGE 1012ac5d8aa9SJoseph Chen if (format == IMAGE_FORMAT_ANDROID) { 1013ac5d8aa9SJoseph Chen struct andr_img_hdr *hdr; 1014ac5d8aa9SJoseph Chen ulong load_addr; 1015ac5d8aa9SJoseph Chen ulong size; 1016ac5d8aa9SJoseph Chen int ret; 1017ac5d8aa9SJoseph Chen 1018ac5d8aa9SJoseph Chen hdr = (struct andr_img_hdr *)img; 1019ac5d8aa9SJoseph Chen printf("BOOTM: transferring to board Android\n"); 1020ac5d8aa9SJoseph Chen 1021ac5d8aa9SJoseph Chen load_addr = env_get_ulong("kernel_addr_r", 16, 0); 1022ac5d8aa9SJoseph Chen load_addr -= hdr->page_size; 1023ac5d8aa9SJoseph Chen size = android_image_get_end(hdr) - (ulong)hdr; 1024ac5d8aa9SJoseph Chen 1025ac5d8aa9SJoseph Chen if (!sysmem_alloc_base(MEM_ANDROID, (ulong)hdr, size)) 1026ac5d8aa9SJoseph Chen return -ENOMEM; 1027324bc518SJoseph Chen 10287bcb4b0dSJoseph Chen ret = bootm_image_populate_dtb(img); 10297bcb4b0dSJoseph Chen if (ret) { 103025a706d2SJoseph Chen printf("bootm can't read dtb, ret=%d\n", ret); 10317bcb4b0dSJoseph Chen return ret; 10327bcb4b0dSJoseph Chen } 1033324bc518SJoseph Chen 1034ac5d8aa9SJoseph Chen ret = android_image_memcpy_separate(hdr, &load_addr); 1035ac5d8aa9SJoseph Chen if (ret) { 1036ac5d8aa9SJoseph Chen printf("board do bootm failed, ret=%d\n", ret); 1037ac5d8aa9SJoseph Chen return ret; 1038ac5d8aa9SJoseph Chen } 1039ac5d8aa9SJoseph Chen 1040ac5d8aa9SJoseph Chen return android_bootloader_boot_kernel(load_addr); 1041ac5d8aa9SJoseph Chen } 1042ac5d8aa9SJoseph Chen #endif 1043ac5d8aa9SJoseph Chen 1044ac5d8aa9SJoseph Chen /* FIT */ 1045ac5d8aa9SJoseph Chen #if IMAGE_ENABLE_FIT 1046ac5d8aa9SJoseph Chen if (format == IMAGE_FORMAT_FIT) { 1047ac5d8aa9SJoseph Chen char boot_cmd[64]; 10487bcb4b0dSJoseph Chen int ret; 1049ac5d8aa9SJoseph Chen 1050ac5d8aa9SJoseph Chen printf("BOOTM: transferring to board FIT\n"); 10517bcb4b0dSJoseph Chen 10527bcb4b0dSJoseph Chen ret = bootm_image_populate_dtb(img); 10537bcb4b0dSJoseph Chen if (ret) { 105425a706d2SJoseph Chen printf("bootm can't read dtb, ret=%d\n", ret); 10557bcb4b0dSJoseph Chen return ret; 10567bcb4b0dSJoseph Chen } 1057ac5d8aa9SJoseph Chen snprintf(boot_cmd, sizeof(boot_cmd), "boot_fit %s", argv[1]); 1058ac5d8aa9SJoseph Chen return run_command(boot_cmd, 0); 1059ac5d8aa9SJoseph Chen } 1060ac5d8aa9SJoseph Chen #endif 1061ac5d8aa9SJoseph Chen 1062ac5d8aa9SJoseph Chen /* uImage */ 10637bcb4b0dSJoseph Chen #if 0 1064ac5d8aa9SJoseph Chen #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 1065ac5d8aa9SJoseph Chen if (format == IMAGE_FORMAT_LEGACY && 1066ac5d8aa9SJoseph Chen image_get_type(img) == IH_TYPE_MULTI) { 1067ac5d8aa9SJoseph Chen char boot_cmd[64]; 1068ac5d8aa9SJoseph Chen 1069ac5d8aa9SJoseph Chen printf("BOOTM: transferring to board uImage\n"); 1070ac5d8aa9SJoseph Chen snprintf(boot_cmd, sizeof(boot_cmd), "boot_uimage %s", argv[1]); 1071ac5d8aa9SJoseph Chen return run_command(boot_cmd, 0); 1072ac5d8aa9SJoseph Chen } 1073ac5d8aa9SJoseph Chen #endif 10747bcb4b0dSJoseph Chen #endif 1075ac5d8aa9SJoseph Chen return 0; 1076ac5d8aa9SJoseph Chen } 1077ac5d8aa9SJoseph Chen #endif 10784ab50248SJoseph Chen 10794ab50248SJoseph Chen void autoboot_command_fail_handle(void) 10804ab50248SJoseph Chen { 10814ab50248SJoseph Chen #ifdef CONFIG_ANDROID_AB 1082c9c15fdcSJason Zhu if (rk_avb_ab_have_bootable_slot() == true) 1083c9c15fdcSJason Zhu run_command("reset;", 0); 1084c9c15fdcSJason Zhu else 1085c9c15fdcSJason Zhu run_command("fastboot usb 0;", 0); 1086c9c15fdcSJason Zhu #endif 1087c9c15fdcSJason Zhu 1088c9c15fdcSJason Zhu #ifdef CONFIG_AVB_VBMETA_PUBLIC_KEY_VALIDATE 108950fd2129SJoseph Chen run_command("download", 0); 10904ab50248SJoseph Chen run_command("fastboot usb 0;", 0); 10914ab50248SJoseph Chen #endif 1092c9c15fdcSJason Zhu 10934ab50248SJoseph Chen } 1094346c39b3SJoseph Chen 1095c29dd8c4SJoseph Chen #ifdef CONFIG_FIT_ROLLBACK_PROTECT 1096c29dd8c4SJoseph Chen 1097c29dd8c4SJoseph Chen #define FIT_ROLLBACK_INDEX_LOCATION 0x66697472 /* "fitr" */ 1098c29dd8c4SJoseph Chen 1099c29dd8c4SJoseph Chen int fit_read_otp_rollback_index(uint32_t fit_index, uint32_t *otp_index) 1100c29dd8c4SJoseph Chen { 1101c29dd8c4SJoseph Chen #ifdef CONFIG_OPTEE_CLIENT 1102c29dd8c4SJoseph Chen u64 index; 1103c29dd8c4SJoseph Chen int ret; 1104c29dd8c4SJoseph Chen 1105c29dd8c4SJoseph Chen ret = trusty_read_rollback_index(FIT_ROLLBACK_INDEX_LOCATION, &index); 1106c29dd8c4SJoseph Chen if (ret) { 1107c29dd8c4SJoseph Chen if (ret != TEE_ERROR_ITEM_NOT_FOUND) 1108c29dd8c4SJoseph Chen return ret; 1109c29dd8c4SJoseph Chen 1110ee7b0fb8SJason Zhu index = 0; 1111c29dd8c4SJoseph Chen printf("Initial otp index as %d\n", fit_index); 1112bcec4579SZain Wang } 1113ee7b0fb8SJason Zhu 1114ee7b0fb8SJason Zhu *otp_index = (uint32_t)index; 1115c29dd8c4SJoseph Chen #else 1116c29dd8c4SJoseph Chen *otp_index = 0; 1117c29dd8c4SJoseph Chen #endif 1118c29dd8c4SJoseph Chen 1119c29dd8c4SJoseph Chen return 0; 1120c29dd8c4SJoseph Chen } 1121c29dd8c4SJoseph Chen 1122e9f9d90dSJoseph Chen int fit_write_trusty_rollback_index(u32 trusty_index) 1123c29dd8c4SJoseph Chen { 1124c29dd8c4SJoseph Chen if (!trusty_index) 1125c29dd8c4SJoseph Chen return 0; 1126b4a3d48eSJoseph Chen #ifdef CONFIG_OPTEE_CLIENT 11278d26d4b3SJoseph Chen return trusty_write_rollback_index(FIT_ROLLBACK_INDEX_LOCATION, 1128c29dd8c4SJoseph Chen (u64)trusty_index); 1129b4a3d48eSJoseph Chen #else 1130b4a3d48eSJoseph Chen return 0; 1131b4a3d48eSJoseph Chen #endif 1132c29dd8c4SJoseph Chen } 1133c29dd8c4SJoseph Chen #endif 1134c29dd8c4SJoseph Chen 1135189c0d68SJoseph Chen void board_quiesce_devices(void *images) 1136189c0d68SJoseph Chen { 1137189c0d68SJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 1138189c0d68SJoseph Chen /* Destroy atags makes next warm boot safer */ 1139189c0d68SJoseph Chen atags_destroy(); 1140189c0d68SJoseph Chen #endif 1141189c0d68SJoseph Chen #ifdef CONFIG_FIT_ROLLBACK_PROTECT 11428d26d4b3SJoseph Chen int ret; 11438d26d4b3SJoseph Chen 11448d26d4b3SJoseph Chen ret = fit_write_trusty_rollback_index(gd->rollback_index); 11458d26d4b3SJoseph Chen if (ret) { 11468d26d4b3SJoseph Chen panic("Failed to write fit rollback index %d, ret=%d", 11478d26d4b3SJoseph Chen gd->rollback_index, ret); 11488d26d4b3SJoseph Chen } 1149189c0d68SJoseph Chen #endif 1150a5401a9dSJoseph Chen #ifdef CONFIG_ROCKCHIP_HW_DECOMPRESS 1151a5401a9dSJoseph Chen misc_decompress_cleanup(); 1152a5401a9dSJoseph Chen #endif 1153c3515b67SJoseph Chen #ifdef CONFIG_ARM64 1154c3515b67SJoseph Chen bootm_headers_t *bootm_images = (bootm_headers_t *)images; 1155c3515b67SJoseph Chen 1156b627269dSJoseph Chen /* relocate kernel after decompress cleanup */ 11574f7cc6a5SJoseph Chen if (orig_images_ep && orig_images_ep != bootm_images->ep) { 11584f7cc6a5SJoseph Chen memmove((char *)bootm_images->ep, (const char *)orig_images_ep, 1159b627269dSJoseph Chen bootm_images->os.image_len); 1160b627269dSJoseph Chen printf("== DO RELOCATE == Kernel from 0x%08lx to 0x%08lx\n", 11614f7cc6a5SJoseph Chen orig_images_ep, bootm_images->ep); 1162b627269dSJoseph Chen } 1163c3515b67SJoseph Chen #endif 1164b627269dSJoseph Chen 1165b627269dSJoseph Chen hotkey_run(HK_CMDLINE); 1166b627269dSJoseph Chen hotkey_run(HK_CLI_OS_GO); 1167b627269dSJoseph Chen #ifdef CONFIG_ROCKCHIP_REBOOT_TEST 1168b627269dSJoseph Chen do_reset(NULL, 0, 0, NULL); 1169b627269dSJoseph Chen #endif 1170189c0d68SJoseph Chen } 1171d87d5275SJoseph Chen 1172d055d2cdSJoseph Chen /* 1173d055d2cdSJoseph Chen * Use hardware rng to seed Linux random 1174d055d2cdSJoseph Chen * 1175d055d2cdSJoseph Chen * 'Android_14 + GKI' requires this information. 1176d055d2cdSJoseph Chen */ 1177d055d2cdSJoseph Chen int board_rng_seed(struct abuf *buf) 1178d055d2cdSJoseph Chen { 11790ea8a3c7SJoseph Chen #ifdef CONFIG_DM_RNG 1180d055d2cdSJoseph Chen struct udevice *dev; 11810ea8a3c7SJoseph Chen #endif 1182d055d2cdSJoseph Chen size_t len = 32; 11830ea8a3c7SJoseph Chen u8 *data; 11840ea8a3c7SJoseph Chen int i; 1185d055d2cdSJoseph Chen 1186d055d2cdSJoseph Chen data = malloc(len); 1187d055d2cdSJoseph Chen if (!data) { 1188d055d2cdSJoseph Chen printf("Out of memory\n"); 1189d055d2cdSJoseph Chen return -ENOMEM; 1190d055d2cdSJoseph Chen } 1191d055d2cdSJoseph Chen 11920ea8a3c7SJoseph Chen #ifdef CONFIG_DM_RNG 11930ea8a3c7SJoseph Chen if (uclass_get_device(UCLASS_RNG, 0, &dev) || dm_rng_read(dev, data, len)) 11940ea8a3c7SJoseph Chen #endif 11950ea8a3c7SJoseph Chen { 11960ea8a3c7SJoseph Chen printf("board seed: Pseudo\n"); 11970ea8a3c7SJoseph Chen for (i = 0; i < len; i++) 11980ea8a3c7SJoseph Chen data[i] = (u8)rand(); 1199d055d2cdSJoseph Chen } 1200d055d2cdSJoseph Chen 1201d055d2cdSJoseph Chen abuf_init_set(buf, data, len); 1202d055d2cdSJoseph Chen 1203d055d2cdSJoseph Chen return 0; 1204d055d2cdSJoseph Chen } 1205d055d2cdSJoseph Chen 1206de77dbbbSJoseph Chen /* 1207de77dbbbSJoseph Chen * Pass fwver when any available. 1208de77dbbbSJoseph Chen */ 1209de77dbbbSJoseph Chen static void bootargs_add_fwver(bool verbose) 1210de77dbbbSJoseph Chen { 1211de77dbbbSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 1212de77dbbbSJoseph Chen struct tag *t; 1213de77dbbbSJoseph Chen char *list1 = NULL; 1214de77dbbbSJoseph Chen char *list2 = NULL; 1215de77dbbbSJoseph Chen char *fwver = NULL; 1216de77dbbbSJoseph Chen char *p = PLAIN_VERSION; 1217de77dbbbSJoseph Chen int i, end; 1218de77dbbbSJoseph Chen 1219de77dbbbSJoseph Chen t = atags_get_tag(ATAG_FWVER); 1220de77dbbbSJoseph Chen if (t) { 1221de77dbbbSJoseph Chen list1 = calloc(1, sizeof(struct tag_fwver)); 1222de77dbbbSJoseph Chen if (!list1) 1223de77dbbbSJoseph Chen return; 1224de77dbbbSJoseph Chen for (i = 0; i < FW_MAX; i++) { 1225de77dbbbSJoseph Chen if (t->u.fwver.ver[i][0] != '\0') { 1226de77dbbbSJoseph Chen strcat(list1, t->u.fwver.ver[i]); 1227de77dbbbSJoseph Chen strcat(list1, ","); 1228de77dbbbSJoseph Chen } 1229de77dbbbSJoseph Chen } 1230de77dbbbSJoseph Chen } 1231de77dbbbSJoseph Chen 1232de77dbbbSJoseph Chen list2 = calloc(1, FWVER_LEN); 1233de77dbbbSJoseph Chen if (!list2) 1234de77dbbbSJoseph Chen goto out; 1235de77dbbbSJoseph Chen strcat(list2, "uboot-"); 1236de77dbbbSJoseph Chen /* optional */ 1237de77dbbbSJoseph Chen #ifdef BUILD_TAG 1238de77dbbbSJoseph Chen strcat(list2, BUILD_TAG); 1239de77dbbbSJoseph Chen strcat(list2, "-"); 1240de77dbbbSJoseph Chen #endif 1241de77dbbbSJoseph Chen /* optional */ 1242de77dbbbSJoseph Chen if (strcmp(PLAIN_VERSION, "2017.09")) { 1243de77dbbbSJoseph Chen strncat(list2, p + strlen("2017.09-g"), 10); 1244de77dbbbSJoseph Chen strcat(list2, "-"); 1245de77dbbbSJoseph Chen } 1246de77dbbbSJoseph Chen strcat(list2, U_BOOT_DMI_DATE); 1247de77dbbbSJoseph Chen 1248de77dbbbSJoseph Chen /* merge ! */ 1249de77dbbbSJoseph Chen if (list1 || list2) { 1250de77dbbbSJoseph Chen fwver = calloc(1, sizeof(struct tag_fwver)); 1251de77dbbbSJoseph Chen if (!fwver) 1252de77dbbbSJoseph Chen goto out; 1253de77dbbbSJoseph Chen 1254de77dbbbSJoseph Chen strcat(fwver, "androidboot.fwver="); 1255de77dbbbSJoseph Chen if (list1) 1256de77dbbbSJoseph Chen strcat(fwver, list1); 1257de77dbbbSJoseph Chen if (list2) { 1258de77dbbbSJoseph Chen strcat(fwver, list2); 1259de77dbbbSJoseph Chen } else { 1260de77dbbbSJoseph Chen end = strlen(fwver) - 1; 1261de77dbbbSJoseph Chen fwver[end] = '\0'; /* omit last ',' */ 1262de77dbbbSJoseph Chen } 1263de77dbbbSJoseph Chen if (verbose) 1264de77dbbbSJoseph Chen printf("## fwver: %s\n\n", fwver); 1265de77dbbbSJoseph Chen env_update("bootargs", fwver); 1266de77dbbbSJoseph Chen env_set("fwver", fwver + strlen("androidboot.")); 1267de77dbbbSJoseph Chen } 1268de77dbbbSJoseph Chen out: 1269de77dbbbSJoseph Chen if (list1) 1270de77dbbbSJoseph Chen free(list1); 1271de77dbbbSJoseph Chen if (list2) 1272de77dbbbSJoseph Chen free(list2); 1273de77dbbbSJoseph Chen if (fwver) 1274de77dbbbSJoseph Chen free(fwver); 1275de77dbbbSJoseph Chen #endif 1276de77dbbbSJoseph Chen } 1277de77dbbbSJoseph Chen 12789cf9d2ddSJoseph Chen static void bootargs_add_android(bool verbose) 1279d87d5275SJoseph Chen { 1280d87d5275SJoseph Chen #ifdef CONFIG_ANDROID_AB 12819cf9d2ddSJoseph Chen ab_update_root_partition(); 12829cf9d2ddSJoseph Chen #endif 12839cf9d2ddSJoseph Chen 12849cf9d2ddSJoseph Chen /* Android header v4+ need this handle */ 12859cf9d2ddSJoseph Chen #ifdef CONFIG_ANDROID_BOOT_IMAGE 12869cf9d2ddSJoseph Chen struct andr_img_hdr *hdr; 1287de77dbbbSJoseph Chen char *fwver; 12889cf9d2ddSJoseph Chen 12899cf9d2ddSJoseph Chen hdr = (void *)env_get_ulong("android_addr_r", 16, 0); 12909cf9d2ddSJoseph Chen if (hdr && !android_image_check_header(hdr) && hdr->header_version >= 4) { 12919cf9d2ddSJoseph Chen if (env_update_extract_subset("bootargs", "andr_bootargs", "androidboot.")) 12929cf9d2ddSJoseph Chen printf("extract androidboot.xxx error\n"); 12939cf9d2ddSJoseph Chen if (verbose) 12949cf9d2ddSJoseph Chen printf("## bootargs(android): %s\n\n", env_get("andr_bootargs")); 1295de77dbbbSJoseph Chen 1296de77dbbbSJoseph Chen /* for kernel cmdline can be read */ 1297de77dbbbSJoseph Chen fwver = env_get("fwver"); 1298de77dbbbSJoseph Chen if (fwver) { 1299de77dbbbSJoseph Chen env_update("bootargs", fwver); 1300de77dbbbSJoseph Chen env_set("fwver", NULL); 1301de77dbbbSJoseph Chen } 13029cf9d2ddSJoseph Chen } 1303d87d5275SJoseph Chen #endif 1304d87d5275SJoseph Chen } 1305d87d5275SJoseph Chen 13069cf9d2ddSJoseph Chen static void bootargs_add_partition(bool verbose) 13079cf9d2ddSJoseph Chen { 1308edafafc4SJoseph Chen #if defined(CONFIG_ENVF) || defined(CONFIG_ENV_PARTITION) 1309edafafc4SJoseph Chen char *part_type[] = { "mtdparts", "blkdevparts" }; 1310edafafc4SJoseph Chen char *part_list; 1311edafafc4SJoseph Chen char *env; 1312edafafc4SJoseph Chen int id = 0; 1313bdb740d4SJoseph Chen 1314edafafc4SJoseph Chen env = env_get(part_type[id]); 1315edafafc4SJoseph Chen if (!env) 1316edafafc4SJoseph Chen env = env_get(part_type[++id]); 1317edafafc4SJoseph Chen if (env) { 1318edafafc4SJoseph Chen if (!strstr(env, part_type[id])) { 1319edafafc4SJoseph Chen part_list = calloc(1, strlen(env) + strlen(part_type[id]) + 2); 1320edafafc4SJoseph Chen if (part_list) { 1321edafafc4SJoseph Chen strcat(part_list, part_type[id]); 1322edafafc4SJoseph Chen strcat(part_list, "="); 1323edafafc4SJoseph Chen strcat(part_list, env); 1324edafafc4SJoseph Chen } 1325edafafc4SJoseph Chen } else { 1326edafafc4SJoseph Chen part_list = env; 1327edafafc4SJoseph Chen } 1328edafafc4SJoseph Chen env_update("bootargs", part_list); 13299cf9d2ddSJoseph Chen if (verbose) 1330edafafc4SJoseph Chen printf("## parts: %s\n\n", part_list); 1331edafafc4SJoseph Chen } 1332edafafc4SJoseph Chen 1333edafafc4SJoseph Chen env = env_get("sys_bootargs"); 1334edafafc4SJoseph Chen if (env) { 1335edafafc4SJoseph Chen env_update("bootargs", env); 13369cf9d2ddSJoseph Chen if (verbose) 1337edafafc4SJoseph Chen printf("## sys_bootargs: %s\n\n", env); 1338bdb740d4SJoseph Chen } 1339bdb740d4SJoseph Chen #endif 1340edafafc4SJoseph Chen 1341d87d5275SJoseph Chen #ifdef CONFIG_MTD_BLK 1342bdb740d4SJoseph Chen if (!env_get("mtdparts")) { 1343d87d5275SJoseph Chen char *mtd_par_info = mtd_part_parse(NULL); 1344d87d5275SJoseph Chen 1345d87d5275SJoseph Chen if (mtd_par_info) { 1346d87d5275SJoseph Chen if (memcmp(env_get("devtype"), "mtd", 3) == 0) 1347d87d5275SJoseph Chen env_update("bootargs", mtd_par_info); 1348d87d5275SJoseph Chen } 1349bdb740d4SJoseph Chen } 1350d87d5275SJoseph Chen #endif 13519cf9d2ddSJoseph Chen } 135280c1210cSzhichao.guo 13539cf9d2ddSJoseph Chen static void bootargs_add_dtb_dtbo(void *fdt, bool verbose) 13549cf9d2ddSJoseph Chen { 13559cf9d2ddSJoseph Chen /* bootargs_ext is used when dtbo is applied. */ 13569cf9d2ddSJoseph Chen const char *arr_bootargs[] = { "bootargs", "bootargs_ext" }; 13579cf9d2ddSJoseph Chen const char *bootargs; 13589cf9d2ddSJoseph Chen char *msg = "kernel"; 13599cf9d2ddSJoseph Chen int i, noffset; 13609cf9d2ddSJoseph Chen 13619cf9d2ddSJoseph Chen /* find or create "/chosen" node. */ 13629cf9d2ddSJoseph Chen noffset = fdt_find_or_add_subnode(fdt, 0, "chosen"); 13639cf9d2ddSJoseph Chen if (noffset < 0) 13649cf9d2ddSJoseph Chen return; 13659cf9d2ddSJoseph Chen 13669cf9d2ddSJoseph Chen for (i = 0; i < ARRAY_SIZE(arr_bootargs); i++) { 13679cf9d2ddSJoseph Chen bootargs = fdt_getprop(fdt, noffset, arr_bootargs[i], NULL); 13689cf9d2ddSJoseph Chen if (!bootargs) 13699cf9d2ddSJoseph Chen continue; 13709cf9d2ddSJoseph Chen if (verbose) 13719cf9d2ddSJoseph Chen printf("## bootargs(%s-%s): %s\n\n", 13729cf9d2ddSJoseph Chen msg, arr_bootargs[i], bootargs); 13739cf9d2ddSJoseph Chen /* 13749cf9d2ddSJoseph Chen * Append kernel bootargs 13759cf9d2ddSJoseph Chen * If use AB system, delete default "root=" which route 13769cf9d2ddSJoseph Chen * to rootfs. Then the ab bootctl will choose the 13779cf9d2ddSJoseph Chen * high priority system to boot and add its UUID 13789cf9d2ddSJoseph Chen * to cmdline. The format is "roo=PARTUUID=xxxx...". 13799cf9d2ddSJoseph Chen */ 138080c1210cSzhichao.guo #ifdef CONFIG_ANDROID_AB 13819cf9d2ddSJoseph Chen env_update_filter("bootargs", bootargs, "root="); 13829cf9d2ddSJoseph Chen #else 13839cf9d2ddSJoseph Chen env_update("bootargs", bootargs); 138480c1210cSzhichao.guo #endif 13859cf9d2ddSJoseph Chen } 13869cf9d2ddSJoseph Chen } 13879cf9d2ddSJoseph Chen 13889cf9d2ddSJoseph Chen char *board_fdt_chosen_bootargs(void *fdt) 13899cf9d2ddSJoseph Chen { 13909cf9d2ddSJoseph Chen int verbose = is_hotkey(HK_CMDLINE); 13919cf9d2ddSJoseph Chen const char *bootargs; 13929cf9d2ddSJoseph Chen 13939cf9d2ddSJoseph Chen /* debug */ 13949cf9d2ddSJoseph Chen hotkey_run(HK_INITCALL); 13959cf9d2ddSJoseph Chen if (verbose) 13969cf9d2ddSJoseph Chen printf("## bootargs(u-boot): %s\n\n", env_get("bootargs")); 13979cf9d2ddSJoseph Chen 13989cf9d2ddSJoseph Chen bootargs_add_dtb_dtbo(fdt, verbose); 13999cf9d2ddSJoseph Chen bootargs_add_partition(verbose); 1400de77dbbbSJoseph Chen bootargs_add_fwver(verbose); 1401b74494b8SJoseph Chen bootargs_add_android(verbose); 14029cf9d2ddSJoseph Chen 1403d87d5275SJoseph Chen /* 1404d87d5275SJoseph Chen * Initrd fixup: remove unused "initrd=0x...,0x...", 1405d87d5275SJoseph Chen * this for compatible with legacy parameter.txt 1406d87d5275SJoseph Chen */ 1407d87d5275SJoseph Chen env_delete("bootargs", "initrd=", 0); 1408d87d5275SJoseph Chen 1409d87d5275SJoseph Chen /* 1410d87d5275SJoseph Chen * If uart is required to be disabled during 1411d87d5275SJoseph Chen * power on, it would be not initialized by 1412d87d5275SJoseph Chen * any pre-loader and U-Boot. 1413d87d5275SJoseph Chen * 1414d87d5275SJoseph Chen * If we don't remove earlycon from commandline, 1415d87d5275SJoseph Chen * kernel hangs while using earlycon to putc/getc 1416d87d5275SJoseph Chen * which may dead loop for waiting uart status. 1417d87d5275SJoseph Chen * (It seems the root cause is baundrate is not 1418d87d5275SJoseph Chen * initilalized) 1419d87d5275SJoseph Chen * 1420d87d5275SJoseph Chen * So let's remove earlycon from commandline. 1421d87d5275SJoseph Chen */ 1422d87d5275SJoseph Chen if (gd->flags & GD_FLG_DISABLE_CONSOLE) 1423d87d5275SJoseph Chen env_delete("bootargs", "earlycon=", 0); 1424d87d5275SJoseph Chen 1425d87d5275SJoseph Chen bootargs = env_get("bootargs"); 14269cf9d2ddSJoseph Chen if (verbose) 1427d87d5275SJoseph Chen printf("## bootargs(merged): %s\n\n", bootargs); 1428d87d5275SJoseph Chen 1429d87d5275SJoseph Chen return (char *)bootargs; 1430d87d5275SJoseph Chen } 1431d87d5275SJoseph Chen 14321761a533SJoseph Chen int ft_verify_fdt(void *fdt) 14331761a533SJoseph Chen { 14341761a533SJoseph Chen /* for android header v4+, we load bootparams and fixup initrd */ 14351761a533SJoseph Chen #if defined(CONFIG_ANDROID_BOOT_IMAGE) && defined(CONFIG_XBC) 14361761a533SJoseph Chen struct andr_img_hdr *hdr; 14371761a533SJoseph Chen uint64_t initrd_start, initrd_end; 14381761a533SJoseph Chen char *bootargs, *p; 14391761a533SJoseph Chen int nodeoffset; 14401761a533SJoseph Chen int is_u64, err; 14411761a533SJoseph Chen u32 len; 14421761a533SJoseph Chen 14431761a533SJoseph Chen hdr = (void *)env_get_ulong("android_addr_r", 16, 0); 14441761a533SJoseph Chen if (!hdr || android_image_check_header(hdr) || 14451761a533SJoseph Chen hdr->header_version < 4) 14461761a533SJoseph Chen return 1; 14471761a533SJoseph Chen 14481761a533SJoseph Chen bootargs = env_get("andr_bootargs"); 14491761a533SJoseph Chen if (!bootargs) 14501761a533SJoseph Chen return 1; 14511761a533SJoseph Chen 14521761a533SJoseph Chen /* trans character: space to new line */ 14531761a533SJoseph Chen p = bootargs; 14541761a533SJoseph Chen while (*p++) { 14551761a533SJoseph Chen if (*p == ' ') 14561761a533SJoseph Chen *p = '\n'; 14571761a533SJoseph Chen } 14581761a533SJoseph Chen 14591761a533SJoseph Chen debug("## andr_bootargs: %s\n", bootargs); 14601761a533SJoseph Chen 14611761a533SJoseph Chen /* 14621761a533SJoseph Chen * add boot params right after bootconfig 14631761a533SJoseph Chen * 14641761a533SJoseph Chen * because we can get final full bootargs in board_fdt_chosen_bootargs(), 14651761a533SJoseph Chen * android_image_get_ramdisk() is early than that. 14661761a533SJoseph Chen * 14671761a533SJoseph Chen * we have to add boot params by now. 14681761a533SJoseph Chen */ 14691761a533SJoseph Chen len = addBootConfigParameters((char *)bootargs, strlen(bootargs), 14701761a533SJoseph Chen (u64)hdr->ramdisk_addr + hdr->ramdisk_size + 14711761a533SJoseph Chen hdr->vendor_ramdisk_size, hdr->vendor_bootconfig_size); 14721761a533SJoseph Chen if (len < 0) { 14731761a533SJoseph Chen printf("error: addBootConfigParameters\n"); 14741761a533SJoseph Chen return 0; 14751761a533SJoseph Chen } 14761761a533SJoseph Chen 14771761a533SJoseph Chen nodeoffset = fdt_subnode_offset(fdt, 0, "chosen"); 14781761a533SJoseph Chen if (nodeoffset < 0) { 14791761a533SJoseph Chen printf("error: No /chosen node\n"); 14801761a533SJoseph Chen return 0; 14811761a533SJoseph Chen } 14821761a533SJoseph Chen 14831761a533SJoseph Chen /* fixup initrd with real value */ 14841761a533SJoseph Chen fdt_delprop(fdt, nodeoffset, "linux,initrd-start"); 14851761a533SJoseph Chen fdt_delprop(fdt, nodeoffset, "linux,initrd-end"); 14861761a533SJoseph Chen 14871761a533SJoseph Chen is_u64 = (fdt_address_cells(fdt, 0) == 2); 14881761a533SJoseph Chen initrd_start = hdr->ramdisk_addr; 14891761a533SJoseph Chen initrd_end = initrd_start + hdr->ramdisk_size + 14901761a533SJoseph Chen hdr->vendor_ramdisk_size + 14911761a533SJoseph Chen hdr->vendor_bootconfig_size + len; 14921761a533SJoseph Chen err = fdt_setprop_uxx(fdt, nodeoffset, "linux,initrd-start", 14931761a533SJoseph Chen initrd_start, is_u64); 14941761a533SJoseph Chen if (err < 0) { 14951761a533SJoseph Chen printf("WARNING: could not set linux,initrd-start %s.\n", 14961761a533SJoseph Chen fdt_strerror(err)); 14971761a533SJoseph Chen return 0; 14981761a533SJoseph Chen } 14991761a533SJoseph Chen err = fdt_setprop_uxx(fdt, nodeoffset, "linux,initrd-end", 15001761a533SJoseph Chen initrd_end, is_u64); 15011761a533SJoseph Chen if (err < 0) { 15021761a533SJoseph Chen printf("WARNING: could not set linux,initrd-end %s.\n", 15031761a533SJoseph Chen fdt_strerror(err)); 15041761a533SJoseph Chen return 0; 15051761a533SJoseph Chen } 15061761a533SJoseph Chen #endif 15071761a533SJoseph Chen return 1; 15081761a533SJoseph Chen } 15091761a533SJoseph Chen 1510