xref: /rk3399_rockchip-uboot/drivers/core/root.c (revision 250a4bb13c77ee68704d77398e85a3d8ec83ca6a)
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 
dm_root(void)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 
dm_fixup_for_gd_move(struct global_data * new_gd)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 
dm_get_translation_offset(void)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 
dm_set_translation_offset(fdt_addr_t offs)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)
fix_drivers(void)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 
fix_uclass(void)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 
fix_devices(void)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 
dm_init(bool of_live)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 
dm_uninit(void)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)
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) {
22619c8205eSSimon Glass 		if (pre_reloc_only &&
227b455f42cSJoseph Chen 		   (!of_find_property(np, "u-boot,dm-pre-reloc", NULL) &&
228930ceb12SJoseph Chen 		    !of_find_property(np, "u-boot,dm-spl", NULL)))
22919c8205eSSimon Glass 			continue;
23019c8205eSSimon Glass 		if (!of_device_is_available(np)) {
231d42197e4SMasahiro Yamada 			pr_debug("   - ignoring disabled device\n");
23219c8205eSSimon Glass 			continue;
23319c8205eSSimon Glass 		}
23419c8205eSSimon Glass 		err = lists_bind_fdt(parent, np_to_ofnode(np), NULL);
23519c8205eSSimon Glass 		if (err && !ret) {
23619c8205eSSimon Glass 			ret = err;
23719c8205eSSimon Glass 			debug("%s: ret=%d\n", np->name, ret);
23819c8205eSSimon Glass 		}
2395120375cSJoseph Chen 
240dfe24df3SJoseph Chen 		/* There is no compatible in "/firmware", bind it by default. */
2415120375cSJoseph Chen 		if (!pre_reloc_only && !strcmp(np->name, "firmware"))
2425120375cSJoseph Chen 			ret = device_bind_driver_to_node(gd->dm_root,
2435120375cSJoseph Chen 				"firmware", np->name, np_to_ofnode(np), NULL);
24419c8205eSSimon Glass 	}
24519c8205eSSimon Glass 
24619c8205eSSimon Glass 	if (ret)
24719c8205eSSimon Glass 		dm_warn("Some drivers failed to bind\n");
24819c8205eSSimon Glass 
24919c8205eSSimon Glass 	return ret;
25019c8205eSSimon Glass }
25119c8205eSSimon Glass #endif /* CONFIG_IS_ENABLED(OF_LIVE) */
25219c8205eSSimon Glass 
25329629eb8SSimon Glass #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
254a771a04fSSimon Glass /**
255a771a04fSSimon Glass  * dm_scan_fdt_node() - Scan the device tree and bind drivers for a node
256a771a04fSSimon Glass  *
257a771a04fSSimon Glass  * This scans the subnodes of a device tree node and and creates a driver
258a771a04fSSimon Glass  * for each one.
259a771a04fSSimon Glass  *
260a771a04fSSimon Glass  * @parent: Parent device for the devices that will be created
261a771a04fSSimon Glass  * @blob: Pointer to device tree blob
262a771a04fSSimon Glass  * @offset: Offset of node to scan
263a771a04fSSimon Glass  * @pre_reloc_only: If true, bind only drivers with the DM_FLAG_PRE_RELOC
264a771a04fSSimon Glass  * flag. If false bind all drivers.
265a771a04fSSimon Glass  * @return 0 if OK, -ve on error
266a771a04fSSimon Glass  */
dm_scan_fdt_node(struct udevice * parent,const void * blob,int offset,bool pre_reloc_only)267a771a04fSSimon Glass static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
268a771a04fSSimon Glass 			    int offset, bool pre_reloc_only)
2696494d708SSimon Glass {
2706494d708SSimon Glass 	int ret = 0, err;
2716494d708SSimon Glass 
2721ca7e206SSimon Glass 	for (offset = fdt_first_subnode(blob, offset);
2731ca7e206SSimon Glass 	     offset > 0;
2741ca7e206SSimon Glass 	     offset = fdt_next_subnode(blob, offset)) {
27500606d7eSSimon Glass 		if (pre_reloc_only &&
27627326c7eSHeiko Stübner 		    !dm_fdt_pre_reloc(blob, offset))
27700606d7eSSimon Glass 			continue;
27894f7afdfSSimon Glass 		if (!fdtdec_get_is_enabled(blob, offset)) {
279d42197e4SMasahiro Yamada 			pr_debug("   - ignoring disabled device\n");
28094f7afdfSSimon Glass 			continue;
28194f7afdfSSimon Glass 		}
282f5b5719cSSimon Glass 		err = lists_bind_fdt(parent, offset_to_ofnode(offset), NULL);
283bc7b2f43SSimon Glass 		if (err && !ret) {
2846494d708SSimon Glass 			ret = err;
285bc7b2f43SSimon Glass 			debug("%s: ret=%d\n", fdt_get_name(blob, offset, NULL),
286bc7b2f43SSimon Glass 			      ret);
287bc7b2f43SSimon Glass 		}
288dfe24df3SJoseph Chen 
289*6d8950bfSJoseph Chen #if CONFIG_IS_ENABLED(SCMI_FIRMWARE)
290*6d8950bfSJoseph Chen 		const char *name;
291*6d8950bfSJoseph Chen 
292dfe24df3SJoseph Chen 		/* There is no compatible in "/firmware", bind it by default. */
293dfe24df3SJoseph Chen 		name = fdt_get_name(blob, offset, NULL);
294dfe24df3SJoseph Chen 		if (name && !strcmp(name, "firmware"))
295dfe24df3SJoseph Chen 			ret = device_bind_driver_to_node(parent, "firmware",
296dfe24df3SJoseph Chen 					name, offset_to_ofnode(offset), NULL);
297*6d8950bfSJoseph Chen #endif
2986494d708SSimon Glass 	}
2996494d708SSimon Glass 
3006494d708SSimon Glass 	if (ret)
3016494d708SSimon Glass 		dm_warn("Some drivers failed to bind\n");
3026494d708SSimon Glass 
3036494d708SSimon Glass 	return ret;
3046494d708SSimon Glass }
3051ca7e206SSimon Glass 
dm_scan_fdt_dev(struct udevice * dev)306cc7f66f7SSimon Glass int dm_scan_fdt_dev(struct udevice *dev)
307cc7f66f7SSimon Glass {
30819c8205eSSimon Glass 	if (!dev_of_valid(dev))
309cc7f66f7SSimon Glass 		return 0;
310cc7f66f7SSimon Glass 
31119c8205eSSimon Glass #if CONFIG_IS_ENABLED(OF_LIVE)
31219c8205eSSimon Glass 	if (of_live_active())
31319c8205eSSimon Glass 		return dm_scan_fdt_live(dev, dev_np(dev),
31419c8205eSSimon Glass 				gd->flags & GD_FLG_RELOC ? false : true);
31519c8205eSSimon Glass 	else
31619c8205eSSimon Glass #endif
317e160f7d4SSimon Glass 	return dm_scan_fdt_node(dev, gd->fdt_blob, dev_of_offset(dev),
318cc7f66f7SSimon Glass 				gd->flags & GD_FLG_RELOC ? false : true);
319cc7f66f7SSimon Glass }
320cc7f66f7SSimon Glass 
dm_scan_fdt(const void * blob,bool pre_reloc_only)3211ca7e206SSimon Glass int dm_scan_fdt(const void *blob, bool pre_reloc_only)
3221ca7e206SSimon Glass {
32319c8205eSSimon Glass #if CONFIG_IS_ENABLED(OF_LIVE)
32419c8205eSSimon Glass 	if (of_live_active())
32519c8205eSSimon Glass 		return dm_scan_fdt_live(gd->dm_root, gd->of_root,
32619c8205eSSimon Glass 					pre_reloc_only);
32719c8205eSSimon Glass 	else
32819c8205eSSimon Glass #endif
3291ca7e206SSimon Glass 	return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only);
3301ca7e206SSimon Glass }
33146fb92f0SPatrice Chotard #else
dm_scan_fdt_node(struct udevice * parent,const void * blob,int offset,bool pre_reloc_only)33246fb92f0SPatrice Chotard static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
33346fb92f0SPatrice Chotard 			    int offset, bool pre_reloc_only)
33446fb92f0SPatrice Chotard {
33546fb92f0SPatrice Chotard 	return 0;
33646fb92f0SPatrice Chotard }
3376494d708SSimon Glass #endif
3386494d708SSimon Glass 
dm_extended_scan_fdt(const void * blob,bool pre_reloc_only)33946fb92f0SPatrice Chotard int dm_extended_scan_fdt(const void *blob, bool pre_reloc_only)
34046fb92f0SPatrice Chotard {
34146fb92f0SPatrice Chotard 	int node, ret;
34246fb92f0SPatrice Chotard 
34346fb92f0SPatrice Chotard 	ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
34446fb92f0SPatrice Chotard 	if (ret) {
34546fb92f0SPatrice Chotard 		debug("dm_scan_fdt() failed: %d\n", ret);
34646fb92f0SPatrice Chotard 		return ret;
34746fb92f0SPatrice Chotard 	}
34846fb92f0SPatrice Chotard 
34946fb92f0SPatrice Chotard 	/* bind fixed-clock */
35046fb92f0SPatrice Chotard 	node = ofnode_to_offset(ofnode_path("/clocks"));
35146fb92f0SPatrice Chotard 	/* if no DT "clocks" node, no need to go further */
35246fb92f0SPatrice Chotard 	if (node < 0)
35346fb92f0SPatrice Chotard 		return ret;
35446fb92f0SPatrice Chotard 
35546fb92f0SPatrice Chotard 	ret = dm_scan_fdt_node(gd->dm_root, gd->fdt_blob, node,
35646fb92f0SPatrice Chotard 			       pre_reloc_only);
35746fb92f0SPatrice Chotard 	if (ret)
35846fb92f0SPatrice Chotard 		debug("dm_scan_fdt_node() failed: %d\n", ret);
35946fb92f0SPatrice Chotard 
36046fb92f0SPatrice Chotard 	return ret;
36146fb92f0SPatrice Chotard }
36246fb92f0SPatrice Chotard 
dm_scan_other(bool pre_reloc_only)363bb58503dSSimon Glass __weak int dm_scan_other(bool pre_reloc_only)
364bb58503dSSimon Glass {
365bb58503dSSimon Glass 	return 0;
366bb58503dSSimon Glass }
367bb58503dSSimon Glass 
dm_init_and_scan(bool pre_reloc_only)368ab7cd627SSimon Glass int dm_init_and_scan(bool pre_reloc_only)
369ab7cd627SSimon Glass {
370ab7cd627SSimon Glass 	int ret;
371ab7cd627SSimon Glass 
37219c8205eSSimon Glass 	ret = dm_init(IS_ENABLED(CONFIG_OF_LIVE));
373ab7cd627SSimon Glass 	if (ret) {
374ab7cd627SSimon Glass 		debug("dm_init() failed: %d\n", ret);
375ab7cd627SSimon Glass 		return ret;
376ab7cd627SSimon Glass 	}
377ab7cd627SSimon Glass 	ret = dm_scan_platdata(pre_reloc_only);
378ab7cd627SSimon Glass 	if (ret) {
379ab7cd627SSimon Glass 		debug("dm_scan_platdata() failed: %d\n", ret);
380ab7cd627SSimon Glass 		return ret;
381ab7cd627SSimon Glass 	}
382b2b0d3e7SSimon Glass 
38329629eb8SSimon Glass 	if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
38446fb92f0SPatrice Chotard 		ret = dm_extended_scan_fdt(gd->fdt_blob, pre_reloc_only);
385ab7cd627SSimon Glass 		if (ret) {
38646fb92f0SPatrice Chotard 			debug("dm_extended_scan_dt() failed: %d\n", ret);
387ab7cd627SSimon Glass 			return ret;
388ab7cd627SSimon Glass 		}
389b2b0d3e7SSimon Glass 	}
390b2b0d3e7SSimon Glass 
391bb58503dSSimon Glass 	ret = dm_scan_other(pre_reloc_only);
392bb58503dSSimon Glass 	if (ret)
393bb58503dSSimon Glass 		return ret;
394ab7cd627SSimon Glass 
395ab7cd627SSimon Glass 	return 0;
396ab7cd627SSimon Glass }
397ab7cd627SSimon Glass 
3986494d708SSimon Glass /* This is the root driver - all drivers are children of this */
3996494d708SSimon Glass U_BOOT_DRIVER(root_driver) = {
4006494d708SSimon Glass 	.name	= "root_driver",
4016494d708SSimon Glass 	.id	= UCLASS_ROOT,
40266eaea6cSStefan Roese 	.priv_auto_alloc_size = sizeof(struct root_priv),
4036494d708SSimon Glass };
4046494d708SSimon Glass 
4056494d708SSimon Glass /* This is the root uclass */
4066494d708SSimon Glass UCLASS_DRIVER(root) = {
4076494d708SSimon Glass 	.name	= "root",
4086494d708SSimon Glass 	.id	= UCLASS_ROOT,
4096494d708SSimon Glass };
410