|
@@ -1055,6 +1055,8 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq)
|
|
|
{
|
|
|
struct mmc_spi_host *host = mmc_priv(mmc);
|
|
|
int status = -EINVAL;
|
|
|
+ int crc_retry = 5;
|
|
|
+ struct mmc_command stop;
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
/* MMC core and layered drivers *MUST* issue SPI-aware commands */
|
|
@@ -1087,10 +1089,29 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq)
|
|
|
/* request exclusive bus access */
|
|
|
spi_bus_lock(host->spi->master);
|
|
|
|
|
|
+crc_recover:
|
|
|
/* issue command; then optionally data and stop */
|
|
|
status = mmc_spi_command_send(host, mrq, mrq->cmd, mrq->data != NULL);
|
|
|
if (status == 0 && mrq->data) {
|
|
|
mmc_spi_data_do(host, mrq->cmd, mrq->data, mrq->data->blksz);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * The SPI bus is not always reliable for large data transfers.
|
|
|
+ * If an occasional crc error is reported by the SD device with
|
|
|
+ * data read/write over SPI, it may be recovered by repeating
|
|
|
+ * the last SD command again. The retry count is set to 5 to
|
|
|
+ * ensure the driver passes stress tests.
|
|
|
+ */
|
|
|
+ if (mrq->data->error == -EILSEQ && crc_retry) {
|
|
|
+ stop.opcode = MMC_STOP_TRANSMISSION;
|
|
|
+ stop.arg = 0;
|
|
|
+ stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
|
|
|
+ status = mmc_spi_command_send(host, mrq, &stop, 0);
|
|
|
+ crc_retry--;
|
|
|
+ mrq->data->error = 0;
|
|
|
+ goto crc_recover;
|
|
|
+ }
|
|
|
+
|
|
|
if (mrq->stop)
|
|
|
status = mmc_spi_command_send(host, mrq, mrq->stop, 0);
|
|
|
else
|