diff options
Diffstat (limited to 'drivers/mmc/fsl_esdhc.c')
| -rw-r--r-- | drivers/mmc/fsl_esdhc.c | 39 | 
1 files changed, 38 insertions, 1 deletions
| diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index a2f35e3e9..07370b572 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -307,19 +307,56 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)  #else  	esdhc_write32(®s->xfertyp, xfertyp);  #endif + +	/* Mask all irqs */ +	esdhc_write32(®s->irqsigen, 0); +  	/* Wait for the command to complete */ -	while (!(esdhc_read32(®s->irqstat) & IRQSTAT_CC)) +	while (!(esdhc_read32(®s->irqstat) & (IRQSTAT_CC | IRQSTAT_CTOE)))  		;  	irqstat = esdhc_read32(®s->irqstat);  	esdhc_write32(®s->irqstat, irqstat); +	/* Reset CMD and DATA portions on error */ +	if (irqstat & (CMD_ERR | IRQSTAT_CTOE)) { +		esdhc_write32(®s->sysctl, esdhc_read32(®s->sysctl) | +			      SYSCTL_RSTC); +		while (esdhc_read32(®s->sysctl) & SYSCTL_RSTC) +			; + +		if (data) { +			esdhc_write32(®s->sysctl, +				      esdhc_read32(®s->sysctl) | +				      SYSCTL_RSTD); +			while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTD)) +				; +		} +	} +  	if (irqstat & CMD_ERR)  		return COMM_ERR;  	if (irqstat & IRQSTAT_CTOE)  		return TIMEOUT; +	/* Workaround for ESDHC errata ENGcm03648 */ +	if (!data && (cmd->resp_type & MMC_RSP_BUSY)) { +		int timeout = 2500; + +		/* Poll on DATA0 line for cmd with busy signal for 250 ms */ +		while (timeout > 0 && !(esdhc_read32(®s->prsstat) & +					PRSSTAT_DAT0)) { +			udelay(100); +			timeout--; +		} + +		if (timeout <= 0) { +			printf("Timeout waiting for DAT0 to go high!\n"); +			return TIMEOUT; +		} +	} +  	/* Copy the response to the response buffer */  	if (cmd->resp_type & MMC_RSP_136) {  		u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0; |