blob: f7fb0cc0fa7c60000153897316b1ef7ff5ae8e95 [file] [log] [blame]
Simon Glassdd6ab882014-02-26 15:59:18 -07001/*
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>
Vignesh R0dff3702016-07-06 09:58:55 +053013#include <asm/io.h>
Simon Glassdb6f0202014-07-23 06:55:12 -060014#include <fdtdec.h>
Stefan Roeseadc09052015-09-02 07:41:12 +020015#include <fdt_support.h>
Simon Glassdd6ab882014-02-26 15:59:18 -070016#include <malloc.h>
17#include <dm/device.h>
18#include <dm/device-internal.h>
19#include <dm/lists.h>
Masahiro Yamadaf8efa632015-08-27 12:44:29 +090020#include <dm/pinctrl.h>
Simon Glassdd6ab882014-02-26 15:59:18 -070021#include <dm/platdata.h>
22#include <dm/uclass.h>
23#include <dm/uclass-internal.h>
24#include <dm/util.h>
25#include <linux/err.h>
26#include <linux/list.h>
27
Simon Glassdb6f0202014-07-23 06:55:12 -060028DECLARE_GLOBAL_DATA_PTR;
29
Stephen Warren8c93df12016-05-11 15:26:24 -060030static int device_bind_common(struct udevice *parent, const struct driver *drv,
31 const char *name, void *platdata,
32 ulong driver_data, int of_offset,
33 struct udevice **devp)
Simon Glassdd6ab882014-02-26 15:59:18 -070034{
Heiko Schocherb74fcb42014-05-22 12:43:05 +020035 struct udevice *dev;
Simon Glassdd6ab882014-02-26 15:59:18 -070036 struct uclass *uc;
Przemyslaw Marczakd850e672015-04-15 13:07:18 +020037 int size, ret = 0;
Simon Glassdd6ab882014-02-26 15:59:18 -070038
Masahiro Yamadae1cc1f02015-08-27 12:44:28 +090039 if (devp)
40 *devp = NULL;
Simon Glassdd6ab882014-02-26 15:59:18 -070041 if (!name)
42 return -EINVAL;
43
44 ret = uclass_get(drv->id, &uc);
Simon Glass43313de2015-08-30 16:55:16 -060045 if (ret) {
46 debug("Missing uclass for driver %s\n", drv->name);
Simon Glassdd6ab882014-02-26 15:59:18 -070047 return ret;
Simon Glass43313de2015-08-30 16:55:16 -060048 }
Simon Glassdd6ab882014-02-26 15:59:18 -070049
Heiko Schocherb74fcb42014-05-22 12:43:05 +020050 dev = calloc(1, sizeof(struct udevice));
Simon Glassdd6ab882014-02-26 15:59:18 -070051 if (!dev)
52 return -ENOMEM;
53
54 INIT_LIST_HEAD(&dev->sibling_node);
55 INIT_LIST_HEAD(&dev->child_head);
56 INIT_LIST_HEAD(&dev->uclass_node);
Masahiro Yamada029bfca2015-07-25 21:52:37 +090057#ifdef CONFIG_DEVRES
Masahiro Yamada8b15b162015-07-25 21:52:35 +090058 INIT_LIST_HEAD(&dev->devres_head);
Masahiro Yamada029bfca2015-07-25 21:52:37 +090059#endif
Simon Glassdd6ab882014-02-26 15:59:18 -070060 dev->platdata = platdata;
Stephen Warren8c93df12016-05-11 15:26:24 -060061 dev->driver_data = driver_data;
Simon Glassdd6ab882014-02-26 15:59:18 -070062 dev->name = name;
63 dev->of_offset = of_offset;
64 dev->parent = parent;
65 dev->driver = drv;
66 dev->uclass = uc;
Simon Glassdb6f0202014-07-23 06:55:12 -060067
Simon Glassdb6f0202014-07-23 06:55:12 -060068 dev->seq = -1;
Simon Glass0ccb0972015-01-25 08:27:05 -070069 dev->req_seq = -1;
Nathan Rossi7fa6ff42016-01-08 03:00:45 +100070 if (CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DM_SEQ_ALIAS)) {
Simon Glass1bd3deb2015-02-27 22:06:30 -070071 /*
Stefan Roese9d4ce6b2016-03-16 09:58:01 +010072 * Some devices, such as a SPI bus, I2C bus and serial ports
73 * are numbered using aliases.
74 *
75 * This is just a 'requested' sequence, and will be
76 * resolved (and ->seq updated) when the device is probed.
77 */
Simon Glass1bd3deb2015-02-27 22:06:30 -070078 if (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS) {
79 if (uc->uc_drv->name && of_offset != -1) {
80 fdtdec_get_alias_seq(gd->fdt_blob,
81 uc->uc_drv->name, of_offset,
82 &dev->req_seq);
83 }
Simon Glass0ccb0972015-01-25 08:27:05 -070084 }
Simon Glassdb6f0202014-07-23 06:55:12 -060085 }
Simon Glass1bd3deb2015-02-27 22:06:30 -070086
Simon Glassba750492015-01-25 08:27:00 -070087 if (!dev->platdata && drv->platdata_auto_alloc_size) {
Simon Glassdd6ab882014-02-26 15:59:18 -070088 dev->flags |= DM_FLAG_ALLOC_PDATA;
Simon Glassba750492015-01-25 08:27:00 -070089 dev->platdata = calloc(1, drv->platdata_auto_alloc_size);
90 if (!dev->platdata) {
91 ret = -ENOMEM;
92 goto fail_alloc1;
93 }
94 }
Przemyslaw Marczakd850e672015-04-15 13:07:18 +020095
96 size = uc->uc_drv->per_device_platdata_auto_alloc_size;
97 if (size) {
98 dev->flags |= DM_FLAG_ALLOC_UCLASS_PDATA;
99 dev->uclass_platdata = calloc(1, size);
100 if (!dev->uclass_platdata) {
101 ret = -ENOMEM;
102 goto fail_alloc2;
103 }
104 }
Simon Glass11b61732015-01-25 08:27:01 -0700105
Przemyslaw Marczakd850e672015-04-15 13:07:18 +0200106 if (parent) {
107 size = parent->driver->per_child_platdata_auto_alloc_size;
Simon Glass57f95402015-01-25 08:27:02 -0700108 if (!size) {
109 size = parent->uclass->uc_drv->
110 per_child_platdata_auto_alloc_size;
111 }
Simon Glass11b61732015-01-25 08:27:01 -0700112 if (size) {
113 dev->flags |= DM_FLAG_ALLOC_PARENT_PDATA;
114 dev->parent_platdata = calloc(1, size);
115 if (!dev->parent_platdata) {
116 ret = -ENOMEM;
Przemyslaw Marczakd850e672015-04-15 13:07:18 +0200117 goto fail_alloc3;
Simon Glass11b61732015-01-25 08:27:01 -0700118 }
119 }
120 }
Simon Glassdd6ab882014-02-26 15:59:18 -0700121
122 /* put dev into parent's successor list */
123 if (parent)
124 list_add_tail(&dev->sibling_node, &parent->child_head);
125
126 ret = uclass_bind_device(dev);
127 if (ret)
Simon Glass4ebe01b2015-01-25 08:26:59 -0700128 goto fail_uclass_bind;
Simon Glassdd6ab882014-02-26 15:59:18 -0700129
130 /* if we fail to bind we remove device from successors and free it */
131 if (drv->bind) {
132 ret = drv->bind(dev);
Simon Glass4ebe01b2015-01-25 08:26:59 -0700133 if (ret)
Simon Glassdd6ab882014-02-26 15:59:18 -0700134 goto fail_bind;
Simon Glassdd6ab882014-02-26 15:59:18 -0700135 }
Simon Glassa4a51a02015-01-25 08:27:03 -0700136 if (parent && parent->driver->child_post_bind) {
137 ret = parent->driver->child_post_bind(dev);
138 if (ret)
139 goto fail_child_post_bind;
140 }
Simon Glass286863d2016-01-05 09:30:59 -0700141 if (uc->uc_drv->post_bind) {
142 ret = uc->uc_drv->post_bind(dev);
143 if (ret)
144 goto fail_uclass_post_bind;
145 }
Simon Glassa4a51a02015-01-25 08:27:03 -0700146
Simon Glassdd6ab882014-02-26 15:59:18 -0700147 if (parent)
148 dm_dbg("Bound device %s to %s\n", dev->name, parent->name);
Masahiro Yamadae1cc1f02015-08-27 12:44:28 +0900149 if (devp)
150 *devp = dev;
Simon Glassdd6ab882014-02-26 15:59:18 -0700151
Masahiro Yamadabdbb5dd2015-07-25 21:52:34 +0900152 dev->flags |= DM_FLAG_BOUND;
153
Simon Glassdd6ab882014-02-26 15:59:18 -0700154 return 0;
155
Simon Glass286863d2016-01-05 09:30:59 -0700156fail_uclass_post_bind:
157 /* There is no child unbind() method, so no clean-up required */
Simon Glassa4a51a02015-01-25 08:27:03 -0700158fail_child_post_bind:
Masahiro Yamada04aa00d2015-08-12 07:31:52 +0900159 if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
Simon Glasse70a4f42015-02-27 22:06:33 -0700160 if (drv->unbind && drv->unbind(dev)) {
161 dm_warn("unbind() method failed on dev '%s' on error path\n",
162 dev->name);
163 }
Simon Glassa4a51a02015-01-25 08:27:03 -0700164 }
165
Simon Glassdd6ab882014-02-26 15:59:18 -0700166fail_bind:
Masahiro Yamada04aa00d2015-08-12 07:31:52 +0900167 if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
Simon Glasse70a4f42015-02-27 22:06:33 -0700168 if (uclass_unbind_device(dev)) {
169 dm_warn("Failed to unbind dev '%s' on error path\n",
170 dev->name);
171 }
Simon Glass4ebe01b2015-01-25 08:26:59 -0700172 }
173fail_uclass_bind:
Masahiro Yamada04aa00d2015-08-12 07:31:52 +0900174 if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
Simon Glasse70a4f42015-02-27 22:06:33 -0700175 list_del(&dev->sibling_node);
176 if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
177 free(dev->parent_platdata);
178 dev->parent_platdata = NULL;
179 }
Simon Glass11b61732015-01-25 08:27:01 -0700180 }
Przemyslaw Marczakd850e672015-04-15 13:07:18 +0200181fail_alloc3:
182 if (dev->flags & DM_FLAG_ALLOC_UCLASS_PDATA) {
183 free(dev->uclass_platdata);
184 dev->uclass_platdata = NULL;
185 }
Simon Glass11b61732015-01-25 08:27:01 -0700186fail_alloc2:
Simon Glassba750492015-01-25 08:27:00 -0700187 if (dev->flags & DM_FLAG_ALLOC_PDATA) {
188 free(dev->platdata);
189 dev->platdata = NULL;
190 }
191fail_alloc1:
Masahiro Yamada8b15b162015-07-25 21:52:35 +0900192 devres_release_all(dev);
193
Simon Glassdd6ab882014-02-26 15:59:18 -0700194 free(dev);
Simon Glass4ebe01b2015-01-25 08:26:59 -0700195
Simon Glassdd6ab882014-02-26 15:59:18 -0700196 return ret;
197}
198
Stephen Warren8c93df12016-05-11 15:26:24 -0600199int device_bind_with_driver_data(struct udevice *parent,
200 const struct driver *drv, const char *name,
201 ulong driver_data, int of_offset,
202 struct udevice **devp)
203{
204 return device_bind_common(parent, drv, name, NULL, driver_data,
205 of_offset, devp);
206}
207
208int device_bind(struct udevice *parent, const struct driver *drv,
209 const char *name, void *platdata, int of_offset,
210 struct udevice **devp)
211{
212 return device_bind_common(parent, drv, name, platdata, 0, of_offset,
213 devp);
214}
215
Simon Glassfef72b72014-07-23 06:55:03 -0600216int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
217 const struct driver_info *info, struct udevice **devp)
Simon Glassdd6ab882014-02-26 15:59:18 -0700218{
219 struct driver *drv;
220
221 drv = lists_driver_lookup_name(info->name);
222 if (!drv)
223 return -ENOENT;
Simon Glassfef72b72014-07-23 06:55:03 -0600224 if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC))
225 return -EPERM;
Simon Glassdd6ab882014-02-26 15:59:18 -0700226
227 return device_bind(parent, drv, info->name, (void *)info->platdata,
228 -1, devp);
229}
230
Simon Glass825d3f92015-03-25 12:21:53 -0600231static void *alloc_priv(int size, uint flags)
232{
233 void *priv;
234
235 if (flags & DM_FLAG_ALLOC_PRIV_DMA) {
236 priv = memalign(ARCH_DMA_MINALIGN, size);
237 if (priv)
238 memset(priv, '\0', size);
239 } else {
240 priv = calloc(1, size);
241 }
242
243 return priv;
244}
245
Simon Glass6142d752016-01-25 14:58:42 -0700246int device_probe(struct udevice *dev)
Simon Glassdd6ab882014-02-26 15:59:18 -0700247{
Simon Glassa626dff2015-03-25 12:21:54 -0600248 const struct driver *drv;
Simon Glassdd6ab882014-02-26 15:59:18 -0700249 int size = 0;
250 int ret;
Simon Glassdb6f0202014-07-23 06:55:12 -0600251 int seq;
Simon Glassdd6ab882014-02-26 15:59:18 -0700252
253 if (!dev)
254 return -EINVAL;
255
256 if (dev->flags & DM_FLAG_ACTIVATED)
257 return 0;
258
259 drv = dev->driver;
260 assert(drv);
261
Bin Meng82cdd782015-08-24 01:14:02 -0700262 /* Allocate private data if requested and not reentered */
263 if (drv->priv_auto_alloc_size && !dev->priv) {
Simon Glass825d3f92015-03-25 12:21:53 -0600264 dev->priv = alloc_priv(drv->priv_auto_alloc_size, drv->flags);
Simon Glassdd6ab882014-02-26 15:59:18 -0700265 if (!dev->priv) {
266 ret = -ENOMEM;
267 goto fail;
268 }
269 }
Bin Meng82cdd782015-08-24 01:14:02 -0700270 /* Allocate private data if requested and not reentered */
Simon Glassdd6ab882014-02-26 15:59:18 -0700271 size = dev->uclass->uc_drv->per_device_auto_alloc_size;
Bin Meng82cdd782015-08-24 01:14:02 -0700272 if (size && !dev->uclass_priv) {
Simon Glassdd6ab882014-02-26 15:59:18 -0700273 dev->uclass_priv = calloc(1, size);
274 if (!dev->uclass_priv) {
275 ret = -ENOMEM;
276 goto fail;
277 }
278 }
279
280 /* Ensure all parents are probed */
281 if (dev->parent) {
Simon Glass60d971b2014-07-23 06:55:20 -0600282 size = dev->parent->driver->per_child_auto_alloc_size;
Simon Glassc23b4282015-01-25 08:27:06 -0700283 if (!size) {
284 size = dev->parent->uclass->uc_drv->
285 per_child_auto_alloc_size;
286 }
Bin Meng82cdd782015-08-24 01:14:02 -0700287 if (size && !dev->parent_priv) {
Simon Glass825d3f92015-03-25 12:21:53 -0600288 dev->parent_priv = alloc_priv(size, drv->flags);
Simon Glass60d971b2014-07-23 06:55:20 -0600289 if (!dev->parent_priv) {
290 ret = -ENOMEM;
291 goto fail;
292 }
293 }
294
Simon Glassdd6ab882014-02-26 15:59:18 -0700295 ret = device_probe(dev->parent);
296 if (ret)
297 goto fail;
Bin Meng82cdd782015-08-24 01:14:02 -0700298
299 /*
300 * The device might have already been probed during
301 * the call to device_probe() on its parent device
302 * (e.g. PCI bridge devices). Test the flags again
303 * so that we don't mess up the device.
304 */
305 if (dev->flags & DM_FLAG_ACTIVATED)
306 return 0;
Simon Glassdd6ab882014-02-26 15:59:18 -0700307 }
Simon Glassdb6f0202014-07-23 06:55:12 -0600308
309 seq = uclass_resolve_seq(dev);
310 if (seq < 0) {
311 ret = seq;
312 goto fail;
313 }
314 dev->seq = seq;
Simon Glassdd6ab882014-02-26 15:59:18 -0700315
Simon Glass8b04e732015-03-25 12:21:56 -0600316 dev->flags |= DM_FLAG_ACTIVATED;
317
Simon Glassbb53bda2015-09-12 08:45:19 -0600318 /*
319 * Process pinctrl for everything except the root device, and
Simon Glass27ce9622016-01-21 19:43:25 -0700320 * continue regardless of the result of pinctrl. Don't process pinctrl
321 * settings for pinctrl devices since the device may not yet be
322 * probed.
Simon Glassbb53bda2015-09-12 08:45:19 -0600323 */
Simon Glass27ce9622016-01-21 19:43:25 -0700324 if (dev->parent && device_get_uclass_id(dev) != UCLASS_PINCTRL)
Simon Glassbb53bda2015-09-12 08:45:19 -0600325 pinctrl_select_state(dev, "default");
Masahiro Yamadaf8efa632015-08-27 12:44:29 +0900326
Simon Glass9c1f3822015-03-05 12:25:22 -0700327 ret = uclass_pre_probe_device(dev);
Simon Glass5104b982015-01-25 08:27:10 -0700328 if (ret)
329 goto fail;
330
Simon Glassd45560d2014-07-23 06:55:21 -0600331 if (dev->parent && dev->parent->driver->child_pre_probe) {
332 ret = dev->parent->driver->child_pre_probe(dev);
333 if (ret)
334 goto fail;
335 }
336
Simon Glassdd6ab882014-02-26 15:59:18 -0700337 if (drv->ofdata_to_platdata && dev->of_offset >= 0) {
338 ret = drv->ofdata_to_platdata(dev);
339 if (ret)
340 goto fail;
341 }
342
343 if (drv->probe) {
344 ret = drv->probe(dev);
Simon Glassd02009d2015-03-05 12:25:21 -0700345 if (ret) {
346 dev->flags &= ~DM_FLAG_ACTIVATED;
Simon Glassdd6ab882014-02-26 15:59:18 -0700347 goto fail;
Simon Glassd02009d2015-03-05 12:25:21 -0700348 }
Simon Glassdd6ab882014-02-26 15:59:18 -0700349 }
350
Simon Glassdd6ab882014-02-26 15:59:18 -0700351 ret = uclass_post_probe_device(dev);
Simon Glass8b04e732015-03-25 12:21:56 -0600352 if (ret)
Simon Glassdd6ab882014-02-26 15:59:18 -0700353 goto fail_uclass;
Simon Glassdd6ab882014-02-26 15:59:18 -0700354
Peng Fan7cf58dd2016-03-12 13:17:38 +0800355 if (dev->parent && device_get_uclass_id(dev) == UCLASS_PINCTRL)
356 pinctrl_select_state(dev, "default");
357
Simon Glassdd6ab882014-02-26 15:59:18 -0700358 return 0;
359fail_uclass:
360 if (device_remove(dev)) {
361 dm_warn("%s: Device '%s' failed to remove on error path\n",
362 __func__, dev->name);
363 }
364fail:
Simon Glass8b04e732015-03-25 12:21:56 -0600365 dev->flags &= ~DM_FLAG_ACTIVATED;
366
Simon Glassdb6f0202014-07-23 06:55:12 -0600367 dev->seq = -1;
Simon Glassdd6ab882014-02-26 15:59:18 -0700368 device_free(dev);
369
370 return ret;
371}
372
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200373void *dev_get_platdata(struct udevice *dev)
Simon Glassdd6ab882014-02-26 15:59:18 -0700374{
375 if (!dev) {
Simon Glassdf1e0722014-12-10 08:55:56 -0700376 dm_warn("%s: null device\n", __func__);
Simon Glassdd6ab882014-02-26 15:59:18 -0700377 return NULL;
378 }
379
380 return dev->platdata;
381}
382
Simon Glass11b61732015-01-25 08:27:01 -0700383void *dev_get_parent_platdata(struct udevice *dev)
384{
385 if (!dev) {
Simon Glasscdfc5052015-07-06 16:47:40 -0600386 dm_warn("%s: null device\n", __func__);
Simon Glass11b61732015-01-25 08:27:01 -0700387 return NULL;
388 }
389
390 return dev->parent_platdata;
391}
392
Przemyslaw Marczakd850e672015-04-15 13:07:18 +0200393void *dev_get_uclass_platdata(struct udevice *dev)
394{
395 if (!dev) {
Simon Glasscdfc5052015-07-06 16:47:40 -0600396 dm_warn("%s: null device\n", __func__);
Przemyslaw Marczakd850e672015-04-15 13:07:18 +0200397 return NULL;
398 }
399
400 return dev->uclass_platdata;
401}
402
Heiko Schocherb74fcb42014-05-22 12:43:05 +0200403void *dev_get_priv(struct udevice *dev)
Simon Glassdd6ab882014-02-26 15:59:18 -0700404{
405 if (!dev) {
Simon Glassdf1e0722014-12-10 08:55:56 -0700406 dm_warn("%s: null device\n", __func__);
Simon Glassdd6ab882014-02-26 15:59:18 -0700407 return NULL;
408 }
409
410 return dev->priv;
411}
Simon Glass48d4e292014-07-23 06:55:19 -0600412
Simon Glassde0977b2015-03-05 12:25:20 -0700413void *dev_get_uclass_priv(struct udevice *dev)
414{
415 if (!dev) {
416 dm_warn("%s: null device\n", __func__);
417 return NULL;
418 }
419
420 return dev->uclass_priv;
421}
422
Simon Glassde44acf2015-09-28 23:32:01 -0600423void *dev_get_parent_priv(struct udevice *dev)
Simon Glass60d971b2014-07-23 06:55:20 -0600424{
425 if (!dev) {
Simon Glassdf1e0722014-12-10 08:55:56 -0700426 dm_warn("%s: null device\n", __func__);
Simon Glass60d971b2014-07-23 06:55:20 -0600427 return NULL;
428 }
429
430 return dev->parent_priv;
431}
432
Simon Glass48d4e292014-07-23 06:55:19 -0600433static int device_get_device_tail(struct udevice *dev, int ret,
434 struct udevice **devp)
435{
436 if (ret)
437 return ret;
438
439 ret = device_probe(dev);
440 if (ret)
441 return ret;
442
443 *devp = dev;
444
445 return 0;
446}
447
448int device_get_child(struct udevice *parent, int index, struct udevice **devp)
449{
450 struct udevice *dev;
451
452 list_for_each_entry(dev, &parent->child_head, sibling_node) {
453 if (!index--)
454 return device_get_device_tail(dev, 0, devp);
455 }
456
457 return -ENODEV;
458}
459
460int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq,
461 bool find_req_seq, struct udevice **devp)
462{
463 struct udevice *dev;
464
465 *devp = NULL;
466 if (seq_or_req_seq == -1)
467 return -ENODEV;
468
469 list_for_each_entry(dev, &parent->child_head, sibling_node) {
470 if ((find_req_seq ? dev->req_seq : dev->seq) ==
471 seq_or_req_seq) {
472 *devp = dev;
473 return 0;
474 }
475 }
476
477 return -ENODEV;
478}
479
480int device_get_child_by_seq(struct udevice *parent, int seq,
481 struct udevice **devp)
482{
483 struct udevice *dev;
484 int ret;
485
486 *devp = NULL;
487 ret = device_find_child_by_seq(parent, seq, false, &dev);
488 if (ret == -ENODEV) {
489 /*
490 * We didn't find it in probed devices. See if there is one
491 * that will request this seq if probed.
492 */
493 ret = device_find_child_by_seq(parent, seq, true, &dev);
494 }
495 return device_get_device_tail(dev, ret, devp);
496}
497
498int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
499 struct udevice **devp)
500{
501 struct udevice *dev;
502
503 *devp = NULL;
504
505 list_for_each_entry(dev, &parent->child_head, sibling_node) {
506 if (dev->of_offset == of_offset) {
507 *devp = dev;
508 return 0;
509 }
510 }
511
512 return -ENODEV;
513}
514
Simon Glass861bc9f2015-06-23 15:38:38 -0600515int device_get_child_by_of_offset(struct udevice *parent, int node,
Simon Glass48d4e292014-07-23 06:55:19 -0600516 struct udevice **devp)
517{
518 struct udevice *dev;
519 int ret;
520
521 *devp = NULL;
Simon Glass861bc9f2015-06-23 15:38:38 -0600522 ret = device_find_child_by_of_offset(parent, node, &dev);
Simon Glass48d4e292014-07-23 06:55:19 -0600523 return device_get_device_tail(dev, ret, devp);
524}
Simon Glass44da7352014-10-13 23:41:49 -0600525
Simon Glassae2efac2015-06-23 15:38:37 -0600526static struct udevice *_device_find_global_by_of_offset(struct udevice *parent,
527 int of_offset)
528{
529 struct udevice *dev, *found;
530
531 if (parent->of_offset == of_offset)
532 return parent;
533
534 list_for_each_entry(dev, &parent->child_head, sibling_node) {
535 found = _device_find_global_by_of_offset(dev, of_offset);
536 if (found)
537 return found;
538 }
539
540 return NULL;
541}
542
543int device_get_global_by_of_offset(int of_offset, struct udevice **devp)
544{
545 struct udevice *dev;
546
547 dev = _device_find_global_by_of_offset(gd->dm_root, of_offset);
548 return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
549}
550
Simon Glass44da7352014-10-13 23:41:49 -0600551int device_find_first_child(struct udevice *parent, struct udevice **devp)
552{
553 if (list_empty(&parent->child_head)) {
554 *devp = NULL;
555 } else {
556 *devp = list_first_entry(&parent->child_head, struct udevice,
557 sibling_node);
558 }
559
560 return 0;
561}
562
563int device_find_next_child(struct udevice **devp)
564{
565 struct udevice *dev = *devp;
566 struct udevice *parent = dev->parent;
567
568 if (list_is_last(&dev->sibling_node, &parent->child_head)) {
569 *devp = NULL;
570 } else {
571 *devp = list_entry(dev->sibling_node.next, struct udevice,
572 sibling_node);
573 }
574
575 return 0;
576}
Simon Glass70c3a0e2014-11-11 10:46:18 -0700577
Simon Glass43f488a2014-11-11 10:46:19 -0700578struct udevice *dev_get_parent(struct udevice *child)
579{
580 return child->parent;
581}
582
Simon Glass46227bd2015-03-25 12:21:55 -0600583ulong dev_get_driver_data(struct udevice *dev)
Simon Glass70c3a0e2014-11-11 10:46:18 -0700584{
Simon Glass46227bd2015-03-25 12:21:55 -0600585 return dev->driver_data;
Simon Glass70c3a0e2014-11-11 10:46:18 -0700586}
Simon Glass98fd5d12015-01-25 08:27:04 -0700587
Przemyslaw Marczakd3ef0d72015-04-15 13:07:24 +0200588const void *dev_get_driver_ops(struct udevice *dev)
589{
590 if (!dev || !dev->driver->ops)
591 return NULL;
592
593 return dev->driver->ops;
594}
595
Simon Glass98fd5d12015-01-25 08:27:04 -0700596enum uclass_id device_get_uclass_id(struct udevice *dev)
597{
598 return dev->uclass->uc_drv->id;
599}
Peng Fan99b72352015-02-10 14:46:32 +0800600
Przemyslaw Marczak5ed2e422015-04-15 13:07:25 +0200601const char *dev_get_uclass_name(struct udevice *dev)
602{
603 if (!dev)
604 return NULL;
605
606 return dev->uclass->uc_drv->name;
607}
608
Mugunthan V N4b776e52015-12-23 20:39:36 +0530609fdt_addr_t dev_get_addr_index(struct udevice *dev, int index)
Peng Fan99b72352015-02-10 14:46:32 +0800610{
Masahiro Yamada366b24f2015-08-12 07:31:55 +0900611#if CONFIG_IS_ENABLED(OF_CONTROL)
Simon Glass59b61962015-07-07 20:53:44 -0600612 fdt_addr_t addr;
613
Stefan Roeseadc09052015-09-02 07:41:12 +0200614 if (CONFIG_IS_ENABLED(OF_TRANSLATE)) {
615 const fdt32_t *reg;
Mugunthan V N4b776e52015-12-23 20:39:36 +0530616 int len = 0;
617 int na, ns;
618
619 na = fdt_address_cells(gd->fdt_blob, dev->parent->of_offset);
620 if (na < 1) {
621 debug("bad #address-cells\n");
622 return FDT_ADDR_T_NONE;
623 }
624
625 ns = fdt_size_cells(gd->fdt_blob, dev->parent->of_offset);
626 if (ns < 0) {
627 debug("bad #size-cells\n");
628 return FDT_ADDR_T_NONE;
629 }
Stefan Roeseadc09052015-09-02 07:41:12 +0200630
Mugunthan V N4b776e52015-12-23 20:39:36 +0530631 reg = fdt_getprop(gd->fdt_blob, dev->of_offset, "reg", &len);
632 if (!reg || (len <= (index * sizeof(fdt32_t) * (na + ns)))) {
633 debug("Req index out of range\n");
Stefan Roeseadc09052015-09-02 07:41:12 +0200634 return FDT_ADDR_T_NONE;
Mugunthan V N4b776e52015-12-23 20:39:36 +0530635 }
636
637 reg += index * (na + ns);
Stefan Roeseadc09052015-09-02 07:41:12 +0200638
639 /*
640 * Use the full-fledged translate function for complex
641 * bus setups.
642 */
Stefan Roesea0ea0f92015-12-14 16:18:15 +0100643 addr = fdt_translate_address((void *)gd->fdt_blob,
Stefan Roeseadc09052015-09-02 07:41:12 +0200644 dev->of_offset, reg);
Stefan Roesea0ea0f92015-12-14 16:18:15 +0100645 } else {
646 /*
647 * Use the "simple" translate function for less complex
648 * bus setups.
649 */
650 addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
651 dev->parent->of_offset,
652 dev->of_offset, "reg",
Mugunthan V N4b776e52015-12-23 20:39:36 +0530653 index, NULL);
Stefan Roesea0ea0f92015-12-14 16:18:15 +0100654 if (CONFIG_IS_ENABLED(SIMPLE_BUS) && addr != FDT_ADDR_T_NONE) {
655 if (device_get_uclass_id(dev->parent) ==
656 UCLASS_SIMPLE_BUS)
657 addr = simple_bus_translate(dev->parent, addr);
658 }
Stefan Roeseadc09052015-09-02 07:41:12 +0200659 }
660
661 /*
Stefan Roesea0ea0f92015-12-14 16:18:15 +0100662 * Some platforms need a special address translation. Those
663 * platforms (e.g. mvebu in SPL) can configure a translation
664 * offset in the DM by calling dm_set_translation_offset() that
665 * will get added to all addresses returned by dev_get_addr().
Stefan Roeseadc09052015-09-02 07:41:12 +0200666 */
Stefan Roesea0ea0f92015-12-14 16:18:15 +0100667 addr += dm_get_translation_offset();
Simon Glass59b61962015-07-07 20:53:44 -0600668
669 return addr;
Peng Fan99b72352015-02-10 14:46:32 +0800670#else
Peng Fan99b72352015-02-10 14:46:32 +0800671 return FDT_ADDR_T_NONE;
Peng Fan99b72352015-02-10 14:46:32 +0800672#endif
Simon Glass59b61962015-07-07 20:53:44 -0600673}
Simon Glass40f829a2015-03-25 12:21:57 -0600674
Stephen Warren18079072016-04-06 12:49:19 -0600675fdt_addr_t dev_get_addr_name(struct udevice *dev, const char *name)
676{
677#if CONFIG_IS_ENABLED(OF_CONTROL)
678 int index;
679
Stephen Warren38b82d52016-04-28 16:04:15 -0600680 index = fdt_find_string(gd->fdt_blob, dev->of_offset, "reg-names",
681 name);
Stephen Warren18079072016-04-06 12:49:19 -0600682 if (index < 0)
683 return index;
684
685 return dev_get_addr_index(dev, index);
686#else
687 return FDT_ADDR_T_NONE;
688#endif
689}
690
Mugunthan V N4b776e52015-12-23 20:39:36 +0530691fdt_addr_t dev_get_addr(struct udevice *dev)
692{
693 return dev_get_addr_index(dev, 0);
694}
695
Stefan Roesed8fc5ff2016-04-21 07:11:34 +0200696void *dev_get_addr_ptr(struct udevice *dev)
697{
698 return (void *)(uintptr_t)dev_get_addr_index(dev, 0);
699}
700
Vignesh R0dff3702016-07-06 09:58:55 +0530701void *dev_map_physmem(struct udevice *dev, unsigned long size)
702{
703 fdt_addr_t addr = dev_get_addr(dev);
704
705 if (addr == FDT_ADDR_T_NONE)
706 return NULL;
707
708 return map_physmem(addr, size, MAP_NOCACHE);
709}
710
Simon Glass40f829a2015-03-25 12:21:57 -0600711bool device_has_children(struct udevice *dev)
712{
713 return !list_empty(&dev->child_head);
714}
715
716bool device_has_active_children(struct udevice *dev)
717{
718 struct udevice *child;
719
720 for (device_find_first_child(dev, &child);
721 child;
722 device_find_next_child(&child)) {
723 if (device_active(child))
724 return true;
725 }
726
727 return false;
728}
729
730bool device_is_last_sibling(struct udevice *dev)
731{
732 struct udevice *parent = dev->parent;
733
734 if (!parent)
735 return false;
736 return list_is_last(&dev->sibling_node, &parent->child_head);
737}
Simon Glasse3b23e22015-07-30 13:40:39 -0600738
Simon Glass7760ba22016-05-01 13:52:23 -0600739void device_set_name_alloced(struct udevice *dev)
740{
741 dev->flags |= DM_NAME_ALLOCED;
742}
743
Simon Glasse3b23e22015-07-30 13:40:39 -0600744int device_set_name(struct udevice *dev, const char *name)
745{
746 name = strdup(name);
747 if (!name)
748 return -ENOMEM;
749 dev->name = name;
Simon Glass7760ba22016-05-01 13:52:23 -0600750 device_set_name_alloced(dev);
Simon Glasse3b23e22015-07-30 13:40:39 -0600751
752 return 0;
753}
Mugunthan V N4666bd92016-04-28 15:36:02 +0530754
755bool of_device_is_compatible(struct udevice *dev, const char *compat)
756{
757 const void *fdt = gd->fdt_blob;
758
759 return !fdt_node_check_compatible(fdt, dev->of_offset, compat);
760}
761
762bool of_machine_is_compatible(const char *compat)
763{
764 const void *fdt = gd->fdt_blob;
765
766 return !fdt_node_check_compatible(fdt, 0, compat);
767}