[PATCH v1 1/3] pinctrl: qcom: lpass-lpi: Switch to PM clock framework for runtime PM

From: Ajay Kumar Nandam

Date: Mon Apr 13 2026 - 08:23:17 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 | 36 +++++++++++++------
drivers/pinctrl/qcom/pinctrl-lpass-lpi.h | 2 ++
.../pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c | 5 +++
3 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c
index 76aed3296..6d50e06ef 100644
--- a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c
+++ b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c
@@ -14,15 +14,16 @@

#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinconf.h>
+#include <linux/pm_runtime.h>
#include <linux/pinctrl/pinmux.h>

#include "../pinctrl-utils.h"

#include "pinctrl-lpass-lpi.h"
+#include <linux/pm_clock.h>

#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);
+ pm_runtime_enable(dev);

pctrl->desc.pctlops = &lpi_gpio_pinctrl_ops;
pctrl->desc.pmxops = &lpi_gpio_pinmux_ops;
@@ -539,20 +540,33 @@ 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;
}
EXPORT_SYMBOL_GPL(lpi_pinctrl_probe);

+int lpi_pinctrl_runtime_suspend(struct device *dev)
+{
+ return pm_clk_suspend(dev);
+}
+EXPORT_SYMBOL_GPL(lpi_pinctrl_runtime_suspend);
+
+int lpi_pinctrl_runtime_resume(struct device *dev)
+{
+ return pm_clk_resume(dev);
+}
+EXPORT_SYMBOL_GPL(lpi_pinctrl_runtime_resume);
+
void lpi_pinctrl_remove(struct platform_device *pdev)
{
struct lpi_pinctrl *pctrl = platform_get_drvdata(pdev);
int i;

+ pm_runtime_disable(pctrl->dev);
+
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-lpass-lpi.h b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.h
index f48368492..ae94ef48d 100644
--- a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.h
+++ b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.h
@@ -107,5 +107,7 @@ struct lpi_pinctrl_variant_data {

int lpi_pinctrl_probe(struct platform_device *pdev);
void lpi_pinctrl_remove(struct platform_device *pdev);
+int lpi_pinctrl_runtime_suspend(struct device *dev);
+int lpi_pinctrl_runtime_resume(struct device *dev);

#endif /*__PINCTRL_LPASS_LPI_H__*/
diff --git a/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c
index 750f41031..2d955643d 100644
--- a/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c
+++ b/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c
@@ -139,10 +139,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(lpi_pinctrl_runtime_suspend, lpi_pinctrl_runtime_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