Re: [PATCH V3] mmc: mmci: Clarify comments and some code for busy detection

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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)
>



[Index of Archives]     [Linux Memonry Technology]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux