aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarius Strobl <marius@FreeBSD.org>2017-07-12 21:46:16 +0000
committerMarius Strobl <marius@FreeBSD.org>2017-07-12 21:46:16 +0000
commitd71b36cda154752729018a6317ae29024db3b0e1 (patch)
treea7dc6a64b84698c92c34fe0741b953fa5710456e
parentf29656e2ea6679cee2ce2178cc37b117c48d0a6a (diff)
downloadsrc-d71b36cda154752729018a6317ae29024db3b0e1.tar.gz
src-d71b36cda154752729018a6317ae29024db3b0e1.zip
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)
Notes
Notes: svn path=/releng/11.1/; revision=320922
-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 26602ec57b4c..52415e405c4b 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);