mmc: sdhci-omap: Fix context restore
authorTony Lindgren <tony@atomide.com>
Tue, 21 Sep 2021 11:00:26 +0000 (14:00 +0300)
committerUlf Hansson <ulf.hansson@linaro.org>
Tue, 12 Oct 2021 08:21:18 +0000 (10:21 +0200)
We need to restore context in a specified order with HCTL set in two
phases. This is similar to what omap_hsmmc_context_restore() is doing.
Otherwise SDIO can stop working on resume.

And for PM runtime and SDIO cards, we need to also save SYSCTL, IE and
ISE.

This should not be a problem currently, and these patches can be applied
whenever suitable.

Fixes: ee0f309263a6 ("mmc: sdhci-omap: Add Support for Suspend/Resume")
Signed-off-by: Tony Lindgren <tony@atomide.com>
Link: https://lore.kernel.org/r/20210921110029.21944-3-tony@atomide.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/host/sdhci-omap.c

index 3ddced7..fd188b6 100644 (file)
@@ -62,6 +62,8 @@
 #define SDHCI_OMAP_IE          0x234
 #define INT_CC_EN              BIT(0)
 
+#define SDHCI_OMAP_ISE         0x238
+
 #define SDHCI_OMAP_AC12                0x23c
 #define AC12_V1V8_SIGEN                BIT(19)
 #define AC12_SCLK_SEL          BIT(23)
@@ -113,6 +115,8 @@ struct sdhci_omap_host {
        u32                     hctl;
        u32                     sysctl;
        u32                     capa;
+       u32                     ie;
+       u32                     ise;
 };
 
 static void sdhci_omap_start_clock(struct sdhci_omap_host *omap_host);
@@ -1245,14 +1249,23 @@ static void sdhci_omap_context_save(struct sdhci_omap_host *omap_host)
 {
        omap_host->con = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON);
        omap_host->hctl = sdhci_omap_readl(omap_host, SDHCI_OMAP_HCTL);
+       omap_host->sysctl = sdhci_omap_readl(omap_host, SDHCI_OMAP_SYSCTL);
        omap_host->capa = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA);
+       omap_host->ie = sdhci_omap_readl(omap_host, SDHCI_OMAP_IE);
+       omap_host->ise = sdhci_omap_readl(omap_host, SDHCI_OMAP_ISE);
 }
 
+/* Order matters here, HCTL must be restored in two phases */
 static void sdhci_omap_context_restore(struct sdhci_omap_host *omap_host)
 {
-       sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, omap_host->con);
        sdhci_omap_writel(omap_host, SDHCI_OMAP_HCTL, omap_host->hctl);
        sdhci_omap_writel(omap_host, SDHCI_OMAP_CAPA, omap_host->capa);
+       sdhci_omap_writel(omap_host, SDHCI_OMAP_HCTL, omap_host->hctl);
+
+       sdhci_omap_writel(omap_host, SDHCI_OMAP_SYSCTL, omap_host->sysctl);
+       sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, omap_host->con);
+       sdhci_omap_writel(omap_host, SDHCI_OMAP_IE, omap_host->ie);
+       sdhci_omap_writel(omap_host, SDHCI_OMAP_ISE, omap_host->ise);
 }
 
 static int __maybe_unused sdhci_omap_suspend(struct device *dev)