xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/board.c (revision 5d5f363eb95cd5fd79b5a928cfdfd76b37add5ba)
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>
986f870d6SJoseph Chen #include <bidram.h>
100ed06f16SJoseph Chen #include <boot_rkimg.h>
110ed06f16SJoseph Chen #include <cli.h>
122208cd92SJoseph Chen #include <clk.h>
132208cd92SJoseph Chen #include <console.h>
14575777c5SKever Yang #include <debug_uart.h>
152208cd92SJoseph Chen #include <dm.h>
162208cd92SJoseph Chen #include <dvfs.h>
172208cd92SJoseph Chen #include <io-domain.h>
187397b961SJoseph Chen #include <key.h>
1986f870d6SJoseph Chen #include <memblk.h>
202208cd92SJoseph Chen #include <misc.h>
212208cd92SJoseph Chen #include <of_live.h>
2238771996SKever Yang #include <ram.h>
232208cd92SJoseph Chen #include <rockchip_debugger.h>
2438771996SKever Yang #include <syscon.h>
256929f85bSJoseph Chen #include <sysmem.h>
262208cd92SJoseph Chen #include <video_rockchip.h>
2738771996SKever Yang #include <asm/io.h>
2838771996SKever Yang #include <asm/gpio.h>
293e45175eSJoseph Chen #include <dm/uclass-internal.h>
302208cd92SJoseph Chen #include <dm/root.h>
312208cd92SJoseph Chen #include <power/charge_display.h>
322208cd92SJoseph Chen #include <power/regulator.h>
332208cd92SJoseph Chen #include <asm/arch/boot_mode.h>
3438771996SKever Yang #include <asm/arch/clock.h>
3560ea26bdSJoseph Chen #include <asm/arch/cpu.h>
36c664909eSJoseph Chen #include <asm/arch/hotkey.h>
376929f85bSJoseph Chen #include <asm/arch/param.h>
382208cd92SJoseph Chen #include <asm/arch/periph.h>
392208cd92SJoseph Chen #include <asm/arch/resource_img.h>
402208cd92SJoseph Chen #include <asm/arch/rk_atags.h>
412208cd92SJoseph Chen #include <asm/arch/vendor.h>
4238771996SKever Yang 
4338771996SKever Yang DECLARE_GLOBAL_DATA_PTR;
4438771996SKever Yang 
4538771996SKever Yang __weak int rk_board_late_init(void)
4638771996SKever Yang {
4738771996SKever Yang 	return 0;
4838771996SKever Yang }
4938771996SKever Yang 
5038ce6261SJoseph Chen __weak int rk_board_fdt_fixup(void *blob)
5138ce6261SJoseph Chen {
5238ce6261SJoseph Chen 	return 0;
5338ce6261SJoseph Chen }
5438ce6261SJoseph Chen 
55efdbac34SFinley Xiao __weak int soc_clk_dump(void)
56efdbac34SFinley Xiao {
57efdbac34SFinley Xiao 	return 0;
58efdbac34SFinley Xiao }
59efdbac34SFinley Xiao 
60058e5d94SFinley Xiao __weak int set_armclk_rate(void)
61058e5d94SFinley Xiao {
62058e5d94SFinley Xiao 	return 0;
63058e5d94SFinley Xiao }
64058e5d94SFinley Xiao 
652208cd92SJoseph Chen __weak int rk_board_init(void)
662208cd92SJoseph Chen {
672208cd92SJoseph Chen 	return 0;
682208cd92SJoseph Chen }
692208cd92SJoseph Chen 
702208cd92SJoseph Chen /*
712208cd92SJoseph Chen  * define serialno max length, the max length is 512 Bytes
722208cd92SJoseph Chen  * The remaining bytes are used to ensure that the first 512 bytes
732208cd92SJoseph Chen  * are valid when executing 'env_set("serial#", value)'.
742208cd92SJoseph Chen  */
752208cd92SJoseph Chen #define VENDOR_SN_MAX	513
762208cd92SJoseph Chen #define CPUID_LEN	0x10
772208cd92SJoseph Chen #define CPUID_OFF	0x07
782208cd92SJoseph Chen 
792208cd92SJoseph Chen static int rockchip_set_ethaddr(void)
802208cd92SJoseph Chen {
812208cd92SJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION
822208cd92SJoseph Chen 	char buf[ARP_HLEN_ASCII + 1];
832208cd92SJoseph Chen 	u8 ethaddr[ARP_HLEN];
842208cd92SJoseph Chen 	int ret;
852208cd92SJoseph Chen 
862208cd92SJoseph Chen 	ret = vendor_storage_read(VENDOR_LAN_MAC_ID, ethaddr, sizeof(ethaddr));
872208cd92SJoseph Chen 	if (ret > 0 && is_valid_ethaddr(ethaddr)) {
882208cd92SJoseph Chen 		sprintf(buf, "%pM", ethaddr);
892208cd92SJoseph Chen 		env_set("ethaddr", buf);
902208cd92SJoseph Chen 	}
912208cd92SJoseph Chen #endif
922208cd92SJoseph Chen 	return 0;
932208cd92SJoseph Chen }
942208cd92SJoseph Chen 
952208cd92SJoseph Chen static int rockchip_set_serialno(void)
962208cd92SJoseph Chen {
972208cd92SJoseph Chen 	u8 low[CPUID_LEN / 2], high[CPUID_LEN / 2];
982208cd92SJoseph Chen 	u8 cpuid[CPUID_LEN] = {0};
992208cd92SJoseph Chen 	char serialno_str[VENDOR_SN_MAX];
1002208cd92SJoseph Chen 	int ret = 0, i;
1012208cd92SJoseph Chen 	u64 serialno;
1022208cd92SJoseph Chen 
1032208cd92SJoseph Chen 	/* Read serial number from vendor storage part */
1042208cd92SJoseph Chen 	memset(serialno_str, 0, VENDOR_SN_MAX);
1052208cd92SJoseph Chen 
1062208cd92SJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION
1072208cd92SJoseph Chen 	ret = vendor_storage_read(VENDOR_SN_ID, serialno_str, (VENDOR_SN_MAX-1));
1082208cd92SJoseph Chen 	if (ret > 0) {
1092208cd92SJoseph Chen 		env_set("serial#", serialno_str);
1102208cd92SJoseph Chen 	} else {
1112208cd92SJoseph Chen #endif
1122208cd92SJoseph Chen #ifdef CONFIG_ROCKCHIP_EFUSE
1132208cd92SJoseph Chen 		struct udevice *dev;
1142208cd92SJoseph Chen 
1152208cd92SJoseph Chen 		/* retrieve the device */
1162208cd92SJoseph Chen 		ret = uclass_get_device_by_driver(UCLASS_MISC,
1172208cd92SJoseph Chen 						  DM_GET_DRIVER(rockchip_efuse),
1182208cd92SJoseph Chen 						  &dev);
1192208cd92SJoseph Chen 		if (ret) {
1202208cd92SJoseph Chen 			printf("%s: could not find efuse device\n", __func__);
1212208cd92SJoseph Chen 			return ret;
1222208cd92SJoseph Chen 		}
1232208cd92SJoseph Chen 
1242208cd92SJoseph Chen 		/* read the cpu_id range from the efuses */
1252208cd92SJoseph Chen 		ret = misc_read(dev, CPUID_OFF, &cpuid, sizeof(cpuid));
1262208cd92SJoseph Chen 		if (ret) {
1272208cd92SJoseph Chen 			printf("%s: read cpuid from efuses failed, ret=%d\n",
1282208cd92SJoseph Chen 			       __func__, ret);
1292208cd92SJoseph Chen 			return ret;
1302208cd92SJoseph Chen 		}
1312208cd92SJoseph Chen #else
1322208cd92SJoseph Chen 		/* generate random cpuid */
1332208cd92SJoseph Chen 		for (i = 0; i < CPUID_LEN; i++)
1342208cd92SJoseph Chen 			cpuid[i] = (u8)(rand());
1352208cd92SJoseph Chen #endif
1362208cd92SJoseph Chen 		/* Generate the serial number based on CPU ID */
1372208cd92SJoseph Chen 		for (i = 0; i < 8; i++) {
1382208cd92SJoseph Chen 			low[i] = cpuid[1 + (i << 1)];
1392208cd92SJoseph Chen 			high[i] = cpuid[i << 1];
1402208cd92SJoseph Chen 		}
1412208cd92SJoseph Chen 
1422208cd92SJoseph Chen 		serialno = crc32_no_comp(0, low, 8);
1432208cd92SJoseph Chen 		serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32;
1442208cd92SJoseph Chen 		snprintf(serialno_str, sizeof(serialno_str), "%llx", serialno);
1452208cd92SJoseph Chen 
1462208cd92SJoseph Chen 		env_set("serial#", serialno_str);
1472208cd92SJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION
1482208cd92SJoseph Chen 	}
1492208cd92SJoseph Chen #endif
1502208cd92SJoseph Chen 
1512208cd92SJoseph Chen 	return ret;
1522208cd92SJoseph Chen }
1532208cd92SJoseph Chen 
1542208cd92SJoseph Chen #if defined(CONFIG_USB_FUNCTION_FASTBOOT)
1552208cd92SJoseph Chen int fb_set_reboot_flag(void)
1562208cd92SJoseph Chen {
1572208cd92SJoseph Chen 	printf("Setting reboot to fastboot flag ...\n");
1582208cd92SJoseph Chen 	writel(BOOT_FASTBOOT, CONFIG_ROCKCHIP_BOOT_MODE_REG);
1592208cd92SJoseph Chen 
1602208cd92SJoseph Chen 	return 0;
1612208cd92SJoseph Chen }
1622208cd92SJoseph Chen #endif
1632208cd92SJoseph Chen 
1640ed06f16SJoseph Chen #ifdef CONFIG_ROCKCHIP_USB_BOOT
1650ed06f16SJoseph Chen static int boot_from_udisk(void)
1660ed06f16SJoseph Chen {
1670ed06f16SJoseph Chen 	struct blk_desc *desc;
1680ed06f16SJoseph Chen 	char *devtype;
1690ed06f16SJoseph Chen 	char *devnum;
1700ed06f16SJoseph Chen 
1710ed06f16SJoseph Chen 	devtype = env_get("devtype");
1720ed06f16SJoseph Chen 	devnum = env_get("devnum");
1730ed06f16SJoseph Chen 
1740ed06f16SJoseph Chen 	/* Booting priority: mmc1 > udisk */
1750ed06f16SJoseph Chen 	if (!strcmp(devtype, "mmc") && !strcmp(devnum, "1"))
1760ed06f16SJoseph Chen 		return 0;
1770ed06f16SJoseph Chen 
1780ed06f16SJoseph Chen 	if (!run_command("usb start", -1)) {
1790ed06f16SJoseph Chen 		desc = blk_get_devnum_by_type(IF_TYPE_USB, 0);
1800ed06f16SJoseph Chen 		if (!desc) {
1810ed06f16SJoseph Chen 			printf("No usb device found\n");
1820ed06f16SJoseph Chen 			return -ENODEV;
1830ed06f16SJoseph Chen 		}
1840ed06f16SJoseph Chen 
1850ed06f16SJoseph Chen 		if (!run_command("rkimgtest usb 0", -1)) {
1860ed06f16SJoseph Chen 			rockchip_set_bootdev(desc);
1870ed06f16SJoseph Chen 			env_set("devtype", "usb");
1880ed06f16SJoseph Chen 			env_set("devnum", "0");
1890ed06f16SJoseph Chen 			printf("Boot from usb 0\n");
1900ed06f16SJoseph Chen 		} else {
1910ed06f16SJoseph Chen 			printf("No usb dev 0 found\n");
1920ed06f16SJoseph Chen 			return -ENODEV;
1930ed06f16SJoseph Chen 		}
1940ed06f16SJoseph Chen 	}
1950ed06f16SJoseph Chen 
1960ed06f16SJoseph Chen 	return 0;
1970ed06f16SJoseph Chen }
1980ed06f16SJoseph Chen #endif
1990ed06f16SJoseph Chen 
20083c9bd4bSJoseph Chen static void cmdline_handle(void)
20183c9bd4bSJoseph Chen {
20283c9bd4bSJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
20383c9bd4bSJoseph Chen 	struct tag *t;
20483c9bd4bSJoseph Chen 
20583c9bd4bSJoseph Chen 	t = atags_get_tag(ATAG_PUB_KEY);
20683c9bd4bSJoseph Chen 	if (t) {
20783c9bd4bSJoseph Chen 		/* Pass if efuse/otp programmed */
20883c9bd4bSJoseph Chen 		if (t->u.pub_key.flag == PUBKEY_FUSE_PROGRAMMED)
20983c9bd4bSJoseph Chen 			env_update("bootargs", "fuse.programmed=1");
21083c9bd4bSJoseph Chen 		else
21183c9bd4bSJoseph Chen 			env_update("bootargs", "fuse.programmed=0");
21283c9bd4bSJoseph Chen 	}
21383c9bd4bSJoseph Chen #endif
21483c9bd4bSJoseph Chen }
21583c9bd4bSJoseph Chen 
21638771996SKever Yang int board_late_init(void)
21738771996SKever Yang {
2182549364dSlanshh 	rockchip_set_ethaddr();
219fc1a5563SJason Zhu 	rockchip_set_serialno();
22038771996SKever Yang #if (CONFIG_ROCKCHIP_BOOT_MODE_REG > 0)
22138771996SKever Yang 	setup_boot_mode();
22238771996SKever Yang #endif
2230ed06f16SJoseph Chen #ifdef CONFIG_ROCKCHIP_USB_BOOT
2240ed06f16SJoseph Chen 	boot_from_udisk();
2250ed06f16SJoseph Chen #endif
22638771996SKever Yang #ifdef CONFIG_DM_CHARGE_DISPLAY
22738771996SKever Yang 	charge_display();
22838771996SKever Yang #endif
22938771996SKever Yang #ifdef CONFIG_DRM_ROCKCHIP
23038771996SKever Yang 	rockchip_show_logo();
23138771996SKever Yang #endif
232efdbac34SFinley Xiao 	soc_clk_dump();
23383c9bd4bSJoseph Chen 	cmdline_handle();
234efdbac34SFinley Xiao 
23538771996SKever Yang 	return rk_board_late_init();
23638771996SKever Yang }
23738771996SKever Yang 
238f8aaa2c2SKever Yang #ifdef CONFIG_USING_KERNEL_DTB
2393e45175eSJoseph Chen /* Here, only fixup cru phandle, pmucru is not included */
2409f8dc175SJoseph Chen static int phandles_fixup_cru(void *fdt)
2413e45175eSJoseph Chen {
2423e45175eSJoseph Chen 	const char *props[] = { "clocks", "assigned-clocks" };
2433e45175eSJoseph Chen 	struct udevice *dev;
2443e45175eSJoseph Chen 	struct uclass *uc;
2453e45175eSJoseph Chen 	const char *comp;
2463e45175eSJoseph Chen 	u32 id, nclocks;
2473e45175eSJoseph Chen 	u32 *clocks;
2483e45175eSJoseph Chen 	int phandle, ncells;
2493e45175eSJoseph Chen 	int off, offset;
2503e45175eSJoseph Chen 	int ret, length;
2513e45175eSJoseph Chen 	int i, j;
2523e45175eSJoseph Chen 	int first_phandle = -1;
2533e45175eSJoseph Chen 
2543e45175eSJoseph Chen 	phandle = -ENODATA;
2553e45175eSJoseph Chen 	ncells = -ENODATA;
2563e45175eSJoseph Chen 
2573e45175eSJoseph Chen 	/* fdt points to kernel dtb, getting cru phandle and "#clock-cells" */
2583e45175eSJoseph Chen 	for (offset = fdt_next_node(fdt, 0, NULL);
2593e45175eSJoseph Chen 	     offset >= 0;
2603e45175eSJoseph Chen 	     offset = fdt_next_node(fdt, offset, NULL)) {
2613e45175eSJoseph Chen 		comp = fdt_getprop(fdt, offset, "compatible", NULL);
2623e45175eSJoseph Chen 		if (!comp)
2633e45175eSJoseph Chen 			continue;
2643e45175eSJoseph Chen 
2653e45175eSJoseph Chen 		/* Actually, this is not a good method to get cru node */
2663e45175eSJoseph Chen 		off = strlen(comp) - strlen("-cru");
2673e45175eSJoseph Chen 		if (off > 0 && !strncmp(comp + off, "-cru", 4)) {
2683e45175eSJoseph Chen 			phandle = fdt_get_phandle(fdt, offset);
2693e45175eSJoseph Chen 			ncells = fdtdec_get_int(fdt, offset,
2703e45175eSJoseph Chen 						"#clock-cells", -ENODATA);
2713e45175eSJoseph Chen 			break;
2723e45175eSJoseph Chen 		}
2733e45175eSJoseph Chen 	}
2743e45175eSJoseph Chen 
2753e45175eSJoseph Chen 	if (phandle == -ENODATA || ncells == -ENODATA)
2763e45175eSJoseph Chen 		return 0;
2773e45175eSJoseph Chen 
2783e45175eSJoseph Chen 	debug("%s: target cru: clock-cells:%d, phandle:0x%x\n",
2793e45175eSJoseph Chen 	      __func__, ncells, fdt32_to_cpu(phandle));
2803e45175eSJoseph Chen 
2813e45175eSJoseph Chen 	/* Try to fixup all cru phandle from U-Boot dtb nodes */
2823e45175eSJoseph Chen 	for (id = 0; id < UCLASS_COUNT; id++) {
2833e45175eSJoseph Chen 		ret = uclass_get(id, &uc);
2843e45175eSJoseph Chen 		if (ret)
2853e45175eSJoseph Chen 			continue;
2863e45175eSJoseph Chen 
2873e45175eSJoseph Chen 		if (list_empty(&uc->dev_head))
2883e45175eSJoseph Chen 			continue;
2893e45175eSJoseph Chen 
2903e45175eSJoseph Chen 		list_for_each_entry(dev, &uc->dev_head, uclass_node) {
2913e45175eSJoseph Chen 			/* Only U-Boot node go further */
292d625acc2SJoseph Chen 			if (!dev_read_bool(dev, "u-boot,dm-pre-reloc") &&
2932a5ad8b3SJoseph Chen 			    !dev_read_bool(dev, "u-boot,dm-spl"))
2943e45175eSJoseph Chen 				continue;
2953e45175eSJoseph Chen 
2963e45175eSJoseph Chen 			for (i = 0; i < ARRAY_SIZE(props); i++) {
2973e45175eSJoseph Chen 				if (!dev_read_prop(dev, props[i], &length))
2983e45175eSJoseph Chen 					continue;
2993e45175eSJoseph Chen 
3003e45175eSJoseph Chen 				clocks = malloc(length);
3013e45175eSJoseph Chen 				if (!clocks)
3023e45175eSJoseph Chen 					return -ENOMEM;
3033e45175eSJoseph Chen 
3043e45175eSJoseph Chen 				/* Read "props[]" which contains cru phandle */
3053e45175eSJoseph Chen 				nclocks = length / sizeof(u32);
3063e45175eSJoseph Chen 				if (dev_read_u32_array(dev, props[i],
3073e45175eSJoseph Chen 						       clocks, nclocks)) {
3083e45175eSJoseph Chen 					free(clocks);
3093e45175eSJoseph Chen 					continue;
3103e45175eSJoseph Chen 				}
3113e45175eSJoseph Chen 
3123e45175eSJoseph Chen 				/* Fixup with kernel cru phandle */
3133e45175eSJoseph Chen 				for (j = 0; j < nclocks; j += (ncells + 1)) {
3143e45175eSJoseph Chen 					/*
3153e45175eSJoseph Chen 					 * Check: update pmucru phandle with cru
3163e45175eSJoseph Chen 					 * phandle by mistake.
3173e45175eSJoseph Chen 					 */
3183e45175eSJoseph Chen 					if (first_phandle == -1)
3193e45175eSJoseph Chen 						first_phandle = clocks[j];
3203e45175eSJoseph Chen 
3218526ae77SJoseph Chen 					if (clocks[j] != first_phandle) {
3228526ae77SJoseph Chen 						debug("WARN: %s: first cru phandle=%d, this=%d\n",
3233e45175eSJoseph Chen 						      dev_read_name(dev),
3243e45175eSJoseph Chen 						      first_phandle, clocks[j]);
3258526ae77SJoseph Chen 						continue;
3268526ae77SJoseph Chen 					}
3273e45175eSJoseph Chen 
3283e45175eSJoseph Chen 					clocks[j] = phandle;
3293e45175eSJoseph Chen 				}
3303e45175eSJoseph Chen 
3313e45175eSJoseph Chen 				/*
3323e45175eSJoseph Chen 				 * Override live dt nodes but not fdt nodes,
3333e45175eSJoseph Chen 				 * because all U-Boot nodes has been imported
3343e45175eSJoseph Chen 				 * to live dt nodes, should use "dev_xxx()".
3353e45175eSJoseph Chen 				 */
3363e45175eSJoseph Chen 				dev_write_u32_array(dev, props[i],
3373e45175eSJoseph Chen 						    clocks, nclocks);
3383e45175eSJoseph Chen 				free(clocks);
3393e45175eSJoseph Chen 			}
3403e45175eSJoseph Chen 		}
3413e45175eSJoseph Chen 	}
3423e45175eSJoseph Chen 
3433e45175eSJoseph Chen 	return 0;
3443e45175eSJoseph Chen }
3453e45175eSJoseph Chen 
3469f8dc175SJoseph Chen static int phandles_fixup_gpio(void *fdt, void *ufdt)
3479f8dc175SJoseph Chen {
3489f8dc175SJoseph Chen 	struct udevice *dev;
3499f8dc175SJoseph Chen 	struct uclass *uc;
3509f8dc175SJoseph Chen 	const char *prop = "gpios";
3519f8dc175SJoseph Chen 	const char *comp;
3529f8dc175SJoseph Chen 	char *gpio_name[10];
3539f8dc175SJoseph Chen 	int gpio_off[10];
3549f8dc175SJoseph Chen 	int pinctrl;
3559f8dc175SJoseph Chen 	int offset;
3569f8dc175SJoseph Chen 	int i = 0;
3579f8dc175SJoseph Chen 	int n = 0;
3589f8dc175SJoseph Chen 
3599f8dc175SJoseph Chen 	pinctrl = fdt_path_offset(fdt, "/pinctrl");
3609f8dc175SJoseph Chen 	if (pinctrl < 0)
3619f8dc175SJoseph Chen 		return 0;
3629f8dc175SJoseph Chen 
3639f8dc175SJoseph Chen 	memset(gpio_name, 0, sizeof(gpio_name));
3649f8dc175SJoseph Chen 	for (offset = fdt_first_subnode(fdt, pinctrl);
3659f8dc175SJoseph Chen 	     offset >= 0;
3669f8dc175SJoseph Chen 	     offset = fdt_next_subnode(fdt, offset)) {
3679f8dc175SJoseph Chen 		/* assume the font nodes are gpio node */
3689f8dc175SJoseph Chen 		if (++i >= ARRAY_SIZE(gpio_name))
3699f8dc175SJoseph Chen 			break;
3709f8dc175SJoseph Chen 
3719f8dc175SJoseph Chen 		comp = fdt_getprop(fdt, offset, "compatible", NULL);
3729f8dc175SJoseph Chen 		if (!comp)
3739f8dc175SJoseph Chen 			continue;
3749f8dc175SJoseph Chen 
3759f8dc175SJoseph Chen 		if (!strcmp(comp, "rockchip,gpio-bank")) {
3769f8dc175SJoseph Chen 			gpio_name[n] = (char *)fdt_get_name(fdt, offset, NULL);
3779f8dc175SJoseph Chen 			gpio_off[n]  = offset;
3789f8dc175SJoseph Chen 			n++;
3799f8dc175SJoseph Chen 		}
3809f8dc175SJoseph Chen 	}
3819f8dc175SJoseph Chen 
3829f8dc175SJoseph Chen 	if (!gpio_name[0])
3839f8dc175SJoseph Chen 		return 0;
3849f8dc175SJoseph Chen 
3859f8dc175SJoseph Chen 	if (uclass_get(UCLASS_KEY, &uc) || list_empty(&uc->dev_head))
3869f8dc175SJoseph Chen 		return 0;
3879f8dc175SJoseph Chen 
3889f8dc175SJoseph Chen 	list_for_each_entry(dev, &uc->dev_head, uclass_node) {
3899f8dc175SJoseph Chen 		u32 new_phd, phd_old;
3909f8dc175SJoseph Chen 		char *name;
3919f8dc175SJoseph Chen 		ofnode ofn;
3929f8dc175SJoseph Chen 
3939f8dc175SJoseph Chen 		if (!dev_read_bool(dev, "u-boot,dm-pre-reloc") &&
3949f8dc175SJoseph Chen 		    !dev_read_bool(dev, "u-boot,dm-spl"))
3959f8dc175SJoseph Chen 			continue;
3969f8dc175SJoseph Chen 
3979f8dc175SJoseph Chen 		if (dev_read_u32_array(dev, prop, &phd_old, 1))
3989f8dc175SJoseph Chen 			continue;
3999f8dc175SJoseph Chen 
4009f8dc175SJoseph Chen 		ofn = ofnode_get_by_phandle(phd_old);
4019f8dc175SJoseph Chen 		if (!ofnode_valid(ofn))
4029f8dc175SJoseph Chen 			continue;
4039f8dc175SJoseph Chen 
4049f8dc175SJoseph Chen 		name = (char *)ofnode_get_name(ofn);
4059f8dc175SJoseph Chen 		if (!name)
4069f8dc175SJoseph Chen 			continue;
4079f8dc175SJoseph Chen 
4089f8dc175SJoseph Chen 		for (i = 0; i < ARRAY_SIZE(gpio_name[i]); i++) {
4099f8dc175SJoseph Chen 			if (gpio_name[i] && !strcmp(name, gpio_name[i])) {
4109f8dc175SJoseph Chen 				new_phd = fdt_get_phandle(fdt, gpio_off[i]);
4119f8dc175SJoseph Chen 				dev_write_u32_array(dev, prop, &new_phd, 1);
4129f8dc175SJoseph Chen 				break;
4139f8dc175SJoseph Chen 			}
4149f8dc175SJoseph Chen 		}
4159f8dc175SJoseph Chen 	}
4169f8dc175SJoseph Chen 
4179f8dc175SJoseph Chen 	return 0;
4189f8dc175SJoseph Chen }
4199f8dc175SJoseph Chen 
420f8aaa2c2SKever Yang int init_kernel_dtb(void)
421f8aaa2c2SKever Yang {
4222208cd92SJoseph Chen 	ulong fdt_addr;
4239f8dc175SJoseph Chen 	void *ufdt_blob;
4242208cd92SJoseph Chen 	int ret;
425f8aaa2c2SKever Yang 
426f8aaa2c2SKever Yang 	fdt_addr = env_get_ulong("fdt_addr_r", 16, 0);
427f8aaa2c2SKever Yang 	if (!fdt_addr) {
428f8aaa2c2SKever Yang 		printf("No Found FDT Load Address.\n");
429f8aaa2c2SKever Yang 		return -1;
430f8aaa2c2SKever Yang 	}
431f8aaa2c2SKever Yang 
432740107bbSJoseph Chen 	ret = rockchip_read_dtb_file((void *)fdt_addr);
433f8aaa2c2SKever Yang 	if (ret < 0) {
4340ed06f16SJoseph Chen 		if (!fdt_check_header(gd->fdt_blob_kern)) {
4350ed06f16SJoseph Chen 			fdt_addr = (ulong)memalign(ARCH_DMA_MINALIGN,
4360ed06f16SJoseph Chen 					fdt_totalsize(gd->fdt_blob_kern));
4370ed06f16SJoseph Chen 			if (!fdt_addr)
4380ed06f16SJoseph Chen 				return -ENOMEM;
4390ed06f16SJoseph Chen 
4400ed06f16SJoseph Chen 			memcpy((void *)fdt_addr, gd->fdt_blob_kern,
4410ed06f16SJoseph Chen 			       fdt_totalsize(gd->fdt_blob_kern));
4420ed06f16SJoseph Chen 			printf("DTB: embedded kern.dtb\n");
4430ed06f16SJoseph Chen 		} else {
4440ed06f16SJoseph Chen 			printf("Failed to get kernel dtb, ret=%d\n", ret);
4450ed06f16SJoseph Chen 			return ret;
446f8aaa2c2SKever Yang 		}
4470ed06f16SJoseph Chen 	}
4480ed06f16SJoseph Chen 
4499f8dc175SJoseph Chen 	ufdt_blob = (void *)gd->fdt_blob;
4500ed06f16SJoseph Chen 	gd->fdt_blob = (void *)fdt_addr;
451f8aaa2c2SKever Yang 
4523e45175eSJoseph Chen 	/*
4533e45175eSJoseph Chen 	 * There is a phandle miss match between U-Boot and kernel dtb node,
4549f8dc175SJoseph Chen 	 * we fixup it in U-Boot live dt nodes.
4559f8dc175SJoseph Chen 	 *
4569f8dc175SJoseph Chen 	 * CRU:	 all nodes.
4579f8dc175SJoseph Chen 	 * GPIO: key nodes.
4583e45175eSJoseph Chen 	 */
4599f8dc175SJoseph Chen 	phandles_fixup_cru((void *)gd->fdt_blob);
4609f8dc175SJoseph Chen 	phandles_fixup_gpio((void *)gd->fdt_blob, (void *)ufdt_blob);
4613e45175eSJoseph Chen 
4620ed06f16SJoseph Chen 	of_live_build((void *)gd->fdt_blob, (struct device_node **)&gd->of_root);
4630ed06f16SJoseph Chen 	dm_scan_fdt((void *)gd->fdt_blob, false);
464f8aaa2c2SKever Yang 
4656929f85bSJoseph Chen 	/* Reserve 'reserved-memory' */
4666929f85bSJoseph Chen 	ret = boot_fdt_add_sysmem_rsv_regions((void *)gd->fdt_blob);
4676929f85bSJoseph Chen 	if (ret)
4686929f85bSJoseph Chen 		return ret;
4696929f85bSJoseph Chen 
470f8aaa2c2SKever Yang 	return 0;
471f8aaa2c2SKever Yang }
472f8aaa2c2SKever Yang #endif
473f8aaa2c2SKever Yang 
474bc04a3ddSJoseph Chen void board_env_fixup(void)
475bc04a3ddSJoseph Chen {
476124f23c6SJoseph Chen 	struct memblock mem;
477124f23c6SJoseph Chen 	ulong u_addr_r;
478124f23c6SJoseph Chen 	phys_size_t end;
4794dfe920aSJoseph Chen 	char *addr_r;
480124f23c6SJoseph Chen 
4814dfe920aSJoseph Chen #ifdef ENV_MEM_LAYOUT_SETTINGS1
4824dfe920aSJoseph Chen 	const char *env_addr0[] = {
4834dfe920aSJoseph Chen 		"scriptaddr", "pxefile_addr_r",
4844dfe920aSJoseph Chen 		"fdt_addr_r", "kernel_addr_r", "ramdisk_addr_r",
4854dfe920aSJoseph Chen 	};
4864dfe920aSJoseph Chen 	const char *env_addr1[] = {
4874dfe920aSJoseph Chen 		"scriptaddr1", "pxefile_addr1_r",
4884dfe920aSJoseph Chen 		"fdt_addr1_r", "kernel_addr1_r", "ramdisk_addr1_r",
4894dfe920aSJoseph Chen 	};
4904dfe920aSJoseph Chen 	int i;
491bc04a3ddSJoseph Chen 
4924dfe920aSJoseph Chen 	/* 128M is a typical ram size for most platform, so as default here */
4934dfe920aSJoseph Chen 	if (gd->ram_size <= SZ_128M) {
4944dfe920aSJoseph Chen 		/* Replace orignal xxx_addr_r */
4954dfe920aSJoseph Chen 		for (i = 0; i < ARRAY_SIZE(env_addr1); i++) {
4964dfe920aSJoseph Chen 			addr_r = env_get(env_addr1[i]);
4974dfe920aSJoseph Chen 			if (addr_r)
4984dfe920aSJoseph Chen 				env_set(env_addr0[i], addr_r);
4994dfe920aSJoseph Chen 		}
5004dfe920aSJoseph Chen 	}
5014dfe920aSJoseph Chen #endif
502bc04a3ddSJoseph Chen 	/* If bl32 is disabled, maybe kernel can be load to lower address. */
5034dfe920aSJoseph Chen 	if (!(gd->flags & GD_FLG_BL32_ENABLED)) {
5044dfe920aSJoseph Chen 		addr_r = env_get("kernel_addr_no_bl32_r");
5054dfe920aSJoseph Chen 		if (addr_r)
5064dfe920aSJoseph Chen 			env_set("kernel_addr_r", addr_r);
507124f23c6SJoseph Chen 	/* If bl32 is enlarged, we move ramdisk addr right behind it */
508124f23c6SJoseph Chen 	} else {
509124f23c6SJoseph Chen 		mem = param_parse_optee_mem();
510124f23c6SJoseph Chen 		end = mem.base + mem.size;
511124f23c6SJoseph Chen 		u_addr_r = env_get_ulong("ramdisk_addr_r", 16, 0);
512124f23c6SJoseph Chen 		if (u_addr_r >= mem.base && u_addr_r < end)
513124f23c6SJoseph Chen 			env_set_hex("ramdisk_addr_r", end);
5144dfe920aSJoseph Chen 	}
515bc04a3ddSJoseph Chen }
516f8aaa2c2SKever Yang 
5177397b961SJoseph Chen static void early_download_init(void)
518644804edSJoseph Chen {
5197397b961SJoseph Chen #if defined(CONFIG_PWRKEY_DNL_TRIGGER_NUM) && \
5207397b961SJoseph Chen 		(CONFIG_PWRKEY_DNL_TRIGGER_NUM > 0)
5217397b961SJoseph Chen 	if (pwrkey_download_init())
5227397b961SJoseph Chen 		printf("Pwrkey download init failed\n");
5237397b961SJoseph Chen #endif
5247397b961SJoseph Chen 
525644804edSJoseph Chen 	if (!tstc())
526644804edSJoseph Chen 		return;
527644804edSJoseph Chen 
528644804edSJoseph Chen 	gd->console_evt = getc();
52915c8c8dbSJoseph Chen 	if (gd->console_evt <= 0x1a) /* 'z' */
53015c8c8dbSJoseph Chen 		printf("Hotkey: ctrl+%c\n", (gd->console_evt + 'a' - 1));
53115c8c8dbSJoseph Chen 
532644804edSJoseph Chen #if (CONFIG_ROCKCHIP_BOOT_MODE_REG > 0)
533c664909eSJoseph Chen 	if (is_hotkey(HK_BROM_DNL)) {
534644804edSJoseph Chen 		printf("Enter bootrom download...");
535363411a1SJoseph Chen 		flushc();
536644804edSJoseph Chen 		writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG);
537644804edSJoseph Chen 		do_reset(NULL, 0, 0, NULL);
538644804edSJoseph Chen 		printf("failed!\n");
539644804edSJoseph Chen 	}
540644804edSJoseph Chen #endif
541644804edSJoseph Chen }
542644804edSJoseph Chen 
543*5d5f363eSJoseph Chen static void board_debug_init(void)
544*5d5f363eSJoseph Chen {
545*5d5f363eSJoseph Chen 	if (!gd->serial.using_pre_serial)
546*5d5f363eSJoseph Chen 		board_debug_uart_init();
547*5d5f363eSJoseph Chen }
548*5d5f363eSJoseph Chen 
54938771996SKever Yang int board_init(void)
55038771996SKever Yang {
551*5d5f363eSJoseph Chen 	board_debug_init();
552ebb6c439SYouMin Chen 
553f0aa8c5dSJason Zhu #ifdef DEBUG
554f0aa8c5dSJason Zhu 	soc_clk_dump();
555f0aa8c5dSJason Zhu #endif
556f0aa8c5dSJason Zhu 
557f8aaa2c2SKever Yang #ifdef CONFIG_USING_KERNEL_DTB
558f8aaa2c2SKever Yang 	init_kernel_dtb();
559f8aaa2c2SKever Yang #endif
5607397b961SJoseph Chen 	early_download_init();
5617397b961SJoseph Chen 
5629f8e13d3SFinley Xiao 	/*
5639f8e13d3SFinley Xiao 	 * pmucru isn't referenced on some platforms, so pmucru driver can't
5649f8e13d3SFinley Xiao 	 * probe that the "assigned-clocks" is unused.
5659f8e13d3SFinley Xiao 	 */
5669f8e13d3SFinley Xiao 	clks_probe();
56738771996SKever Yang #ifdef CONFIG_DM_REGULATOR
568dba9c9e5SJoseph Chen 	if (regulators_enable_boot_on(is_hotkey(HK_REGULATOR)))
5692208cd92SJoseph Chen 		debug("%s: Can't enable boot on regulator\n", __func__);
57038771996SKever Yang #endif
571dae20286SJianqun Xu 
572dae20286SJianqun Xu #ifdef CONFIG_ROCKCHIP_IO_DOMAIN
573dae20286SJianqun Xu 	io_domain_init();
574dae20286SJianqun Xu #endif
575dae20286SJianqun Xu 
576058e5d94SFinley Xiao 	set_armclk_rate();
57738771996SKever Yang 
5783acf4edfSJoseph Chen #ifdef CONFIG_DM_DVFS
5793acf4edfSJoseph Chen 	dvfs_init(true);
5803acf4edfSJoseph Chen #endif
5813acf4edfSJoseph Chen 
58238771996SKever Yang 	return rk_board_init();
58338771996SKever Yang }
58438771996SKever Yang 
585c563adc7SJoseph Chen int interrupt_debugger_init(void)
586c563adc7SJoseph Chen {
587c563adc7SJoseph Chen #ifdef CONFIG_ROCKCHIP_DEBUGGER
5882208cd92SJoseph Chen 	return rockchip_debugger_init();
5892208cd92SJoseph Chen #else
5902208cd92SJoseph Chen 	return 0;
591c563adc7SJoseph Chen #endif
592c563adc7SJoseph Chen }
593c563adc7SJoseph Chen 
594e09b1e4aSJoseph Chen int board_fdt_fixup(void *blob)
595e09b1e4aSJoseph Chen {
5962208cd92SJoseph Chen 	/* Common fixup for DRM */
597e09b1e4aSJoseph Chen #ifdef CONFIG_DRM_ROCKCHIP
598e09b1e4aSJoseph Chen 	rockchip_display_fixup(blob);
599e09b1e4aSJoseph Chen #endif
600e09b1e4aSJoseph Chen 
60138ce6261SJoseph Chen 	return rk_board_fdt_fixup(blob);
602e09b1e4aSJoseph Chen }
603e09b1e4aSJoseph Chen 
604e3fbd280SJoseph Chen #ifdef CONFIG_ARM64_BOOT_AARCH32
605e3fbd280SJoseph Chen /*
606e3fbd280SJoseph Chen  * Fixup MMU region attr for OP-TEE on ARMv8 CPU:
607e3fbd280SJoseph Chen  *
608e3fbd280SJoseph Chen  * What ever U-Boot is 64-bit or 32-bit mode, the OP-TEE is always 64-bit mode.
609e3fbd280SJoseph Chen  *
610e3fbd280SJoseph Chen  * Command for OP-TEE:
611e3fbd280SJoseph Chen  *	64-bit mode: dcache is always enabled;
612e3fbd280SJoseph Chen  *	32-bit mode: dcache is always disabled(Due to some unknown issue);
613e3fbd280SJoseph Chen  *
614e3fbd280SJoseph Chen  * Command for U-Boot:
615e3fbd280SJoseph Chen  *	64-bit mode: MMU table is static defined in rkxxx.c file, all memory
616e3fbd280SJoseph Chen  *		     regions are mapped. That's good to match OP-TEE MMU policy.
617e3fbd280SJoseph Chen  *
618e3fbd280SJoseph Chen  *	32-bit mode: MMU table is setup according to gd->bd->bi_dram[..] where
619e3fbd280SJoseph Chen  *		     the OP-TEE region has been reserved, so it can not be
620e3fbd280SJoseph Chen  *		     mapped(i.e. dcache is disabled). That's also good to match
621e3fbd280SJoseph Chen  *		     OP-TEE MMU policy.
622e3fbd280SJoseph Chen  *
623e3fbd280SJoseph Chen  * For the data coherence when communication between U-Boot and OP-TEE, U-Boot
624e3fbd280SJoseph Chen  * should follow OP-TEE MMU policy.
625e3fbd280SJoseph Chen  *
626e3fbd280SJoseph Chen  * Here is the special:
627e3fbd280SJoseph Chen  *	When CONFIG_ARM64_BOOT_AARCH32 is enabled, U-Boot is 32-bit mode while
628e3fbd280SJoseph Chen  *	OP-TEE is still 64-bit mode. U-Boot would not map MMU table for OP-TEE
629e3fbd280SJoseph Chen  *	region(but OP-TEE requires it cacheable) so we fixup here.
630e3fbd280SJoseph Chen  */
631e3fbd280SJoseph Chen int board_initr_caches_fixup(void)
632e3fbd280SJoseph Chen {
633e3fbd280SJoseph Chen 	struct memblock mem;
634e3fbd280SJoseph Chen 
635e3fbd280SJoseph Chen 	mem = param_parse_optee_mem();
636e3fbd280SJoseph Chen 	if (mem.size)
637e3fbd280SJoseph Chen 		mmu_set_region_dcache_behaviour(mem.base, mem.size,
638e3fbd280SJoseph Chen 						DCACHE_WRITEBACK);
639e3fbd280SJoseph Chen 	return 0;
640e3fbd280SJoseph Chen }
641e3fbd280SJoseph Chen #endif
642e3fbd280SJoseph Chen 
643665be4b0SJoseph Chen void arch_preboot_os(uint32_t bootm_state)
644665be4b0SJoseph Chen {
645665be4b0SJoseph Chen 	if (bootm_state & BOOTM_STATE_OS_PREP)
646665be4b0SJoseph Chen 		hotkey_run(HK_CLI_OS_PRE);
647665be4b0SJoseph Chen }
648665be4b0SJoseph Chen 
6493e6a97f9SJoseph Chen void board_quiesce_devices(void)
6503e6a97f9SJoseph Chen {
65115c8c8dbSJoseph Chen 	hotkey_run(HK_CMDLINE);
652665be4b0SJoseph Chen 	hotkey_run(HK_CLI_OS_GO);
65315c8c8dbSJoseph Chen 
6544892a977SJoseph Chen #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
6553e6a97f9SJoseph Chen 	/* Destroy atags makes next warm boot safer */
6563e6a97f9SJoseph Chen 	atags_destroy();
6574892a977SJoseph Chen #endif
6589dfc5f87SJoseph Chen 
6599dfc5f87SJoseph Chen #if defined(CONFIG_CONSOLE_RECORD)
6609dfc5f87SJoseph Chen 	/* Print record console data */
6619dfc5f87SJoseph Chen 	console_record_print_purge();
6629dfc5f87SJoseph Chen #endif
6633e6a97f9SJoseph Chen }
6643e6a97f9SJoseph Chen 
66538771996SKever Yang void enable_caches(void)
66638771996SKever Yang {
667567735c8SJoseph Chen 	icache_enable();
66838771996SKever Yang 	dcache_enable();
66938771996SKever Yang }
67038771996SKever Yang 
6712dc2d048SJoseph Chen #ifdef CONFIG_LMB
6722c6a058bSJoseph Chen /*
6732c6a058bSJoseph Chen  * Using last bi_dram[...] to initialize "bootm_low" and "bootm_mapsize".
6742c6a058bSJoseph Chen  * This makes lmb_alloc_base() always alloc from tail of sdram.
6752c6a058bSJoseph Chen  * If we don't assign it, bi_dram[0] is used by default and it may cause
6762c6a058bSJoseph Chen  * lmb_alloc_base() fail when bi_dram[0] range is small.
6772c6a058bSJoseph Chen  */
6782c6a058bSJoseph Chen void board_lmb_reserve(struct lmb *lmb)
6792c6a058bSJoseph Chen {
6802c6a058bSJoseph Chen 	char bootm_mapsize[32];
6812208cd92SJoseph Chen 	char bootm_low[32];
6822208cd92SJoseph Chen 	u64 start, size;
6832c6a058bSJoseph Chen 	int i;
6842c6a058bSJoseph Chen 
6852c6a058bSJoseph Chen 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
6862c6a058bSJoseph Chen 		if (!gd->bd->bi_dram[i].size)
6872c6a058bSJoseph Chen 			break;
6882c6a058bSJoseph Chen 	}
6892c6a058bSJoseph Chen 
6902c6a058bSJoseph Chen 	start = gd->bd->bi_dram[i - 1].start;
6912c6a058bSJoseph Chen 	size = gd->bd->bi_dram[i - 1].size;
6922c6a058bSJoseph Chen 
6932c6a058bSJoseph Chen 	/*
6942dc2d048SJoseph Chen 	 * 32-bit kernel: ramdisk/fdt shouldn't be loaded to highmem area(768MB+),
6952dc2d048SJoseph Chen 	 * otherwise "Unable to handle kernel paging request at virtual address ...".
6962dc2d048SJoseph Chen 	 *
6972dc2d048SJoseph Chen 	 * So that we hope limit highest address at 768M, but there comes the the
6982dc2d048SJoseph Chen 	 * problem: ramdisk is a compressed image and it expands after descompress,
6992dc2d048SJoseph Chen 	 * so it accesses 768MB+ and brings the above "Unable to handle kernel ...".
7002dc2d048SJoseph Chen 	 *
7012dc2d048SJoseph Chen 	 * We make a appointment that the highest memory address is 512MB, it
7022dc2d048SJoseph Chen 	 * makes lmb alloc safer.
7032c6a058bSJoseph Chen 	 */
7042dc2d048SJoseph Chen #ifndef CONFIG_ARM64
7052dc2d048SJoseph Chen 	if (start >= ((u64)CONFIG_SYS_SDRAM_BASE + SZ_512M)) {
7062c6a058bSJoseph Chen 		start = gd->bd->bi_dram[i - 2].start;
7072c6a058bSJoseph Chen 		size = gd->bd->bi_dram[i - 2].size;
7082c6a058bSJoseph Chen 	}
7092c6a058bSJoseph Chen 
7102dc2d048SJoseph Chen 	if ((start + size) > ((u64)CONFIG_SYS_SDRAM_BASE + SZ_512M))
7112dc2d048SJoseph Chen 		size = (u64)CONFIG_SYS_SDRAM_BASE + SZ_512M - start;
7122c6a058bSJoseph Chen #endif
7132c6a058bSJoseph Chen 	sprintf(bootm_low, "0x%llx", start);
7142c6a058bSJoseph Chen 	sprintf(bootm_mapsize, "0x%llx", size);
7152c6a058bSJoseph Chen 	env_set("bootm_low", bootm_low);
7162c6a058bSJoseph Chen 	env_set("bootm_mapsize", bootm_mapsize);
7172c6a058bSJoseph Chen }
7182dc2d048SJoseph Chen #endif
7192c6a058bSJoseph Chen 
72086f870d6SJoseph Chen #ifdef CONFIG_BIDRAM
72186f870d6SJoseph Chen int board_bidram_reserve(struct bidram *bidram)
72286f870d6SJoseph Chen {
72386f870d6SJoseph Chen 	struct memblock mem;
72486f870d6SJoseph Chen 	int ret;
72586f870d6SJoseph Chen 
72686f870d6SJoseph Chen 	/* ATF */
72786f870d6SJoseph Chen 	mem = param_parse_atf_mem();
72886f870d6SJoseph Chen 	ret = bidram_reserve(MEMBLK_ID_ATF, mem.base, mem.size);
72986f870d6SJoseph Chen 	if (ret)
73086f870d6SJoseph Chen 		return ret;
73186f870d6SJoseph Chen 
73286f870d6SJoseph Chen 	/* PSTORE/ATAGS/SHM */
73386f870d6SJoseph Chen 	mem = param_parse_common_resv_mem();
73486f870d6SJoseph Chen 	ret = bidram_reserve(MEMBLK_ID_SHM, mem.base, mem.size);
73586f870d6SJoseph Chen 	if (ret)
73686f870d6SJoseph Chen 		return ret;
73786f870d6SJoseph Chen 
73886f870d6SJoseph Chen 	/* OP-TEE */
73986f870d6SJoseph Chen 	mem = param_parse_optee_mem();
74086f870d6SJoseph Chen 	ret = bidram_reserve(MEMBLK_ID_OPTEE, mem.base, mem.size);
74186f870d6SJoseph Chen 	if (ret)
74286f870d6SJoseph Chen 		return ret;
74386f870d6SJoseph Chen 
74486f870d6SJoseph Chen 	return 0;
74586f870d6SJoseph Chen }
74686f870d6SJoseph Chen 
74786f870d6SJoseph Chen parse_fn_t board_bidram_parse_fn(void)
74886f870d6SJoseph Chen {
74986f870d6SJoseph Chen 	return param_parse_ddr_mem;
75086f870d6SJoseph Chen }
75186f870d6SJoseph Chen #endif
75286f870d6SJoseph Chen 
75350d35c45SJoseph Chen #ifdef CONFIG_ROCKCHIP_AMP
75450d35c45SJoseph Chen void cpu_secondary_init_r(void)
75550d35c45SJoseph Chen {
75650d35c45SJoseph Chen 	amp_cpus_on();
75750d35c45SJoseph Chen }
75850d35c45SJoseph Chen #endif
75950d35c45SJoseph Chen 
7604892a977SJoseph Chen #if defined(CONFIG_ROCKCHIP_PRELOADER_SERIAL) && \
7614892a977SJoseph Chen     defined(CONFIG_ROCKCHIP_PRELOADER_ATAGS)
762064eb493SJoseph Chen int board_init_f_init_serial(void)
763064eb493SJoseph Chen {
764064eb493SJoseph Chen 	struct tag *t = atags_get_tag(ATAG_SERIAL);
765064eb493SJoseph Chen 
766064eb493SJoseph Chen 	if (t) {
767064eb493SJoseph Chen 		gd->serial.using_pre_serial = t->u.serial.enable;
768064eb493SJoseph Chen 		gd->serial.addr = t->u.serial.addr;
769064eb493SJoseph Chen 		gd->serial.baudrate = t->u.serial.baudrate;
770064eb493SJoseph Chen 		gd->serial.id = t->u.serial.id;
771064eb493SJoseph Chen 
772064eb493SJoseph Chen 		debug("%s: enable=%d, addr=0x%lx, baudrate=%d, id=%d\n",
773064eb493SJoseph Chen 		      __func__, gd->serial.using_pre_serial,
774064eb493SJoseph Chen 		      gd->serial.addr, gd->serial.baudrate,
775064eb493SJoseph Chen 		      gd->serial.id);
776064eb493SJoseph Chen 	}
777064eb493SJoseph Chen 
778064eb493SJoseph Chen 	return 0;
779064eb493SJoseph Chen }
780064eb493SJoseph Chen #endif
781064eb493SJoseph Chen 
78238771996SKever Yang #if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
7836f7b6465SFrank Wang #include <fdt_support.h>
78438771996SKever Yang #include <usb.h>
78538771996SKever Yang #include <usb/dwc2_udc.h>
78638771996SKever Yang 
78738771996SKever Yang static struct dwc2_plat_otg_data otg_data = {
78838771996SKever Yang 	.rx_fifo_sz	= 512,
78938771996SKever Yang 	.np_tx_fifo_sz	= 16,
79038771996SKever Yang 	.tx_fifo_sz	= 128,
79138771996SKever Yang };
79238771996SKever Yang 
79338771996SKever Yang int board_usb_init(int index, enum usb_init_type init)
79438771996SKever Yang {
79538771996SKever Yang 	const void *blob = gd->fdt_blob;
7962208cd92SJoseph Chen 	const fdt32_t *reg;
7972208cd92SJoseph Chen 	fdt_addr_t addr;
7982208cd92SJoseph Chen 	int node;
79938771996SKever Yang 
80038771996SKever Yang 	/* find the usb_otg node */
801294ad617SWilliam Wu 	node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc2");
80238771996SKever Yang 
803294ad617SWilliam Wu retry:
804294ad617SWilliam Wu 	if (node > 0) {
805294ad617SWilliam Wu 		reg = fdt_getprop(blob, node, "reg", NULL);
806294ad617SWilliam Wu 		if (!reg)
807294ad617SWilliam Wu 			return -EINVAL;
808294ad617SWilliam Wu 
809294ad617SWilliam Wu 		addr = fdt_translate_address(blob, node, reg);
810294ad617SWilliam Wu 		if (addr == OF_BAD_ADDR) {
811294ad617SWilliam Wu 			pr_err("Not found usb_otg address\n");
812294ad617SWilliam Wu 			return -EINVAL;
81338771996SKever Yang 		}
81438771996SKever Yang 
815294ad617SWilliam Wu #if defined(CONFIG_ROCKCHIP_RK3288)
816294ad617SWilliam Wu 		if (addr != 0xff580000) {
81738771996SKever Yang 			node = fdt_node_offset_by_compatible(blob, node,
81838771996SKever Yang 							     "snps,dwc2");
819294ad617SWilliam Wu 			goto retry;
82038771996SKever Yang 		}
821294ad617SWilliam Wu #endif
822294ad617SWilliam Wu 	} else {
823e7b5bb3cSWilliam Wu 		/*
824e7b5bb3cSWilliam Wu 		 * With kernel dtb support, rk3288 dwc2 otg node
825e7b5bb3cSWilliam Wu 		 * use the rockchip legacy dwc2 driver "dwc_otg_310"
826e0b87408SJoseph Chen 		 * with the compatible "rockchip,rk3288_usb20_otg",
827e0b87408SJoseph Chen 		 * and rk3368 also use the "dwc_otg_310" driver with
828e0b87408SJoseph Chen 		 * the compatible "rockchip,rk3368-usb".
829e7b5bb3cSWilliam Wu 		 */
830e0b87408SJoseph Chen #if defined(CONFIG_ROCKCHIP_RK3288)
831e7b5bb3cSWilliam Wu 		node = fdt_node_offset_by_compatible(blob, -1,
832e7b5bb3cSWilliam Wu 				"rockchip,rk3288_usb20_otg");
833e0b87408SJoseph Chen #elif defined(CONFIG_ROCKCHIP_RK3368)
834e0b87408SJoseph Chen 		node = fdt_node_offset_by_compatible(blob, -1,
835e0b87408SJoseph Chen 				"rockchip,rk3368-usb");
836e0b87408SJoseph Chen #endif
837e7b5bb3cSWilliam Wu 		if (node > 0) {
838294ad617SWilliam Wu 			goto retry;
839e7b5bb3cSWilliam Wu 		} else {
840e7b5bb3cSWilliam Wu 			pr_err("Not found usb_otg device\n");
84138771996SKever Yang 			return -ENODEV;
84238771996SKever Yang 		}
843e7b5bb3cSWilliam Wu 	}
8446f7b6465SFrank Wang 
8456f7b6465SFrank Wang 	otg_data.regs_otg = (uintptr_t)addr;
84638771996SKever Yang 
84738771996SKever Yang 	return dwc2_udc_probe(&otg_data);
84838771996SKever Yang }
84938771996SKever Yang 
85038771996SKever Yang int board_usb_cleanup(int index, enum usb_init_type init)
85138771996SKever Yang {
85238771996SKever Yang 	return 0;
85338771996SKever Yang }
85438771996SKever Yang #endif
855