From patchwork Tue Sep 3 09:29:36 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 2853165 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 36AB79F3DC for ; Tue, 3 Sep 2013 09:32:14 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 06E24203EC for ; Tue, 3 Sep 2013 09:32:13 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 95E7920266 for ; Tue, 3 Sep 2013 09:32:11 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VGmx1-0007R6-KU; Tue, 03 Sep 2013 09:31:08 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VGmwi-0002MH-Rs; Tue, 03 Sep 2013 09:30:48 +0000 Received: from mail-ee0-f43.google.com ([74.125.83.43]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VGmwa-0002JI-Ik for linux-arm-kernel@lists.infradead.org; Tue, 03 Sep 2013 09:30:41 +0000 Received: by mail-ee0-f43.google.com with SMTP id e52so2859979eek.16 for ; Tue, 03 Sep 2013 02:30:18 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=2C3DMOl+p9QJ1+iAlNGE8kkoc1LZvPnk08nM6l3F6iw=; b=Pq290mcOujsk1TQJi8Wtfr2RTM9TdECwMrmokZJpBYcEw2qxM++5C96FonLz+W9/SH aZxzEgrUMMyeika6WreTxfvgLO2j8BeWPIm0vFCQVvb/fhA+djN7+pFPULzR6XCn6Dqq ZYjkDQVAKM31Qu84HfG5v6hfzx1oeKL8FIkFfi4ozJT4rN0e17kmVuR7D195EpqEuAm0 kh5vBQzYfCNNFDlUjJdfer/ognS2o3Vsov5/7Epw8yeAM0MgkZvsnhI9NK99dobxUkpR RQW8rF5vlcowgR2n8O8ArrB66RY9rheDC9wiG+1f9itb5tei1e0NCAwQlYL7JHvNi6J9 I7ig== X-Gm-Message-State: ALoCoQnbBsB0wUNJFiXz72AL4majMfG5HksqaDklFAKEjceAlcNL0Xl1CVjnDzI0ldoiy77M1CUZ X-Received: by 10.14.37.4 with SMTP id x4mr45286914eea.16.1378200618725; Tue, 03 Sep 2013 02:30:18 -0700 (PDT) Received: from localhost.localdomain ([85.235.11.236]) by mx.google.com with ESMTPSA id z12sm29882771eev.6.1969.12.31.16.00.00 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 03 Sep 2013 02:30:18 -0700 (PDT) From: Ulf Hansson To: linux-arm-kernel@lists.infradead.org, Russell King Subject: [PATCH V3 4/4] mmc: mmci: Save and restore register context Date: Tue, 3 Sep 2013 11:29:36 +0200 Message-Id: <1378200576-13413-5-git-send-email-ulf.hansson@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1378200576-13413-1-git-send-email-ulf.hansson@linaro.org> References: <1378200576-13413-1-git-send-email-ulf.hansson@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130903_053040_778022_C6D3AAB6 X-CRM114-Status: GOOD ( 16.90 ) X-Spam-Score: -2.6 (--) Cc: Linus Walleij , Chris Ball , linux-mmc@vger.kernel.org, Daniel Lezcano , Ulf Hansson X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-6.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD,T_FRT_SLUT,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP If a corresponding power domain exists for the device and it manages to cut the domain regulator while the device is runtime suspended, the IP loses it's registers context. We restore the context in the .runtime_resume callback from the existing register caches to adapt to this siutuation. We also want to make sure the registers are in a known state while restoring context in the case when the power domain did not drop the power, since there are restrictions for the order of writing to these registers. To handle this, we clear the registers in the .runtime_suspend callback. Signed-off-by: Ulf Hansson Acked-by: Rickard Andersson Cc: Daniel Lezcano Reviewed-by: Daniel Lezcano --- drivers/mmc/host/mmci.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 82afcd3..97e541b 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -62,6 +62,7 @@ static unsigned int fmax = 515633; * @signal_direction: input/out direction of bus signals can be indicated * @pwrreg_clkgate: MMCIPOWER register must be used to gate the clock * @busy_detect: true if busy detection on dat0 is supported + * @pwrreg_nopower: bits in MMCIPOWER don't controls ext. power supply */ struct variant_data { unsigned int clkreg; @@ -76,6 +77,7 @@ struct variant_data { bool signal_direction; bool pwrreg_clkgate; bool busy_detect; + bool pwrreg_nopower; }; static struct variant_data variant_arm = { @@ -109,6 +111,7 @@ static struct variant_data variant_u300 = { .pwrreg_powerup = MCI_PWR_ON, .signal_direction = true, .pwrreg_clkgate = true, + .pwrreg_nopower = true, }; static struct variant_data variant_nomadik = { @@ -121,6 +124,7 @@ static struct variant_data variant_nomadik = { .pwrreg_powerup = MCI_PWR_ON, .signal_direction = true, .pwrreg_clkgate = true, + .pwrreg_nopower = true, }; static struct variant_data variant_ux500 = { @@ -135,6 +139,7 @@ static struct variant_data variant_ux500 = { .signal_direction = true, .pwrreg_clkgate = true, .busy_detect = true, + .pwrreg_nopower = true, }; static struct variant_data variant_ux500v2 = { @@ -150,6 +155,7 @@ static struct variant_data variant_ux500v2 = { .signal_direction = true, .pwrreg_clkgate = true, .busy_detect = true, + .pwrreg_nopower = true, }; static int mmci_card_busy(struct mmc_host *mmc) @@ -1759,6 +1765,41 @@ static int mmci_resume(struct device *dev) #endif #ifdef CONFIG_PM_RUNTIME +static void mmci_save(struct mmci_host *host) +{ + unsigned long flags; + + if (host->variant->pwrreg_nopower) { + spin_lock_irqsave(&host->lock, flags); + + writel(0, host->base + MMCIMASK0); + writel(0, host->base + MMCIDATACTRL); + writel(0, host->base + MMCIPOWER); + writel(0, host->base + MMCICLOCK); + mmci_reg_delay(host); + + spin_unlock_irqrestore(&host->lock, flags); + } + +} + +static void mmci_restore(struct mmci_host *host) +{ + unsigned long flags; + + if (host->variant->pwrreg_nopower) { + spin_lock_irqsave(&host->lock, flags); + + writel(host->clk_reg, host->base + MMCICLOCK); + writel(host->datactrl_reg, host->base + MMCIDATACTRL); + writel(host->pwr_reg, host->base + MMCIPOWER); + writel(MCI_IRQENABLE, host->base + MMCIMASK0); + mmci_reg_delay(host); + + spin_unlock_irqrestore(&host->lock, flags); + } +} + static int mmci_runtime_suspend(struct device *dev) { struct amba_device *adev = to_amba_device(dev); @@ -1767,6 +1808,7 @@ static int mmci_runtime_suspend(struct device *dev) if (mmc) { struct mmci_host *host = mmc_priv(mmc); pinctrl_pm_select_sleep_state(dev); + mmci_save(host); clk_disable_unprepare(host->clk); } @@ -1781,6 +1823,7 @@ static int mmci_runtime_resume(struct device *dev) if (mmc) { struct mmci_host *host = mmc_priv(mmc); clk_prepare_enable(host->clk); + mmci_restore(host); pinctrl_pm_select_default_state(dev); }