[PATCH v2 1/3] pinctrl: qcom: lpass-lpi: Switch to PM clock framework for runtime PM
From: Ajay Kumar Nandam
Date: Mon Apr 20 2026 - 08:36:25 EST
Convert the LPASS LPI pinctrl driver to use the PM clock framework for
runtime power management.
This allows the LPASS LPI pinctrl driver to drop clock votes when idle,
improves power efficiency on platforms using LPASS LPI island mode, and
aligns the driver with common runtime PM patterns used across Qualcomm
LPASS subsystems.
Signed-off-by: Ajay Kumar Nandam <ajay.nandam@xxxxxxxxxxxxxxxx>
---
drivers/pinctrl/qcom/pinctrl-lpass-lpi.c | 22 +++++++++----------
.../pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c | 7 ++++++
2 files changed, 18 insertions(+), 11 deletions(-)
diff --git a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c
index 76aed3296279..2b0956ff2ae0 100644
--- a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c
+++ b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c
@@ -15,6 +15,8 @@
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinmux.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_runtime.h>
#include "../pinctrl-utils.h"
@@ -22,7 +24,6 @@
#define MAX_NR_GPIO 32
#define GPIO_FUNC 0
-#define MAX_LPI_NUM_CLKS 2
struct lpi_pinctrl {
struct device *dev;
@@ -31,7 +32,6 @@ struct lpi_pinctrl {
struct pinctrl_desc desc;
char __iomem *tlmm_base;
char __iomem *slew_base;
- struct clk_bulk_data clks[MAX_LPI_NUM_CLKS];
/* Protects from concurrent register updates */
struct mutex lock;
DECLARE_BITMAP(ever_gpio, MAX_NR_GPIO);
@@ -480,9 +480,6 @@ int lpi_pinctrl_probe(struct platform_device *pdev)
pctrl->data = data;
pctrl->dev = &pdev->dev;
- pctrl->clks[0].id = "core";
- pctrl->clks[1].id = "audio";
-
pctrl->tlmm_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pctrl->tlmm_base))
return dev_err_probe(dev, PTR_ERR(pctrl->tlmm_base),
@@ -495,13 +492,17 @@ int lpi_pinctrl_probe(struct platform_device *pdev)
"Slew resource not provided\n");
}
- ret = devm_clk_bulk_get_optional(dev, MAX_LPI_NUM_CLKS, pctrl->clks);
+ ret = devm_pm_clk_create(dev);
if (ret)
return ret;
- ret = clk_bulk_prepare_enable(MAX_LPI_NUM_CLKS, pctrl->clks);
- if (ret)
- return dev_err_probe(dev, ret, "Can't enable clocks\n");
+ ret = of_pm_clk_add_clks(dev);
+ if (ret < 0)
+ return ret;
+
+ pm_runtime_set_autosuspend_delay(dev, 100);
+ pm_runtime_use_autosuspend(dev);
+ devm_pm_runtime_enable(dev);
pctrl->desc.pctlops = &lpi_gpio_pinctrl_ops;
pctrl->desc.pmxops = &lpi_gpio_pinmux_ops;
@@ -539,8 +540,8 @@ int lpi_pinctrl_probe(struct platform_device *pdev)
return 0;
err_pinctrl:
+ pm_runtime_disable(dev);
mutex_destroy(&pctrl->lock);
- clk_bulk_disable_unprepare(MAX_LPI_NUM_CLKS, pctrl->clks);
return ret;
}
@@ -552,7 +553,6 @@ void lpi_pinctrl_remove(struct platform_device *pdev)
int i;
mutex_destroy(&pctrl->lock);
- clk_bulk_disable_unprepare(MAX_LPI_NUM_CLKS, pctrl->clks);
for (i = 0; i < pctrl->data->npins; i++)
pinctrl_generic_remove_group(pctrl->ctrl, i);
diff --git a/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c
index 750f410311a8..64a200dd8f41 100644
--- a/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c
+++ b/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c
@@ -7,6 +7,8 @@
#include <linux/gpio/driver.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_runtime.h>
#include "pinctrl-lpass-lpi.h"
@@ -139,10 +141,15 @@ static const struct of_device_id lpi_pinctrl_of_match[] = {
};
MODULE_DEVICE_TABLE(of, lpi_pinctrl_of_match);
+static const struct dev_pm_ops lpi_pinctrl_pm_ops = {
+ RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
+};
+
static struct platform_driver lpi_pinctrl_driver = {
.driver = {
.name = "qcom-sc7280-lpass-lpi-pinctrl",
.of_match_table = lpi_pinctrl_of_match,
+ .pm = pm_ptr(&lpi_pinctrl_pm_ops),
},
.probe = lpi_pinctrl_probe,
.remove = lpi_pinctrl_remove,
--
2.34.1