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