git: 1f84b3a247bf - main - sdhci_fsl_fdt.c: Read supported voltages from dts.

Marcin Wojtas mw at FreeBSD.org
Fri May 14 08:53:24 UTC 2021


The branch main has been updated by mw:

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

commit 1f84b3a247bf4c0e584e36576a20dc120def1214
Author:     Marcin Wojtas <mw at FreeBSD.org>
AuthorDate: 2021-04-22 11:01:06 +0000
Commit:     Marcin Wojtas <mw at FreeBSD.org>
CommitDate: 2021-05-14 08:34:37 +0000

    sdhci_fsl_fdt.c: Read supported voltages from dts.
    
    We shouldn't overwrite capability register. Instead, voltages supported
    by the controller have to be read from dts, as the hardware doesn't
    report correct values.
    
    Submitted by: Lukasz Hajec <lha at semihalf.com>
    Reviewed by: manu
    Obtained from: Semihalf
    Sponsored by: Alstom Group
    Differential Revision: https://reviews.freebsd.org/D30123
---
 sys/dev/sdhci/sdhci_fsl_fdt.c | 73 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 65 insertions(+), 8 deletions(-)

diff --git a/sys/dev/sdhci/sdhci_fsl_fdt.c b/sys/dev/sdhci/sdhci_fsl_fdt.c
index c2330a679963..26092f662406 100644
--- a/sys/dev/sdhci/sdhci_fsl_fdt.c
+++ b/sys/dev/sdhci/sdhci_fsl_fdt.c
@@ -90,6 +90,9 @@ __FBSDID("$FreeBSD$");
 #define	SDHCI_FSL_ESDHC_CTRL_SNOOP	(1 << 6)
 #define	SDHCI_FSL_ESDHC_CTRL_CLK_DIV2	(1 << 19)
 
+#define SDHCI_FSL_CAN_VDD_MASK		\
+    (SDHCI_CAN_VDD_180 | SDHCI_CAN_VDD_300 | SDHCI_CAN_VDD_330)
+
 struct sdhci_fsl_fdt_softc {
 	device_t				dev;
 	const struct sdhci_fsl_fdt_soc_data	*soc_data;
@@ -295,18 +298,11 @@ sdhci_fsl_fdt_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off)
 
 	val32 = RD4(sc, off);
 
-	switch (off) {
-	case SDHCI_CAPABILITIES:
-		val32 &= ~(SDHCI_CAN_DO_SUSPEND | SDHCI_CAN_VDD_180);
-		break;
-	case SDHCI_PRESENT_STATE:
+	if (off == SDHCI_PRESENT_STATE) {
 		wrk32 = val32;
 		val32 &= SDHCI_FSL_PRES_COMPAT_MASK;
 		val32 |= (wrk32 >> 4) & SDHCI_STATE_DAT_MASK;
 		val32 |= (wrk32 << 1) & SDHCI_STATE_CMD;
-		break;
-	default:
-		break;
 	}
 
 	return (val32);
@@ -546,17 +542,78 @@ sdhci_fsl_fdt_get_card_present(device_t dev, struct sdhci_slot *slot)
 	return (sdhci_fdt_gpio_get_present(sc->gpio));
 }
 
+static uint32_t
+sdhci_fsl_fdt_vddrange_to_mask(device_t dev, uint32_t *vdd_ranges, int len)
+{
+	uint32_t vdd_min, vdd_max;
+	uint32_t vdd_mask = 0;
+	int i;
+
+	/* Ranges are organized as pairs of values. */
+	if ((len % 2) != 0) {
+		device_printf(dev, "Invalid voltage range\n");
+		return (0);
+	}
+	len = len / 2;
+
+	for (i = 0; i < len; i++) {
+		vdd_min = vdd_ranges[2 * i];
+		vdd_max = vdd_ranges[2 * i + 1];
+
+		if (vdd_min > vdd_max || vdd_min < 1650 || vdd_min > 3600 ||
+		    vdd_max < 1650 || vdd_max > 3600) {
+			device_printf(dev, "Voltage range %d - %d is out of bounds\n",
+			    vdd_min, vdd_max);
+			return (0);
+		}
+
+		if (vdd_min <= 1800 && vdd_max >= 1800)
+			vdd_mask |= SDHCI_CAN_VDD_180;
+		if (vdd_min <= 3000 && vdd_max >= 3000)
+			vdd_mask |= SDHCI_CAN_VDD_300;
+		if (vdd_min <= 3300 && vdd_max >= 3300)
+			vdd_mask |= SDHCI_CAN_VDD_330;
+	}
+
+	return (vdd_mask);
+}
+
 static void
 sdhci_fsl_fdt_of_parse(device_t dev)
 {
 	struct sdhci_fsl_fdt_softc *sc;
 	phandle_t node;
+	pcell_t *voltage_ranges;
+	uint32_t vdd_mask = 0;
+	ssize_t num_ranges;
 
 	sc = device_get_softc(dev);
 	node = ofw_bus_get_node(dev);
 
 	/* Call mmc_fdt_parse in order to get mmc related properties. */
 	mmc_fdt_parse(dev, node, &sc->fdt_helper, &sc->slot.host);
+
+	sc->slot.caps = sdhci_fsl_fdt_read_4(dev, &sc->slot,
+	    SDHCI_CAPABILITIES) & ~(SDHCI_CAN_DO_SUSPEND);
+	sc->slot.caps2 = sdhci_fsl_fdt_read_4(dev, &sc->slot,
+	    SDHCI_CAPABILITIES2);
+
+	/* Parse the "voltage-ranges" dts property. */
+	num_ranges = OF_getencprop_alloc(node, "voltage-ranges",
+	    (void **) &voltage_ranges);
+	if (num_ranges <= 0)
+		return;
+	vdd_mask = sdhci_fsl_fdt_vddrange_to_mask(dev, voltage_ranges,
+	    num_ranges / sizeof(uint32_t));
+	OF_prop_free(voltage_ranges);
+
+	/* Overwrite voltage caps only if we got something from dts. */
+	if (vdd_mask != 0 &&
+	    (vdd_mask != (sc->slot.caps & SDHCI_FSL_CAN_VDD_MASK))) {
+		sc->slot.caps &= ~(SDHCI_FSL_CAN_VDD_MASK);
+		sc->slot.caps |= vdd_mask;
+		sc->slot.quirks |= SDHCI_QUIRK_MISSING_CAPS;
+	}
 }
 
 static int


More information about the dev-commits-src-main mailing list