xref: /openbmc/u-boot/drivers/core/root.c (revision 7ff485c68b7e5573e5a4a877066e98398283a24f)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
26494d708SSimon Glass /*
36494d708SSimon Glass  * Copyright (c) 2013 Google, Inc
46494d708SSimon Glass  *
56494d708SSimon Glass  * (C) Copyright 2012
66494d708SSimon Glass  * Pavel Herrmann <morpheus.ibis@gmail.com>
76494d708SSimon Glass  */
86494d708SSimon Glass 
96494d708SSimon Glass #include <common.h>
106494d708SSimon Glass #include <errno.h>
1194f7afdfSSimon Glass #include <fdtdec.h>
126494d708SSimon Glass #include <malloc.h>
13b08c8c48SMasahiro Yamada #include <linux/libfdt.h>
146494d708SSimon Glass #include <dm/device.h>
156494d708SSimon Glass #include <dm/device-internal.h>
166494d708SSimon Glass #include <dm/lists.h>
1719c8205eSSimon Glass #include <dm/of.h>
1819c8205eSSimon Glass #include <dm/of_access.h>
196494d708SSimon Glass #include <dm/platdata.h>
2019c8205eSSimon Glass #include <dm/read.h>
21fd536d81SJeroen Hofstee #include <dm/root.h>
226494d708SSimon Glass #include <dm/uclass.h>
236494d708SSimon Glass #include <dm/util.h>
246494d708SSimon Glass #include <linux/list.h>
256494d708SSimon Glass 
266494d708SSimon Glass DECLARE_GLOBAL_DATA_PTR;
276494d708SSimon Glass 
2866eaea6cSStefan Roese struct root_priv {
2966eaea6cSStefan Roese 	fdt_addr_t translation_offset;	/* optional translation offset */
3066eaea6cSStefan Roese };
3166eaea6cSStefan Roese 
326494d708SSimon Glass static const struct driver_info root_info = {
336494d708SSimon Glass 	.name		= "root_driver",
346494d708SSimon Glass };
356494d708SSimon Glass 
dm_root(void)3654c5d08aSHeiko Schocher struct udevice *dm_root(void)
376494d708SSimon Glass {
386494d708SSimon Glass 	if (!gd->dm_root) {
396494d708SSimon Glass 		dm_warn("Virtual root driver does not exist!\n");
406494d708SSimon Glass 		return NULL;
416494d708SSimon Glass 	}
426494d708SSimon Glass 
436494d708SSimon Glass 	return gd->dm_root;
446494d708SSimon Glass }
456494d708SSimon Glass 
dm_fixup_for_gd_move(struct global_data * new_gd)462f11cd91SSimon Glass void dm_fixup_for_gd_move(struct global_data *new_gd)
472f11cd91SSimon Glass {
482f11cd91SSimon Glass 	/* The sentinel node has moved, so update things that point to it */
49b0d9512aSLokesh Vutla 	if (gd->dm_root) {
502f11cd91SSimon Glass 		new_gd->uclass_root.next->prev = &new_gd->uclass_root;
512f11cd91SSimon Glass 		new_gd->uclass_root.prev->next = &new_gd->uclass_root;
522f11cd91SSimon Glass 	}
53b0d9512aSLokesh Vutla }
542f11cd91SSimon Glass 
dm_get_translation_offset(void)5566eaea6cSStefan Roese fdt_addr_t dm_get_translation_offset(void)
5666eaea6cSStefan Roese {
5766eaea6cSStefan Roese 	struct udevice *root = dm_root();
5866eaea6cSStefan Roese 	struct root_priv *priv = dev_get_priv(root);
5966eaea6cSStefan Roese 
6066eaea6cSStefan Roese 	return priv->translation_offset;
6166eaea6cSStefan Roese }
6266eaea6cSStefan Roese 
dm_set_translation_offset(fdt_addr_t offs)6366eaea6cSStefan Roese void dm_set_translation_offset(fdt_addr_t offs)
6466eaea6cSStefan Roese {
6566eaea6cSStefan Roese 	struct udevice *root = dm_root();
6666eaea6cSStefan Roese 	struct root_priv *priv = dev_get_priv(root);
6766eaea6cSStefan Roese 
6866eaea6cSStefan Roese 	priv->translation_offset = offs;
6966eaea6cSStefan Roese }
7066eaea6cSStefan Roese 
71484fdf5bSMichal Simek #if defined(CONFIG_NEEDS_MANUAL_RELOC)
fix_drivers(void)72484fdf5bSMichal Simek void fix_drivers(void)
73484fdf5bSMichal Simek {
74484fdf5bSMichal Simek 	struct driver *drv =
75484fdf5bSMichal Simek 		ll_entry_start(struct driver, driver);
76484fdf5bSMichal Simek 	const int n_ents = ll_entry_count(struct driver, driver);
77484fdf5bSMichal Simek 	struct driver *entry;
78484fdf5bSMichal Simek 
79484fdf5bSMichal Simek 	for (entry = drv; entry != drv + n_ents; entry++) {
80484fdf5bSMichal Simek 		if (entry->of_match)
81484fdf5bSMichal Simek 			entry->of_match = (const struct udevice_id *)
82484fdf5bSMichal Simek 				((u32)entry->of_match + gd->reloc_off);
83484fdf5bSMichal Simek 		if (entry->bind)
84484fdf5bSMichal Simek 			entry->bind += gd->reloc_off;
85484fdf5bSMichal Simek 		if (entry->probe)
86484fdf5bSMichal Simek 			entry->probe += gd->reloc_off;
87484fdf5bSMichal Simek 		if (entry->remove)
88484fdf5bSMichal Simek 			entry->remove += gd->reloc_off;
89484fdf5bSMichal Simek 		if (entry->unbind)
90484fdf5bSMichal Simek 			entry->unbind += gd->reloc_off;
91484fdf5bSMichal Simek 		if (entry->ofdata_to_platdata)
92484fdf5bSMichal Simek 			entry->ofdata_to_platdata += gd->reloc_off;
9331e1029aSMichal Simek 		if (entry->child_post_bind)
9431e1029aSMichal Simek 			entry->child_post_bind += gd->reloc_off;
95484fdf5bSMichal Simek 		if (entry->child_pre_probe)
96484fdf5bSMichal Simek 			entry->child_pre_probe += gd->reloc_off;
97484fdf5bSMichal Simek 		if (entry->child_post_remove)
98484fdf5bSMichal Simek 			entry->child_post_remove += gd->reloc_off;
99484fdf5bSMichal Simek 		/* OPS are fixed in every uclass post_probe function */
100484fdf5bSMichal Simek 		if (entry->ops)
101484fdf5bSMichal Simek 			entry->ops += gd->reloc_off;
102484fdf5bSMichal Simek 	}
103484fdf5bSMichal Simek }
104484fdf5bSMichal Simek 
fix_uclass(void)105484fdf5bSMichal Simek void fix_uclass(void)
106484fdf5bSMichal Simek {
107484fdf5bSMichal Simek 	struct uclass_driver *uclass =
108484fdf5bSMichal Simek 		ll_entry_start(struct uclass_driver, uclass);
109484fdf5bSMichal Simek 	const int n_ents = ll_entry_count(struct uclass_driver, uclass);
110484fdf5bSMichal Simek 	struct uclass_driver *entry;
111484fdf5bSMichal Simek 
112484fdf5bSMichal Simek 	for (entry = uclass; entry != uclass + n_ents; entry++) {
113484fdf5bSMichal Simek 		if (entry->post_bind)
114484fdf5bSMichal Simek 			entry->post_bind += gd->reloc_off;
115484fdf5bSMichal Simek 		if (entry->pre_unbind)
116484fdf5bSMichal Simek 			entry->pre_unbind += gd->reloc_off;
11731e1029aSMichal Simek 		if (entry->pre_probe)
11831e1029aSMichal Simek 			entry->pre_probe += gd->reloc_off;
119484fdf5bSMichal Simek 		if (entry->post_probe)
120484fdf5bSMichal Simek 			entry->post_probe += gd->reloc_off;
121484fdf5bSMichal Simek 		if (entry->pre_remove)
122484fdf5bSMichal Simek 			entry->pre_remove += gd->reloc_off;
12331e1029aSMichal Simek 		if (entry->child_post_bind)
12431e1029aSMichal Simek 			entry->child_post_bind += gd->reloc_off;
12531e1029aSMichal Simek 		if (entry->child_pre_probe)
12631e1029aSMichal Simek 			entry->child_pre_probe += gd->reloc_off;
127484fdf5bSMichal Simek 		if (entry->init)
128484fdf5bSMichal Simek 			entry->init += gd->reloc_off;
129484fdf5bSMichal Simek 		if (entry->destroy)
130484fdf5bSMichal Simek 			entry->destroy += gd->reloc_off;
131484fdf5bSMichal Simek 		/* FIXME maybe also need to fix these ops */
132484fdf5bSMichal Simek 		if (entry->ops)
133484fdf5bSMichal Simek 			entry->ops += gd->reloc_off;
134484fdf5bSMichal Simek 	}
135484fdf5bSMichal Simek }
1365aeedebcSAngelo Dureghello 
fix_devices(void)1375aeedebcSAngelo Dureghello void fix_devices(void)
1385aeedebcSAngelo Dureghello {
1395aeedebcSAngelo Dureghello 	struct driver_info *dev =
1405aeedebcSAngelo Dureghello 		ll_entry_start(struct driver_info, driver_info);
1415aeedebcSAngelo Dureghello 	const int n_ents = ll_entry_count(struct driver_info, driver_info);
1425aeedebcSAngelo Dureghello 	struct driver_info *entry;
1435aeedebcSAngelo Dureghello 
1445aeedebcSAngelo Dureghello 	for (entry = dev; entry != dev + n_ents; entry++) {
1455aeedebcSAngelo Dureghello 		if (entry->platdata)
1465aeedebcSAngelo Dureghello 			entry->platdata += gd->reloc_off;
1475aeedebcSAngelo Dureghello 	}
1485aeedebcSAngelo Dureghello }
1495aeedebcSAngelo Dureghello 
150484fdf5bSMichal Simek #endif
151484fdf5bSMichal Simek 
dm_init(bool of_live)15219c8205eSSimon Glass int dm_init(bool of_live)
1536494d708SSimon Glass {
1546494d708SSimon Glass 	int ret;
1556494d708SSimon Glass 
1566494d708SSimon Glass 	if (gd->dm_root) {
1576494d708SSimon Glass 		dm_warn("Virtual root driver already exists!\n");
1586494d708SSimon Glass 		return -EINVAL;
1596494d708SSimon Glass 	}
16089876a55SSimon Glass 	INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST);
1616494d708SSimon Glass 
162484fdf5bSMichal Simek #if defined(CONFIG_NEEDS_MANUAL_RELOC)
163484fdf5bSMichal Simek 	fix_drivers();
164484fdf5bSMichal Simek 	fix_uclass();
1655aeedebcSAngelo Dureghello 	fix_devices();
166484fdf5bSMichal Simek #endif
167484fdf5bSMichal Simek 
16800606d7eSSimon Glass 	ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
1696494d708SSimon Glass 	if (ret)
1706494d708SSimon Glass 		return ret;
1710f925822SMasahiro Yamada #if CONFIG_IS_ENABLED(OF_CONTROL)
17219c8205eSSimon Glass # if CONFIG_IS_ENABLED(OF_LIVE)
17319c8205eSSimon Glass 	if (of_live)
17419c8205eSSimon Glass 		DM_ROOT_NON_CONST->node = np_to_ofnode(gd->of_root);
17519c8205eSSimon Glass 	else
17619c8205eSSimon Glass #endif
1774984de2bSSimon Glass 		DM_ROOT_NON_CONST->node = offset_to_ofnode(0);
1782f3b95dbSSimon Glass #endif
1797497812dSSimon Glass 	ret = device_probe(DM_ROOT_NON_CONST);
1807497812dSSimon Glass 	if (ret)
1817497812dSSimon Glass 		return ret;
1826494d708SSimon Glass 
1836494d708SSimon Glass 	return 0;
1846494d708SSimon Glass }
1856494d708SSimon Glass 
dm_uninit(void)1869adbd7a1SSimon Glass int dm_uninit(void)
1879adbd7a1SSimon Glass {
188706865afSStefan Roese 	device_remove(dm_root(), DM_REMOVE_NORMAL);
1899adbd7a1SSimon Glass 	device_unbind(dm_root());
190*c483f4ceSJean-Jacques Hiblot 	gd->dm_root = NULL;
1919adbd7a1SSimon Glass 
1929adbd7a1SSimon Glass 	return 0;
1939adbd7a1SSimon Glass }
1949adbd7a1SSimon Glass 
195bc85aa40SStefan Roese #if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
dm_remove_devices_flags(uint flags)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 
dm_scan_platdata(bool pre_reloc_only)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)
dm_scan_fdt_live(struct udevice * parent,const struct device_node * node_parent,bool pre_reloc_only)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) {
2268e39afcdSBin Meng 		/* "chosen" node isn't a device itself but may contain some: */
2278e39afcdSBin Meng 		if (!strcmp(np->name, "chosen")) {
2288e39afcdSBin Meng 			pr_debug("parsing subnodes of \"chosen\"\n");
2298e39afcdSBin Meng 
2308e39afcdSBin Meng 			err = dm_scan_fdt_live(parent, np, pre_reloc_only);
2318e39afcdSBin Meng 			if (err && !ret)
2328e39afcdSBin Meng 				ret = err;
2338e39afcdSBin Meng 			continue;
2348e39afcdSBin Meng 		}
2358e39afcdSBin Meng 
23619c8205eSSimon Glass 		if (!of_device_is_available(np)) {
237ceb91909SMasahiro Yamada 			pr_debug("   - ignoring disabled device\n");
23819c8205eSSimon Glass 			continue;
23919c8205eSSimon Glass 		}
2408d773c4aSBin Meng 		err = lists_bind_fdt(parent, np_to_ofnode(np), NULL,
2418d773c4aSBin Meng 				     pre_reloc_only);
24219c8205eSSimon Glass 		if (err && !ret) {
24319c8205eSSimon Glass 			ret = err;
24419c8205eSSimon Glass 			debug("%s: ret=%d\n", np->name, ret);
24519c8205eSSimon Glass 		}
24619c8205eSSimon Glass 	}
24719c8205eSSimon Glass 
24819c8205eSSimon Glass 	if (ret)
24919c8205eSSimon Glass 		dm_warn("Some drivers failed to bind\n");
25019c8205eSSimon Glass 
25119c8205eSSimon Glass 	return ret;
25219c8205eSSimon Glass }
25319c8205eSSimon Glass #endif /* CONFIG_IS_ENABLED(OF_LIVE) */
25419c8205eSSimon Glass 
25529629eb8SSimon Glass #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
256a771a04fSSimon Glass /**
257a771a04fSSimon Glass  * dm_scan_fdt_node() - Scan the device tree and bind drivers for a node
258a771a04fSSimon Glass  *
259a771a04fSSimon Glass  * This scans the subnodes of a device tree node and and creates a driver
260a771a04fSSimon Glass  * for each one.
261a771a04fSSimon Glass  *
262a771a04fSSimon Glass  * @parent: Parent device for the devices that will be created
263a771a04fSSimon Glass  * @blob: Pointer to device tree blob
264a771a04fSSimon Glass  * @offset: Offset of node to scan
265a771a04fSSimon Glass  * @pre_reloc_only: If true, bind only drivers with the DM_FLAG_PRE_RELOC
266a771a04fSSimon Glass  * flag. If false bind all drivers.
267a771a04fSSimon Glass  * @return 0 if OK, -ve on error
268a771a04fSSimon Glass  */
dm_scan_fdt_node(struct udevice * parent,const void * blob,int offset,bool pre_reloc_only)269a771a04fSSimon Glass static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
270a771a04fSSimon Glass 			    int offset, bool pre_reloc_only)
2716494d708SSimon Glass {
2726494d708SSimon Glass 	int ret = 0, err;
2736494d708SSimon Glass 
2741ca7e206SSimon Glass 	for (offset = fdt_first_subnode(blob, offset);
2751ca7e206SSimon Glass 	     offset > 0;
2761ca7e206SSimon Glass 	     offset = fdt_next_subnode(blob, offset)) {
277747558d0SJens Wiklander 		const char *node_name = fdt_get_name(blob, offset, NULL);
278747558d0SJens Wiklander 
279747558d0SJens Wiklander 		/*
280747558d0SJens Wiklander 		 * The "chosen" and "firmware" nodes aren't devices
281747558d0SJens Wiklander 		 * themselves but may contain some:
282747558d0SJens Wiklander 		 */
283747558d0SJens Wiklander 		if (!strcmp(node_name, "chosen") ||
284747558d0SJens Wiklander 		    !strcmp(node_name, "firmware")) {
285747558d0SJens Wiklander 			pr_debug("parsing subnodes of \"%s\"\n", node_name);
286f2006808SRob Clark 
287f2006808SRob Clark 			err = dm_scan_fdt_node(parent, blob, offset,
288f2006808SRob Clark 					       pre_reloc_only);
289f2006808SRob Clark 			if (err && !ret)
290f2006808SRob Clark 				ret = err;
291f2006808SRob Clark 			continue;
292f2006808SRob Clark 		}
293f2006808SRob Clark 
29494f7afdfSSimon Glass 		if (!fdtdec_get_is_enabled(blob, offset)) {
295ceb91909SMasahiro Yamada 			pr_debug("   - ignoring disabled device\n");
29694f7afdfSSimon Glass 			continue;
29794f7afdfSSimon Glass 		}
2988d773c4aSBin Meng 		err = lists_bind_fdt(parent, offset_to_ofnode(offset), NULL,
2998d773c4aSBin Meng 				     pre_reloc_only);
300bc7b2f43SSimon Glass 		if (err && !ret) {
3016494d708SSimon Glass 			ret = err;
302747558d0SJens Wiklander 			debug("%s: ret=%d\n", node_name, ret);
303bc7b2f43SSimon Glass 		}
3046494d708SSimon Glass 	}
3056494d708SSimon Glass 
3066494d708SSimon Glass 	if (ret)
3076494d708SSimon Glass 		dm_warn("Some drivers failed to bind\n");
3086494d708SSimon Glass 
3096494d708SSimon Glass 	return ret;
3106494d708SSimon Glass }
3111ca7e206SSimon Glass 
dm_scan_fdt_dev(struct udevice * dev)312cc7f66f7SSimon Glass int dm_scan_fdt_dev(struct udevice *dev)
313cc7f66f7SSimon Glass {
31419c8205eSSimon Glass 	if (!dev_of_valid(dev))
315cc7f66f7SSimon Glass 		return 0;
316cc7f66f7SSimon Glass 
31719c8205eSSimon Glass #if CONFIG_IS_ENABLED(OF_LIVE)
31819c8205eSSimon Glass 	if (of_live_active())
31919c8205eSSimon Glass 		return dm_scan_fdt_live(dev, dev_np(dev),
32019c8205eSSimon Glass 				gd->flags & GD_FLG_RELOC ? false : true);
32119c8205eSSimon Glass 	else
32219c8205eSSimon Glass #endif
323e160f7d4SSimon Glass 	return dm_scan_fdt_node(dev, gd->fdt_blob, dev_of_offset(dev),
324cc7f66f7SSimon Glass 				gd->flags & GD_FLG_RELOC ? false : true);
325cc7f66f7SSimon Glass }
326cc7f66f7SSimon Glass 
dm_scan_fdt(const void * blob,bool pre_reloc_only)3271ca7e206SSimon Glass int dm_scan_fdt(const void *blob, bool pre_reloc_only)
3281ca7e206SSimon Glass {
32919c8205eSSimon Glass #if CONFIG_IS_ENABLED(OF_LIVE)
33019c8205eSSimon Glass 	if (of_live_active())
33119c8205eSSimon Glass 		return dm_scan_fdt_live(gd->dm_root, gd->of_root,
33219c8205eSSimon Glass 					pre_reloc_only);
33319c8205eSSimon Glass 	else
33419c8205eSSimon Glass #endif
3351ca7e206SSimon Glass 	return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only);
3361ca7e206SSimon Glass }
337e81c9864SPatrice Chotard #else
dm_scan_fdt_node(struct udevice * parent,const void * blob,int offset,bool pre_reloc_only)338e81c9864SPatrice Chotard static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
339e81c9864SPatrice Chotard 			    int offset, bool pre_reloc_only)
340e81c9864SPatrice Chotard {
341e81c9864SPatrice Chotard 	return 0;
342e81c9864SPatrice Chotard }
3436494d708SSimon Glass #endif
3446494d708SSimon Glass 
dm_scan_fdt_ofnode_path(const char * path,bool pre_reloc_only)34568d215d9SRajan Vaja static int dm_scan_fdt_ofnode_path(const char *path, bool pre_reloc_only)
34668d215d9SRajan Vaja {
34768d215d9SRajan Vaja 	ofnode node;
34868d215d9SRajan Vaja 
34968d215d9SRajan Vaja 	node = ofnode_path(path);
35068d215d9SRajan Vaja 	if (!ofnode_valid(node))
35168d215d9SRajan Vaja 		return 0;
35268d215d9SRajan Vaja 
35368d215d9SRajan Vaja #if CONFIG_IS_ENABLED(OF_LIVE)
35468d215d9SRajan Vaja 	if (of_live_active())
35568d215d9SRajan Vaja 		return dm_scan_fdt_live(gd->dm_root, node.np, pre_reloc_only);
35668d215d9SRajan Vaja #endif
35768d215d9SRajan Vaja 	return dm_scan_fdt_node(gd->dm_root, gd->fdt_blob, node.of_offset,
35868d215d9SRajan Vaja 				pre_reloc_only);
35968d215d9SRajan Vaja }
36068d215d9SRajan Vaja 
dm_extended_scan_fdt(const void * blob,bool pre_reloc_only)361e81c9864SPatrice Chotard int dm_extended_scan_fdt(const void *blob, bool pre_reloc_only)
362e81c9864SPatrice Chotard {
363bcfdf055SAndy Yan 	int ret;
364e81c9864SPatrice Chotard 
365e81c9864SPatrice Chotard 	ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
366e81c9864SPatrice Chotard 	if (ret) {
367e81c9864SPatrice Chotard 		debug("dm_scan_fdt() failed: %d\n", ret);
368e81c9864SPatrice Chotard 		return ret;
369e81c9864SPatrice Chotard 	}
370e81c9864SPatrice Chotard 
37168d215d9SRajan Vaja 	ret = dm_scan_fdt_ofnode_path("/clocks", pre_reloc_only);
3721712ca21SRajan Vaja 	if (ret) {
37368d215d9SRajan Vaja 		debug("scan for /clocks failed: %d\n", ret);
3741712ca21SRajan Vaja 		return ret;
3751712ca21SRajan Vaja 	}
3761712ca21SRajan Vaja 
3771712ca21SRajan Vaja 	ret = dm_scan_fdt_ofnode_path("/firmware", pre_reloc_only);
3781712ca21SRajan Vaja 	if (ret)
3791712ca21SRajan Vaja 		debug("scan for /firmware failed: %d\n", ret);
380e81c9864SPatrice Chotard 
381e81c9864SPatrice Chotard 	return ret;
382e81c9864SPatrice Chotard }
383e81c9864SPatrice Chotard 
dm_scan_other(bool pre_reloc_only)384bb58503dSSimon Glass __weak int dm_scan_other(bool pre_reloc_only)
385bb58503dSSimon Glass {
386bb58503dSSimon Glass 	return 0;
387bb58503dSSimon Glass }
388bb58503dSSimon Glass 
dm_init_and_scan(bool pre_reloc_only)389ab7cd627SSimon Glass int dm_init_and_scan(bool pre_reloc_only)
390ab7cd627SSimon Glass {
391ab7cd627SSimon Glass 	int ret;
392ab7cd627SSimon Glass 
39319c8205eSSimon Glass 	ret = dm_init(IS_ENABLED(CONFIG_OF_LIVE));
394ab7cd627SSimon Glass 	if (ret) {
395ab7cd627SSimon Glass 		debug("dm_init() failed: %d\n", ret);
396ab7cd627SSimon Glass 		return ret;
397ab7cd627SSimon Glass 	}
398ab7cd627SSimon Glass 	ret = dm_scan_platdata(pre_reloc_only);
399ab7cd627SSimon Glass 	if (ret) {
400ab7cd627SSimon Glass 		debug("dm_scan_platdata() failed: %d\n", ret);
401ab7cd627SSimon Glass 		return ret;
402ab7cd627SSimon Glass 	}
403b2b0d3e7SSimon Glass 
40429629eb8SSimon Glass 	if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
405e81c9864SPatrice Chotard 		ret = dm_extended_scan_fdt(gd->fdt_blob, pre_reloc_only);
406ab7cd627SSimon Glass 		if (ret) {
407e81c9864SPatrice Chotard 			debug("dm_extended_scan_dt() failed: %d\n", ret);
408ab7cd627SSimon Glass 			return ret;
409ab7cd627SSimon Glass 		}
410b2b0d3e7SSimon Glass 	}
411b2b0d3e7SSimon Glass 
412bb58503dSSimon Glass 	ret = dm_scan_other(pre_reloc_only);
413bb58503dSSimon Glass 	if (ret)
414bb58503dSSimon Glass 		return ret;
415ab7cd627SSimon Glass 
416ab7cd627SSimon Glass 	return 0;
417ab7cd627SSimon Glass }
418ab7cd627SSimon Glass 
4196494d708SSimon Glass /* This is the root driver - all drivers are children of this */
4206494d708SSimon Glass U_BOOT_DRIVER(root_driver) = {
4216494d708SSimon Glass 	.name	= "root_driver",
4226494d708SSimon Glass 	.id	= UCLASS_ROOT,
42366eaea6cSStefan Roese 	.priv_auto_alloc_size = sizeof(struct root_priv),
4246494d708SSimon Glass };
4256494d708SSimon Glass 
4266494d708SSimon Glass /* This is the root uclass */
4276494d708SSimon Glass UCLASS_DRIVER(root) = {
4286494d708SSimon Glass 	.name	= "root",
4296494d708SSimon Glass 	.id	= UCLASS_ROOT,
4306494d708SSimon Glass };
431