summaryrefslogtreecommitdiff
path: root/drivers/mmc/host/mmci.h
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2023-06-16 23:42:23 +0300
committerUlf Hansson <ulf.hansson@linaro.org>2023-06-19 14:14:26 +0300
commit7be5ac5f7a4890422920d6d91f94fff5d114d076 (patch)
tree01b7d50cdae1c49055b716aaeb36c36664601db2 /drivers/mmc/host/mmci.h
parente1a2485cc367cd0efe6821e2d8deef863c4ba250 (diff)
downloadlinux-7be5ac5f7a4890422920d6d91f94fff5d114d076.tar.xz
mmc: mmci: Make busy complete state machine explicit
This refactors the ->busy_complete() callback currently only used by Ux500 and STM32 to handle busy detection on hardware where one and the same IRQ is fired whether we get a start or an end signal on busy detect. The code is currently using the cached status from the command IRQ in ->busy_status as a state to select what to do next: if this state is non-zero we are waiting for IRQs and if it is zero we treat the state as the starting point for a busy detect wait cycle. Make this explicit by creating a state machine where the ->busy_complete callback moves between three states. The Ux500 busy detect code currently assumes this order: we enable the busy detect IRQ, get a busy start IRQ, then a busy end IRQ, and then we clear and mask this IRQ and proceed. We insert debug prints for unexpected states. This works as before on most cards, however on a problematic card that is not working with busy detect, and which I have been debugging, the following happens a lot: [ 3.380554] mmci-pl18x 80005000.mmc: no busy signalling in time [ 3.387420] mmci-pl18x 80005000.mmc: no busy signalling in time [ 3.394561] mmci-pl18x 80005000.mmc: lost busy status when waiting for busy start IRQ This probably means that the busy detect start IRQ has already occurred when we start executing the ->busy_complete() callbacks, and the busy detect end IRQ is counted as the start IRQ, and this is what is causing the card to not be detected properly. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://lore.kernel.org/r/20230405-pl180-busydetect-fix-v7-5-69a7164f2a61@linaro.org Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc/host/mmci.h')
-rw-r--r--drivers/mmc/host/mmci.h14
1 files changed, 14 insertions, 0 deletions
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index e1a9b96a3396..12a7bbd3ce26 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -262,6 +262,19 @@ struct dma_chan;
struct mmci_host;
/**
+ * enum mmci_busy_state - enumerate the busy detect wait states
+ *
+ * This is used for the state machine waiting for different busy detect
+ * interrupts on hardware that fire a single IRQ for start and end of
+ * the busy detect phase on DAT0.
+ */
+enum mmci_busy_state {
+ MMCI_BUSY_WAITING_FOR_START_IRQ,
+ MMCI_BUSY_WAITING_FOR_END_IRQ,
+ MMCI_BUSY_DONE,
+};
+
+/**
* struct variant_data - MMCI variant-specific quirks
* @clkreg: default value for MCICLOCK register
* @clkreg_enable: enable value for MMCICLOCK register
@@ -409,6 +422,7 @@ struct mmci_host {
u32 clk_reg;
u32 clk_reg_add;
u32 datactrl_reg;
+ enum mmci_busy_state busy_state;
u32 busy_status;
u32 mask1_reg;
u8 vqmmc_enabled:1;