Index: sys/dev/mmc/mmc.c =================================================================== --- sys/dev/mmc/mmc.c +++ sys/dev/mmc/mmc.c @@ -958,17 +958,32 @@ mmc_set_vccq(struct mmc_softc *sc, struct mmc_ivars *ivar, enum mmc_bus_timing timing) { - - if (isset(&ivar->vccq_120, timing)) + if (isset(&ivar->vccq_120, timing)) { mmcbr_set_vccq(sc->dev, vccq_120); - else if (isset(&ivar->vccq_180, timing)) + if (mmcbr_switch_vccq(sc->dev) == 0) + return (MMC_ERR_NONE); + + /* Failed to switch to 1.2V, disabling it for this timing */ + clrbit(&ivar->vccq_120, timing); + } + + if (isset(&ivar->vccq_180, timing)) { mmcbr_set_vccq(sc->dev, vccq_180); - else + if (mmcbr_switch_vccq(sc->dev) == 0) + return (MMC_ERR_NONE); + + /* Failed to switch to 1.8V, disabling it for this timing */ + clrbit(&ivar->vccq_180, timing); + } + + if (timing == bus_timing_normal || timing == bus_timing_hs) { + /* Only these two run on 3.3V */ mmcbr_set_vccq(sc->dev, vccq_330); - if (mmcbr_switch_vccq(sc->dev) != 0) - return (MMC_ERR_INVALID); - else - return (MMC_ERR_NONE); + if (mmcbr_switch_vccq(sc->dev) == 0) + return (MMC_ERR_NONE); + } + + return (MMC_ERR_INVALID); } static const uint8_t p8[8] = { @@ -2120,6 +2135,8 @@ dev = sc->dev; max_dtr = mmcbr_get_f_max(dev); max_timing = bus_timing_max; + +again: do { changed = false; for (i = 0; i < sc->child_count; i++) { @@ -2151,6 +2168,12 @@ mmc_timing_to_string(max_timing)); } + /* + * We deselect the card in case we failed to switch + * timing in the previous try on the first card + */ + (void)mmc_select_card(sc, 0); + /* * HS400 must be tuned in HS200 mode, so in case of HS400 we begin * with HS200 following the sequence as described in "6.6.2.2 HS200 @@ -2178,7 +2201,8 @@ if (mmc_set_vccq(sc, ivar, timing) != MMC_ERR_NONE) { device_printf(dev, "Failed to set VCCQ for " "card at relative address %d\n", rca); - continue; + max_timing = timing - 1; + goto again; } } @@ -2226,7 +2250,8 @@ if (mmc_set_vccq(sc, ivar, timing) != MMC_ERR_NONE) { device_printf(dev, "Failed to set VCCQ for " "card at relative address %d\n", rca); - continue; + max_timing = timing - 1; + goto again; } }