aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorSonny Rao <sonnyrao@chromium.org>2014-08-04 21:19:50 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2014-08-11 03:52:55 -0400
commit3a33a94ce27068c8fef63a4f9ab7cff1210e2a4e (patch)
tree08c5707e295a6948eacc88a971eb1cccac38a8d8 /drivers/mmc
parent3df5b28149df5c04f0fbb4efe15ef870ce93de93 (diff)
mmc: dw_mmc: change to use recommended reset procedure
This patch changes the fifo reset code to follow the reset procedure outlined in the documentation of Synopsys Mobile storage host databook. Signed-off-by: Sonny Rao <sonnyrao@chromium.org> Signed-off-by: Yuvaraj Kumar C D <yuvaraj.cd@samsung.com> Acked-by: Seungwon Jeon <tgih.jun@samsung.com> [sonnyrao: fix compile for !CONFIG_MMC_DW_IDMAC case] Acked-by: Jaehoon Chung <jh80.chung@samsung.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/dw_mmc.c87
-rw-r--r--drivers/mmc/host/dw_mmc.h5
2 files changed, 69 insertions, 23 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 1ac227c603b7..39cf54f479d9 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -111,8 +111,7 @@ static const u8 tuning_blk_pattern_8bit[] = {
111 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 111 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
112}; 112};
113 113
114static inline bool dw_mci_fifo_reset(struct dw_mci *host); 114static bool dw_mci_reset(struct dw_mci *host);
115static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host);
116 115
117#if defined(CONFIG_DEBUG_FS) 116#if defined(CONFIG_DEBUG_FS)
118static int dw_mci_req_show(struct seq_file *s, void *v) 117static int dw_mci_req_show(struct seq_file *s, void *v)
@@ -1235,7 +1234,7 @@ static int dw_mci_data_complete(struct dw_mci *host, struct mmc_data *data)
1235 * After an error, there may be data lingering 1234 * After an error, there may be data lingering
1236 * in the FIFO 1235 * in the FIFO
1237 */ 1236 */
1238 dw_mci_fifo_reset(host); 1237 dw_mci_reset(host);
1239 } else { 1238 } else {
1240 data->bytes_xfered = data->blocks * data->blksz; 1239 data->bytes_xfered = data->blocks * data->blksz;
1241 data->error = 0; 1240 data->error = 0;
@@ -1352,7 +1351,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
1352 1351
1353 /* CMD error in data command */ 1352 /* CMD error in data command */
1354 if (mrq->cmd->error && mrq->data) 1353 if (mrq->cmd->error && mrq->data)
1355 dw_mci_fifo_reset(host); 1354 dw_mci_reset(host);
1356 1355
1357 host->cmd = NULL; 1356 host->cmd = NULL;
1358 host->data = NULL; 1357 host->data = NULL;
@@ -1963,14 +1962,8 @@ static void dw_mci_work_routine_card(struct work_struct *work)
1963 } 1962 }
1964 1963
1965 /* Power down slot */ 1964 /* Power down slot */
1966 if (present == 0) { 1965 if (present == 0)
1967 /* Clear down the FIFO */ 1966 dw_mci_reset(host);
1968 dw_mci_fifo_reset(host);
1969#ifdef CONFIG_MMC_DW_IDMAC
1970 dw_mci_idmac_reset(host);
1971#endif
1972
1973 }
1974 1967
1975 spin_unlock_bh(&host->lock); 1968 spin_unlock_bh(&host->lock);
1976 1969
@@ -2208,8 +2201,11 @@ static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset)
2208 return false; 2201 return false;
2209} 2202}
2210 2203
2211static inline bool dw_mci_fifo_reset(struct dw_mci *host) 2204static bool dw_mci_reset(struct dw_mci *host)
2212{ 2205{
2206 u32 flags = SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET;
2207 bool ret = false;
2208
2213 /* 2209 /*
2214 * Reseting generates a block interrupt, hence setting 2210 * Reseting generates a block interrupt, hence setting
2215 * the scatter-gather pointer to NULL. 2211 * the scatter-gather pointer to NULL.
@@ -2219,15 +2215,60 @@ static inline bool dw_mci_fifo_reset(struct dw_mci *host)
2219 host->sg = NULL; 2215 host->sg = NULL;
2220 } 2216 }
2221 2217
2222 return dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET); 2218 if (host->use_dma)
2223} 2219 flags |= SDMMC_CTRL_DMA_RESET;
2224 2220
2225static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host) 2221 if (dw_mci_ctrl_reset(host, flags)) {
2226{ 2222 /*
2227 return dw_mci_ctrl_reset(host, 2223 * In all cases we clear the RAWINTS register to clear any
2228 SDMMC_CTRL_FIFO_RESET | 2224 * interrupts.
2229 SDMMC_CTRL_RESET | 2225 */
2230 SDMMC_CTRL_DMA_RESET); 2226 mci_writel(host, RINTSTS, 0xFFFFFFFF);
2227
2228 /* if using dma we wait for dma_req to clear */
2229 if (host->use_dma) {
2230 unsigned long timeout = jiffies + msecs_to_jiffies(500);
2231 u32 status;
2232 do {
2233 status = mci_readl(host, STATUS);
2234 if (!(status & SDMMC_STATUS_DMA_REQ))
2235 break;
2236 cpu_relax();
2237 } while (time_before(jiffies, timeout));
2238
2239 if (status & SDMMC_STATUS_DMA_REQ) {
2240 dev_err(host->dev,
2241 "%s: Timeout waiting for dma_req to "
2242 "clear during reset\n", __func__);
2243 goto ciu_out;
2244 }
2245
2246 /* when using DMA next we reset the fifo again */
2247 if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET))
2248 goto ciu_out;
2249 }
2250 } else {
2251 /* if the controller reset bit did clear, then set clock regs */
2252 if (!(mci_readl(host, CTRL) & SDMMC_CTRL_RESET)) {
2253 dev_err(host->dev, "%s: fifo/dma reset bits didn't "
2254 "clear but ciu was reset, doing clock update\n",
2255 __func__);
2256 goto ciu_out;
2257 }
2258 }
2259
2260#if IS_ENABLED(CONFIG_MMC_DW_IDMAC)
2261 /* It is also recommended that we reset and reprogram idmac */
2262 dw_mci_idmac_reset(host);
2263#endif
2264
2265 ret = true;
2266
2267ciu_out:
2268 /* After a CTRL reset we need to have CIU set clock registers */
2269 mci_send_cmd(host->cur_slot, SDMMC_CMD_UPD_CLK, 0);
2270
2271 return ret;
2231} 2272}
2232 2273
2233#ifdef CONFIG_OF 2274#ifdef CONFIG_OF
@@ -2425,7 +2466,7 @@ int dw_mci_probe(struct dw_mci *host)
2425 } 2466 }
2426 2467
2427 /* Reset all blocks */ 2468 /* Reset all blocks */
2428 if (!dw_mci_ctrl_all_reset(host)) 2469 if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS))
2429 return -ENODEV; 2470 return -ENODEV;
2430 2471
2431 host->dma_ops = host->pdata->dma_ops; 2472 host->dma_ops = host->pdata->dma_ops;
@@ -2612,7 +2653,7 @@ int dw_mci_resume(struct dw_mci *host)
2612 } 2653 }
2613 } 2654 }
2614 2655
2615 if (!dw_mci_ctrl_all_reset(host)) { 2656 if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS)) {
2616 ret = -ENODEV; 2657 ret = -ENODEV;
2617 return ret; 2658 return ret;
2618 } 2659 }
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 738fa241d058..08fd956d81f3 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -129,6 +129,7 @@
129#define SDMMC_CMD_INDX(n) ((n) & 0x1F) 129#define SDMMC_CMD_INDX(n) ((n) & 0x1F)
130/* Status register defines */ 130/* Status register defines */
131#define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FFF) 131#define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FFF)
132#define SDMMC_STATUS_DMA_REQ BIT(31)
132/* FIFOTH register defines */ 133/* FIFOTH register defines */
133#define SDMMC_SET_FIFOTH(m, r, t) (((m) & 0x7) << 28 | \ 134#define SDMMC_SET_FIFOTH(m, r, t) (((m) & 0x7) << 28 | \
134 ((r) & 0xFFF) << 16 | \ 135 ((r) & 0xFFF) << 16 | \
@@ -150,6 +151,10 @@
150/* Card read threshold */ 151/* Card read threshold */
151#define SDMMC_SET_RD_THLD(v, x) (((v) & 0x1FFF) << 16 | (x)) 152#define SDMMC_SET_RD_THLD(v, x) (((v) & 0x1FFF) << 16 | (x))
152 153
154/* All ctrl reset bits */
155#define SDMMC_CTRL_ALL_RESET_FLAGS \
156 (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET)
157
153/* Register access macros */ 158/* Register access macros */
154#define mci_readl(dev, reg) \ 159#define mci_readl(dev, reg) \
155 __raw_readl((dev)->regs + SDMMC_##reg) 160 __raw_readl((dev)->regs + SDMMC_##reg)