]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/core/device.c
dm: core: Correct device_get_child_by_of_offset() parameter
[karo-tx-uboot.git] / drivers / core / device.c
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>
13 #include <fdtdec.h>
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
25 DECLARE_GLOBAL_DATA_PTR;
26
27 int device_bind(struct udevice *parent, const struct driver *drv,
28                 const char *name, void *platdata, int of_offset,
29                 struct udevice **devp)
30 {
31         struct udevice *dev;
32         struct uclass *uc;
33         int size, ret = 0;
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
43         dev = calloc(1, sizeof(struct udevice));
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;
56
57         dev->seq = -1;
58         dev->req_seq = -1;
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                         }
73                 }
74         }
75
76         if (!dev->platdata && drv->platdata_auto_alloc_size) {
77                 dev->flags |= DM_FLAG_ALLOC_PDATA;
78                 dev->platdata = calloc(1, drv->platdata_auto_alloc_size);
79                 if (!dev->platdata) {
80                         ret = -ENOMEM;
81                         goto fail_alloc1;
82                 }
83         }
84
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;
97                 if (!size) {
98                         size = parent->uclass->uc_drv->
99                                         per_child_platdata_auto_alloc_size;
100                 }
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;
106                                 goto fail_alloc3;
107                         }
108                 }
109         }
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)
117                 goto fail_uclass_bind;
118
119         /* if we fail to bind we remove device from successors and free it */
120         if (drv->bind) {
121                 ret = drv->bind(dev);
122                 if (ret)
123                         goto fail_bind;
124         }
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
131         if (parent)
132                 dm_dbg("Bound device %s to %s\n", dev->name, parent->name);
133         *devp = dev;
134
135         return 0;
136
137 fail_child_post_bind:
138         if (IS_ENABLED(CONFIG_DM_DEVICE_REMOVE)) {
139                 if (drv->unbind && drv->unbind(dev)) {
140                         dm_warn("unbind() method failed on dev '%s' on error path\n",
141                                 dev->name);
142                 }
143         }
144
145 fail_bind:
146         if (IS_ENABLED(CONFIG_DM_DEVICE_REMOVE)) {
147                 if (uclass_unbind_device(dev)) {
148                         dm_warn("Failed to unbind dev '%s' on error path\n",
149                                 dev->name);
150                 }
151         }
152 fail_uclass_bind:
153         if (IS_ENABLED(CONFIG_DM_DEVICE_REMOVE)) {
154                 list_del(&dev->sibling_node);
155                 if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
156                         free(dev->parent_platdata);
157                         dev->parent_platdata = NULL;
158                 }
159         }
160 fail_alloc3:
161         if (dev->flags & DM_FLAG_ALLOC_UCLASS_PDATA) {
162                 free(dev->uclass_platdata);
163                 dev->uclass_platdata = NULL;
164         }
165 fail_alloc2:
166         if (dev->flags & DM_FLAG_ALLOC_PDATA) {
167                 free(dev->platdata);
168                 dev->platdata = NULL;
169         }
170 fail_alloc1:
171         free(dev);
172
173         return ret;
174 }
175
176 int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
177                         const struct driver_info *info, struct udevice **devp)
178 {
179         struct driver *drv;
180
181         drv = lists_driver_lookup_name(info->name);
182         if (!drv)
183                 return -ENOENT;
184         if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC))
185                 return -EPERM;
186
187         return device_bind(parent, drv, info->name, (void *)info->platdata,
188                            -1, devp);
189 }
190
191 static void *alloc_priv(int size, uint flags)
192 {
193         void *priv;
194
195         if (flags & DM_FLAG_ALLOC_PRIV_DMA) {
196                 priv = memalign(ARCH_DMA_MINALIGN, size);
197                 if (priv)
198                         memset(priv, '\0', size);
199         } else {
200                 priv = calloc(1, size);
201         }
202
203         return priv;
204 }
205
206 int device_probe_child(struct udevice *dev, void *parent_priv)
207 {
208         const struct driver *drv;
209         int size = 0;
210         int ret;
211         int seq;
212
213         if (!dev)
214                 return -EINVAL;
215
216         if (dev->flags & DM_FLAG_ACTIVATED)
217                 return 0;
218
219         drv = dev->driver;
220         assert(drv);
221
222         /* Allocate private data if requested */
223         if (drv->priv_auto_alloc_size) {
224                 dev->priv = alloc_priv(drv->priv_auto_alloc_size, drv->flags);
225                 if (!dev->priv) {
226                         ret = -ENOMEM;
227                         goto fail;
228                 }
229         }
230         /* Allocate private data if requested */
231         size = dev->uclass->uc_drv->per_device_auto_alloc_size;
232         if (size) {
233                 dev->uclass_priv = calloc(1, size);
234                 if (!dev->uclass_priv) {
235                         ret = -ENOMEM;
236                         goto fail;
237                 }
238         }
239
240         /* Ensure all parents are probed */
241         if (dev->parent) {
242                 size = dev->parent->driver->per_child_auto_alloc_size;
243                 if (!size) {
244                         size = dev->parent->uclass->uc_drv->
245                                         per_child_auto_alloc_size;
246                 }
247                 if (size) {
248                         dev->parent_priv = alloc_priv(size, drv->flags);
249                         if (!dev->parent_priv) {
250                                 ret = -ENOMEM;
251                                 goto fail;
252                         }
253                         if (parent_priv)
254                                 memcpy(dev->parent_priv, parent_priv, size);
255                 }
256
257                 ret = device_probe(dev->parent);
258                 if (ret)
259                         goto fail;
260         }
261
262         seq = uclass_resolve_seq(dev);
263         if (seq < 0) {
264                 ret = seq;
265                 goto fail;
266         }
267         dev->seq = seq;
268
269         dev->flags |= DM_FLAG_ACTIVATED;
270
271         ret = uclass_pre_probe_device(dev);
272         if (ret)
273                 goto fail;
274
275         if (dev->parent && dev->parent->driver->child_pre_probe) {
276                 ret = dev->parent->driver->child_pre_probe(dev);
277                 if (ret)
278                         goto fail;
279         }
280
281         if (drv->ofdata_to_platdata && dev->of_offset >= 0) {
282                 ret = drv->ofdata_to_platdata(dev);
283                 if (ret)
284                         goto fail;
285         }
286
287         dev->flags |= DM_FLAG_ACTIVATED;
288         if (drv->probe) {
289                 ret = drv->probe(dev);
290                 if (ret) {
291                         dev->flags &= ~DM_FLAG_ACTIVATED;
292                         goto fail;
293                 }
294         }
295
296         ret = uclass_post_probe_device(dev);
297         if (ret)
298                 goto fail_uclass;
299
300         return 0;
301 fail_uclass:
302         if (device_remove(dev)) {
303                 dm_warn("%s: Device '%s' failed to remove on error path\n",
304                         __func__, dev->name);
305         }
306 fail:
307         dev->flags &= ~DM_FLAG_ACTIVATED;
308
309         dev->seq = -1;
310         device_free(dev);
311
312         return ret;
313 }
314
315 int device_probe(struct udevice *dev)
316 {
317         return device_probe_child(dev, NULL);
318 }
319
320 void *dev_get_platdata(struct udevice *dev)
321 {
322         if (!dev) {
323                 dm_warn("%s: null device\n", __func__);
324                 return NULL;
325         }
326
327         return dev->platdata;
328 }
329
330 void *dev_get_parent_platdata(struct udevice *dev)
331 {
332         if (!dev) {
333                 dm_warn("%s: null device", __func__);
334                 return NULL;
335         }
336
337         return dev->parent_platdata;
338 }
339
340 void *dev_get_uclass_platdata(struct udevice *dev)
341 {
342         if (!dev) {
343                 dm_warn("%s: null device", __func__);
344                 return NULL;
345         }
346
347         return dev->uclass_platdata;
348 }
349
350 void *dev_get_priv(struct udevice *dev)
351 {
352         if (!dev) {
353                 dm_warn("%s: null device\n", __func__);
354                 return NULL;
355         }
356
357         return dev->priv;
358 }
359
360 void *dev_get_uclass_priv(struct udevice *dev)
361 {
362         if (!dev) {
363                 dm_warn("%s: null device\n", __func__);
364                 return NULL;
365         }
366
367         return dev->uclass_priv;
368 }
369
370 void *dev_get_parentdata(struct udevice *dev)
371 {
372         if (!dev) {
373                 dm_warn("%s: null device\n", __func__);
374                 return NULL;
375         }
376
377         return dev->parent_priv;
378 }
379
380 static int device_get_device_tail(struct udevice *dev, int ret,
381                                   struct udevice **devp)
382 {
383         if (ret)
384                 return ret;
385
386         ret = device_probe(dev);
387         if (ret)
388                 return ret;
389
390         *devp = dev;
391
392         return 0;
393 }
394
395 int device_get_child(struct udevice *parent, int index, struct udevice **devp)
396 {
397         struct udevice *dev;
398
399         list_for_each_entry(dev, &parent->child_head, sibling_node) {
400                 if (!index--)
401                         return device_get_device_tail(dev, 0, devp);
402         }
403
404         return -ENODEV;
405 }
406
407 int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq,
408                              bool find_req_seq, struct udevice **devp)
409 {
410         struct udevice *dev;
411
412         *devp = NULL;
413         if (seq_or_req_seq == -1)
414                 return -ENODEV;
415
416         list_for_each_entry(dev, &parent->child_head, sibling_node) {
417                 if ((find_req_seq ? dev->req_seq : dev->seq) ==
418                                 seq_or_req_seq) {
419                         *devp = dev;
420                         return 0;
421                 }
422         }
423
424         return -ENODEV;
425 }
426
427 int device_get_child_by_seq(struct udevice *parent, int seq,
428                             struct udevice **devp)
429 {
430         struct udevice *dev;
431         int ret;
432
433         *devp = NULL;
434         ret = device_find_child_by_seq(parent, seq, false, &dev);
435         if (ret == -ENODEV) {
436                 /*
437                  * We didn't find it in probed devices. See if there is one
438                  * that will request this seq if probed.
439                  */
440                 ret = device_find_child_by_seq(parent, seq, true, &dev);
441         }
442         return device_get_device_tail(dev, ret, devp);
443 }
444
445 int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
446                                    struct udevice **devp)
447 {
448         struct udevice *dev;
449
450         *devp = NULL;
451
452         list_for_each_entry(dev, &parent->child_head, sibling_node) {
453                 if (dev->of_offset == of_offset) {
454                         *devp = dev;
455                         return 0;
456                 }
457         }
458
459         return -ENODEV;
460 }
461
462 int device_get_child_by_of_offset(struct udevice *parent, int node,
463                                   struct udevice **devp)
464 {
465         struct udevice *dev;
466         int ret;
467
468         *devp = NULL;
469         ret = device_find_child_by_of_offset(parent, node, &dev);
470         return device_get_device_tail(dev, ret, devp);
471 }
472
473 static struct udevice *_device_find_global_by_of_offset(struct udevice *parent,
474                                                         int of_offset)
475 {
476         struct udevice *dev, *found;
477
478         if (parent->of_offset == of_offset)
479                 return parent;
480
481         list_for_each_entry(dev, &parent->child_head, sibling_node) {
482                 found = _device_find_global_by_of_offset(dev, of_offset);
483                 if (found)
484                         return found;
485         }
486
487         return NULL;
488 }
489
490 int device_get_global_by_of_offset(int of_offset, struct udevice **devp)
491 {
492         struct udevice *dev;
493
494         dev = _device_find_global_by_of_offset(gd->dm_root, of_offset);
495         return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
496 }
497
498 int device_find_first_child(struct udevice *parent, struct udevice **devp)
499 {
500         if (list_empty(&parent->child_head)) {
501                 *devp = NULL;
502         } else {
503                 *devp = list_first_entry(&parent->child_head, struct udevice,
504                                          sibling_node);
505         }
506
507         return 0;
508 }
509
510 int device_find_next_child(struct udevice **devp)
511 {
512         struct udevice *dev = *devp;
513         struct udevice *parent = dev->parent;
514
515         if (list_is_last(&dev->sibling_node, &parent->child_head)) {
516                 *devp = NULL;
517         } else {
518                 *devp = list_entry(dev->sibling_node.next, struct udevice,
519                                    sibling_node);
520         }
521
522         return 0;
523 }
524
525 struct udevice *dev_get_parent(struct udevice *child)
526 {
527         return child->parent;
528 }
529
530 ulong dev_get_driver_data(struct udevice *dev)
531 {
532         return dev->driver_data;
533 }
534
535 const void *dev_get_driver_ops(struct udevice *dev)
536 {
537         if (!dev || !dev->driver->ops)
538                 return NULL;
539
540         return dev->driver->ops;
541 }
542
543 enum uclass_id device_get_uclass_id(struct udevice *dev)
544 {
545         return dev->uclass->uc_drv->id;
546 }
547
548 const char *dev_get_uclass_name(struct udevice *dev)
549 {
550         if (!dev)
551                 return NULL;
552
553         return dev->uclass->uc_drv->name;
554 }
555
556 #ifdef CONFIG_OF_CONTROL
557 fdt_addr_t dev_get_addr(struct udevice *dev)
558 {
559         return fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
560 }
561 #else
562 fdt_addr_t dev_get_addr(struct udevice *dev)
563 {
564         return FDT_ADDR_T_NONE;
565 }
566 #endif
567
568 bool device_has_children(struct udevice *dev)
569 {
570         return !list_empty(&dev->child_head);
571 }
572
573 bool device_has_active_children(struct udevice *dev)
574 {
575         struct udevice *child;
576
577         for (device_find_first_child(dev, &child);
578              child;
579              device_find_next_child(&child)) {
580                 if (device_active(child))
581                         return true;
582         }
583
584         return false;
585 }
586
587 bool device_is_last_sibling(struct udevice *dev)
588 {
589         struct udevice *parent = dev->parent;
590
591         if (!parent)
592                 return false;
593         return list_is_last(&dev->sibling_node, &parent->child_head);
594 }