From patchwork Mon Feb 17 15:20:41 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 24776 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pb0-f71.google.com (mail-pb0-f71.google.com [209.85.160.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 7EE4820143 for ; Mon, 17 Feb 2014 15:20:49 +0000 (UTC) Received: by mail-pb0-f71.google.com with SMTP id jt11sf35688536pbb.6 for ; Mon, 17 Feb 2014 07:20:48 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:x-original-sender:x-original-authentication-results :precedence:mailing-list:list-id:list-post:list-help:list-archive :list-unsubscribe; bh=bQVwiD4bPEvoBY2g+Cwn4ntGfDITKVuZP74LOG/MrN8=; b=cWd9nketxJblH3x1SFiP6tnTAWQxmviua74VpwpiNRSRHo+Niy2E/iCVrWuFD0hNDb 9cuOeC+gDoQDiUpwvqrTotMjiz2aWUj2yHAQXN+EiKlLJ9pMvBOM4b/wHRiKF2j1W5cN ItZHelH5hBPzsItNCPgTV4dWENLyNRHoKSG16iqGj61wb6N+2bIDhnwdtFbk0p21sZDt asDKuQ1I5lNNtB5r8ZgwkiR5UXa2yGPWFfG8KJ74MFV+kKaWqKjXO+BDZl7tE7+fe7hx eSAKp7qPCcj9hUykU+234Yp2xr42dRzkcgwBhzxR3HFsssnACts3Po6iquOJ5K++bStj gp1A== X-Gm-Message-State: ALoCoQn4mhucj1mNUJAdwWwK8FGwa0HPa5l24luQMvTyjnVZhuWU6owm2ymKF+NznFCVUCUJJl2U X-Received: by 10.66.172.103 with SMTP id bb7mr10571048pac.44.1392650448557; Mon, 17 Feb 2014 07:20:48 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.107.228 with SMTP id h91ls935145qgf.76.gmail; Mon, 17 Feb 2014 07:20:48 -0800 (PST) X-Received: by 10.221.34.211 with SMTP id st19mr17483488vcb.5.1392650448414; Mon, 17 Feb 2014 07:20:48 -0800 (PST) Received: from mail-ve0-f172.google.com (mail-ve0-f172.google.com [209.85.128.172]) by mx.google.com with ESMTPS id b7si4535909vej.70.2014.02.17.07.20.48 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 17 Feb 2014 07:20:48 -0800 (PST) Received-SPF: neutral (google.com: 209.85.128.172 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.172; Received: by mail-ve0-f172.google.com with SMTP id c14so12413595vea.3 for ; Mon, 17 Feb 2014 07:20:48 -0800 (PST) X-Received: by 10.52.185.196 with SMTP id fe4mr11130218vdc.27.1392650448308; Mon, 17 Feb 2014 07:20:48 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp146471vcz; Mon, 17 Feb 2014 07:20:47 -0800 (PST) X-Received: by 10.112.200.201 with SMTP id ju9mr82857lbc.76.1392650446751; Mon, 17 Feb 2014 07:20:46 -0800 (PST) Received: from mail-lb0-f172.google.com (mail-lb0-f172.google.com [209.85.217.172]) by mx.google.com with ESMTPS id b5si25684895lbp.43.2014.02.17.07.20.46 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 17 Feb 2014 07:20:46 -0800 (PST) Received-SPF: neutral (google.com: 209.85.217.172 is neither permitted nor denied by best guess record for domain of ulf.hansson@linaro.org) client-ip=209.85.217.172; Received: by mail-lb0-f172.google.com with SMTP id c11so11475146lbj.31 for ; Mon, 17 Feb 2014 07:20:46 -0800 (PST) X-Received: by 10.112.142.100 with SMTP id rv4mr14595lbb.78.1392650446075; Mon, 17 Feb 2014 07:20:46 -0800 (PST) Received: from linaro-ulf.lan (90-231-160-185-no158.tbcn.telia.com. [90.231.160.185]) by mx.google.com with ESMTPSA id e1sm26240692laa.8.2014.02.17.07.20.44 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 17 Feb 2014 07:20:45 -0800 (PST) From: Ulf Hansson To: Alessandro Rubini , Linus Walleij , Wolfram Sang , linux-i2c@vger.kernel.org Cc: Russell King , linux-arm-kernel@lists.infradead.org, Mark Brown , Ulf Hansson Subject: [PATCH V3 14/17] i2c: nomadik: Fixup deployment of runtime PM Date: Mon, 17 Feb 2014 16:20:41 +0100 Message-Id: <1392650441-14890-1-git-send-email-ulf.hansson@linaro.org> X-Mailer: git-send-email 1.7.9.5 X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: ulf.hansson@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.172 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Since the runtime PM state is expected to be active according to the amba bus, we must align our behaviour while probing to it. Moreover, this is needed to be able to have the driver fully functional without depending on CONFIG_RUNTIME_PM. Since the device is active while a successful probe has been completed, the reference counting for the clock will be screwed up and never reach zero. We resolve this by implementing runtime PM callbacks and let them handle the resources accordingly, including the clock. Cc: Alessandro Rubini Cc: Linus Walleij Cc: Wolfram Sang Signed-off-by: Ulf Hansson --- drivers/i2c/busses/i2c-nomadik.c | 77 +++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 5fdfc97..3e08ba1 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -666,7 +666,7 @@ static int nmk_i2c_xfer_one(struct nmk_i2c_dev *dev, u16 flags) static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num_msgs) { - int status; + int status = 0; int i; struct nmk_i2c_dev *dev = i2c_get_adapdata(i2c_adap); int j; @@ -675,19 +675,6 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, pm_runtime_get_sync(&dev->adev->dev); - status = clk_prepare_enable(dev->clk); - if (status) { - dev_err(&dev->adev->dev, "can't prepare_enable clock\n"); - goto out_clk; - } - - /* Optionaly enable pins to be muxed in and configured */ - pinctrl_pm_select_default_state(&dev->adev->dev); - - status = init_hw(dev); - if (status) - goto out; - /* Attempt three times to send the message queue */ for (j = 0; j < 3; j++) { /* setup the i2c controller */ @@ -708,12 +695,6 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, break; } -out: - clk_disable_unprepare(dev->clk); -out_clk: - /* Optionally let pins go into idle state */ - pinctrl_pm_select_idle_state(&dev->adev->dev); - pm_runtime_put_sync(&dev->adev->dev); dev->busy = false; @@ -930,6 +911,41 @@ static int nmk_i2c_resume(struct device *dev) #define nmk_i2c_resume NULL #endif +#if CONFIG_PM +static int nmk_i2c_runtime_suspend(struct device *dev) +{ + struct amba_device *adev = to_amba_device(dev); + struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev); + + clk_disable_unprepare(nmk_i2c->clk); + pinctrl_pm_select_idle_state(dev); + return 0; +} + +static int nmk_i2c_runtime_resume(struct device *dev) +{ + struct amba_device *adev = to_amba_device(dev); + struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev); + int ret; + + ret = clk_prepare_enable(nmk_i2c->clk); + if (ret) { + dev_err(dev, "can't prepare_enable clock\n"); + return ret; + } + + pinctrl_pm_select_default_state(dev); + + ret = init_hw(nmk_i2c); + if (ret) { + clk_disable_unprepare(nmk_i2c->clk); + pinctrl_pm_select_idle_state(dev); + } + + return ret; +} +#endif + /* * 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 @@ -938,6 +954,9 @@ static int nmk_i2c_resume(struct device *dev) static const struct dev_pm_ops nmk_i2c_pm = { .suspend_noirq = nmk_i2c_suspend, .resume_noirq = nmk_i2c_resume, + SET_PM_RUNTIME_PM_OPS(nmk_i2c_runtime_suspend, + nmk_i2c_runtime_resume, + NULL) }; static unsigned int nmk_i2c_functionality(struct i2c_adapter *adap) @@ -1006,11 +1025,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) amba_set_drvdata(adev, dev); - /* Select default pin state */ - pinctrl_pm_select_default_state(&adev->dev); - /* If possible, let's go to idle until the first transfer */ - pinctrl_pm_select_idle_state(&adev->dev); - dev->virtbase = devm_ioremap(&adev->dev, adev->res.start, resource_size(&adev->res)); if (IS_ERR(dev->virtbase)) { @@ -1035,6 +1049,14 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) goto err_no_mem; } + ret = clk_prepare_enable(dev->clk); + if (ret) { + dev_err(&adev->dev, "can't prepare_enable clock\n"); + goto err_no_mem; + } + + init_hw(dev); + adap = &dev->adap; adap->dev.of_node = np; adap->dev.parent = &adev->dev; @@ -1054,13 +1076,15 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) ret = i2c_add_adapter(adap); if (ret) { dev_err(&adev->dev, "failed to add adapter\n"); - goto err_no_mem; + goto err_no_adap; } pm_runtime_put(&adev->dev); return 0; + err_no_adap: + clk_disable_unprepare(dev->clk); err_no_mem: return ret; @@ -1077,6 +1101,7 @@ static int nmk_i2c_remove(struct amba_device *adev) clear_all_interrupts(dev); /* disable the controller */ i2c_clr_bit(dev->virtbase + I2C_CR, I2C_CR_PE); + clk_disable_unprepare(dev->clk); if (res) release_mem_region(res->start, resource_size(res));