sdcard emmc2 speed - #970
Merged
Kalamatee merged 6 commits intoAug 9, 2026
Merged
Conversation
WaitCmd() slept on the completion signal unconditionally, so a controller whose interrupt never arrives wedged the boot instead of reporting a timeout. Run the handler from the polling path until a real interrupt has proved the line works. Ported from work by John Knipper.
The wrapper that records a working interrupt line called the SDHCI handler by name instead of dispatching through the bus, so the SDHOST bus - which uses a different register layout and leaves the SDHCI accessors NULL - crashed as soon as an interrupt arrived. Dispatch through sdcb_BusIRQHandler, and treat it as optional, the way BusTask already does. Introduced when the polling fallback was brought in.
GETCLKRATE answers with the rate the clock is running at, and on BCM2711 the EMMC2 clock is parked until something asks for it - so the driver read a maximum of 0Hz, never clocked the card, and the bus task sat there until the boot wait gave up. Fall back to GETMAXCLKRATE.
The divider ran against the mailbox's maximum of 500MHz while the block runs off 100MHz, and read the register as a plain divisor rather than SDHCI's base/(2N), so the card was clocked at 5.5MHz instead of 50. High speed timing is selected too, which the card needs above 25MHz.
Waiting a millisecond at a time cost more than the work being waited for: a 64K transfer takes about 2.7ms, so one overshoot was a quarter of it. The waits now run at 25us and the timeouts are measured against the system timer rather than counted in loop iterations, so the callers' limits are unchanged.
PIO reads a block at a time from inside the interrupt handler, which holds the machine for as long as the transfer lasts - 2.7ms for every 64K. ADMA2 is used where the controller offers it, and proves itself against a PIO read of the same sectors at startup before anything relies on it.
Kalamatee
approved these changes
Aug 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes:
GETCLKRATEreports the EMMC2 clock as parked (0), so the driver asked themailbox what the clock could do and got 500MHz. That is not what the SDHCI
divider divides — the controller reports its own base clock in CAPABILITIES,
and on this SoC it is 100MHz.
FinishData()andWaitCmd()slept a millisecond at a time. A 64K transfertakes about 2.7ms, so a single overshoot cost a quarter of it. Polling now
runs at 25us, and the timeouts are measured against the system timer instead
of counted in loop iterations, so the callers' limits are unchanged.
Added ADMA2 support in addition to PIO