From patchwork Fri Mar 14 14:53:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zoie Lin X-Patchwork-Id: 14017025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4250BC282EC for ; Fri, 14 Mar 2025 14:58:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Type: Content-Transfer-Encoding:MIME-Version:Message-ID:Date:Subject:CC:To:From: Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender :Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Owner; bh=3mTgXdjRhAbeq30ZDJ/sx04DyGkMzLexZXSrhYrxbCg=; b=ea2a0eHigjDATk8//1iqQgYEC/ ezHbW0gY7iTVandCXqWTOsv1QX4Q/EJgUuqW2yXIesTjPyrgTqHhOjFYZ9SLsdWf9tZBSzrGx2Jmt v6LHLRPAjM4BBWBEJqq274JjZ6lGn+XoYtru29un6BWblEqd9HcLnl+kUWTyUFE51hZww4TlepId0 UdEFU5e73M33Y3hmmEiMNyGSQRlKMKdfaWsojQlGPdKifBV+MUPFDzDXAheikxfnnsZgFC+37DA+U esOVuzXxv+HMoE74R6CJ6hJSvz2580EVOKJhDsnc2GySZjoceql95CGKaiTHI46pZAgkg7kt+fKsw jFJKN70g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tt6U0-0000000ETmi-0jid; Fri, 14 Mar 2025 14:57:56 +0000 Received: from mailgw01.mediatek.com ([216.200.240.184]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tt6Qe-0000000ET9d-1HlC; Fri, 14 Mar 2025 14:54:29 +0000 X-UUID: 378a5d1400e411f083f2a1c9db70dae0-20250314 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:Content-Transfer-Encoding:MIME-Version:Message-ID:Date:Subject:CC:To:From; bh=3mTgXdjRhAbeq30ZDJ/sx04DyGkMzLexZXSrhYrxbCg=; b=VpzaK7nwdRxS73ILbAswK0JFqwosNHJjJN3hEJX2xndhp1ZuYuS0aa4xBIS0EzVre64VJX2Gs3GiE1iQKBuRwodkC/nrqdlHEm0DFLV26io/pYILS1DfRkSGo7i9CcDPiXryV5Ns3j3v2AlMzfIqDGqsuA9+LKHbRizq5atp1EM=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.2.1,REQID:0c665353-3a6b-4b7c-a071-cb7659dcc8c3,IP:0,UR L:0,TC:0,Content:-25,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTION :release,TS:-25 X-CID-META: VersionHash:0ef645f,CLOUDID:022a59c6-16da-468a-87f7-8ca8d6b3b9f7,B ulkID:nil,BulkQuantity:0,Recheck:0,SF:102,TC:nil,Content:0|50,EDM:-3,IP:ni l,URL:0,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV:0,LES :1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0,ARC:0 X-CID-BVR: 0 X-CID-BAS: 0,_,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR X-UUID: 378a5d1400e411f083f2a1c9db70dae0-20250314 Received: from mtkmbs10n2.mediatek.inc [(172.21.101.183)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 2073565401; Fri, 14 Mar 2025 07:54:23 -0700 Received: from mtkmbs11n2.mediatek.inc (172.21.101.187) by MTKMBS09N2.mediatek.inc (172.21.101.94) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.28; Fri, 14 Mar 2025 22:54:20 +0800 Received: from mtksitap99.mediatek.inc (10.233.130.16) by mtkmbs11n2.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1258.28 via Frontend Transport; Fri, 14 Mar 2025 22:54:20 +0800 From: Zoie Lin To: Qii Wang , Andi Shyti , Matthias Brugger , AngeloGioacchino Del Regno CC: , , , , , , , , Zoie Lin Subject: [PATCH v5 1/1] i2c: mediatek: add runtime PM operations and bus regulator control Date: Fri, 14 Mar 2025 22:53:43 +0800 Message-ID: <20250314145407.2900190-1-zoie.lin@mediatek.com> X-Mailer: git-send-email 2.45.2 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250314_075428_350076_6043D590 X-CRM114-Status: GOOD ( 17.82 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Introduce support for runtime PM operations in the I2C driver, enabling runtime suspend and resume functionality. Although in most platforms, the bus power of i2c is 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 --- drivers/i2c/busses/i2c-mt65xx.c | 74 ++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 11 deletions(-) This series is based on linux-next, tag: next-20250314 Changes in v5: - Add pm runtime autosuspend setting to 250ms - Add error message for clock enable failure Changes in v4: - Removed unnecessary variable initialization. - Removed unnecessary brackets. - Corrected grammar issues in the commit message. - Confirmed autosuspend delay is not necessary. Changes in v3: - Removed the autosuspend functionality - Resumed the I2C bus in mtk_i2c_resume_noirq() Changes in v2: - Author name modification - Replacement of pm runtime API - Removal of redundant error messages - Return value adjustment - Add runtime pm status check diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index 5bd342047d59..a630733a8890 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -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_resume_and_get(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,38 @@ 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; + struct mtk_i2c *i2c = dev_get_drvdata(dev); + + if (i2c->adap.bus_regulator) { + ret = regulator_enable(i2c->adap.bus_regulator); + if (ret) { + dev_err(dev, "enable regulator failed!\n"); + return ret; + } + } + + ret = clk_bulk_enable(I2C_MT65XX_CLK_MAX, i2c->clocks); + if (ret) + if (i2c->adap.bus_regulator) + regulator_disable(i2c->adap.bus_regulator); + + return ret; +} + static int mtk_i2c_probe(struct platform_device *pdev) { int ret = 0; @@ -1472,13 +1507,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"); 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 +1527,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, 250); + 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 +1554,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); } @@ -1518,6 +1563,10 @@ static int mtk_i2c_suspend_noirq(struct device *dev) struct mtk_i2c *i2c = dev_get_drvdata(dev); i2c_mark_adapter_suspended(&i2c->adap); + + if (!pm_runtime_status_suspended(dev)) + mtk_i2c_runtime_suspend(dev); + clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); return 0; @@ -1536,7 +1585,8 @@ static int mtk_i2c_resume_noirq(struct device *dev) mtk_i2c_init_hw(i2c); - clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks); + if (pm_runtime_status_suspended(dev)) + mtk_i2c_runtime_resume(dev); i2c_mark_adapter_resumed(&i2c->adap); @@ -1546,6 +1596,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 = {