blob: 0de5d7c70d61749283a5e2f439525697c6d40905 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glassdd6ab882014-02-26 15:59:18 -07002/*
3 * Copyright (c) 2013 Google, Inc
4 *
5 * (C) Copyright 2012
6 * Pavel Herrmann <morpheus.ibis@gmail.com>
Simon Glassdd6ab882014-02-26 15:59:18 -07007 */
8
9#include <common.h>
10#include <errno.h>
Simon Glass528b1ef2015-01-25 08:27:16 -070011#include <fdtdec.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Simon Glassdd6ab882014-02-26 15:59:18 -070013#include <malloc.h>
Masahiro Yamada75f82d02018-03-05 01:20:11 +090014#include <linux/libfdt.h>
Simon Glassdd6ab882014-02-26 15:59:18 -070015#include <dm/device.h>
16#include <dm/device-internal.h>
17#include <dm/lists.h>
Simon Glassf19d9f22017-05-18 20:09:08 -060018#include <dm/of.h>
19#include <dm/of_access.h>
Simon Glassdd6ab882014-02-26 15:59:18 -070020#include <dm/platdata.h>
Simon Glassf19d9f22017-05-18 20:09:08 -060021#include <dm/read.h>
Jeroen Hofsteecf0cf822014-06-25 21:57:45 +020022#include <dm/root.h>
Simon Glassdd6ab882014-02-26 15:59:18 -070023#include <dm/uclass.h>
24#include <dm/util.h>
25#include <linux/list.h>
26
27DECLARE_GLOBAL_DATA_PTR;
28
Walter Lozano95282d62020-06-25 01:10:10 -030029static struct driver_info root_info = {
Simon Glassdd6ab882014-02-26 15:59:18 -070030 .name = "root_driver",
31};
32
Heiko Schocherb74fcb42014-05-22 12:43:05 +020033struct udevice *dm_root(void)
Simon Glassdd6ab882014-02-26 15:59:18 -070034{
35 if (!gd->dm_root) {
36 dm_warn("Virtual root driver does not exist!\n");
37 return NULL;
38 }
39
40 return gd->dm_root;
41}
42
Simon Glass1b0deee2016-11-13 14:21:58 -070043void dm_fixup_for_gd_move(struct global_data *new_gd)
44{
45 /* The sentinel node has moved, so update things that point to it */
Lokesh Vutla02ba17f2017-02-13 09:21:22 +053046 if (gd->dm_root) {
47 new_gd->uclass_root.next->prev = &new_gd->uclass_root;
48 new_gd->uclass_root.prev->next = &new_gd->uclass_root;
49 }
Simon Glass1b0deee2016-11-13 14:21:58 -070050}
51
Michal Simek0ec473b2015-02-02 16:31:59 +010052#if defined(CONFIG_NEEDS_MANUAL_RELOC)
53void fix_drivers(void)
54{
55 struct driver *drv =
56 ll_entry_start(struct driver, driver);
57 const int n_ents = ll_entry_count(struct driver, driver);
58 struct driver *entry;
59
60 for (entry = drv; entry != drv + n_ents; entry++) {
61 if (entry->of_match)
62 entry->of_match = (const struct udevice_id *)
63 ((u32)entry->of_match + gd->reloc_off);
64 if (entry->bind)
65 entry->bind += gd->reloc_off;
66 if (entry->probe)
67 entry->probe += gd->reloc_off;
68 if (entry->remove)
69 entry->remove += gd->reloc_off;
70 if (entry->unbind)
71 entry->unbind += gd->reloc_off;
72 if (entry->ofdata_to_platdata)
73 entry->ofdata_to_platdata += gd->reloc_off;
Michal Simek61809f52015-10-27 13:48:08 +010074 if (entry->child_post_bind)
75 entry->child_post_bind += gd->reloc_off;
Michal Simek0ec473b2015-02-02 16:31:59 +010076 if (entry->child_pre_probe)
77 entry->child_pre_probe += gd->reloc_off;
78 if (entry->child_post_remove)
79 entry->child_post_remove += gd->reloc_off;
80 /* OPS are fixed in every uclass post_probe function */
81 if (entry->ops)
82 entry->ops += gd->reloc_off;
83 }
84}
85
86void fix_uclass(void)
87{
88 struct uclass_driver *uclass =
89 ll_entry_start(struct uclass_driver, uclass);
90 const int n_ents = ll_entry_count(struct uclass_driver, uclass);
91 struct uclass_driver *entry;
92
93 for (entry = uclass; entry != uclass + n_ents; entry++) {
94 if (entry->post_bind)
95 entry->post_bind += gd->reloc_off;
96 if (entry->pre_unbind)
97 entry->pre_unbind += gd->reloc_off;
Michal Simek61809f52015-10-27 13:48:08 +010098 if (entry->pre_probe)
99 entry->pre_probe += gd->reloc_off;
Michal Simek0ec473b2015-02-02 16:31:59 +0100100 if (entry->post_probe)
101 entry->post_probe += gd->reloc_off;
102 if (entry->pre_remove)
103 entry->pre_remove += gd->reloc_off;
Michal Simek61809f52015-10-27 13:48:08 +0100104 if (entry->child_post_bind)
105 entry->child_post_bind += gd->reloc_off;
106 if (entry->child_pre_probe)
107 entry->child_pre_probe += gd->reloc_off;
Michal Simek0ec473b2015-02-02 16:31:59 +0100108 if (entry->init)
109 entry->init += gd->reloc_off;
110 if (entry->destroy)
111 entry->destroy += gd->reloc_off;
112 /* FIXME maybe also need to fix these ops */
113 if (entry->ops)
114 entry->ops += gd->reloc_off;
115 }
116}
Angelo Dureghellof4d193b2016-05-21 12:05:49 +0200117
118void fix_devices(void)
119{
120 struct driver_info *dev =
121 ll_entry_start(struct driver_info, driver_info);
122 const int n_ents = ll_entry_count(struct driver_info, driver_info);
123 struct driver_info *entry;
124
125 for (entry = dev; entry != dev + n_ents; entry++) {
126 if (entry->platdata)
127 entry->platdata += gd->reloc_off;
128 }
129}
130
Michal Simek0ec473b2015-02-02 16:31:59 +0100131#endif
132
Simon Glassf19d9f22017-05-18 20:09:08 -0600133int dm_init(bool of_live)
Simon Glassdd6ab882014-02-26 15:59:18 -0700134{
135 int ret;
136
137 if (gd->dm_root) {
138 dm_warn("Virtual root driver already exists!\n");
139 return -EINVAL;
140 }
Simon Glass34a1d352014-06-11 23:29:49 -0600141 INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST);
Simon Glassdd6ab882014-02-26 15:59:18 -0700142
Michal Simek0ec473b2015-02-02 16:31:59 +0100143#if defined(CONFIG_NEEDS_MANUAL_RELOC)
144 fix_drivers();
145 fix_uclass();
Angelo Dureghellof4d193b2016-05-21 12:05:49 +0200146 fix_devices();
Michal Simek0ec473b2015-02-02 16:31:59 +0100147#endif
148
Simon Glassfef72b72014-07-23 06:55:03 -0600149 ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
Simon Glassdd6ab882014-02-26 15:59:18 -0700150 if (ret)
151 return ret;
Masahiro Yamada366b24f2015-08-12 07:31:55 +0900152#if CONFIG_IS_ENABLED(OF_CONTROL)
Simon Glassf19d9f22017-05-18 20:09:08 -0600153# if CONFIG_IS_ENABLED(OF_LIVE)
154 if (of_live)
155 DM_ROOT_NON_CONST->node = np_to_ofnode(gd->of_root);
156 else
157#endif
158 DM_ROOT_NON_CONST->node = offset_to_ofnode(0);
Simon Glasscc7cf942015-01-25 08:26:58 -0700159#endif
Simon Glass6d3b3e22014-07-23 06:55:00 -0600160 ret = device_probe(DM_ROOT_NON_CONST);
161 if (ret)
162 return ret;
Simon Glassdd6ab882014-02-26 15:59:18 -0700163
164 return 0;
165}
166
Simon Glass00197582014-07-23 06:55:01 -0600167int dm_uninit(void)
168{
Stefan Roese80b5bc92017-03-20 12:51:48 +0100169 device_remove(dm_root(), DM_REMOVE_NORMAL);
Simon Glass00197582014-07-23 06:55:01 -0600170 device_unbind(dm_root());
Jean-Jacques Hiblot272b67d2018-12-07 14:50:54 +0100171 gd->dm_root = NULL;
Simon Glass00197582014-07-23 06:55:01 -0600172
173 return 0;
174}
175
Stefan Roese505045d2017-03-27 10:58:53 +0200176#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
177int dm_remove_devices_flags(uint flags)
178{
179 device_remove(dm_root(), flags);
180
181 return 0;
182}
183#endif
184
Simon Glassfef72b72014-07-23 06:55:03 -0600185int dm_scan_platdata(bool pre_reloc_only)
Simon Glassdd6ab882014-02-26 15:59:18 -0700186{
187 int ret;
188
Simon Glassfef72b72014-07-23 06:55:03 -0600189 ret = lists_bind_drivers(DM_ROOT_NON_CONST, pre_reloc_only);
Simon Glassdd6ab882014-02-26 15:59:18 -0700190 if (ret == -ENOENT) {
191 dm_warn("Some drivers were not found\n");
192 ret = 0;
193 }
Simon Glassdd6ab882014-02-26 15:59:18 -0700194
Masahiro Yamada6cac81a2014-11-17 17:19:38 +0900195 return ret;
Simon Glassdd6ab882014-02-26 15:59:18 -0700196}
197
Simon Glassf19d9f22017-05-18 20:09:08 -0600198#if CONFIG_IS_ENABLED(OF_LIVE)
199static int dm_scan_fdt_live(struct udevice *parent,
200 const struct device_node *node_parent,
201 bool pre_reloc_only)
202{
203 struct device_node *np;
204 int ret = 0, err;
205
206 for (np = node_parent->child; np; np = np->sibling) {
Bin Mengc596a592018-10-10 22:07:00 -0700207
Simon Glassf19d9f22017-05-18 20:09:08 -0600208 if (!of_device_is_available(np)) {
Masahiro Yamadaf70f39f2017-09-29 12:31:20 +0900209 pr_debug(" - ignoring disabled device\n");
Simon Glassf19d9f22017-05-18 20:09:08 -0600210 continue;
211 }
Bin Meng9a9b0742018-10-10 22:06:58 -0700212 err = lists_bind_fdt(parent, np_to_ofnode(np), NULL,
213 pre_reloc_only);
Simon Glassf19d9f22017-05-18 20:09:08 -0600214 if (err && !ret) {
215 ret = err;
216 debug("%s: ret=%d\n", np->name, ret);
217 }
218 }
219
220 if (ret)
221 dm_warn("Some drivers failed to bind\n");
222
223 return ret;
224}
225#endif /* CONFIG_IS_ENABLED(OF_LIVE) */
226
Simon Glass8d7e8162016-07-04 11:57:58 -0600227#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
Simon Glassa4dbe252017-05-17 17:18:08 -0600228/**
229 * dm_scan_fdt_node() - Scan the device tree and bind drivers for a node
230 *
231 * This scans the subnodes of a device tree node and and creates a driver
232 * for each one.
233 *
234 * @parent: Parent device for the devices that will be created
235 * @blob: Pointer to device tree blob
236 * @offset: Offset of node to scan
237 * @pre_reloc_only: If true, bind only drivers with the DM_FLAG_PRE_RELOC
238 * flag. If false bind all drivers.
239 * @return 0 if OK, -ve on error
240 */
241static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
242 int offset, bool pre_reloc_only)
Simon Glassdd6ab882014-02-26 15:59:18 -0700243{
Simon Glassdd6ab882014-02-26 15:59:18 -0700244 int ret = 0, err;
Simon Glassdd6ab882014-02-26 15:59:18 -0700245
Simon Glass40717422014-07-23 06:55:18 -0600246 for (offset = fdt_first_subnode(blob, offset);
247 offset > 0;
248 offset = fdt_next_subnode(blob, offset)) {
Jens Wiklander651a8362018-09-25 16:40:05 +0200249 const char *node_name = fdt_get_name(blob, offset, NULL);
250
Simon Glass528b1ef2015-01-25 08:27:16 -0700251 if (!fdtdec_get_is_enabled(blob, offset)) {
Masahiro Yamadaf70f39f2017-09-29 12:31:20 +0900252 pr_debug(" - ignoring disabled device\n");
Simon Glass528b1ef2015-01-25 08:27:16 -0700253 continue;
254 }
Bin Meng9a9b0742018-10-10 22:06:58 -0700255 err = lists_bind_fdt(parent, offset_to_ofnode(offset), NULL,
256 pre_reloc_only);
Simon Glassc90b9172015-08-30 16:55:17 -0600257 if (err && !ret) {
Simon Glass40717422014-07-23 06:55:18 -0600258 ret = err;
Jens Wiklander651a8362018-09-25 16:40:05 +0200259 debug("%s: ret=%d\n", node_name, ret);
Simon Glassc90b9172015-08-30 16:55:17 -0600260 }
Simon Glass40717422014-07-23 06:55:18 -0600261 }
Simon Glassdd6ab882014-02-26 15:59:18 -0700262
263 if (ret)
264 dm_warn("Some drivers failed to bind\n");
265
266 return ret;
267}
Simon Glass40717422014-07-23 06:55:18 -0600268
Simon Glass5d5388d2016-07-05 17:10:08 -0600269int dm_scan_fdt_dev(struct udevice *dev)
270{
Simon Glassf19d9f22017-05-18 20:09:08 -0600271 if (!dev_of_valid(dev))
Simon Glass5d5388d2016-07-05 17:10:08 -0600272 return 0;
273
Simon Glassf19d9f22017-05-18 20:09:08 -0600274#if CONFIG_IS_ENABLED(OF_LIVE)
275 if (of_live_active())
276 return dm_scan_fdt_live(dev, dev_np(dev),
277 gd->flags & GD_FLG_RELOC ? false : true);
278 else
279#endif
Simon Glassdd79d6e2017-01-17 16:52:55 -0700280 return dm_scan_fdt_node(dev, gd->fdt_blob, dev_of_offset(dev),
Simon Glass5d5388d2016-07-05 17:10:08 -0600281 gd->flags & GD_FLG_RELOC ? false : true);
282}
283
Simon Glass40717422014-07-23 06:55:18 -0600284int dm_scan_fdt(const void *blob, bool pre_reloc_only)
285{
Simon Glassf19d9f22017-05-18 20:09:08 -0600286#if CONFIG_IS_ENABLED(OF_LIVE)
287 if (of_live_active())
288 return dm_scan_fdt_live(gd->dm_root, gd->of_root,
289 pre_reloc_only);
290 else
291#endif
Simon Glass40717422014-07-23 06:55:18 -0600292 return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only);
293}
Simon Glassdd6ab882014-02-26 15:59:18 -0700294
Patrick Delaunayc779e202020-02-18 15:43:46 +0100295static int dm_scan_fdt_ofnode_path(const void *blob, const char *path,
296 bool pre_reloc_only)
Rajan Vajafac64632018-08-10 01:45:33 -0700297{
298 ofnode node;
299
300 node = ofnode_path(path);
301 if (!ofnode_valid(node))
302 return 0;
303
304#if CONFIG_IS_ENABLED(OF_LIVE)
305 if (of_live_active())
306 return dm_scan_fdt_live(gd->dm_root, node.np, pre_reloc_only);
307#endif
Patrick Delaunayc779e202020-02-18 15:43:46 +0100308 return dm_scan_fdt_node(gd->dm_root, blob, node.of_offset,
Rajan Vajafac64632018-08-10 01:45:33 -0700309 pre_reloc_only);
310}
311
Patrice Chotardbb3a45b2017-09-04 14:55:56 +0200312int dm_extended_scan_fdt(const void *blob, bool pre_reloc_only)
313{
Patrick Delaunayc779e202020-02-18 15:43:46 +0100314 int ret, i;
315 const char * const nodes[] = {
316 "/chosen",
317 "/clocks",
318 "/firmware"
319 };
Patrice Chotardbb3a45b2017-09-04 14:55:56 +0200320
Patrice Chotard1e5f6e32019-05-15 10:07:01 +0200321 ret = dm_scan_fdt(blob, pre_reloc_only);
Patrice Chotardbb3a45b2017-09-04 14:55:56 +0200322 if (ret) {
323 debug("dm_scan_fdt() failed: %d\n", ret);
324 return ret;
325 }
326
Patrick Delaunayc779e202020-02-18 15:43:46 +0100327 /* Some nodes aren't devices themselves but may contain some */
328 for (i = 0; i < ARRAY_SIZE(nodes); i++) {
329 ret = dm_scan_fdt_ofnode_path(blob, nodes[i], pre_reloc_only);
330 if (ret) {
331 debug("dm_scan_fdt() scan for %s failed: %d\n",
332 nodes[i], ret);
333 return ret;
334 }
Rajan Vajae9fc81d2018-08-10 01:45:34 -0700335 }
336
Patrice Chotardbb3a45b2017-09-04 14:55:56 +0200337 return ret;
338}
Marek Vasut7f18c342019-08-31 18:03:28 +0200339#endif
Patrice Chotardbb3a45b2017-09-04 14:55:56 +0200340
Simon Glass97e22e32014-07-23 06:55:23 -0600341__weak int dm_scan_other(bool pre_reloc_only)
342{
343 return 0;
344}
345
Simon Glassa730c5d2014-07-23 06:55:04 -0600346int dm_init_and_scan(bool pre_reloc_only)
347{
348 int ret;
349
Walter Lozanoffc41b02020-06-25 01:10:11 -0300350#if CONFIG_IS_ENABLED(OF_PLATDATA)
351 dm_populate_phandle_data();
352#endif
353
Simon Glassf19d9f22017-05-18 20:09:08 -0600354 ret = dm_init(IS_ENABLED(CONFIG_OF_LIVE));
Simon Glassa730c5d2014-07-23 06:55:04 -0600355 if (ret) {
356 debug("dm_init() failed: %d\n", ret);
357 return ret;
358 }
359 ret = dm_scan_platdata(pre_reloc_only);
360 if (ret) {
361 debug("dm_scan_platdata() failed: %d\n", ret);
362 return ret;
363 }
Simon Glass0704b852015-02-27 22:06:41 -0700364
Simon Glass8d7e8162016-07-04 11:57:58 -0600365 if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
Patrice Chotardbb3a45b2017-09-04 14:55:56 +0200366 ret = dm_extended_scan_fdt(gd->fdt_blob, pre_reloc_only);
Simon Glass0704b852015-02-27 22:06:41 -0700367 if (ret) {
Patrice Chotardbb3a45b2017-09-04 14:55:56 +0200368 debug("dm_extended_scan_dt() failed: %d\n", ret);
Simon Glass0704b852015-02-27 22:06:41 -0700369 return ret;
370 }
Simon Glassa730c5d2014-07-23 06:55:04 -0600371 }
Simon Glass0704b852015-02-27 22:06:41 -0700372
Simon Glass97e22e32014-07-23 06:55:23 -0600373 ret = dm_scan_other(pre_reloc_only);
374 if (ret)
375 return ret;
Simon Glassa730c5d2014-07-23 06:55:04 -0600376
377 return 0;
378}
379
Simon Glassdd6ab882014-02-26 15:59:18 -0700380/* This is the root driver - all drivers are children of this */
381U_BOOT_DRIVER(root_driver) = {
382 .name = "root_driver",
383 .id = UCLASS_ROOT,
Simon Glassdd6ab882014-02-26 15:59:18 -0700384};
385
386/* This is the root uclass */
387UCLASS_DRIVER(root) = {
388 .name = "root",
389 .id = UCLASS_ROOT,
390};