sdhc_pci: gpio card detect
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
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