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> 90f44aebdSJason Zhu #include <android_ab.h> 10ac5d8aa9SJoseph Chen #include <android_bootloader.h> 11ac5d8aa9SJoseph Chen #include <android_image.h> 1286f870d6SJoseph Chen #include <bidram.h> 130ed06f16SJoseph Chen #include <boot_rkimg.h> 140ed06f16SJoseph Chen #include <cli.h> 152208cd92SJoseph Chen #include <clk.h> 162208cd92SJoseph Chen #include <console.h> 17575777c5SKever Yang #include <debug_uart.h> 182208cd92SJoseph Chen #include <dm.h> 192208cd92SJoseph Chen #include <dvfs.h> 2067bee0b5SXiao Ya peng #include <fdt_support.h> 212208cd92SJoseph Chen #include <io-domain.h> 2203fd0d5bSJoseph Chen #include <image.h> 237397b961SJoseph Chen #include <key.h> 2486f870d6SJoseph Chen #include <memblk.h> 252208cd92SJoseph Chen #include <misc.h> 262208cd92SJoseph Chen #include <of_live.h> 27459f5cb0SJason Zhu #include <mtd_blk.h> 2838771996SKever Yang #include <ram.h> 292208cd92SJoseph Chen #include <rockchip_debugger.h> 3038771996SKever Yang #include <syscon.h> 316929f85bSJoseph Chen #include <sysmem.h> 322208cd92SJoseph Chen #include <video_rockchip.h> 331761a533SJoseph Chen #include <xbc.h> 3438771996SKever Yang #include <asm/io.h> 3538771996SKever Yang #include <asm/gpio.h> 36c9c15fdcSJason Zhu #include <android_avb/rk_avb_ops_user.h> 373e45175eSJoseph Chen #include <dm/uclass-internal.h> 382208cd92SJoseph Chen #include <dm/root.h> 392208cd92SJoseph Chen #include <power/charge_display.h> 402208cd92SJoseph Chen #include <power/regulator.h> 4103fd0d5bSJoseph Chen #include <optee_include/OpteeClientInterface.h> 42396e3049SElon Zhang #include <optee_include/OpteeClientApiLib.h> 43c29dd8c4SJoseph Chen #include <optee_include/tee_api_defines.h> 442208cd92SJoseph Chen #include <asm/arch/boot_mode.h> 4538771996SKever Yang #include <asm/arch/clock.h> 4660ea26bdSJoseph Chen #include <asm/arch/cpu.h> 47c664909eSJoseph Chen #include <asm/arch/hotkey.h> 486929f85bSJoseph Chen #include <asm/arch/param.h> 492208cd92SJoseph Chen #include <asm/arch/periph.h> 502208cd92SJoseph Chen #include <asm/arch/resource_img.h> 512208cd92SJoseph Chen #include <asm/arch/rk_atags.h> 522208cd92SJoseph Chen #include <asm/arch/vendor.h> 53efeef7e5SWenping Zhang #ifdef CONFIG_ROCKCHIP_EINK_DISPLAY 54efeef7e5SWenping Zhang #include <rk_eink.h> 55efeef7e5SWenping Zhang #endif 56d87d5275SJoseph Chen 5738771996SKever Yang DECLARE_GLOBAL_DATA_PTR; 5838771996SKever Yang 594f7cc6a5SJoseph Chen #ifdef CONFIG_ARM64 604f7cc6a5SJoseph Chen static ulong orig_images_ep; 614f7cc6a5SJoseph Chen #endif 624f7cc6a5SJoseph Chen 6338771996SKever Yang __weak int rk_board_late_init(void) 6438771996SKever Yang { 6538771996SKever Yang return 0; 6638771996SKever Yang } 6738771996SKever Yang 6838ce6261SJoseph Chen __weak int rk_board_fdt_fixup(void *blob) 6938ce6261SJoseph Chen { 7038ce6261SJoseph Chen return 0; 7138ce6261SJoseph Chen } 7238ce6261SJoseph Chen 7320a45088SJoseph Chen __weak int rk_board_dm_fdt_fixup(void *blob) 7420a45088SJoseph Chen { 7520a45088SJoseph Chen return 0; 7620a45088SJoseph Chen } 7720a45088SJoseph Chen 78efdbac34SFinley Xiao __weak int soc_clk_dump(void) 79efdbac34SFinley Xiao { 80efdbac34SFinley Xiao return 0; 81efdbac34SFinley Xiao } 82efdbac34SFinley Xiao 83058e5d94SFinley Xiao __weak int set_armclk_rate(void) 84058e5d94SFinley Xiao { 85058e5d94SFinley Xiao return 0; 86058e5d94SFinley Xiao } 87058e5d94SFinley Xiao 882208cd92SJoseph Chen __weak int rk_board_init(void) 892208cd92SJoseph Chen { 902208cd92SJoseph Chen return 0; 912208cd92SJoseph Chen } 922208cd92SJoseph Chen 93c9a034c4SJoseph Chen #ifdef CONFIG_ROCKCHIP_SET_ETHADDR 942208cd92SJoseph Chen /* 952208cd92SJoseph Chen * define serialno max length, the max length is 512 Bytes 962208cd92SJoseph Chen * The remaining bytes are used to ensure that the first 512 bytes 972208cd92SJoseph Chen * are valid when executing 'env_set("serial#", value)'. 982208cd92SJoseph Chen */ 992208cd92SJoseph Chen #define VENDOR_SN_MAX 513 1002208cd92SJoseph Chen #define CPUID_LEN 0x10 1012208cd92SJoseph Chen #define CPUID_OFF 0x07 1022208cd92SJoseph Chen 1032e32f666SDavid Wu #define MAX_ETHERNET 0x2 1042e32f666SDavid Wu 1052208cd92SJoseph Chen static int rockchip_set_ethaddr(void) 1062208cd92SJoseph Chen { 1076d9793cfSJoseph Chen __maybe_unused bool need_write = false; 1086d9793cfSJoseph Chen bool randomed = false; 1092e32f666SDavid Wu char buf[ARP_HLEN_ASCII + 1], mac[16]; 1102e32f666SDavid Wu u8 ethaddr[ARP_HLEN * MAX_ETHERNET] = {0}; 1116d9793cfSJoseph Chen int i, ret = -EINVAL; 1122208cd92SJoseph Chen 1136d9793cfSJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 11400fc4eeeSYifeng Zhao ret = vendor_storage_read(LAN_MAC_ID, ethaddr, sizeof(ethaddr)); 1156d9793cfSJoseph Chen #endif 1162e32f666SDavid Wu for (i = 0; i < MAX_ETHERNET; i++) { 1172e32f666SDavid Wu if (ret <= 0 || !is_valid_ethaddr(ðaddr[i * ARP_HLEN])) { 1182cde40a1SDavid Wu if (!randomed) { 1192e32f666SDavid Wu net_random_ethaddr(ðaddr[i * ARP_HLEN]); 1202cde40a1SDavid Wu randomed = true; 1212cde40a1SDavid Wu } else { 1222cde40a1SDavid Wu if (i > 0) { 1232cde40a1SDavid Wu memcpy(ðaddr[i * ARP_HLEN], 1242cde40a1SDavid Wu ðaddr[(i - 1) * ARP_HLEN], 1252cde40a1SDavid Wu ARP_HLEN); 1262cde40a1SDavid Wu ethaddr[i * ARP_HLEN] |= 0x02; 1272cde40a1SDavid Wu ethaddr[i * ARP_HLEN] += (i << 2); 1282cde40a1SDavid Wu } 1292cde40a1SDavid Wu } 1302cde40a1SDavid Wu 1312e32f666SDavid Wu need_write = true; 1322e32f666SDavid Wu } 1332e32f666SDavid Wu 1342e32f666SDavid Wu if (is_valid_ethaddr(ðaddr[i * ARP_HLEN])) { 135c1c7e89dSJianqun Xu snprintf(buf, ARP_HLEN_ASCII + 1, "%pM", ðaddr[i * ARP_HLEN]); 1362e32f666SDavid Wu if (i == 0) 1372e32f666SDavid Wu memcpy(mac, "ethaddr", sizeof("ethaddr")); 1382e32f666SDavid Wu else 1392e32f666SDavid Wu sprintf(mac, "eth%daddr", i); 1402e32f666SDavid Wu env_set(mac, buf); 1412e32f666SDavid Wu } 1422e32f666SDavid Wu } 1432e32f666SDavid Wu 1446d9793cfSJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 1452e32f666SDavid Wu if (need_write) { 14600fc4eeeSYifeng Zhao ret = vendor_storage_write(LAN_MAC_ID, 1472e32f666SDavid Wu ethaddr, sizeof(ethaddr)); 1482e32f666SDavid Wu if (ret < 0) 1492e32f666SDavid Wu printf("%s: vendor_storage_write failed %d\n", 1502e32f666SDavid Wu __func__, ret); 1512208cd92SJoseph Chen } 1522208cd92SJoseph Chen #endif 1532208cd92SJoseph Chen return 0; 1542208cd92SJoseph Chen } 155c9a034c4SJoseph Chen #endif 1562208cd92SJoseph Chen 157c9a034c4SJoseph Chen #ifdef CONFIG_ROCKCHIP_SET_SN 1582208cd92SJoseph Chen static int rockchip_set_serialno(void) 1592208cd92SJoseph Chen { 1602208cd92SJoseph Chen u8 low[CPUID_LEN / 2], high[CPUID_LEN / 2]; 1612208cd92SJoseph Chen u8 cpuid[CPUID_LEN] = {0}; 1622208cd92SJoseph Chen char serialno_str[VENDOR_SN_MAX]; 1632208cd92SJoseph Chen int ret = 0, i; 1642208cd92SJoseph Chen u64 serialno; 1652208cd92SJoseph Chen 1662208cd92SJoseph Chen /* Read serial number from vendor storage part */ 1672208cd92SJoseph Chen memset(serialno_str, 0, VENDOR_SN_MAX); 1682208cd92SJoseph Chen 1692208cd92SJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 17080b41b17SJon Lin int j; 17180b41b17SJon Lin 17200fc4eeeSYifeng Zhao ret = vendor_storage_read(SN_ID, serialno_str, (VENDOR_SN_MAX-1)); 1732208cd92SJoseph Chen if (ret > 0) { 17480b41b17SJon Lin j = strlen(serialno_str); 17580b41b17SJon Lin for (i = 0; i < j; i++) { 176df197bd2SJason Zhu if ((serialno_str[i] >= 'a' && serialno_str[i] <= 'z') || 177df197bd2SJason Zhu (serialno_str[i] >= 'A' && serialno_str[i] <= 'Z') || 178df197bd2SJason Zhu (serialno_str[i] >= '0' && serialno_str[i] <= '9')) 179d20d7c0cSJason Zhu continue; 180d20d7c0cSJason Zhu else 181df197bd2SJason Zhu break; 182df197bd2SJason Zhu } 183df197bd2SJason Zhu 184fa7e137dSJoseph Chen /* valid character count > 0 */ 185fa7e137dSJoseph Chen if (i > 0) { 186df197bd2SJason Zhu serialno_str[i + 1] = 0x0; 1872208cd92SJoseph Chen env_set("serial#", serialno_str); 188fa7e137dSJoseph Chen } 189fa7e137dSJoseph Chen } 1902208cd92SJoseph Chen #endif 191fa7e137dSJoseph Chen if (!env_get("serial#")) { 192d3cb8b06SSugar Zhang #if defined(CONFIG_ROCKCHIP_EFUSE) || defined(CONFIG_ROCKCHIP_OTP) 1932208cd92SJoseph Chen struct udevice *dev; 1942208cd92SJoseph Chen 1952208cd92SJoseph Chen /* retrieve the device */ 196d3cb8b06SSugar Zhang if (IS_ENABLED(CONFIG_ROCKCHIP_EFUSE)) 1972208cd92SJoseph Chen ret = uclass_get_device_by_driver(UCLASS_MISC, 1982208cd92SJoseph Chen DM_GET_DRIVER(rockchip_efuse), 1992208cd92SJoseph Chen &dev); 200d3cb8b06SSugar Zhang else 201d3cb8b06SSugar Zhang ret = uclass_get_device_by_driver(UCLASS_MISC, 202d3cb8b06SSugar Zhang DM_GET_DRIVER(rockchip_otp), 203d3cb8b06SSugar Zhang &dev); 204d3cb8b06SSugar Zhang 2052208cd92SJoseph Chen if (ret) { 206d3cb8b06SSugar Zhang printf("%s: could not find efuse/otp device\n", __func__); 2072208cd92SJoseph Chen return ret; 2082208cd92SJoseph Chen } 2092208cd92SJoseph Chen 2102208cd92SJoseph Chen /* read the cpu_id range from the efuses */ 2112208cd92SJoseph Chen ret = misc_read(dev, CPUID_OFF, &cpuid, sizeof(cpuid)); 2122208cd92SJoseph Chen if (ret) { 213d3cb8b06SSugar Zhang printf("%s: read cpuid from efuse/otp failed, ret=%d\n", 2142208cd92SJoseph Chen __func__, ret); 2152208cd92SJoseph Chen return ret; 2162208cd92SJoseph Chen } 2172208cd92SJoseph Chen #else 2182208cd92SJoseph Chen /* generate random cpuid */ 2192208cd92SJoseph Chen for (i = 0; i < CPUID_LEN; i++) 2202208cd92SJoseph Chen cpuid[i] = (u8)(rand()); 2212208cd92SJoseph Chen #endif 2222208cd92SJoseph Chen /* Generate the serial number based on CPU ID */ 2232208cd92SJoseph Chen for (i = 0; i < 8; i++) { 2242208cd92SJoseph Chen low[i] = cpuid[1 + (i << 1)]; 2252208cd92SJoseph Chen high[i] = cpuid[i << 1]; 2262208cd92SJoseph Chen } 2272208cd92SJoseph Chen 2282208cd92SJoseph Chen serialno = crc32_no_comp(0, low, 8); 2292208cd92SJoseph Chen serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32; 2302208cd92SJoseph Chen snprintf(serialno_str, sizeof(serialno_str), "%llx", serialno); 2312208cd92SJoseph Chen 2322208cd92SJoseph Chen env_set("serial#", serialno_str); 2332208cd92SJoseph Chen } 2342208cd92SJoseph Chen 2352208cd92SJoseph Chen return ret; 2362208cd92SJoseph Chen } 237c9a034c4SJoseph Chen #endif 238c9a034c4SJoseph Chen 2392208cd92SJoseph Chen #if defined(CONFIG_USB_FUNCTION_FASTBOOT) 2402208cd92SJoseph Chen int fb_set_reboot_flag(void) 2412208cd92SJoseph Chen { 2422208cd92SJoseph Chen printf("Setting reboot to fastboot flag ...\n"); 2432208cd92SJoseph Chen writel(BOOT_FASTBOOT, CONFIG_ROCKCHIP_BOOT_MODE_REG); 2442208cd92SJoseph Chen 2452208cd92SJoseph Chen return 0; 2462208cd92SJoseph Chen } 2472208cd92SJoseph Chen #endif 2482208cd92SJoseph Chen 2490ed06f16SJoseph Chen #ifdef CONFIG_ROCKCHIP_USB_BOOT 2500ed06f16SJoseph Chen static int boot_from_udisk(void) 2510ed06f16SJoseph Chen { 2520ed06f16SJoseph Chen struct blk_desc *desc; 25383be1580SJoseph Chen struct udevice *dev; 25483be1580SJoseph Chen int devnum = -1; 25583be1580SJoseph Chen char buf[32]; 2560ed06f16SJoseph Chen 2570ed06f16SJoseph Chen /* Booting priority: mmc1 > udisk */ 25883be1580SJoseph Chen if (!strcmp(env_get("devtype"), "mmc") && !strcmp(env_get("devnum"), "1")) 2590ed06f16SJoseph Chen return 0; 2600ed06f16SJoseph Chen 2610ed06f16SJoseph Chen if (!run_command("usb start", -1)) { 26283be1580SJoseph Chen for (blk_first_device(IF_TYPE_USB, &dev); 26383be1580SJoseph Chen dev; 26483be1580SJoseph Chen blk_next_device(&dev)) { 26583be1580SJoseph Chen desc = dev_get_uclass_platdata(dev); 26683be1580SJoseph Chen printf("Scanning usb %d ...\n", desc->devnum); 26783be1580SJoseph Chen if (desc->type == DEV_TYPE_UNKNOWN) 26883be1580SJoseph Chen continue; 26983be1580SJoseph Chen 27083be1580SJoseph Chen if (desc->lba > 0L && desc->blksz > 0L) { 27183be1580SJoseph Chen devnum = desc->devnum; 27283be1580SJoseph Chen break; 27383be1580SJoseph Chen } 27483be1580SJoseph Chen } 27583be1580SJoseph Chen if (devnum < 0) { 27683be1580SJoseph Chen printf("No usb mass storage found\n"); 2770ed06f16SJoseph Chen return -ENODEV; 2780ed06f16SJoseph Chen } 2790ed06f16SJoseph Chen 28083be1580SJoseph Chen desc = blk_get_devnum_by_type(IF_TYPE_USB, devnum); 28183be1580SJoseph Chen if (!desc) { 28283be1580SJoseph Chen printf("No usb %d found\n", devnum); 28383be1580SJoseph Chen return -ENODEV; 28483be1580SJoseph Chen } 28583be1580SJoseph Chen 28683be1580SJoseph Chen snprintf(buf, 32, "rkimgtest usb %d", devnum); 28783be1580SJoseph Chen if (!run_command(buf, -1)) { 28883be1580SJoseph Chen snprintf(buf, 32, "%d", devnum); 2890ed06f16SJoseph Chen rockchip_set_bootdev(desc); 2900ed06f16SJoseph Chen env_set("devtype", "usb"); 29183be1580SJoseph Chen env_set("devnum", buf); 29283be1580SJoseph Chen printf("=== Booting from usb %d ===\n", devnum); 2930ed06f16SJoseph Chen } else { 29483be1580SJoseph Chen printf("No available udisk image on usb %d\n", devnum); 2950ed06f16SJoseph Chen return -ENODEV; 2960ed06f16SJoseph Chen } 2970ed06f16SJoseph Chen } 2980ed06f16SJoseph Chen 2990ed06f16SJoseph Chen return 0; 3000ed06f16SJoseph Chen } 3010ed06f16SJoseph Chen #endif 3020ed06f16SJoseph Chen 303c6f0e819SJoseph Chen static void env_fixup(void) 304c6f0e819SJoseph Chen { 305c6f0e819SJoseph Chen struct memblock mem; 306c6f0e819SJoseph Chen ulong u_addr_r; 307c6f0e819SJoseph Chen phys_size_t end; 308c6f0e819SJoseph Chen char *addr_r; 309c6f0e819SJoseph Chen 310c6f0e819SJoseph Chen #ifdef ENV_MEM_LAYOUT_SETTINGS1 311c6f0e819SJoseph Chen const char *env_addr0[] = { 312c6f0e819SJoseph Chen "scriptaddr", "pxefile_addr_r", 313c6f0e819SJoseph Chen "fdt_addr_r", "kernel_addr_r", "ramdisk_addr_r", 314c6f0e819SJoseph Chen }; 315c6f0e819SJoseph Chen const char *env_addr1[] = { 316c6f0e819SJoseph Chen "scriptaddr1", "pxefile_addr1_r", 317c6f0e819SJoseph Chen "fdt_addr1_r", "kernel_addr1_r", "ramdisk_addr1_r", 318c6f0e819SJoseph Chen }; 319c6f0e819SJoseph Chen int i; 320c6f0e819SJoseph Chen 321c6f0e819SJoseph Chen /* 128M is a typical ram size for most platform, so as default here */ 322c6f0e819SJoseph Chen if (gd->ram_size <= SZ_128M) { 323c6f0e819SJoseph Chen /* Replace orignal xxx_addr_r */ 324c6f0e819SJoseph Chen for (i = 0; i < ARRAY_SIZE(env_addr1); i++) { 325c6f0e819SJoseph Chen addr_r = env_get(env_addr1[i]); 326c6f0e819SJoseph Chen if (addr_r) 327c6f0e819SJoseph Chen env_set(env_addr0[i], addr_r); 328c6f0e819SJoseph Chen } 329c6f0e819SJoseph Chen } 330c6f0e819SJoseph Chen #endif 33149e18ddbSJoseph Chen /* No BL32 ? */ 332c6f0e819SJoseph Chen if (!(gd->flags & GD_FLG_BL32_ENABLED)) { 33349e18ddbSJoseph Chen /* 33449e18ddbSJoseph Chen * [1] Move kernel to lower address if possible. 33549e18ddbSJoseph Chen */ 33649e18ddbSJoseph Chen addr_r = env_get("kernel_addr_no_low_bl32_r"); 337c6f0e819SJoseph Chen if (addr_r) 338c6f0e819SJoseph Chen env_set("kernel_addr_r", addr_r); 3394175c722SJoseph Chen 3404175c722SJoseph Chen /* 34149e18ddbSJoseph Chen * [2] Move ramdisk at BL32 position if need. 34249e18ddbSJoseph Chen * 3434175c722SJoseph Chen * 0x0a200000 and 0x08400000 are rockchip traditional address 3444175c722SJoseph Chen * of BL32 and ramdisk: 3454175c722SJoseph Chen * 3464175c722SJoseph Chen * |------------|------------| 3474175c722SJoseph Chen * | BL32 | ramdisk | 3484175c722SJoseph Chen * |------------|------------| 3494175c722SJoseph Chen * 3504175c722SJoseph Chen * Move ramdisk to BL32 address to fix sysmem alloc failed 3514175c722SJoseph Chen * issue on the board with critical memory(ie. 256MB). 3524175c722SJoseph Chen */ 3534175c722SJoseph Chen if (gd->ram_size > SZ_128M && gd->ram_size <= SZ_256M) { 3544175c722SJoseph Chen u_addr_r = env_get_ulong("ramdisk_addr_r", 16, 0); 3554175c722SJoseph Chen if (u_addr_r == 0x0a200000) 3564175c722SJoseph Chen env_set("ramdisk_addr_r", "0x08400000"); 3574175c722SJoseph Chen } 358c6f0e819SJoseph Chen } else { 359c6f0e819SJoseph Chen mem = param_parse_optee_mem(); 36049e18ddbSJoseph Chen 36149e18ddbSJoseph Chen /* 36249e18ddbSJoseph Chen * [1] Move kernel forward if possible. 36349e18ddbSJoseph Chen */ 36449e18ddbSJoseph Chen if (mem.base > SZ_128M) { 36549e18ddbSJoseph Chen addr_r = env_get("kernel_addr_no_low_bl32_r"); 36649e18ddbSJoseph Chen if (addr_r) 36749e18ddbSJoseph Chen env_set("kernel_addr_r", addr_r); 36849e18ddbSJoseph Chen } 36949e18ddbSJoseph Chen 37049e18ddbSJoseph Chen /* 37149e18ddbSJoseph Chen * [2] Move ramdisk backward if optee enlarge. 37249e18ddbSJoseph Chen */ 373c6f0e819SJoseph Chen end = mem.base + mem.size; 374c6f0e819SJoseph Chen u_addr_r = env_get_ulong("ramdisk_addr_r", 16, 0); 375c6f0e819SJoseph Chen if (u_addr_r >= mem.base && u_addr_r < end) 376c6f0e819SJoseph Chen env_set_hex("ramdisk_addr_r", end); 377c6f0e819SJoseph Chen } 378c6f0e819SJoseph Chen } 379c6f0e819SJoseph Chen 38083c9bd4bSJoseph Chen static void cmdline_handle(void) 38183c9bd4bSJoseph Chen { 38260f07e75SJoseph Chen struct blk_desc *dev_desc; 38383be1580SJoseph Chen int if_type; 38483be1580SJoseph Chen int devnum; 38560f07e75SJoseph Chen 386045d3eaaSJoseph Chen param_parse_pubkey_fuse_programmed(); 38783c9bd4bSJoseph Chen 38860f07e75SJoseph Chen dev_desc = rockchip_get_bootdev(); 38960f07e75SJoseph Chen if (!dev_desc) 39060f07e75SJoseph Chen return; 39160f07e75SJoseph Chen 392692d3098SJoseph Chen /* 3933d2521fcSJoseph Chen * 1. From rk356x, the sd/udisk recovery update flag was moved from 394692d3098SJoseph Chen * IDB to Android BCB. 3953d2521fcSJoseph Chen * 3963d2521fcSJoseph Chen * 2. Udisk is init at the late boot_from_udisk(), but 3973d2521fcSJoseph Chen * rockchip_get_boot_mode() actually only read once, 3983d2521fcSJoseph Chen * we need to update boot mode according to udisk BCB. 399692d3098SJoseph Chen */ 40083be1580SJoseph Chen if_type = dev_desc->if_type; 40183be1580SJoseph Chen devnum = dev_desc->devnum; 40283be1580SJoseph Chen if ((if_type == IF_TYPE_MMC && devnum == 1) || (if_type == IF_TYPE_USB)) { 403706ec1d4SJoseph Chen if (get_bcb_recovery_msg() == BCB_MSG_RECOVERY_RK_FWUPDATE) { 40483be1580SJoseph Chen if (if_type == IF_TYPE_MMC && devnum == 1) { 40560f07e75SJoseph Chen env_update("bootargs", "sdfwupdate"); 40683be1580SJoseph Chen } else if (if_type == IF_TYPE_USB) { 40760f07e75SJoseph Chen env_update("bootargs", "usbfwupdate"); 4083d2521fcSJoseph Chen env_set("reboot_mode", "recovery-usb"); 4093d2521fcSJoseph Chen } 4103d2521fcSJoseph Chen } else { 41183be1580SJoseph Chen if (if_type == IF_TYPE_USB) 4123d2521fcSJoseph Chen env_set("reboot_mode", "normal"); 4133d2521fcSJoseph Chen } 41460f07e75SJoseph Chen } 41583c9bd4bSJoseph Chen } 41683c9bd4bSJoseph Chen 417*a03ccd5bSJoseph Chen static void scan_run_cmd(void) 418*a03ccd5bSJoseph Chen { 419*a03ccd5bSJoseph Chen char *config = CONFIG_ROCKCHIP_CMD; 420*a03ccd5bSJoseph Chen char *cmd, *key; 421*a03ccd5bSJoseph Chen 422*a03ccd5bSJoseph Chen key = strchr(config, ' '); 423*a03ccd5bSJoseph Chen if (!key) 424*a03ccd5bSJoseph Chen return; 425*a03ccd5bSJoseph Chen 426*a03ccd5bSJoseph Chen cmd = strdup(config); 427*a03ccd5bSJoseph Chen cmd[key - config] = 0; 428*a03ccd5bSJoseph Chen key++; 429*a03ccd5bSJoseph Chen 430*a03ccd5bSJoseph Chen if (!strcmp(key, "-")) { 431*a03ccd5bSJoseph Chen run_command(cmd, 0); 432*a03ccd5bSJoseph Chen } else { 433*a03ccd5bSJoseph Chen #ifdef CONFIG_DM_KEY 434*a03ccd5bSJoseph Chen ulong map; 435*a03ccd5bSJoseph Chen 436*a03ccd5bSJoseph Chen map = simple_strtoul(key, NULL, 10); 437*a03ccd5bSJoseph Chen if (key_is_pressed(key_read(map))) { 438*a03ccd5bSJoseph Chen printf("## Key<%ld> pressed... run cmd '%s'\n", map, cmd); 439*a03ccd5bSJoseph Chen run_command(cmd, 0); 440*a03ccd5bSJoseph Chen } 441*a03ccd5bSJoseph Chen #endif 442*a03ccd5bSJoseph Chen } 443*a03ccd5bSJoseph Chen } 444*a03ccd5bSJoseph Chen 44538771996SKever Yang int board_late_init(void) 44638771996SKever Yang { 447c9a034c4SJoseph Chen #ifdef CONFIG_ROCKCHIP_SET_ETHADDR 4482549364dSlanshh rockchip_set_ethaddr(); 449c9a034c4SJoseph Chen #endif 450c9a034c4SJoseph Chen #ifdef CONFIG_ROCKCHIP_SET_SN 451fc1a5563SJason Zhu rockchip_set_serialno(); 452c9a034c4SJoseph Chen #endif 453d04ada6cSJoseph Chen setup_download_mode(); 454*a03ccd5bSJoseph Chen scan_run_cmd(); 4550ed06f16SJoseph Chen #ifdef CONFIG_ROCKCHIP_USB_BOOT 4560ed06f16SJoseph Chen boot_from_udisk(); 4570ed06f16SJoseph Chen #endif 45838771996SKever Yang #ifdef CONFIG_DM_CHARGE_DISPLAY 45938771996SKever Yang charge_display(); 46038771996SKever Yang #endif 46138771996SKever Yang #ifdef CONFIG_DRM_ROCKCHIP 46238771996SKever Yang rockchip_show_logo(); 46338771996SKever Yang #endif 464efeef7e5SWenping Zhang #ifdef CONFIG_ROCKCHIP_EINK_DISPLAY 465efeef7e5SWenping Zhang rockchip_eink_show_uboot_logo(); 466efeef7e5SWenping Zhang #endif 46791ed07e5SJoseph Chen #if (CONFIG_ROCKCHIP_BOOT_MODE_REG > 0) 46891ed07e5SJoseph Chen setup_boot_mode(); 46991ed07e5SJoseph Chen #endif 470c6f0e819SJoseph Chen env_fixup(); 471efdbac34SFinley Xiao soc_clk_dump(); 47283c9bd4bSJoseph Chen cmdline_handle(); 47375ac0a02SJoseph Chen #ifdef CONFIG_AMP 47475ac0a02SJoseph Chen amp_cpus_on(); 47575ac0a02SJoseph Chen #endif 47638771996SKever Yang return rk_board_late_init(); 47738771996SKever Yang } 47838771996SKever Yang 479a7940145SJoseph Chen static void early_download(void) 480644804edSJoseph Chen { 4817397b961SJoseph Chen #if defined(CONFIG_PWRKEY_DNL_TRIGGER_NUM) && \ 4827397b961SJoseph Chen (CONFIG_PWRKEY_DNL_TRIGGER_NUM > 0) 4837397b961SJoseph Chen if (pwrkey_download_init()) 4847397b961SJoseph Chen printf("Pwrkey download init failed\n"); 4857397b961SJoseph Chen #endif 4867397b961SJoseph Chen 487644804edSJoseph Chen #if (CONFIG_ROCKCHIP_BOOT_MODE_REG > 0) 488c664909eSJoseph Chen if (is_hotkey(HK_BROM_DNL)) { 489644804edSJoseph Chen printf("Enter bootrom download..."); 490363411a1SJoseph Chen flushc(); 491644804edSJoseph Chen writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG); 492644804edSJoseph Chen do_reset(NULL, 0, 0, NULL); 493644804edSJoseph Chen printf("failed!\n"); 494644804edSJoseph Chen } 495644804edSJoseph Chen #endif 496644804edSJoseph Chen } 497644804edSJoseph Chen 4985d5f363eSJoseph Chen static void board_debug_init(void) 4995d5f363eSJoseph Chen { 50093586e70SJoseph Chen if (!gd->serial.using_pre_serial && 50193586e70SJoseph Chen !(gd->flags & GD_FLG_DISABLE_CONSOLE)) 5027abb254dSJoseph Chen debug_uart_init(); 50346f61401SJoseph Chen 50446f61401SJoseph Chen if (tstc()) { 50546f61401SJoseph Chen gd->console_evt = getc(); 50646f61401SJoseph Chen if (gd->console_evt <= 0x1a) /* 'z' */ 50746f61401SJoseph Chen printf("Hotkey: ctrl+%c\n", gd->console_evt + 'a' - 1); 50846f61401SJoseph Chen } 5099889a0e0SJoseph Chen 5109889a0e0SJoseph Chen if (IS_ENABLED(CONFIG_CONSOLE_DISABLE_CLI)) 51125047d3fSJoseph Chen printf("Cmd interface: disabled\n"); 5125d5f363eSJoseph Chen } 5135d5f363eSJoseph Chen 51438771996SKever Yang int board_init(void) 51538771996SKever Yang { 5165d5f363eSJoseph Chen board_debug_init(); 517f0aa8c5dSJason Zhu #ifdef DEBUG 518f0aa8c5dSJason Zhu soc_clk_dump(); 519f0aa8c5dSJason Zhu #endif 520e8086feaSJoseph Chen #ifdef CONFIG_OPTEE_CLIENT 521e8086feaSJoseph Chen trusty_select_security_level(); 522e8086feaSJoseph Chen #endif 523e8086feaSJoseph Chen #ifdef CONFIG_USING_KERNEL_DTB 524f8aaa2c2SKever Yang init_kernel_dtb(); 525f8aaa2c2SKever Yang #endif 526a7940145SJoseph Chen early_download(); 5277397b961SJoseph Chen 5289f8e13d3SFinley Xiao clks_probe(); 52938771996SKever Yang #ifdef CONFIG_DM_REGULATOR 530e8086feaSJoseph Chen regulators_enable_boot_on(is_hotkey(HK_REGULATOR)); 53138771996SKever Yang #endif 532dae20286SJianqun Xu #ifdef CONFIG_ROCKCHIP_IO_DOMAIN 533dae20286SJianqun Xu io_domain_init(); 534dae20286SJianqun Xu #endif 535058e5d94SFinley Xiao set_armclk_rate(); 5363acf4edfSJoseph Chen #ifdef CONFIG_DM_DVFS 5373acf4edfSJoseph Chen dvfs_init(true); 5383acf4edfSJoseph Chen #endif 5390f44aebdSJason Zhu #ifdef CONFIG_ANDROID_AB 5400f44aebdSJason Zhu if (ab_decrease_tries()) 5410f44aebdSJason Zhu printf("Decrease ab tries count fail!\n"); 5420f44aebdSJason Zhu #endif 5430f44aebdSJason Zhu 54438771996SKever Yang return rk_board_init(); 54538771996SKever Yang } 54638771996SKever Yang 547c563adc7SJoseph Chen int interrupt_debugger_init(void) 548c563adc7SJoseph Chen { 549c563adc7SJoseph Chen #ifdef CONFIG_ROCKCHIP_DEBUGGER 5502208cd92SJoseph Chen return rockchip_debugger_init(); 5512208cd92SJoseph Chen #else 5522208cd92SJoseph Chen return 0; 553c563adc7SJoseph Chen #endif 554c563adc7SJoseph Chen } 555c563adc7SJoseph Chen 556e09b1e4aSJoseph Chen int board_fdt_fixup(void *blob) 557e09b1e4aSJoseph Chen { 55820a45088SJoseph Chen /* 55920a45088SJoseph Chen * Device's platdata points to orignal fdt blob property, 56020a45088SJoseph Chen * access DM device before any fdt fixup. 56120a45088SJoseph Chen */ 56220a45088SJoseph Chen rk_board_dm_fdt_fixup(blob); 56320a45088SJoseph Chen 5642208cd92SJoseph Chen /* Common fixup for DRM */ 565e09b1e4aSJoseph Chen #ifdef CONFIG_DRM_ROCKCHIP 566e09b1e4aSJoseph Chen rockchip_display_fixup(blob); 567e09b1e4aSJoseph Chen #endif 568e09b1e4aSJoseph Chen 56938ce6261SJoseph Chen return rk_board_fdt_fixup(blob); 570e09b1e4aSJoseph Chen } 571e09b1e4aSJoseph Chen 572102dfafcSElon Zhang #if defined(CONFIG_ARM64_BOOT_AARCH32) || !defined(CONFIG_ARM64) 573e3fbd280SJoseph Chen /* 574f1d65189SJoseph Chen * Common for OP-TEE: 575396e3049SElon Zhang * 64-bit & 32-bit mode: share memory dcache is always enabled; 576e3fbd280SJoseph Chen * 577f1d65189SJoseph Chen * Common for U-Boot: 578e3fbd280SJoseph Chen * 64-bit mode: MMU table is static defined in rkxxx.c file, all memory 579e3fbd280SJoseph Chen * regions are mapped. That's good to match OP-TEE MMU policy. 580e3fbd280SJoseph Chen * 581e3fbd280SJoseph Chen * 32-bit mode: MMU table is setup according to gd->bd->bi_dram[..] where 582e3fbd280SJoseph Chen * the OP-TEE region has been reserved, so it can not be 583102dfafcSElon Zhang * mapped(i.e. dcache is disabled). That's *NOT* good to match 584e3fbd280SJoseph Chen * OP-TEE MMU policy. 585e3fbd280SJoseph Chen * 586e3fbd280SJoseph Chen * For the data coherence when communication between U-Boot and OP-TEE, U-Boot 587e3fbd280SJoseph Chen * should follow OP-TEE MMU policy. 588e3fbd280SJoseph Chen * 589396e3049SElon Zhang * So 32-bit mode U-Boot should map OP-TEE share memory as dcache enabled. 590e3fbd280SJoseph Chen */ 591e3fbd280SJoseph Chen int board_initr_caches_fixup(void) 592e3fbd280SJoseph Chen { 593396e3049SElon Zhang #ifdef CONFIG_OPTEE_CLIENT 594e3fbd280SJoseph Chen struct memblock mem; 595e3fbd280SJoseph Chen 596396e3049SElon Zhang mem.base = 0; 597396e3049SElon Zhang mem.size = 0; 598396e3049SElon Zhang 599396e3049SElon Zhang optee_get_shm_config(&mem.base, &mem.size); 600e3fbd280SJoseph Chen if (mem.size) 601e3fbd280SJoseph Chen mmu_set_region_dcache_behaviour(mem.base, mem.size, 602e3fbd280SJoseph Chen DCACHE_WRITEBACK); 603396e3049SElon Zhang #endif 604e3fbd280SJoseph Chen return 0; 605e3fbd280SJoseph Chen } 606e3fbd280SJoseph Chen #endif 607e3fbd280SJoseph Chen 6084353cdc4SJoseph Chen void arch_preboot_os(uint32_t bootm_state, bootm_headers_t *images) 609665be4b0SJoseph Chen { 6104353cdc4SJoseph Chen if (!(bootm_state & BOOTM_STATE_OS_PREP)) 6114353cdc4SJoseph Chen return; 6124353cdc4SJoseph Chen 6134353cdc4SJoseph Chen #ifdef CONFIG_ARM64 6144353cdc4SJoseph Chen u8 *data = (void *)images->ep; 6154353cdc4SJoseph Chen 6164353cdc4SJoseph Chen /* 6174353cdc4SJoseph Chen * Fix kernel 5.10 arm64 boot warning: 6184353cdc4SJoseph Chen * "[Firmware Bug]: Kernel image misaligned at boot, please fix your bootloader!" 6194353cdc4SJoseph Chen * 6204353cdc4SJoseph Chen * kernel: 5.10 commit 120dc60d0bdb ("arm64: get rid of TEXT_OFFSET") 6214353cdc4SJoseph Chen * arm64 kernel version: 622c3515b67SJoseph Chen * data[10] == 0x00 if kernel version >= 5.10: N*2MB align 623c3515b67SJoseph Chen * data[10] == 0x08 if kernel version < 5.10: N*2MB + 0x80000(TEXT_OFFSET) 6244353cdc4SJoseph Chen * 6254353cdc4SJoseph Chen * Why fix here? 6264353cdc4SJoseph Chen * 1. this is the common and final path for any boot command. 6274353cdc4SJoseph Chen * 2. don't influence original boot flow, just fix it exactly before 6284353cdc4SJoseph Chen * jumping kernel. 629b627269dSJoseph Chen * 630b627269dSJoseph Chen * But relocation is in board_quiesce_devices() until all decompress 631b627269dSJoseph Chen * done, mainly for saving boot time. 6324353cdc4SJoseph Chen */ 6334f7cc6a5SJoseph Chen 6344f7cc6a5SJoseph Chen orig_images_ep = images->ep; 6354f7cc6a5SJoseph Chen 6364353cdc4SJoseph Chen if (data[10] == 0x00) { 637b627269dSJoseph Chen if (round_down(images->ep, SZ_2M) != images->ep) 638b627269dSJoseph Chen images->ep = round_down(images->ep, SZ_2M); 639a4625d53SJoseph Chen } else { 640b627269dSJoseph Chen if (IS_ALIGNED(images->ep, SZ_2M)) 641b627269dSJoseph Chen images->ep += 0x80000; 6424353cdc4SJoseph Chen } 6434353cdc4SJoseph Chen #endif 644665be4b0SJoseph Chen hotkey_run(HK_CLI_OS_PRE); 645665be4b0SJoseph Chen } 646665be4b0SJoseph Chen 64738771996SKever Yang void enable_caches(void) 64838771996SKever Yang { 649567735c8SJoseph Chen icache_enable(); 65038771996SKever Yang dcache_enable(); 65138771996SKever Yang } 65238771996SKever Yang 6532dc2d048SJoseph Chen #ifdef CONFIG_LMB 6542c6a058bSJoseph Chen /* 6552c6a058bSJoseph Chen * Using last bi_dram[...] to initialize "bootm_low" and "bootm_mapsize". 6562c6a058bSJoseph Chen * This makes lmb_alloc_base() always alloc from tail of sdram. 6572c6a058bSJoseph Chen * If we don't assign it, bi_dram[0] is used by default and it may cause 6582c6a058bSJoseph Chen * lmb_alloc_base() fail when bi_dram[0] range is small. 6592c6a058bSJoseph Chen */ 6602c6a058bSJoseph Chen void board_lmb_reserve(struct lmb *lmb) 6612c6a058bSJoseph Chen { 6622c6a058bSJoseph Chen char bootm_mapsize[32]; 6632208cd92SJoseph Chen char bootm_low[32]; 6642208cd92SJoseph Chen u64 start, size; 6652c6a058bSJoseph Chen int i; 6662c6a058bSJoseph Chen 6672c6a058bSJoseph Chen for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 6682c6a058bSJoseph Chen if (!gd->bd->bi_dram[i].size) 6692c6a058bSJoseph Chen break; 6702c6a058bSJoseph Chen } 6712c6a058bSJoseph Chen 6722c6a058bSJoseph Chen start = gd->bd->bi_dram[i - 1].start; 6732c6a058bSJoseph Chen size = gd->bd->bi_dram[i - 1].size; 6742c6a058bSJoseph Chen 6752c6a058bSJoseph Chen /* 6762dc2d048SJoseph Chen * 32-bit kernel: ramdisk/fdt shouldn't be loaded to highmem area(768MB+), 6772dc2d048SJoseph Chen * otherwise "Unable to handle kernel paging request at virtual address ...". 6782dc2d048SJoseph Chen * 6792dc2d048SJoseph Chen * So that we hope limit highest address at 768M, but there comes the the 6802dc2d048SJoseph Chen * problem: ramdisk is a compressed image and it expands after descompress, 6812dc2d048SJoseph Chen * so it accesses 768MB+ and brings the above "Unable to handle kernel ...". 6822dc2d048SJoseph Chen * 6832dc2d048SJoseph Chen * We make a appointment that the highest memory address is 512MB, it 6842dc2d048SJoseph Chen * makes lmb alloc safer. 6852c6a058bSJoseph Chen */ 6862dc2d048SJoseph Chen #ifndef CONFIG_ARM64 6872dc2d048SJoseph Chen if (start >= ((u64)CONFIG_SYS_SDRAM_BASE + SZ_512M)) { 6882c6a058bSJoseph Chen start = gd->bd->bi_dram[i - 2].start; 6892c6a058bSJoseph Chen size = gd->bd->bi_dram[i - 2].size; 6902c6a058bSJoseph Chen } 6912c6a058bSJoseph Chen 6922dc2d048SJoseph Chen if ((start + size) > ((u64)CONFIG_SYS_SDRAM_BASE + SZ_512M)) 6932dc2d048SJoseph Chen size = (u64)CONFIG_SYS_SDRAM_BASE + SZ_512M - start; 6942c6a058bSJoseph Chen #endif 6952c6a058bSJoseph Chen sprintf(bootm_low, "0x%llx", start); 6962c6a058bSJoseph Chen sprintf(bootm_mapsize, "0x%llx", size); 6972c6a058bSJoseph Chen env_set("bootm_low", bootm_low); 6982c6a058bSJoseph Chen env_set("bootm_mapsize", bootm_mapsize); 6992c6a058bSJoseph Chen } 7002dc2d048SJoseph Chen #endif 7012c6a058bSJoseph Chen 70286f870d6SJoseph Chen #ifdef CONFIG_BIDRAM 70386f870d6SJoseph Chen int board_bidram_reserve(struct bidram *bidram) 70486f870d6SJoseph Chen { 70586f870d6SJoseph Chen struct memblock mem; 70686f870d6SJoseph Chen int ret; 70786f870d6SJoseph Chen 70886f870d6SJoseph Chen /* ATF */ 70986f870d6SJoseph Chen mem = param_parse_atf_mem(); 710c01d4489SJoseph Chen ret = bidram_reserve(MEM_ATF, mem.base, mem.size); 71186f870d6SJoseph Chen if (ret) 71286f870d6SJoseph Chen return ret; 71386f870d6SJoseph Chen 71486f870d6SJoseph Chen /* PSTORE/ATAGS/SHM */ 71586f870d6SJoseph Chen mem = param_parse_common_resv_mem(); 716c01d4489SJoseph Chen ret = bidram_reserve(MEM_SHM, mem.base, mem.size); 71786f870d6SJoseph Chen if (ret) 71886f870d6SJoseph Chen return ret; 71986f870d6SJoseph Chen 72086f870d6SJoseph Chen /* OP-TEE */ 72186f870d6SJoseph Chen mem = param_parse_optee_mem(); 722c01d4489SJoseph Chen ret = bidram_reserve(MEM_OPTEE, mem.base, mem.size); 72386f870d6SJoseph Chen if (ret) 72486f870d6SJoseph Chen return ret; 72586f870d6SJoseph Chen 72686f870d6SJoseph Chen return 0; 72786f870d6SJoseph Chen } 72886f870d6SJoseph Chen 7295b879fbfSJoseph Chen #ifdef CONFIG_SYSMEM 730b3a6659cSJoseph Chen int board_sysmem_reserve(struct sysmem *sysmem) 731b3a6659cSJoseph Chen { 732b3a6659cSJoseph Chen #ifdef CONFIG_SKIP_RELOCATE_UBOOT 733b3a6659cSJoseph Chen if (!sysmem_alloc_base_by_name("NO-RELOC-CODE", 734b3a6659cSJoseph Chen CONFIG_SYS_TEXT_BASE, SZ_2M)) { 735b3a6659cSJoseph Chen printf("Failed to reserve sysmem for U-Boot code\n"); 736b3a6659cSJoseph Chen return -ENOMEM; 737b3a6659cSJoseph Chen } 738b3a6659cSJoseph Chen #endif 739b3a6659cSJoseph Chen return 0; 740b3a6659cSJoseph Chen } 7415b879fbfSJoseph Chen #endif 742b3a6659cSJoseph Chen 74386f870d6SJoseph Chen parse_fn_t board_bidram_parse_fn(void) 74486f870d6SJoseph Chen { 74586f870d6SJoseph Chen return param_parse_ddr_mem; 74686f870d6SJoseph Chen } 74786f870d6SJoseph Chen #endif 74886f870d6SJoseph Chen 74993586e70SJoseph Chen int board_init_f_boot_flags(void) 75093586e70SJoseph Chen { 75193586e70SJoseph Chen int boot_flags = 0; 75293586e70SJoseph Chen 7539f68846bSJoseph Chen #ifdef CONFIG_FPGA_ROCKCHIP 75483f9654dSJoseph Chen arch_fpga_init(); 7559f68846bSJoseph Chen #endif 756ad771a9cSHuibin Hong #ifdef CONFIG_PSTORE 757ad771a9cSHuibin Hong param_parse_pstore(); 758ad771a9cSHuibin Hong #endif 7599d10124aSJoseph Chen param_parse_pre_serial(&boot_flags); 76093586e70SJoseph Chen 76193586e70SJoseph Chen /* The highest priority to turn off (override) console */ 76293586e70SJoseph Chen #if defined(CONFIG_DISABLE_CONSOLE) 76393586e70SJoseph Chen boot_flags |= GD_FLG_DISABLE_CONSOLE; 76493586e70SJoseph Chen #endif 76593586e70SJoseph Chen 76693586e70SJoseph Chen return boot_flags; 76793586e70SJoseph Chen } 768064eb493SJoseph Chen 76938771996SKever Yang #if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG) 7706f7b6465SFrank Wang #include <fdt_support.h> 77138771996SKever Yang #include <usb.h> 77238771996SKever Yang #include <usb/dwc2_udc.h> 77338771996SKever Yang 77438771996SKever Yang static struct dwc2_plat_otg_data otg_data = { 77538771996SKever Yang .rx_fifo_sz = 512, 77638771996SKever Yang .np_tx_fifo_sz = 16, 77738771996SKever Yang .tx_fifo_sz = 128, 77838771996SKever Yang }; 77938771996SKever Yang 78038771996SKever Yang int board_usb_init(int index, enum usb_init_type init) 78138771996SKever Yang { 78238771996SKever Yang const void *blob = gd->fdt_blob; 7832208cd92SJoseph Chen const fdt32_t *reg; 7842208cd92SJoseph Chen fdt_addr_t addr; 7852208cd92SJoseph Chen int node; 78638771996SKever Yang 78738771996SKever Yang /* find the usb_otg node */ 788294ad617SWilliam Wu node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc2"); 78938771996SKever Yang 790294ad617SWilliam Wu retry: 791294ad617SWilliam Wu if (node > 0) { 792294ad617SWilliam Wu reg = fdt_getprop(blob, node, "reg", NULL); 793294ad617SWilliam Wu if (!reg) 794294ad617SWilliam Wu return -EINVAL; 795294ad617SWilliam Wu 796294ad617SWilliam Wu addr = fdt_translate_address(blob, node, reg); 797294ad617SWilliam Wu if (addr == OF_BAD_ADDR) { 798294ad617SWilliam Wu pr_err("Not found usb_otg address\n"); 799294ad617SWilliam Wu return -EINVAL; 80038771996SKever Yang } 80138771996SKever Yang 802294ad617SWilliam Wu #if defined(CONFIG_ROCKCHIP_RK3288) 803294ad617SWilliam Wu if (addr != 0xff580000) { 80438771996SKever Yang node = fdt_node_offset_by_compatible(blob, node, 80538771996SKever Yang "snps,dwc2"); 806294ad617SWilliam Wu goto retry; 80738771996SKever Yang } 808294ad617SWilliam Wu #endif 809294ad617SWilliam Wu } else { 810e7b5bb3cSWilliam Wu /* 811e7b5bb3cSWilliam Wu * With kernel dtb support, rk3288 dwc2 otg node 812e7b5bb3cSWilliam Wu * use the rockchip legacy dwc2 driver "dwc_otg_310" 813e0b87408SJoseph Chen * with the compatible "rockchip,rk3288_usb20_otg", 814e0b87408SJoseph Chen * and rk3368 also use the "dwc_otg_310" driver with 815e0b87408SJoseph Chen * the compatible "rockchip,rk3368-usb". 816e7b5bb3cSWilliam Wu */ 817e0b87408SJoseph Chen #if defined(CONFIG_ROCKCHIP_RK3288) 818e7b5bb3cSWilliam Wu node = fdt_node_offset_by_compatible(blob, -1, 819e7b5bb3cSWilliam Wu "rockchip,rk3288_usb20_otg"); 820e0b87408SJoseph Chen #elif defined(CONFIG_ROCKCHIP_RK3368) 821e0b87408SJoseph Chen node = fdt_node_offset_by_compatible(blob, -1, 822e0b87408SJoseph Chen "rockchip,rk3368-usb"); 823e0b87408SJoseph Chen #endif 824e7b5bb3cSWilliam Wu if (node > 0) { 825294ad617SWilliam Wu goto retry; 826e7b5bb3cSWilliam Wu } else { 827e7b5bb3cSWilliam Wu pr_err("Not found usb_otg device\n"); 82838771996SKever Yang return -ENODEV; 82938771996SKever Yang } 830e7b5bb3cSWilliam Wu } 8316f7b6465SFrank Wang 8326f7b6465SFrank Wang otg_data.regs_otg = (uintptr_t)addr; 83338771996SKever Yang 83438771996SKever Yang return dwc2_udc_probe(&otg_data); 83538771996SKever Yang } 83638771996SKever Yang 83738771996SKever Yang int board_usb_cleanup(int index, enum usb_init_type init) 83838771996SKever Yang { 83938771996SKever Yang return 0; 84038771996SKever Yang } 84138771996SKever Yang #endif 84285cad72dSJoseph Chen 84385cad72dSJoseph Chen static void bootm_no_reloc(void) 84485cad72dSJoseph Chen { 84585cad72dSJoseph Chen char *ramdisk_high; 84685cad72dSJoseph Chen char *fdt_high; 84785cad72dSJoseph Chen 84885cad72dSJoseph Chen if (!env_get_yesno("bootm-no-reloc")) 84985cad72dSJoseph Chen return; 85085cad72dSJoseph Chen 85185cad72dSJoseph Chen ramdisk_high = env_get("initrd_high"); 85285cad72dSJoseph Chen fdt_high = env_get("fdt_high"); 85385cad72dSJoseph Chen 85485cad72dSJoseph Chen if (!fdt_high) { 85585cad72dSJoseph Chen env_set_hex("fdt_high", -1UL); 85685cad72dSJoseph Chen printf("Fdt "); 85785cad72dSJoseph Chen } 85885cad72dSJoseph Chen 85985cad72dSJoseph Chen if (!ramdisk_high) { 86085cad72dSJoseph Chen env_set_hex("initrd_high", -1UL); 86185cad72dSJoseph Chen printf("Ramdisk "); 86285cad72dSJoseph Chen } 86385cad72dSJoseph Chen 86485cad72dSJoseph Chen if (!fdt_high || !ramdisk_high) 86585cad72dSJoseph Chen printf("skip relocation\n"); 86685cad72dSJoseph Chen } 86785cad72dSJoseph Chen 86885cad72dSJoseph Chen int bootm_board_start(void) 86985cad72dSJoseph Chen { 87085cad72dSJoseph Chen /* 87185cad72dSJoseph Chen * print console record data 87285cad72dSJoseph Chen * 87385cad72dSJoseph Chen * On some rockchip platforms, uart debug and sdmmc pin are multiplex. 87485cad72dSJoseph Chen * If boot from sdmmc mode, the console data would be record in buffer, 87585cad72dSJoseph Chen * we switch to uart debug function in order to print it after loading 87685cad72dSJoseph Chen * images. 87785cad72dSJoseph Chen */ 87885cad72dSJoseph Chen #if defined(CONFIG_CONSOLE_RECORD) 87985cad72dSJoseph Chen if (!strcmp("mmc", env_get("devtype")) && 88085cad72dSJoseph Chen !strcmp("1", env_get("devnum"))) { 88185cad72dSJoseph Chen printf("IOMUX: sdmmc => uart debug"); 88285cad72dSJoseph Chen pinctrl_select_state(gd->cur_serial_dev, "default"); 88385cad72dSJoseph Chen console_record_print_purge(); 88485cad72dSJoseph Chen } 88585cad72dSJoseph Chen #endif 88685cad72dSJoseph Chen /* disable bootm relcation to save boot time */ 88785cad72dSJoseph Chen bootm_no_reloc(); 88885cad72dSJoseph Chen 889a18cd24eSJoseph Chen /* PCBA test needs more permission */ 890a18cd24eSJoseph Chen if (get_bcb_recovery_msg() == BCB_MSG_RECOVERY_PCBA) 891a18cd24eSJoseph Chen env_update("bootargs", "androidboot.selinux=permissive"); 892a18cd24eSJoseph Chen 89385cad72dSJoseph Chen /* sysmem */ 89485cad72dSJoseph Chen hotkey_run(HK_SYSMEM); 89585cad72dSJoseph Chen sysmem_overflow_check(); 89685cad72dSJoseph Chen 89785cad72dSJoseph Chen return 0; 89885cad72dSJoseph Chen } 899ac5d8aa9SJoseph Chen 9007bcb4b0dSJoseph Chen int bootm_image_populate_dtb(void *img) 9017bcb4b0dSJoseph Chen { 9027bcb4b0dSJoseph Chen if ((gd->flags & GD_FLG_KDTB_READY) && !gd->fdt_blob_kern) 9037bcb4b0dSJoseph Chen sysmem_free((phys_addr_t)gd->fdt_blob); 9047bcb4b0dSJoseph Chen else 9057bcb4b0dSJoseph Chen gd->fdt_blob = (void *)env_get_ulong("fdt_addr_r", 16, 0); 9067bcb4b0dSJoseph Chen 90725a706d2SJoseph Chen return rockchip_ram_read_dtb_file(img, (void *)gd->fdt_blob); 9087bcb4b0dSJoseph Chen } 9097bcb4b0dSJoseph Chen 910ac5d8aa9SJoseph Chen /* 911ac5d8aa9SJoseph Chen * Implement it to support CLI command: 912ac5d8aa9SJoseph Chen * - Android: bootm [aosp addr] 913ac5d8aa9SJoseph Chen * - FIT: bootm [fit addr] 914ac5d8aa9SJoseph Chen * - uImage: bootm [uimage addr] 915ac5d8aa9SJoseph Chen * 916ac5d8aa9SJoseph Chen * Purpose: 917ac5d8aa9SJoseph Chen * - The original bootm command args require fdt addr on AOSP, 918ac5d8aa9SJoseph Chen * which is not flexible on rockchip boot/recovery.img. 919ac5d8aa9SJoseph Chen * - Take Android/FIT/uImage image into sysmem management to avoid image 920ac5d8aa9SJoseph Chen * memory overlap. 921ac5d8aa9SJoseph Chen */ 922ac5d8aa9SJoseph Chen #if defined(CONFIG_ANDROID_BOOTLOADER) || \ 923ac5d8aa9SJoseph Chen defined(CONFIG_ROCKCHIP_FIT_IMAGE) || \ 924ac5d8aa9SJoseph Chen defined(CONFIG_ROCKCHIP_UIMAGE) 925ac5d8aa9SJoseph Chen int board_do_bootm(int argc, char * const argv[]) 926ac5d8aa9SJoseph Chen { 927ac5d8aa9SJoseph Chen int format; 928ac5d8aa9SJoseph Chen void *img; 929ac5d8aa9SJoseph Chen 930c3515b67SJoseph Chen /* only 'bootm' full image goes further */ 931ac5d8aa9SJoseph Chen if (argc != 2) 932ac5d8aa9SJoseph Chen return 0; 933ac5d8aa9SJoseph Chen 934ac5d8aa9SJoseph Chen img = (void *)simple_strtoul(argv[1], NULL, 16); 935ac5d8aa9SJoseph Chen format = (genimg_get_format(img)); 936ac5d8aa9SJoseph Chen 937ac5d8aa9SJoseph Chen /* Android */ 938ac5d8aa9SJoseph Chen #ifdef CONFIG_ANDROID_BOOT_IMAGE 939ac5d8aa9SJoseph Chen if (format == IMAGE_FORMAT_ANDROID) { 940ac5d8aa9SJoseph Chen struct andr_img_hdr *hdr; 941ac5d8aa9SJoseph Chen ulong load_addr; 942ac5d8aa9SJoseph Chen ulong size; 943ac5d8aa9SJoseph Chen int ret; 944ac5d8aa9SJoseph Chen 945ac5d8aa9SJoseph Chen hdr = (struct andr_img_hdr *)img; 946ac5d8aa9SJoseph Chen printf("BOOTM: transferring to board Android\n"); 947ac5d8aa9SJoseph Chen 948ac5d8aa9SJoseph Chen load_addr = env_get_ulong("kernel_addr_r", 16, 0); 949ac5d8aa9SJoseph Chen load_addr -= hdr->page_size; 950ac5d8aa9SJoseph Chen size = android_image_get_end(hdr) - (ulong)hdr; 951ac5d8aa9SJoseph Chen 952ac5d8aa9SJoseph Chen if (!sysmem_alloc_base(MEM_ANDROID, (ulong)hdr, size)) 953ac5d8aa9SJoseph Chen return -ENOMEM; 954c6f7c1a3SJoseph Chen if (0) { 9557bcb4b0dSJoseph Chen ret = bootm_image_populate_dtb(img); 9567bcb4b0dSJoseph Chen if (ret) { 95725a706d2SJoseph Chen printf("bootm can't read dtb, ret=%d\n", ret); 9587bcb4b0dSJoseph Chen return ret; 9597bcb4b0dSJoseph Chen } 960c6f7c1a3SJoseph Chen } 961ac5d8aa9SJoseph Chen ret = android_image_memcpy_separate(hdr, &load_addr); 962ac5d8aa9SJoseph Chen if (ret) { 963ac5d8aa9SJoseph Chen printf("board do bootm failed, ret=%d\n", ret); 964ac5d8aa9SJoseph Chen return ret; 965ac5d8aa9SJoseph Chen } 966ac5d8aa9SJoseph Chen 967ac5d8aa9SJoseph Chen return android_bootloader_boot_kernel(load_addr); 968ac5d8aa9SJoseph Chen } 969ac5d8aa9SJoseph Chen #endif 970ac5d8aa9SJoseph Chen 971ac5d8aa9SJoseph Chen /* FIT */ 972ac5d8aa9SJoseph Chen #if IMAGE_ENABLE_FIT 973ac5d8aa9SJoseph Chen if (format == IMAGE_FORMAT_FIT) { 974ac5d8aa9SJoseph Chen char boot_cmd[64]; 9757bcb4b0dSJoseph Chen int ret; 976ac5d8aa9SJoseph Chen 977ac5d8aa9SJoseph Chen printf("BOOTM: transferring to board FIT\n"); 9787bcb4b0dSJoseph Chen 9797bcb4b0dSJoseph Chen ret = bootm_image_populate_dtb(img); 9807bcb4b0dSJoseph Chen if (ret) { 98125a706d2SJoseph Chen printf("bootm can't read dtb, ret=%d\n", ret); 9827bcb4b0dSJoseph Chen return ret; 9837bcb4b0dSJoseph Chen } 984ac5d8aa9SJoseph Chen snprintf(boot_cmd, sizeof(boot_cmd), "boot_fit %s", argv[1]); 985ac5d8aa9SJoseph Chen return run_command(boot_cmd, 0); 986ac5d8aa9SJoseph Chen } 987ac5d8aa9SJoseph Chen #endif 988ac5d8aa9SJoseph Chen 989ac5d8aa9SJoseph Chen /* uImage */ 9907bcb4b0dSJoseph Chen #if 0 991ac5d8aa9SJoseph Chen #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 992ac5d8aa9SJoseph Chen if (format == IMAGE_FORMAT_LEGACY && 993ac5d8aa9SJoseph Chen image_get_type(img) == IH_TYPE_MULTI) { 994ac5d8aa9SJoseph Chen char boot_cmd[64]; 995ac5d8aa9SJoseph Chen 996ac5d8aa9SJoseph Chen printf("BOOTM: transferring to board uImage\n"); 997ac5d8aa9SJoseph Chen snprintf(boot_cmd, sizeof(boot_cmd), "boot_uimage %s", argv[1]); 998ac5d8aa9SJoseph Chen return run_command(boot_cmd, 0); 999ac5d8aa9SJoseph Chen } 1000ac5d8aa9SJoseph Chen #endif 10017bcb4b0dSJoseph Chen #endif 1002ac5d8aa9SJoseph Chen return 0; 1003ac5d8aa9SJoseph Chen } 1004ac5d8aa9SJoseph Chen #endif 10054ab50248SJoseph Chen 10064ab50248SJoseph Chen void autoboot_command_fail_handle(void) 10074ab50248SJoseph Chen { 10084ab50248SJoseph Chen #ifdef CONFIG_ANDROID_AB 1009c9c15fdcSJason Zhu if (rk_avb_ab_have_bootable_slot() == true) 1010c9c15fdcSJason Zhu run_command("reset;", 0); 1011c9c15fdcSJason Zhu else 1012c9c15fdcSJason Zhu run_command("fastboot usb 0;", 0); 1013c9c15fdcSJason Zhu #endif 1014c9c15fdcSJason Zhu 1015c9c15fdcSJason Zhu #ifdef CONFIG_AVB_VBMETA_PUBLIC_KEY_VALIDATE 101650fd2129SJoseph Chen run_command("download", 0); 10174ab50248SJoseph Chen run_command("fastboot usb 0;", 0); 10184ab50248SJoseph Chen #endif 1019c9c15fdcSJason Zhu 10204ab50248SJoseph Chen } 1021346c39b3SJoseph Chen 1022c29dd8c4SJoseph Chen #ifdef CONFIG_FIT_ROLLBACK_PROTECT 1023c29dd8c4SJoseph Chen 1024c29dd8c4SJoseph Chen #define FIT_ROLLBACK_INDEX_LOCATION 0x66697472 /* "fitr" */ 1025c29dd8c4SJoseph Chen 1026c29dd8c4SJoseph Chen int fit_read_otp_rollback_index(uint32_t fit_index, uint32_t *otp_index) 1027c29dd8c4SJoseph Chen { 1028c29dd8c4SJoseph Chen #ifdef CONFIG_OPTEE_CLIENT 1029c29dd8c4SJoseph Chen u64 index; 1030c29dd8c4SJoseph Chen int ret; 1031c29dd8c4SJoseph Chen 1032c29dd8c4SJoseph Chen ret = trusty_read_rollback_index(FIT_ROLLBACK_INDEX_LOCATION, &index); 1033c29dd8c4SJoseph Chen if (ret) { 1034c29dd8c4SJoseph Chen if (ret != TEE_ERROR_ITEM_NOT_FOUND) 1035c29dd8c4SJoseph Chen return ret; 1036c29dd8c4SJoseph Chen 1037ee7b0fb8SJason Zhu index = 0; 1038c29dd8c4SJoseph Chen printf("Initial otp index as %d\n", fit_index); 1039bcec4579SZain Wang } 1040ee7b0fb8SJason Zhu 1041ee7b0fb8SJason Zhu *otp_index = (uint32_t)index; 1042c29dd8c4SJoseph Chen #else 1043c29dd8c4SJoseph Chen *otp_index = 0; 1044c29dd8c4SJoseph Chen #endif 1045c29dd8c4SJoseph Chen 1046c29dd8c4SJoseph Chen return 0; 1047c29dd8c4SJoseph Chen } 1048c29dd8c4SJoseph Chen 1049e9f9d90dSJoseph Chen int fit_write_trusty_rollback_index(u32 trusty_index) 1050c29dd8c4SJoseph Chen { 1051c29dd8c4SJoseph Chen if (!trusty_index) 1052c29dd8c4SJoseph Chen return 0; 1053b4a3d48eSJoseph Chen #ifdef CONFIG_OPTEE_CLIENT 10548d26d4b3SJoseph Chen return trusty_write_rollback_index(FIT_ROLLBACK_INDEX_LOCATION, 1055c29dd8c4SJoseph Chen (u64)trusty_index); 1056b4a3d48eSJoseph Chen #else 1057b4a3d48eSJoseph Chen return 0; 1058b4a3d48eSJoseph Chen #endif 1059c29dd8c4SJoseph Chen } 1060c29dd8c4SJoseph Chen #endif 1061c29dd8c4SJoseph Chen 1062189c0d68SJoseph Chen void board_quiesce_devices(void *images) 1063189c0d68SJoseph Chen { 1064189c0d68SJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 1065189c0d68SJoseph Chen /* Destroy atags makes next warm boot safer */ 1066189c0d68SJoseph Chen atags_destroy(); 1067189c0d68SJoseph Chen #endif 1068189c0d68SJoseph Chen #ifdef CONFIG_FIT_ROLLBACK_PROTECT 10698d26d4b3SJoseph Chen int ret; 10708d26d4b3SJoseph Chen 10718d26d4b3SJoseph Chen ret = fit_write_trusty_rollback_index(gd->rollback_index); 10728d26d4b3SJoseph Chen if (ret) { 10738d26d4b3SJoseph Chen panic("Failed to write fit rollback index %d, ret=%d", 10748d26d4b3SJoseph Chen gd->rollback_index, ret); 10758d26d4b3SJoseph Chen } 1076189c0d68SJoseph Chen #endif 1077a5401a9dSJoseph Chen #ifdef CONFIG_ROCKCHIP_HW_DECOMPRESS 1078a5401a9dSJoseph Chen misc_decompress_cleanup(); 1079a5401a9dSJoseph Chen #endif 1080c3515b67SJoseph Chen #ifdef CONFIG_ARM64 1081c3515b67SJoseph Chen bootm_headers_t *bootm_images = (bootm_headers_t *)images; 1082c3515b67SJoseph Chen 1083b627269dSJoseph Chen /* relocate kernel after decompress cleanup */ 10844f7cc6a5SJoseph Chen if (orig_images_ep && orig_images_ep != bootm_images->ep) { 10854f7cc6a5SJoseph Chen memmove((char *)bootm_images->ep, (const char *)orig_images_ep, 1086b627269dSJoseph Chen bootm_images->os.image_len); 1087b627269dSJoseph Chen printf("== DO RELOCATE == Kernel from 0x%08lx to 0x%08lx\n", 10884f7cc6a5SJoseph Chen orig_images_ep, bootm_images->ep); 1089b627269dSJoseph Chen } 1090c3515b67SJoseph Chen #endif 1091b627269dSJoseph Chen 1092b627269dSJoseph Chen hotkey_run(HK_CMDLINE); 1093b627269dSJoseph Chen hotkey_run(HK_CLI_OS_GO); 1094b627269dSJoseph Chen #ifdef CONFIG_ROCKCHIP_REBOOT_TEST 1095b627269dSJoseph Chen do_reset(NULL, 0, 0, NULL); 1096b627269dSJoseph Chen #endif 1097189c0d68SJoseph Chen } 1098d87d5275SJoseph Chen 1099d87d5275SJoseph Chen char *board_fdt_chosen_bootargs(void *fdt) 1100d87d5275SJoseph Chen { 1101d87d5275SJoseph Chen /* bootargs_ext is used when dtbo is applied. */ 1102d87d5275SJoseph Chen const char *arr_bootargs[] = { "bootargs", "bootargs_ext" }; 1103d87d5275SJoseph Chen const char *bootargs; 1104d87d5275SJoseph Chen int nodeoffset; 1105d87d5275SJoseph Chen int i, dump; 11060de7ff3bSJoseph Chen char *msg = "kernel"; 1107d87d5275SJoseph Chen 1108d87d5275SJoseph Chen /* debug */ 1109d87d5275SJoseph Chen hotkey_run(HK_INITCALL); 1110d87d5275SJoseph Chen dump = is_hotkey(HK_CMDLINE); 1111d87d5275SJoseph Chen if (dump) 1112d87d5275SJoseph Chen printf("## bootargs(u-boot): %s\n\n", env_get("bootargs")); 1113d87d5275SJoseph Chen 1114d87d5275SJoseph Chen /* find or create "/chosen" node. */ 1115d87d5275SJoseph Chen nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen"); 1116d87d5275SJoseph Chen if (nodeoffset < 0) 1117d87d5275SJoseph Chen return NULL; 1118d87d5275SJoseph Chen 1119d87d5275SJoseph Chen for (i = 0; i < ARRAY_SIZE(arr_bootargs); i++) { 1120d87d5275SJoseph Chen bootargs = fdt_getprop(fdt, nodeoffset, arr_bootargs[i], NULL); 1121d87d5275SJoseph Chen if (!bootargs) 1122d87d5275SJoseph Chen continue; 1123d87d5275SJoseph Chen if (dump) 11240de7ff3bSJoseph Chen printf("## bootargs(%s-%s): %s\n\n", 11250de7ff3bSJoseph Chen msg, arr_bootargs[i], bootargs); 1126d87d5275SJoseph Chen /* 1127d87d5275SJoseph Chen * Append kernel bootargs 1128d87d5275SJoseph Chen * If use AB system, delete default "root=" which route 1129d87d5275SJoseph Chen * to rootfs. Then the ab bootctl will choose the 1130d87d5275SJoseph Chen * high priority system to boot and add its UUID 1131d87d5275SJoseph Chen * to cmdline. The format is "roo=PARTUUID=xxxx...". 1132d87d5275SJoseph Chen */ 1133d87d5275SJoseph Chen #ifdef CONFIG_ANDROID_AB 1134d87d5275SJoseph Chen env_update_filter("bootargs", bootargs, "root="); 113568720998SZhichao Guo ab_update_root_partition(); 1136d87d5275SJoseph Chen #else 1137d87d5275SJoseph Chen env_update("bootargs", bootargs); 1138d87d5275SJoseph Chen #endif 1139d87d5275SJoseph Chen } 1140d87d5275SJoseph Chen 1141edafafc4SJoseph Chen #if defined(CONFIG_ENVF) || defined(CONFIG_ENV_PARTITION) 1142edafafc4SJoseph Chen char *part_type[] = { "mtdparts", "blkdevparts" }; 1143edafafc4SJoseph Chen char *part_list; 1144edafafc4SJoseph Chen char *env; 1145edafafc4SJoseph Chen int id = 0; 1146bdb740d4SJoseph Chen 1147edafafc4SJoseph Chen env = env_get(part_type[id]); 1148edafafc4SJoseph Chen if (!env) 1149edafafc4SJoseph Chen env = env_get(part_type[++id]); 1150edafafc4SJoseph Chen if (env) { 1151edafafc4SJoseph Chen if (!strstr(env, part_type[id])) { 1152edafafc4SJoseph Chen part_list = calloc(1, strlen(env) + strlen(part_type[id]) + 2); 1153edafafc4SJoseph Chen if (part_list) { 1154edafafc4SJoseph Chen strcat(part_list, part_type[id]); 1155edafafc4SJoseph Chen strcat(part_list, "="); 1156edafafc4SJoseph Chen strcat(part_list, env); 1157edafafc4SJoseph Chen } 1158edafafc4SJoseph Chen } else { 1159edafafc4SJoseph Chen part_list = env; 1160edafafc4SJoseph Chen } 1161edafafc4SJoseph Chen env_update("bootargs", part_list); 1162bdb740d4SJoseph Chen if (dump) 1163edafafc4SJoseph Chen printf("## parts: %s\n\n", part_list); 1164edafafc4SJoseph Chen } 1165edafafc4SJoseph Chen 1166edafafc4SJoseph Chen env = env_get("sys_bootargs"); 1167edafafc4SJoseph Chen if (env) { 1168edafafc4SJoseph Chen env_update("bootargs", env); 1169edafafc4SJoseph Chen if (dump) 1170edafafc4SJoseph Chen printf("## sys_bootargs: %s\n\n", env); 1171bdb740d4SJoseph Chen } 1172bdb740d4SJoseph Chen #endif 1173edafafc4SJoseph Chen 1174d87d5275SJoseph Chen #ifdef CONFIG_MTD_BLK 1175bdb740d4SJoseph Chen if (!env_get("mtdparts")) { 1176d87d5275SJoseph Chen char *mtd_par_info = mtd_part_parse(NULL); 1177d87d5275SJoseph Chen 1178d87d5275SJoseph Chen if (mtd_par_info) { 1179d87d5275SJoseph Chen if (memcmp(env_get("devtype"), "mtd", 3) == 0) 1180d87d5275SJoseph Chen env_update("bootargs", mtd_par_info); 1181d87d5275SJoseph Chen } 1182bdb740d4SJoseph Chen } 1183d87d5275SJoseph Chen #endif 1184d87d5275SJoseph Chen /* 1185d87d5275SJoseph Chen * Initrd fixup: remove unused "initrd=0x...,0x...", 1186d87d5275SJoseph Chen * this for compatible with legacy parameter.txt 1187d87d5275SJoseph Chen */ 1188d87d5275SJoseph Chen env_delete("bootargs", "initrd=", 0); 1189d87d5275SJoseph Chen 1190d87d5275SJoseph Chen /* 1191d87d5275SJoseph Chen * If uart is required to be disabled during 1192d87d5275SJoseph Chen * power on, it would be not initialized by 1193d87d5275SJoseph Chen * any pre-loader and U-Boot. 1194d87d5275SJoseph Chen * 1195d87d5275SJoseph Chen * If we don't remove earlycon from commandline, 1196d87d5275SJoseph Chen * kernel hangs while using earlycon to putc/getc 1197d87d5275SJoseph Chen * which may dead loop for waiting uart status. 1198d87d5275SJoseph Chen * (It seems the root cause is baundrate is not 1199d87d5275SJoseph Chen * initilalized) 1200d87d5275SJoseph Chen * 1201d87d5275SJoseph Chen * So let's remove earlycon from commandline. 1202d87d5275SJoseph Chen */ 1203d87d5275SJoseph Chen if (gd->flags & GD_FLG_DISABLE_CONSOLE) 1204d87d5275SJoseph Chen env_delete("bootargs", "earlycon=", 0); 1205d87d5275SJoseph Chen 12061761a533SJoseph Chen /* Android header v4+ need this handle */ 12071761a533SJoseph Chen #ifdef CONFIG_ANDROID_BOOT_IMAGE 12081761a533SJoseph Chen struct andr_img_hdr *hdr; 12091761a533SJoseph Chen 12101761a533SJoseph Chen hdr = (void *)env_get_ulong("android_addr_r", 16, 0); 12111761a533SJoseph Chen if (hdr && !android_image_check_header(hdr) && hdr->header_version >= 4) { 12121761a533SJoseph Chen if (env_update_extract_subset("bootargs", "andr_bootargs", "androidboot.")) 12131761a533SJoseph Chen printf("extract androidboot.xxx error\n"); 12141761a533SJoseph Chen if (dump) 12151761a533SJoseph Chen printf("## bootargs(android): %s\n\n", env_get("andr_bootargs")); 12161761a533SJoseph Chen } 12171761a533SJoseph Chen #endif 1218d87d5275SJoseph Chen bootargs = env_get("bootargs"); 1219d87d5275SJoseph Chen if (dump) 1220d87d5275SJoseph Chen printf("## bootargs(merged): %s\n\n", bootargs); 1221d87d5275SJoseph Chen 1222d87d5275SJoseph Chen return (char *)bootargs; 1223d87d5275SJoseph Chen } 1224d87d5275SJoseph Chen 12251761a533SJoseph Chen int ft_verify_fdt(void *fdt) 12261761a533SJoseph Chen { 12271761a533SJoseph Chen /* for android header v4+, we load bootparams and fixup initrd */ 12281761a533SJoseph Chen #if defined(CONFIG_ANDROID_BOOT_IMAGE) && defined(CONFIG_XBC) 12291761a533SJoseph Chen struct andr_img_hdr *hdr; 12301761a533SJoseph Chen uint64_t initrd_start, initrd_end; 12311761a533SJoseph Chen char *bootargs, *p; 12321761a533SJoseph Chen int nodeoffset; 12331761a533SJoseph Chen int is_u64, err; 12341761a533SJoseph Chen u32 len; 12351761a533SJoseph Chen 12361761a533SJoseph Chen hdr = (void *)env_get_ulong("android_addr_r", 16, 0); 12371761a533SJoseph Chen if (!hdr || android_image_check_header(hdr) || 12381761a533SJoseph Chen hdr->header_version < 4) 12391761a533SJoseph Chen return 1; 12401761a533SJoseph Chen 12411761a533SJoseph Chen bootargs = env_get("andr_bootargs"); 12421761a533SJoseph Chen if (!bootargs) 12431761a533SJoseph Chen return 1; 12441761a533SJoseph Chen 12451761a533SJoseph Chen /* trans character: space to new line */ 12461761a533SJoseph Chen p = bootargs; 12471761a533SJoseph Chen while (*p++) { 12481761a533SJoseph Chen if (*p == ' ') 12491761a533SJoseph Chen *p = '\n'; 12501761a533SJoseph Chen } 12511761a533SJoseph Chen 12521761a533SJoseph Chen debug("## andr_bootargs: %s\n", bootargs); 12531761a533SJoseph Chen 12541761a533SJoseph Chen /* 12551761a533SJoseph Chen * add boot params right after bootconfig 12561761a533SJoseph Chen * 12571761a533SJoseph Chen * because we can get final full bootargs in board_fdt_chosen_bootargs(), 12581761a533SJoseph Chen * android_image_get_ramdisk() is early than that. 12591761a533SJoseph Chen * 12601761a533SJoseph Chen * we have to add boot params by now. 12611761a533SJoseph Chen */ 12621761a533SJoseph Chen len = addBootConfigParameters((char *)bootargs, strlen(bootargs), 12631761a533SJoseph Chen (u64)hdr->ramdisk_addr + hdr->ramdisk_size + 12641761a533SJoseph Chen hdr->vendor_ramdisk_size, hdr->vendor_bootconfig_size); 12651761a533SJoseph Chen if (len < 0) { 12661761a533SJoseph Chen printf("error: addBootConfigParameters\n"); 12671761a533SJoseph Chen return 0; 12681761a533SJoseph Chen } 12691761a533SJoseph Chen 12701761a533SJoseph Chen nodeoffset = fdt_subnode_offset(fdt, 0, "chosen"); 12711761a533SJoseph Chen if (nodeoffset < 0) { 12721761a533SJoseph Chen printf("error: No /chosen node\n"); 12731761a533SJoseph Chen return 0; 12741761a533SJoseph Chen } 12751761a533SJoseph Chen 12761761a533SJoseph Chen /* fixup initrd with real value */ 12771761a533SJoseph Chen fdt_delprop(fdt, nodeoffset, "linux,initrd-start"); 12781761a533SJoseph Chen fdt_delprop(fdt, nodeoffset, "linux,initrd-end"); 12791761a533SJoseph Chen 12801761a533SJoseph Chen is_u64 = (fdt_address_cells(fdt, 0) == 2); 12811761a533SJoseph Chen initrd_start = hdr->ramdisk_addr; 12821761a533SJoseph Chen initrd_end = initrd_start + hdr->ramdisk_size + 12831761a533SJoseph Chen hdr->vendor_ramdisk_size + 12841761a533SJoseph Chen hdr->vendor_bootconfig_size + len; 12851761a533SJoseph Chen err = fdt_setprop_uxx(fdt, nodeoffset, "linux,initrd-start", 12861761a533SJoseph Chen initrd_start, is_u64); 12871761a533SJoseph Chen if (err < 0) { 12881761a533SJoseph Chen printf("WARNING: could not set linux,initrd-start %s.\n", 12891761a533SJoseph Chen fdt_strerror(err)); 12901761a533SJoseph Chen return 0; 12911761a533SJoseph Chen } 12921761a533SJoseph Chen err = fdt_setprop_uxx(fdt, nodeoffset, "linux,initrd-end", 12931761a533SJoseph Chen initrd_end, is_u64); 12941761a533SJoseph Chen if (err < 0) { 12951761a533SJoseph Chen printf("WARNING: could not set linux,initrd-end %s.\n", 12961761a533SJoseph Chen fdt_strerror(err)); 12971761a533SJoseph Chen return 0; 12981761a533SJoseph Chen } 12991761a533SJoseph Chen #endif 13001761a533SJoseph Chen return 1; 13011761a533SJoseph Chen } 13021761a533SJoseph Chen 1303