From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dirk Behme Date: Wed, 12 Jun 2013 07:16:04 +0200 Subject: [U-Boot] [PATCH] fsl_esdhc: Do not clear interrupt status bits until data processed In-Reply-To: <1370964862-26947-1-git-send-email-andrew_gabbasov@mentor.com> References: <6C5EA58090A5ED459815C4D04C2B466FD9332ACA@EU-MBX-01.mgc.mentorg.com> <1370964862-26947-1-git-send-email-andrew_gabbasov@mentor.com> Message-ID: <51B80414.40808@de.bosch.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de On 11.06.2013 17:34, Andrew Gabbasov wrote: > After waiting for the command completion event, the interrupt status > bits, that occured to be set by that time, are cleared by writing them > back. It is supposed, that it should be command related bits (command > complete and may be command errors). > > However, in some cases the DMA already completes by that time before > the full transaction completes. The corresponding DINT bit gets set > and then cleared before even entering the loop, waiting for data part > completion. That waiting loop never gets this bit set, causing the > operation to hang. This is reported to happen, for example, for write > operation of 1 sector to upper area (block #7400000) of SanDisk Ultra II > 8GB card. > > The solution could be to explicitly clear only command related interrupt > status bits. However, since subsequent processing does not rely on > any command bits state, it could be easier just to remove clearing > of any bits at that point, leaving them all until all data processing > completes. After that the whole register will be cleared at once. > > Also, on occasion, interrupts masking moved to before writing the command, > just for the case there should be no chance of interrupt between the first > command and interrupts masking. > > Reported-by: Dirk Behme > Signed-off-by: Andrew Gabbasov Acked-by: Dirk Behme Thanks Dirk > --- > drivers/mmc/fsl_esdhc.c | 7 +++---- > 1 file changed, 3 insertions(+), 4 deletions(-) > > diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c > index 861f4b9..b501b4d 100644 > --- a/drivers/mmc/fsl_esdhc.c > +++ b/drivers/mmc/fsl_esdhc.c > @@ -310,6 +310,9 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) > /* Figure out the transfer arguments */ > xfertyp = esdhc_xfertyp(cmd, data); > > + /* Mask all irqs */ > + esdhc_write32(®s->irqsigen, 0); > + > /* Send the command */ > esdhc_write32(®s->cmdarg, cmd->cmdarg); > #if defined(CONFIG_FSL_USDHC) > @@ -320,15 +323,11 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) > esdhc_write32(®s->xfertyp, xfertyp); > #endif > > - /* Mask all irqs */ > - esdhc_write32(®s->irqsigen, 0); > - > /* Wait for the command to complete */ > while (!(esdhc_read32(®s->irqstat) & (IRQSTAT_CC | IRQSTAT_CTOE))) > ; > > irqstat = esdhc_read32(®s->irqstat); > - esdhc_write32(®s->irqstat, irqstat); > > /* Reset CMD and DATA portions on error */ > if (irqstat & (CMD_ERR | IRQSTAT_CTOE)) {