diff options
author | Sonny Rao <sonnyrao@chromium.org> | 2014-08-04 21:19:50 -0400 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2014-08-11 03:52:55 -0400 |
commit | 3a33a94ce27068c8fef63a4f9ab7cff1210e2a4e (patch) | |
tree | 08c5707e295a6948eacc88a971eb1cccac38a8d8 /drivers/mmc | |
parent | 3df5b28149df5c04f0fbb4efe15ef870ce93de93 (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.c | 87 | ||||
-rw-r--r-- | drivers/mmc/host/dw_mmc.h | 5 |
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 | ||
114 | static inline bool dw_mci_fifo_reset(struct dw_mci *host); | 114 | static bool dw_mci_reset(struct dw_mci *host); |
115 | static 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) |
118 | static int dw_mci_req_show(struct seq_file *s, void *v) | 117 | static 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 | ||
2211 | static inline bool dw_mci_fifo_reset(struct dw_mci *host) | 2204 | static 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 | ||
2225 | static 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 | |||
2267 | ciu_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) |