|
@@ -111,8 +111,7 @@ static const u8 tuning_blk_pattern_8bit[] = {
|
|
|
0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
|
|
|
};
|
|
|
|
|
|
-static inline bool dw_mci_fifo_reset(struct dw_mci *host);
|
|
|
-static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host);
|
|
|
+static bool dw_mci_reset(struct dw_mci *host);
|
|
|
|
|
|
#if defined(CONFIG_DEBUG_FS)
|
|
|
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)
|
|
|
* After an error, there may be data lingering
|
|
|
* in the FIFO
|
|
|
*/
|
|
|
- dw_mci_fifo_reset(host);
|
|
|
+ dw_mci_reset(host);
|
|
|
} else {
|
|
|
data->bytes_xfered = data->blocks * data->blksz;
|
|
|
data->error = 0;
|
|
@@ -1352,7 +1351,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
|
|
|
|
|
|
/* CMD error in data command */
|
|
|
if (mrq->cmd->error && mrq->data)
|
|
|
- dw_mci_fifo_reset(host);
|
|
|
+ dw_mci_reset(host);
|
|
|
|
|
|
host->cmd = NULL;
|
|
|
host->data = NULL;
|
|
@@ -1963,14 +1962,8 @@ static void dw_mci_work_routine_card(struct work_struct *work)
|
|
|
}
|
|
|
|
|
|
/* Power down slot */
|
|
|
- if (present == 0) {
|
|
|
- /* Clear down the FIFO */
|
|
|
- dw_mci_fifo_reset(host);
|
|
|
-#ifdef CONFIG_MMC_DW_IDMAC
|
|
|
- dw_mci_idmac_reset(host);
|
|
|
-#endif
|
|
|
-
|
|
|
- }
|
|
|
+ if (present == 0)
|
|
|
+ dw_mci_reset(host);
|
|
|
|
|
|
spin_unlock_bh(&host->lock);
|
|
|
|
|
@@ -2208,8 +2201,11 @@ static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-static inline bool dw_mci_fifo_reset(struct dw_mci *host)
|
|
|
+static bool dw_mci_reset(struct dw_mci *host)
|
|
|
{
|
|
|
+ u32 flags = SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET;
|
|
|
+ bool ret = false;
|
|
|
+
|
|
|
/*
|
|
|
* Reseting generates a block interrupt, hence setting
|
|
|
* the scatter-gather pointer to NULL.
|
|
@@ -2219,15 +2215,60 @@ static inline bool dw_mci_fifo_reset(struct dw_mci *host)
|
|
|
host->sg = NULL;
|
|
|
}
|
|
|
|
|
|
- return dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET);
|
|
|
-}
|
|
|
+ if (host->use_dma)
|
|
|
+ flags |= SDMMC_CTRL_DMA_RESET;
|
|
|
|
|
|
-static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host)
|
|
|
-{
|
|
|
- return dw_mci_ctrl_reset(host,
|
|
|
- SDMMC_CTRL_FIFO_RESET |
|
|
|
- SDMMC_CTRL_RESET |
|
|
|
- SDMMC_CTRL_DMA_RESET);
|
|
|
+ if (dw_mci_ctrl_reset(host, flags)) {
|
|
|
+ /*
|
|
|
+ * In all cases we clear the RAWINTS register to clear any
|
|
|
+ * interrupts.
|
|
|
+ */
|
|
|
+ mci_writel(host, RINTSTS, 0xFFFFFFFF);
|
|
|
+
|
|
|
+ /* if using dma we wait for dma_req to clear */
|
|
|
+ if (host->use_dma) {
|
|
|
+ unsigned long timeout = jiffies + msecs_to_jiffies(500);
|
|
|
+ u32 status;
|
|
|
+ do {
|
|
|
+ status = mci_readl(host, STATUS);
|
|
|
+ if (!(status & SDMMC_STATUS_DMA_REQ))
|
|
|
+ break;
|
|
|
+ cpu_relax();
|
|
|
+ } while (time_before(jiffies, timeout));
|
|
|
+
|
|
|
+ if (status & SDMMC_STATUS_DMA_REQ) {
|
|
|
+ dev_err(host->dev,
|
|
|
+ "%s: Timeout waiting for dma_req to "
|
|
|
+ "clear during reset\n", __func__);
|
|
|
+ goto ciu_out;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* when using DMA next we reset the fifo again */
|
|
|
+ if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET))
|
|
|
+ goto ciu_out;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ /* if the controller reset bit did clear, then set clock regs */
|
|
|
+ if (!(mci_readl(host, CTRL) & SDMMC_CTRL_RESET)) {
|
|
|
+ dev_err(host->dev, "%s: fifo/dma reset bits didn't "
|
|
|
+ "clear but ciu was reset, doing clock update\n",
|
|
|
+ __func__);
|
|
|
+ goto ciu_out;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+#if IS_ENABLED(CONFIG_MMC_DW_IDMAC)
|
|
|
+ /* It is also recommended that we reset and reprogram idmac */
|
|
|
+ dw_mci_idmac_reset(host);
|
|
|
+#endif
|
|
|
+
|
|
|
+ ret = true;
|
|
|
+
|
|
|
+ciu_out:
|
|
|
+ /* After a CTRL reset we need to have CIU set clock registers */
|
|
|
+ mci_send_cmd(host->cur_slot, SDMMC_CMD_UPD_CLK, 0);
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_OF
|
|
@@ -2425,7 +2466,7 @@ int dw_mci_probe(struct dw_mci *host)
|
|
|
}
|
|
|
|
|
|
/* Reset all blocks */
|
|
|
- if (!dw_mci_ctrl_all_reset(host))
|
|
|
+ if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS))
|
|
|
return -ENODEV;
|
|
|
|
|
|
host->dma_ops = host->pdata->dma_ops;
|
|
@@ -2612,7 +2653,7 @@ int dw_mci_resume(struct dw_mci *host)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (!dw_mci_ctrl_all_reset(host)) {
|
|
|
+ if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS)) {
|
|
|
ret = -ENODEV;
|
|
|
return ret;
|
|
|
}
|