xref: /rk3399_rockchip-uboot/drivers/core/root.c (revision dfe24df30ae9908b9af6d7bd818a8619d02632cb)
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 
244*dfe24df3SJoseph 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;
275*dfe24df3SJoseph Chen 	const char *name;
2766494d708SSimon Glass 
2771ca7e206SSimon Glass 	for (offset = fdt_first_subnode(blob, offset);
2781ca7e206SSimon Glass 	     offset > 0;
2791ca7e206SSimon Glass 	     offset = fdt_next_subnode(blob, offset)) {
28000606d7eSSimon Glass 		if (pre_reloc_only &&
28127326c7eSHeiko Stübner 		    !dm_fdt_pre_reloc(blob, offset))
28200606d7eSSimon Glass 			continue;
28394f7afdfSSimon Glass 		if (!fdtdec_get_is_enabled(blob, offset)) {
284d42197e4SMasahiro Yamada 			pr_debug("   - ignoring disabled device\n");
28594f7afdfSSimon Glass 			continue;
28694f7afdfSSimon Glass 		}
287f5b5719cSSimon Glass 		err = lists_bind_fdt(parent, offset_to_ofnode(offset), NULL);
288bc7b2f43SSimon Glass 		if (err && !ret) {
2896494d708SSimon Glass 			ret = err;
290bc7b2f43SSimon Glass 			debug("%s: ret=%d\n", fdt_get_name(blob, offset, NULL),
291bc7b2f43SSimon Glass 			      ret);
292bc7b2f43SSimon Glass 		}
293*dfe24df3SJoseph Chen 
294*dfe24df3SJoseph Chen 		/* There is no compatible in "/firmware", bind it by default. */
295*dfe24df3SJoseph Chen 		name = fdt_get_name(blob, offset, NULL);
296*dfe24df3SJoseph Chen 		if (name && !strcmp(name, "firmware"))
297*dfe24df3SJoseph Chen 			ret = device_bind_driver_to_node(parent, "firmware",
298*dfe24df3SJoseph Chen 					name, offset_to_ofnode(offset), NULL);
2996494d708SSimon Glass 	}
3006494d708SSimon Glass 
3016494d708SSimon Glass 	if (ret)
3026494d708SSimon Glass 		dm_warn("Some drivers failed to bind\n");
3036494d708SSimon Glass 
3046494d708SSimon Glass 	return ret;
3056494d708SSimon Glass }
3061ca7e206SSimon Glass 
307cc7f66f7SSimon Glass int dm_scan_fdt_dev(struct udevice *dev)
308cc7f66f7SSimon Glass {
30919c8205eSSimon Glass 	if (!dev_of_valid(dev))
310cc7f66f7SSimon Glass 		return 0;
311cc7f66f7SSimon Glass 
31219c8205eSSimon Glass #if CONFIG_IS_ENABLED(OF_LIVE)
31319c8205eSSimon Glass 	if (of_live_active())
31419c8205eSSimon Glass 		return dm_scan_fdt_live(dev, dev_np(dev),
31519c8205eSSimon Glass 				gd->flags & GD_FLG_RELOC ? false : true);
31619c8205eSSimon Glass 	else
31719c8205eSSimon Glass #endif
318e160f7d4SSimon Glass 	return dm_scan_fdt_node(dev, gd->fdt_blob, dev_of_offset(dev),
319cc7f66f7SSimon Glass 				gd->flags & GD_FLG_RELOC ? false : true);
320cc7f66f7SSimon Glass }
321cc7f66f7SSimon Glass 
3221ca7e206SSimon Glass int dm_scan_fdt(const void *blob, bool pre_reloc_only)
3231ca7e206SSimon Glass {
32419c8205eSSimon Glass #if CONFIG_IS_ENABLED(OF_LIVE)
32519c8205eSSimon Glass 	if (of_live_active())
32619c8205eSSimon Glass 		return dm_scan_fdt_live(gd->dm_root, gd->of_root,
32719c8205eSSimon Glass 					pre_reloc_only);
32819c8205eSSimon Glass 	else
32919c8205eSSimon Glass #endif
3301ca7e206SSimon Glass 	return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only);
3311ca7e206SSimon Glass }
33246fb92f0SPatrice Chotard #else
33346fb92f0SPatrice Chotard static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
33446fb92f0SPatrice Chotard 			    int offset, bool pre_reloc_only)
33546fb92f0SPatrice Chotard {
33646fb92f0SPatrice Chotard 	return 0;
33746fb92f0SPatrice Chotard }
3386494d708SSimon Glass #endif
3396494d708SSimon Glass 
34046fb92f0SPatrice Chotard int dm_extended_scan_fdt(const void *blob, bool pre_reloc_only)
34146fb92f0SPatrice Chotard {
34246fb92f0SPatrice Chotard 	int node, ret;
34346fb92f0SPatrice Chotard 
34446fb92f0SPatrice Chotard 	ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
34546fb92f0SPatrice Chotard 	if (ret) {
34646fb92f0SPatrice Chotard 		debug("dm_scan_fdt() failed: %d\n", ret);
34746fb92f0SPatrice Chotard 		return ret;
34846fb92f0SPatrice Chotard 	}
34946fb92f0SPatrice Chotard 
35046fb92f0SPatrice Chotard 	/* bind fixed-clock */
35146fb92f0SPatrice Chotard 	node = ofnode_to_offset(ofnode_path("/clocks"));
35246fb92f0SPatrice Chotard 	/* if no DT "clocks" node, no need to go further */
35346fb92f0SPatrice Chotard 	if (node < 0)
35446fb92f0SPatrice Chotard 		return ret;
35546fb92f0SPatrice Chotard 
35646fb92f0SPatrice Chotard 	ret = dm_scan_fdt_node(gd->dm_root, gd->fdt_blob, node,
35746fb92f0SPatrice Chotard 			       pre_reloc_only);
35846fb92f0SPatrice Chotard 	if (ret)
35946fb92f0SPatrice Chotard 		debug("dm_scan_fdt_node() failed: %d\n", ret);
36046fb92f0SPatrice Chotard 
36146fb92f0SPatrice Chotard 	return ret;
36246fb92f0SPatrice Chotard }
36346fb92f0SPatrice Chotard 
364bb58503dSSimon Glass __weak int dm_scan_other(bool pre_reloc_only)
365bb58503dSSimon Glass {
366bb58503dSSimon Glass 	return 0;
367bb58503dSSimon Glass }
368bb58503dSSimon Glass 
369ab7cd627SSimon Glass int dm_init_and_scan(bool pre_reloc_only)
370ab7cd627SSimon Glass {
371ab7cd627SSimon Glass 	int ret;
372ab7cd627SSimon Glass 
37319c8205eSSimon Glass 	ret = dm_init(IS_ENABLED(CONFIG_OF_LIVE));
374ab7cd627SSimon Glass 	if (ret) {
375ab7cd627SSimon Glass 		debug("dm_init() failed: %d\n", ret);
376ab7cd627SSimon Glass 		return ret;
377ab7cd627SSimon Glass 	}
378ab7cd627SSimon Glass 	ret = dm_scan_platdata(pre_reloc_only);
379ab7cd627SSimon Glass 	if (ret) {
380ab7cd627SSimon Glass 		debug("dm_scan_platdata() failed: %d\n", ret);
381ab7cd627SSimon Glass 		return ret;
382ab7cd627SSimon Glass 	}
383b2b0d3e7SSimon Glass 
38429629eb8SSimon Glass 	if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
38546fb92f0SPatrice Chotard 		ret = dm_extended_scan_fdt(gd->fdt_blob, pre_reloc_only);
386ab7cd627SSimon Glass 		if (ret) {
38746fb92f0SPatrice Chotard 			debug("dm_extended_scan_dt() failed: %d\n", ret);
388ab7cd627SSimon Glass 			return ret;
389ab7cd627SSimon Glass 		}
390b2b0d3e7SSimon Glass 	}
391b2b0d3e7SSimon Glass 
392bb58503dSSimon Glass 	ret = dm_scan_other(pre_reloc_only);
393bb58503dSSimon Glass 	if (ret)
394bb58503dSSimon Glass 		return ret;
395ab7cd627SSimon Glass 
396ab7cd627SSimon Glass 	return 0;
397ab7cd627SSimon Glass }
398ab7cd627SSimon Glass 
3996494d708SSimon Glass /* This is the root driver - all drivers are children of this */
4006494d708SSimon Glass U_BOOT_DRIVER(root_driver) = {
4016494d708SSimon Glass 	.name	= "root_driver",
4026494d708SSimon Glass 	.id	= UCLASS_ROOT,
40366eaea6cSStefan Roese 	.priv_auto_alloc_size = sizeof(struct root_priv),
4046494d708SSimon Glass };
4056494d708SSimon Glass 
4066494d708SSimon Glass /* This is the root uclass */
4076494d708SSimon Glass UCLASS_DRIVER(root) = {
4086494d708SSimon Glass 	.name	= "root",
4096494d708SSimon Glass 	.id	= UCLASS_ROOT,
4106494d708SSimon Glass };
411