X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fmmc%2Ffsl_esdhc.c;h=a368fe60db4a285bb5b43a8ec16069ab8e436d24;hb=f12d4cb48a1040c25a55148d0eedee1a896364e6;hp=85354e893a4483ada568967b997d94f3105e6185;hpb=cc4d1226585fa2544b5116702b02eacbb7aa48a1;p=u-boot diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 85354e893a..a368fe60db 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,12 +99,78 @@ 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 void +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; + } + 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 = (char *)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; + } + 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; int timeout; struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; +#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO + uint wml_value; wml_value = data->blocksize/4; @@ -110,8 +178,7 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) if (wml_value > 0x10) wml_value = 0x10; - wml_value = 0x100000 | wml_value; - + esdhc_clrsetbits32(®s->wml, WML_RD_WML_MASK, wml_value); esdhc_write32(®s->dsaddr, (u32)data->dest); } else { if (wml_value > 0x80) @@ -120,11 +187,22 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) printf("\nThe SD card is locked. Can not write to a locked card.\n\n"); return TIMEOUT; } - wml_value = wml_value << 16 | 0x10; + + esdhc_clrsetbits32(®s->wml, WML_WR_WML_MASK, + wml_value << 16); esdhc_write32(®s->dsaddr, (u32)data->src); } - - esdhc_write32(®s->wml, wml_value); +#else /* 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); +#endif /* CONFIG_SYS_FSL_ESDHC_USE_PIO */ esdhc_write32(®s->blkattr, data->blocks << 16 | data->blocksize); @@ -221,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); @@ -231,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); @@ -344,6 +426,20 @@ static int esdhc_init(struct mmc *mmc) return ret; } +static void esdhc_reset(struct fsl_esdhc *regs) +{ + unsigned long timeout = 100; /* wait max 100 ms */ + + /* reset the controller */ + esdhc_write32(®s->sysctl, SYSCTL_RSTA); + + /* hardware clears the bit when it is done */ + while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTA) && --timeout) + udelay(1000); + if (!timeout) + printf("MMC/SD: Reset never completed.\n"); +} + int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) { struct fsl_esdhc *regs; @@ -358,6 +454,9 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) sprintf(mmc->name, "FSL_ESDHC"); regs = (struct fsl_esdhc *)cfg->esdhc_base; + /* First reset the eSDHC controller */ + esdhc_reset(regs); + mmc->priv = cfg; mmc->send_cmd = esdhc_send_cmd; mmc->set_ios = esdhc_set_ios;