]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/core/device.c
dm: core: Drop device removal error path when not supported
[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(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(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(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 seq,
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, seq, &dev);
470         return device_get_device_tail(dev, ret, devp);
471 }
472
473 int device_find_first_child(struct udevice *parent, struct udevice **devp)
474 {
475         if (list_empty(&parent->child_head)) {
476                 *devp = NULL;
477         } else {
478                 *devp = list_first_entry(&parent->child_head, struct udevice,
479                                          sibling_node);
480         }
481
482         return 0;
483 }
484
485 int device_find_next_child(struct udevice **devp)
486 {
487         struct udevice *dev = *devp;
488         struct udevice *parent = dev->parent;
489
490         if (list_is_last(&dev->sibling_node, &parent->child_head)) {
491                 *devp = NULL;
492         } else {
493                 *devp = list_entry(dev->sibling_node.next, struct udevice,
494                                    sibling_node);
495         }
496
497         return 0;
498 }
499
500 struct udevice *dev_get_parent(struct udevice *child)
501 {
502         return child->parent;
503 }
504
505 ulong dev_get_driver_data(struct udevice *dev)
506 {
507         return dev->driver_data;
508 }
509
510 const void *dev_get_driver_ops(struct udevice *dev)
511 {
512         if (!dev || !dev->driver->ops)
513                 return NULL;
514
515         return dev->driver->ops;
516 }
517
518 enum uclass_id device_get_uclass_id(struct udevice *dev)
519 {
520         return dev->uclass->uc_drv->id;
521 }
522
523 const char *dev_get_uclass_name(struct udevice *dev)
524 {
525         if (!dev)
526                 return NULL;
527
528         return dev->uclass->uc_drv->name;
529 }
530
531 #ifdef CONFIG_OF_CONTROL
532 fdt_addr_t dev_get_addr(struct udevice *dev)
533 {
534         return fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
535 }
536 #else
537 fdt_addr_t dev_get_addr(struct udevice *dev)
538 {
539         return FDT_ADDR_T_NONE;
540 }
541 #endif
542
543 bool device_has_children(struct udevice *dev)
544 {
545         return !list_empty(&dev->child_head);
546 }
547
548 bool device_has_active_children(struct udevice *dev)
549 {
550         struct udevice *child;
551
552         for (device_find_first_child(dev, &child);
553              child;
554              device_find_next_child(&child)) {
555                 if (device_active(child))
556                         return true;
557         }
558
559         return false;
560 }
561
562 bool device_is_last_sibling(struct udevice *dev)
563 {
564         struct udevice *parent = dev->parent;
565
566         if (!parent)
567                 return false;
568         return list_is_last(&dev->sibling_node, &parent->child_head);
569 }