diff options
author | marius <marius@FreeBSD.org> | 2017-07-12 21:46:16 +0000 |
---|---|---|
committer | marius <marius@FreeBSD.org> | 2017-07-12 21:46:16 +0000 |
commit | 3d6ec55b9b8b214178308cd956202d62953d8b52 (patch) | |
tree | a7dc6a64b84698c92c34fe0741b953fa5710456e | |
parent | 19285e4939bf9d407078204de4e10a66650c6afa (diff) | |
download | FreeBSD-src-3d6ec55b9b8b214178308cd956202d62953d8b52.zip FreeBSD-src-3d6ec55b9b8b214178308cd956202d62953d8b52.tar.gz |
MF11: r320898; MFC: r320577, r320620
Retry up to 2 ms to enable bus power as at least with some Intel
SDHCI/eMMC controllers the first attempt after a D3 to D0 transition,
i. e. when the firmware has put the devices into D3 state before,
can fail.
Approved by: re (gjb)
-rw-r--r-- | sys/dev/sdhci/sdhci.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c index 26602ec..52415e4 100644 --- a/sys/dev/sdhci/sdhci.c +++ b/sys/dev/sdhci/sdhci.c @@ -366,6 +366,7 @@ sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock) static void sdhci_set_power(struct sdhci_slot *slot, u_char power) { + int i; uint8_t pwr; if (slot->power == power) @@ -394,9 +395,20 @@ sdhci_set_power(struct sdhci_slot *slot, u_char power) break; } WR1(slot, SDHCI_POWER_CONTROL, pwr); - /* Turn on the power. */ + /* + * Turn on VDD1 power. Note that at least some Intel controllers can + * fail to enable bus power on the first try after transiting from D3 + * to D0, so we give them up to 2 ms. + */ pwr |= SDHCI_POWER_ON; - WR1(slot, SDHCI_POWER_CONTROL, pwr); + for (i = 0; i < 20; i++) { + WR1(slot, SDHCI_POWER_CONTROL, pwr); + if (RD1(slot, SDHCI_POWER_CONTROL) & SDHCI_POWER_ON) + break; + DELAY(100); + } + if (!(RD1(slot, SDHCI_POWER_CONTROL) & SDHCI_POWER_ON)) + slot_printf(slot, "Bus power failed to enable"); if (slot->quirks & SDHCI_QUIRK_INTEL_POWER_UP_RESET) { WR1(slot, SDHCI_POWER_CONTROL, pwr | 0x10); |