[PATCH v9 3/4] bus: simple-pm-bus: Remove child devices when the bus is unbound
From: Herve Codina
Date: Mon Nov 09 2026 - 09:27:37 EST
During its probe, the simple-pm-bus driver (simple-pm-bus compatible
variant) populates its child devices but it doesn't touch them during
its removal.
This leads to bus child devices present and bound to drivers whereas the
bus itself is unbound.
Be consistent and remove child devices when the bus itself is unbound.
Signed-off-by: Herve Codina <herve.codina@xxxxxxxxxxx>
---
drivers/bus/simple-pm-bus.c | 45 +++++++++++++++++++++++++++++++++++--
1 file changed, 43 insertions(+), 2 deletions(-)
diff --git a/drivers/bus/simple-pm-bus.c b/drivers/bus/simple-pm-bus.c
index e45700156732..23ac18551fd9 100644
--- a/drivers/bus/simple-pm-bus.c
+++ b/drivers/bus/simple-pm-bus.c
@@ -22,6 +22,46 @@ struct simple_pm_bus {
int num_clks;
};
+static void simple_pm_bus_depopulate(void *data)
+{
+ struct device *dev = data;
+
+ /*
+ * Bus stays on for children
+ * This ensure that the bus will not be put in idle asynchronously when
+ * all its children are removed.
+ */
+ pm_runtime_get_sync(dev);
+
+ /* Let remove children */
+ of_platform_depopulate(dev);
+
+ /*
+ * Lets runtime_suspend() calls simple_pm_bus_runtime_suspend() in a
+ * synchronous way before disabling runtime pm.
+ *
+ * This guarantee that clocks are disabled and unprepared before the
+ * bus is removed in all cases.
+ */
+ pm_runtime_put_sync(dev);
+}
+
+static int simple_pm_bus_populate(struct device *dev,
+ const struct of_dev_auxdata *lookup)
+{
+ struct device_node *np = dev->of_node;
+ int ret;
+
+ if (!np)
+ return 0;
+
+ ret = of_platform_populate(np, NULL, lookup, dev);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(dev, simple_pm_bus_depopulate, dev);
+}
+
static int simple_pm_bus_probe(struct platform_device *pdev)
{
const struct device *dev = &pdev->dev;
@@ -71,8 +111,9 @@ static int simple_pm_bus_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(&pdev->dev, ret, "failed enable pm_runtime\n");
- if (np)
- of_platform_populate(np, NULL, lookup, &pdev->dev);
+ ret = simple_pm_bus_populate(&pdev->dev, lookup);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "failed to populate\n");
return 0;
}
--
2.56.0