From patchwork Thu Mar 8 13:30:07 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 7169 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id B5A7A23E64 for ; Thu, 8 Mar 2012 13:30:37 +0000 (UTC) Received: from mail-iy0-f180.google.com (mail-iy0-f180.google.com [209.85.210.180]) by fiordland.canonical.com (Postfix) with ESMTP id 5AD74A18568 for ; Thu, 8 Mar 2012 13:30:37 +0000 (UTC) Received: by iage36 with SMTP id e36so930711iag.11 for ; Thu, 08 Mar 2012 05:30:36 -0800 (PST) Received: by 10.50.197.135 with SMTP id iu7mr6740484igc.50.1331213436682; Thu, 08 Mar 2012 05:30:36 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.231.53.18 with SMTP id k18csp9508ibg; Thu, 8 Mar 2012 05:30:35 -0800 (PST) Received: by 10.213.32.78 with SMTP id b14mr1256483ebd.151.1331213434658; Thu, 08 Mar 2012 05:30:34 -0800 (PST) Received: from eu1sys200aog107.obsmtp.com (eu1sys200aog107.obsmtp.com. [207.126.144.123]) by mx.google.com with SMTP id e16si1021883eeb.190.2012.03.08.05.30.30 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 08 Mar 2012 05:30:34 -0800 (PST) Received-SPF: neutral (google.com: 207.126.144.123 is neither permitted nor denied by best guess record for domain of linus.walleij@stericsson.com) client-ip=207.126.144.123; Authentication-Results: mx.google.com; spf=neutral (google.com: 207.126.144.123 is neither permitted nor denied by best guess record for domain of linus.walleij@stericsson.com) smtp.mail=linus.walleij@stericsson.com Received: from beta.dmz-us.st.com ([167.4.1.35]) (using TLSv1) by eu1sys200aob107.postini.com ([207.126.147.11]) with SMTP ID DSNKT1i0dUdnIN4UxTZrW7LBXYFhLPFRvx5t@postini.com; Thu, 08 Mar 2012 13:30:34 UTC Received: from zeta.dmz-us.st.com (ns4.st.com [167.4.16.71]) by beta.dmz-us.st.com (STMicroelectronics) with ESMTP id 4DC50E5; Thu, 8 Mar 2012 13:30:05 +0000 (GMT) Received: from relay2.stm.gmessaging.net (unknown [10.230.100.18]) by zeta.dmz-us.st.com (STMicroelectronics) with ESMTP id 4FC3949; Thu, 8 Mar 2012 11:56:27 +0000 (GMT) Received: from exdcvycastm004.EQ1STM.local (alteon-source-exch [10.230.100.61]) (using TLSv1 with cipher RC4-MD5 (128/128 bits)) (Client CN "exdcvycastm004", Issuer "exdcvycastm004" (not verified)) by relay2.stm.gmessaging.net (Postfix) with ESMTPS id C858EA8081; Thu, 8 Mar 2012 14:30:11 +0100 (CET) Received: from steludxu4075.lud.stericsson.com (10.230.100.153) by smtp.stericsson.com (10.230.100.2) with Microsoft SMTP Server (TLS) id 8.3.83.0; Thu, 8 Mar 2012 14:30:16 +0100 From: Linus Walleij To: Ben Dooks , Cc: Jonas Aaberg , Magnus Damm , "Rafael J. Wysocki" , Mark Brown , Linus Walleij Subject: [PATCH RESEND] i2c/nomadik: runtime PM support Date: Thu, 8 Mar 2012 14:30:07 +0100 Message-ID: <1331213407-10135-1-git-send-email-linus.walleij@stericsson.com> X-Mailer: git-send-email 1.7.8 MIME-Version: 1.0 X-Gm-Message-State: ALoCoQnUWdGOkvHCYjqsmhj3z60hzkzimtAUxHgOVcCfYIm+5i8C8PzcSUPWE2fsw5WLnFGXWUk6 From: Jonas Aaberg Turn off the clock and regulator to the I2C block using runtime PM. Cc: Magnus Damm Cc: Rafael J. Wysocki Cc: Mark Brown Signed-off-by: Jonas Aaberg Signed-off-by: Linus Walleij --- So I'm resending this, after discussion with Mark Brown and others I can only conclude that the question of whether to handle clocks and/or regulators centrally in say drivers/base/power/clock_ops.c or distributed in drivers is not simple to determine. When I discussed the matter with Mark I think we concluded that the approach for his systems will be to add calls in the drivers to begin with, then consolidate to the system-wide handlers when/if it makes sense. The key reason is that we have hardware blocks with different characteristics on the order to do things, whereas in some other systems (like shmobile I guess) every IP block shall be twisted the same way. We have a mixed legacy of ARM PrimeCells and IP blocks from different corners of the world and just cannot do it in one single way. ARM PrimeCells already have some centralized runtime PM callbacks. --- drivers/i2c/busses/i2c-nomadik.c | 53 ++++++++++++++++++++++++++++---------- 1 files changed, 39 insertions(+), 14 deletions(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 5267ab9..3c9803d 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -628,12 +628,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, dev->busy = true; - if (dev->regulator) - regulator_enable(dev->regulator); pm_runtime_get_sync(&dev->pdev->dev); - clk_enable(dev->clk); - status = init_hw(dev); if (status) goto out; @@ -666,10 +662,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, } out: - clk_disable(dev->clk); - pm_runtime_put_sync(&dev->pdev->dev); - if (dev->regulator) - regulator_disable(dev->regulator); + + pm_runtime_put(&dev->pdev->dev); dev->busy = false; @@ -859,9 +853,9 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg) #ifdef CONFIG_PM -static int nmk_i2c_suspend(struct device *dev) + +static int nmk_i2c_suspend(struct platform_device *pdev, pm_message_t state) { - struct platform_device *pdev = to_platform_device(dev); struct nmk_i2c_dev *nmk_i2c = platform_get_drvdata(pdev); if (nmk_i2c->busy) @@ -870,23 +864,53 @@ static int nmk_i2c_suspend(struct device *dev) return 0; } -static int nmk_i2c_resume(struct device *dev) +static int nmk_i2c_suspend_noirq(struct device *dev) { + struct nmk_i2c_dev *nmk_i2c = + platform_get_drvdata(to_platform_device(dev)); + + if (nmk_i2c->busy) + return -EBUSY; + return 0; } + #else #define nmk_i2c_suspend NULL -#define nmk_i2c_resume NULL +#define nmk_i2c_suspend_noirq NULL #endif +static int nmk_i2c_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct nmk_i2c_dev *nmk_i2c = platform_get_drvdata(pdev); + + clk_disable(nmk_i2c->clk); + if (nmk_i2c->regulator) + regulator_disable(nmk_i2c->regulator); + return 0; +} + +static int nmk_i2c_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct nmk_i2c_dev *nmk_i2c = platform_get_drvdata(pdev); + + if (nmk_i2c->regulator) + regulator_enable(nmk_i2c->regulator); + clk_enable(nmk_i2c->clk); + return 0; +} + /* * We use noirq so that we suspend late and resume before the wakeup interrupt * to ensure that we do the !pm_runtime_suspended() check in resume before * there has been a regular pm runtime resume (via pm_runtime_get_sync()). */ static const struct dev_pm_ops nmk_i2c_pm = { - .suspend_noirq = nmk_i2c_suspend, - .resume_noirq = nmk_i2c_resume, + SET_RUNTIME_PM_OPS(nmk_i2c_runtime_suspend, nmk_i2c_runtime_resume, + NULL) + .suspend_noirq = nmk_i2c_suspend_noirq, }; static unsigned int nmk_i2c_functionality(struct i2c_adapter *adap) @@ -1047,6 +1071,7 @@ static struct platform_driver nmk_i2c_driver = { }, .probe = nmk_i2c_probe, .remove = __devexit_p(nmk_i2c_remove), + .suspend = nmk_i2c_suspend, }; static int __init nmk_i2c_init(void)