Improve how quirks are handled on sdhc(4)-compatible drivers. So far
authorpatrick <patrick@openbsd.org>
Tue, 18 Jan 2022 11:36:21 +0000 (11:36 +0000)
committerpatrick <patrick@openbsd.org>
Tue, 18 Jan 2022 11:36:21 +0000 (11:36 +0000)
we have passed a modified version of the contents in the capabilities
register if we wanted to override what sdhc(4) would otherwise read.
Unfortunately there's a second capabilities register that we did not
yet take into consideration, which is why to disable DDR50 support we
created a quirk flag in the softc.  The sdhc(4) ACPI nodes have a way
to mask and set bits in both of the capabilities register, which is a
flexible approach to solving that issue and using that for our sdhc(4)
drivers even improves readability.

ok kettenis@

sys/arch/armv7/marvell/mvpxa.c
sys/dev/acpi/sdhc_acpi.c
sys/dev/fdt/cdsdhc.c
sys/dev/fdt/sdhc_fdt.c
sys/dev/pci/sdhc_pci.c
sys/dev/sdmmc/sdhc.c
sys/dev/sdmmc/sdhcvar.h

index 27aaef3..aaa2b93 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: mvpxa.c,v 1.3 2021/10/24 17:52:27 mpi Exp $   */
+/*     $OpenBSD: mvpxa.c,v 1.4 2022/01/18 11:36:21 patrick Exp $       */
 /*
  * Copyright (c) 2017 Mark Kettenis
  * Copyright (c) 2017 Patrick Wildt <patrick@blueri.se>
@@ -111,7 +111,7 @@ mvpxa_attach(struct device *parent, struct device *self, void *aux)
 {
        struct mvpxa_softc *sc = (struct mvpxa_softc *)self;
        struct fdt_attach_args *faa = aux;
-       uint32_t caps;
+       uint64_t capmask = 0, capset = 0;
 
        if (faa->fa_nreg < 3) {
                printf(": not enough registers\n");
@@ -162,11 +162,11 @@ mvpxa_attach(struct device *parent, struct device *self, void *aux)
        sc->sc.sc_host = &sc->sc_host;
        sc->sc.sc_dmat = faa->fa_dmat;
 
-       caps = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SDHC_CAPABILITIES);
        if (OF_getproplen(faa->fa_node, "no-1-8-v") >= 0)
-               caps &= ~SDHC_VOLTAGE_SUPP_1_8V;
+               capmask |= SDHC_VOLTAGE_SUPP_1_8V;
 
-       sdhc_host_found(&sc->sc, sc->sc_iot, sc->sc_ioh, sc->sc_size, 1, caps);
+       sdhc_host_found(&sc->sc, sc->sc_iot, sc->sc_ioh, sc->sc_size, 1,
+           capmask, capset);
        return;
 
 unmap:
index 0e3a633..17931f0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sdhc_acpi.c,v 1.19 2021/12/21 20:53:46 kettenis Exp $ */
+/*     $OpenBSD: sdhc_acpi.c,v 1.20 2022/01/18 11:36:21 patrick Exp $  */
 /*
  * Copyright (c) 2016 Mark Kettenis
  *
@@ -88,7 +88,7 @@ sdhc_acpi_attach(struct device *parent, struct device *self, void *aux)
        struct sdhc_acpi_softc *sc = (struct sdhc_acpi_softc *)self;
        struct acpi_attach_args *aaa = aux;
        struct aml_value res;
-       uint32_t cap, capmask;
+       uint64_t capmask, capset;
 
        sc->sc_acpi = (struct acpi_softc *)parent;
        sc->sc_node = aaa->aaa_node;
@@ -135,13 +135,8 @@ sdhc_acpi_attach(struct device *parent, struct device *self, void *aux)
        sdhc_acpi_power_on(sc, sc->sc_node);
        sdhc_acpi_explore(sc);
 
-       cap = acpi_getpropint(sc->sc_node, "sdhci-caps", 0);
        capmask = acpi_getpropint(sc->sc_node, "sdhci-caps-mask", 0);
-       if (capmask != 0) {
-               cap = bus_space_read_4(sc->sc_memt, sc->sc_memh,
-                   SDHC_CAPABILITIES);
-               cap &= ~capmask;
-       }
+       capset = acpi_getpropint(sc->sc_node, "sdhci-caps", 0);
 
        /* Raspberry Pi4 "emmc2" controller. */
        if (strcmp(aaa->aaa_dev, "BRCME88C") == 0)
@@ -152,7 +147,7 @@ sdhc_acpi_attach(struct device *parent, struct device *self, void *aux)
        sc->sc.sc_clkbase = acpi_getpropint(sc->sc_node,
            "clock-frequency", 0) / 1000;
        sdhc_host_found(&sc->sc, sc->sc_memt, sc->sc_memh,
-           aaa->aaa_size[0], 1, cap);
+           aaa->aaa_size[0], 1, capmask, capset);
 }
 
 int
index df3b760..6c31225 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cdsdhc.c,v 1.1 2022/01/18 07:53:39 visa Exp $ */
+/*     $OpenBSD: cdsdhc.c,v 1.2 2022/01/18 11:36:21 patrick Exp $      */
 
 /*
  * Copyright (c) 2022 Visa Hankala
@@ -97,7 +97,7 @@ cdsdhc_attach(struct device *parent, struct device *self, void *aux)
 {
        struct fdt_attach_args *faa = aux;
        struct cdsdhc_softc *sc = (struct cdsdhc_softc *)self;
-       uint32_t caps = 0;
+       uint64_t capmask = 0, capset = 0;
        uint32_t ver;
 
        sc->sc_iot = faa->fa_iot;
@@ -131,7 +131,7 @@ cdsdhc_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_sdhc.sc_dmat = faa->fa_dmat;
        sc->sc_sdhc.sc_bus_clock_pre = cdsdhc_bus_clock_pre;
        sdhc_host_found(&sc->sc_sdhc, sc->sc_iot, sc->sc_srs_ioh, SRS_SIZE,
-           1, caps);
+           1, capmask, capset);
        return;
 
 disable:
index 2ca8757..67b4015 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sdhc_fdt.c,v 1.18 2021/10/24 17:52:27 mpi Exp $       */
+/*     $OpenBSD: sdhc_fdt.c,v 1.19 2022/01/18 11:36:21 patrick Exp $   */
 /*
  * Copyright (c) 2017 Mark Kettenis
  *
@@ -140,7 +140,8 @@ sdhc_fdt_attach(struct device *parent, struct device *self, void *aux)
        struct sdhc_fdt_softc *sc = (struct sdhc_fdt_softc *)self;
        struct fdt_attach_args *faa = aux;
        struct regmap *rm = NULL;
-       uint32_t reg, phandle, freq, cap = 0;
+       uint64_t capmask = 0, capset = 0;
+       uint32_t reg, phandle, freq;
        char pad_type[16] = { 0 };
 
        if (faa->fa_nreg < 1) {
@@ -230,7 +231,7 @@ sdhc_fdt_attach(struct device *parent, struct device *self, void *aux)
                sc->sc.sc_flags |= SDHC_F_NOPWR0;
 
                /* XXX Doesn't work on Rockchip RK3399. */
-               sc->sc.sc_flags |= SDHC_F_NODDR50;
+               capmask |= (uint64_t)SDHC_DDR50_SUPP << 32;
        }
 
        if (OF_is_compatible(faa->fa_node, "arasan,sdhci-8.9a")) {
@@ -242,8 +243,9 @@ sdhc_fdt_attach(struct device *parent, struct device *self, void *aux)
                sc->sc.sc_flags |= SDHC_F_NOPWR0;
 
        if (OF_is_compatible(faa->fa_node, "brcm,bcm2835-sdhci")) {
-               cap = SDHC_VOLTAGE_SUPP_3_3V | SDHC_HIGH_SPEED_SUPP;
-               cap |= SDHC_MAX_BLK_LEN_1024 << SDHC_MAX_BLK_LEN_SHIFT;
+               capmask = 0xffffffff;
+               capset = SDHC_VOLTAGE_SUPP_3_3V | SDHC_HIGH_SPEED_SUPP;
+               capset |= SDHC_MAX_BLK_LEN_1024 << SDHC_MAX_BLK_LEN_SHIFT;
 
                freq = clock_get_frequency(faa->fa_node, NULL);
                sc->sc.sc_clkbase = freq / 1000;
@@ -278,13 +280,11 @@ sdhc_fdt_attach(struct device *parent, struct device *self, void *aux)
                        }
                }
 
-               cap = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
-                   SDHC_CAPABILITIES);
                if (OF_getpropint(faa->fa_node, "bus-width", 1) != 8)
-                       cap &= ~SDHC_8BIT_MODE_SUPP;
+                       capmask |= SDHC_8BIT_MODE_SUPP;
                if (OF_getproplen(faa->fa_node, "no-1-8-v") == 0) {
-                       cap &= ~SDHC_VOLTAGE_SUPP_1_8V;
-                       sc->sc.sc_flags |= SDHC_F_NODDR50;
+                       capmask |= SDHC_VOLTAGE_SUPP_1_8V;
+                       capmask |= (uint64_t)SDHC_DDR50_SUPP << 32;
                }
                if (OF_getproplen(faa->fa_node,
                    "marvell,xenon-phy-slow-mode") == 0)
@@ -318,7 +318,8 @@ sdhc_fdt_attach(struct device *parent, struct device *self, void *aux)
                sc->sc.sc_bus_clock_post = sdhc_fdt_xenon_bus_clock_post;
        }
 
-       sdhc_host_found(&sc->sc, sc->sc_iot, sc->sc_ioh, sc->sc_size, 1, cap);
+       sdhc_host_found(&sc->sc, sc->sc_iot, sc->sc_ioh, sc->sc_size, 1,
+           capmask, capset);
        return;
 
 unmap:
index 7d83836..de582cc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sdhc_pci.c,v 1.22 2022/01/11 21:41:15 jsg Exp $       */
+/*     $OpenBSD: sdhc_pci.c,v 1.23 2022/01/18 11:36:21 patrick Exp $   */
 
 /*
  * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -110,7 +110,6 @@ sdhc_pci_attach(struct device *parent, struct device *self, void *aux)
        bus_space_tag_t iot;
        bus_space_handle_t ioh;
        bus_size_t size;
-       u_int32_t caps = 0;
 
        sc->sc_pc = pa->pa_pc;
        sc->sc_tag = pa->pa_tag;
@@ -183,7 +182,7 @@ sdhc_pci_attach(struct device *parent, struct device *self, void *aux)
                        break;
                }
 
-               if (sdhc_host_found(&sc->sc, iot, ioh, size, usedma, caps) != 0)
+               if (sdhc_host_found(&sc->sc, iot, ioh, size, usedma, 0, 0) != 0)
                        printf("%s at 0x%x: can't initialize host\n",
                            sc->sc.sc_dev.dv_xname, reg);
 
index 6e6847b..46c2ab4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sdhc.c,v 1.71 2021/09/11 22:42:12 mglocker Exp $      */
+/*     $OpenBSD: sdhc.c,v 1.72 2022/01/18 11:36:21 patrick Exp $       */
 
 /*
  * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -238,10 +238,12 @@ sdhc_write_2(struct sdhc_host *hp, bus_size_t offset, uint16_t value)
  */
 int
 sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
-    bus_space_handle_t ioh, bus_size_t iosize, int usedma, u_int32_t caps)
+    bus_space_handle_t ioh, bus_size_t iosize, int usedma, uint64_t capmask,
+    uint64_t capset)
 {
        struct sdmmcbus_attach_args saa;
        struct sdhc_host *hp;
+       uint32_t caps;
        int error = 1;
        int max_clock;
 
@@ -267,8 +269,9 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
        (void)sdhc_host_reset(hp);
 
        /* Determine host capabilities. */
-       if (caps == 0)
-               caps = HREAD4(hp, SDHC_CAPABILITIES);
+       caps = HREAD4(hp, SDHC_CAPABILITIES);
+       caps &= ~capmask;
+       caps |= capset;
 
        /* Use DMA if the host system and the controller support it. */
        if (usedma && ISSET(caps, SDHC_ADMA2_SUPP)) {
@@ -404,6 +407,8 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
 
        if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3) {
                uint32_t caps2 = HREAD4(hp, SDHC_CAPABILITIES2);
+               caps2 &= ~(capmask >> 32);
+               caps2 |= capset >> 32;
 
                if (ISSET(caps, SDHC_8BIT_MODE_SUPP))
                        saa.caps |= SMC_CAPS_8BIT_MODE;
@@ -412,9 +417,6 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
                        saa.caps |= SMC_CAPS_MMC_DDR52;
        }
 
-       if (ISSET(sc->sc_flags, SDHC_F_NODDR50))
-               saa.caps &= ~SMC_CAPS_MMC_DDR52;
-
        if (ISSET(sc->sc_flags, SDHC_F_NONREMOVABLE))
                saa.caps |= SMC_CAPS_NONREMOVABLE;
 
index 831ac2e..fd96416 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sdhcvar.h,v 1.15 2021/09/11 22:42:12 mglocker Exp $   */
+/*     $OpenBSD: sdhcvar.h,v 1.16 2022/01/18 11:36:21 patrick Exp $    */
 
 /*
  * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -40,7 +40,7 @@ struct sdhc_softc {
 
 /* Host controller functions called by the attachment driver. */
 int    sdhc_host_found(struct sdhc_softc *, bus_space_tag_t,
-           bus_space_handle_t, bus_size_t, int, u_int32_t);
+           bus_space_handle_t, bus_size_t, int, uint64_t, uint64_t);
 int    sdhc_activate(struct device *, int);
 void   sdhc_shutdown(void *);
 int    sdhc_intr(void *);
@@ -49,9 +49,8 @@ void  sdhc_needs_discover(struct sdhc_softc *);
 
 /* flag values */
 #define SDHC_F_NOPWR0          (1 << 0)
-#define SDHC_F_NODDR50         (1 << 1)
-#define SDHC_F_NONREMOVABLE    (1 << 2)
-#define SDHC_F_32BIT_ACCESS    (1 << 3)
-#define SDHC_F_NO_HS_BIT       (1 << 4)
+#define SDHC_F_NONREMOVABLE    (1 << 1)
+#define SDHC_F_32BIT_ACCESS    (1 << 2)
+#define SDHC_F_NO_HS_BIT       (1 << 3)
 
 #endif