Unless I'm missing something, dwmmc has no mechanism for detecting 
card changes on removable devices?

This sets up the gpio interrupt if there is a cd-gpios value and 
also unmasks SDMMC_RINTSTS_CDT to get those card detect transition 
interrupts from the device.

This makes card insertion and removal work on my RK3128 device.


diff --git sys/dev/fdt/dwmmc.c sys/dev/fdt/dwmmc.c
index 073052599db..9eee1764347 100644
--- sys/dev/fdt/dwmmc.c
+++ sys/dev/fdt/dwmmc.c
@@ -236,6 +236,7 @@ int dwmmc_intr(void *);
 int    dwmmc_host_reset(sdmmc_chipset_handle_t);
 uint32_t dwmmc_host_ocr(sdmmc_chipset_handle_t);
 int    dwmmc_host_maxblklen(sdmmc_chipset_handle_t);
+int    dwmmc_card_detect_intr(void *);
 int    dwmmc_card_detect(sdmmc_chipset_handle_t);
 int    dwmmc_bus_power(sdmmc_chipset_handle_t, uint32_t);
 int    dwmmc_bus_clock(sdmmc_chipset_handle_t, int, int);
@@ -380,8 +381,11 @@ dwmmc_attach(struct device *parent, struct device *self, 
void *aux)
 
        OF_getpropintarray(faa->fa_node, "cd-gpios", sc->sc_gpio,
            sizeof(sc->sc_gpio));
-       if (sc->sc_gpio[0])
+       if (sc->sc_gpio[0]) {
                gpio_controller_config_pin(sc->sc_gpio, GPIO_CONFIG_INPUT);
+               gpio_controller_intr_establish(sc->sc_gpio, IPL_SDMMC,
+                   NULL, dwmmc_card_detect_intr, sc, DEVNAME(sc));
+       }
 
        sc->sc_sdio_irq = (OF_getproplen(sc->sc_node, "cap-sdio-irq") == 0);
        sc->sc_vqmmc = OF_getpropint(sc->sc_node, "vqmmc-supply", 0);
@@ -442,6 +446,14 @@ dwmmc_attach(struct device *parent, struct device *self, 
void *aux)
                saa.caps |= SMC_CAPS_4BIT_MODE;
 
        sc->sc_sdmmc = config_found(self, &saa, NULL);
+
+       if (OF_getproplen(sc->sc_node, "non-removable") == -1 &&
+           OF_getproplen(sc->sc_node, "broken-cd") == -1) {
+               /* removable devices with non-broken CD lines, enable CD intr */
+               HWRITE4(sc, SDMMC_RINTSTS, SDMMC_RINTSTS_CDT);
+               HSET4(sc, SDMMC_INTMASK, SDMMC_RINTSTS_CDT);
+       }
+
        return;
 
 unmap:
@@ -562,6 +574,11 @@ dwmmc_intr(void *arg)
        }
 
        stat = HREAD4(sc, SDMMC_MINTSTS);
+       if (stat & SDMMC_RINTSTS_CDT) {
+               HWRITE4(sc, SDMMC_RINTSTS, SDMMC_RINTSTS_CDT);
+               sdmmc_needs_discover(sc->sc_sdmmc);
+               handled = 1;
+       }
        if (stat & SDMMC_RINTSTS_SDIO) {
                HWRITE4(sc, SDMMC_RINTSTS, SDMMC_RINTSTS_SDIO);
                HCLR4(sc, SDMMC_INTMASK, SDMMC_RINTSTS_SDIO);
@@ -610,6 +627,15 @@ dwmmc_host_maxblklen(sdmmc_chipset_handle_t sch)
        return 512;
 }
 
+int
+dwmmc_card_detect_intr(void *arg)
+{
+       struct dwmmc_softc *sc = arg;
+
+       sdmmc_needs_discover(sc->sc_sdmmc);
+       return 1;
+}
+
 int
 dwmmc_card_detect(sdmmc_chipset_handle_t sch)
 {

Reply via email to