]> git.karo-electronics.de Git - linux-beck.git/commitdiff
mmc: dw_mmc: fix the IDMAC sw reset
authorSeungwon Jeon <tgih.jun@samsung.com>
Tue, 22 May 2012 04:01:03 +0000 (13:01 +0900)
committerChris Ball <cjb@laptop.org>
Wed, 6 Jun 2012 13:36:21 +0000 (09:36 -0400)
IDMAC may not be cleaned in driver probe if it has been already used in
boot time. So IDMAC needs sw reset newly. And DMA interface reset
precedes the internal DMAC reset. Additionally SDMMC_IDMAC_SWRESET is
replaced with magic code.

Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
Acked-by: Will Newton <will.newton@gmail.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
drivers/mmc/host/dw_mmc.c

index b46faf0cfb2761d36174ccccf025a1726168e15b..98fe02347d596f27d72fa391686db4c3a2b804fa 100644 (file)
@@ -418,6 +418,8 @@ static int dw_mci_idmac_init(struct dw_mci *host)
        p->des3 = host->sg_dma;
        p->des0 = IDMAC_DES0_ER;
 
+       mci_writel(host, BMOD, SDMMC_IDMAC_SWRESET);
+
        /* Mask out interrupts - get Tx & Rx complete only */
        mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI |
                   SDMMC_IDMAC_INT_TI);
@@ -1724,7 +1726,8 @@ static void dw_mci_work_routine_card(struct work_struct *work)
 
 #ifdef CONFIG_MMC_DW_IDMAC
                                ctrl = mci_readl(host, BMOD);
-                               ctrl |= 0x01; /* Software reset of DMA */
+                               /* Software reset of DMA */
+                               ctrl |= SDMMC_IDMAC_SWRESET;
                                mci_writel(host, BMOD, ctrl);
 #endif
 
@@ -1949,10 +1952,6 @@ int dw_mci_probe(struct dw_mci *host)
        spin_lock_init(&host->lock);
        INIT_LIST_HEAD(&host->queue);
 
-
-       host->dma_ops = host->pdata->dma_ops;
-       dw_mci_init_dma(host);
-
        /*
         * Get the host data width - this assumes that HCON has been set with
         * the correct values.
@@ -1980,10 +1979,11 @@ int dw_mci_probe(struct dw_mci *host)
        }
 
        /* Reset all blocks */
-       if (!mci_wait_reset(&host->dev, host)) {
-               ret = -ENODEV;
-               goto err_dmaunmap;
-       }
+       if (!mci_wait_reset(&host->dev, host))
+               return -ENODEV;
+
+       host->dma_ops = host->pdata->dma_ops;
+       dw_mci_init_dma(host);
 
        /* Clear the interrupts for the host controller */
        mci_writel(host, RINTSTS, 0xFFFFFFFF);
@@ -2169,14 +2169,14 @@ int dw_mci_resume(struct dw_mci *host)
        if (host->vmmc)
                regulator_enable(host->vmmc);
 
-       if (host->dma_ops->init)
-               host->dma_ops->init(host);
-
        if (!mci_wait_reset(&host->dev, host)) {
                ret = -ENODEV;
                return ret;
        }
 
+       if (host->dma_ops->init)
+               host->dma_ops->init(host);
+
        /* Restore the old value at FIFOTH register */
        mci_writel(host, FIFOTH, host->fifoth_val);