From mboxrd@z Thu Jan 1 00:00:00 1970 From: Zhang Haijun Date: Fri, 10 Jan 2014 11:54:21 +0800 Subject: [U-Boot] [PATCH 7/7 V5] powerpc/esdhc: Update esdhc command execution process In-Reply-To: References: <1388391658-28560-1-git-send-email-haijun.zhang@freescale.com> <1388391658-28560-7-git-send-email-haijun.zhang@freescale.com> Message-ID: <52CF6EED.2060805@freescale.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de 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. >> >> 1. Add data reset procedure for data error and command with busy error. >> 2. Add timeout value detecting during waiting for transfer complete. >> 3. Ignore Command inhibit (DAT) state when excuting CMD12. >> 4. Add command CRC error detecting. >> 5. Enlarged the timeout value used for busy state release. >> >> Signed-off-by: Haijun Zhang >> --- >> 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 > > >