The branch main has been updated by wma:

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

commit ec9333c3aac300d15009df9f24fe5cf37852578b
Author:     Artur Rojek <a...@semihalf.com>
AuthorDate: 2021-09-10 16:03:19 +0000
Commit:     Wojciech Macek <w...@freebsd.org>
CommitDate: 2021-12-08 10:21:02 +0000

    sdhci_fsl_fdt: Fix vccq reconfiguration
    
    As `vqmmc-supply` is an optional Device Tree property, don't skip vccq
    reconfiguration when the regulator is not specified. Instead, accept
    voltage specified by the `voltage-ranges` property.
    
    The actual voltage switch is done through a hw register in LS1028A.
    Add errata flag for other boards, as they are not supported. Return
    not supported error code when switching to 1.8V on affected platforms.
    
    Fixes: b08bf4c35ca ("sdhci_fsl_fdt: Skip vccq reconfiguration without 
regulator")
    
    Co-authored-by: Artur Rojek <a...@semihalf.com>
    
    Reviewed by:            manu, mw
    Obtained from:          Semihalf
    Sponsored by:           Alstom Group
    Differential revision:  https://reviews.freebsd.org/D33319
---
 sys/dev/sdhci/sdhci_fsl_fdt.c | 44 +++++++++++++++++++++++++++++--------------
 1 file changed, 30 insertions(+), 14 deletions(-)

diff --git a/sys/dev/sdhci/sdhci_fsl_fdt.c b/sys/dev/sdhci/sdhci_fsl_fdt.c
index 2d6c7115ff1e..d17811634353 100644
--- a/sys/dev/sdhci/sdhci_fsl_fdt.c
+++ b/sys/dev/sdhci/sdhci_fsl_fdt.c
@@ -70,6 +70,7 @@ __FBSDID("$FreeBSD$");
 #define        SDHCI_FSL_PROT_CTRL_BYTE_NATIVE (2 << 4)
 #define        SDHCI_FSL_PROT_CTRL_BYTE_MASK   (3 << 4)
 #define        SDHCI_FSL_PROT_CTRL_DMA_MASK    (3 << 8)
+#define        SDHCI_FSL_PROT_CTRL_VOLT_SEL    (1 << 10)
 
 #define        SDHCI_FSL_SYS_CTRL              0x2c
 #define        SDHCI_FSL_CLK_IPGEN             (1 << 0)
@@ -102,6 +103,8 @@ __FBSDID("$FreeBSD$");
 
 /* Some platforms do not detect pulse width correctly. */
 #define SDHCI_FSL_UNRELIABLE_PULSE_DET (1 << 0)
+/* On some platforms switching voltage to 1.8V is not supported */
+#define SDHCI_FSL_UNSUPP_1_8V          (1 << 1)
 
 struct sdhci_fsl_fdt_softc {
        device_t                                dev;
@@ -132,7 +135,7 @@ struct sdhci_fsl_fdt_soc_data {
 static const struct sdhci_fsl_fdt_soc_data sdhci_fsl_fdt_ls1012a_soc_data = {
        .quirks = 0,
        .baseclk_div = 1,
-       .errata = 0
+       .errata = SDHCI_FSL_UNSUPP_1_8V,
 };
 
 static const struct sdhci_fsl_fdt_soc_data sdhci_fsl_fdt_ls1028a_soc_data = {
@@ -145,6 +148,7 @@ static const struct sdhci_fsl_fdt_soc_data 
sdhci_fsl_fdt_ls1028a_soc_data = {
 static const struct sdhci_fsl_fdt_soc_data sdhci_fsl_fdt_ls1046a_soc_data = {
        .quirks = SDHCI_QUIRK_DONT_SET_HISPD_BIT | SDHCI_QUIRK_BROKEN_AUTO_STOP,
        .baseclk_div = 2,
+       .errata = SDHCI_FSL_UNSUPP_1_8V,
 };
 
 static const struct sdhci_fsl_fdt_soc_data sdhci_fsl_fdt_gen_data = {
@@ -517,34 +521,46 @@ sdhci_fsl_fdt_switch_vccq(device_t brdev, device_t reqdev)
 {
        struct sdhci_fsl_fdt_softc *sc;
        struct sdhci_slot *slot;
+       regulator_t vqmmc_supply;
+       uint32_t val_old, val;
        int uvolt, err;
 
        sc = device_get_softc(brdev);
+       slot = device_get_ivars(reqdev);
 
-       if (sc->fdt_helper.vqmmc_supply == NULL)
-               return EOPNOTSUPP;
-
-       err = sdhci_generic_switch_vccq(brdev, reqdev);
-       if (err != 0)
-               return (err);
+       val_old = val = RD4(sc, SDHCI_FSL_PROT_CTRL);
 
-       slot = device_get_ivars(reqdev);
        switch (slot->host.ios.vccq) {
        case vccq_180:
+               if (sc->soc_data->errata & SDHCI_FSL_UNSUPP_1_8V)
+                       return (EOPNOTSUPP);
+
+               val |= SDHCI_FSL_PROT_CTRL_VOLT_SEL;
                uvolt = 1800000;
                break;
        case vccq_330:
+               val &= ~SDHCI_FSL_PROT_CTRL_VOLT_SEL;
                uvolt = 3300000;
                break;
        default:
-               return EINVAL;
+               return (EOPNOTSUPP);
        }
 
-       err = regulator_set_voltage(sc->fdt_helper.vqmmc_supply, uvolt, uvolt);
-       if (err != 0) {
-               device_printf(sc->dev,
-                   "Cannot set vqmmc to %d<->%d\n", uvolt, uvolt);
-               return (err);
+       WR4(sc, SDHCI_FSL_PROT_CTRL, val);
+
+       vqmmc_supply = sc->fdt_helper.vqmmc_supply;
+       /*
+        * Even though we expect to find a fixed regulator in this controller
+        * family, let's play safe.
+        */
+       if (vqmmc_supply != NULL) {
+               err = regulator_set_voltage(vqmmc_supply, uvolt, uvolt);
+               if (err != 0) {
+                       device_printf(sc->dev,
+                           "Cannot set vqmmc to %d<->%d\n", uvolt, uvolt);
+                       WR4(sc, SDHCI_FSL_PROT_CTRL, val_old);
+                       return (err);
+               }
        }
 
        return (0);

Reply via email to