Commit ddb5a92d authored by Linus Walleij's avatar Linus Walleij Committed by Ulf Hansson
Browse files

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: default avatarLinus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20230405-pl180-busydetect-fix-v7-8-69a7164f2a61@linaro.org


Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent e85fecc3
Loading
Loading
Loading
Loading
+17 −12
Original line number Diff line number Diff line
@@ -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);