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 5938771996SKever Yang __weak int rk_board_late_init(void) 6038771996SKever Yang { 6138771996SKever Yang return 0; 6238771996SKever Yang } 6338771996SKever Yang 6438ce6261SJoseph Chen __weak int rk_board_fdt_fixup(void *blob) 6538ce6261SJoseph Chen { 6638ce6261SJoseph Chen return 0; 6738ce6261SJoseph Chen } 6838ce6261SJoseph Chen 69efdbac34SFinley Xiao __weak int soc_clk_dump(void) 70efdbac34SFinley Xiao { 71efdbac34SFinley Xiao return 0; 72efdbac34SFinley Xiao } 73efdbac34SFinley Xiao 74058e5d94SFinley Xiao __weak int set_armclk_rate(void) 75058e5d94SFinley Xiao { 76058e5d94SFinley Xiao return 0; 77058e5d94SFinley Xiao } 78058e5d94SFinley Xiao 792208cd92SJoseph Chen __weak int rk_board_init(void) 802208cd92SJoseph Chen { 812208cd92SJoseph Chen return 0; 822208cd92SJoseph Chen } 832208cd92SJoseph Chen 84c9a034c4SJoseph Chen #ifdef CONFIG_ROCKCHIP_SET_ETHADDR 852208cd92SJoseph Chen /* 862208cd92SJoseph Chen * define serialno max length, the max length is 512 Bytes 872208cd92SJoseph Chen * The remaining bytes are used to ensure that the first 512 bytes 882208cd92SJoseph Chen * are valid when executing 'env_set("serial#", value)'. 892208cd92SJoseph Chen */ 902208cd92SJoseph Chen #define VENDOR_SN_MAX 513 912208cd92SJoseph Chen #define CPUID_LEN 0x10 922208cd92SJoseph Chen #define CPUID_OFF 0x07 932208cd92SJoseph Chen 942e32f666SDavid Wu #define MAX_ETHERNET 0x2 952e32f666SDavid Wu 962208cd92SJoseph Chen static int rockchip_set_ethaddr(void) 972208cd92SJoseph Chen { 986d9793cfSJoseph Chen __maybe_unused bool need_write = false; 996d9793cfSJoseph Chen bool randomed = false; 1002e32f666SDavid Wu char buf[ARP_HLEN_ASCII + 1], mac[16]; 1012e32f666SDavid Wu u8 ethaddr[ARP_HLEN * MAX_ETHERNET] = {0}; 1026d9793cfSJoseph Chen int i, ret = -EINVAL; 1032208cd92SJoseph Chen 1046d9793cfSJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 10500fc4eeeSYifeng Zhao ret = vendor_storage_read(LAN_MAC_ID, ethaddr, sizeof(ethaddr)); 1066d9793cfSJoseph Chen #endif 1072e32f666SDavid Wu for (i = 0; i < MAX_ETHERNET; i++) { 1082e32f666SDavid Wu if (ret <= 0 || !is_valid_ethaddr(ðaddr[i * ARP_HLEN])) { 1092cde40a1SDavid Wu if (!randomed) { 1102e32f666SDavid Wu net_random_ethaddr(ðaddr[i * ARP_HLEN]); 1112cde40a1SDavid Wu randomed = true; 1122cde40a1SDavid Wu } else { 1132cde40a1SDavid Wu if (i > 0) { 1142cde40a1SDavid Wu memcpy(ðaddr[i * ARP_HLEN], 1152cde40a1SDavid Wu ðaddr[(i - 1) * ARP_HLEN], 1162cde40a1SDavid Wu ARP_HLEN); 1172cde40a1SDavid Wu ethaddr[i * ARP_HLEN] |= 0x02; 1182cde40a1SDavid Wu ethaddr[i * ARP_HLEN] += (i << 2); 1192cde40a1SDavid Wu } 1202cde40a1SDavid Wu } 1212cde40a1SDavid Wu 1222e32f666SDavid Wu need_write = true; 1232e32f666SDavid Wu } 1242e32f666SDavid Wu 1252e32f666SDavid Wu if (is_valid_ethaddr(ðaddr[i * ARP_HLEN])) { 126c1c7e89dSJianqun Xu snprintf(buf, ARP_HLEN_ASCII + 1, "%pM", ðaddr[i * ARP_HLEN]); 1272e32f666SDavid Wu if (i == 0) 1282e32f666SDavid Wu memcpy(mac, "ethaddr", sizeof("ethaddr")); 1292e32f666SDavid Wu else 1302e32f666SDavid Wu sprintf(mac, "eth%daddr", i); 1312e32f666SDavid Wu env_set(mac, buf); 1322e32f666SDavid Wu } 1332e32f666SDavid Wu } 1342e32f666SDavid Wu 1356d9793cfSJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 1362e32f666SDavid Wu if (need_write) { 13700fc4eeeSYifeng Zhao ret = vendor_storage_write(LAN_MAC_ID, 1382e32f666SDavid Wu ethaddr, sizeof(ethaddr)); 1392e32f666SDavid Wu if (ret < 0) 1402e32f666SDavid Wu printf("%s: vendor_storage_write failed %d\n", 1412e32f666SDavid Wu __func__, ret); 1422208cd92SJoseph Chen } 1432208cd92SJoseph Chen #endif 1442208cd92SJoseph Chen return 0; 1452208cd92SJoseph Chen } 146c9a034c4SJoseph Chen #endif 1472208cd92SJoseph Chen 148c9a034c4SJoseph Chen #ifdef CONFIG_ROCKCHIP_SET_SN 1492208cd92SJoseph Chen static int rockchip_set_serialno(void) 1502208cd92SJoseph Chen { 1512208cd92SJoseph Chen u8 low[CPUID_LEN / 2], high[CPUID_LEN / 2]; 1522208cd92SJoseph Chen u8 cpuid[CPUID_LEN] = {0}; 1532208cd92SJoseph Chen char serialno_str[VENDOR_SN_MAX]; 1542208cd92SJoseph Chen int ret = 0, i; 1552208cd92SJoseph Chen u64 serialno; 1562208cd92SJoseph Chen 1572208cd92SJoseph Chen /* Read serial number from vendor storage part */ 1582208cd92SJoseph Chen memset(serialno_str, 0, VENDOR_SN_MAX); 1592208cd92SJoseph Chen 1602208cd92SJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION 161*80b41b17SJon Lin int j; 162*80b41b17SJon Lin 16300fc4eeeSYifeng Zhao ret = vendor_storage_read(SN_ID, serialno_str, (VENDOR_SN_MAX-1)); 1642208cd92SJoseph Chen if (ret > 0) { 165*80b41b17SJon Lin j = strlen(serialno_str); 166*80b41b17SJon Lin for (i = 0; i < j; i++) { 167df197bd2SJason Zhu if ((serialno_str[i] >= 'a' && serialno_str[i] <= 'z') || 168df197bd2SJason Zhu (serialno_str[i] >= 'A' && serialno_str[i] <= 'Z') || 169df197bd2SJason Zhu (serialno_str[i] >= '0' && serialno_str[i] <= '9')) 170df197bd2SJason Zhu break; 171df197bd2SJason Zhu } 172df197bd2SJason Zhu 173fa7e137dSJoseph Chen /* valid character count > 0 */ 174fa7e137dSJoseph Chen if (i > 0) { 175df197bd2SJason Zhu serialno_str[i + 1] = 0x0; 1762208cd92SJoseph Chen env_set("serial#", serialno_str); 177fa7e137dSJoseph Chen } 178fa7e137dSJoseph Chen } 1792208cd92SJoseph Chen #endif 180fa7e137dSJoseph Chen if (!env_get("serial#")) { 181d3cb8b06SSugar Zhang #if defined(CONFIG_ROCKCHIP_EFUSE) || defined(CONFIG_ROCKCHIP_OTP) 1822208cd92SJoseph Chen struct udevice *dev; 1832208cd92SJoseph Chen 1842208cd92SJoseph Chen /* retrieve the device */ 185d3cb8b06SSugar Zhang if (IS_ENABLED(CONFIG_ROCKCHIP_EFUSE)) 1862208cd92SJoseph Chen ret = uclass_get_device_by_driver(UCLASS_MISC, 1872208cd92SJoseph Chen DM_GET_DRIVER(rockchip_efuse), 1882208cd92SJoseph Chen &dev); 189d3cb8b06SSugar Zhang else 190d3cb8b06SSugar Zhang ret = uclass_get_device_by_driver(UCLASS_MISC, 191d3cb8b06SSugar Zhang DM_GET_DRIVER(rockchip_otp), 192d3cb8b06SSugar Zhang &dev); 193d3cb8b06SSugar Zhang 1942208cd92SJoseph Chen if (ret) { 195d3cb8b06SSugar Zhang printf("%s: could not find efuse/otp device\n", __func__); 1962208cd92SJoseph Chen return ret; 1972208cd92SJoseph Chen } 1982208cd92SJoseph Chen 1992208cd92SJoseph Chen /* read the cpu_id range from the efuses */ 2002208cd92SJoseph Chen ret = misc_read(dev, CPUID_OFF, &cpuid, sizeof(cpuid)); 2012208cd92SJoseph Chen if (ret) { 202d3cb8b06SSugar Zhang printf("%s: read cpuid from efuse/otp failed, ret=%d\n", 2032208cd92SJoseph Chen __func__, ret); 2042208cd92SJoseph Chen return ret; 2052208cd92SJoseph Chen } 2062208cd92SJoseph Chen #else 2072208cd92SJoseph Chen /* generate random cpuid */ 2082208cd92SJoseph Chen for (i = 0; i < CPUID_LEN; i++) 2092208cd92SJoseph Chen cpuid[i] = (u8)(rand()); 2102208cd92SJoseph Chen #endif 2112208cd92SJoseph Chen /* Generate the serial number based on CPU ID */ 2122208cd92SJoseph Chen for (i = 0; i < 8; i++) { 2132208cd92SJoseph Chen low[i] = cpuid[1 + (i << 1)]; 2142208cd92SJoseph Chen high[i] = cpuid[i << 1]; 2152208cd92SJoseph Chen } 2162208cd92SJoseph Chen 2172208cd92SJoseph Chen serialno = crc32_no_comp(0, low, 8); 2182208cd92SJoseph Chen serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32; 2192208cd92SJoseph Chen snprintf(serialno_str, sizeof(serialno_str), "%llx", serialno); 2202208cd92SJoseph Chen 2212208cd92SJoseph Chen env_set("serial#", serialno_str); 2222208cd92SJoseph Chen } 2232208cd92SJoseph Chen 2242208cd92SJoseph Chen return ret; 2252208cd92SJoseph Chen } 226c9a034c4SJoseph Chen #endif 227c9a034c4SJoseph Chen 2282208cd92SJoseph Chen #if defined(CONFIG_USB_FUNCTION_FASTBOOT) 2292208cd92SJoseph Chen int fb_set_reboot_flag(void) 2302208cd92SJoseph Chen { 2312208cd92SJoseph Chen printf("Setting reboot to fastboot flag ...\n"); 2322208cd92SJoseph Chen writel(BOOT_FASTBOOT, CONFIG_ROCKCHIP_BOOT_MODE_REG); 2332208cd92SJoseph Chen 2342208cd92SJoseph Chen return 0; 2352208cd92SJoseph Chen } 2362208cd92SJoseph Chen #endif 2372208cd92SJoseph Chen 2380ed06f16SJoseph Chen #ifdef CONFIG_ROCKCHIP_USB_BOOT 2390ed06f16SJoseph Chen static int boot_from_udisk(void) 2400ed06f16SJoseph Chen { 2410ed06f16SJoseph Chen struct blk_desc *desc; 2420ed06f16SJoseph Chen char *devtype; 2430ed06f16SJoseph Chen char *devnum; 2440ed06f16SJoseph Chen 2450ed06f16SJoseph Chen devtype = env_get("devtype"); 2460ed06f16SJoseph Chen devnum = env_get("devnum"); 2470ed06f16SJoseph Chen 2480ed06f16SJoseph Chen /* Booting priority: mmc1 > udisk */ 2490ed06f16SJoseph Chen if (!strcmp(devtype, "mmc") && !strcmp(devnum, "1")) 2500ed06f16SJoseph Chen return 0; 2510ed06f16SJoseph Chen 2520ed06f16SJoseph Chen if (!run_command("usb start", -1)) { 2530ed06f16SJoseph Chen desc = blk_get_devnum_by_type(IF_TYPE_USB, 0); 2540ed06f16SJoseph Chen if (!desc) { 2550ed06f16SJoseph Chen printf("No usb device found\n"); 2560ed06f16SJoseph Chen return -ENODEV; 2570ed06f16SJoseph Chen } 2580ed06f16SJoseph Chen 2590ed06f16SJoseph Chen if (!run_command("rkimgtest usb 0", -1)) { 2600ed06f16SJoseph Chen rockchip_set_bootdev(desc); 2610ed06f16SJoseph Chen env_set("devtype", "usb"); 2620ed06f16SJoseph Chen env_set("devnum", "0"); 2630ed06f16SJoseph Chen printf("Boot from usb 0\n"); 2640ed06f16SJoseph Chen } else { 2650ed06f16SJoseph Chen printf("No usb dev 0 found\n"); 2660ed06f16SJoseph Chen return -ENODEV; 2670ed06f16SJoseph Chen } 2680ed06f16SJoseph Chen } 2690ed06f16SJoseph Chen 2700ed06f16SJoseph Chen return 0; 2710ed06f16SJoseph Chen } 2720ed06f16SJoseph Chen #endif 2730ed06f16SJoseph Chen 274c6f0e819SJoseph Chen static void env_fixup(void) 275c6f0e819SJoseph Chen { 276c6f0e819SJoseph Chen struct memblock mem; 277c6f0e819SJoseph Chen ulong u_addr_r; 278c6f0e819SJoseph Chen phys_size_t end; 279c6f0e819SJoseph Chen char *addr_r; 280c6f0e819SJoseph Chen 281c6f0e819SJoseph Chen #ifdef ENV_MEM_LAYOUT_SETTINGS1 282c6f0e819SJoseph Chen const char *env_addr0[] = { 283c6f0e819SJoseph Chen "scriptaddr", "pxefile_addr_r", 284c6f0e819SJoseph Chen "fdt_addr_r", "kernel_addr_r", "ramdisk_addr_r", 285c6f0e819SJoseph Chen }; 286c6f0e819SJoseph Chen const char *env_addr1[] = { 287c6f0e819SJoseph Chen "scriptaddr1", "pxefile_addr1_r", 288c6f0e819SJoseph Chen "fdt_addr1_r", "kernel_addr1_r", "ramdisk_addr1_r", 289c6f0e819SJoseph Chen }; 290c6f0e819SJoseph Chen int i; 291c6f0e819SJoseph Chen 292c6f0e819SJoseph Chen /* 128M is a typical ram size for most platform, so as default here */ 293c6f0e819SJoseph Chen if (gd->ram_size <= SZ_128M) { 294c6f0e819SJoseph Chen /* Replace orignal xxx_addr_r */ 295c6f0e819SJoseph Chen for (i = 0; i < ARRAY_SIZE(env_addr1); i++) { 296c6f0e819SJoseph Chen addr_r = env_get(env_addr1[i]); 297c6f0e819SJoseph Chen if (addr_r) 298c6f0e819SJoseph Chen env_set(env_addr0[i], addr_r); 299c6f0e819SJoseph Chen } 300c6f0e819SJoseph Chen } 301c6f0e819SJoseph Chen #endif 30249e18ddbSJoseph Chen /* No BL32 ? */ 303c6f0e819SJoseph Chen if (!(gd->flags & GD_FLG_BL32_ENABLED)) { 30449e18ddbSJoseph Chen /* 30549e18ddbSJoseph Chen * [1] Move kernel to lower address if possible. 30649e18ddbSJoseph Chen */ 30749e18ddbSJoseph Chen addr_r = env_get("kernel_addr_no_low_bl32_r"); 308c6f0e819SJoseph Chen if (addr_r) 309c6f0e819SJoseph Chen env_set("kernel_addr_r", addr_r); 3104175c722SJoseph Chen 3114175c722SJoseph Chen /* 31249e18ddbSJoseph Chen * [2] Move ramdisk at BL32 position if need. 31349e18ddbSJoseph Chen * 3144175c722SJoseph Chen * 0x0a200000 and 0x08400000 are rockchip traditional address 3154175c722SJoseph Chen * of BL32 and ramdisk: 3164175c722SJoseph Chen * 3174175c722SJoseph Chen * |------------|------------| 3184175c722SJoseph Chen * | BL32 | ramdisk | 3194175c722SJoseph Chen * |------------|------------| 3204175c722SJoseph Chen * 3214175c722SJoseph Chen * Move ramdisk to BL32 address to fix sysmem alloc failed 3224175c722SJoseph Chen * issue on the board with critical memory(ie. 256MB). 3234175c722SJoseph Chen */ 3244175c722SJoseph Chen if (gd->ram_size > SZ_128M && gd->ram_size <= SZ_256M) { 3254175c722SJoseph Chen u_addr_r = env_get_ulong("ramdisk_addr_r", 16, 0); 3264175c722SJoseph Chen if (u_addr_r == 0x0a200000) 3274175c722SJoseph Chen env_set("ramdisk_addr_r", "0x08400000"); 3284175c722SJoseph Chen } 329c6f0e819SJoseph Chen } else { 330c6f0e819SJoseph Chen mem = param_parse_optee_mem(); 33149e18ddbSJoseph Chen 33249e18ddbSJoseph Chen /* 33349e18ddbSJoseph Chen * [1] Move kernel forward if possible. 33449e18ddbSJoseph Chen */ 33549e18ddbSJoseph Chen if (mem.base > SZ_128M) { 33649e18ddbSJoseph Chen addr_r = env_get("kernel_addr_no_low_bl32_r"); 33749e18ddbSJoseph Chen if (addr_r) 33849e18ddbSJoseph Chen env_set("kernel_addr_r", addr_r); 33949e18ddbSJoseph Chen } 34049e18ddbSJoseph Chen 34149e18ddbSJoseph Chen /* 34249e18ddbSJoseph Chen * [2] Move ramdisk backward if optee enlarge. 34349e18ddbSJoseph Chen */ 344c6f0e819SJoseph Chen end = mem.base + mem.size; 345c6f0e819SJoseph Chen u_addr_r = env_get_ulong("ramdisk_addr_r", 16, 0); 346c6f0e819SJoseph Chen if (u_addr_r >= mem.base && u_addr_r < end) 347c6f0e819SJoseph Chen env_set_hex("ramdisk_addr_r", end); 348c6f0e819SJoseph Chen } 349c6f0e819SJoseph Chen } 350c6f0e819SJoseph Chen 35183c9bd4bSJoseph Chen static void cmdline_handle(void) 35283c9bd4bSJoseph Chen { 35360f07e75SJoseph Chen struct blk_desc *dev_desc; 35460f07e75SJoseph Chen 355045d3eaaSJoseph Chen param_parse_pubkey_fuse_programmed(); 35683c9bd4bSJoseph Chen 35760f07e75SJoseph Chen dev_desc = rockchip_get_bootdev(); 35860f07e75SJoseph Chen if (!dev_desc) 35960f07e75SJoseph Chen return; 36060f07e75SJoseph Chen 361692d3098SJoseph Chen /* 3623d2521fcSJoseph Chen * 1. From rk356x, the sd/udisk recovery update flag was moved from 363692d3098SJoseph Chen * IDB to Android BCB. 3643d2521fcSJoseph Chen * 3653d2521fcSJoseph Chen * 2. Udisk is init at the late boot_from_udisk(), but 3663d2521fcSJoseph Chen * rockchip_get_boot_mode() actually only read once, 3673d2521fcSJoseph Chen * we need to update boot mode according to udisk BCB. 368692d3098SJoseph Chen */ 3693d2521fcSJoseph Chen if ((dev_desc->if_type == IF_TYPE_MMC && dev_desc->devnum == 1) || 3703d2521fcSJoseph Chen (dev_desc->if_type == IF_TYPE_USB && dev_desc->devnum == 0)) { 371706ec1d4SJoseph Chen if (get_bcb_recovery_msg() == BCB_MSG_RECOVERY_RK_FWUPDATE) { 3723d2521fcSJoseph Chen if (dev_desc->if_type == IF_TYPE_MMC && dev_desc->devnum == 1) { 37360f07e75SJoseph Chen env_update("bootargs", "sdfwupdate"); 3743d2521fcSJoseph Chen } else if (dev_desc->if_type == IF_TYPE_USB && dev_desc->devnum == 0) { 37560f07e75SJoseph Chen env_update("bootargs", "usbfwupdate"); 3763d2521fcSJoseph Chen env_set("reboot_mode", "recovery-usb"); 3773d2521fcSJoseph Chen } 3783d2521fcSJoseph Chen } else { 3793d2521fcSJoseph Chen if (dev_desc->if_type == IF_TYPE_USB && dev_desc->devnum == 0) 3803d2521fcSJoseph Chen env_set("reboot_mode", "normal"); 3813d2521fcSJoseph Chen } 38260f07e75SJoseph Chen } 38383c9bd4bSJoseph Chen } 38483c9bd4bSJoseph Chen 38538771996SKever Yang int board_late_init(void) 38638771996SKever Yang { 387c9a034c4SJoseph Chen #ifdef CONFIG_ROCKCHIP_SET_ETHADDR 3882549364dSlanshh rockchip_set_ethaddr(); 389c9a034c4SJoseph Chen #endif 390c9a034c4SJoseph Chen #ifdef CONFIG_ROCKCHIP_SET_SN 391fc1a5563SJason Zhu rockchip_set_serialno(); 392c9a034c4SJoseph Chen #endif 393d04ada6cSJoseph Chen setup_download_mode(); 39491ed07e5SJoseph Chen 3950ed06f16SJoseph Chen #ifdef CONFIG_ROCKCHIP_USB_BOOT 3960ed06f16SJoseph Chen boot_from_udisk(); 3970ed06f16SJoseph Chen #endif 39838771996SKever Yang #ifdef CONFIG_DM_CHARGE_DISPLAY 39938771996SKever Yang charge_display(); 40038771996SKever Yang #endif 40138771996SKever Yang #ifdef CONFIG_DRM_ROCKCHIP 40238771996SKever Yang rockchip_show_logo(); 40338771996SKever Yang #endif 404efeef7e5SWenping Zhang #ifdef CONFIG_ROCKCHIP_EINK_DISPLAY 405efeef7e5SWenping Zhang rockchip_eink_show_uboot_logo(); 406efeef7e5SWenping Zhang #endif 40791ed07e5SJoseph Chen #if (CONFIG_ROCKCHIP_BOOT_MODE_REG > 0) 40891ed07e5SJoseph Chen setup_boot_mode(); 40991ed07e5SJoseph Chen #endif 410c6f0e819SJoseph Chen env_fixup(); 411efdbac34SFinley Xiao soc_clk_dump(); 41283c9bd4bSJoseph Chen cmdline_handle(); 41375ac0a02SJoseph Chen #ifdef CONFIG_AMP 41475ac0a02SJoseph Chen amp_cpus_on(); 41575ac0a02SJoseph Chen #endif 41638771996SKever Yang return rk_board_late_init(); 41738771996SKever Yang } 41838771996SKever Yang 419a7940145SJoseph Chen static void early_download(void) 420644804edSJoseph Chen { 4217397b961SJoseph Chen #if defined(CONFIG_PWRKEY_DNL_TRIGGER_NUM) && \ 4227397b961SJoseph Chen (CONFIG_PWRKEY_DNL_TRIGGER_NUM > 0) 4237397b961SJoseph Chen if (pwrkey_download_init()) 4247397b961SJoseph Chen printf("Pwrkey download init failed\n"); 4257397b961SJoseph Chen #endif 4267397b961SJoseph Chen 427644804edSJoseph Chen #if (CONFIG_ROCKCHIP_BOOT_MODE_REG > 0) 428c664909eSJoseph Chen if (is_hotkey(HK_BROM_DNL)) { 429644804edSJoseph Chen printf("Enter bootrom download..."); 430363411a1SJoseph Chen flushc(); 431644804edSJoseph Chen writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG); 432644804edSJoseph Chen do_reset(NULL, 0, 0, NULL); 433644804edSJoseph Chen printf("failed!\n"); 434644804edSJoseph Chen } 435644804edSJoseph Chen #endif 436644804edSJoseph Chen } 437644804edSJoseph Chen 4385d5f363eSJoseph Chen static void board_debug_init(void) 4395d5f363eSJoseph Chen { 44093586e70SJoseph Chen if (!gd->serial.using_pre_serial && 44193586e70SJoseph Chen !(gd->flags & GD_FLG_DISABLE_CONSOLE)) 4427abb254dSJoseph Chen debug_uart_init(); 44346f61401SJoseph Chen 44446f61401SJoseph Chen if (tstc()) { 44546f61401SJoseph Chen gd->console_evt = getc(); 44646f61401SJoseph Chen if (gd->console_evt <= 0x1a) /* 'z' */ 44746f61401SJoseph Chen printf("Hotkey: ctrl+%c\n", gd->console_evt + 'a' - 1); 44846f61401SJoseph Chen } 4499889a0e0SJoseph Chen 4509889a0e0SJoseph Chen if (IS_ENABLED(CONFIG_CONSOLE_DISABLE_CLI)) 45125047d3fSJoseph Chen printf("Cmd interface: disabled\n"); 4525d5f363eSJoseph Chen } 4535d5f363eSJoseph Chen 45497c86b55SJoseph Chen #if defined(CONFIG_MTD_BLK) && defined(CONFIG_USING_KERNEL_DTB) 455459f5cb0SJason Zhu static void board_mtd_blk_map_partitions(void) 456459f5cb0SJason Zhu { 457459f5cb0SJason Zhu struct blk_desc *dev_desc; 458459f5cb0SJason Zhu 459459f5cb0SJason Zhu dev_desc = rockchip_get_bootdev(); 460459f5cb0SJason Zhu if (dev_desc) 461459f5cb0SJason Zhu mtd_blk_map_partitions(dev_desc); 462459f5cb0SJason Zhu } 463459f5cb0SJason Zhu #endif 464459f5cb0SJason Zhu 46538771996SKever Yang int board_init(void) 46638771996SKever Yang { 4675d5f363eSJoseph Chen board_debug_init(); 4687504da74SHisping Lin /* optee select security level */ 4697504da74SHisping Lin #ifdef CONFIG_OPTEE_CLIENT 4707504da74SHisping Lin trusty_select_security_level(); 4717504da74SHisping Lin #endif 472ebb6c439SYouMin Chen 473f0aa8c5dSJason Zhu #ifdef DEBUG 474f0aa8c5dSJason Zhu soc_clk_dump(); 475f0aa8c5dSJason Zhu #endif 476f0aa8c5dSJason Zhu 477f8aaa2c2SKever Yang #ifdef CONFIG_USING_KERNEL_DTB 478459f5cb0SJason Zhu #ifdef CONFIG_MTD_BLK 479459f5cb0SJason Zhu board_mtd_blk_map_partitions(); 480459f5cb0SJason Zhu #endif 481f8aaa2c2SKever Yang init_kernel_dtb(); 482f8aaa2c2SKever Yang #endif 483a7940145SJoseph Chen early_download(); 4847397b961SJoseph Chen 4859f8e13d3SFinley Xiao /* 4869f8e13d3SFinley Xiao * pmucru isn't referenced on some platforms, so pmucru driver can't 4879f8e13d3SFinley Xiao * probe that the "assigned-clocks" is unused. 4889f8e13d3SFinley Xiao */ 4899f8e13d3SFinley Xiao clks_probe(); 49038771996SKever Yang #ifdef CONFIG_DM_REGULATOR 491dba9c9e5SJoseph Chen if (regulators_enable_boot_on(is_hotkey(HK_REGULATOR))) 4922208cd92SJoseph Chen debug("%s: Can't enable boot on regulator\n", __func__); 49338771996SKever Yang #endif 494dae20286SJianqun Xu 495dae20286SJianqun Xu #ifdef CONFIG_ROCKCHIP_IO_DOMAIN 496dae20286SJianqun Xu io_domain_init(); 497dae20286SJianqun Xu #endif 498dae20286SJianqun Xu 499058e5d94SFinley Xiao set_armclk_rate(); 50038771996SKever Yang 5013acf4edfSJoseph Chen #ifdef CONFIG_DM_DVFS 5023acf4edfSJoseph Chen dvfs_init(true); 5033acf4edfSJoseph Chen #endif 5043acf4edfSJoseph Chen 5050f44aebdSJason Zhu #ifdef CONFIG_ANDROID_AB 5060f44aebdSJason Zhu if (ab_decrease_tries()) 5070f44aebdSJason Zhu printf("Decrease ab tries count fail!\n"); 5080f44aebdSJason Zhu #endif 5090f44aebdSJason Zhu 51038771996SKever Yang return rk_board_init(); 51138771996SKever Yang } 51238771996SKever Yang 513c563adc7SJoseph Chen int interrupt_debugger_init(void) 514c563adc7SJoseph Chen { 515c563adc7SJoseph Chen #ifdef CONFIG_ROCKCHIP_DEBUGGER 5162208cd92SJoseph Chen return rockchip_debugger_init(); 5172208cd92SJoseph Chen #else 5182208cd92SJoseph Chen return 0; 519c563adc7SJoseph Chen #endif 520c563adc7SJoseph Chen } 521c563adc7SJoseph Chen 522e09b1e4aSJoseph Chen int board_fdt_fixup(void *blob) 523e09b1e4aSJoseph Chen { 5242208cd92SJoseph Chen /* Common fixup for DRM */ 525e09b1e4aSJoseph Chen #ifdef CONFIG_DRM_ROCKCHIP 526e09b1e4aSJoseph Chen rockchip_display_fixup(blob); 527e09b1e4aSJoseph Chen #endif 528e09b1e4aSJoseph Chen 52938ce6261SJoseph Chen return rk_board_fdt_fixup(blob); 530e09b1e4aSJoseph Chen } 531e09b1e4aSJoseph Chen 532102dfafcSElon Zhang #if defined(CONFIG_ARM64_BOOT_AARCH32) || !defined(CONFIG_ARM64) 533e3fbd280SJoseph Chen /* 534f1d65189SJoseph Chen * Common for OP-TEE: 535396e3049SElon Zhang * 64-bit & 32-bit mode: share memory dcache is always enabled; 536e3fbd280SJoseph Chen * 537f1d65189SJoseph Chen * Common for U-Boot: 538e3fbd280SJoseph Chen * 64-bit mode: MMU table is static defined in rkxxx.c file, all memory 539e3fbd280SJoseph Chen * regions are mapped. That's good to match OP-TEE MMU policy. 540e3fbd280SJoseph Chen * 541e3fbd280SJoseph Chen * 32-bit mode: MMU table is setup according to gd->bd->bi_dram[..] where 542e3fbd280SJoseph Chen * the OP-TEE region has been reserved, so it can not be 543102dfafcSElon Zhang * mapped(i.e. dcache is disabled). That's *NOT* good to match 544e3fbd280SJoseph Chen * OP-TEE MMU policy. 545e3fbd280SJoseph Chen * 546e3fbd280SJoseph Chen * For the data coherence when communication between U-Boot and OP-TEE, U-Boot 547e3fbd280SJoseph Chen * should follow OP-TEE MMU policy. 548e3fbd280SJoseph Chen * 549396e3049SElon Zhang * So 32-bit mode U-Boot should map OP-TEE share memory as dcache enabled. 550e3fbd280SJoseph Chen */ 551e3fbd280SJoseph Chen int board_initr_caches_fixup(void) 552e3fbd280SJoseph Chen { 553396e3049SElon Zhang #ifdef CONFIG_OPTEE_CLIENT 554e3fbd280SJoseph Chen struct memblock mem; 555e3fbd280SJoseph Chen 556396e3049SElon Zhang mem.base = 0; 557396e3049SElon Zhang mem.size = 0; 558396e3049SElon Zhang 559396e3049SElon Zhang optee_get_shm_config(&mem.base, &mem.size); 560e3fbd280SJoseph Chen if (mem.size) 561e3fbd280SJoseph Chen mmu_set_region_dcache_behaviour(mem.base, mem.size, 562e3fbd280SJoseph Chen DCACHE_WRITEBACK); 563396e3049SElon Zhang #endif 564e3fbd280SJoseph Chen return 0; 565e3fbd280SJoseph Chen } 566e3fbd280SJoseph Chen #endif 567e3fbd280SJoseph Chen 5684353cdc4SJoseph Chen void arch_preboot_os(uint32_t bootm_state, bootm_headers_t *images) 569665be4b0SJoseph Chen { 5704353cdc4SJoseph Chen if (!(bootm_state & BOOTM_STATE_OS_PREP)) 5714353cdc4SJoseph Chen return; 5724353cdc4SJoseph Chen 5734353cdc4SJoseph Chen #ifdef CONFIG_ARM64 5744353cdc4SJoseph Chen u8 *data = (void *)images->ep; 5754353cdc4SJoseph Chen 5764353cdc4SJoseph Chen /* 5774353cdc4SJoseph Chen * Fix kernel 5.10 arm64 boot warning: 5784353cdc4SJoseph Chen * "[Firmware Bug]: Kernel image misaligned at boot, please fix your bootloader!" 5794353cdc4SJoseph Chen * 5804353cdc4SJoseph Chen * kernel: 5.10 commit 120dc60d0bdb ("arm64: get rid of TEXT_OFFSET") 5814353cdc4SJoseph Chen * arm64 kernel version: 582c3515b67SJoseph Chen * data[10] == 0x00 if kernel version >= 5.10: N*2MB align 583c3515b67SJoseph Chen * data[10] == 0x08 if kernel version < 5.10: N*2MB + 0x80000(TEXT_OFFSET) 5844353cdc4SJoseph Chen * 5854353cdc4SJoseph Chen * Why fix here? 5864353cdc4SJoseph Chen * 1. this is the common and final path for any boot command. 5874353cdc4SJoseph Chen * 2. don't influence original boot flow, just fix it exactly before 5884353cdc4SJoseph Chen * jumping kernel. 589b627269dSJoseph Chen * 590b627269dSJoseph Chen * But relocation is in board_quiesce_devices() until all decompress 591b627269dSJoseph Chen * done, mainly for saving boot time. 5924353cdc4SJoseph Chen */ 5934353cdc4SJoseph Chen if (data[10] == 0x00) { 594b627269dSJoseph Chen if (round_down(images->ep, SZ_2M) != images->ep) 595b627269dSJoseph Chen images->ep = round_down(images->ep, SZ_2M); 596a4625d53SJoseph Chen } else { 597b627269dSJoseph Chen if (IS_ALIGNED(images->ep, SZ_2M)) 598b627269dSJoseph Chen images->ep += 0x80000; 5994353cdc4SJoseph Chen } 6004353cdc4SJoseph Chen #endif 601665be4b0SJoseph Chen hotkey_run(HK_CLI_OS_PRE); 602665be4b0SJoseph Chen } 603665be4b0SJoseph Chen 60438771996SKever Yang void enable_caches(void) 60538771996SKever Yang { 606567735c8SJoseph Chen icache_enable(); 60738771996SKever Yang dcache_enable(); 60838771996SKever Yang } 60938771996SKever Yang 6102dc2d048SJoseph Chen #ifdef CONFIG_LMB 6112c6a058bSJoseph Chen /* 6122c6a058bSJoseph Chen * Using last bi_dram[...] to initialize "bootm_low" and "bootm_mapsize". 6132c6a058bSJoseph Chen * This makes lmb_alloc_base() always alloc from tail of sdram. 6142c6a058bSJoseph Chen * If we don't assign it, bi_dram[0] is used by default and it may cause 6152c6a058bSJoseph Chen * lmb_alloc_base() fail when bi_dram[0] range is small. 6162c6a058bSJoseph Chen */ 6172c6a058bSJoseph Chen void board_lmb_reserve(struct lmb *lmb) 6182c6a058bSJoseph Chen { 6192c6a058bSJoseph Chen char bootm_mapsize[32]; 6202208cd92SJoseph Chen char bootm_low[32]; 6212208cd92SJoseph Chen u64 start, size; 6222c6a058bSJoseph Chen int i; 6232c6a058bSJoseph Chen 6242c6a058bSJoseph Chen for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 6252c6a058bSJoseph Chen if (!gd->bd->bi_dram[i].size) 6262c6a058bSJoseph Chen break; 6272c6a058bSJoseph Chen } 6282c6a058bSJoseph Chen 6292c6a058bSJoseph Chen start = gd->bd->bi_dram[i - 1].start; 6302c6a058bSJoseph Chen size = gd->bd->bi_dram[i - 1].size; 6312c6a058bSJoseph Chen 6322c6a058bSJoseph Chen /* 6332dc2d048SJoseph Chen * 32-bit kernel: ramdisk/fdt shouldn't be loaded to highmem area(768MB+), 6342dc2d048SJoseph Chen * otherwise "Unable to handle kernel paging request at virtual address ...". 6352dc2d048SJoseph Chen * 6362dc2d048SJoseph Chen * So that we hope limit highest address at 768M, but there comes the the 6372dc2d048SJoseph Chen * problem: ramdisk is a compressed image and it expands after descompress, 6382dc2d048SJoseph Chen * so it accesses 768MB+ and brings the above "Unable to handle kernel ...". 6392dc2d048SJoseph Chen * 6402dc2d048SJoseph Chen * We make a appointment that the highest memory address is 512MB, it 6412dc2d048SJoseph Chen * makes lmb alloc safer. 6422c6a058bSJoseph Chen */ 6432dc2d048SJoseph Chen #ifndef CONFIG_ARM64 6442dc2d048SJoseph Chen if (start >= ((u64)CONFIG_SYS_SDRAM_BASE + SZ_512M)) { 6452c6a058bSJoseph Chen start = gd->bd->bi_dram[i - 2].start; 6462c6a058bSJoseph Chen size = gd->bd->bi_dram[i - 2].size; 6472c6a058bSJoseph Chen } 6482c6a058bSJoseph Chen 6492dc2d048SJoseph Chen if ((start + size) > ((u64)CONFIG_SYS_SDRAM_BASE + SZ_512M)) 6502dc2d048SJoseph Chen size = (u64)CONFIG_SYS_SDRAM_BASE + SZ_512M - start; 6512c6a058bSJoseph Chen #endif 6522c6a058bSJoseph Chen sprintf(bootm_low, "0x%llx", start); 6532c6a058bSJoseph Chen sprintf(bootm_mapsize, "0x%llx", size); 6542c6a058bSJoseph Chen env_set("bootm_low", bootm_low); 6552c6a058bSJoseph Chen env_set("bootm_mapsize", bootm_mapsize); 6562c6a058bSJoseph Chen } 6572dc2d048SJoseph Chen #endif 6582c6a058bSJoseph Chen 65986f870d6SJoseph Chen #ifdef CONFIG_BIDRAM 66086f870d6SJoseph Chen int board_bidram_reserve(struct bidram *bidram) 66186f870d6SJoseph Chen { 66286f870d6SJoseph Chen struct memblock mem; 66386f870d6SJoseph Chen int ret; 66486f870d6SJoseph Chen 66586f870d6SJoseph Chen /* ATF */ 66686f870d6SJoseph Chen mem = param_parse_atf_mem(); 667c01d4489SJoseph Chen ret = bidram_reserve(MEM_ATF, mem.base, mem.size); 66886f870d6SJoseph Chen if (ret) 66986f870d6SJoseph Chen return ret; 67086f870d6SJoseph Chen 67186f870d6SJoseph Chen /* PSTORE/ATAGS/SHM */ 67286f870d6SJoseph Chen mem = param_parse_common_resv_mem(); 673c01d4489SJoseph Chen ret = bidram_reserve(MEM_SHM, mem.base, mem.size); 67486f870d6SJoseph Chen if (ret) 67586f870d6SJoseph Chen return ret; 67686f870d6SJoseph Chen 67786f870d6SJoseph Chen /* OP-TEE */ 67886f870d6SJoseph Chen mem = param_parse_optee_mem(); 679c01d4489SJoseph Chen ret = bidram_reserve(MEM_OPTEE, mem.base, mem.size); 68086f870d6SJoseph Chen if (ret) 68186f870d6SJoseph Chen return ret; 68286f870d6SJoseph Chen 68386f870d6SJoseph Chen return 0; 68486f870d6SJoseph Chen } 68586f870d6SJoseph Chen 6865b879fbfSJoseph Chen #ifdef CONFIG_SYSMEM 687b3a6659cSJoseph Chen int board_sysmem_reserve(struct sysmem *sysmem) 688b3a6659cSJoseph Chen { 689b3a6659cSJoseph Chen #ifdef CONFIG_SKIP_RELOCATE_UBOOT 690b3a6659cSJoseph Chen if (!sysmem_alloc_base_by_name("NO-RELOC-CODE", 691b3a6659cSJoseph Chen CONFIG_SYS_TEXT_BASE, SZ_2M)) { 692b3a6659cSJoseph Chen printf("Failed to reserve sysmem for U-Boot code\n"); 693b3a6659cSJoseph Chen return -ENOMEM; 694b3a6659cSJoseph Chen } 695b3a6659cSJoseph Chen #endif 696b3a6659cSJoseph Chen return 0; 697b3a6659cSJoseph Chen } 6985b879fbfSJoseph Chen #endif 699b3a6659cSJoseph Chen 70086f870d6SJoseph Chen parse_fn_t board_bidram_parse_fn(void) 70186f870d6SJoseph Chen { 70286f870d6SJoseph Chen return param_parse_ddr_mem; 70386f870d6SJoseph Chen } 70486f870d6SJoseph Chen #endif 70586f870d6SJoseph Chen 70693586e70SJoseph Chen int board_init_f_boot_flags(void) 70793586e70SJoseph Chen { 70893586e70SJoseph Chen int boot_flags = 0; 70993586e70SJoseph Chen 71083f9654dSJoseph Chen arch_fpga_init(); 71183f9654dSJoseph Chen 7129d10124aSJoseph Chen param_parse_pre_serial(&boot_flags); 71393586e70SJoseph Chen 71493586e70SJoseph Chen /* The highest priority to turn off (override) console */ 71593586e70SJoseph Chen #if defined(CONFIG_DISABLE_CONSOLE) 71693586e70SJoseph Chen boot_flags |= GD_FLG_DISABLE_CONSOLE; 71793586e70SJoseph Chen #endif 71893586e70SJoseph Chen 71993586e70SJoseph Chen return boot_flags; 72093586e70SJoseph Chen } 721064eb493SJoseph Chen 72238771996SKever Yang #if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG) 7236f7b6465SFrank Wang #include <fdt_support.h> 72438771996SKever Yang #include <usb.h> 72538771996SKever Yang #include <usb/dwc2_udc.h> 72638771996SKever Yang 72738771996SKever Yang static struct dwc2_plat_otg_data otg_data = { 72838771996SKever Yang .rx_fifo_sz = 512, 72938771996SKever Yang .np_tx_fifo_sz = 16, 73038771996SKever Yang .tx_fifo_sz = 128, 73138771996SKever Yang }; 73238771996SKever Yang 73338771996SKever Yang int board_usb_init(int index, enum usb_init_type init) 73438771996SKever Yang { 73538771996SKever Yang const void *blob = gd->fdt_blob; 7362208cd92SJoseph Chen const fdt32_t *reg; 7372208cd92SJoseph Chen fdt_addr_t addr; 7382208cd92SJoseph Chen int node; 73938771996SKever Yang 74038771996SKever Yang /* find the usb_otg node */ 741294ad617SWilliam Wu node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc2"); 74238771996SKever Yang 743294ad617SWilliam Wu retry: 744294ad617SWilliam Wu if (node > 0) { 745294ad617SWilliam Wu reg = fdt_getprop(blob, node, "reg", NULL); 746294ad617SWilliam Wu if (!reg) 747294ad617SWilliam Wu return -EINVAL; 748294ad617SWilliam Wu 749294ad617SWilliam Wu addr = fdt_translate_address(blob, node, reg); 750294ad617SWilliam Wu if (addr == OF_BAD_ADDR) { 751294ad617SWilliam Wu pr_err("Not found usb_otg address\n"); 752294ad617SWilliam Wu return -EINVAL; 75338771996SKever Yang } 75438771996SKever Yang 755294ad617SWilliam Wu #if defined(CONFIG_ROCKCHIP_RK3288) 756294ad617SWilliam Wu if (addr != 0xff580000) { 75738771996SKever Yang node = fdt_node_offset_by_compatible(blob, node, 75838771996SKever Yang "snps,dwc2"); 759294ad617SWilliam Wu goto retry; 76038771996SKever Yang } 761294ad617SWilliam Wu #endif 762294ad617SWilliam Wu } else { 763e7b5bb3cSWilliam Wu /* 764e7b5bb3cSWilliam Wu * With kernel dtb support, rk3288 dwc2 otg node 765e7b5bb3cSWilliam Wu * use the rockchip legacy dwc2 driver "dwc_otg_310" 766e0b87408SJoseph Chen * with the compatible "rockchip,rk3288_usb20_otg", 767e0b87408SJoseph Chen * and rk3368 also use the "dwc_otg_310" driver with 768e0b87408SJoseph Chen * the compatible "rockchip,rk3368-usb". 769e7b5bb3cSWilliam Wu */ 770e0b87408SJoseph Chen #if defined(CONFIG_ROCKCHIP_RK3288) 771e7b5bb3cSWilliam Wu node = fdt_node_offset_by_compatible(blob, -1, 772e7b5bb3cSWilliam Wu "rockchip,rk3288_usb20_otg"); 773e0b87408SJoseph Chen #elif defined(CONFIG_ROCKCHIP_RK3368) 774e0b87408SJoseph Chen node = fdt_node_offset_by_compatible(blob, -1, 775e0b87408SJoseph Chen "rockchip,rk3368-usb"); 776e0b87408SJoseph Chen #endif 777e7b5bb3cSWilliam Wu if (node > 0) { 778294ad617SWilliam Wu goto retry; 779e7b5bb3cSWilliam Wu } else { 780e7b5bb3cSWilliam Wu pr_err("Not found usb_otg device\n"); 78138771996SKever Yang return -ENODEV; 78238771996SKever Yang } 783e7b5bb3cSWilliam Wu } 7846f7b6465SFrank Wang 7856f7b6465SFrank Wang otg_data.regs_otg = (uintptr_t)addr; 78638771996SKever Yang 78738771996SKever Yang return dwc2_udc_probe(&otg_data); 78838771996SKever Yang } 78938771996SKever Yang 79038771996SKever Yang int board_usb_cleanup(int index, enum usb_init_type init) 79138771996SKever Yang { 79238771996SKever Yang return 0; 79338771996SKever Yang } 79438771996SKever Yang #endif 79585cad72dSJoseph Chen 79685cad72dSJoseph Chen static void bootm_no_reloc(void) 79785cad72dSJoseph Chen { 79885cad72dSJoseph Chen char *ramdisk_high; 79985cad72dSJoseph Chen char *fdt_high; 80085cad72dSJoseph Chen 80185cad72dSJoseph Chen if (!env_get_yesno("bootm-no-reloc")) 80285cad72dSJoseph Chen return; 80385cad72dSJoseph Chen 80485cad72dSJoseph Chen ramdisk_high = env_get("initrd_high"); 80585cad72dSJoseph Chen fdt_high = env_get("fdt_high"); 80685cad72dSJoseph Chen 80785cad72dSJoseph Chen if (!fdt_high) { 80885cad72dSJoseph Chen env_set_hex("fdt_high", -1UL); 80985cad72dSJoseph Chen printf("Fdt "); 81085cad72dSJoseph Chen } 81185cad72dSJoseph Chen 81285cad72dSJoseph Chen if (!ramdisk_high) { 81385cad72dSJoseph Chen env_set_hex("initrd_high", -1UL); 81485cad72dSJoseph Chen printf("Ramdisk "); 81585cad72dSJoseph Chen } 81685cad72dSJoseph Chen 81785cad72dSJoseph Chen if (!fdt_high || !ramdisk_high) 81885cad72dSJoseph Chen printf("skip relocation\n"); 81985cad72dSJoseph Chen } 82085cad72dSJoseph Chen 82185cad72dSJoseph Chen int bootm_board_start(void) 82285cad72dSJoseph Chen { 82385cad72dSJoseph Chen /* 82485cad72dSJoseph Chen * print console record data 82585cad72dSJoseph Chen * 82685cad72dSJoseph Chen * On some rockchip platforms, uart debug and sdmmc pin are multiplex. 82785cad72dSJoseph Chen * If boot from sdmmc mode, the console data would be record in buffer, 82885cad72dSJoseph Chen * we switch to uart debug function in order to print it after loading 82985cad72dSJoseph Chen * images. 83085cad72dSJoseph Chen */ 83185cad72dSJoseph Chen #if defined(CONFIG_CONSOLE_RECORD) 83285cad72dSJoseph Chen if (!strcmp("mmc", env_get("devtype")) && 83385cad72dSJoseph Chen !strcmp("1", env_get("devnum"))) { 83485cad72dSJoseph Chen printf("IOMUX: sdmmc => uart debug"); 83585cad72dSJoseph Chen pinctrl_select_state(gd->cur_serial_dev, "default"); 83685cad72dSJoseph Chen console_record_print_purge(); 83785cad72dSJoseph Chen } 83885cad72dSJoseph Chen #endif 83985cad72dSJoseph Chen /* disable bootm relcation to save boot time */ 84085cad72dSJoseph Chen bootm_no_reloc(); 84185cad72dSJoseph Chen 842a18cd24eSJoseph Chen /* PCBA test needs more permission */ 843a18cd24eSJoseph Chen if (get_bcb_recovery_msg() == BCB_MSG_RECOVERY_PCBA) 844a18cd24eSJoseph Chen env_update("bootargs", "androidboot.selinux=permissive"); 845a18cd24eSJoseph Chen 84685cad72dSJoseph Chen /* sysmem */ 84785cad72dSJoseph Chen hotkey_run(HK_SYSMEM); 84885cad72dSJoseph Chen sysmem_overflow_check(); 84985cad72dSJoseph Chen 85085cad72dSJoseph Chen return 0; 85185cad72dSJoseph Chen } 852ac5d8aa9SJoseph Chen 8537bcb4b0dSJoseph Chen int bootm_image_populate_dtb(void *img) 8547bcb4b0dSJoseph Chen { 8557bcb4b0dSJoseph Chen if ((gd->flags & GD_FLG_KDTB_READY) && !gd->fdt_blob_kern) 8567bcb4b0dSJoseph Chen sysmem_free((phys_addr_t)gd->fdt_blob); 8577bcb4b0dSJoseph Chen else 8587bcb4b0dSJoseph Chen gd->fdt_blob = (void *)env_get_ulong("fdt_addr_r", 16, 0); 8597bcb4b0dSJoseph Chen 86025a706d2SJoseph Chen return rockchip_ram_read_dtb_file(img, (void *)gd->fdt_blob); 8617bcb4b0dSJoseph Chen } 8627bcb4b0dSJoseph Chen 863ac5d8aa9SJoseph Chen /* 864ac5d8aa9SJoseph Chen * Implement it to support CLI command: 865ac5d8aa9SJoseph Chen * - Android: bootm [aosp addr] 866ac5d8aa9SJoseph Chen * - FIT: bootm [fit addr] 867ac5d8aa9SJoseph Chen * - uImage: bootm [uimage addr] 868ac5d8aa9SJoseph Chen * 869ac5d8aa9SJoseph Chen * Purpose: 870ac5d8aa9SJoseph Chen * - The original bootm command args require fdt addr on AOSP, 871ac5d8aa9SJoseph Chen * which is not flexible on rockchip boot/recovery.img. 872ac5d8aa9SJoseph Chen * - Take Android/FIT/uImage image into sysmem management to avoid image 873ac5d8aa9SJoseph Chen * memory overlap. 874ac5d8aa9SJoseph Chen */ 875ac5d8aa9SJoseph Chen #if defined(CONFIG_ANDROID_BOOTLOADER) || \ 876ac5d8aa9SJoseph Chen defined(CONFIG_ROCKCHIP_FIT_IMAGE) || \ 877ac5d8aa9SJoseph Chen defined(CONFIG_ROCKCHIP_UIMAGE) 878ac5d8aa9SJoseph Chen int board_do_bootm(int argc, char * const argv[]) 879ac5d8aa9SJoseph Chen { 880ac5d8aa9SJoseph Chen int format; 881ac5d8aa9SJoseph Chen void *img; 882ac5d8aa9SJoseph Chen 883c3515b67SJoseph Chen /* only 'bootm' full image goes further */ 884ac5d8aa9SJoseph Chen if (argc != 2) 885ac5d8aa9SJoseph Chen return 0; 886ac5d8aa9SJoseph Chen 887ac5d8aa9SJoseph Chen img = (void *)simple_strtoul(argv[1], NULL, 16); 888ac5d8aa9SJoseph Chen format = (genimg_get_format(img)); 889ac5d8aa9SJoseph Chen 890ac5d8aa9SJoseph Chen /* Android */ 891ac5d8aa9SJoseph Chen #ifdef CONFIG_ANDROID_BOOT_IMAGE 892ac5d8aa9SJoseph Chen if (format == IMAGE_FORMAT_ANDROID) { 893ac5d8aa9SJoseph Chen struct andr_img_hdr *hdr; 894ac5d8aa9SJoseph Chen ulong load_addr; 895ac5d8aa9SJoseph Chen ulong size; 896ac5d8aa9SJoseph Chen int ret; 897ac5d8aa9SJoseph Chen 898ac5d8aa9SJoseph Chen hdr = (struct andr_img_hdr *)img; 899ac5d8aa9SJoseph Chen printf("BOOTM: transferring to board Android\n"); 900ac5d8aa9SJoseph Chen 901ac5d8aa9SJoseph Chen load_addr = env_get_ulong("kernel_addr_r", 16, 0); 902ac5d8aa9SJoseph Chen load_addr -= hdr->page_size; 903ac5d8aa9SJoseph Chen size = android_image_get_end(hdr) - (ulong)hdr; 904ac5d8aa9SJoseph Chen 905ac5d8aa9SJoseph Chen if (!sysmem_alloc_base(MEM_ANDROID, (ulong)hdr, size)) 906ac5d8aa9SJoseph Chen return -ENOMEM; 907ac5d8aa9SJoseph Chen 9087bcb4b0dSJoseph Chen ret = bootm_image_populate_dtb(img); 9097bcb4b0dSJoseph Chen if (ret) { 91025a706d2SJoseph Chen printf("bootm can't read dtb, ret=%d\n", ret); 9117bcb4b0dSJoseph Chen return ret; 9127bcb4b0dSJoseph Chen } 9137bcb4b0dSJoseph Chen 914ac5d8aa9SJoseph Chen ret = android_image_memcpy_separate(hdr, &load_addr); 915ac5d8aa9SJoseph Chen if (ret) { 916ac5d8aa9SJoseph Chen printf("board do bootm failed, ret=%d\n", ret); 917ac5d8aa9SJoseph Chen return ret; 918ac5d8aa9SJoseph Chen } 919ac5d8aa9SJoseph Chen 920ac5d8aa9SJoseph Chen return android_bootloader_boot_kernel(load_addr); 921ac5d8aa9SJoseph Chen } 922ac5d8aa9SJoseph Chen #endif 923ac5d8aa9SJoseph Chen 924ac5d8aa9SJoseph Chen /* FIT */ 925ac5d8aa9SJoseph Chen #if IMAGE_ENABLE_FIT 926ac5d8aa9SJoseph Chen if (format == IMAGE_FORMAT_FIT) { 927ac5d8aa9SJoseph Chen char boot_cmd[64]; 9287bcb4b0dSJoseph Chen int ret; 929ac5d8aa9SJoseph Chen 930ac5d8aa9SJoseph Chen printf("BOOTM: transferring to board FIT\n"); 9317bcb4b0dSJoseph Chen 9327bcb4b0dSJoseph Chen ret = bootm_image_populate_dtb(img); 9337bcb4b0dSJoseph Chen if (ret) { 93425a706d2SJoseph Chen printf("bootm can't read dtb, ret=%d\n", ret); 9357bcb4b0dSJoseph Chen return ret; 9367bcb4b0dSJoseph Chen } 937ac5d8aa9SJoseph Chen snprintf(boot_cmd, sizeof(boot_cmd), "boot_fit %s", argv[1]); 938ac5d8aa9SJoseph Chen return run_command(boot_cmd, 0); 939ac5d8aa9SJoseph Chen } 940ac5d8aa9SJoseph Chen #endif 941ac5d8aa9SJoseph Chen 942ac5d8aa9SJoseph Chen /* uImage */ 9437bcb4b0dSJoseph Chen #if 0 944ac5d8aa9SJoseph Chen #if defined(CONFIG_IMAGE_FORMAT_LEGACY) 945ac5d8aa9SJoseph Chen if (format == IMAGE_FORMAT_LEGACY && 946ac5d8aa9SJoseph Chen image_get_type(img) == IH_TYPE_MULTI) { 947ac5d8aa9SJoseph Chen char boot_cmd[64]; 948ac5d8aa9SJoseph Chen 949ac5d8aa9SJoseph Chen printf("BOOTM: transferring to board uImage\n"); 950ac5d8aa9SJoseph Chen snprintf(boot_cmd, sizeof(boot_cmd), "boot_uimage %s", argv[1]); 951ac5d8aa9SJoseph Chen return run_command(boot_cmd, 0); 952ac5d8aa9SJoseph Chen } 953ac5d8aa9SJoseph Chen #endif 9547bcb4b0dSJoseph Chen #endif 955ac5d8aa9SJoseph Chen return 0; 956ac5d8aa9SJoseph Chen } 957ac5d8aa9SJoseph Chen #endif 9584ab50248SJoseph Chen 9594ab50248SJoseph Chen void autoboot_command_fail_handle(void) 9604ab50248SJoseph Chen { 9614ab50248SJoseph Chen #ifdef CONFIG_ANDROID_AB 962c9c15fdcSJason Zhu if (rk_avb_ab_have_bootable_slot() == true) 963c9c15fdcSJason Zhu run_command("reset;", 0); 964c9c15fdcSJason Zhu else 965c9c15fdcSJason Zhu run_command("fastboot usb 0;", 0); 966c9c15fdcSJason Zhu #endif 967c9c15fdcSJason Zhu 968c9c15fdcSJason Zhu #ifdef CONFIG_AVB_VBMETA_PUBLIC_KEY_VALIDATE 9694ab50248SJoseph Chen run_command("rockusb 0 ${devtype} ${devnum}", 0); 9704ab50248SJoseph Chen run_command("fastboot usb 0;", 0); 9714ab50248SJoseph Chen #endif 972c9c15fdcSJason Zhu 9734ab50248SJoseph Chen } 974346c39b3SJoseph Chen 975c29dd8c4SJoseph Chen #ifdef CONFIG_FIT_ROLLBACK_PROTECT 976c29dd8c4SJoseph Chen 977c29dd8c4SJoseph Chen #define FIT_ROLLBACK_INDEX_LOCATION 0x66697472 /* "fitr" */ 978c29dd8c4SJoseph Chen 979c29dd8c4SJoseph Chen int fit_read_otp_rollback_index(uint32_t fit_index, uint32_t *otp_index) 980c29dd8c4SJoseph Chen { 981c29dd8c4SJoseph Chen #ifdef CONFIG_OPTEE_CLIENT 982c29dd8c4SJoseph Chen u64 index; 983c29dd8c4SJoseph Chen int ret; 984c29dd8c4SJoseph Chen 985c29dd8c4SJoseph Chen ret = trusty_read_rollback_index(FIT_ROLLBACK_INDEX_LOCATION, &index); 986c29dd8c4SJoseph Chen if (ret) { 987c29dd8c4SJoseph Chen if (ret != TEE_ERROR_ITEM_NOT_FOUND) 988c29dd8c4SJoseph Chen return ret; 989c29dd8c4SJoseph Chen 990ee7b0fb8SJason Zhu index = 0; 991c29dd8c4SJoseph Chen printf("Initial otp index as %d\n", fit_index); 992bcec4579SZain Wang } 993ee7b0fb8SJason Zhu 994ee7b0fb8SJason Zhu *otp_index = (uint32_t)index; 995c29dd8c4SJoseph Chen #else 996c29dd8c4SJoseph Chen *otp_index = 0; 997c29dd8c4SJoseph Chen #endif 998c29dd8c4SJoseph Chen 999c29dd8c4SJoseph Chen return 0; 1000c29dd8c4SJoseph Chen } 1001c29dd8c4SJoseph Chen 1002e9f9d90dSJoseph Chen int fit_write_trusty_rollback_index(u32 trusty_index) 1003c29dd8c4SJoseph Chen { 1004c29dd8c4SJoseph Chen if (!trusty_index) 1005c29dd8c4SJoseph Chen return 0; 1006b4a3d48eSJoseph Chen #ifdef CONFIG_OPTEE_CLIENT 10078d26d4b3SJoseph Chen return trusty_write_rollback_index(FIT_ROLLBACK_INDEX_LOCATION, 1008c29dd8c4SJoseph Chen (u64)trusty_index); 1009b4a3d48eSJoseph Chen #else 1010b4a3d48eSJoseph Chen return 0; 1011b4a3d48eSJoseph Chen #endif 1012c29dd8c4SJoseph Chen } 1013c29dd8c4SJoseph Chen #endif 1014c29dd8c4SJoseph Chen 1015189c0d68SJoseph Chen void board_quiesce_devices(void *images) 1016189c0d68SJoseph Chen { 1017189c0d68SJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS 1018189c0d68SJoseph Chen /* Destroy atags makes next warm boot safer */ 1019189c0d68SJoseph Chen atags_destroy(); 1020189c0d68SJoseph Chen #endif 1021189c0d68SJoseph Chen #ifdef CONFIG_FIT_ROLLBACK_PROTECT 10228d26d4b3SJoseph Chen int ret; 10238d26d4b3SJoseph Chen 10248d26d4b3SJoseph Chen ret = fit_write_trusty_rollback_index(gd->rollback_index); 10258d26d4b3SJoseph Chen if (ret) { 10268d26d4b3SJoseph Chen panic("Failed to write fit rollback index %d, ret=%d", 10278d26d4b3SJoseph Chen gd->rollback_index, ret); 10288d26d4b3SJoseph Chen } 1029189c0d68SJoseph Chen #endif 1030a5401a9dSJoseph Chen #ifdef CONFIG_ROCKCHIP_HW_DECOMPRESS 1031a5401a9dSJoseph Chen misc_decompress_cleanup(); 1032a5401a9dSJoseph Chen #endif 1033c3515b67SJoseph Chen #ifdef CONFIG_ARM64 1034c3515b67SJoseph Chen bootm_headers_t *bootm_images = (bootm_headers_t *)images; 1035c3515b67SJoseph Chen ulong kernel_addr; 1036c3515b67SJoseph Chen 1037b627269dSJoseph Chen /* relocate kernel after decompress cleanup */ 1038b627269dSJoseph Chen kernel_addr = env_get_ulong("kernel_addr_r", 16, 0); 1039b627269dSJoseph Chen if (kernel_addr != bootm_images->ep) { 1040b627269dSJoseph Chen memmove((char *)bootm_images->ep, (const char *)kernel_addr, 1041b627269dSJoseph Chen bootm_images->os.image_len); 1042b627269dSJoseph Chen printf("== DO RELOCATE == Kernel from 0x%08lx to 0x%08lx\n", 1043b627269dSJoseph Chen kernel_addr, bootm_images->ep); 1044b627269dSJoseph Chen } 1045c3515b67SJoseph Chen #endif 1046b627269dSJoseph Chen 1047b627269dSJoseph Chen hotkey_run(HK_CMDLINE); 1048b627269dSJoseph Chen hotkey_run(HK_CLI_OS_GO); 1049b627269dSJoseph Chen #ifdef CONFIG_ROCKCHIP_REBOOT_TEST 1050b627269dSJoseph Chen do_reset(NULL, 0, 0, NULL); 1051b627269dSJoseph Chen #endif 1052189c0d68SJoseph Chen } 1053d87d5275SJoseph Chen 1054d87d5275SJoseph Chen char *board_fdt_chosen_bootargs(void *fdt) 1055d87d5275SJoseph Chen { 1056d87d5275SJoseph Chen /* bootargs_ext is used when dtbo is applied. */ 1057d87d5275SJoseph Chen const char *arr_bootargs[] = { "bootargs", "bootargs_ext" }; 1058d87d5275SJoseph Chen const char *bootargs; 1059d87d5275SJoseph Chen int nodeoffset; 1060d87d5275SJoseph Chen int i, dump; 10610de7ff3bSJoseph Chen char *msg = "kernel"; 1062d87d5275SJoseph Chen 1063d87d5275SJoseph Chen /* debug */ 1064d87d5275SJoseph Chen hotkey_run(HK_INITCALL); 1065d87d5275SJoseph Chen dump = is_hotkey(HK_CMDLINE); 1066d87d5275SJoseph Chen if (dump) 1067d87d5275SJoseph Chen printf("## bootargs(u-boot): %s\n\n", env_get("bootargs")); 1068d87d5275SJoseph Chen 1069d87d5275SJoseph Chen /* find or create "/chosen" node. */ 1070d87d5275SJoseph Chen nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen"); 1071d87d5275SJoseph Chen if (nodeoffset < 0) 1072d87d5275SJoseph Chen return NULL; 1073d87d5275SJoseph Chen 1074d87d5275SJoseph Chen for (i = 0; i < ARRAY_SIZE(arr_bootargs); i++) { 1075d87d5275SJoseph Chen bootargs = fdt_getprop(fdt, nodeoffset, arr_bootargs[i], NULL); 1076d87d5275SJoseph Chen if (!bootargs) 1077d87d5275SJoseph Chen continue; 1078d87d5275SJoseph Chen if (dump) 10790de7ff3bSJoseph Chen printf("## bootargs(%s-%s): %s\n\n", 10800de7ff3bSJoseph Chen msg, arr_bootargs[i], bootargs); 1081d87d5275SJoseph Chen /* 1082d87d5275SJoseph Chen * Append kernel bootargs 1083d87d5275SJoseph Chen * If use AB system, delete default "root=" which route 1084d87d5275SJoseph Chen * to rootfs. Then the ab bootctl will choose the 1085d87d5275SJoseph Chen * high priority system to boot and add its UUID 1086d87d5275SJoseph Chen * to cmdline. The format is "roo=PARTUUID=xxxx...". 1087d87d5275SJoseph Chen */ 1088d87d5275SJoseph Chen #ifdef CONFIG_ANDROID_AB 1089d87d5275SJoseph Chen env_update_filter("bootargs", bootargs, "root="); 1090d87d5275SJoseph Chen #else 1091d87d5275SJoseph Chen env_update("bootargs", bootargs); 1092d87d5275SJoseph Chen #endif 1093d87d5275SJoseph Chen } 1094d87d5275SJoseph Chen 1095bdb740d4SJoseph Chen #ifdef CONFIG_ENVF 1096bdb740d4SJoseph Chen char * sys_bootargs; 1097bdb740d4SJoseph Chen 1098bdb740d4SJoseph Chen sys_bootargs = env_get("sys_bootargs"); 1099bdb740d4SJoseph Chen if (sys_bootargs) { 1100bdb740d4SJoseph Chen env_update("bootargs", sys_bootargs); 1101bdb740d4SJoseph Chen if (dump) 1102bdb740d4SJoseph Chen printf("## sys_bootargs: %s\n\n", sys_bootargs); 1103bdb740d4SJoseph Chen } 1104bdb740d4SJoseph Chen #endif 1105d87d5275SJoseph Chen #ifdef CONFIG_MTD_BLK 1106bdb740d4SJoseph Chen if (!env_get("mtdparts")) { 1107d87d5275SJoseph Chen char *mtd_par_info = mtd_part_parse(NULL); 1108d87d5275SJoseph Chen 1109d87d5275SJoseph Chen if (mtd_par_info) { 1110d87d5275SJoseph Chen if (memcmp(env_get("devtype"), "mtd", 3) == 0) 1111d87d5275SJoseph Chen env_update("bootargs", mtd_par_info); 1112d87d5275SJoseph Chen } 1113bdb740d4SJoseph Chen } 1114d87d5275SJoseph Chen #endif 1115d87d5275SJoseph Chen /* 1116d87d5275SJoseph Chen * Initrd fixup: remove unused "initrd=0x...,0x...", 1117d87d5275SJoseph Chen * this for compatible with legacy parameter.txt 1118d87d5275SJoseph Chen */ 1119d87d5275SJoseph Chen env_delete("bootargs", "initrd=", 0); 1120d87d5275SJoseph Chen 1121d87d5275SJoseph Chen /* 1122d87d5275SJoseph Chen * If uart is required to be disabled during 1123d87d5275SJoseph Chen * power on, it would be not initialized by 1124d87d5275SJoseph Chen * any pre-loader and U-Boot. 1125d87d5275SJoseph Chen * 1126d87d5275SJoseph Chen * If we don't remove earlycon from commandline, 1127d87d5275SJoseph Chen * kernel hangs while using earlycon to putc/getc 1128d87d5275SJoseph Chen * which may dead loop for waiting uart status. 1129d87d5275SJoseph Chen * (It seems the root cause is baundrate is not 1130d87d5275SJoseph Chen * initilalized) 1131d87d5275SJoseph Chen * 1132d87d5275SJoseph Chen * So let's remove earlycon from commandline. 1133d87d5275SJoseph Chen */ 1134d87d5275SJoseph Chen if (gd->flags & GD_FLG_DISABLE_CONSOLE) 1135d87d5275SJoseph Chen env_delete("bootargs", "earlycon=", 0); 1136d87d5275SJoseph Chen 11371761a533SJoseph Chen /* Android header v4+ need this handle */ 11381761a533SJoseph Chen #ifdef CONFIG_ANDROID_BOOT_IMAGE 11391761a533SJoseph Chen struct andr_img_hdr *hdr; 11401761a533SJoseph Chen 11411761a533SJoseph Chen hdr = (void *)env_get_ulong("android_addr_r", 16, 0); 11421761a533SJoseph Chen if (hdr && !android_image_check_header(hdr) && hdr->header_version >= 4) { 11431761a533SJoseph Chen if (env_update_extract_subset("bootargs", "andr_bootargs", "androidboot.")) 11441761a533SJoseph Chen printf("extract androidboot.xxx error\n"); 11451761a533SJoseph Chen if (dump) 11461761a533SJoseph Chen printf("## bootargs(android): %s\n\n", env_get("andr_bootargs")); 11471761a533SJoseph Chen } 11481761a533SJoseph Chen #endif 1149d87d5275SJoseph Chen bootargs = env_get("bootargs"); 1150d87d5275SJoseph Chen if (dump) 1151d87d5275SJoseph Chen printf("## bootargs(merged): %s\n\n", bootargs); 1152d87d5275SJoseph Chen 1153d87d5275SJoseph Chen return (char *)bootargs; 1154d87d5275SJoseph Chen } 1155d87d5275SJoseph Chen 11561761a533SJoseph Chen int ft_verify_fdt(void *fdt) 11571761a533SJoseph Chen { 11581761a533SJoseph Chen /* for android header v4+, we load bootparams and fixup initrd */ 11591761a533SJoseph Chen #if defined(CONFIG_ANDROID_BOOT_IMAGE) && defined(CONFIG_XBC) 11601761a533SJoseph Chen struct andr_img_hdr *hdr; 11611761a533SJoseph Chen uint64_t initrd_start, initrd_end; 11621761a533SJoseph Chen char *bootargs, *p; 11631761a533SJoseph Chen int nodeoffset; 11641761a533SJoseph Chen int is_u64, err; 11651761a533SJoseph Chen u32 len; 11661761a533SJoseph Chen 11671761a533SJoseph Chen hdr = (void *)env_get_ulong("android_addr_r", 16, 0); 11681761a533SJoseph Chen if (!hdr || android_image_check_header(hdr) || 11691761a533SJoseph Chen hdr->header_version < 4) 11701761a533SJoseph Chen return 1; 11711761a533SJoseph Chen 11721761a533SJoseph Chen bootargs = env_get("andr_bootargs"); 11731761a533SJoseph Chen if (!bootargs) 11741761a533SJoseph Chen return 1; 11751761a533SJoseph Chen 11761761a533SJoseph Chen /* trans character: space to new line */ 11771761a533SJoseph Chen p = bootargs; 11781761a533SJoseph Chen while (*p++) { 11791761a533SJoseph Chen if (*p == ' ') 11801761a533SJoseph Chen *p = '\n'; 11811761a533SJoseph Chen } 11821761a533SJoseph Chen 11831761a533SJoseph Chen debug("## andr_bootargs: %s\n", bootargs); 11841761a533SJoseph Chen 11851761a533SJoseph Chen /* 11861761a533SJoseph Chen * add boot params right after bootconfig 11871761a533SJoseph Chen * 11881761a533SJoseph Chen * because we can get final full bootargs in board_fdt_chosen_bootargs(), 11891761a533SJoseph Chen * android_image_get_ramdisk() is early than that. 11901761a533SJoseph Chen * 11911761a533SJoseph Chen * we have to add boot params by now. 11921761a533SJoseph Chen */ 11931761a533SJoseph Chen len = addBootConfigParameters((char *)bootargs, strlen(bootargs), 11941761a533SJoseph Chen (u64)hdr->ramdisk_addr + hdr->ramdisk_size + 11951761a533SJoseph Chen hdr->vendor_ramdisk_size, hdr->vendor_bootconfig_size); 11961761a533SJoseph Chen if (len < 0) { 11971761a533SJoseph Chen printf("error: addBootConfigParameters\n"); 11981761a533SJoseph Chen return 0; 11991761a533SJoseph Chen } 12001761a533SJoseph Chen 12011761a533SJoseph Chen nodeoffset = fdt_subnode_offset(fdt, 0, "chosen"); 12021761a533SJoseph Chen if (nodeoffset < 0) { 12031761a533SJoseph Chen printf("error: No /chosen node\n"); 12041761a533SJoseph Chen return 0; 12051761a533SJoseph Chen } 12061761a533SJoseph Chen 12071761a533SJoseph Chen /* fixup initrd with real value */ 12081761a533SJoseph Chen fdt_delprop(fdt, nodeoffset, "linux,initrd-start"); 12091761a533SJoseph Chen fdt_delprop(fdt, nodeoffset, "linux,initrd-end"); 12101761a533SJoseph Chen 12111761a533SJoseph Chen is_u64 = (fdt_address_cells(fdt, 0) == 2); 12121761a533SJoseph Chen initrd_start = hdr->ramdisk_addr; 12131761a533SJoseph Chen initrd_end = initrd_start + hdr->ramdisk_size + 12141761a533SJoseph Chen hdr->vendor_ramdisk_size + 12151761a533SJoseph Chen hdr->vendor_bootconfig_size + len; 12161761a533SJoseph Chen err = fdt_setprop_uxx(fdt, nodeoffset, "linux,initrd-start", 12171761a533SJoseph Chen initrd_start, is_u64); 12181761a533SJoseph Chen if (err < 0) { 12191761a533SJoseph Chen printf("WARNING: could not set linux,initrd-start %s.\n", 12201761a533SJoseph Chen fdt_strerror(err)); 12211761a533SJoseph Chen return 0; 12221761a533SJoseph Chen } 12231761a533SJoseph Chen err = fdt_setprop_uxx(fdt, nodeoffset, "linux,initrd-end", 12241761a533SJoseph Chen initrd_end, is_u64); 12251761a533SJoseph Chen if (err < 0) { 12261761a533SJoseph Chen printf("WARNING: could not set linux,initrd-end %s.\n", 12271761a533SJoseph Chen fdt_strerror(err)); 12281761a533SJoseph Chen return 0; 12291761a533SJoseph Chen } 12301761a533SJoseph Chen #endif 12311761a533SJoseph Chen return 1; 12321761a533SJoseph Chen } 12331761a533SJoseph Chen 1234