xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/kernel_dtb.c (revision 18b9d982b58c6051c4ba2c65c5f6dfd406c34e1c)
157be1825SJoseph Chen /*
257be1825SJoseph Chen  * (C) Copyright 2019 Rockchip Electronics Co., Ltd
357be1825SJoseph Chen  *
457be1825SJoseph Chen  * SPDX-License-Identifier:     GPL-2.0+
557be1825SJoseph Chen  */
657be1825SJoseph Chen #include <common.h>
757be1825SJoseph Chen #include <boot_rkimg.h>
857be1825SJoseph Chen #include <dm.h>
957be1825SJoseph Chen #include <malloc.h>
1057be1825SJoseph Chen #include <of_live.h>
1157be1825SJoseph Chen #include <dm/root.h>
12*18b9d982SJoseph Chen #include <dm/uclass-internal.h>
1357be1825SJoseph Chen #include <asm/arch/hotkey.h>
1457be1825SJoseph Chen 
1557be1825SJoseph Chen DECLARE_GLOBAL_DATA_PTR;
1657be1825SJoseph Chen 
17*18b9d982SJoseph Chen #ifdef CONFIG_USING_KERNEL_DTB_V2
18*18b9d982SJoseph Chen static int dm_rm_kernel_dev(void)
19*18b9d982SJoseph Chen {
20*18b9d982SJoseph Chen 	struct udevice *dev, *rec[10];
21*18b9d982SJoseph Chen 	u32 uclass[] = { UCLASS_CRYPTO };
22*18b9d982SJoseph Chen 	int i, j, k;
23*18b9d982SJoseph Chen 
24*18b9d982SJoseph Chen 	for (i = 0, j = 0; i < ARRAY_SIZE(uclass); i++) {
25*18b9d982SJoseph Chen 		for (uclass_find_first_device(uclass[i], &dev); dev;
26*18b9d982SJoseph Chen 		     uclass_find_next_device(&dev)) {
27*18b9d982SJoseph Chen 			if (dev->flags & DM_FLAG_KNRL_DTB)
28*18b9d982SJoseph Chen 				rec[j++] = dev;
29*18b9d982SJoseph Chen 		}
30*18b9d982SJoseph Chen 
31*18b9d982SJoseph Chen 		for (k = 0; k < j; k++)
32*18b9d982SJoseph Chen 			list_del_init(&rec[k]->uclass_node);
33*18b9d982SJoseph Chen 	}
34*18b9d982SJoseph Chen 
35*18b9d982SJoseph Chen 	return 0;
36*18b9d982SJoseph Chen }
37*18b9d982SJoseph Chen 
38*18b9d982SJoseph Chen static int dm_rm_u_boot_dev(void)
39*18b9d982SJoseph Chen {
40*18b9d982SJoseph Chen 	struct udevice *dev, *rec[10];
41*18b9d982SJoseph Chen 	u32 uclass[] = { UCLASS_ETH };
42*18b9d982SJoseph Chen 	int del = 0;
43*18b9d982SJoseph Chen 	int i, j, k;
44*18b9d982SJoseph Chen 
45*18b9d982SJoseph Chen 	for (i = 0, j = 0; i < ARRAY_SIZE(uclass); i++) {
46*18b9d982SJoseph Chen 		for (uclass_find_first_device(uclass[i], &dev); dev;
47*18b9d982SJoseph Chen 		     uclass_find_next_device(&dev)) {
48*18b9d982SJoseph Chen 			if (dev->flags & DM_FLAG_KNRL_DTB)
49*18b9d982SJoseph Chen 				del = 1;
50*18b9d982SJoseph Chen 			else
51*18b9d982SJoseph Chen 				rec[j++] = dev;
52*18b9d982SJoseph Chen 		}
53*18b9d982SJoseph Chen 
54*18b9d982SJoseph Chen 		/* remove u-boot dev if there is someone from kernel */
55*18b9d982SJoseph Chen 		if (del) {
56*18b9d982SJoseph Chen 			for (k = 0; k < j; k++)
57*18b9d982SJoseph Chen 				list_del_init(&rec[k]->uclass_node);
58*18b9d982SJoseph Chen 		}
59*18b9d982SJoseph Chen 	}
60*18b9d982SJoseph Chen 
61*18b9d982SJoseph Chen 	return 0;
62*18b9d982SJoseph Chen }
63*18b9d982SJoseph Chen 
64*18b9d982SJoseph Chen #else
6557be1825SJoseph Chen /* Here, only fixup cru phandle, pmucru is not included */
6657be1825SJoseph Chen static int phandles_fixup_cru(const void *fdt)
6757be1825SJoseph Chen {
684d85f76cSJoseph Chen 	const char *props[] = { "clocks", "assigned-clocks", "resets"};
6957be1825SJoseph Chen 	struct udevice *dev;
7057be1825SJoseph Chen 	struct uclass *uc;
7157be1825SJoseph Chen 	const char *comp;
7257be1825SJoseph Chen 	u32 id, nclocks;
7357be1825SJoseph Chen 	u32 *clocks;
7457be1825SJoseph Chen 	int phandle, ncells;
7557be1825SJoseph Chen 	int off, offset;
7657be1825SJoseph Chen 	int ret, length;
7757be1825SJoseph Chen 	int i, j;
7857be1825SJoseph Chen 	int first_phandle = -1;
7957be1825SJoseph Chen 
8057be1825SJoseph Chen 	phandle = -ENODATA;
8157be1825SJoseph Chen 	ncells = -ENODATA;
8257be1825SJoseph Chen 
8357be1825SJoseph Chen 	/* fdt points to kernel dtb, getting cru phandle and "#clock-cells" */
8457be1825SJoseph Chen 	for (offset = fdt_next_node(fdt, 0, NULL);
8557be1825SJoseph Chen 	     offset >= 0;
8657be1825SJoseph Chen 	     offset = fdt_next_node(fdt, offset, NULL)) {
8757be1825SJoseph Chen 		comp = fdt_getprop(fdt, offset, "compatible", NULL);
8857be1825SJoseph Chen 		if (!comp)
8957be1825SJoseph Chen 			continue;
9057be1825SJoseph Chen 
9157be1825SJoseph Chen 		/* Actually, this is not a good method to get cru node */
9257be1825SJoseph Chen 		off = strlen(comp) - strlen("-cru");
9357be1825SJoseph Chen 		if (off > 0 && !strncmp(comp + off, "-cru", 4)) {
9457be1825SJoseph Chen 			phandle = fdt_get_phandle(fdt, offset);
9557be1825SJoseph Chen 			ncells = fdtdec_get_int(fdt, offset,
9657be1825SJoseph Chen 						"#clock-cells", -ENODATA);
9757be1825SJoseph Chen 			break;
9857be1825SJoseph Chen 		}
9957be1825SJoseph Chen 	}
10057be1825SJoseph Chen 
10157be1825SJoseph Chen 	if (phandle == -ENODATA || ncells == -ENODATA)
10257be1825SJoseph Chen 		return 0;
10357be1825SJoseph Chen 
10457be1825SJoseph Chen 	debug("%s: target cru: clock-cells:%d, phandle:0x%x\n",
10557be1825SJoseph Chen 	      __func__, ncells, fdt32_to_cpu(phandle));
10657be1825SJoseph Chen 
10757be1825SJoseph Chen 	/* Try to fixup all cru phandle from U-Boot dtb nodes */
10857be1825SJoseph Chen 	for (id = 0; id < UCLASS_COUNT; id++) {
10957be1825SJoseph Chen 		ret = uclass_get(id, &uc);
11057be1825SJoseph Chen 		if (ret)
11157be1825SJoseph Chen 			continue;
11257be1825SJoseph Chen 
11357be1825SJoseph Chen 		if (list_empty(&uc->dev_head))
11457be1825SJoseph Chen 			continue;
11557be1825SJoseph Chen 
11657be1825SJoseph Chen 		list_for_each_entry(dev, &uc->dev_head, uclass_node) {
11757be1825SJoseph Chen 			/* Only U-Boot node go further */
11857be1825SJoseph Chen 			if (!dev_read_bool(dev, "u-boot,dm-pre-reloc") &&
11957be1825SJoseph Chen 			    !dev_read_bool(dev, "u-boot,dm-spl"))
12057be1825SJoseph Chen 				continue;
12157be1825SJoseph Chen 
12257be1825SJoseph Chen 			for (i = 0; i < ARRAY_SIZE(props); i++) {
12357be1825SJoseph Chen 				if (!dev_read_prop(dev, props[i], &length))
12457be1825SJoseph Chen 					continue;
12557be1825SJoseph Chen 
12657be1825SJoseph Chen 				clocks = malloc(length);
12757be1825SJoseph Chen 				if (!clocks)
12857be1825SJoseph Chen 					return -ENOMEM;
12957be1825SJoseph Chen 
13057be1825SJoseph Chen 				/* Read "props[]" which contains cru phandle */
13157be1825SJoseph Chen 				nclocks = length / sizeof(u32);
13257be1825SJoseph Chen 				if (dev_read_u32_array(dev, props[i],
13357be1825SJoseph Chen 						       clocks, nclocks)) {
13457be1825SJoseph Chen 					free(clocks);
13557be1825SJoseph Chen 					continue;
13657be1825SJoseph Chen 				}
13757be1825SJoseph Chen 
13857be1825SJoseph Chen 				/* Fixup with kernel cru phandle */
13957be1825SJoseph Chen 				for (j = 0; j < nclocks; j += (ncells + 1)) {
14057be1825SJoseph Chen 					/*
14157be1825SJoseph Chen 					 * Check: update pmucru phandle with cru
14257be1825SJoseph Chen 					 * phandle by mistake.
14357be1825SJoseph Chen 					 */
14457be1825SJoseph Chen 					if (first_phandle == -1)
14557be1825SJoseph Chen 						first_phandle = clocks[j];
14657be1825SJoseph Chen 
14757be1825SJoseph Chen 					if (clocks[j] != first_phandle) {
14857be1825SJoseph Chen 						debug("WARN: %s: first cru phandle=%d, this=%d\n",
14957be1825SJoseph Chen 						      dev_read_name(dev),
15057be1825SJoseph Chen 						      first_phandle, clocks[j]);
15157be1825SJoseph Chen 						continue;
15257be1825SJoseph Chen 					}
15357be1825SJoseph Chen 
15457be1825SJoseph Chen 					clocks[j] = phandle;
15557be1825SJoseph Chen 				}
15657be1825SJoseph Chen 
15757be1825SJoseph Chen 				/*
15857be1825SJoseph Chen 				 * Override live dt nodes but not fdt nodes,
15957be1825SJoseph Chen 				 * because all U-Boot nodes has been imported
16057be1825SJoseph Chen 				 * to live dt nodes, should use "dev_xxx()".
16157be1825SJoseph Chen 				 */
16257be1825SJoseph Chen 				dev_write_u32_array(dev, props[i],
16357be1825SJoseph Chen 						    clocks, nclocks);
16457be1825SJoseph Chen 				free(clocks);
16557be1825SJoseph Chen 			}
16657be1825SJoseph Chen 		}
16757be1825SJoseph Chen 	}
16857be1825SJoseph Chen 
16957be1825SJoseph Chen 	return 0;
17057be1825SJoseph Chen }
17157be1825SJoseph Chen 
17257be1825SJoseph Chen static int phandles_fixup_gpio(const void *fdt, void *ufdt)
17357be1825SJoseph Chen {
17457be1825SJoseph Chen 	struct udevice *dev;
17557be1825SJoseph Chen 	struct uclass *uc;
17657be1825SJoseph Chen 	const char *prop = "gpios";
17757be1825SJoseph Chen 	const char *comp;
17857be1825SJoseph Chen 	char *gpio_name[10];
17957be1825SJoseph Chen 	int gpio_off[10];
18057be1825SJoseph Chen 	int pinctrl;
18157be1825SJoseph Chen 	int offset;
18257be1825SJoseph Chen 	int i = 0;
18357be1825SJoseph Chen 	int n = 0;
18457be1825SJoseph Chen 
18557be1825SJoseph Chen 	pinctrl = fdt_path_offset(fdt, "/pinctrl");
18657be1825SJoseph Chen 	if (pinctrl < 0)
18757be1825SJoseph Chen 		return 0;
18857be1825SJoseph Chen 
18957be1825SJoseph Chen 	memset(gpio_name, 0, sizeof(gpio_name));
19057be1825SJoseph Chen 	for (offset = fdt_first_subnode(fdt, pinctrl);
19157be1825SJoseph Chen 	     offset >= 0;
19257be1825SJoseph Chen 	     offset = fdt_next_subnode(fdt, offset)) {
19357be1825SJoseph Chen 		/* assume the font nodes are gpio node */
19457be1825SJoseph Chen 		if (++i >= ARRAY_SIZE(gpio_name))
19557be1825SJoseph Chen 			break;
19657be1825SJoseph Chen 
19757be1825SJoseph Chen 		comp = fdt_getprop(fdt, offset, "compatible", NULL);
19857be1825SJoseph Chen 		if (!comp)
19957be1825SJoseph Chen 			continue;
20057be1825SJoseph Chen 
20157be1825SJoseph Chen 		if (!strcmp(comp, "rockchip,gpio-bank")) {
20257be1825SJoseph Chen 			gpio_name[n] = (char *)fdt_get_name(fdt, offset, NULL);
20357be1825SJoseph Chen 			gpio_off[n]  = offset;
20457be1825SJoseph Chen 			n++;
20557be1825SJoseph Chen 		}
20657be1825SJoseph Chen 	}
20757be1825SJoseph Chen 
20857be1825SJoseph Chen 	if (!gpio_name[0])
20957be1825SJoseph Chen 		return 0;
21057be1825SJoseph Chen 
21157be1825SJoseph Chen 	if (uclass_get(UCLASS_KEY, &uc) || list_empty(&uc->dev_head))
21257be1825SJoseph Chen 		return 0;
21357be1825SJoseph Chen 
21457be1825SJoseph Chen 	list_for_each_entry(dev, &uc->dev_head, uclass_node) {
21557be1825SJoseph Chen 		u32 new_phd, phd_old;
21657be1825SJoseph Chen 		char *name;
21757be1825SJoseph Chen 		ofnode ofn;
21857be1825SJoseph Chen 
21957be1825SJoseph Chen 		if (!dev_read_bool(dev, "u-boot,dm-pre-reloc") &&
22057be1825SJoseph Chen 		    !dev_read_bool(dev, "u-boot,dm-spl"))
22157be1825SJoseph Chen 			continue;
22257be1825SJoseph Chen 
22357be1825SJoseph Chen 		if (dev_read_u32_array(dev, prop, &phd_old, 1))
22457be1825SJoseph Chen 			continue;
22557be1825SJoseph Chen 
22657be1825SJoseph Chen 		ofn = ofnode_get_by_phandle(phd_old);
22757be1825SJoseph Chen 		if (!ofnode_valid(ofn))
22857be1825SJoseph Chen 			continue;
22957be1825SJoseph Chen 
23057be1825SJoseph Chen 		name = (char *)ofnode_get_name(ofn);
23157be1825SJoseph Chen 		if (!name)
23257be1825SJoseph Chen 			continue;
23357be1825SJoseph Chen 
2342a931879SJoseph Chen 		for (i = 0; i < ARRAY_SIZE(gpio_name); i++) {
23557be1825SJoseph Chen 			if (gpio_name[i] && !strcmp(name, gpio_name[i])) {
23657be1825SJoseph Chen 				new_phd = fdt_get_phandle(fdt, gpio_off[i]);
23757be1825SJoseph Chen 				dev_write_u32_array(dev, prop, &new_phd, 1);
23857be1825SJoseph Chen 				break;
23957be1825SJoseph Chen 			}
24057be1825SJoseph Chen 		}
24157be1825SJoseph Chen 	}
24257be1825SJoseph Chen 
24357be1825SJoseph Chen 	return 0;
24457be1825SJoseph Chen }
24595eb462eSJoseph Chen #endif
24657be1825SJoseph Chen 
24757be1825SJoseph Chen __weak int board_mmc_dm_reinit(struct udevice *dev)
24857be1825SJoseph Chen {
24957be1825SJoseph Chen 	return 0;
25057be1825SJoseph Chen }
25157be1825SJoseph Chen 
25257be1825SJoseph Chen static int mmc_dm_reinit(void)
25357be1825SJoseph Chen {
25457be1825SJoseph Chen 	struct udevice *dev;
25557be1825SJoseph Chen 	struct uclass *uc;
25657be1825SJoseph Chen 	int ret;
25757be1825SJoseph Chen 
25857be1825SJoseph Chen 	if (uclass_get(UCLASS_MMC, &uc) || list_empty(&uc->dev_head))
25957be1825SJoseph Chen 		return 0;
26057be1825SJoseph Chen 
26157be1825SJoseph Chen 	list_for_each_entry(dev, &uc->dev_head, uclass_node) {
26257be1825SJoseph Chen 		ret = board_mmc_dm_reinit(dev);
26357be1825SJoseph Chen 		if (ret)
26457be1825SJoseph Chen 			return ret;
26557be1825SJoseph Chen 	}
26657be1825SJoseph Chen 
26757be1825SJoseph Chen 	return 0;
26857be1825SJoseph Chen }
26957be1825SJoseph Chen 
27074ec585eSJoseph Chen /* Check by property: "/compatible" */
27174ec585eSJoseph Chen static int dtb_check_ok(void *kfdt, void *ufdt)
27220647277SJoseph Chen {
27320647277SJoseph Chen 	const char *compat;
27474ec585eSJoseph Chen 	int index;
27520647277SJoseph Chen 
27684cb34e7SJoseph Chen 	/* TODO */
27784cb34e7SJoseph Chen 	return 1;
27884cb34e7SJoseph Chen 
27974ec585eSJoseph Chen 	for (index = 0;
28074ec585eSJoseph Chen 	     compat = fdt_stringlist_get(ufdt, 0, "compatible",
28174ec585eSJoseph Chen 					 index, NULL), compat;
28274ec585eSJoseph Chen 	     index++) {
28374ec585eSJoseph Chen 		debug("u-compat: %s\n", compat);
28474ec585eSJoseph Chen 		if (!fdt_node_check_compatible(kfdt, 0, compat))
2858f98eecbSJoseph Chen 			return 1;
28674ec585eSJoseph Chen 	}
28720647277SJoseph Chen 
28820647277SJoseph Chen 	return 0;
28920647277SJoseph Chen }
29020647277SJoseph Chen 
29157be1825SJoseph Chen int init_kernel_dtb(void)
29257be1825SJoseph Chen {
29395eb462eSJoseph Chen #ifndef CONFIG_USING_KERNEL_DTB_V2
29495eb462eSJoseph Chen 	void *ufdt_blob = (void *)gd->fdt_blob;
29595eb462eSJoseph Chen #endif
296a4fb9a7eSJoseph Chen 	ulong fdt_addr = 0;
29703781805SJoseph Chen 	int ret = -ENODEV;
29857be1825SJoseph Chen 
299*18b9d982SJoseph Chen 	printf("DM: v%d\n", IS_ENABLED(CONFIG_USING_KERNEL_DTB_V2) ? 2 : 1);
300*18b9d982SJoseph Chen 
301a4fb9a7eSJoseph Chen 	/*
302a4fb9a7eSJoseph Chen 	 * If memory size <= 128MB, we firstly try to get "fdt_addr1_r".
303a4fb9a7eSJoseph Chen 	 */
304a4fb9a7eSJoseph Chen 	if (gd->ram_size <= SZ_128M)
305a4fb9a7eSJoseph Chen 		fdt_addr = env_get_ulong("fdt_addr1_r", 16, 0);
306a4fb9a7eSJoseph Chen 
307a4fb9a7eSJoseph Chen 	if (!fdt_addr)
30857be1825SJoseph Chen 		fdt_addr = env_get_ulong("fdt_addr_r", 16, 0);
30957be1825SJoseph Chen 	if (!fdt_addr) {
31057be1825SJoseph Chen 		printf("No Found FDT Load Address.\n");
31120647277SJoseph Chen 		return -ENODEV;
31257be1825SJoseph Chen 	}
31357be1825SJoseph Chen 
31403781805SJoseph Chen 	if (IS_ENABLED(CONFIG_EMBED_KERNEL_DTB_ALWAYS)) {
31503781805SJoseph Chen 		printf("Always embed kernel dtb\n");
31603781805SJoseph Chen 		goto dtb_embed;
31703781805SJoseph Chen 	}
31803781805SJoseph Chen 
31957be1825SJoseph Chen 	ret = rockchip_read_dtb_file((void *)fdt_addr);
32020647277SJoseph Chen 	if (!ret) {
32120647277SJoseph Chen 		if (!dtb_check_ok((void *)fdt_addr, (void *)gd->fdt_blob)) {
32220647277SJoseph Chen 			ret = -EINVAL;
32320647277SJoseph Chen 			printf("Kernel dtb mismatch this platform!\n");
32420647277SJoseph Chen 		} else {
32520647277SJoseph Chen 			goto dtb_okay;
32620647277SJoseph Chen 		}
32720647277SJoseph Chen 	}
32820647277SJoseph Chen 
32903781805SJoseph Chen dtb_embed:
3303fc8bcd2SJoseph Chen 	if (gd->fdt_blob_kern) {
33120647277SJoseph Chen 		if (!dtb_check_ok((void *)gd->fdt_blob_kern, (void *)gd->fdt_blob)) {
33220647277SJoseph Chen 			printf("Embedded kernel dtb mismatch this platform!\n");
33320647277SJoseph Chen 			return -EINVAL;
33420647277SJoseph Chen 		}
33520647277SJoseph Chen 
33657be1825SJoseph Chen 		fdt_addr = (ulong)memalign(ARCH_DMA_MINALIGN,
33757be1825SJoseph Chen 				fdt_totalsize(gd->fdt_blob_kern));
33857be1825SJoseph Chen 		if (!fdt_addr)
33957be1825SJoseph Chen 			return -ENOMEM;
34057be1825SJoseph Chen 
34103781805SJoseph Chen 		/*
34203781805SJoseph Chen 		 * Alloc another space for this embed kernel dtb.
34303781805SJoseph Chen 		 * Because "fdt_addr_r" *MUST* be the fdt passed to kernel.
34403781805SJoseph Chen 		 */
34557be1825SJoseph Chen 		memcpy((void *)fdt_addr, gd->fdt_blob_kern,
34657be1825SJoseph Chen 		       fdt_totalsize(gd->fdt_blob_kern));
34703781805SJoseph Chen 		printf("DTB: %s\n", CONFIG_EMBED_KERNEL_DTB_PATH);
3487952efb8SJoseph Chen 	} else {
34957be1825SJoseph Chen 		printf("Failed to get kernel dtb, ret=%d\n", ret);
3507952efb8SJoseph Chen 		return -ENOENT;
35157be1825SJoseph Chen 	}
35257be1825SJoseph Chen 
35320647277SJoseph Chen dtb_okay:
35457be1825SJoseph Chen 	gd->fdt_blob = (void *)fdt_addr;
35557be1825SJoseph Chen 	hotkey_run(HK_FDT);
35657be1825SJoseph Chen 
35795eb462eSJoseph Chen #ifndef CONFIG_USING_KERNEL_DTB_V2
35857be1825SJoseph Chen 	/*
35957be1825SJoseph Chen 	 * There is a phandle miss match between U-Boot and kernel dtb node,
36057be1825SJoseph Chen 	 * we fixup it in U-Boot live dt nodes.
36157be1825SJoseph Chen 	 *
36257be1825SJoseph Chen 	 * CRU:	 all nodes.
36357be1825SJoseph Chen 	 * GPIO: key nodes.
36457be1825SJoseph Chen 	 */
36557be1825SJoseph Chen 	phandles_fixup_cru((void *)gd->fdt_blob);
36657be1825SJoseph Chen 	phandles_fixup_gpio((void *)gd->fdt_blob, (void *)ufdt_blob);
36795eb462eSJoseph Chen #endif
36857be1825SJoseph Chen 
369a85a3b31SJoseph Chen 	gd->flags |= GD_FLG_KDTB_READY;
370d276a5eaSJoseph Chen 	gd->of_root_f = gd->of_root;
37157be1825SJoseph Chen 	of_live_build((void *)gd->fdt_blob, (struct device_node **)&gd->of_root);
37257be1825SJoseph Chen 	dm_scan_fdt((void *)gd->fdt_blob, false);
37357be1825SJoseph Chen 
374*18b9d982SJoseph Chen #ifdef CONFIG_USING_KERNEL_DTB_V2
375*18b9d982SJoseph Chen 	dm_rm_kernel_dev();
376*18b9d982SJoseph Chen 	dm_rm_u_boot_dev();
377*18b9d982SJoseph Chen #endif
37857be1825SJoseph Chen 	/*
37957be1825SJoseph Chen 	 * There maybe something for the mmc devices to do after kernel dtb
38057be1825SJoseph Chen 	 * dm setup, eg: regain the clock device binding from kernel dtb.
38157be1825SJoseph Chen 	 */
38257be1825SJoseph Chen 	mmc_dm_reinit();
38357be1825SJoseph Chen 
38457be1825SJoseph Chen 	/* Reserve 'reserved-memory' */
38557be1825SJoseph Chen 	ret = boot_fdt_add_sysmem_rsv_regions((void *)gd->fdt_blob);
38657be1825SJoseph Chen 	if (ret)
38757be1825SJoseph Chen 		return ret;
38857be1825SJoseph Chen 
38957be1825SJoseph Chen 	return 0;
39057be1825SJoseph Chen }
39195eb462eSJoseph Chen 
392