Diff below does two things:

1. Put controllers and child devices into _PS0.  It seems the BIOS is
   supposed to deliver them to us in that state, but apparently some
   BIOSen don't do that.

2. Override the card detect if ACPI says that the child devices are
   non-removable.  Apparently SDHC card detect is borked (or simply
   not implemented) on the Intel SDIO controllers.

With these diffs, the SDIO WiFi in my Asus X205TA is probed correctly.
And it even works with the bwfm(4) driver after some further magic.

ok?


Index: dev/acpi/sdhc_acpi.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/sdhc_acpi.c,v
retrieving revision 1.9
diff -u -p -r1.9 sdhc_acpi.c
--- dev/acpi/sdhc_acpi.c        25 Oct 2016 06:48:58 -0000      1.9
+++ dev/acpi/sdhc_acpi.c        20 May 2018 23:14:26 -0000
@@ -70,8 +70,11 @@ const char *sdhc_hids[] = {
 };
 
 int    sdhc_acpi_parse_resources(int, union acpi_resource *, void *);
-int    sdhc_acpi_card_detect(struct sdhc_softc *);
+int    sdhc_acpi_card_detect_nonremovable(struct sdhc_softc *);
+int    sdhc_acpi_card_detect_gpio(struct sdhc_softc *);
 int    sdhc_acpi_card_detect_intr(void *);
+void   sdhc_acpi_power_on(struct sdhc_acpi_softc *, struct aml_node *);
+void   sdhc_acpi_explore(struct sdhc_acpi_softc *);
 
 int
 sdhc_acpi_match(struct device *parent, void *match, void *aux)
@@ -122,10 +125,12 @@ sdhc_acpi_attach(struct device *parent, 
        }
 
        if (sc->sc_gpio_io_node && sc->sc_gpio_io_node->gpio) {
-               sc->sc.sc_card_detect = sdhc_acpi_card_detect;
+               sc->sc.sc_card_detect = sdhc_acpi_card_detect_gpio;
                printf(", gpio");
        }
 
+       printf("\n");
+
        if (sc->sc_gpio_int_node && sc->sc_gpio_int_node->gpio) {
                struct acpi_gpio *gpio = sc->sc_gpio_int_node->gpio;
 
@@ -133,7 +138,8 @@ sdhc_acpi_attach(struct device *parent, 
                    sc->sc_gpio_int_flags, sdhc_acpi_card_detect_intr, sc);
        }
 
-       printf("\n");
+       sdhc_acpi_power_on(sc, sc->sc_node);
+       sdhc_acpi_explore(sc);
 
        sc->sc.sc_host = &sc->sc_host;
        sc->sc.sc_dmat = &pci_bus_dma_tag;
@@ -175,7 +181,13 @@ sdhc_acpi_parse_resources(int crsidx, un
 }
 
 int
-sdhc_acpi_card_detect(struct sdhc_softc *ssc)
+sdhc_acpi_card_detect_nonremovable(struct sdhc_softc *ssc)
+{
+       return 1;
+}
+
+int
+sdhc_acpi_card_detect_gpio(struct sdhc_softc *ssc)
 {
        struct sdhc_acpi_softc *sc = (struct sdhc_acpi_softc *)ssc;
        struct acpi_gpio *gpio = sc->sc_gpio_io_node->gpio;
@@ -193,4 +205,48 @@ sdhc_acpi_card_detect_intr(void *arg)
        sdhc_needs_discover(&sc->sc);
 
        return (1);
+}
+
+void
+sdhc_acpi_power_on(struct sdhc_acpi_softc *sc, struct aml_node *node)
+{
+       node = aml_searchname(node, "_PS0");
+       if (node && aml_evalnode(sc->sc_acpi, node, 0, NULL, NULL))
+               printf("%s: _PS0 failed\n", sc->sc.sc_dev.dv_xname);
+}
+
+int
+sdhc_acpi_do_explore(struct aml_node *node, void *arg)
+{
+       struct sdhc_acpi_softc *sc = arg;
+       int64_t sta, rmv;
+
+       /* We're only interested in our children. */
+       if (node == sc->sc_node)
+               return 0;
+
+       /* Only consider devices that are actually present. */
+       if (node->value == NULL ||
+           node->value->type != AML_OBJTYPE_DEVICE)
+               return 1;
+       if (aml_evalinteger(sc->sc_acpi, node, "_STA", 0, NULL, &sta))
+               sta = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000;
+       if ((sta & STA_PRESENT) == 0)
+               return 1;
+
+       /* Override card detect if we have non-removable devices. */
+       if (aml_evalinteger(sc->sc_acpi, node, "_RMV", 0, NULL, &rmv))
+               rmv = 1;
+       if (rmv == 0 && sc->sc.sc_card_detect == NULL)
+               sc->sc.sc_card_detect = sdhc_acpi_card_detect_nonremovable;
+
+       sdhc_acpi_power_on(sc, node);
+
+       return 1;
+}
+
+void
+sdhc_acpi_explore(struct sdhc_acpi_softc *sc)
+{
+       aml_walknodes(sc->sc_node, AML_WALK_PRE, sdhc_acpi_do_explore, sc);
 }

Reply via email to