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