sdhc_pci: gpio card detect

2019-06-17 Thread James Hastings
Index: sys/dev/pci/sdhc_pci.c
===
RCS file: /cvs/src/sys/dev/pci/sdhc_pci.c,v
retrieving revision 1.20
diff -u -p -u -r1.20 sdhc_pci.c
--- sys/dev/pci/sdhc_pci.c  30 Apr 2016 11:32:23 -  1.20
+++ sys/dev/pci/sdhc_pci.c  11 Jun 2019 01:31:04 -
@@ -21,6 +21,16 @@
 #include 
 #include 
 
+#include "acpi.h"
+#if NACPI > 0
+#include 
+#include 
+#include 
+#include 
+#include 
+#undef DEVNAME
+#endif
+
 #include 
 #include 
 #include 
@@ -52,6 +62,16 @@ struct sdhc_pci_softc {
pcitag_t sc_tag;
pcireg_t sc_id;
void *sc_ih;
+#if NACPI > 0
+   struct acpi_softc *sc_acpi;
+   struct aml_node *sc_node;
+
+   struct aml_node *sc_gpio_int_node;
+   struct aml_node *sc_gpio_io_node;
+   uint16_t sc_gpio_int_pin;
+   uint16_t sc_gpio_int_flags;
+   uint16_t sc_gpio_io_pin;
+#endif
 };
 
 intsdhc_pci_match(struct device *, void *, void *);
@@ -62,6 +82,17 @@ void sdhc_pci_conf_write(pci_chipset_tag
 void   sdhc_takecontroller(struct pci_attach_args *);
 void   sdhc_ricohfix(struct sdhc_pci_softc *);
 
+#if NACPI > 0
+struct aml_node *acpi_pci_match(struct device *, struct pci_attach_args *);
+intsdhc_pci_card_detect_nonremovable(struct sdhc_softc *);
+intsdhc_pci_card_detect_gpio(struct sdhc_softc *);
+intsdhc_pci_card_detect_intr(void *);
+intsdhc_pci_acpi_parse_resources(int, union acpi_resource *, void *);
+void   sdhc_pci_acpi_get_resources(struct sdhc_pci_softc *);
+void   sdhc_pci_acpi_explore(struct sdhc_pci_softc *);
+void   sdhc_pci_acpi_power_on(struct sdhc_pci_softc *, struct aml_node *);
+#endif
+
 struct cfattach sdhc_pci_ca = {
sizeof(struct sdhc_pci_softc), sdhc_pci_match, sdhc_pci_attach,
NULL, sdhc_pci_activate
@@ -147,6 +178,14 @@ sdhc_pci_attach(struct device *parent, s
}
printf(": %s\n", intrstr);
 
+#if NACPI > 0
+   sc->sc_node = acpi_pci_match(self, pa);
+   if (sc->sc_node != NULL) {
+   sdhc_pci_acpi_get_resources(sc);
+   sdhc_pci_acpi_power_on(sc, sc->sc_node);
+   sdhc_pci_acpi_explore(sc);
+   }
+#endif
/* Enable use of DMA if supported by the interface. */
usedma = PCI_INTERFACE(pa->pa_class) == SDHC_PCI_INTERFACE_DMA;
sc->sc.sc_dmat = pa->pa_dmat;
@@ -257,3 +296,123 @@ sdhc_pci_conf_write(pci_chipset_tag_t pc
tmp |= (val << ((reg & 0x3) * 8));
pci_conf_write(pc, tag, reg & ~0x3, tmp);
 }
+#if NACPI > 0
+int
+sdhc_pci_card_detect_nonremovable(struct sdhc_softc *sc)
+{
+   return 1;
+}
+
+int
+sdhc_pci_card_detect_gpio(struct sdhc_softc *ssc)
+{
+   struct sdhc_pci_softc *sc = (struct sdhc_pci_softc *)ssc;
+   struct acpi_gpio *gpio = sc->sc_gpio_io_node->gpio;
+   uint16_t pin = sc->sc_gpio_io_pin;
+
+   /* Card detect GPIO signal is active-low. */
+   return !gpio->read_pin(gpio->cookie, pin);
+}
+
+int
+sdhc_pci_card_detect_intr(void *arg)
+{
+   struct sdhc_pci_softc *sc = arg;
+
+   sdhc_needs_discover(>sc);
+
+   return 1;
+}
+
+int
+sdhc_pci_acpi_parse_resources(int crsidx, union acpi_resource *crs, void *arg)
+{
+   struct sdhc_pci_softc *sc = arg;
+   int type = AML_CRSTYPE(crs);
+   struct aml_node *node;
+   uint16_t pin;
+
+   switch (type) {
+   case LR_GPIO:
+   node = aml_searchname(sc->sc_node, (char 
*)>pad[crs->lr_gpio.res_off]);
+   pin = *(uint16_t *)>pad[crs->lr_gpio.pin_off];
+   if (crs->lr_gpio.type == LR_GPIO_INT) {
+   sc->sc_gpio_int_node = node;
+   sc->sc_gpio_int_pin = pin;
+   sc->sc_gpio_int_flags = crs->lr_gpio.tflags;
+   } else if (crs->lr_gpio.type == LR_GPIO_IO) {
+   sc->sc_gpio_io_node = node;
+   sc->sc_gpio_io_pin = pin;
+   }
+   }
+
+   return 0;
+}
+
+void
+sdhc_pci_acpi_get_resources(struct sdhc_pci_softc *sc)
+{
+   struct aml_value res;
+
+   aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, );
+   aml_parse_resource(, sdhc_pci_acpi_parse_resources, sc);
+
+   if (sc->sc_gpio_io_node && sc->sc_gpio_io_node->gpio)
+   sc->sc.sc_card_detect = sdhc_pci_card_detect_gpio;
+
+   if (sc->sc_gpio_int_node && sc->sc_gpio_int_node->gpio) {
+   struct acpi_gpio *gpio = sc->sc_gpio_int_node->gpio;
+   gpio->intr_establish(gpio->cookie, sc->sc_gpio_int_pin,
+   sc->sc_gpio_int_flags, sdhc_pci_card_detect_intr, sc);
+   }
+}
+
+void
+sdhc_pci_acpi_power_on(struct sdhc_pci_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_pci_acpi_do_explore(struct aml_node *node, void *arg)
+{
+   struct 

sdhc_pci: gpio card detect

2019-06-10 Thread James Hastings
I ported the GPIO card detect bits from sdhc_acpi frontend to sdhc_pci.
This feels like a lot of duplicated code, should it be pushed down to
acpi or sdmmc stack?
I tested this in conjunction with apollo lake gpio driver on an Acer
Spin 1.
Card insertion and removal is now detected but card does not enable yet.


Index: sys/dev/pci/sdhc_pci.c
===
RCS file: /cvs/src/sys/dev/pci/sdhc_pci.c,v
retrieving revision 1.20
diff -u -p -u -r1.20 sdhc_pci.c
--- sys/dev/pci/sdhc_pci.c  30 Apr 2016 11:32:23 -  1.20
+++ sys/dev/pci/sdhc_pci.c  11 Jun 2019 01:31:04 -
@@ -21,6 +21,16 @@
 #include 
 #include 

+#include "acpi.h"
+#if NACPI > 0
+#include 
+#include 
+#include 
+#include 
+#include 
+#undef DEVNAME
+#endif
+
 #include 
 #include 
 #include 
@@ -52,6 +62,16 @@ struct sdhc_pci_softc {
pcitag_t sc_tag;
pcireg_t sc_id;
void *sc_ih;
+#if NACPI > 0
+   struct acpi_softc *sc_acpi;
+   struct aml_node *sc_node;
+
+   struct aml_node *sc_gpio_int_node;
+   struct aml_node *sc_gpio_io_node;
+   uint16_t sc_gpio_int_pin;
+   uint16_t sc_gpio_int_flags;
+   uint16_t sc_gpio_io_pin;
+#endif
 };

 intsdhc_pci_match(struct device *, void *, void *);
@@ -62,6 +82,17 @@ void sdhc_pci_conf_write(pci_chipset_tag
 void   sdhc_takecontroller(struct pci_attach_args *);
 void   sdhc_ricohfix(struct sdhc_pci_softc *);

+#if NACPI > 0
+struct aml_node *acpi_pci_match(struct device *, struct pci_attach_args *);
+intsdhc_pci_card_detect_nonremovable(struct sdhc_softc *);
+intsdhc_pci_card_detect_gpio(struct sdhc_softc *);
+intsdhc_pci_card_detect_intr(void *);
+intsdhc_pci_acpi_parse_resources(int, union acpi_resource *, void *);
+void   sdhc_pci_acpi_get_resources(struct sdhc_pci_softc *);
+void   sdhc_pci_acpi_explore(struct sdhc_pci_softc *);
+void   sdhc_pci_acpi_power_on(struct sdhc_pci_softc *, struct aml_node *);
+#endif
+
 struct cfattach sdhc_pci_ca = {
sizeof(struct sdhc_pci_softc), sdhc_pci_match, sdhc_pci_attach,
NULL, sdhc_pci_activate
@@ -147,6 +178,14 @@ sdhc_pci_attach(struct device *parent, s
}
printf(": %s\n", intrstr);

+#if NACPI > 0
+   sc->sc_node = acpi_pci_match(self, pa);
+   if (sc->sc_node != NULL) {
+   sdhc_pci_acpi_get_resources(sc);
+   sdhc_pci_acpi_power_on(sc, sc->sc_node);
+   sdhc_pci_acpi_explore(sc);
+   }
+#endif
/* Enable use of DMA if supported by the interface. */
usedma = PCI_INTERFACE(pa->pa_class) == SDHC_PCI_INTERFACE_DMA;
sc->sc.sc_dmat = pa->pa_dmat;
@@ -257,3 +296,123 @@ sdhc_pci_conf_write(pci_chipset_tag_t pc
tmp |= (val << ((reg & 0x3) * 8));
pci_conf_write(pc, tag, reg & ~0x3, tmp);
 }
+#if NACPI > 0
+int
+sdhc_pci_card_detect_nonremovable(struct sdhc_softc *sc)
+{
+   return 1;
+}
+
+int
+sdhc_pci_card_detect_gpio(struct sdhc_softc *ssc)
+{
+   struct sdhc_pci_softc *sc = (struct sdhc_pci_softc *)ssc;
+   struct acpi_gpio *gpio = sc->sc_gpio_io_node->gpio;
+   uint16_t pin = sc->sc_gpio_io_pin;
+
+   /* Card detect GPIO signal is active-low. */
+   return !gpio->read_pin(gpio->cookie, pin);
+}
+
+int
+sdhc_pci_card_detect_intr(void *arg)
+{
+   struct sdhc_pci_softc *sc = arg;
+
+   sdhc_needs_discover(>sc);
+
+   return 1;
+}
+
+int
+sdhc_pci_acpi_parse_resources(int crsidx, union acpi_resource *crs,
void *arg)
+{
+   struct sdhc_pci_softc *sc = arg;
+   int type = AML_CRSTYPE(crs);
+   struct aml_node *node;
+   uint16_t pin;
+
+   switch (type) {
+   case LR_GPIO:
+   node = aml_searchname(sc->sc_node, (char
*)>pad[crs->lr_gpio.res_off]);
+   pin = *(uint16_t *)>pad[crs->lr_gpio.pin_off];
+   if (crs->lr_gpio.type == LR_GPIO_INT) {
+   sc->sc_gpio_int_node = node;
+   sc->sc_gpio_int_pin = pin;
+   sc->sc_gpio_int_flags = crs->lr_gpio.tflags;
+   } else if (crs->lr_gpio.type == LR_GPIO_IO) {
+   sc->sc_gpio_io_node = node;
+   sc->sc_gpio_io_pin = pin;
+   }
+   }
+
+   return 0;
+}
+
+void
+sdhc_pci_acpi_get_resources(struct sdhc_pci_softc *sc)
+{
+   struct aml_value res;
+
+   aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, );
+   aml_parse_resource(, sdhc_pci_acpi_parse_resources, sc);
+
+   if (sc->sc_gpio_io_node && sc->sc_gpio_io_node->gpio)
+   sc->sc.sc_card_detect = sdhc_pci_card_detect_gpio;
+
+   if (sc->sc_gpio_int_node && sc->sc_gpio_int_node->gpio) {
+   struct acpi_gpio *gpio = sc->sc_gpio_int_node->gpio;
+   gpio->intr_establish(gpio->cookie, sc->sc_gpio_int_pin,
+   sc->sc_gpio_int_flags, sdhc_pci_card_detect_intr, sc);
+   }
+}
+
+void
+sdhc_pci_acpi_power_on(struct