[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250108012846.3275443-5-swboyd@chromium.org>
Date: Tue, 7 Jan 2025 17:28:41 -0800
From: Stephen Boyd <swboyd@...omium.org>
To: Bjorn Andersson <andersson@...nel.org>,
Konrad Dybcio <konradybcio@...nel.org>
Cc: linux-kernel@...r.kernel.org,
patches@...ts.linux.dev,
devicetree@...r.kernel.org,
Dmitry Baryshkov <dmitry.baryshkov@...aro.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@...aro.org>,
Rob Herring <robh@...nel.org>,
linux-arm-msm@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org,
Arnd Bergmann <arnd@...db.de>,
Conor Dooley <conor+dt@...nel.org>,
Saravana Kannan <saravanak@...gle.com>,
Uwe Kleine-König <u.kleine-koenig@...libre.com>
Subject: [RFC PATCH 4/6] of: Extract alloc/add functions from of_platform_device_create_pdata()
Allow drivers to modify the 'struct device' for a device node by
splitting of_platform_device_create_pdata() into two functions. The
first function, of_platform_device_alloc(), allocates the platform
device and the second function, of_platform_device_add(), adds the
platform device to the platform bus. SoC power management drivers can
use these APIs to allocate a platform device for a node underneath the
soc node, attach pmdomains and/or set the device as runtime PM active,
and finally add the platform device to the platform bus.
Cc: Rob Herring <robh@...nel.org>
Cc: Saravana Kannan <saravanak@...gle.com>
Cc: <devicetree@...r.kernel.org>
Cc: Bjorn Andersson <andersson@...nel.org>
Cc: Konrad Dybcio <konradybcio@...nel.org>
Cc: <linux-arm-msm@...r.kernel.org>
Signed-off-by: Stephen Boyd <swboyd@...omium.org>
---
drivers/of/platform.c | 80 ++++++++++++++++++++++++++++++-------
include/linux/of_platform.h | 14 +++++++
2 files changed, 79 insertions(+), 15 deletions(-)
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 63a80c30d515..d8ee2d38a382 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -138,6 +138,66 @@ struct platform_device *of_device_alloc(struct device_node *np,
}
EXPORT_SYMBOL(of_device_alloc);
+/**
+ * of_platform_device_alloc - Alloc and initialize an of_device
+ * @np: pointer to node to create device for
+ * @bus_id: name to assign device
+ * @parent: Linux device model parent device.
+ *
+ * Return: Pointer to created platform device, or NULL if a device was not
+ * allocated. Unavailable devices will not get allocated.
+ */
+struct platform_device *
+of_platform_device_alloc(struct device_node *np, const char *bus_id,
+ struct device *parent)
+{
+ struct platform_device *ofdev;
+
+ pr_debug("alloc platform device: %pOF\n", np);
+
+ if (!of_device_is_available(np) ||
+ of_node_test_and_set_flag(np, OF_POPULATED))
+ return NULL;
+
+ ofdev = of_device_alloc(np, bus_id, parent);
+ if (!ofdev) {
+ of_node_clear_flag(np, OF_POPULATED);
+ return ofdev;
+ }
+
+ ofdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ if (!ofdev->dev.dma_mask)
+ ofdev->dev.dma_mask = &ofdev->dev.coherent_dma_mask;
+ ofdev->dev.bus = &platform_bus_type;
+ of_msi_configure(&ofdev->dev, ofdev->dev.of_node);
+
+ return ofdev;
+}
+EXPORT_SYMBOL(of_platform_device_alloc);
+
+/**
+ * of_platform_device_add - Add an of_device to the platform bus
+ * @ofdev: of_device to add
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int of_platform_device_add(struct platform_device *ofdev)
+{
+ struct device_node *np = ofdev->dev.of_node;
+ int ret;
+
+ pr_debug("adding platform device: %pOF\n", np);
+
+ ret = of_device_add(ofdev);
+ if (ret) {
+ platform_device_put(ofdev);
+ of_node_clear_flag(np, OF_POPULATED);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(of_platform_device_add);
+
/**
* of_platform_device_create_pdata - Alloc, initialize and register an of_device
* @np: pointer to node to create device for
@@ -154,29 +214,19 @@ static struct platform_device *of_platform_device_create_pdata(
void *platform_data,
struct device *parent)
{
+ int ret;
struct platform_device *dev;
pr_debug("create platform device: %pOF\n", np);
- if (!of_device_is_available(np) ||
- of_node_test_and_set_flag(np, OF_POPULATED))
+ dev = of_platform_device_alloc(np, bus_id, parent);
+ if (!dev)
return NULL;
- dev = of_device_alloc(np, bus_id, parent);
- if (!dev)
- goto err_clear_flag;
-
- dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
- if (!dev->dev.dma_mask)
- dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
- dev->dev.bus = &platform_bus_type;
dev->dev.platform_data = platform_data;
- of_msi_configure(&dev->dev, dev->dev.of_node);
-
- if (of_device_add(dev) != 0) {
- platform_device_put(dev);
+ ret = of_platform_device_add(dev);
+ if (ret)
goto err_clear_flag;
- }
return dev;
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index 17471ef8e092..e55c1371b560 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -71,6 +71,10 @@ extern int of_platform_bus_probe(struct device_node *root,
#ifdef CONFIG_OF_ADDRESS
/* Platform devices and busses creation */
+extern struct platform_device *of_platform_device_alloc(struct device_node *np,
+ const char *bus_id,
+ struct device *parent);
+extern int of_platform_device_add(struct platform_device *ofdev);
extern struct platform_device *of_platform_device_create(struct device_node *np,
const char *bus_id,
struct device *parent);
@@ -91,6 +95,16 @@ extern int devm_of_platform_populate(struct device *dev);
extern void devm_of_platform_depopulate(struct device *dev);
#else
/* Platform devices and busses creation */
+static inline struct platform_device *of_platform_device_alloc(struct device_node *np,
+ const char *bus_id,
+ struct device *parent)
+{
+ return NULL;
+}
+static inline int of_platform_device_add(struct platform_device *ofdev)
+{
+ return -ENODEV;
+}
static inline struct platform_device *of_platform_device_create(struct device_node *np,
const char *bus_id,
struct device *parent)
--
https://chromeos.dev
Powered by blists - more mailing lists