
Hi, Pantelis
This patch is based on patch http://patchwork.ozlabs.org/patch/283002/
I'm afraid it was delegated to York by mistake.
Best regards, Haijun
δΊ 2014/1/9 19:08, Pantelis Antoniou ει:
Hi Haijun,
Patch does not apply.
On Dec 30, 2013, at 10:20 AM, Haijun Zhang wrote:
The max timeout value esdhc host can accept is about 2.69 sec. At 50 Mhz SD_CLK period, the max busy timeout value = 2^27 * SD_CLK period ~= 2.69 sec.
In case erase command CMD38 timeout is caculated by mult * 300ms * num(unit by erase group), so the time one erase group need should be more than 300ms, 5000ms should be enough.
- Add data reset procedure for data error and command with busy error.
- Add timeout value detecting during waiting for transfer complete.
- Ignore Command inhibit (DAT) state when excuting CMD12.
- Add command CRC error detecting.
- Enlarged the timeout value used for busy state release.
Signed-off-by: Haijun Zhang Haijun.Zhang@freescale.com
changes for V5:
- no changes
drivers/mmc/fsl_esdhc.c | 164 +++++++++++++++++++++++++++++++----------------- 1 file changed, 106 insertions(+), 58 deletions(-)
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 9f4d3a2..134a02d 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -266,26 +266,36 @@ static int esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { uint xfertyp;
- uint irqstat;
- uint irqstat = 0, mask; struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
- int ret = 0, timeout;
- esdhc_write32(®s->irqstat, 0xffffffffU);
- sync();
- mask = PRSSTAT_CICHB | PRSSTAT_CIDHB;
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111 if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) return 0; +#else
- if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
mask &= ~PRSSTAT_CIDHB;
#endif
- esdhc_write32(®s->irqstat, -1);
- sync();
- /* Wait for the bus to be idle */
- while ((esdhc_read32(®s->prsstat) & PRSSTAT_CICHB) ||
(esdhc_read32(®s->prsstat) & PRSSTAT_CIDHB))
;
- while (esdhc_read32(®s->prsstat) & PRSSTAT_DLA)
;
timeout = 1000;
while (esdhc_read32(®s->prsstat) & mask) {
if (timeout == 0) {
printf("\nController never released inhibit bit(s).\n");
ret = COMM_ERR;
goto reset;
}
timeout--;
mdelay(1);
}
/* Wait at least 8 SD clock cycles before the next command */ /*
@@ -296,11 +306,9 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
/* Set up for a data transfer if we have one */ if (data) {
int err;
err = esdhc_setup_data(mmc, data);
if(err)
return err;
ret = esdhc_setup_data(mmc, data);
if (ret)
goto reset;
}
/* Figure out the transfer arguments */
@@ -325,43 +333,14 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
irqstat = esdhc_read32(®s->irqstat);
- /* Reset CMD and DATA portions on error */
- if (irqstat & CMD_ERR) {
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 & IRQSTAT_CTOE) {
ret = TIMEOUT;
}goto reset;
- if (irqstat & IRQSTAT_CTOE)
return TIMEOUT;
- if (irqstat & CMD_ERR)
return COMM_ERR;
- /* 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;
}
if (irqstat & CMD_ERR) {
ret = COMM_ERR;
goto reset;
}
/* Copy the response to the response buffer */
@@ -379,7 +358,20 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) } else cmd->response[0] = esdhc_read32(®s->cmdrsp0);
- /* Wait until all of the blocks are transferred */
- /*
* At 50 Mhz SD_CLK period, the max busy timeout
* value or data transfer time need was about
* = 2^27 * SD_CLK period ~= 2.69 sec.
* So wait max 10 sec for data transfer complete or busy
* state release.
*/
- timeout = 10000;
- /*
* eSDHC host V2.3 has response busy interrupt, so
* we should wait for busy state to be released and data
* was out of programing state before next command send.
if (data) {*/
#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO esdhc_pio_read_write(mmc, data); @@ -387,20 +379,76 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) do { irqstat = esdhc_read32(®s->irqstat);
if (irqstat & IRQSTAT_DTOE)
return TIMEOUT;
if (irqstat & IRQSTAT_DTOE) {
ret = TIMEOUT;
break;
}
if (irqstat & DATA_ERR)
return COMM_ERR;
} while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE);
if (irqstat & DATA_ERR) {
ret = COMM_ERR;
break;
}
if (timeout <= 0) {
ret = TIMEOUT;
break;
}
mdelay(1);
timeout--;
} while (((irqstat & DATA_COMPLETE) != DATA_COMPLETE) &&
(esdhc_read32(®s->prsstat) & PRSSTAT_DLA));
#endif if (data->flags & MMC_DATA_READ) check_and_invalidate_dcache_range(cmd, data); }
- esdhc_write32(®s->irqstat, -1);
/* Workaround for ESDHC errata ENGcm03648 */
if (!data && (cmd->resp_type & MMC_RSP_BUSY)) {
int timeout = 5000;
/* Poll on DATA0 line for cmd with busy signal for 5 sec */
while (timeout > 0 && !(esdhc_read32(®s->prsstat) &
PRSSTAT_DAT0)) {
mdelay(1);
timeout--;
}
if (timeout <= 0) {
printf("\nTimeout waiting for DAT0 to go high!\n");
ret = TIMEOUT;
goto reset;
}
}
if (esdhc_read32(®s->irqstat) & (DATA_ERR | CMD_ERR))
ret = COMM_ERR;
if (ret)
goto reset;
esdhc_write32(®s->irqstat, 0xffffffffU);
return 0;
+reset:
- /* Reset CMD and DATA portions on error */
- esdhc_write32(®s->sysctl, esdhc_read32(®s->sysctl) |
SYSCTL_RSTC);
- while (esdhc_read32(®s->sysctl) & SYSCTL_RSTC)
;
- if (data || (cmd->resp_type & MMC_RSP_BUSY)) {
esdhc_write32(®s->sysctl,
esdhc_read32(®s->sysctl) |
SYSCTL_RSTD);
while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTD))
;
- }
- esdhc_write32(®s->irqstat, 0xffffffffU);
- return ret;
}
static void set_sysctl(struct mmc *mmc, uint clock)
1.8.4.1
Regards
-- Pantelis