The branch stable/13 has been updated by mw:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=7518736826a2569e2799595d444cbdf0c9c82e5a

commit 7518736826a2569e2799595d444cbdf0c9c82e5a
Author:     Marcin Wojtas <m...@freebsd.org>
AuthorDate: 2021-05-27 18:39:12 +0000
Commit:     Marcin Wojtas <m...@freebsd.org>
CommitDate: 2022-03-07 15:59:50 +0000

    sdhci_xenon: improve the VCCQ voltage switch sequence
    
    Improve the VCCQ voltage switch, so that to properly
    handle the SDHCI_HOST_CONTROL2 register signaling
    flags and along with manipulating the regulator.
    
    Reviewed by: manu
    Obtained from: Semihalf
    Sponsored by: Marvell
    Differential Revision: https://reviews.freebsd.org/D30564
    MFC after: 2 weeks
    
    (cherry picked from commit c80e2ca57e0c1b3647b55471584c6d32214232ea)
---
 sys/dev/sdhci/sdhci_xenon.c | 84 ++++++++++++++++++++++++++++++++++++---------
 1 file changed, 68 insertions(+), 16 deletions(-)

diff --git a/sys/dev/sdhci/sdhci_xenon.c b/sys/dev/sdhci/sdhci_xenon.c
index f92d02608abb..42f36b619b36 100644
--- a/sys/dev/sdhci/sdhci_xenon.c
+++ b/sys/dev/sdhci/sdhci_xenon.c
@@ -388,35 +388,87 @@ sdhci_xenon_switch_vccq(device_t brdev, device_t reqdev)
 {
        struct sdhci_xenon_softc *sc;
        struct sdhci_slot *slot;
+       uint16_t hostctrl2;
        int uvolt, err;
 
+       slot = device_get_ivars(reqdev);
+
+       if (slot->version < SDHCI_SPEC_300)
+               return (0);
+
        sc = device_get_softc(brdev);
 
        if (sc->mmc_helper.vqmmc_supply == NULL)
                return EOPNOTSUPP;
 
-       slot = device_get_ivars(reqdev);
+       err = 0;
+
+       hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2);
        switch (slot->host.ios.vccq) {
-       case vccq_180:
-               uvolt = 1800000;
-               break;
        case vccq_330:
+               if (!(hostctrl2 & SDHCI_CTRL2_S18_ENABLE))
+                       return (0);
+               hostctrl2 &= ~SDHCI_CTRL2_S18_ENABLE;
+               bus_write_2(sc->mem_res, SDHCI_HOST_CONTROL2, hostctrl2);
+
                uvolt = 3300000;
-               break;
+               err = regulator_set_voltage(sc->mmc_helper.vqmmc_supply,
+                   uvolt, uvolt);
+               if (err != 0) {
+                       device_printf(sc->dev,
+                           "Cannot set vqmmc to %d<->%d\n",
+                           uvolt,
+                           uvolt);
+                       return (err);
+               }
+
+               /*
+                * According to the 'SD Host Controller Simplified
+                * Specification 4.20 the host driver should take more
+                * than 5ms for stable time of host voltage regulator
+                * from changing 1.8V Signaling Enable.
+                */
+               DELAY(5000);
+               hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2);
+               if (!(hostctrl2 & SDHCI_CTRL2_S18_ENABLE))
+                       return (0);
+               return EAGAIN;
+       case vccq_180:
+               if (!(slot->host.caps & MMC_CAP_SIGNALING_180)) {
+                       return EINVAL;
+               }
+               if (hostctrl2 & SDHCI_CTRL2_S18_ENABLE)
+                       return (0);
+               hostctrl2 |= SDHCI_CTRL2_S18_ENABLE;
+               bus_write_2(sc->mem_res, SDHCI_HOST_CONTROL2, hostctrl2);
+
+               uvolt = 1800000;
+               err = regulator_set_voltage(sc->mmc_helper.vqmmc_supply,
+                   uvolt, uvolt);
+               if (err != 0) {
+                       device_printf(sc->dev,
+                           "Cannot set vqmmc to %d<->%d\n",
+                           uvolt,
+                           uvolt);
+                       return (err);
+               }
+
+               /*
+                * According to the 'SD Host Controller Simplified
+                * Specification 4.20 the host driver should take more
+                * than 5ms for stable time of host voltage regulator
+                * from changing 1.8V Signaling Enable.
+                */
+               DELAY(5000);
+               hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2);
+               if (hostctrl2 & SDHCI_CTRL2_S18_ENABLE)
+                       return (0);
+               return EAGAIN;
        default:
+               device_printf(brdev,
+                   "Attempt to set unsupported signaling voltage\n");
                return EINVAL;
        }
-
-       err = regulator_set_voltage(sc->mmc_helper.vqmmc_supply, uvolt, uvolt);
-       if (err != 0) {
-               device_printf(sc->dev,
-                   "Cannot set vqmmc to %d<->%d\n",
-                   uvolt,
-                   uvolt);
-               return (err);
-       }
-
-       return (0);
 }
 
 static int

Reply via email to