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: 19703 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-qe0-f71.google.com (mail-qe0-f71.google.com [209.85.128.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id D75F824869 for ; Tue, 3 Sep 2013 09:30:20 +0000 (UTC) Received: by mail-qe0-f71.google.com with SMTP id 1sf6301379qee.10 for ; Tue, 03 Sep 2013 02:30:20 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=mime-version:x-gm-message-state:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=2C3DMOl+p9QJ1+iAlNGE8kkoc1LZvPnk08nM6l3F6iw=; b=fyvHctu124JWjf6pVrDGvXz0IcI1vEAQPHq1MzhgaKpkBDYCaO/sP1ESyC20YcY6Gr BbvgnAUEI5nHoF3gXnGglF8Z4cYKiiYlc92p4oKniH8Pu/puzm+Zpx8XdGu5Yg0QvTWK ee2Ngy/exssEEcxYtdFM8X+Jjb1Th7qJ/u5PCBAwI4cWZOcUeKeHUXPtFMHeCFQ142BX 0UFzQRrcM8JbVSLQPDrC60qcObXihuV9PMF8MbyEjAhXoBKLtPUX8Lu7gvUqdqAxztwH l/gpJ/OvoqOjqWLjcZpP1A2wdbUZK+HPN8xf+VB7SjdJEN7j2gb0yCAfAhGIyO/l/HT/ Afbw== X-Received: by 10.236.223.130 with SMTP id v2mr10110440yhp.34.1378200620580; Tue, 03 Sep 2013 02:30:20 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.12.166 with SMTP id z6ls2520155qeb.18.gmail; Tue, 03 Sep 2013 02:30:20 -0700 (PDT) X-Received: by 10.52.103.101 with SMTP id fv5mr394386vdb.31.1378200620492; Tue, 03 Sep 2013 02:30:20 -0700 (PDT) Received: from mail-vb0-f54.google.com (mail-vb0-f54.google.com [209.85.212.54]) by mx.google.com with ESMTPS id wp10si3780073vdb.6.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 03 Sep 2013 02:30:20 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.212.54 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.212.54; Received: by mail-vb0-f54.google.com with SMTP id q14so3835627vbe.27 for ; Tue, 03 Sep 2013 02:30:20 -0700 (PDT) X-Gm-Message-State: ALoCoQnGEEh/bktZnUk9fFvaUeWH+PRL3xwZRPX/OMXDIVA9pXpW6HaZH3Iy67G1CGCdeejJQGPx X-Received: by 10.58.119.233 with SMTP id kx9mr27210966veb.3.1378200620393; Tue, 03 Sep 2013 02:30:20 -0700 (PDT) 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 u4csp160154vcz; Tue, 3 Sep 2013 02:30:19 -0700 (PDT) X-Received: by 10.14.107.68 with SMTP id n44mr45360512eeg.26.1378200619262; Tue, 03 Sep 2013 02:30:19 -0700 (PDT) Received: from mail-ee0-f44.google.com (mail-ee0-f44.google.com [74.125.83.44]) by mx.google.com with ESMTPS id t9si13766363eeh.153.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 03 Sep 2013 02:30:19 -0700 (PDT) Received-SPF: neutral (google.com: 74.125.83.44 is neither permitted nor denied by best guess record for domain of ulf.hansson@linaro.org) client-ip=74.125.83.44; Received: by mail-ee0-f44.google.com with SMTP id b47so2857896eek.17 for ; Tue, 03 Sep 2013 02:30:18 -0700 (PDT) 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 Cc: linux-mmc@vger.kernel.org, Chris Ball , Daniel Lezcano , Linus Walleij , Ulf Hansson 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-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.212.54 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: , 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 --- 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); }