aboutsummaryrefslogtreecommitdiff
path: root/include/dm
diff options
context:
space:
mode:
authorMarek Vasut <marek.vasut@gmail.com>2021-01-24 14:32:46 -0700
committerSimon Glass <sjg@chromium.org>2021-02-03 03:38:41 -0700
commitcc6f4c8f2574472e359cb915811f6f93efdfcad4 (patch)
tree67b550a1af9bd00eb5fed3bc5d257eda641abcae /include/dm
parentc51d2e704a1c89d504b379b133bd552c3387fa6c (diff)
downloadu-boot-cc6f4c8f2574472e359cb915811f6f93efdfcad4.zip
u-boot-cc6f4c8f2574472e359cb915811f6f93efdfcad4.tar.gz
u-boot-cc6f4c8f2574472e359cb915811f6f93efdfcad4.tar.bz2
dm: core: Add late driver remove option
Add another flag to the DM core which could be assigned to drivers and which makes those drivers call their remove callbacks last, just before booting OS and after all the other drivers finished with their remove callbacks. This is necessary for things like clock drivers, where the other drivers might depend on the clock driver in their remove callbacks. Prime example is the mmc subsystem, which can reconfigure a card from HS mode to slower modes in the remove callback and for that it needs to reconfigure the controller clock. Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com> Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'include/dm')
-rw-r--r--include/dm/device-internal.h10
-rw-r--r--include/dm/device.h10
2 files changed, 16 insertions, 4 deletions
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
index b513b68..39406c3 100644
--- a/include/dm/device-internal.h
+++ b/include/dm/device-internal.h
@@ -123,7 +123,8 @@ int device_probe(struct udevice *dev);
*
* @dev: Pointer to device to remove
* @flags: Flags for selective device removal (DM_REMOVE_...)
- * @return 0 if OK, -EKEYREJECTED if not removed due to flags, other -ve on
+ * @return 0 if OK, -EKEYREJECTED if not removed due to flags, -EPROBE_DEFER if
+ * this is a vital device and flags is DM_REMOVE_NON_VITAL, other -ve on
* error (such an error here is normally a very bad thing)
*/
#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
@@ -178,12 +179,15 @@ static inline int device_chld_unbind(struct udevice *dev, struct driver *drv)
* This continues through all children recursively stopping part-way through if
* an error occurs. Return values of -EKEYREJECTED are ignored and processing
* continues, since they just indicate that the child did not elect to be
- * removed based on the value of @flags.
+ * removed based on the value of @flags. Return values of -EPROBE_DEFER cause
+ * processing of other children to continue, but the function will return
+ * -EPROBE_DEFER.
*
* @dev: The device whose children are to be removed
* @drv: The targeted driver
* @flags: Flag, if this functions is called in the pre-OS stage
- * @return 0 on success, -ve on error
+ * @return 0 on success, -EPROBE_DEFER if any child failed to remove, other
+ * -ve on error
*/
#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
int device_chld_remove(struct udevice *dev, struct driver *drv,
diff --git a/include/dm/device.h b/include/dm/device.h
index 204441f..28533ce 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -74,6 +74,13 @@ struct driver_info;
#define DM_FLAG_LEAVE_PD_ON (1 << 13)
/*
+ * Device is vital to the operation of other devices. It is possible to remove
+ * removed this device after all regular devices are removed. This is useful
+ * e.g. for clock, which need to be active during the device-removal phase.
+ */
+#define DM_FLAG_VITAL (1 << 14)
+
+/*
* One or multiple of these flags are passed to device_remove() so that
* a selective device removal as specified by the remove-stage and the
* driver flags can be done.
@@ -91,7 +98,8 @@ enum {
/* Remove devices which need some final OS preparation steps */
DM_REMOVE_OS_PREPARE = DM_FLAG_OS_PREPARE,
- /* Add more use cases here */
+ /* Remove only devices that are not marked vital */
+ DM_REMOVE_NON_VITAL = DM_FLAG_VITAL,
/* Remove devices with any active flag */
DM_REMOVE_ACTIVE_ALL = DM_REMOVE_ACTIVE_DMA | DM_REMOVE_OS_PREPARE,