mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 20:22:09 +00:00
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:
parent
e85fecc386
commit
ddb5a92da5
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user