mmccam: Wait for the power to settle when probing a card

The mmc(4) stack waits after powering up a card: mmc_power_up() waits 1 ms
after the supplies are on and 2 ms after the clock is running, before the
first command is sent.  The MMCCAM probe had no such wait: it went from the
power_up request to the power_on request to CMD0 without any delay.

Some devices do not answer the first commands if they are sent too early and
then never enumerate, with no error.  On a RockPro64 the Broadcom SDIO Wi-Fi
(BCM4359) was not detected on any of 8 boots without a delay.  It was
detected on 8 out of 8 with the same waits as mmc_power_up() added to the
probe.

Add the same two waits, once the power_up request and once the power_on
request are done.  This replaces the delay that was in mmc_fdt_set_power(),
which was a fixed 10 ms for FDT hosts only; the waits of the legacy stack are
enough and apply to every MMCCAM host.

MFC after:	1 week
Reviewed by:	imp
Differential Revision:	https://reviews.freebsd.org/D61077
This commit is contained in:
Emmanuel Vadot committed 2026-11-05 15:51:36 +01:00
1 parent 604e2b5c2a
commit 1af3197bbe
1 file changed
+14
+14
View File
@@ -842,12 +842,26 @@ mmcprobe_done(struct cam_periph *periph, union ccb *done_ccb)
case PROBE_RESET_BUS:
{
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("done with PROBE_RESET_BUS\n"));
/*
* Let the supplies settle after the card is powered up before
* the clock is started, like mmc_power_up() does in the mmc(4)
* stack. This is a busy wait because it runs from the xpt done
* thread, where sleeping is not allowed.
*/
DELAY(1000);
PROBE_SET_ACTION(softc, PROBE_SET_ID_FREQ);
break;
}
case PROBE_SET_ID_FREQ:
{
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("done with PROBE_SET_ID_FREQ\n"));
/*
* The card needs at least 74 clock cycles, or 1 ms, with the
* clock running before it can take the first command. Wait for
* the same time as mmc_power_up() in the mmc(4) stack. Some
* cards (e.g. Broadcom SDIO Wi-Fi) are not detected without it.
*/
DELAY(2000);
PROBE_SET_ACTION(softc, PROBE_SET_CS);
break;
}