git: ec9333c3aac3 - main - sdhci_fsl_fdt: Fix vccq reconfiguration
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 08 Dec 2021 10:21:33 UTC
The branch main has been updated by wma: URL: https://cgit.FreeBSD.org/src/commit/?id=ec9333c3aac300d15009df9f24fe5cf37852578b commit ec9333c3aac300d15009df9f24fe5cf37852578b Author: Artur Rojek <ar@semihalf.com> AuthorDate: 2021-09-10 16:03:19 +0000 Commit: Wojciech Macek <wma@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 <ar@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);