On Sun, Mar 27, 2016 at 09:28:25PM +0200, Mark Kettenis wrote: > The diff below is a first stab at adding support for GPIOs as defined > in ACPI 5.0. The primary target for this new ACPI feature is hardware > reduced platforms like those based on Intel's Bay Trail SoC. The diff > adds a bytgpio(4) driver for the hardware found on that SoC. This > driver registers itself with the acpi framework by setting the struct > acpi_gpio pointer on the AML node for the device. Then this gets used > by the acpi sdhc(4) frontend to use the appropriate gpio as the card > detect signal. This makes it possible to detectwhether a card is > inserted when the kernel boots. Support for GPIO-based interrupts is > still missing, so hotplugging SD cards doesn't work yet. > > There are some debug printfs here that will disappear eventually. > > ok?
Works on ideapad 100s: bytgpio0 at acpi0: GPO0 uid 1 addr 0xfed0c000/0x1000 irq 49, 102 pins bytgpio1 at acpi0: GPO1 uid 2 addr 0xfed0d000/0x1000 irq 48, 28 pins bytgpio2 at acpi0: GPO2 uid 3 addr 0xfed0e000/0x1000 irq 50, 44 pins sdhc0 at acpi0: SDHA addr 0x9091d000/0x1000 irq 44 sdmmc0 at sdhc0 sdhc at acpi0 not configured sdhc1 at acpi0: SDHD GPO0 pin 38 tflags 0x1d ppi 0x3 drs 0x0 dbt 0x2710 GPO0 pin 38 tflags 0x9 ppi 0x0 drs 0x0 dbt 0x0 addr 0x90903000/0x1000 irq 47 sdmmc1 at sdhc1 ... scsibus1 at sdmmc0: 2 targets, initiator 0 sd0 at scsibus1 targ 1 lun 0: <SD/MMC, Drive #01, > SCSI2 0/direct fixed sd0: 29820MB, 512 bytes/sector, 61071360 sectors scsibus2 at sdmmc1: 2 targets, initiator 0 sd1 at scsibus2 targ 1 lun 0: <SD/MMC, Drive #01, > SCSI2 0/direct fixed sd1: 15271MB, 512 bytes/sector, 31275008 sectors sdmmc0 is emmc sdmmc1 is a usd card in the slot. Though after some network traffic over usb the machine seems to hang. Opening new windows in tmux over ssh works but shells don't spawn. I can still type locally (with the polling diff) but can't login on tty. Is it possible this somehow enables gpio interrupts that we then don't acknowledge? > > > Index: acpi.c > =================================================================== > RCS file: /cvs/src/sys/dev/acpi/acpi.c,v > retrieving revision 1.305 > diff -u -p -r1.305 acpi.c > --- acpi.c 17 Jan 2016 09:04:18 -0000 1.305 > +++ acpi.c 27 Mar 2016 19:18:31 -0000 > @@ -2801,6 +2801,8 @@ acpi_foundhid(struct aml_node *node, voi > !strcmp(dev, ACPI_DEV_TOSHIBA_SPA40)) { > aaa.aaa_name = "acpitoshiba"; > acpi_toshiba_enabled = 1; > + } else if (!strcmp(dev, "INT33FC")) { > + aaa.aaa_name = "bytgpio"; > } else if (!strcmp(dev, "80860F14") || !strcmp(dev, "PNP0FFF")) { > aaa.aaa_name = "sdhc"; > } else if (!strcmp(dev, ACPI_DEV_DWIIC1) || > Index: amltypes.h > =================================================================== > RCS file: /cvs/src/sys/dev/acpi/amltypes.h,v > retrieving revision 1.40 > diff -u -p -r1.40 amltypes.h > --- amltypes.h 7 Sep 2012 19:19:59 -0000 1.40 > +++ amltypes.h 27 Mar 2016 19:18:31 -0000 > @@ -364,6 +364,11 @@ struct acpi_pci { > int _s4w; > }; > > +struct acpi_gpio { > + void *cookie; > + int (*read_pin)(void *, int); > +}; > + > struct aml_node { > struct aml_node *parent; > > @@ -377,6 +382,7 @@ struct aml_node { > > struct aml_value *value; > struct acpi_pci *pci; > + struct acpi_gpio *gpio; > }; > > #define aml_bitmask(n) (1L << ((n) & 0x7)) > Index: bytgpio.c > =================================================================== > RCS file: bytgpio.c > diff -N bytgpio.c > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ bytgpio.c 27 Mar 2016 19:18:31 -0000 > @@ -0,0 +1,242 @@ > +/* $OpenBSD$ */ > +/* > + * Copyright (c) 2016 Mark Kettenis > + * > + * Permission to use, copy, modify, and distribute this software for any > + * purpose with or without fee is hereby granted, provided that the above > + * copyright notice and this permission notice appear in all copies. > + * > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > + > +#include <sys/param.h> > +#include <sys/malloc.h> > +#include <sys/systm.h> > + > +#include <dev/acpi/acpireg.h> > +#include <dev/acpi/acpivar.h> > +#include <dev/acpi/acpidev.h> > +#include <dev/acpi/amltypes.h> > +#include <dev/acpi/dsdt.h> > + > +#define BYTGPIO_PAD_VAL 0x00000001 > + > +struct bytgpio_softc { > + struct device sc_dev; > + struct acpi_softc *sc_acpi; > + struct aml_node *sc_node; > + > + bus_space_tag_t sc_memt; > + bus_space_handle_t sc_memh; > + bus_addr_t sc_addr; > + bus_size_t sc_size; > + > + int sc_irq; > + int sc_irq_flags; > + void *sc_ih; > + > + const int *sc_pins; > + int sc_npins; > + > + struct acpi_gpio sc_gpio; > +}; > + > +int bytgpio_match(struct device *, void *, void *); > +void bytgpio_attach(struct device *, struct device *, void *); > + > +struct cfattach bytgpio_ca = { > + sizeof(struct bytgpio_softc), bytgpio_match, bytgpio_attach > +}; > + > +struct cfdriver bytgpio_cd = { > + NULL, "bytgpio", DV_DULL > +}; > + > +const char *bytgpio_hids[] = { > + "INT33FC", > + 0 > +}; > + > +/* > + * The pads for the pins are randomly ordered. > + */ > + > +const int byt_score_pins[] = { > + 85, 89, 93, 96, 99, 102, 98, 101, 34, 37, 36, 38, 39, 35, 40, > + 84, 62, 61, 64, 59, 54, 56, 60, 55, 63, 57, 51, 50, 53, 47, > + 52, 49, 48, 43, 46, 41, 45, 42, 58, 44, 95, 105, 70, 68, 67, > + 66, 69, 71, 65, 72, 86, 90, 88, 92, 103, 77, 79, 83, 78, 81, > + 80, 82, 13, 12, 15, 14, 17, 18, 19, 16, 2, 1, 0, 4, 6, 7, 9, > + 8, 33, 32, 31, 30, 29, 27, 25, 28, 26, 23, 21, 20, 24, 22, 5, > + 3, 10, 11, 106, 87, 91, 104, 97, 100 > +}; > + > +const int byt_ncore_pins[] = { > + 19, 18, 17, 20, 21, 22, 24, 25, 23, 16, 14, 15, 12, 26, 27, > + 1, 4, 8, 11, 0, 3, 6, 10, 13, 2, 5, 9, 7 > +}; > + > +const int byt_sus_pins[] = { > + 29, 33, 30, 31, 32, 34, 36, 35, 38, 37, 18, 7, 11, 20, 17, 1, > + 8, 10, 19, 12, 0, 2, 23, 39, 28, 27, 22, 21, 24, 25, 26, 51, > + 56, 54, 49, 55, 48, 57, 50, 58, 52, 53, 59, 40 > +}; > + > +int bytgpio_parse_resources(union acpi_resource *, void *); > +int bytgpio_read_pin(void *, int); > +int bytgpio_intr(void *); > + > +int > +bytgpio_match(struct device *parent, void *match, void *aux) > +{ > + struct acpi_attach_args *aaa = aux; > + struct cfdata *cf = match; > + int64_t sta; > + > + if (!acpi_matchhids(aaa, bytgpio_hids, cf->cf_driver->cd_name)) > + return 0; > + > + if (aml_evalinteger((struct acpi_softc *)parent, aaa->aaa_node, > + "_STA", 0, NULL, &sta)) > + sta = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000; > + > + if ((sta & STA_PRESENT) == 0) > + return 0; > + > + return 1; > +} > + > +void > +bytgpio_attach(struct device *parent, struct device *self, void *aux) > +{ > + struct acpi_attach_args *aaa = aux; > + struct bytgpio_softc *sc = (struct bytgpio_softc *)self; > + struct aml_value res; > + int64_t uid; > + > + sc->sc_acpi = (struct acpi_softc *)parent; > + sc->sc_node = aaa->aaa_node; > + printf(": %s", sc->sc_node->name); > + > + if (aml_evalinteger(sc->sc_acpi, sc->sc_node, "_UID", 0, NULL, &uid)) { > + printf(", can't find uid\n"); > + return; > + } > + > + printf(" uid %lld", uid); > + > + switch (uid) { > + case 1: > + sc->sc_pins = byt_score_pins; > + sc->sc_npins = nitems(byt_score_pins); > + break; > + case 2: > + sc->sc_pins = byt_score_pins; > + sc->sc_npins = nitems(byt_ncore_pins); > + break; > + case 3: > + sc->sc_pins = byt_score_pins; > + sc->sc_npins = nitems(byt_sus_pins); > + break; > + default: > + return; > + } > + > + if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) { > + printf(", can't find registers\n"); > + return; > + } > + > + aml_parse_resource(&res, bytgpio_parse_resources, sc); > + printf(" addr 0x%lx/0x%lx", sc->sc_addr, sc->sc_size); > + if (sc->sc_addr == 0 || sc->sc_size == 0) { > + printf("\n"); > + return; > + } > + > + printf(" irq %d", sc->sc_irq); > + > + sc->sc_memt = aaa->aaa_memt; > + if (bus_space_map(sc->sc_memt, sc->sc_addr, sc->sc_size, 0, > + &sc->sc_memh)) { > + printf(", can't map registers\n"); > + return; > + } > + > +#if 0 > + sc->sc_ih = acpi_intr_establish(sc->sc_irq, sc->sc_irq_flags, IPL_BIO, > + bytgpio_intr, sc, sc->sc_dev.dv_xname); > + if (sc->sc_ih == NULL) { > + printf(", can't establish interrupt\n"); > + return; > + } > +#endif > + > + sc->sc_gpio.cookie = sc; > + sc->sc_gpio.read_pin = bytgpio_read_pin; > + sc->sc_node->gpio = &sc->sc_gpio; > + > + printf(", %d pins\n", sc->sc_npins); > +} > + > +int > +bytgpio_parse_resources(union acpi_resource *crs, void *arg) > +{ > + struct bytgpio_softc *sc = arg; > + int type = AML_CRSTYPE(crs); > + > + switch (type) { > + case LR_MEM32FIXED: > + sc->sc_addr = crs->lr_m32fixed._bas; > + sc->sc_size = crs->lr_m32fixed._len; > + break; > + case LR_EXTIRQ: > + sc->sc_irq = crs->lr_extirq.irq[0]; > + sc->sc_irq_flags = crs->lr_extirq.flags; > + break; > + default: > + printf(" type 0x%x\n", type); > + break; > + } > + > + return 0; > +} > + > +int > +bytgpio_read_pin(void *cookie, int pin) > +{ > + struct bytgpio_softc *sc = cookie; > + uint32_t reg; > + > + reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16 > + 8); > + return (reg & BYTGPIO_PAD_VAL); > +} > + > +#if 0 > + > +int > +bytgpio_intr(void *arg) > +{ > + struct bytgpio_softc *sc = arg; > + uint32_t reg; > + int pin; > + > + for (pin = 0; pin < sc->sc_npins; pin++) { > + if (pin % 32 == 0) > + reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, 0x800 > + (pin / 8)); > + if (reg & (1 << (pin % 32))) { > + > + } > + } > + > + printf("%s\n", __func__); > + return 1; > +} > + > +#endif > Index: dsdt.h > =================================================================== > RCS file: /cvs/src/sys/dev/acpi/dsdt.h,v > retrieving revision 1.68 > diff -u -p -r1.68 dsdt.h > --- dsdt.h 14 Mar 2016 06:37:31 -0000 1.68 > +++ dsdt.h 27 Mar 2016 19:18:31 -0000 > @@ -103,6 +103,7 @@ const char *aml_nodename(struct aml_nod > #define LR_WORD 0x88 > #define LR_EXTIRQ 0x89 > #define LR_QWORD 0x8A > +#define LR_GPIO 0x8C > #define LR_SERBUS 0x8E > > #define __amlflagbit(v,s,l) > @@ -226,6 +227,24 @@ union acpi_resource { > uint8_t src_index; > char src[1]; > } __packed lr_qword; > + struct { > + uint8_t typecode; > + uint16_t length; > + uint8_t revid; > + uint8_t type; > +#define LR_GPIO_INT 0x00 > +#define LR_GPIO_IO 0x01 > + uint16_t flags; > + uint16_t tflags; > + uint8_t _ppi; > + uint16_t _drs; > + uint16_t _dbt; > + uint16_t pin_off; > + uint8_t residx; > + uint16_t res_off; > + uint16_t vd_off; > + uint16_t vd_len; > + } __packed lr_gpio; > struct { > uint8_t typecode; > uint16_t length; > Index: files.acpi > =================================================================== > RCS file: /cvs/src/sys/dev/acpi/files.acpi,v > retrieving revision 1.30 > diff -u -p -r1.30 files.acpi > --- files.acpi 12 Jan 2016 01:11:15 -0000 1.30 > +++ files.acpi 27 Mar 2016 19:18:31 -0000 > @@ -112,6 +112,11 @@ device aibs > attach aibs at acpi > file dev/acpi/atk0110.c aibs > > +# Intel Bay Trail GPIO > +device bytgpio > +attach bytgpio at acpi > +file dev/acpi/bytgpio.c bytgpio > + > # SD Host Controller > attach sdhc at acpi with sdhc_acpi > file dev/acpi/sdhc_acpi.c sdhc_acpi > Index: sdhc_acpi.c > =================================================================== > RCS file: /cvs/src/sys/dev/acpi/sdhc_acpi.c,v > retrieving revision 1.1 > diff -u -p -r1.1 sdhc_acpi.c > --- sdhc_acpi.c 11 Jan 2016 07:36:10 -0000 1.1 > +++ sdhc_acpi.c 27 Mar 2016 19:18:31 -0000 > @@ -43,6 +43,11 @@ struct sdhc_acpi_softc { > int sc_irq_flags; > void *sc_ih; > > + struct aml_node *sc_gpio_int_node; > + struct aml_node *sc_gpio_io_node; > + uint16_t sc_gpio_int_pin; > + uint16_t sc_gpio_io_pin; > + > struct sdhc_host *sc_host; > }; > > @@ -62,6 +67,7 @@ const char *sdhc_hids[] = { > }; > > int sdhc_acpi_parse_resources(union acpi_resource *, void *); > +int sdhc_acpi_card_detect(struct sdhc_softc *); > > int > sdhc_acpi_match(struct device *parent, void *match, void *aux) > @@ -122,6 +128,9 @@ sdhc_acpi_attach(struct device *parent, > return; > } > > + if (sc->sc_gpio_io_node != NULL) > + sc->sc.sc_card_detect = sdhc_acpi_card_detect; > + > printf("\n"); > > sc->sc.sc_host = &sc->sc_host; > @@ -133,6 +142,8 @@ sdhc_acpi_parse_resources(union acpi_res > { > struct sdhc_acpi_softc *sc = arg; > int type = AML_CRSTYPE(crs); > + struct aml_node *node; > + uint16_t pin; > > switch (type) { > case LR_MEM32FIXED: > @@ -143,8 +154,21 @@ sdhc_acpi_parse_resources(union acpi_res > sc->sc_irq = crs->lr_extirq.irq[0]; > sc->sc_irq_flags = crs->lr_extirq.flags; > break; > - case 0x8c: > - /* XXX GPIO; use for card detect. */ > + case LR_GPIO: > + node = aml_searchname(sc->sc_node, (char > *)&crs->pad[crs->lr_gpio.res_off]); > + pin = *(uint16_t *)&crs->pad[crs->lr_gpio.pin_off]; > + printf(" %s pin %d\n", node->name, pin); > + if (crs->lr_gpio.type == LR_GPIO_INT) { > + sc->sc_gpio_int_node = node; > + sc->sc_gpio_int_pin = pin; > + } else if (crs->lr_gpio.type == LR_GPIO_IO) { > + sc->sc_gpio_io_node = node; > + sc->sc_gpio_io_pin = pin; > + } > + printf(" tflags 0x%x\n", crs->lr_gpio.tflags); > + printf(" ppi 0x%x\n", crs->lr_gpio._ppi); > + printf(" drs 0x%x\n", crs->lr_gpio._drs); > + printf(" dbt 0x%x\n", crs->lr_gpio._dbt); > break; > default: > printf(" type 0x%x\n", type); > @@ -152,4 +176,14 @@ sdhc_acpi_parse_resources(union acpi_res > } > > return 0; > +} > + > +int > +sdhc_acpi_card_detect(struct sdhc_softc *ssc) > +{ > + struct sdhc_acpi_softc *sc = (struct sdhc_acpi_softc *)ssc; > + struct acpi_gpio *gpio = sc->sc_gpio_io_node->gpio; > + uint16_t pin = sc->sc_gpio_io_pin; > + > + return !gpio->read_pin(gpio->cookie, pin); > } >