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