@@ -1222,19 +1222,30 @@ 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 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.
+ */
if (host->busy_status &&
(status & host->variant->busy_detect_flag))
return;
/*
* Before unmasking for the busy end IRQ, confirm that the
- * command was sent successfully.
+ * command was sent successfully. To keep track of having a
+ * command in-progress, while waiting for busy signaling to end,
+ * store the status in host->busy_status.
+ *
+ * Note that, since the HW seems to be triggering an IRQ on both
+ * edges while monitoring DAT0 for busy completion, but the same
+ * status bit in MMCISTATUS is used to monitor both 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.
*/
if (!host->busy_status &&
!(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) &&
@@ -1248,19 +1259,17 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
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 and the busy status 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) {
@@ -1506,14 +1515,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)
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. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> --- drivers/mmc/host/mmci.c | 43 ++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 20 deletions(-) -- 2.17.1