mmc: mmci: Use a switch statement machine

As is custom, use a big switch statement to transition
between the edges of the state machine inside
the ux500 ->busy_complete callback.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20230405-pl180-busydetect-fix-v7-8-69a7164f2a61@linaro.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
Linus Walleij 2023-06-16 22:42:26 +02:00 committed by Ulf Hansson
parent e85fecc386
commit ddb5a92da5

View file

@ -686,6 +686,12 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
goto out_ret_state;
}
/*
* The state transitions are encoded in a state machine crossing
* the edges in this switch statement.
*/
switch (host->busy_state) {
/*
* Before unmasking for the busy end IRQ, confirm that the
* command was sent successfully. To keep track of having a
@ -696,7 +702,7 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
* it starts signaling busy on DAT0, hence re-read the
* MMCISTATUS register here, to allow the busy bit to be set.
*/
if (host->busy_state == MMCI_BUSY_DONE) {
case MMCI_BUSY_DONE:
/*
* Save the first status register read to be sure to catch
* all bits that may be lost will retrying. If the command
@ -722,8 +728,7 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
writel(readl(base + MMCIMASK0) &
~host->variant->busy_detect_mask, base + MMCIMASK0);
host->busy_state = MMCI_BUSY_DONE;
goto out_ret_state;
}
break;
/*
* If there is a command in-progress that has been successfully
@ -736,12 +741,11 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
* 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_state == MMCI_BUSY_WAITING_FOR_START_IRQ) {
case MMCI_BUSY_WAITING_FOR_START_IRQ:
if (status & host->variant->busy_detect_flag) {
host->busy_status |= status & (MCI_CMDSENT | MCI_CMDRESPEND);
writel(host->variant->busy_detect_mask, base + MMCICLEAR);
host->busy_state = MMCI_BUSY_WAITING_FOR_END_IRQ;
goto out_ret_state;
} else {
dev_dbg(mmc_dev(host->mmc),
"lost busy status when waiting for busy start IRQ\n");
@ -750,23 +754,24 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
~host->variant->busy_detect_mask, base + MMCIMASK0);
host->busy_state = MMCI_BUSY_DONE;
host->busy_status = 0;
goto out_ret_state;
}
}
break;
if (host->busy_state == MMCI_BUSY_WAITING_FOR_END_IRQ) {
case MMCI_BUSY_WAITING_FOR_END_IRQ:
if (!(status & host->variant->busy_detect_flag)) {
host->busy_status |= status & (MCI_CMDSENT | MCI_CMDRESPEND);
host->busy_state = MMCI_BUSY_DONE;
goto out_ret_state;
} else {
dev_dbg(mmc_dev(host->mmc),
"busy status still asserted when handling busy end IRQ - will keep waiting\n");
goto out_ret_state;
}
}
break;
return true;
default:
dev_dbg(mmc_dev(host->mmc), "fell through on state %d\n",
host->busy_state);
break;
}
out_ret_state:
return (host->busy_state == MMCI_BUSY_DONE);