From: zoie.lin <zoie.lin@mediatek.com>
To: Qii Wang <qii.wang@mediatek.com>,
Andi Shyti <andi.shyti@kernel.org>,
Matthias Brugger <matthias.bgg@gmail.com>,
AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com>
Cc: <Project_Global_Chrome_Upstream_Group@mediatek.com>,
<linux-i2c@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>,
<linux-mediatek@lists.infradead.org>,
zoie.lin <zoie.lin@mediatek.com>
Subject: [v1,1/1] i2c: mediatek: add runtime PM operations and bus regulator control
Date: Fri, 20 Sep 2024 22:36:27 +0800 [thread overview]
Message-ID: <20240920143627.23811-2-zoie.lin@mediatek.com> (raw)
In-Reply-To: <20240920143627.23811-1-zoie.lin@mediatek.com>
This commit introduces support for runtime PM operations in
the I2C driver, enabling runtime suspend and resume functionality.
Although in the most platforms, the bus power of i2c are always
on, some platforms disable the i2c bus power in order to meet
low power request.
This implementation includes bus regulator control to facilitate
proper handling of the bus power based on platform requirements.
Signed-off-by: zoie.lin <zoie.lin@mediatek.com>
---
drivers/i2c/busses/i2c-mt65xx.c | 72 ++++++++++++++++++++++++++++-----
1 file changed, 61 insertions(+), 11 deletions(-)
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index e0ba653dec2d..aae0189ba210 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -21,6 +21,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/scatterlist.h>
#include <linux/sched.h>
#include <linux/slab.h>
@@ -1245,8 +1246,8 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
int left_num = num;
struct mtk_i2c *i2c = i2c_get_adapdata(adap);
- ret = clk_bulk_enable(I2C_MT65XX_CLK_MAX, i2c->clocks);
- if (ret)
+ ret = pm_runtime_get_sync(i2c->dev);
+ if (ret < 0)
return ret;
i2c->auto_restart = i2c->dev_comp->auto_restart;
@@ -1299,7 +1300,9 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
ret = num;
err_exit:
- clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+ pm_runtime_mark_last_busy(i2c->dev);
+ pm_runtime_put_autosuspend(i2c->dev);
+
return ret;
}
@@ -1370,6 +1373,41 @@ static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c)
return 0;
}
+static int mtk_i2c_runtime_suspend(struct device *dev)
+{
+ struct mtk_i2c *i2c = dev_get_drvdata(dev);
+
+ clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+ if (i2c->adap.bus_regulator)
+ regulator_disable(i2c->adap.bus_regulator);
+
+ return 0;
+}
+
+static int mtk_i2c_runtime_resume(struct device *dev)
+{
+ int ret = 0;
+ struct mtk_i2c *i2c = dev_get_drvdata(dev);
+
+ if (i2c->adap.bus_regulator) {
+ ret = regulator_enable(i2c->adap.bus_regulator);
+ if (ret < 0) {
+ dev_err(dev, "enable regulator failed!\n");
+ return ret;
+ }
+ }
+
+ ret = clk_bulk_enable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+ if (ret < 0) {
+ dev_err(dev, "clock enable failed!\n");
+ if (i2c->adap.bus_regulator)
+ regulator_disable(i2c->adap.bus_regulator);
+ return ret;
+ }
+
+ return ret;
+}
+
static int mtk_i2c_probe(struct platform_device *pdev)
{
int ret = 0;
@@ -1472,13 +1510,19 @@ static int mtk_i2c_probe(struct platform_device *pdev)
}
}
- ret = clk_bulk_prepare_enable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+ ret = clk_bulk_prepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
if (ret) {
- dev_err(&pdev->dev, "clock enable failed!\n");
+ dev_err(&pdev->dev, "clk_bulk_prepare failed\n");
return ret;
}
+
+ platform_set_drvdata(pdev, i2c);
+
+ ret = mtk_i2c_runtime_resume(i2c->dev);
+ if (ret < 0)
+ goto err_clk_bulk_unprepare;
mtk_i2c_init_hw(i2c);
- clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks);
+ mtk_i2c_runtime_suspend(i2c->dev);
ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq,
IRQF_NO_SUSPEND | IRQF_TRIGGER_NONE,
@@ -1486,19 +1530,22 @@ static int mtk_i2c_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(&pdev->dev,
"Request I2C IRQ %d fail\n", irq);
- goto err_bulk_unprepare;
+ goto err_clk_bulk_unprepare;
}
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
i2c_set_adapdata(&i2c->adap, i2c);
ret = i2c_add_adapter(&i2c->adap);
if (ret)
- goto err_bulk_unprepare;
-
- platform_set_drvdata(pdev, i2c);
+ goto err_pm_runtime_disable;
return 0;
-err_bulk_unprepare:
+err_pm_runtime_disable:
+ pm_runtime_disable(&pdev->dev);
+err_clk_bulk_unprepare:
clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
return ret;
@@ -1510,6 +1557,7 @@ static void mtk_i2c_remove(struct platform_device *pdev)
i2c_del_adapter(&i2c->adap);
+ pm_runtime_disable(&pdev->dev);
clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks);
}
@@ -1546,6 +1594,8 @@ static int mtk_i2c_resume_noirq(struct device *dev)
static const struct dev_pm_ops mtk_i2c_pm = {
NOIRQ_SYSTEM_SLEEP_PM_OPS(mtk_i2c_suspend_noirq,
mtk_i2c_resume_noirq)
+ SET_RUNTIME_PM_OPS(mtk_i2c_runtime_suspend, mtk_i2c_runtime_resume,
+ NULL)
};
static struct platform_driver mtk_i2c_driver = {
--
2.45.2
next prev parent reply other threads:[~2024-09-20 14:36 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-09-20 14:36 [v1,0/1] i2c: mediatek: add runtime PM operations and bus regulator control zoie.lin
2024-09-20 14:36 ` zoie.lin [this message]
2024-09-24 8:39 ` [v1,1/1] " AngeloGioacchino Del Regno
2024-09-25 8:18 ` Andi Shyti
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240920143627.23811-2-zoie.lin@mediatek.com \
--to=zoie.lin@mediatek.com \
--cc=Project_Global_Chrome_Upstream_Group@mediatek.com \
--cc=andi.shyti@kernel.org \
--cc=angelogioacchino.delregno@collabora.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-i2c@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=matthias.bgg@gmail.com \
--cc=qii.wang@mediatek.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox