xref: /rk3399_rockchip-uboot/drivers/core/device.c (revision e59f458de6999b8a786da857e653db6777f675ca)
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->req_seq = fdtdec_get_int(gd->fdt_blob, of_offset, "reg", -1);
110 	dev->seq = -1;
111 	if (uc->uc_drv->name && of_offset != -1) {
112 		fdtdec_get_alias_seq(gd->fdt_blob, uc->uc_drv->name, of_offset,
113 				     &dev->req_seq);
114 	}
115 
116 	if (!dev->platdata && drv->platdata_auto_alloc_size)
117 		dev->flags |= DM_FLAG_ALLOC_PDATA;
118 
119 	/* put dev into parent's successor list */
120 	if (parent)
121 		list_add_tail(&dev->sibling_node, &parent->child_head);
122 
123 	ret = uclass_bind_device(dev);
124 	if (ret)
125 		goto fail_bind;
126 
127 	/* if we fail to bind we remove device from successors and free it */
128 	if (drv->bind) {
129 		ret = drv->bind(dev);
130 		if (ret) {
131 			if (uclass_unbind_device(dev)) {
132 				dm_warn("Failed to unbind dev '%s' on error path\n",
133 					dev->name);
134 			}
135 			goto fail_bind;
136 		}
137 	}
138 	if (parent)
139 		dm_dbg("Bound device %s to %s\n", dev->name, parent->name);
140 	*devp = dev;
141 
142 	return 0;
143 
144 fail_bind:
145 	list_del(&dev->sibling_node);
146 	free(dev);
147 	return ret;
148 }
149 
150 int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
151 			const struct driver_info *info, struct udevice **devp)
152 {
153 	struct driver *drv;
154 
155 	drv = lists_driver_lookup_name(info->name);
156 	if (!drv)
157 		return -ENOENT;
158 	if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC))
159 		return -EPERM;
160 
161 	return device_bind(parent, drv, info->name, (void *)info->platdata,
162 			   -1, devp);
163 }
164 
165 int device_unbind(struct udevice *dev)
166 {
167 	struct driver *drv;
168 	int ret;
169 
170 	if (!dev)
171 		return -EINVAL;
172 
173 	if (dev->flags & DM_FLAG_ACTIVATED)
174 		return -EINVAL;
175 
176 	drv = dev->driver;
177 	assert(drv);
178 
179 	if (drv->unbind) {
180 		ret = drv->unbind(dev);
181 		if (ret)
182 			return ret;
183 	}
184 
185 	ret = device_chld_unbind(dev);
186 	if (ret)
187 		return ret;
188 
189 	ret = uclass_unbind_device(dev);
190 	if (ret)
191 		return ret;
192 
193 	if (dev->parent)
194 		list_del(&dev->sibling_node);
195 	free(dev);
196 
197 	return 0;
198 }
199 
200 /**
201  * device_free() - Free memory buffers allocated by a device
202  * @dev:	Device that is to be started
203  */
204 static void device_free(struct udevice *dev)
205 {
206 	int size;
207 
208 	if (dev->driver->priv_auto_alloc_size) {
209 		free(dev->priv);
210 		dev->priv = NULL;
211 	}
212 	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
213 		free(dev->platdata);
214 		dev->platdata = NULL;
215 	}
216 	size = dev->uclass->uc_drv->per_device_auto_alloc_size;
217 	if (size) {
218 		free(dev->uclass_priv);
219 		dev->uclass_priv = NULL;
220 	}
221 	if (dev->parent) {
222 		size = dev->parent->driver->per_child_auto_alloc_size;
223 		if (size) {
224 			free(dev->parent_priv);
225 			dev->parent_priv = NULL;
226 		}
227 	}
228 }
229 
230 int device_probe(struct udevice *dev)
231 {
232 	struct driver *drv;
233 	int size = 0;
234 	int ret;
235 	int seq;
236 
237 	if (!dev)
238 		return -EINVAL;
239 
240 	if (dev->flags & DM_FLAG_ACTIVATED)
241 		return 0;
242 
243 	drv = dev->driver;
244 	assert(drv);
245 
246 	/* Allocate private data and platdata if requested */
247 	if (drv->priv_auto_alloc_size) {
248 		dev->priv = calloc(1, drv->priv_auto_alloc_size);
249 		if (!dev->priv) {
250 			ret = -ENOMEM;
251 			goto fail;
252 		}
253 	}
254 	/* Allocate private data if requested */
255 	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
256 		dev->platdata = calloc(1, drv->platdata_auto_alloc_size);
257 		if (!dev->platdata) {
258 			ret = -ENOMEM;
259 			goto fail;
260 		}
261 	}
262 	size = dev->uclass->uc_drv->per_device_auto_alloc_size;
263 	if (size) {
264 		dev->uclass_priv = calloc(1, size);
265 		if (!dev->uclass_priv) {
266 			ret = -ENOMEM;
267 			goto fail;
268 		}
269 	}
270 
271 	/* Ensure all parents are probed */
272 	if (dev->parent) {
273 		size = dev->parent->driver->per_child_auto_alloc_size;
274 		if (size) {
275 			dev->parent_priv = calloc(1, size);
276 			if (!dev->parent_priv) {
277 				ret = -ENOMEM;
278 				goto fail;
279 			}
280 		}
281 
282 		ret = device_probe(dev->parent);
283 		if (ret)
284 			goto fail;
285 	}
286 
287 	seq = uclass_resolve_seq(dev);
288 	if (seq < 0) {
289 		ret = seq;
290 		goto fail;
291 	}
292 	dev->seq = seq;
293 
294 	if (drv->ofdata_to_platdata && dev->of_offset >= 0) {
295 		ret = drv->ofdata_to_platdata(dev);
296 		if (ret)
297 			goto fail;
298 	}
299 
300 	if (drv->probe) {
301 		ret = drv->probe(dev);
302 		if (ret)
303 			goto fail;
304 	}
305 
306 	dev->flags |= DM_FLAG_ACTIVATED;
307 
308 	ret = uclass_post_probe_device(dev);
309 	if (ret) {
310 		dev->flags &= ~DM_FLAG_ACTIVATED;
311 		goto fail_uclass;
312 	}
313 
314 	return 0;
315 fail_uclass:
316 	if (device_remove(dev)) {
317 		dm_warn("%s: Device '%s' failed to remove on error path\n",
318 			__func__, dev->name);
319 	}
320 fail:
321 	dev->seq = -1;
322 	device_free(dev);
323 
324 	return ret;
325 }
326 
327 int device_remove(struct udevice *dev)
328 {
329 	struct driver *drv;
330 	int ret;
331 
332 	if (!dev)
333 		return -EINVAL;
334 
335 	if (!(dev->flags & DM_FLAG_ACTIVATED))
336 		return 0;
337 
338 	drv = dev->driver;
339 	assert(drv);
340 
341 	ret = uclass_pre_remove_device(dev);
342 	if (ret)
343 		return ret;
344 
345 	ret = device_chld_remove(dev);
346 	if (ret)
347 		goto err;
348 
349 	if (drv->remove) {
350 		ret = drv->remove(dev);
351 		if (ret)
352 			goto err_remove;
353 	}
354 
355 	device_free(dev);
356 
357 	dev->seq = -1;
358 	dev->flags &= ~DM_FLAG_ACTIVATED;
359 
360 	return 0;
361 
362 err_remove:
363 	/* We can't put the children back */
364 	dm_warn("%s: Device '%s' failed to remove, but children are gone\n",
365 		__func__, dev->name);
366 err:
367 	ret = uclass_post_probe_device(dev);
368 	if (ret) {
369 		dm_warn("%s: Device '%s' failed to post_probe on error path\n",
370 			__func__, dev->name);
371 	}
372 
373 	return ret;
374 }
375 
376 void *dev_get_platdata(struct udevice *dev)
377 {
378 	if (!dev) {
379 		dm_warn("%s: null device", __func__);
380 		return NULL;
381 	}
382 
383 	return dev->platdata;
384 }
385 
386 void *dev_get_priv(struct udevice *dev)
387 {
388 	if (!dev) {
389 		dm_warn("%s: null device", __func__);
390 		return NULL;
391 	}
392 
393 	return dev->priv;
394 }
395 
396 void *dev_get_parentdata(struct udevice *dev)
397 {
398 	if (!dev) {
399 		dm_warn("%s: null device", __func__);
400 		return NULL;
401 	}
402 
403 	return dev->parent_priv;
404 }
405 
406 static int device_get_device_tail(struct udevice *dev, int ret,
407 				  struct udevice **devp)
408 {
409 	if (ret)
410 		return ret;
411 
412 	ret = device_probe(dev);
413 	if (ret)
414 		return ret;
415 
416 	*devp = dev;
417 
418 	return 0;
419 }
420 
421 int device_get_child(struct udevice *parent, int index, struct udevice **devp)
422 {
423 	struct udevice *dev;
424 
425 	list_for_each_entry(dev, &parent->child_head, sibling_node) {
426 		if (!index--)
427 			return device_get_device_tail(dev, 0, devp);
428 	}
429 
430 	return -ENODEV;
431 }
432 
433 int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq,
434 			     bool find_req_seq, struct udevice **devp)
435 {
436 	struct udevice *dev;
437 
438 	*devp = NULL;
439 	if (seq_or_req_seq == -1)
440 		return -ENODEV;
441 
442 	list_for_each_entry(dev, &parent->child_head, sibling_node) {
443 		if ((find_req_seq ? dev->req_seq : dev->seq) ==
444 				seq_or_req_seq) {
445 			*devp = dev;
446 			return 0;
447 		}
448 	}
449 
450 	return -ENODEV;
451 }
452 
453 int device_get_child_by_seq(struct udevice *parent, int seq,
454 			    struct udevice **devp)
455 {
456 	struct udevice *dev;
457 	int ret;
458 
459 	*devp = NULL;
460 	ret = device_find_child_by_seq(parent, seq, false, &dev);
461 	if (ret == -ENODEV) {
462 		/*
463 		 * We didn't find it in probed devices. See if there is one
464 		 * that will request this seq if probed.
465 		 */
466 		ret = device_find_child_by_seq(parent, seq, true, &dev);
467 	}
468 	return device_get_device_tail(dev, ret, devp);
469 }
470 
471 int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
472 				   struct udevice **devp)
473 {
474 	struct udevice *dev;
475 
476 	*devp = NULL;
477 
478 	list_for_each_entry(dev, &parent->child_head, sibling_node) {
479 		if (dev->of_offset == of_offset) {
480 			*devp = dev;
481 			return 0;
482 		}
483 	}
484 
485 	return -ENODEV;
486 }
487 
488 int device_get_child_by_of_offset(struct udevice *parent, int seq,
489 				  struct udevice **devp)
490 {
491 	struct udevice *dev;
492 	int ret;
493 
494 	*devp = NULL;
495 	ret = device_find_child_by_of_offset(parent, seq, &dev);
496 	return device_get_device_tail(dev, ret, devp);
497 }
498