[Linux-stm32] [PATCH 00/13] Fix busydetect on Ux500 PL180/MMCI
Yann Gautier
yann.gautier at foss.st.com
Thu Apr 6 11:44:57 UTC 2023
On 4/6/23 11:27, Yann Gautier wrote:
> On 4/5/23 08:50, Linus Walleij wrote:
>> This series fixes a pretty serious problem in the MMCI
>> busy detect handling, discovered only after going up and
>> down a ladder of refactorings.
>>
>> The code is written expecting the Ux500 busy detect
>> to fire two interrupts: one at the start of the busy
>> signalling and one at the end of the busy signalling.
>>
>> The root cause of the problem seen on some devices
>> is that only the first IRQ arrives, and then the device
>> hangs, waiting perpetually for the next IRQ to arrive.
>>
>> This is eventually solved by adding a timeout using
>> a delayed work that fire after 10 ms if the busy detect
>> has not stopped at this point. (Other delay spans can
>> be suggested.) This is the last patch in the series.
>>
>> I included the rewrite of the entire busy detect logic
>> to use a state machine as this makes it way easier to
>> debug and will print messages about other error
>> conditions as well.
>>
>> The problem affects especially the Skomer
>> (Samsung GT-I9070) and Kyle (Samsung SGH-I407).
>>
>> It is fine to just apply this for the -next kernel,
>> despite it fixes the busy detect that has been broken
>> for these devices for a while, we can think about
>> backporting a simpler version of the timeout for
>> stable kernels if we want.
>>
>> Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
>> ---
>> Linus Walleij (13):
>> mmc: mmci: Only call busy_complete if callback defined
>> mmc: mmci: Clear busy_status when starting command
>> mmc: mmci: Unwind big if() clause
>> mmc: mmci: Stash status while waiting for busy
>> mmc: mmci: Break out error check in busy detect
>> mmc: mmci: Make busy complete state machine explicit
>> mmc: mmci: Retry the busy start condition
>> mmc: mmci: Use state machine state as exit condition
>> mmc: mmci: Use a switch statement machine
>> mmc: mmci: Break out a helper function
>> mmc: mmci: mmci_card_busy() from state machine
>> mmc: mmci: Drop end IRQ from Ux500 busydetect
>> mmc: mmci: Add busydetect timeout
>>
>> drivers/mmc/host/mmci.c | 165
>> +++++++++++++++++++++++++++---------
>> drivers/mmc/host/mmci.h | 17 ++++
>> drivers/mmc/host/mmci_stm32_sdmmc.c | 6 +-
>> 3 files changed, 149 insertions(+), 39 deletions(-)
>> ---
>> base-commit: fe15c26ee26efa11741a7b632e9f23b01aca4cc6
>> change-id: 20230405-pl180-busydetect-fix-66a0360d398a
>>
>> Best regards,
>
> Hi Linus,
>
> With this series, it is no more possible to switch to UHS modes on
> STM32MP1. I will add some traces and try to see what's wrong or missing
> to have it working again.
> I've tested on STM32MP157F-EV1 board and got those traces:
> [ 3.186504] mmc0: Skipping voltage switch
> [ 3.302170] mmc0: new high speed SDHC card at address aaaa
>
> Whereas with the previous version I had:
> [ 1.882084] mmc0: new ultra high speed DDR50 SDHC card at address aaaa
> [ 1.899142] mmcblk0: mmc0:aaaa SC16G 14.8 GiB
>
> On STM32MP13 that can do SDR104 (tested on an internal board), it fails
> to initialized the card:
> [ 3.194072] mmc0: error -110 whilst initialising SD card
>
> When adding some dynamic debug traces, I can see this in the trace:
> [ 78.039648] mmc0: Signal voltage switch failed, power cycling card
>
> I'll try to add more traces to see what happens exactly.
>
>
> Best regards,
> Yann
Hi,
The issue occurs in mmc_set_uhs_voltage(), when calling
host->ops->card_busy(), which is mmci_card_busy() for this driver.
It is expected here to return busy after the SD_SWITCH_VOLTAGE (CMD11),
but host->busy_state = 0 in mmci_card_busy(), so it return 0.
A possible correction, but that may break what you've done, could be:
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 3ff6655a56d1..006fd84090ac 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -340,13 +340,10 @@ static int mmci_card_busy(struct mmc_host *mmc)
unsigned long flags;
int busy = 0;
- if (host->ops->busy_complete) {
- if ((host->busy_state == MMCI_BUSY_IDLE) ||
- (host->busy_state == MMCI_BUSY_DONE))
- return 0;
- else
- return 1;
- }
+ if (host->ops->busy_complete &&
+ host->busy_state != MMCI_BUSY_IDLE &&
+ host->busy_state != MMCI_BUSY_DONE)
+ return 1;
spin_lock_irqsave(&host->lock, flags);
The SD-card is now properly detected (and in SDR104 mode) on STM32MP13
board.
Best regards,
Yann
More information about the Linux-stm32
mailing list