diff options
Diffstat (limited to 'drivers/mmc/fsl_esdhc.c')
| -rw-r--r-- | drivers/mmc/fsl_esdhc.c | 87 | 
1 files changed, 85 insertions, 2 deletions
| diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 0f6f8b161..a9b07a97c 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -72,8 +72,10 @@ uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)  	uint xfertyp = 0;  	if (data) { -		xfertyp |= XFERTYP_DPSEL | XFERTYP_DMAEN; - +		xfertyp |= XFERTYP_DPSEL; +#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO +		xfertyp |= XFERTYP_DMAEN; +#endif  		if (data->blocks > 1) {  			xfertyp |= XFERTYP_MSBSEL;  			xfertyp |= XFERTYP_BCEN; @@ -97,6 +99,71 @@ uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)  	return XFERTYP_CMD(cmd->cmdidx) | xfertyp;  } +#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO +/* + * PIO Read/Write Mode reduce the performace as DMA is not used in this mode. + */ +static int +esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data) +{ +	struct fsl_esdhc *regs = mmc->priv; +	uint blocks; +	char *buffer; +	uint databuf; +	uint size; +	uint irqstat; +	uint timeout; + +	if (data->flags & MMC_DATA_READ) { +		blocks = data->blocks; +		buffer = data->dest; +		while (blocks) { +			timeout = PIO_TIMEOUT; +			size = data->blocksize; +			irqstat = esdhc_read32(®s->irqstat); +			while (!(esdhc_read32(®s->prsstat) & PRSSTAT_BREN) +				&& --timeout); +			if (timeout <= 0) { +				printf("\nData Read Failed in PIO Mode."); +				return timeout; +			} +			while (size && (!(irqstat & IRQSTAT_TC))) { +				udelay(100); /* Wait before last byte transfer complete */ +				irqstat = esdhc_read32(®s->irqstat); +				databuf = in_le32(®s->datport); +				*((uint *)buffer) = databuf; +				buffer += 4; +				size -= 4; +			} +			blocks--; +		} +	} else { +		blocks = data->blocks; +		buffer = data->src; +		while (blocks) { +			timeout = PIO_TIMEOUT; +			size = data->blocksize; +			irqstat = esdhc_read32(®s->irqstat); +			while (!(esdhc_read32(®s->prsstat) & PRSSTAT_BWEN) +				&& --timeout); +			if (timeout <= 0) { +				printf("\nData Write Failed in PIO Mode."); +				return timeout; +			} +			while (size && (!(irqstat & IRQSTAT_TC))) { +				udelay(100); /* Wait before last byte transfer complete */ +				databuf = *((uint *)buffer); +				buffer += 4; +				size -= 4; +				irqstat = esdhc_read32(®s->irqstat); +				out_le32(®s->datport, databuf); +			} +			blocks--; +		} +	} +} +#endif +  static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)  {  	uint wml_value; @@ -104,6 +171,17 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)  	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;  	struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; +#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO +	if (!(data->flags & MMC_DATA_READ)) { +		if ((esdhc_read32(®s->prsstat) & PRSSTAT_WPSPL) == 0) { +			printf("\nThe SD card is locked. " +				"Can not write to a locked card.\n\n"); +			return TIMEOUT; +		} +		esdhc_write32(®s->dsaddr, (u32)data->src); +	} else +		esdhc_write32(®s->dsaddr, (u32)data->dest); +#else  	wml_value = data->blocksize/4;  	if (data->flags & MMC_DATA_READ) { @@ -124,6 +202,7 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)  					wml_value << 16);  		esdhc_write32(®s->dsaddr, (u32)data->src);  	} +#endif  	esdhc_write32(®s->blkattr, data->blocks << 16 | data->blocksize); @@ -220,6 +299,9 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)  	/* Wait until all of the blocks are transferred */  	if (data) { +#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO +		esdhc_pio_read_write(mmc, data); +#else  		do {  			irqstat = esdhc_read32(®s->irqstat); @@ -230,6 +312,7 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)  				return TIMEOUT;  		} while (!(irqstat & IRQSTAT_TC) &&  				(esdhc_read32(®s->prsstat) & PRSSTAT_DLA)); +#endif  	}  	esdhc_write32(®s->irqstat, -1); |