]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/core/device.c
dm: Add a panic_str() function to reduce code size
[people/ms/u-boot.git] / drivers / core / device.c
CommitLineData
6494d708
SG
1/*
2 * Device manager
3 *
4 * Copyright (c) 2013 Google, Inc
5 *
6 * (C) Copyright 2012
7 * Pavel Herrmann <morpheus.ibis@gmail.com>
8 *
9 * SPDX-License-Identifier: GPL-2.0+
10 */
11
12#include <common.h>
5a66a8ff 13#include <fdtdec.h>
6494d708
SG
14#include <malloc.h>
15#include <dm/device.h>
16#include <dm/device-internal.h>
17#include <dm/lists.h>
18#include <dm/platdata.h>
19#include <dm/uclass.h>
20#include <dm/uclass-internal.h>
21#include <dm/util.h>
22#include <linux/err.h>
23#include <linux/list.h>
24
5a66a8ff
SG
25DECLARE_GLOBAL_DATA_PTR;
26
3479253d
SG
27int device_bind(struct udevice *parent, const struct driver *drv,
28 const char *name, void *platdata, int of_offset,
29 struct udevice **devp)
6494d708 30{
54c5d08a 31 struct udevice *dev;
6494d708 32 struct uclass *uc;
5eaed880 33 int size, ret = 0;
6494d708
SG
34
35 *devp = NULL;
36 if (!name)
37 return -EINVAL;
38
39 ret = uclass_get(drv->id, &uc);
40 if (ret)
41 return ret;
42
54c5d08a 43 dev = calloc(1, sizeof(struct udevice));
6494d708
SG
44 if (!dev)
45 return -ENOMEM;
46
47 INIT_LIST_HEAD(&dev->sibling_node);
48 INIT_LIST_HEAD(&dev->child_head);
49 INIT_LIST_HEAD(&dev->uclass_node);
50 dev->platdata = platdata;
51 dev->name = name;
52 dev->of_offset = of_offset;
53 dev->parent = parent;
54 dev->driver = drv;
55 dev->uclass = uc;
5a66a8ff 56
5a66a8ff 57 dev->seq = -1;
9cc36a2b 58 dev->req_seq = -1;
36fa61dc
SG
59 if (IS_ENABLED(CONFIG_OF_CONTROL) && IS_ENABLED(CONFIG_DM_SEQ_ALIAS)) {
60 /*
61 * Some devices, such as a SPI bus, I2C bus and serial ports
62 * are numbered using aliases.
63 *
64 * This is just a 'requested' sequence, and will be
65 * resolved (and ->seq updated) when the device is probed.
66 */
67 if (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS) {
68 if (uc->uc_drv->name && of_offset != -1) {
69 fdtdec_get_alias_seq(gd->fdt_blob,
70 uc->uc_drv->name, of_offset,
71 &dev->req_seq);
72 }
9cc36a2b 73 }
5a66a8ff 74 }
36fa61dc 75
f8a85449 76 if (!dev->platdata && drv->platdata_auto_alloc_size) {
6494d708 77 dev->flags |= DM_FLAG_ALLOC_PDATA;
f8a85449
SG
78 dev->platdata = calloc(1, drv->platdata_auto_alloc_size);
79 if (!dev->platdata) {
80 ret = -ENOMEM;
81 goto fail_alloc1;
82 }
83 }
cdc133bd 84
5eaed880
PM
85 size = uc->uc_drv->per_device_platdata_auto_alloc_size;
86 if (size) {
87 dev->flags |= DM_FLAG_ALLOC_UCLASS_PDATA;
88 dev->uclass_platdata = calloc(1, size);
89 if (!dev->uclass_platdata) {
90 ret = -ENOMEM;
91 goto fail_alloc2;
92 }
93 }
94
95 if (parent) {
96 size = parent->driver->per_child_platdata_auto_alloc_size;
ba8da9dc
SG
97 if (!size) {
98 size = parent->uclass->uc_drv->
99 per_child_platdata_auto_alloc_size;
100 }
cdc133bd
SG
101 if (size) {
102 dev->flags |= DM_FLAG_ALLOC_PARENT_PDATA;
103 dev->parent_platdata = calloc(1, size);
104 if (!dev->parent_platdata) {
105 ret = -ENOMEM;
5eaed880 106 goto fail_alloc3;
cdc133bd
SG
107 }
108 }
109 }
6494d708
SG
110
111 /* put dev into parent's successor list */
112 if (parent)
113 list_add_tail(&dev->sibling_node, &parent->child_head);
114
115 ret = uclass_bind_device(dev);
116 if (ret)
72ebfe86 117 goto fail_uclass_bind;
6494d708
SG
118
119 /* if we fail to bind we remove device from successors and free it */
120 if (drv->bind) {
121 ret = drv->bind(dev);
72ebfe86 122 if (ret)
6494d708 123 goto fail_bind;
6494d708 124 }
0118ce79
SG
125 if (parent && parent->driver->child_post_bind) {
126 ret = parent->driver->child_post_bind(dev);
127 if (ret)
128 goto fail_child_post_bind;
129 }
130
6494d708
SG
131 if (parent)
132 dm_dbg("Bound device %s to %s\n", dev->name, parent->name);
133 *devp = dev;
134
135 return 0;
136
0118ce79
SG
137fail_child_post_bind:
138 if (drv->unbind && drv->unbind(dev)) {
139 dm_warn("unbind() method failed on dev '%s' on error path\n",
140 dev->name);
141 }
142
6494d708 143fail_bind:
72ebfe86
SG
144 if (uclass_unbind_device(dev)) {
145 dm_warn("Failed to unbind dev '%s' on error path\n",
146 dev->name);
147 }
148fail_uclass_bind:
cdc133bd
SG
149 list_del(&dev->sibling_node);
150 if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
151 free(dev->parent_platdata);
152 dev->parent_platdata = NULL;
153 }
5eaed880
PM
154fail_alloc3:
155 if (dev->flags & DM_FLAG_ALLOC_UCLASS_PDATA) {
156 free(dev->uclass_platdata);
157 dev->uclass_platdata = NULL;
158 }
cdc133bd 159fail_alloc2:
f8a85449
SG
160 if (dev->flags & DM_FLAG_ALLOC_PDATA) {
161 free(dev->platdata);
162 dev->platdata = NULL;
163 }
164fail_alloc1:
6494d708 165 free(dev);
72ebfe86 166
6494d708
SG
167 return ret;
168}
169
00606d7e
SG
170int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
171 const struct driver_info *info, struct udevice **devp)
6494d708
SG
172{
173 struct driver *drv;
174
175 drv = lists_driver_lookup_name(info->name);
176 if (!drv)
177 return -ENOENT;
00606d7e
SG
178 if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC))
179 return -EPERM;
6494d708
SG
180
181 return device_bind(parent, drv, info->name, (void *)info->platdata,
182 -1, devp);
183}
184
2c03c463
SG
185static void *alloc_priv(int size, uint flags)
186{
187 void *priv;
188
189 if (flags & DM_FLAG_ALLOC_PRIV_DMA) {
190 priv = memalign(ARCH_DMA_MINALIGN, size);
191 if (priv)
192 memset(priv, '\0', size);
193 } else {
194 priv = calloc(1, size);
195 }
196
197 return priv;
198}
199
accd4b19 200int device_probe_child(struct udevice *dev, void *parent_priv)
6494d708 201{
3479253d 202 const struct driver *drv;
6494d708
SG
203 int size = 0;
204 int ret;
5a66a8ff 205 int seq;
6494d708
SG
206
207 if (!dev)
208 return -EINVAL;
209
210 if (dev->flags & DM_FLAG_ACTIVATED)
211 return 0;
212
213 drv = dev->driver;
214 assert(drv);
215
f8a85449 216 /* Allocate private data if requested */
6494d708 217 if (drv->priv_auto_alloc_size) {
2c03c463 218 dev->priv = alloc_priv(drv->priv_auto_alloc_size, drv->flags);
6494d708
SG
219 if (!dev->priv) {
220 ret = -ENOMEM;
221 goto fail;
222 }
223 }
224 /* Allocate private data if requested */
6494d708
SG
225 size = dev->uclass->uc_drv->per_device_auto_alloc_size;
226 if (size) {
227 dev->uclass_priv = calloc(1, size);
228 if (!dev->uclass_priv) {
229 ret = -ENOMEM;
230 goto fail;
231 }
232 }
233
234 /* Ensure all parents are probed */
235 if (dev->parent) {
e59f458d 236 size = dev->parent->driver->per_child_auto_alloc_size;
dac8db2c
SG
237 if (!size) {
238 size = dev->parent->uclass->uc_drv->
239 per_child_auto_alloc_size;
240 }
e59f458d 241 if (size) {
2c03c463 242 dev->parent_priv = alloc_priv(size, drv->flags);
e59f458d
SG
243 if (!dev->parent_priv) {
244 ret = -ENOMEM;
245 goto fail;
246 }
accd4b19
SG
247 if (parent_priv)
248 memcpy(dev->parent_priv, parent_priv, size);
e59f458d
SG
249 }
250
6494d708
SG
251 ret = device_probe(dev->parent);
252 if (ret)
253 goto fail;
254 }
255
5a66a8ff
SG
256 seq = uclass_resolve_seq(dev);
257 if (seq < 0) {
258 ret = seq;
259 goto fail;
260 }
261 dev->seq = seq;
262
206d4d2b
SG
263 dev->flags |= DM_FLAG_ACTIVATED;
264
02c07b37 265 ret = uclass_pre_probe_device(dev);
83c7e434
SG
266 if (ret)
267 goto fail;
268
a327dee0
SG
269 if (dev->parent && dev->parent->driver->child_pre_probe) {
270 ret = dev->parent->driver->child_pre_probe(dev);
271 if (ret)
272 goto fail;
273 }
274
6494d708
SG
275 if (drv->ofdata_to_platdata && dev->of_offset >= 0) {
276 ret = drv->ofdata_to_platdata(dev);
277 if (ret)
278 goto fail;
279 }
280
02eeb1bb 281 dev->flags |= DM_FLAG_ACTIVATED;
6494d708
SG
282 if (drv->probe) {
283 ret = drv->probe(dev);
02eeb1bb
SG
284 if (ret) {
285 dev->flags &= ~DM_FLAG_ACTIVATED;
6494d708 286 goto fail;
02eeb1bb 287 }
6494d708
SG
288 }
289
6494d708 290 ret = uclass_post_probe_device(dev);
206d4d2b 291 if (ret)
6494d708 292 goto fail_uclass;
6494d708
SG
293
294 return 0;
295fail_uclass:
296 if (device_remove(dev)) {
297 dm_warn("%s: Device '%s' failed to remove on error path\n",
298 __func__, dev->name);
299 }
300fail:
206d4d2b
SG
301 dev->flags &= ~DM_FLAG_ACTIVATED;
302
5a66a8ff 303 dev->seq = -1;
6494d708
SG
304 device_free(dev);
305
306 return ret;
307}
308
accd4b19
SG
309int device_probe(struct udevice *dev)
310{
311 return device_probe_child(dev, NULL);
312}
313
54c5d08a 314void *dev_get_platdata(struct udevice *dev)
6494d708
SG
315{
316 if (!dev) {
964d153c 317 dm_warn("%s: null device\n", __func__);
6494d708
SG
318 return NULL;
319 }
320
321 return dev->platdata;
322}
323
cdc133bd
SG
324void *dev_get_parent_platdata(struct udevice *dev)
325{
326 if (!dev) {
327 dm_warn("%s: null device", __func__);
328 return NULL;
329 }
330
331 return dev->parent_platdata;
332}
333
5eaed880
PM
334void *dev_get_uclass_platdata(struct udevice *dev)
335{
336 if (!dev) {
337 dm_warn("%s: null device", __func__);
338 return NULL;
339 }
340
341 return dev->uclass_platdata;
342}
343
54c5d08a 344void *dev_get_priv(struct udevice *dev)
6494d708
SG
345{
346 if (!dev) {
964d153c 347 dm_warn("%s: null device\n", __func__);
6494d708
SG
348 return NULL;
349 }
350
351 return dev->priv;
352}
997c87bb 353
e564f054
SG
354void *dev_get_uclass_priv(struct udevice *dev)
355{
356 if (!dev) {
357 dm_warn("%s: null device\n", __func__);
358 return NULL;
359 }
360
361 return dev->uclass_priv;
362}
363
e59f458d
SG
364void *dev_get_parentdata(struct udevice *dev)
365{
366 if (!dev) {
964d153c 367 dm_warn("%s: null device\n", __func__);
e59f458d
SG
368 return NULL;
369 }
370
371 return dev->parent_priv;
372}
373
997c87bb
SG
374static int device_get_device_tail(struct udevice *dev, int ret,
375 struct udevice **devp)
376{
377 if (ret)
378 return ret;
379
380 ret = device_probe(dev);
381 if (ret)
382 return ret;
383
384 *devp = dev;
385
386 return 0;
387}
388
389int device_get_child(struct udevice *parent, int index, struct udevice **devp)
390{
391 struct udevice *dev;
392
393 list_for_each_entry(dev, &parent->child_head, sibling_node) {
394 if (!index--)
395 return device_get_device_tail(dev, 0, devp);
396 }
397
398 return -ENODEV;
399}
400
401int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq,
402 bool find_req_seq, struct udevice **devp)
403{
404 struct udevice *dev;
405
406 *devp = NULL;
407 if (seq_or_req_seq == -1)
408 return -ENODEV;
409
410 list_for_each_entry(dev, &parent->child_head, sibling_node) {
411 if ((find_req_seq ? dev->req_seq : dev->seq) ==
412 seq_or_req_seq) {
413 *devp = dev;
414 return 0;
415 }
416 }
417
418 return -ENODEV;
419}
420
421int device_get_child_by_seq(struct udevice *parent, int seq,
422 struct udevice **devp)
423{
424 struct udevice *dev;
425 int ret;
426
427 *devp = NULL;
428 ret = device_find_child_by_seq(parent, seq, false, &dev);
429 if (ret == -ENODEV) {
430 /*
431 * We didn't find it in probed devices. See if there is one
432 * that will request this seq if probed.
433 */
434 ret = device_find_child_by_seq(parent, seq, true, &dev);
435 }
436 return device_get_device_tail(dev, ret, devp);
437}
438
439int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
440 struct udevice **devp)
441{
442 struct udevice *dev;
443
444 *devp = NULL;
445
446 list_for_each_entry(dev, &parent->child_head, sibling_node) {
447 if (dev->of_offset == of_offset) {
448 *devp = dev;
449 return 0;
450 }
451 }
452
453 return -ENODEV;
454}
455
456int device_get_child_by_of_offset(struct udevice *parent, int seq,
457 struct udevice **devp)
458{
459 struct udevice *dev;
460 int ret;
461
462 *devp = NULL;
463 ret = device_find_child_by_of_offset(parent, seq, &dev);
464 return device_get_device_tail(dev, ret, devp);
465}
a8981d4f
SG
466
467int device_find_first_child(struct udevice *parent, struct udevice **devp)
468{
469 if (list_empty(&parent->child_head)) {
470 *devp = NULL;
471 } else {
472 *devp = list_first_entry(&parent->child_head, struct udevice,
473 sibling_node);
474 }
475
476 return 0;
477}
478
479int device_find_next_child(struct udevice **devp)
480{
481 struct udevice *dev = *devp;
482 struct udevice *parent = dev->parent;
483
484 if (list_is_last(&dev->sibling_node, &parent->child_head)) {
485 *devp = NULL;
486 } else {
487 *devp = list_entry(dev->sibling_node.next, struct udevice,
488 sibling_node);
489 }
490
491 return 0;
492}
2ef249b4 493
479728cb
SG
494struct udevice *dev_get_parent(struct udevice *child)
495{
496 return child->parent;
497}
498
39de8433 499ulong dev_get_driver_data(struct udevice *dev)
2ef249b4 500{
39de8433 501 return dev->driver_data;
2ef249b4 502}
b3670531 503
cc73d37b
PM
504const void *dev_get_driver_ops(struct udevice *dev)
505{
506 if (!dev || !dev->driver->ops)
507 return NULL;
508
509 return dev->driver->ops;
510}
511
b3670531
SG
512enum uclass_id device_get_uclass_id(struct udevice *dev)
513{
514 return dev->uclass->uc_drv->id;
515}
c9cac3f8 516
f9c370dc
PM
517const char *dev_get_uclass_name(struct udevice *dev)
518{
519 if (!dev)
520 return NULL;
521
522 return dev->uclass->uc_drv->name;
523}
524
c9cac3f8
PF
525#ifdef CONFIG_OF_CONTROL
526fdt_addr_t dev_get_addr(struct udevice *dev)
527{
528 return fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
529}
530#else
531fdt_addr_t dev_get_addr(struct udevice *dev)
532{
533 return FDT_ADDR_T_NONE;
534}
535#endif
c5785673
SG
536
537bool device_has_children(struct udevice *dev)
538{
539 return !list_empty(&dev->child_head);
540}
541
542bool device_has_active_children(struct udevice *dev)
543{
544 struct udevice *child;
545
546 for (device_find_first_child(dev, &child);
547 child;
548 device_find_next_child(&child)) {
549 if (device_active(child))
550 return true;
551 }
552
553 return false;
554}
555
556bool device_is_last_sibling(struct udevice *dev)
557{
558 struct udevice *parent = dev->parent;
559
560 if (!parent)
561 return false;
562 return list_is_last(&dev->sibling_node, &parent->child_head);
563}