mmc: mmci: Send a CMD12 to clear the DPSM at errors
The current approach with sending a CMD12 (STOP_TRANSMISSION) to complete a data transfer request, either because of using the open-ended transmission type or because of receiving an error during a pre-defined data transfer, isn't sufficient for the STM32 sdmmc variant. More precisely, this variant needs to clear the DPSM ("Data Path State Machine") by sending a CMD12, for all failing ADTC commands. Support this, by adding a struct mmc_command inside the struct mmci_host and initialize it to a CMD12 during ->probe(). Let's also add checks for the new conditions, to enable mmci_data_irq() and mmci_cmd_irq() to postpone the calls to mmci_request_end(), but instead send the CMD12. Cc: Ludovic Barre <ludovic.barre@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Tested-by: Ludovic Barre <ludovic.barre@st.com>
This commit is contained in:
parent
e9d6a371cf
commit
e9968c6fa8
|
@ -1127,6 +1127,12 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
|
|||
writel(c, base + MMCICOMMAND);
|
||||
}
|
||||
|
||||
static void mmci_stop_command(struct mmci_host *host)
|
||||
{
|
||||
host->stop_abort.error = 0;
|
||||
mmci_start_command(host, &host->stop_abort, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
|
||||
unsigned int status)
|
||||
|
@ -1196,11 +1202,17 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
|
|||
/* The error clause is handled above, success! */
|
||||
data->bytes_xfered = data->blksz * data->blocks;
|
||||
|
||||
if (!data->stop || (host->mrq->sbc && !data->error))
|
||||
mmci_request_end(host, data->mrq);
|
||||
if (!data->stop) {
|
||||
if (host->variant->cmdreg_stop && data->error)
|
||||
mmci_stop_command(host);
|
||||
else
|
||||
mmci_request_end(host, data->mrq);
|
||||
} else if (host->mrq->sbc && !data->error) {
|
||||
mmci_request_end(host, data->mrq);
|
||||
} else {
|
||||
mmci_start_command(host, data->stop, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1298,6 +1310,10 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
|
|||
mmci_dma_error(host);
|
||||
|
||||
mmci_stop_data(host);
|
||||
if (host->variant->cmdreg_stop && cmd->error) {
|
||||
mmci_stop_command(host);
|
||||
return;
|
||||
}
|
||||
}
|
||||
mmci_request_end(host, host->mrq);
|
||||
} else if (sbc) {
|
||||
|
@ -1956,6 +1972,11 @@ static int mmci_probe(struct amba_device *dev,
|
|||
mmc->max_busy_timeout = 0;
|
||||
}
|
||||
|
||||
/* Prepare a CMD12 - needed to clear the DPSM on some variants. */
|
||||
host->stop_abort.opcode = MMC_STOP_TRANSMISSION;
|
||||
host->stop_abort.arg = 0;
|
||||
host->stop_abort.flags = MMC_RSP_R1B | MMC_CMD_AC;
|
||||
|
||||
mmc->ops = &mmci_ops;
|
||||
|
||||
/* We support these PM capabilities. */
|
||||
|
|
|
@ -377,6 +377,7 @@ struct mmci_host {
|
|||
void __iomem *base;
|
||||
struct mmc_request *mrq;
|
||||
struct mmc_command *cmd;
|
||||
struct mmc_command stop_abort;
|
||||
struct mmc_data *data;
|
||||
struct mmc_host *mmc;
|
||||
struct clk *clk;
|
||||
|
|
Loading…
Reference in New Issue