summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2017-07-12 21:46:16 +0000
committermarius <marius@FreeBSD.org>2017-07-12 21:46:16 +0000
commit3d6ec55b9b8b214178308cd956202d62953d8b52 (patch)
treea7dc6a64b84698c92c34fe0741b953fa5710456e
parent19285e4939bf9d407078204de4e10a66650c6afa (diff)
downloadFreeBSD-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.c16
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);
OpenPOWER on IntegriCloud