1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2013 Google, Inc
6 * Pavel Herrmann <morpheus.ibis@gmail.com>
13 #include <dm/device.h>
14 #include <dm/device-internal.h>
16 #include <dm/uclass.h>
17 #include <dm/uclass-internal.h>
20 DECLARE_GLOBAL_DATA_PTR
;
22 struct uclass
*uclass_find(enum uclass_id key
)
29 * TODO(sjg@chromium.org): Optimise this, perhaps moving the found
30 * node to the start of the list, or creating a linear array mapping
33 list_for_each_entry(uc
, &gd
->uclass_root
, sibling_node
) {
34 if (uc
->uc_drv
->id
== key
)
42 * uclass_add() - Create new uclass in list
43 * @id: Id number to create
44 * @ucp: Returns pointer to uclass, or NULL on error
45 * @return 0 on success, -ve on error
47 * The new uclass is added to the list. There must be only one uclass for
50 static int uclass_add(enum uclass_id id
, struct uclass
**ucp
)
52 struct uclass_driver
*uc_drv
;
57 uc_drv
= lists_uclass_lookup(id
);
59 debug("Cannot find uclass for id %d: please add the UCLASS_DRIVER() declaration for this UCLASS_... id\n",
62 * Use a strange error to make this case easier to find. When
63 * a uclass is not available it can prevent driver model from
64 * starting up and this failure is otherwise hard to debug.
68 uc
= calloc(1, sizeof(*uc
));
71 if (uc_drv
->priv_auto_alloc_size
) {
72 uc
->priv
= calloc(1, uc_drv
->priv_auto_alloc_size
);
79 INIT_LIST_HEAD(&uc
->sibling_node
);
80 INIT_LIST_HEAD(&uc
->dev_head
);
81 list_add(&uc
->sibling_node
, &DM_UCLASS_ROOT_NON_CONST
);
84 ret
= uc_drv
->init(uc
);
93 if (uc_drv
->priv_auto_alloc_size
) {
97 list_del(&uc
->sibling_node
);
104 int uclass_destroy(struct uclass
*uc
)
106 struct uclass_driver
*uc_drv
;
111 * We cannot use list_for_each_entry_safe() here. If a device in this
112 * uclass has a child device also in this uclass, it will be also be
113 * unbound (by the recursion in the call to device_unbind() below).
114 * We can loop until the list is empty.
116 while (!list_empty(&uc
->dev_head
)) {
117 dev
= list_first_entry(&uc
->dev_head
, struct udevice
,
119 ret
= device_remove(dev
, DM_REMOVE_NORMAL
);
122 ret
= device_unbind(dev
);
130 list_del(&uc
->sibling_node
);
131 if (uc_drv
->priv_auto_alloc_size
)
138 int uclass_get(enum uclass_id id
, struct uclass
**ucp
)
143 uc
= uclass_find(id
);
145 return uclass_add(id
, ucp
);
151 const char *uclass_get_name(enum uclass_id id
)
155 if (uclass_get(id
, &uc
))
157 return uc
->uc_drv
->name
;
160 enum uclass_id
uclass_get_by_name(const char *name
)
164 for (i
= 0; i
< UCLASS_COUNT
; i
++) {
165 struct uclass_driver
*uc_drv
= lists_uclass_lookup(i
);
167 if (uc_drv
&& !strcmp(uc_drv
->name
, name
))
171 return UCLASS_INVALID
;
174 int dev_get_uclass_index(struct udevice
*dev
, struct uclass
**ucp
)
176 struct udevice
*iter
;
177 struct uclass
*uc
= dev
->uclass
;
180 if (list_empty(&uc
->dev_head
))
183 uclass_foreach_dev(iter
, uc
) {
195 int uclass_find_device(enum uclass_id id
, int index
, struct udevice
**devp
)
202 ret
= uclass_get(id
, &uc
);
205 if (list_empty(&uc
->dev_head
))
208 uclass_foreach_dev(dev
, uc
) {
218 int uclass_find_first_device(enum uclass_id id
, struct udevice
**devp
)
224 ret
= uclass_get(id
, &uc
);
227 if (list_empty(&uc
->dev_head
))
230 *devp
= list_first_entry(&uc
->dev_head
, struct udevice
, uclass_node
);
235 int uclass_find_next_device(struct udevice
**devp
)
237 struct udevice
*dev
= *devp
;
240 if (list_is_last(&dev
->uclass_node
, &dev
->uclass
->dev_head
))
243 *devp
= list_entry(dev
->uclass_node
.next
, struct udevice
, uclass_node
);
248 int uclass_find_device_by_name(enum uclass_id id
, const char *name
,
249 struct udevice
**devp
)
258 ret
= uclass_get(id
, &uc
);
262 uclass_foreach_dev(dev
, uc
) {
263 if (!strncmp(dev
->name
, name
, strlen(name
))) {
272 #if !CONFIG_IS_ENABLED(OF_CONTROL) || CONFIG_IS_ENABLED(OF_PLATDATA)
273 int uclass_find_next_free_req_seq(enum uclass_id id
)
280 ret
= uclass_get(id
, &uc
);
284 list_for_each_entry(dev
, &uc
->dev_head
, uclass_node
) {
285 if ((dev
->req_seq
!= -1) && (dev
->req_seq
> max
))
296 int uclass_find_device_by_seq(enum uclass_id id
, int seq_or_req_seq
,
297 bool find_req_seq
, struct udevice
**devp
)
304 debug("%s: %d %d\n", __func__
, find_req_seq
, seq_or_req_seq
);
305 if (seq_or_req_seq
== -1)
307 ret
= uclass_get(id
, &uc
);
311 uclass_foreach_dev(dev
, uc
) {
312 debug(" - %d %d '%s'\n", dev
->req_seq
, dev
->seq
, dev
->name
);
313 if ((find_req_seq
? dev
->req_seq
: dev
->seq
) ==
320 debug(" - not found\n");
325 int uclass_find_device_by_of_offset(enum uclass_id id
, int node
,
326 struct udevice
**devp
)
335 ret
= uclass_get(id
, &uc
);
339 uclass_foreach_dev(dev
, uc
) {
340 if (dev_of_offset(dev
) == node
) {
349 int uclass_find_device_by_ofnode(enum uclass_id id
, ofnode node
,
350 struct udevice
**devp
)
356 log(LOGC_DM
, LOGL_DEBUG
, "Looking for %s\n", ofnode_get_name(node
));
358 if (!ofnode_valid(node
))
360 ret
= uclass_get(id
, &uc
);
364 uclass_foreach_dev(dev
, uc
) {
365 log(LOGC_DM
, LOGL_DEBUG_CONTENT
, " - checking %s\n",
367 if (ofnode_equal(dev_ofnode(dev
), node
)) {
375 log(LOGC_DM
, LOGL_DEBUG
, " - result for %s: %s (ret=%d)\n",
376 ofnode_get_name(node
), *devp
? (*devp
)->name
: "(none)", ret
);
380 #if CONFIG_IS_ENABLED(OF_CONTROL)
381 int uclass_find_device_by_phandle(enum uclass_id id
, struct udevice
*parent
,
382 const char *name
, struct udevice
**devp
)
390 find_phandle
= dev_read_u32_default(parent
, name
, -1);
391 if (find_phandle
<= 0)
393 ret
= uclass_get(id
, &uc
);
397 uclass_foreach_dev(dev
, uc
) {
400 phandle
= dev_read_phandle(dev
);
402 if (phandle
== find_phandle
) {
412 int uclass_get_device_by_driver(enum uclass_id id
,
413 const struct driver
*find_drv
,
414 struct udevice
**devp
)
420 ret
= uclass_get(id
, &uc
);
424 uclass_foreach_dev(dev
, uc
) {
425 if (dev
->driver
== find_drv
)
426 return uclass_get_device_tail(dev
, 0, devp
);
432 int uclass_get_device_tail(struct udevice
*dev
, int ret
, struct udevice
**devp
)
438 ret
= device_probe(dev
);
447 int uclass_get_device(enum uclass_id id
, int index
, struct udevice
**devp
)
453 ret
= uclass_find_device(id
, index
, &dev
);
454 return uclass_get_device_tail(dev
, ret
, devp
);
457 int uclass_get_device_by_name(enum uclass_id id
, const char *name
,
458 struct udevice
**devp
)
464 ret
= uclass_find_device_by_name(id
, name
, &dev
);
465 return uclass_get_device_tail(dev
, ret
, devp
);
468 int uclass_get_device_by_seq(enum uclass_id id
, int seq
, struct udevice
**devp
)
474 ret
= uclass_find_device_by_seq(id
, seq
, false, &dev
);
475 if (ret
== -ENODEV
) {
477 * We didn't find it in probed devices. See if there is one
478 * that will request this seq if probed.
480 ret
= uclass_find_device_by_seq(id
, seq
, true, &dev
);
482 return uclass_get_device_tail(dev
, ret
, devp
);
485 int uclass_get_device_by_of_offset(enum uclass_id id
, int node
,
486 struct udevice
**devp
)
492 ret
= uclass_find_device_by_of_offset(id
, node
, &dev
);
493 return uclass_get_device_tail(dev
, ret
, devp
);
496 int uclass_get_device_by_ofnode(enum uclass_id id
, ofnode node
,
497 struct udevice
**devp
)
502 log(LOGC_DM
, LOGL_DEBUG
, "Looking for %s\n", ofnode_get_name(node
));
504 ret
= uclass_find_device_by_ofnode(id
, node
, &dev
);
505 log(LOGC_DM
, LOGL_DEBUG
, " - result for %s: %s (ret=%d)\n",
506 ofnode_get_name(node
), dev
? dev
->name
: "(none)", ret
);
508 return uclass_get_device_tail(dev
, ret
, devp
);
511 #if CONFIG_IS_ENABLED(OF_CONTROL)
512 int uclass_get_device_by_phandle_id(enum uclass_id id
, uint phandle_id
,
513 struct udevice
**devp
)
520 ret
= uclass_get(id
, &uc
);
524 uclass_foreach_dev(dev
, uc
) {
527 phandle
= dev_read_phandle(dev
);
529 if (phandle
== phandle_id
) {
531 return uclass_get_device_tail(dev
, ret
, devp
);
538 int uclass_get_device_by_phandle(enum uclass_id id
, struct udevice
*parent
,
539 const char *name
, struct udevice
**devp
)
545 ret
= uclass_find_device_by_phandle(id
, parent
, name
, &dev
);
546 return uclass_get_device_tail(dev
, ret
, devp
);
550 int uclass_first_device(enum uclass_id id
, struct udevice
**devp
)
556 ret
= uclass_find_first_device(id
, &dev
);
559 return uclass_get_device_tail(dev
, ret
, devp
);
562 int uclass_first_device_err(enum uclass_id id
, struct udevice
**devp
)
566 ret
= uclass_first_device(id
, devp
);
575 int uclass_next_device(struct udevice
**devp
)
577 struct udevice
*dev
= *devp
;
581 ret
= uclass_find_next_device(&dev
);
584 return uclass_get_device_tail(dev
, ret
, devp
);
587 int uclass_next_device_err(struct udevice
**devp
)
591 ret
= uclass_next_device(devp
);
600 int uclass_first_device_check(enum uclass_id id
, struct udevice
**devp
)
605 ret
= uclass_find_first_device(id
, devp
);
611 return device_probe(*devp
);
614 int uclass_next_device_check(struct udevice
**devp
)
618 ret
= uclass_find_next_device(devp
);
624 return device_probe(*devp
);
627 int uclass_bind_device(struct udevice
*dev
)
633 list_add_tail(&dev
->uclass_node
, &uc
->dev_head
);
636 struct uclass_driver
*uc_drv
= dev
->parent
->uclass
->uc_drv
;
638 if (uc_drv
->child_post_bind
) {
639 ret
= uc_drv
->child_post_bind(dev
);
647 /* There is no need to undo the parent's post_bind call */
648 list_del(&dev
->uclass_node
);
653 #if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
654 int uclass_unbind_device(struct udevice
*dev
)
660 if (uc
->uc_drv
->pre_unbind
) {
661 ret
= uc
->uc_drv
->pre_unbind(dev
);
666 list_del(&dev
->uclass_node
);
671 int uclass_resolve_seq(struct udevice
*dev
)
677 assert(dev
->seq
== -1);
678 ret
= uclass_find_device_by_seq(dev
->uclass
->uc_drv
->id
, dev
->req_seq
,
681 dm_warn("Device '%s': seq %d is in use by '%s'\n",
682 dev
->name
, dev
->req_seq
, dup
->name
);
683 } else if (ret
== -ENODEV
) {
684 /* Our requested sequence number is available */
685 if (dev
->req_seq
!= -1)
691 for (seq
= 0; seq
< DM_MAX_SEQ
; seq
++) {
692 ret
= uclass_find_device_by_seq(dev
->uclass
->uc_drv
->id
, seq
,
702 int uclass_pre_probe_device(struct udevice
*dev
)
704 struct uclass_driver
*uc_drv
;
707 uc_drv
= dev
->uclass
->uc_drv
;
708 if (uc_drv
->pre_probe
) {
709 ret
= uc_drv
->pre_probe(dev
);
716 uc_drv
= dev
->parent
->uclass
->uc_drv
;
717 if (uc_drv
->child_pre_probe
)
718 return uc_drv
->child_pre_probe(dev
);
723 int uclass_post_probe_device(struct udevice
*dev
)
725 struct uclass_driver
*uc_drv
;
729 uc_drv
= dev
->parent
->uclass
->uc_drv
;
730 if (uc_drv
->child_post_probe
) {
731 ret
= uc_drv
->child_post_probe(dev
);
737 uc_drv
= dev
->uclass
->uc_drv
;
738 if (uc_drv
->post_probe
)
739 return uc_drv
->post_probe(dev
);
744 #if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
745 int uclass_pre_remove_device(struct udevice
*dev
)
751 if (uc
->uc_drv
->pre_remove
) {
752 ret
= uc
->uc_drv
->pre_remove(dev
);
761 UCLASS_DRIVER(nop
) = {