4 * Copyright (c) 2014 Google, Inc
7 * Pavel Herrmann <morpheus.ibis@gmail.com>
9 * SPDX-License-Identifier: GPL-2.0+
15 #include <dm/device.h>
16 #include <dm/device-internal.h>
17 #include <dm/uclass.h>
18 #include <dm/uclass-internal.h>
21 int device_unbind_children(struct udevice
*dev
)
23 struct udevice
*pos
, *n
;
24 int ret
, saved_ret
= 0;
28 list_for_each_entry_safe(pos
, n
, &dev
->child_head
, sibling_node
) {
29 ret
= device_unbind(pos
);
30 if (ret
&& !saved_ret
)
37 int device_remove_children(struct udevice
*dev
)
39 struct udevice
*pos
, *n
;
44 list_for_each_entry_safe(pos
, n
, &dev
->child_head
, sibling_node
) {
45 ret
= device_remove(pos
);
53 int device_unbind(struct udevice
*dev
)
55 const struct driver
*drv
;
61 if (dev
->flags
& DM_FLAG_ACTIVATED
)
64 if (!(dev
->flags
& DM_FLAG_BOUND
))
71 ret
= drv
->unbind(dev
);
76 ret
= device_unbind_children(dev
);
80 if (dev
->flags
& DM_FLAG_ALLOC_PDATA
) {
84 if (dev
->flags
& DM_FLAG_ALLOC_UCLASS_PDATA
) {
85 free(dev
->uclass_platdata
);
86 dev
->uclass_platdata
= NULL
;
88 if (dev
->flags
& DM_FLAG_ALLOC_PARENT_PDATA
) {
89 free(dev
->parent_platdata
);
90 dev
->parent_platdata
= NULL
;
92 ret
= uclass_unbind_device(dev
);
97 list_del(&dev
->sibling_node
);
99 devres_release_all(dev
);
107 * device_free() - Free memory buffers allocated by a device
108 * @dev: Device that is to be started
110 void device_free(struct udevice
*dev
)
114 if (dev
->driver
->priv_auto_alloc_size
) {
118 size
= dev
->uclass
->uc_drv
->per_device_auto_alloc_size
;
120 free(dev
->uclass_priv
);
121 dev
->uclass_priv
= NULL
;
124 size
= dev
->parent
->driver
->per_child_auto_alloc_size
;
126 size
= dev
->parent
->uclass
->uc_drv
->
127 per_child_auto_alloc_size
;
130 free(dev
->parent_priv
);
131 dev
->parent_priv
= NULL
;
135 devres_release_probe(dev
);
138 int device_remove(struct udevice
*dev
)
140 const struct driver
*drv
;
146 if (!(dev
->flags
& DM_FLAG_ACTIVATED
))
152 ret
= uclass_pre_remove_device(dev
);
156 ret
= device_remove_children(dev
);
161 ret
= drv
->remove(dev
);
166 if (dev
->parent
&& dev
->parent
->driver
->child_post_remove
) {
167 ret
= dev
->parent
->driver
->child_post_remove(dev
);
169 dm_warn("%s: Device '%s' failed child_post_remove()",
170 __func__
, dev
->name
);
177 dev
->flags
&= ~DM_FLAG_ACTIVATED
;
182 /* We can't put the children back */
183 dm_warn("%s: Device '%s' failed to remove, but children are gone\n",
184 __func__
, dev
->name
);
186 ret
= uclass_post_probe_device(dev
);
188 dm_warn("%s: Device '%s' failed to post_probe on error path\n",
189 __func__
, dev
->name
);