xref: /rk3399_rockchip-uboot/drivers/core/root.c (revision 6d8950bff0f71be9b02c6c6255505ca44fd4a3da)
16494d708SSimon Glass /*
26494d708SSimon Glass  * Copyright (c) 2013 Google, Inc
36494d708SSimon Glass  *
46494d708SSimon Glass  * (C) Copyright 2012
56494d708SSimon Glass  * Pavel Herrmann <morpheus.ibis@gmail.com>
66494d708SSimon Glass  *
76494d708SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
86494d708SSimon Glass  */
96494d708SSimon Glass 
106494d708SSimon Glass #include <common.h>
116494d708SSimon Glass #include <errno.h>
1294f7afdfSSimon Glass #include <fdtdec.h>
136494d708SSimon Glass #include <malloc.h>
140e00a84cSMasahiro Yamada #include <linux/libfdt.h>
156494d708SSimon Glass #include <dm/device.h>
166494d708SSimon Glass #include <dm/device-internal.h>
176494d708SSimon Glass #include <dm/lists.h>
1819c8205eSSimon Glass #include <dm/of.h>
1919c8205eSSimon Glass #include <dm/of_access.h>
206494d708SSimon Glass #include <dm/platdata.h>
2119c8205eSSimon Glass #include <dm/read.h>
22fd536d81SJeroen Hofstee #include <dm/root.h>
236494d708SSimon Glass #include <dm/uclass.h>
246494d708SSimon Glass #include <dm/util.h>
256494d708SSimon Glass #include <linux/list.h>
266494d708SSimon Glass 
276494d708SSimon Glass DECLARE_GLOBAL_DATA_PTR;
286494d708SSimon Glass 
2966eaea6cSStefan Roese struct root_priv {
3066eaea6cSStefan Roese 	fdt_addr_t translation_offset;	/* optional translation offset */
3166eaea6cSStefan Roese };
3266eaea6cSStefan Roese 
336494d708SSimon Glass static const struct driver_info root_info = {
346494d708SSimon Glass 	.name		= "root_driver",
356494d708SSimon Glass };
366494d708SSimon Glass 
3754c5d08aSHeiko Schocher struct udevice *dm_root(void)
386494d708SSimon Glass {
396494d708SSimon Glass 	if (!gd->dm_root) {
406494d708SSimon Glass 		dm_warn("Virtual root driver does not exist!\n");
416494d708SSimon Glass 		return NULL;
426494d708SSimon Glass 	}
436494d708SSimon Glass 
446494d708SSimon Glass 	return gd->dm_root;
456494d708SSimon Glass }
466494d708SSimon Glass 
472f11cd91SSimon Glass void dm_fixup_for_gd_move(struct global_data *new_gd)
482f11cd91SSimon Glass {
492f11cd91SSimon Glass 	/* The sentinel node has moved, so update things that point to it */
50b0d9512aSLokesh Vutla 	if (gd->dm_root) {
512f11cd91SSimon Glass 		new_gd->uclass_root.next->prev = &new_gd->uclass_root;
522f11cd91SSimon Glass 		new_gd->uclass_root.prev->next = &new_gd->uclass_root;
532f11cd91SSimon Glass 	}
54b0d9512aSLokesh Vutla }
552f11cd91SSimon Glass 
5666eaea6cSStefan Roese fdt_addr_t dm_get_translation_offset(void)
5766eaea6cSStefan Roese {
5866eaea6cSStefan Roese 	struct udevice *root = dm_root();
5966eaea6cSStefan Roese 	struct root_priv *priv = dev_get_priv(root);
6066eaea6cSStefan Roese 
6166eaea6cSStefan Roese 	return priv->translation_offset;
6266eaea6cSStefan Roese }
6366eaea6cSStefan Roese 
6466eaea6cSStefan Roese void dm_set_translation_offset(fdt_addr_t offs)
6566eaea6cSStefan Roese {
6666eaea6cSStefan Roese 	struct udevice *root = dm_root();
6766eaea6cSStefan Roese 	struct root_priv *priv = dev_get_priv(root);
6866eaea6cSStefan Roese 
6966eaea6cSStefan Roese 	priv->translation_offset = offs;
7066eaea6cSStefan Roese }
7166eaea6cSStefan Roese 
72484fdf5bSMichal Simek #if defined(CONFIG_NEEDS_MANUAL_RELOC)
73484fdf5bSMichal Simek void fix_drivers(void)
74484fdf5bSMichal Simek {
75484fdf5bSMichal Simek 	struct driver *drv =
76484fdf5bSMichal Simek 		ll_entry_start(struct driver, driver);
77484fdf5bSMichal Simek 	const int n_ents = ll_entry_count(struct driver, driver);
78484fdf5bSMichal Simek 	struct driver *entry;
79484fdf5bSMichal Simek 
80484fdf5bSMichal Simek 	for (entry = drv; entry != drv + n_ents; entry++) {
81484fdf5bSMichal Simek 		if (entry->of_match)
82484fdf5bSMichal Simek 			entry->of_match = (const struct udevice_id *)
83484fdf5bSMichal Simek 				((u32)entry->of_match + gd->reloc_off);
84484fdf5bSMichal Simek 		if (entry->bind)
85484fdf5bSMichal Simek 			entry->bind += gd->reloc_off;
86484fdf5bSMichal Simek 		if (entry->probe)
87484fdf5bSMichal Simek 			entry->probe += gd->reloc_off;
88484fdf5bSMichal Simek 		if (entry->remove)
89484fdf5bSMichal Simek 			entry->remove += gd->reloc_off;
90484fdf5bSMichal Simek 		if (entry->unbind)
91484fdf5bSMichal Simek 			entry->unbind += gd->reloc_off;
92484fdf5bSMichal Simek 		if (entry->ofdata_to_platdata)
93484fdf5bSMichal Simek 			entry->ofdata_to_platdata += gd->reloc_off;
9431e1029aSMichal Simek 		if (entry->child_post_bind)
9531e1029aSMichal Simek 			entry->child_post_bind += gd->reloc_off;
96484fdf5bSMichal Simek 		if (entry->child_pre_probe)
97484fdf5bSMichal Simek 			entry->child_pre_probe += gd->reloc_off;
98484fdf5bSMichal Simek 		if (entry->child_post_remove)
99484fdf5bSMichal Simek 			entry->child_post_remove += gd->reloc_off;
100484fdf5bSMichal Simek 		/* OPS are fixed in every uclass post_probe function */
101484fdf5bSMichal Simek 		if (entry->ops)
102484fdf5bSMichal Simek 			entry->ops += gd->reloc_off;
103484fdf5bSMichal Simek 	}
104484fdf5bSMichal Simek }
105484fdf5bSMichal Simek 
106484fdf5bSMichal Simek void fix_uclass(void)
107484fdf5bSMichal Simek {
108484fdf5bSMichal Simek 	struct uclass_driver *uclass =
109484fdf5bSMichal Simek 		ll_entry_start(struct uclass_driver, uclass);
110484fdf5bSMichal Simek 	const int n_ents = ll_entry_count(struct uclass_driver, uclass);
111484fdf5bSMichal Simek 	struct uclass_driver *entry;
112484fdf5bSMichal Simek 
113484fdf5bSMichal Simek 	for (entry = uclass; entry != uclass + n_ents; entry++) {
114484fdf5bSMichal Simek 		if (entry->post_bind)
115484fdf5bSMichal Simek 			entry->post_bind += gd->reloc_off;
116484fdf5bSMichal Simek 		if (entry->pre_unbind)
117484fdf5bSMichal Simek 			entry->pre_unbind += gd->reloc_off;
11831e1029aSMichal Simek 		if (entry->pre_probe)
11931e1029aSMichal Simek 			entry->pre_probe += gd->reloc_off;
120484fdf5bSMichal Simek 		if (entry->post_probe)
121484fdf5bSMichal Simek 			entry->post_probe += gd->reloc_off;
122484fdf5bSMichal Simek 		if (entry->pre_remove)
123484fdf5bSMichal Simek 			entry->pre_remove += gd->reloc_off;
12431e1029aSMichal Simek 		if (entry->child_post_bind)
12531e1029aSMichal Simek 			entry->child_post_bind += gd->reloc_off;
12631e1029aSMichal Simek 		if (entry->child_pre_probe)
12731e1029aSMichal Simek 			entry->child_pre_probe += gd->reloc_off;
128484fdf5bSMichal Simek 		if (entry->init)
129484fdf5bSMichal Simek 			entry->init += gd->reloc_off;
130484fdf5bSMichal Simek 		if (entry->destroy)
131484fdf5bSMichal Simek 			entry->destroy += gd->reloc_off;
132484fdf5bSMichal Simek 		/* FIXME maybe also need to fix these ops */
133484fdf5bSMichal Simek 		if (entry->ops)
134484fdf5bSMichal Simek 			entry->ops += gd->reloc_off;
135484fdf5bSMichal Simek 	}
136484fdf5bSMichal Simek }
1375aeedebcSAngelo Dureghello 
1385aeedebcSAngelo Dureghello void fix_devices(void)
1395aeedebcSAngelo Dureghello {
1405aeedebcSAngelo Dureghello 	struct driver_info *dev =
1415aeedebcSAngelo Dureghello 		ll_entry_start(struct driver_info, driver_info);
1425aeedebcSAngelo Dureghello 	const int n_ents = ll_entry_count(struct driver_info, driver_info);
1435aeedebcSAngelo Dureghello 	struct driver_info *entry;
1445aeedebcSAngelo Dureghello 
1455aeedebcSAngelo Dureghello 	for (entry = dev; entry != dev + n_ents; entry++) {
1465aeedebcSAngelo Dureghello 		if (entry->platdata)
1475aeedebcSAngelo Dureghello 			entry->platdata += gd->reloc_off;
1485aeedebcSAngelo Dureghello 	}
1495aeedebcSAngelo Dureghello }
1505aeedebcSAngelo Dureghello 
151484fdf5bSMichal Simek #endif
152484fdf5bSMichal Simek 
15319c8205eSSimon Glass int dm_init(bool of_live)
1546494d708SSimon Glass {
1556494d708SSimon Glass 	int ret;
1566494d708SSimon Glass 
1576494d708SSimon Glass 	if (gd->dm_root) {
1586494d708SSimon Glass 		dm_warn("Virtual root driver already exists!\n");
1596494d708SSimon Glass 		return -EINVAL;
1606494d708SSimon Glass 	}
16189876a55SSimon Glass 	INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST);
1626494d708SSimon Glass 
163484fdf5bSMichal Simek #if defined(CONFIG_NEEDS_MANUAL_RELOC)
164484fdf5bSMichal Simek 	fix_drivers();
165484fdf5bSMichal Simek 	fix_uclass();
1665aeedebcSAngelo Dureghello 	fix_devices();
167484fdf5bSMichal Simek #endif
168484fdf5bSMichal Simek 
16900606d7eSSimon Glass 	ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
1706494d708SSimon Glass 	if (ret)
1716494d708SSimon Glass 		return ret;
1720f925822SMasahiro Yamada #if CONFIG_IS_ENABLED(OF_CONTROL)
17319c8205eSSimon Glass # if CONFIG_IS_ENABLED(OF_LIVE)
17419c8205eSSimon Glass 	if (of_live)
17519c8205eSSimon Glass 		DM_ROOT_NON_CONST->node = np_to_ofnode(gd->of_root);
17619c8205eSSimon Glass 	else
17719c8205eSSimon Glass #endif
1784984de2bSSimon Glass 		DM_ROOT_NON_CONST->node = offset_to_ofnode(0);
1792f3b95dbSSimon Glass #endif
1807497812dSSimon Glass 	ret = device_probe(DM_ROOT_NON_CONST);
1817497812dSSimon Glass 	if (ret)
1827497812dSSimon Glass 		return ret;
1836494d708SSimon Glass 
1846494d708SSimon Glass 	return 0;
1856494d708SSimon Glass }
1866494d708SSimon Glass 
1879adbd7a1SSimon Glass int dm_uninit(void)
1889adbd7a1SSimon Glass {
189706865afSStefan Roese 	device_remove(dm_root(), DM_REMOVE_NORMAL);
1909adbd7a1SSimon Glass 	device_unbind(dm_root());
1919adbd7a1SSimon Glass 
1929adbd7a1SSimon Glass 	return 0;
1939adbd7a1SSimon Glass }
1949adbd7a1SSimon Glass 
195bc85aa40SStefan Roese #if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
196bc85aa40SStefan Roese int dm_remove_devices_flags(uint flags)
197bc85aa40SStefan Roese {
198bc85aa40SStefan Roese 	device_remove(dm_root(), flags);
199bc85aa40SStefan Roese 
200bc85aa40SStefan Roese 	return 0;
201bc85aa40SStefan Roese }
202bc85aa40SStefan Roese #endif
203bc85aa40SStefan Roese 
20400606d7eSSimon Glass int dm_scan_platdata(bool pre_reloc_only)
2056494d708SSimon Glass {
2066494d708SSimon Glass 	int ret;
2076494d708SSimon Glass 
20800606d7eSSimon Glass 	ret = lists_bind_drivers(DM_ROOT_NON_CONST, pre_reloc_only);
2096494d708SSimon Glass 	if (ret == -ENOENT) {
2106494d708SSimon Glass 		dm_warn("Some drivers were not found\n");
2116494d708SSimon Glass 		ret = 0;
2126494d708SSimon Glass 	}
2136494d708SSimon Glass 
214cbf86d71SMasahiro Yamada 	return ret;
2156494d708SSimon Glass }
2166494d708SSimon Glass 
21719c8205eSSimon Glass #if CONFIG_IS_ENABLED(OF_LIVE)
21819c8205eSSimon Glass static int dm_scan_fdt_live(struct udevice *parent,
21919c8205eSSimon Glass 			    const struct device_node *node_parent,
22019c8205eSSimon Glass 			    bool pre_reloc_only)
22119c8205eSSimon Glass {
22219c8205eSSimon Glass 	struct device_node *np;
22319c8205eSSimon Glass 	int ret = 0, err;
22419c8205eSSimon Glass 
22519c8205eSSimon Glass 	for (np = node_parent->child; np; np = np->sibling) {
22619c8205eSSimon Glass 		if (pre_reloc_only &&
227930ceb12SJoseph Chen #ifdef CONFIG_USING_KERNEL_DTB
228b455f42cSJoseph Chen 		    (!of_find_property(np, "u-boot,dm-pre-reloc", NULL) &&
229930ceb12SJoseph Chen 		     !of_find_property(np, "u-boot,dm-spl", NULL)))
230930ceb12SJoseph Chen #else
23119c8205eSSimon Glass 		     !of_find_property(np, "u-boot,dm-pre-reloc", NULL))
232930ceb12SJoseph Chen #endif
23319c8205eSSimon Glass 			continue;
23419c8205eSSimon Glass 		if (!of_device_is_available(np)) {
235d42197e4SMasahiro Yamada 			pr_debug("   - ignoring disabled device\n");
23619c8205eSSimon Glass 			continue;
23719c8205eSSimon Glass 		}
23819c8205eSSimon Glass 		err = lists_bind_fdt(parent, np_to_ofnode(np), NULL);
23919c8205eSSimon Glass 		if (err && !ret) {
24019c8205eSSimon Glass 			ret = err;
24119c8205eSSimon Glass 			debug("%s: ret=%d\n", np->name, ret);
24219c8205eSSimon Glass 		}
2435120375cSJoseph Chen 
244dfe24df3SJoseph Chen 		/* There is no compatible in "/firmware", bind it by default. */
2455120375cSJoseph Chen 		if (!pre_reloc_only && !strcmp(np->name, "firmware"))
2465120375cSJoseph Chen 			ret = device_bind_driver_to_node(gd->dm_root,
2475120375cSJoseph Chen 				"firmware", np->name, np_to_ofnode(np), NULL);
24819c8205eSSimon Glass 	}
24919c8205eSSimon Glass 
25019c8205eSSimon Glass 	if (ret)
25119c8205eSSimon Glass 		dm_warn("Some drivers failed to bind\n");
25219c8205eSSimon Glass 
25319c8205eSSimon Glass 	return ret;
25419c8205eSSimon Glass }
25519c8205eSSimon Glass #endif /* CONFIG_IS_ENABLED(OF_LIVE) */
25619c8205eSSimon Glass 
25729629eb8SSimon Glass #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
258a771a04fSSimon Glass /**
259a771a04fSSimon Glass  * dm_scan_fdt_node() - Scan the device tree and bind drivers for a node
260a771a04fSSimon Glass  *
261a771a04fSSimon Glass  * This scans the subnodes of a device tree node and and creates a driver
262a771a04fSSimon Glass  * for each one.
263a771a04fSSimon Glass  *
264a771a04fSSimon Glass  * @parent: Parent device for the devices that will be created
265a771a04fSSimon Glass  * @blob: Pointer to device tree blob
266a771a04fSSimon Glass  * @offset: Offset of node to scan
267a771a04fSSimon Glass  * @pre_reloc_only: If true, bind only drivers with the DM_FLAG_PRE_RELOC
268a771a04fSSimon Glass  * flag. If false bind all drivers.
269a771a04fSSimon Glass  * @return 0 if OK, -ve on error
270a771a04fSSimon Glass  */
271a771a04fSSimon Glass static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
272a771a04fSSimon Glass 			    int offset, bool pre_reloc_only)
2736494d708SSimon Glass {
2746494d708SSimon Glass 	int ret = 0, err;
2756494d708SSimon Glass 
2761ca7e206SSimon Glass 	for (offset = fdt_first_subnode(blob, offset);
2771ca7e206SSimon Glass 	     offset > 0;
2781ca7e206SSimon Glass 	     offset = fdt_next_subnode(blob, offset)) {
27900606d7eSSimon Glass 		if (pre_reloc_only &&
28027326c7eSHeiko Stübner 		    !dm_fdt_pre_reloc(blob, offset))
28100606d7eSSimon Glass 			continue;
28294f7afdfSSimon Glass 		if (!fdtdec_get_is_enabled(blob, offset)) {
283d42197e4SMasahiro Yamada 			pr_debug("   - ignoring disabled device\n");
28494f7afdfSSimon Glass 			continue;
28594f7afdfSSimon Glass 		}
286f5b5719cSSimon Glass 		err = lists_bind_fdt(parent, offset_to_ofnode(offset), NULL);
287bc7b2f43SSimon Glass 		if (err && !ret) {
2886494d708SSimon Glass 			ret = err;
289bc7b2f43SSimon Glass 			debug("%s: ret=%d\n", fdt_get_name(blob, offset, NULL),
290bc7b2f43SSimon Glass 			      ret);
291bc7b2f43SSimon Glass 		}
292dfe24df3SJoseph Chen 
293*6d8950bfSJoseph Chen #if CONFIG_IS_ENABLED(SCMI_FIRMWARE)
294*6d8950bfSJoseph Chen 		const char *name;
295*6d8950bfSJoseph Chen 
296dfe24df3SJoseph Chen 		/* There is no compatible in "/firmware", bind it by default. */
297dfe24df3SJoseph Chen 		name = fdt_get_name(blob, offset, NULL);
298dfe24df3SJoseph Chen 		if (name && !strcmp(name, "firmware"))
299dfe24df3SJoseph Chen 			ret = device_bind_driver_to_node(parent, "firmware",
300dfe24df3SJoseph Chen 					name, offset_to_ofnode(offset), NULL);
301*6d8950bfSJoseph Chen #endif
3026494d708SSimon Glass 	}
3036494d708SSimon Glass 
3046494d708SSimon Glass 	if (ret)
3056494d708SSimon Glass 		dm_warn("Some drivers failed to bind\n");
3066494d708SSimon Glass 
3076494d708SSimon Glass 	return ret;
3086494d708SSimon Glass }
3091ca7e206SSimon Glass 
310cc7f66f7SSimon Glass int dm_scan_fdt_dev(struct udevice *dev)
311cc7f66f7SSimon Glass {
31219c8205eSSimon Glass 	if (!dev_of_valid(dev))
313cc7f66f7SSimon Glass 		return 0;
314cc7f66f7SSimon Glass 
31519c8205eSSimon Glass #if CONFIG_IS_ENABLED(OF_LIVE)
31619c8205eSSimon Glass 	if (of_live_active())
31719c8205eSSimon Glass 		return dm_scan_fdt_live(dev, dev_np(dev),
31819c8205eSSimon Glass 				gd->flags & GD_FLG_RELOC ? false : true);
31919c8205eSSimon Glass 	else
32019c8205eSSimon Glass #endif
321e160f7d4SSimon Glass 	return dm_scan_fdt_node(dev, gd->fdt_blob, dev_of_offset(dev),
322cc7f66f7SSimon Glass 				gd->flags & GD_FLG_RELOC ? false : true);
323cc7f66f7SSimon Glass }
324cc7f66f7SSimon Glass 
3251ca7e206SSimon Glass int dm_scan_fdt(const void *blob, bool pre_reloc_only)
3261ca7e206SSimon Glass {
32719c8205eSSimon Glass #if CONFIG_IS_ENABLED(OF_LIVE)
32819c8205eSSimon Glass 	if (of_live_active())
32919c8205eSSimon Glass 		return dm_scan_fdt_live(gd->dm_root, gd->of_root,
33019c8205eSSimon Glass 					pre_reloc_only);
33119c8205eSSimon Glass 	else
33219c8205eSSimon Glass #endif
3331ca7e206SSimon Glass 	return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only);
3341ca7e206SSimon Glass }
33546fb92f0SPatrice Chotard #else
33646fb92f0SPatrice Chotard static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
33746fb92f0SPatrice Chotard 			    int offset, bool pre_reloc_only)
33846fb92f0SPatrice Chotard {
33946fb92f0SPatrice Chotard 	return 0;
34046fb92f0SPatrice Chotard }
3416494d708SSimon Glass #endif
3426494d708SSimon Glass 
34346fb92f0SPatrice Chotard int dm_extended_scan_fdt(const void *blob, bool pre_reloc_only)
34446fb92f0SPatrice Chotard {
34546fb92f0SPatrice Chotard 	int node, ret;
34646fb92f0SPatrice Chotard 
34746fb92f0SPatrice Chotard 	ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
34846fb92f0SPatrice Chotard 	if (ret) {
34946fb92f0SPatrice Chotard 		debug("dm_scan_fdt() failed: %d\n", ret);
35046fb92f0SPatrice Chotard 		return ret;
35146fb92f0SPatrice Chotard 	}
35246fb92f0SPatrice Chotard 
35346fb92f0SPatrice Chotard 	/* bind fixed-clock */
35446fb92f0SPatrice Chotard 	node = ofnode_to_offset(ofnode_path("/clocks"));
35546fb92f0SPatrice Chotard 	/* if no DT "clocks" node, no need to go further */
35646fb92f0SPatrice Chotard 	if (node < 0)
35746fb92f0SPatrice Chotard 		return ret;
35846fb92f0SPatrice Chotard 
35946fb92f0SPatrice Chotard 	ret = dm_scan_fdt_node(gd->dm_root, gd->fdt_blob, node,
36046fb92f0SPatrice Chotard 			       pre_reloc_only);
36146fb92f0SPatrice Chotard 	if (ret)
36246fb92f0SPatrice Chotard 		debug("dm_scan_fdt_node() failed: %d\n", ret);
36346fb92f0SPatrice Chotard 
36446fb92f0SPatrice Chotard 	return ret;
36546fb92f0SPatrice Chotard }
36646fb92f0SPatrice Chotard 
367bb58503dSSimon Glass __weak int dm_scan_other(bool pre_reloc_only)
368bb58503dSSimon Glass {
369bb58503dSSimon Glass 	return 0;
370bb58503dSSimon Glass }
371bb58503dSSimon Glass 
372ab7cd627SSimon Glass int dm_init_and_scan(bool pre_reloc_only)
373ab7cd627SSimon Glass {
374ab7cd627SSimon Glass 	int ret;
375ab7cd627SSimon Glass 
37619c8205eSSimon Glass 	ret = dm_init(IS_ENABLED(CONFIG_OF_LIVE));
377ab7cd627SSimon Glass 	if (ret) {
378ab7cd627SSimon Glass 		debug("dm_init() failed: %d\n", ret);
379ab7cd627SSimon Glass 		return ret;
380ab7cd627SSimon Glass 	}
381ab7cd627SSimon Glass 	ret = dm_scan_platdata(pre_reloc_only);
382ab7cd627SSimon Glass 	if (ret) {
383ab7cd627SSimon Glass 		debug("dm_scan_platdata() failed: %d\n", ret);
384ab7cd627SSimon Glass 		return ret;
385ab7cd627SSimon Glass 	}
386b2b0d3e7SSimon Glass 
38729629eb8SSimon Glass 	if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
38846fb92f0SPatrice Chotard 		ret = dm_extended_scan_fdt(gd->fdt_blob, pre_reloc_only);
389ab7cd627SSimon Glass 		if (ret) {
39046fb92f0SPatrice Chotard 			debug("dm_extended_scan_dt() failed: %d\n", ret);
391ab7cd627SSimon Glass 			return ret;
392ab7cd627SSimon Glass 		}
393b2b0d3e7SSimon Glass 	}
394b2b0d3e7SSimon Glass 
395bb58503dSSimon Glass 	ret = dm_scan_other(pre_reloc_only);
396bb58503dSSimon Glass 	if (ret)
397bb58503dSSimon Glass 		return ret;
398ab7cd627SSimon Glass 
399ab7cd627SSimon Glass 	return 0;
400ab7cd627SSimon Glass }
401ab7cd627SSimon Glass 
4026494d708SSimon Glass /* This is the root driver - all drivers are children of this */
4036494d708SSimon Glass U_BOOT_DRIVER(root_driver) = {
4046494d708SSimon Glass 	.name	= "root_driver",
4056494d708SSimon Glass 	.id	= UCLASS_ROOT,
40666eaea6cSStefan Roese 	.priv_auto_alloc_size = sizeof(struct root_priv),
4076494d708SSimon Glass };
4086494d708SSimon Glass 
4096494d708SSimon Glass /* This is the root uclass */
4106494d708SSimon Glass UCLASS_DRIVER(root) = {
4116494d708SSimon Glass 	.name	= "root",
4126494d708SSimon Glass 	.id	= UCLASS_ROOT,
4136494d708SSimon Glass };
414