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