From patchwork Fri Sep 20 14:36:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?Wm9pZSBMaW4gKOael+emueWmoSk=?= X-Patchwork-Id: 13808555 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 3CF62C78853 for ; Fri, 20 Sep 2024 14:39:23 +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:MIME-Version: References:In-Reply-To:Message-ID:Date:Subject:CC:To:From:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=djf1UONhf6mmcgtWmOvFlBs8ovmE1gdcWLKGsW8YciE=; b=xmMZIdc2NkAE4VTtQSZbtm+F6o yupgQ6LL8J7deXdNebggUm/B+BLyOvVSRJwoDEnZIEeaLWMeimyqknfxw6Z86HOHPpiT3biQSfoq6 MoCM49IRwltN2+z3RBVMbUrSzfYTrsl++IpYR2oJ90ztRQndWm1StHM63lHknP4G6CSJdvqSFvzxv fOj+kRhHwYp1hNXUO3vCffmCYL/x3r/a1UILNBbu078e0TDiiFrB1rVOdmFENonCvj7iGsnF6HRth 9K02kZot0dhf8zn9FGqMXR/B2MDWZMjbN3JjBklY9+kNdWQ1ygdCAkZ5kFUfcH8j6nr7K+7C6VJOY jnxJS9Zw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1sremw-0000000CP8N-06D7; Fri, 20 Sep 2024 14:39:14 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1srekj-0000000COnE-3Mg3; Fri, 20 Sep 2024 14:36:59 +0000 X-UUID: c7af1f4e775d11efba0aef63c0775dbf-20240920 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=djf1UONhf6mmcgtWmOvFlBs8ovmE1gdcWLKGsW8YciE=; b=Xjtr3ez5iZAnWNL8OEQPYC3WZbPWAxygCXhxWTF84ZilglpUtgddXBihko9mTx+rJIsWUpfjTdX5dox/qVenIayjeVI8EKF4bOt0+aEQ6o0qNkdL8+5BnTfZRYVGPp7EIAw9omZaFdy6wVaBqGj1ElTOCTHCEYNXYkpRH1kIuyw=; X-CID-CACHE: Type:Local,Time:202409200719-07,HitQuantity:1 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.41,REQID:9cafda02-8932-492a-813b-80a1ebedc426,IP:0,U RL:0,TC:0,Content:-25,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTIO N:release,TS:-25 X-CID-META: VersionHash:6dc6a47,CLOUDID:3b0883d0-7921-4900-88a1-3aef019a55ce,B ulkID:nil,BulkQuantity:0,Recheck:0,SF:102,TC:nil,Content:0,EDM:-3,IP:nil,U RL: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: c7af1f4e775d11efba0aef63c0775dbf-20240920 Received: from mtkmbs11n1.mediatek.inc [(172.21.101.185)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 796256231; Fri, 20 Sep 2024 07:36:53 -0700 Received: from mtkmbs13n2.mediatek.inc (172.21.101.108) by mtkmbs11n1.mediatek.inc (172.21.101.185) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Fri, 20 Sep 2024 22:36:51 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkmbs13n2.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Fri, 20 Sep 2024 22:36:51 +0800 From: zoie.lin To: Qii Wang , Andi Shyti , Matthias Brugger , AngeloGioacchino Del Regno CC: , , , , , zoie.lin Subject: [v1,1/1] i2c: mediatek: add runtime PM operations and bus regulator control Date: Fri, 20 Sep 2024 22:36:27 +0800 Message-ID: <20240920143627.23811-2-zoie.lin@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20240920143627.23811-1-zoie.lin@mediatek.com> References: <20240920143627.23811-1-zoie.lin@mediatek.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240920_073657_870989_7DE6005B X-CRM114-Status: GOOD ( 17.40 ) 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 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 --- 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 #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_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 = {