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