On Tue, 23 Jul 2019 at 15:00, Jean Nicolas GRAUX <jean-nicolas.graux@xxxxxx> wrote: > > Hi Ulf, > > I did a quick test booting on emmc with that new patch. > Looks good to me. Thanks, I will take that as a tested/reviewed-by tag and amend the patch with that when I queue it up. Kind regards Uffe > > Best regards, > Jean-Nicolas. > > On 7/23/19 2:28 PM, Ulf Hansson wrote: > > The code dealing with busy detection is somewhat complicated. In a way to > > make it a bit clearer, let's try to clarify the comments in the code about > > it. > > > > Additionally, move the part for clearing the so called busy start IRQ, to > > the place where the IRQ is actually delivered. Ideally, this should make > > the code a bit more robust. > > > > Finally, to improve understanding of the code and the sequence of the busy > > detection, move the corresponding code around a bit in mmci_cmd_irq(). > > > > Signed-off-by: Ulf Hansson <ulf.hansson@xxxxxxxxxx> > > --- > > > > Changes in v3: > > - Move some code arround to make it even more clear how the busy > > detection works. Updated the changelog accordingly. > > > > --- > > drivers/mmc/host/mmci.c | 69 ++++++++++++++++++++++------------------- > > 1 file changed, 37 insertions(+), 32 deletions(-) > > > > diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c > > index 356833a606d5..4c35e7609c89 100644 > > --- a/drivers/mmc/host/mmci.c > > +++ b/drivers/mmc/host/mmci.c > > @@ -1222,47 +1222,58 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, > > (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND))) > > return; > > > > - /* > > - * ST Micro variant: handle busy detection. > > - */ > > + /* Handle busy detection on DAT0 if the variant supports it. */ > > if (busy_resp && host->variant->busy_detect) { > > > > - /* We are busy with a command, return */ > > - if (host->busy_status && > > - (status & host->variant->busy_detect_flag)) > > - return; > > - > > /* > > - * We were not busy, but we now got a busy response on > > - * something that was not an error, and we double-check > > - * that the special busy status bit is still set before > > - * proceeding. > > + * Before unmasking for the busy end IRQ, confirm that the > > + * command was sent successfully. To keep track of having a > > + * command in-progress, waiting for busy signaling to end, > > + * store the status in host->busy_status. > > + * > > + * Note that, the card may need a couple of clock cycles before > > + * it starts signaling busy on DAT0, hence re-read the > > + * MMCISTATUS register here, to allow the busy bit to be set. > > + * Potentially we may even need to poll the register for a > > + * while, to allow it to be set, but tests indicates that it > > + * isn't needed. > > */ > > if (!host->busy_status && > > !(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) && > > (readl(base + MMCISTATUS) & host->variant->busy_detect_flag)) { > > > > - /* Clear the busy start IRQ */ > > - writel(host->variant->busy_detect_mask, > > - host->base + MMCICLEAR); > > - > > - /* Unmask the busy end IRQ */ > > writel(readl(base + MMCIMASK0) | > > host->variant->busy_detect_mask, > > base + MMCIMASK0); > > - /* > > - * Now cache the last response status code (until > > - * the busy bit goes low), and return. > > - */ > > + > > host->busy_status = > > status & (MCI_CMDSENT|MCI_CMDRESPEND); > > return; > > } > > > > /* > > - * At this point we are not busy with a command, we have > > - * not received a new busy request, clear and mask the busy > > - * end IRQ and fall through to process the IRQ. > > + * If there is a command in-progress that has been successfully > > + * sent, then bail out if busy status is set and wait for the > > + * busy end IRQ. > > + * > > + * Note that, the HW triggers an IRQ on both edges while > > + * monitoring DAT0 for busy completion, but there is only one > > + * status bit in MMCISTATUS for the busy state. Therefore > > + * both the start and the end interrupts needs to be cleared, > > + * one after the other. So, clear the busy start IRQ here. > > + */ > > + if (host->busy_status && > > + (status & host->variant->busy_detect_flag)) { > > + writel(host->variant->busy_detect_mask, > > + host->base + MMCICLEAR); > > + return; > > + } > > + > > + /* > > + * If there is a command in-progress that has been successfully > > + * sent and the busy bit isn't set, it means we have received > > + * the busy end IRQ. Clear and mask the IRQ, then continue to > > + * process the command. > > */ > > if (host->busy_status) { > > > > @@ -1508,14 +1519,8 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) > > } > > > > /* > > - * We intentionally clear the MCI_ST_CARDBUSY IRQ (if it's > > - * enabled) in mmci_cmd_irq() function where ST Micro busy > > - * detection variant is handled. Considering the HW seems to be > > - * triggering the IRQ on both edges while monitoring DAT0 for > > - * busy completion and that same status bit is used to monitor > > - * start and end of busy detection, special care must be taken > > - * to make sure that both start and end interrupts are always > > - * cleared one after the other. > > + * Busy detection is managed by mmci_cmd_irq(), including to > > + * clear the corresponding IRQ. > > */ > > status &= readl(host->base + MMCIMASK0); > > if (host->variant->busy_detect) >