mmc: dw_mmc: fix suspend/resume operation
authorJaehoon Chung <jh80.chung@samsung.com>
Thu, 17 Mar 2011 11:32:33 +0000 (20:32 +0900)
committerChris Ball <cjb@laptop.org>
Thu, 17 Mar 2011 19:35:20 +0000 (15:35 -0400)
This patch is related to re-init processing on suspend/resume.

When card is resuming, some register is reset.  If card is removable,
maybe controller should be rescan for card.  But if assume card is
non-removable, need to restore the old value at registers.

We store the value of FIFOTH at probe time and then restore it in
dw_mci_resume().

Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Will Newton <will.newton@imgtec.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
drivers/mmc/host/dw_mmc.c
include/linux/mmc/dw_mmc.h

index 94ec650..51ee2f5 100644 (file)
@@ -1639,8 +1639,9 @@ static int dw_mci_probe(struct platform_device *pdev)
         */
        fifo_size = mci_readl(host, FIFOTH);
        fifo_size = (fifo_size >> 16) & 0x7ff;
-       mci_writel(host, FIFOTH, ((0x2 << 28) | ((fifo_size/2 - 1) << 16) |
-                                 ((fifo_size/2) << 0)));
+       host->fifoth_val = ((0x2 << 28) | ((fifo_size/2 - 1) << 16) |
+                       ((fifo_size/2) << 0));
+       mci_writel(host, FIFOTH, host->fifoth_val);
 
        /* disable clock to CIU */
        mci_writel(host, CLKENA, 0);
@@ -1772,6 +1773,23 @@ static int dw_mci_resume(struct platform_device *pdev)
        int i, ret;
        struct dw_mci *host = platform_get_drvdata(pdev);
 
+       if (host->dma_ops->init)
+               host->dma_ops->init(host);
+
+       if (!mci_wait_reset(&pdev->dev, host)) {
+               ret = -ENODEV;
+               return ret;
+       }
+
+       /* Restore the old value at FIFOTH register */
+       mci_writel(host, FIFOTH, host->fifoth_val);
+
+       mci_writel(host, RINTSTS, 0xFFFFFFFF);
+       mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
+                  SDMMC_INT_TXDR | SDMMC_INT_RXDR |
+                  DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
+       mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE);
+
        for (i = 0; i < host->num_slots; i++) {
                struct dw_mci_slot *slot = host->slot[i];
                if (!slot)
index f081631..6c324de 100644 (file)
@@ -140,6 +140,7 @@ struct dw_mci {
        u32                     bus_hz;
        u32                     current_speed;
        u32                     num_slots;
+       u32                     fifoth_val;
        struct platform_device  *pdev;
        struct dw_mci_board     *pdata;
        struct dw_mci_slot      *slot[MAX_MCI_SLOTS];