Merge tag 'dm-pull-5jan21' of git://git.denx.de/u-boot-dm into next
[platform/kernel/u-boot.git] / drivers / core / root.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2013 Google, Inc
4  *
5  * (C) Copyright 2012
6  * Pavel Herrmann <morpheus.ibis@gmail.com>
7  */
8
9 #include <common.h>
10 #include <errno.h>
11 #include <fdtdec.h>
12 #include <log.h>
13 #include <malloc.h>
14 #include <linux/libfdt.h>
15 #include <dm/acpi.h>
16 #include <dm/device.h>
17 #include <dm/device-internal.h>
18 #include <dm/lists.h>
19 #include <dm/of.h>
20 #include <dm/of_access.h>
21 #include <dm/platdata.h>
22 #include <dm/read.h>
23 #include <dm/root.h>
24 #include <dm/uclass.h>
25 #include <dm/util.h>
26 #include <linux/list.h>
27
28 DECLARE_GLOBAL_DATA_PTR;
29
30 static struct driver_info root_info = {
31         .name           = "root_driver",
32 };
33
34 struct udevice *dm_root(void)
35 {
36         if (!gd->dm_root) {
37                 dm_warn("Virtual root driver does not exist!\n");
38                 return NULL;
39         }
40
41         return gd->dm_root;
42 }
43
44 void dm_fixup_for_gd_move(struct global_data *new_gd)
45 {
46         /* The sentinel node has moved, so update things that point to it */
47         if (gd->dm_root) {
48                 new_gd->uclass_root->next->prev = new_gd->uclass_root;
49                 new_gd->uclass_root->prev->next = new_gd->uclass_root;
50         }
51 }
52
53 void 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                                 ((ulong)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->of_to_plat)
73                         entry->of_to_plat += gd->reloc_off;
74                 if (entry->child_post_bind)
75                         entry->child_post_bind += gd->reloc_off;
76                 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
86 void fix_uclass(void)
87 {
88         struct uclass_driver *uclass =
89                 ll_entry_start(struct uclass_driver, uclass_driver);
90         const int n_ents = ll_entry_count(struct uclass_driver, uclass_driver);
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;
98                 if (entry->pre_probe)
99                         entry->pre_probe += gd->reloc_off;
100                 if (entry->post_probe)
101                         entry->post_probe += gd->reloc_off;
102                 if (entry->pre_remove)
103                         entry->pre_remove += gd->reloc_off;
104                 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;
108                 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 }
117
118 void 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->plat)
127                         entry->plat += gd->reloc_off;
128         }
129 }
130
131 int dm_init(bool of_live)
132 {
133         int ret;
134
135         if (gd->dm_root) {
136                 dm_warn("Virtual root driver already exists!\n");
137                 return -EINVAL;
138         }
139         gd->uclass_root = &DM_UCLASS_ROOT_S_NON_CONST;
140         INIT_LIST_HEAD(DM_UCLASS_ROOT_NON_CONST);
141
142         if (IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)) {
143                 fix_drivers();
144                 fix_uclass();
145                 fix_devices();
146         }
147
148         ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
149         if (ret)
150                 return ret;
151         if (CONFIG_IS_ENABLED(OF_CONTROL))
152                 dev_set_ofnode(DM_ROOT_NON_CONST, ofnode_root());
153         ret = device_probe(DM_ROOT_NON_CONST);
154         if (ret)
155                 return ret;
156
157         return 0;
158 }
159
160 int dm_uninit(void)
161 {
162         device_remove(dm_root(), DM_REMOVE_NORMAL);
163         device_unbind(dm_root());
164         gd->dm_root = NULL;
165
166         return 0;
167 }
168
169 #if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
170 int dm_remove_devices_flags(uint flags)
171 {
172         device_remove(dm_root(), flags);
173
174         return 0;
175 }
176 #endif
177
178 int dm_scan_plat(bool pre_reloc_only)
179 {
180         int ret;
181
182         if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
183                 struct driver_rt *dyn;
184                 int n_ents;
185
186                 n_ents = ll_entry_count(struct driver_info, driver_info);
187                 dyn = calloc(n_ents, sizeof(struct driver_rt));
188                 if (!dyn)
189                         return -ENOMEM;
190                 gd_set_dm_driver_rt(dyn);
191         }
192
193         ret = lists_bind_drivers(DM_ROOT_NON_CONST, pre_reloc_only);
194         if (ret == -ENOENT) {
195                 dm_warn("Some drivers were not found\n");
196                 ret = 0;
197         }
198
199         return ret;
200 }
201
202 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
203 /**
204  * dm_scan_fdt_node() - Scan the device tree and bind drivers for a node
205  *
206  * This scans the subnodes of a device tree node and and creates a driver
207  * for each one.
208  *
209  * @parent: Parent device for the devices that will be created
210  * @node: Node to scan
211  * @pre_reloc_only: If true, bind only drivers with the DM_FLAG_PRE_RELOC
212  * flag. If false bind all drivers.
213  * @return 0 if OK, -ve on error
214  */
215 static int dm_scan_fdt_node(struct udevice *parent, ofnode parent_node,
216                             bool pre_reloc_only)
217 {
218         int ret = 0, err;
219         ofnode node;
220
221         if (!ofnode_valid(parent_node))
222                 return 0;
223
224         for (node = ofnode_first_subnode(parent_node);
225              ofnode_valid(node);
226              node = ofnode_next_subnode(node)) {
227                 const char *node_name = ofnode_get_name(node);
228
229                 if (!ofnode_is_enabled(node)) {
230                         pr_debug("   - ignoring disabled device\n");
231                         continue;
232                 }
233                 err = lists_bind_fdt(parent, node, NULL, pre_reloc_only);
234                 if (err && !ret) {
235                         ret = err;
236                         debug("%s: ret=%d\n", node_name, ret);
237                 }
238         }
239
240         if (ret)
241                 dm_warn("Some drivers failed to bind\n");
242
243         return ret;
244 }
245
246 int dm_scan_fdt_dev(struct udevice *dev)
247 {
248         return dm_scan_fdt_node(dev, dev_ofnode(dev),
249                                 gd->flags & GD_FLG_RELOC ? false : true);
250 }
251
252 int dm_scan_fdt(bool pre_reloc_only)
253 {
254         return dm_scan_fdt_node(gd->dm_root, ofnode_root(), pre_reloc_only);
255 }
256
257 static int dm_scan_fdt_ofnode_path(const char *path, bool pre_reloc_only)
258 {
259         ofnode node;
260
261         node = ofnode_path(path);
262
263         return dm_scan_fdt_node(gd->dm_root, node, pre_reloc_only);
264 }
265
266 int dm_extended_scan(bool pre_reloc_only)
267 {
268         int ret, i;
269         const char * const nodes[] = {
270                 "/chosen",
271                 "/clocks",
272                 "/firmware"
273         };
274
275         ret = dm_scan_fdt(pre_reloc_only);
276         if (ret) {
277                 debug("dm_scan_fdt() failed: %d\n", ret);
278                 return ret;
279         }
280
281         /* Some nodes aren't devices themselves but may contain some */
282         for (i = 0; i < ARRAY_SIZE(nodes); i++) {
283                 ret = dm_scan_fdt_ofnode_path(nodes[i], pre_reloc_only);
284                 if (ret) {
285                         debug("dm_scan_fdt() scan for %s failed: %d\n",
286                               nodes[i], ret);
287                         return ret;
288                 }
289         }
290
291         return ret;
292 }
293 #endif
294
295 __weak int dm_scan_other(bool pre_reloc_only)
296 {
297         return 0;
298 }
299
300 /**
301  * dm_scan() - Scan tables to bind devices
302  *
303  * Runs through the driver_info tables and binds the devices it finds. Then runs
304  * through the devicetree nodes. Finally calls dm_scan_other() to add any
305  * special devices
306  *
307  * @pre_reloc_only: If true, bind only nodes with special devicetree properties,
308  * or drivers with the DM_FLAG_PRE_RELOC flag. If false bind all drivers.
309  */
310 static int dm_scan(bool pre_reloc_only)
311 {
312         int ret;
313
314         ret = dm_scan_plat(pre_reloc_only);
315         if (ret) {
316                 debug("dm_scan_plat() failed: %d\n", ret);
317                 return ret;
318         }
319
320         if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
321                 ret = dm_extended_scan(pre_reloc_only);
322                 if (ret) {
323                         debug("dm_extended_scan() failed: %d\n", ret);
324                         return ret;
325                 }
326         }
327
328         ret = dm_scan_other(pre_reloc_only);
329         if (ret)
330                 return ret;
331
332         return 0;
333 }
334
335 int dm_init_and_scan(bool pre_reloc_only)
336 {
337         int ret;
338
339         ret = dm_init(CONFIG_IS_ENABLED(OF_LIVE));
340         if (ret) {
341                 debug("dm_init() failed: %d\n", ret);
342                 return ret;
343         }
344         ret = dm_scan(pre_reloc_only);
345         if (ret) {
346                 log_debug("dm_scan() failed: %d\n", ret);
347                 return ret;
348         }
349
350         return 0;
351 }
352
353 #ifdef CONFIG_ACPIGEN
354 static int root_acpi_get_name(const struct udevice *dev, char *out_name)
355 {
356         return acpi_copy_name(out_name, "\\_SB");
357 }
358
359 struct acpi_ops root_acpi_ops = {
360         .get_name       = root_acpi_get_name,
361 };
362 #endif
363
364 /* This is the root driver - all drivers are children of this */
365 U_BOOT_DRIVER(root_driver) = {
366         .name   = "root_driver",
367         .id     = UCLASS_ROOT,
368         ACPI_OPS_PTR(&root_acpi_ops)
369 };
370
371 /* This is the root uclass */
372 UCLASS_DRIVER(root) = {
373         .name   = "root",
374         .id     = UCLASS_ROOT,
375 };