[PATCH v3 1/2] drivers: bus: simple-pm-bus: Add support for probing simple bus only devices

From: Saravana Kannan
Date: Fri Sep 03 2021 - 20:05:53 EST


fw_devlink could end up creating device links for bus only devices.
However, bus only devices don't get probed and can block probe() or
sync_state() [1] call backs of other devices. To avoid this, probe these
devices using the simple-pm-bus driver.

However, there are instances of devices that are not simple buses (they
get probed by their specific drivers) that also list the "simple-bus"
(or other bus only compatible strings) in their compatible property to
automatically populate their child devices. We still want these devices
to get probed by their specific drivers. So, we make sure this driver
only probes devices that are only buses.

[1] - https://lore.kernel.org/lkml/CAPDyKFo9Bxremkb1dDrr4OcXSpE0keVze94Cm=zrkOVxHHxBmQ@xxxxxxxxxxxxxx/
Signed-off-by: Saravana Kannan <saravanak@xxxxxxxxxx>
Tested-by: Saravana Kannan <saravanak@xxxxxxxxxx>
---
drivers/bus/simple-pm-bus.c | 32 +++++++++++++++++++++++++++++---
1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/bus/simple-pm-bus.c b/drivers/bus/simple-pm-bus.c
index 01a3d0cd08ed..3e086a9f34cb 100644
--- a/drivers/bus/simple-pm-bus.c
+++ b/drivers/bus/simple-pm-bus.c
@@ -13,11 +13,26 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>

-
static int simple_pm_bus_probe(struct platform_device *pdev)
{
- const struct of_dev_auxdata *lookup = dev_get_platdata(&pdev->dev);
- struct device_node *np = pdev->dev.of_node;
+ const struct device *dev = &pdev->dev;
+ const struct of_dev_auxdata *lookup = dev_get_platdata(dev);
+ struct device_node *np = dev->of_node;
+ const struct of_device_id *match;
+
+ match = of_match_device(dev->driver->of_match_table, dev);
+
+ /*
+ * These are transparent bus devices (not simple-pm-bus matches) that
+ * have their child nodes populated automatically. So, don't need to
+ * do anything more.
+ */
+ if (match && match->data) {
+ if (of_property_match_string(np, "compatible", match->compatible) == 0)
+ return 0;
+ else
+ return -ENODEV;
+ }

dev_dbg(&pdev->dev, "%s\n", __func__);

@@ -31,14 +46,25 @@ static int simple_pm_bus_probe(struct platform_device *pdev)

static int simple_pm_bus_remove(struct platform_device *pdev)
{
+ const void *data = of_device_get_match_data(&pdev->dev);
+
+ if (data)
+ return 0;
+
dev_dbg(&pdev->dev, "%s\n", __func__);

pm_runtime_disable(&pdev->dev);
return 0;
}

+#define ONLY_BUS ((void *) 1) /* Match if the device is only a bus. */
+
static const struct of_device_id simple_pm_bus_of_match[] = {
{ .compatible = "simple-pm-bus", },
+ { .compatible = "simple-bus", .data = ONLY_BUS },
+ { .compatible = "simple-mfd", .data = ONLY_BUS },
+ { .compatible = "isa", .data = ONLY_BUS },
+ { .compatible = "arm,amba-bus", .data = ONLY_BUS },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, simple_pm_bus_of_match);
--
2.33.0.153.gba50c8fa24-goog