]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/core/device.c
dm: core: Allow parents to pass data to children during probe
[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 /**
28  * device_chld_unbind() - Unbind all device's children from the device
29  *
30  * On error, the function continues to unbind all children, and reports the
31  * first error.
32  *
33  * @dev:        The device that is to be stripped of its children
34  * @return 0 on success, -ve on error
35  */
36 static int device_chld_unbind(struct udevice *dev)
37 {
38         struct udevice *pos, *n;
39         int ret, saved_ret = 0;
40
41         assert(dev);
42
43         list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
44                 ret = device_unbind(pos);
45                 if (ret && !saved_ret)
46                         saved_ret = ret;
47         }
48
49         return saved_ret;
50 }
51
52 /**
53  * device_chld_remove() - Stop all device's children
54  * @dev:        The device whose children are to be removed
55  * @return 0 on success, -ve on error
56  */
57 static int device_chld_remove(struct udevice *dev)
58 {
59         struct udevice *pos, *n;
60         int ret;
61
62         assert(dev);
63
64         list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
65                 ret = device_remove(pos);
66                 if (ret)
67                         return ret;
68         }
69
70         return 0;
71 }
72
73 int device_bind(struct udevice *parent, struct driver *drv, const char *name,
74                 void *platdata, int of_offset, struct udevice **devp)
75 {
76         struct udevice *dev;
77         struct uclass *uc;
78         int ret = 0;
79
80         *devp = NULL;
81         if (!name)
82                 return -EINVAL;
83
84         ret = uclass_get(drv->id, &uc);
85         if (ret)
86                 return ret;
87
88         dev = calloc(1, sizeof(struct udevice));
89         if (!dev)
90                 return -ENOMEM;
91
92         INIT_LIST_HEAD(&dev->sibling_node);
93         INIT_LIST_HEAD(&dev->child_head);
94         INIT_LIST_HEAD(&dev->uclass_node);
95         dev->platdata = platdata;
96         dev->name = name;
97         dev->of_offset = of_offset;
98         dev->parent = parent;
99         dev->driver = drv;
100         dev->uclass = uc;
101
102         /*
103          * For some devices, such as a SPI or I2C bus, the 'reg' property
104          * is a reasonable indicator of the sequence number. But if there is
105          * an alias, we use that in preference. In any case, this is just
106          * a 'requested' sequence, and will be resolved (and ->seq updated)
107          * when the device is probed.
108          */
109         dev->seq = -1;
110 #ifdef CONFIG_OF_CONTROL
111         dev->req_seq = fdtdec_get_int(gd->fdt_blob, of_offset, "reg", -1);
112         if (!IS_ERR_VALUE(dev->req_seq))
113                 dev->req_seq &= INT_MAX;
114         if (uc->uc_drv->name && of_offset != -1) {
115                 fdtdec_get_alias_seq(gd->fdt_blob, uc->uc_drv->name, of_offset,
116                                      &dev->req_seq);
117         }
118 #else
119         dev->req_seq = -1;
120 #endif
121         if (!dev->platdata && drv->platdata_auto_alloc_size)
122                 dev->flags |= DM_FLAG_ALLOC_PDATA;
123
124         /* put dev into parent's successor list */
125         if (parent)
126                 list_add_tail(&dev->sibling_node, &parent->child_head);
127
128         ret = uclass_bind_device(dev);
129         if (ret)
130                 goto fail_bind;
131
132         /* if we fail to bind we remove device from successors and free it */
133         if (drv->bind) {
134                 ret = drv->bind(dev);
135                 if (ret) {
136                         if (uclass_unbind_device(dev)) {
137                                 dm_warn("Failed to unbind dev '%s' on error path\n",
138                                         dev->name);
139                         }
140                         goto fail_bind;
141                 }
142         }
143         if (parent)
144                 dm_dbg("Bound device %s to %s\n", dev->name, parent->name);
145         *devp = dev;
146
147         return 0;
148
149 fail_bind:
150         list_del(&dev->sibling_node);
151         free(dev);
152         return ret;
153 }
154
155 int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
156                         const struct driver_info *info, struct udevice **devp)
157 {
158         struct driver *drv;
159
160         drv = lists_driver_lookup_name(info->name);
161         if (!drv)
162                 return -ENOENT;
163         if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC))
164                 return -EPERM;
165
166         return device_bind(parent, drv, info->name, (void *)info->platdata,
167                            -1, devp);
168 }
169
170 int device_unbind(struct udevice *dev)
171 {
172         struct driver *drv;
173         int ret;
174
175         if (!dev)
176                 return -EINVAL;
177
178         if (dev->flags & DM_FLAG_ACTIVATED)
179                 return -EINVAL;
180
181         drv = dev->driver;
182         assert(drv);
183
184         if (drv->unbind) {
185                 ret = drv->unbind(dev);
186                 if (ret)
187                         return ret;
188         }
189
190         ret = device_chld_unbind(dev);
191         if (ret)
192                 return ret;
193
194         ret = uclass_unbind_device(dev);
195         if (ret)
196                 return ret;
197
198         if (dev->parent)
199                 list_del(&dev->sibling_node);
200         free(dev);
201
202         return 0;
203 }
204
205 /**
206  * device_free() - Free memory buffers allocated by a device
207  * @dev:        Device that is to be started
208  */
209 static void device_free(struct udevice *dev)
210 {
211         int size;
212
213         if (dev->driver->priv_auto_alloc_size) {
214                 free(dev->priv);
215                 dev->priv = NULL;
216         }
217         if (dev->flags & DM_FLAG_ALLOC_PDATA) {
218                 free(dev->platdata);
219                 dev->platdata = NULL;
220         }
221         size = dev->uclass->uc_drv->per_device_auto_alloc_size;
222         if (size) {
223                 free(dev->uclass_priv);
224                 dev->uclass_priv = NULL;
225         }
226         if (dev->parent) {
227                 size = dev->parent->driver->per_child_auto_alloc_size;
228                 if (size) {
229                         free(dev->parent_priv);
230                         dev->parent_priv = NULL;
231                 }
232         }
233 }
234
235 int device_probe_child(struct udevice *dev, void *parent_priv)
236 {
237         struct driver *drv;
238         int size = 0;
239         int ret;
240         int seq;
241
242         if (!dev)
243                 return -EINVAL;
244
245         if (dev->flags & DM_FLAG_ACTIVATED)
246                 return 0;
247
248         drv = dev->driver;
249         assert(drv);
250
251         /* Allocate private data and platdata if requested */
252         if (drv->priv_auto_alloc_size) {
253                 dev->priv = calloc(1, drv->priv_auto_alloc_size);
254                 if (!dev->priv) {
255                         ret = -ENOMEM;
256                         goto fail;
257                 }
258         }
259         /* Allocate private data if requested */
260         if (dev->flags & DM_FLAG_ALLOC_PDATA) {
261                 dev->platdata = calloc(1, drv->platdata_auto_alloc_size);
262                 if (!dev->platdata) {
263                         ret = -ENOMEM;
264                         goto fail;
265                 }
266         }
267         size = dev->uclass->uc_drv->per_device_auto_alloc_size;
268         if (size) {
269                 dev->uclass_priv = calloc(1, size);
270                 if (!dev->uclass_priv) {
271                         ret = -ENOMEM;
272                         goto fail;
273                 }
274         }
275
276         /* Ensure all parents are probed */
277         if (dev->parent) {
278                 size = dev->parent->driver->per_child_auto_alloc_size;
279                 if (size) {
280                         dev->parent_priv = calloc(1, size);
281                         if (!dev->parent_priv) {
282                                 ret = -ENOMEM;
283                                 goto fail;
284                         }
285                         if (parent_priv)
286                                 memcpy(dev->parent_priv, parent_priv, size);
287                 }
288
289                 ret = device_probe(dev->parent);
290                 if (ret)
291                         goto fail;
292         }
293
294         seq = uclass_resolve_seq(dev);
295         if (seq < 0) {
296                 ret = seq;
297                 goto fail;
298         }
299         dev->seq = seq;
300
301         if (dev->parent && dev->parent->driver->child_pre_probe) {
302                 ret = dev->parent->driver->child_pre_probe(dev);
303                 if (ret)
304                         goto fail;
305         }
306
307         if (drv->ofdata_to_platdata && dev->of_offset >= 0) {
308                 ret = drv->ofdata_to_platdata(dev);
309                 if (ret)
310                         goto fail;
311         }
312
313         if (drv->probe) {
314                 ret = drv->probe(dev);
315                 if (ret)
316                         goto fail;
317         }
318
319         dev->flags |= DM_FLAG_ACTIVATED;
320
321         ret = uclass_post_probe_device(dev);
322         if (ret) {
323                 dev->flags &= ~DM_FLAG_ACTIVATED;
324                 goto fail_uclass;
325         }
326
327         return 0;
328 fail_uclass:
329         if (device_remove(dev)) {
330                 dm_warn("%s: Device '%s' failed to remove on error path\n",
331                         __func__, dev->name);
332         }
333 fail:
334         dev->seq = -1;
335         device_free(dev);
336
337         return ret;
338 }
339
340 int device_probe(struct udevice *dev)
341 {
342         return device_probe_child(dev, NULL);
343 }
344
345 int device_remove(struct udevice *dev)
346 {
347         struct driver *drv;
348         int ret;
349
350         if (!dev)
351                 return -EINVAL;
352
353         if (!(dev->flags & DM_FLAG_ACTIVATED))
354                 return 0;
355
356         drv = dev->driver;
357         assert(drv);
358
359         ret = uclass_pre_remove_device(dev);
360         if (ret)
361                 return ret;
362
363         ret = device_chld_remove(dev);
364         if (ret)
365                 goto err;
366
367         if (drv->remove) {
368                 ret = drv->remove(dev);
369                 if (ret)
370                         goto err_remove;
371         }
372
373         if (dev->parent && dev->parent->driver->child_post_remove) {
374                 ret = dev->parent->driver->child_post_remove(dev);
375                 if (ret) {
376                         dm_warn("%s: Device '%s' failed child_post_remove()",
377                                 __func__, dev->name);
378                 }
379         }
380
381         device_free(dev);
382
383         dev->seq = -1;
384         dev->flags &= ~DM_FLAG_ACTIVATED;
385
386         return ret;
387
388 err_remove:
389         /* We can't put the children back */
390         dm_warn("%s: Device '%s' failed to remove, but children are gone\n",
391                 __func__, dev->name);
392 err:
393         ret = uclass_post_probe_device(dev);
394         if (ret) {
395                 dm_warn("%s: Device '%s' failed to post_probe on error path\n",
396                         __func__, dev->name);
397         }
398
399         return ret;
400 }
401
402 void *dev_get_platdata(struct udevice *dev)
403 {
404         if (!dev) {
405                 dm_warn("%s: null device", __func__);
406                 return NULL;
407         }
408
409         return dev->platdata;
410 }
411
412 void *dev_get_priv(struct udevice *dev)
413 {
414         if (!dev) {
415                 dm_warn("%s: null device", __func__);
416                 return NULL;
417         }
418
419         return dev->priv;
420 }
421
422 void *dev_get_parentdata(struct udevice *dev)
423 {
424         if (!dev) {
425                 dm_warn("%s: null device", __func__);
426                 return NULL;
427         }
428
429         return dev->parent_priv;
430 }
431
432 static int device_get_device_tail(struct udevice *dev, int ret,
433                                   struct udevice **devp)
434 {
435         if (ret)
436                 return ret;
437
438         ret = device_probe(dev);
439         if (ret)
440                 return ret;
441
442         *devp = dev;
443
444         return 0;
445 }
446
447 int device_get_child(struct udevice *parent, int index, struct udevice **devp)
448 {
449         struct udevice *dev;
450
451         list_for_each_entry(dev, &parent->child_head, sibling_node) {
452                 if (!index--)
453                         return device_get_device_tail(dev, 0, devp);
454         }
455
456         return -ENODEV;
457 }
458
459 int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq,
460                              bool find_req_seq, struct udevice **devp)
461 {
462         struct udevice *dev;
463
464         *devp = NULL;
465         if (seq_or_req_seq == -1)
466                 return -ENODEV;
467
468         list_for_each_entry(dev, &parent->child_head, sibling_node) {
469                 if ((find_req_seq ? dev->req_seq : dev->seq) ==
470                                 seq_or_req_seq) {
471                         *devp = dev;
472                         return 0;
473                 }
474         }
475
476         return -ENODEV;
477 }
478
479 int device_get_child_by_seq(struct udevice *parent, int seq,
480                             struct udevice **devp)
481 {
482         struct udevice *dev;
483         int ret;
484
485         *devp = NULL;
486         ret = device_find_child_by_seq(parent, seq, false, &dev);
487         if (ret == -ENODEV) {
488                 /*
489                  * We didn't find it in probed devices. See if there is one
490                  * that will request this seq if probed.
491                  */
492                 ret = device_find_child_by_seq(parent, seq, true, &dev);
493         }
494         return device_get_device_tail(dev, ret, devp);
495 }
496
497 int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
498                                    struct udevice **devp)
499 {
500         struct udevice *dev;
501
502         *devp = NULL;
503
504         list_for_each_entry(dev, &parent->child_head, sibling_node) {
505                 if (dev->of_offset == of_offset) {
506                         *devp = dev;
507                         return 0;
508                 }
509         }
510
511         return -ENODEV;
512 }
513
514 int device_get_child_by_of_offset(struct udevice *parent, int seq,
515                                   struct udevice **devp)
516 {
517         struct udevice *dev;
518         int ret;
519
520         *devp = NULL;
521         ret = device_find_child_by_of_offset(parent, seq, &dev);
522         return device_get_device_tail(dev, ret, devp);
523 }
524
525 int device_find_first_child(struct udevice *parent, struct udevice **devp)
526 {
527         if (list_empty(&parent->child_head)) {
528                 *devp = NULL;
529         } else {
530                 *devp = list_first_entry(&parent->child_head, struct udevice,
531                                          sibling_node);
532         }
533
534         return 0;
535 }
536
537 int device_find_next_child(struct udevice **devp)
538 {
539         struct udevice *dev = *devp;
540         struct udevice *parent = dev->parent;
541
542         if (list_is_last(&dev->sibling_node, &parent->child_head)) {
543                 *devp = NULL;
544         } else {
545                 *devp = list_entry(dev->sibling_node.next, struct udevice,
546                                    sibling_node);
547         }
548
549         return 0;
550 }