mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-27 22:56:49 +08:00
ppc/85xx: PIO Support for FSL eSDHC Controller Driver
On some Freescale SoC Internal DMA of eSDHC controller has bug. So PIO Mode has been introduced to do data transfer using CPU. Signed-off-by: Dipen Dudhat <dipen.dudhat@freescale.com>
This commit is contained in:
parent
a47a12becf
commit
77c1458d13
@ -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);
|
||||
|
@ -90,6 +90,7 @@
|
||||
#define PRSSTAT_CDPL (0x00040000)
|
||||
#define PRSSTAT_CINS (0x00010000)
|
||||
#define PRSSTAT_BREN (0x00000800)
|
||||
#define PRSSTAT_BWEN (0x00000400)
|
||||
#define PRSSTAT_DLA (0x00000004)
|
||||
#define PRSSTAT_CICHB (0x00000002)
|
||||
#define PRSSTAT_CIDHB (0x00000001)
|
||||
@ -121,6 +122,7 @@
|
||||
#define XFERTYP_DMAEN 0x00000001
|
||||
|
||||
#define CINS_TIMEOUT 1000
|
||||
#define PIO_TIMEOUT 100000
|
||||
|
||||
#define DSADDR 0x2e004
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user