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);
>  }
> 

Reply via email to