--- sys/dev/acpi/files.acpi.orig +++ sys/dev/acpi/files.acpi @@ -301,8 +301,12 @@ # DesignWare Ethernet Quality-of-Service controller attach eqos at acpinodebus with eqos_acpi file dev/acpi/eqos_acpi.c eqos_acpi +# Intel GPIO +attach igpio at acpinodebus with igpio_acpi +file dev/acpi/igpio_acpi.c igpio_acpi + # DesignWare Mobile Storage Host Controller attach dwcmmc at acpinodebus with dwcmmc_acpi file dev/acpi/dwcmmc_acpi.c dwcmmc_acpi --- sys/dev/acpi/igpio_acpi.c.orig +++ sys/dev/acpi/igpio_acpi.c @@ -0,0 +1,237 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2021,2022 Emmanuel Dreyfus + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: igpio_acpi.c,v 1.7 2021/01/29 15:49:55 thorpej Exp $"); + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +struct igpio_acpi_softc { + ACPI_HANDLE sc_handle; + struct igpio_softc sc_isc; + struct acpi_event * sc_event[8]; + int sc_pmf; + void *sc_intr; +}; + +static int igpio_acpi_match(device_t, cfdata_t, void *); +static void igpio_acpi_attach(device_t, device_t, void *); +static int igpio_acpi_detach(device_t, int); + +static void igpio_acpi_register_event(void *, struct acpi_event *, ACPI_RESOURCE_GPIO *); +static int igpio_acpi_intr(void *); + +CFATTACH_DECL_NEW(igpio_acpi, sizeof(struct igpio_acpi_softc), igpio_acpi_match, igpio_acpi_attach, igpio_acpi_detach, NULL); + +static const struct device_compatible_entry compat_data[] = { + { .compat = "INT33B2" }, /* baytrail */ + { .compat = "INT33C7" }, /* lynxpoint */ + { .compat = "INT33FC" }, /* baytrail */ + { .compat = "INT3437" }, /* lynxpoint */ + { .compat = "INT344B" }, /* sunrisepoint */ + { .compat = "INT3450" }, /* cannonlake */ + { .compat = "INT3451" }, /* sunrisepoint */ + { .compat = "INT3453" }, /* geminilake */ + { .compat = "INT3455" }, /* icelake */ + { .compat = "INT345D" }, /* sunrisepoint */ + { .compat = "INT34BB" }, /* cannonlake */ + { .compat = "INT34C4" }, /* lakefield */ + { .compat = "INT34C5" }, /* tigerlake */ + { .compat = "INT34C6" }, /* tigerlake */ + { .compat = "INT34C8" }, /* jasperlake */ + { .compat = "INT3536" }, /* lewisburg */ + { .compat = "INTC1055" }, /* tigerlake */ + { .compat = "INTC1056" }, /* alderlake */ + { .compat = "INTC1057" }, /* tigerlake */ + { .compat = "INTC1071" }, /* emmitsburg */ + { .compat = "INTC3000" }, /* denverton */ + { .compat = "INTC3001" }, /* cedarfork */ +#ifdef notyet + /* + * Complete bank setup in src/sys/dev/ic/igpioreg.h + * before enabling + */ + { .compat = "INT3452" }, /* broxton */ + { .compat = "INT34D1" }, /* broxton */ + { .compat = "apollolake-pinctrl" }, /* broxton */ + { .compat = "broxton-pinctrl" }, /* broxton */ + { .compat = "INT33FF" }, /* cherryview */ +#endif + DEVICE_COMPAT_EOL +}; + +static int +igpio_acpi_match(device_t parent, cfdata_t cf, void *aux) +{ + struct acpi_attach_args *aa = aux; + + return acpi_compatible_match(aa, compat_data); +} + +static void +igpio_acpi_attach(device_t parent, device_t self, void *aux) +{ + struct igpio_acpi_softc * const asc = device_private(self); + struct acpi_attach_args *aa = aux; + ACPI_DEVICE_INFO *ad = aa->aa_node->ad_devinfo; + struct acpi_resources res; + struct acpi_mem *mem; + struct acpi_irq *irq; + int nbar; + ACPI_STATUS rv; + int i; + + asc->sc_handle = aa->aa_node->ad_handle; + + rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS", + &res, &acpi_resource_parse_ops_default); + if (ACPI_FAILURE(rv)) + return; + + irq = acpi_res_irq(&res, 0); + if (irq == NULL) { + aprint_error_dev(self, "couldn't find irq resource\n"); + goto done; + } + + asc->sc_isc.sc_dev = self; + + asc->sc_isc.sc_bst = aa->aa_memt; + for (nbar = 0; acpi_res_mem(&res, nbar); nbar++); + asc->sc_isc.sc_nbar = nbar; + asc->sc_isc.sc_base = + kmem_zalloc(sizeof(*asc->sc_isc.sc_base) * nbar, KM_SLEEP); + asc->sc_isc.sc_length = + kmem_zalloc(sizeof(*asc->sc_isc.sc_length) * nbar, KM_SLEEP); + asc->sc_isc.sc_bsh = + kmem_zalloc(sizeof(*asc->sc_isc.sc_bsh) * nbar, KM_SLEEP); + + asc->sc_isc.sc_acpi_hid = ad->HardwareId.String; + + for (i = 0; i < nbar; i++) { + mem = acpi_res_mem(&res, i); + if (mem == NULL) { + aprint_error_dev(self, "couldn't find mem resource\n"); + goto done; + } + + asc->sc_isc.sc_base[i] = mem->ar_base; + asc->sc_isc.sc_length[i] = mem->ar_length; + } + + igpio_attach(&asc->sc_isc); + + /* If attachement failed */ + if (asc->sc_isc.sc_banks == NULL) { + igpio_acpi_detach(self, 0); + goto done; + } + + rv = acpi_event_create_gpio(self, asc->sc_handle, igpio_acpi_register_event, asc); + if (ACPI_FAILURE(rv)) { + if (rv != AE_NOT_FOUND) + aprint_error_dev(self, "failed to create events: %s\n", AcpiFormatException(rv)); + goto done; + } + + asc->sc_intr = acpi_intr_establish(self, + (uint64_t)(uintptr_t)asc->sc_handle, + IPL_VM, false, igpio_acpi_intr, asc, device_xname(self)); + if (asc->sc_intr == NULL) + aprint_error_dev(self, "couldn't establish interrupt\n"); + +done: + acpi_resource_cleanup(&res); + (void)pmf_device_register(self, NULL, NULL); + asc->sc_pmf = 1; +} + +static int +igpio_acpi_detach(device_t self, int flags) +{ + struct igpio_acpi_softc * const asc = device_private(self); + struct igpio_softc * const isc = &asc->sc_isc; + int nbar = isc->sc_nbar; + + acpi_intr_disestablish(asc->sc_intr); + + igpio_detach(&asc->sc_isc); + + if (isc->sc_base != NULL) { + kmem_free(isc->sc_base, sizeof(*isc->sc_base) * nbar); + isc->sc_base = NULL; + } + + if (isc->sc_length != NULL) { + kmem_free(isc->sc_length, sizeof(*isc->sc_length) * nbar); + isc->sc_length = NULL; + } + + if (isc->sc_bsh != NULL) { + kmem_free(isc->sc_bsh, sizeof(*isc->sc_bsh) * nbar); + isc->sc_length = NULL; + } + + if (asc->sc_pmf) { + pmf_device_deregister(self); + asc->sc_pmf = 0; + } + + return 0; +} + +static void +igpio_acpi_register_event(void *priv, struct acpi_event *ev, ACPI_RESOURCE_GPIO *gpio) +{ + return; +} + +static int +igpio_acpi_intr(void *priv) +{ + struct igpio_acpi_softc *asc = priv; + struct igpio_softc * const isc = &asc->sc_isc; + int ret; + + ret = igpio_intr(isc); + + return ret; +} --- sys/dev/ic/igpio.c.orig +++ sys/dev/ic/igpio.c @@ -0,0 +1,643 @@ +/* $NetBSD$ */ + +/* + * Copyright (c) 2021,2022 Emmanuel Dreyfus + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "gpio.h" + +#include +#include + +struct igpio_intr { + int (*ii_func)(void *); + void *ii_arg; + struct igpio_bank *ii_bank; + int ii_pin; +}; + +struct igpio_bank { + int ib_barno; + int ib_revid; + int ib_cap; + int ib_padbar; + struct igpio_bank_setup *ib_setup; + struct igpio_softc *ib_sc; + struct igpio_intr *ib_intr; + kmutex_t ib_mtx; +}; + + +static int igpio_debug = 0; +#define DPRINTF(x) if (igpio_debug) printf x; + +static struct igpio_bank_setup * +igpio_find_bank_setup(struct igpio_bank *ib, int barno) +{ + struct igpio_bank_setup *ibs; + + for (ibs = igpio_bank_setup; ibs->ibs_acpi_hid; ibs++) { + if (strcmp(ib->ib_sc->sc_acpi_hid, ibs->ibs_acpi_hid) != 0) + continue; + if (ibs->ibs_barno != barno) + continue; + + return ibs; + } + + return NULL; +} + +static struct igpio_bank * +igpio_find_bank(struct igpio_softc *sc, int pin) +{ + int i; + struct igpio_bank *ib; + + for (i = 0; i < sc->sc_nbar; i++) { + ib = &sc->sc_banks[i]; + if (pin >= ib->ib_setup->ibs_first_pin && + pin <= ib->ib_setup->ibs_last_pin) + goto out; + } + + ib = NULL; +out: + return ib; +} + +static int +igpio_bank_pin(struct igpio_bank *ib, int pin) +{ + return pin - ib->ib_setup->ibs_first_pin; +} + +void +igpio_attach(struct igpio_softc *sc) +{ + device_t self = sc->sc_dev; + int i,j; + struct gpiobus_attach_args gba; + int success = 0; + + sc->sc_banks = + kmem_zalloc(sizeof(*sc->sc_banks) * sc->sc_nbar, KM_SLEEP); + + sc->sc_npins = 0; + + for (i = 0; i < sc->sc_nbar; i++) { + struct igpio_bank *ib = &sc->sc_banks[i]; + struct igpio_bank_setup *ibs; + bus_size_t reg; + uint32_t val; + int error; + int npins; + + ib->ib_barno = i; + ib->ib_sc = sc; + + mutex_init(&ib->ib_mtx, MUTEX_DEFAULT, IPL_VM); + + error = bus_space_map(sc->sc_bst, sc->sc_base[i], + sc->sc_length[i], 0, &sc->sc_bsh[i]); + if (error) { + aprint_error_dev(self, "couldn't map registers\n"); + goto out; + } + + reg = IGPIO_REVID; + val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[i], reg); + if (val == 0) { + aprint_error_dev(self, "couldn't find revid\n"); + goto out; + } + ib->ib_revid = val >> 16; + + DPRINTF(("revid[%d] = #%x\n", i, ib->ib_revid)); + + if (ib->ib_revid > 0x94) { + ib->ib_cap |= IGPIO_PINCTRL_FEATURE_DEBOUNCE; + ib->ib_cap |= IGPIO_PINCTRL_FEATURE_1K_PD; + } + + reg = IGPIO_CAPLIST; + do { + /* higher 16 bits: value, lower 16 bits, next reg */ + val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[i], reg); + + reg = val & 0xffff; + val = val >> 16; + + switch (val) { + case IGPIO_CAPLIST_ID_GPIO_HW_INFO: + ib->ib_cap |= + IGPIO_PINCTRL_FEATURE_GPIO_HW_INFO; + break; + case IGPIO_CAPLIST_ID_PWM: + ib->ib_cap |= IGPIO_PINCTRL_FEATURE_PWM; + break; + case IGPIO_CAPLIST_ID_BLINK: + ib->ib_cap |= IGPIO_PINCTRL_FEATURE_BLINK; + break; + case IGPIO_CAPLIST_ID_EXP: + ib->ib_cap |= IGPIO_PINCTRL_FEATURE_EXP; + break; + default: + break; + } + } while (reg); + DPRINTF(("cap[%d] = #%x\n", i, ib->ib_cap)); + + reg = IGPIO_PADBAR; + val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[i], reg); + ib->ib_padbar = val; + DPRINTF(("padbar[%d] = #%x\n", i, ib->ib_padbar)); + + ib->ib_setup = igpio_find_bank_setup(ib, i); + if (ib->ib_setup == NULL) { + printf("Missing BAR %d\n", i); + goto out; + } + + ibs = ib->ib_setup; + + DPRINTF(("setup[%d] = " + "{ barno = %d, first_pin = %d, last_pin = %d }\n", + i, ibs->ibs_barno, ibs->ibs_first_pin, ibs->ibs_last_pin)); + + npins = 1 + ibs->ibs_last_pin - ibs->ibs_first_pin; + + ib->ib_intr = + kmem_zalloc(sizeof(*ib->ib_intr) * npins, KM_SLEEP); + + sc->sc_npins += npins; + } + + if (sc->sc_npins < 1 || sc->sc_npins > 4096) { + printf("Unexpected pin count %d\n", sc->sc_npins); + goto out; + } + + sc->sc_pins = + kmem_zalloc(sizeof(*sc->sc_pins) * sc->sc_npins, KM_SLEEP); + + for (j = 0; j < sc->sc_npins; j++) { + sc->sc_pins[j].pin_num = j; + sc->sc_pins[j].pin_caps = + GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; + sc->sc_pins[j].pin_intrcaps = + GPIO_INTR_POS_EDGE | GPIO_INTR_NEG_EDGE | + GPIO_INTR_DOUBLE_EDGE | GPIO_INTR_HIGH_LEVEL | + GPIO_INTR_LOW_LEVEL | GPIO_INTR_MPSAFE; + sc->sc_pins[j].pin_state = igpio_pin_read(sc, j); + } + + sc->sc_gc.gp_cookie = sc; + sc->sc_gc.gp_pin_read = igpio_pin_read; + sc->sc_gc.gp_pin_write = igpio_pin_write; + sc->sc_gc.gp_pin_ctl = igpio_pin_ctl; + sc->sc_gc.gp_intr_establish = igpio_intr_establish; + sc->sc_gc.gp_intr_disestablish = igpio_intr_disestablish; + sc->sc_gc.gp_intr_str = igpio_intr_str; + + memset(&gba, 0, sizeof(gba)); + gba.gba_gc = &sc->sc_gc; + gba.gba_pins = sc->sc_pins; + gba.gba_npins = sc->sc_npins; + +#if NGPIO > 0 + config_found(sc->sc_dev, &gba, gpiobus_print, CFARGS_NONE); +#endif + + success = 1; +out: + if (!success) + igpio_detach(sc); + + return; +} + +void +igpio_detach(struct igpio_softc *sc) +{ + int i; + + for (i = 0; i < sc->sc_nbar; i++) { + struct igpio_bank *ib = &sc->sc_banks[i]; + struct igpio_bank_setup *ibs = ib->ib_setup; + int npins = 1 + ibs->ibs_last_pin - ibs->ibs_first_pin; + + if (ib->ib_intr != NULL) { + kmem_free(ib->ib_intr, sizeof(*ib->ib_intr) * npins); + ib->ib_intr = NULL; + } + } + + if (sc->sc_pins != NULL) { + kmem_free(sc->sc_pins, sizeof(*sc->sc_pins) * sc->sc_npins); + sc->sc_pins = NULL; + } + + if (sc->sc_banks != NULL) { + kmem_free(sc->sc_banks, sizeof(*sc->sc_banks) * sc->sc_nbar); + sc->sc_banks = NULL; + } + + return; +} + +static bus_addr_t +igpio_pincfg(struct igpio_bank *ib, int pin, int reg) +{ + int nregs = (ib->ib_cap & IGPIO_PINCTRL_FEATURE_DEBOUNCE) ? 4 : 2; + bus_addr_t pincfg; + + pincfg = ib->ib_padbar + reg + (pin * nregs * 4); + DPRINTF(("%s pin %d reg #%x pincfg = %p\n", + __func__, pin, reg, (void *)pincfg)); + return pincfg; +} + +#if notyet +static struct igpio_pin_group * +igpio_find_group(struct igpio_bank *ib, int pin) +{ + struct igpio_bank_setup *ibs = ib->ib_setup; + struct igpio_pin_group *found_ipg = NULL; + struct igpio_pin_group *ipg; + + if (pin > ibs->ibs_last_pin) { + DPRINTF(("%s: barno %d, pin = %d > past pin = %d\n", __func__, + ibs->ibs_barno, pin, ibs->ibs_last_pin)); + return NULL; + } + + for (ipg = igpio_pin_group; ipg->ipg_acpi_hid; ipg++) { + if (strcmp(ipg->ipg_acpi_hid, ibs->ibs_acpi_hid) != 0) + continue; + + if (pin > ipg->ipg_first_pin) { + found_ipg = ipg; + continue; + } + } + + return found_ipg; +} + +static bus_addr_t +igpio_groupcfg(struct igpio_bank *ib, int pin) +{ + struct igpio_bank_setup *ibs = ib->ib_setup; + struct igpio_pin_group *ipg; + bus_addr_t groupcfg; + + if ((ipg = igpio_find_group(ib, pin)) == NULL) + return (bus_addr_t)NULL; + + groupcfg = ib->ib_padbar + + (ipg->ipg_groupno * 4) + + (pin - ipg->ipg_first_pin) / 2; + + DPRINTF(("%s: barno %d, pin = %d, found group %d \"%s\", cfg %p\n", \ + __func__, ibs->ibs_barno, pin, ipg->ipg_groupno, \ + ipg->ipg_name, (void *)groupcfg)); + + return groupcfg; +} +#endif + + +int +igpio_pin_read(void *priv, int pin) +{ + struct igpio_softc *sc = priv; + struct igpio_bank *ib = igpio_find_bank(sc, pin); + bus_addr_t cfg0; + uint32_t val; + + pin = igpio_bank_pin(ib, pin); + cfg0 = igpio_pincfg(ib, pin, IGPIO_PADCFG0); + + mutex_enter(&ib->ib_mtx); + + val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0); + DPRINTF(("%s: pin %d val #%x\n", __func__, pin, val)); + + if (val & IGPIO_PADCFG0_GPIOTXDIS) + val = (val & IGPIO_PADCFG0_GPIORXSTATE) ? 1 : 0; + else + val = (val & IGPIO_PADCFG0_GPIOTXSTATE) ? 1 : 0; + + mutex_exit(&ib->ib_mtx); + + return val; +} + +void +igpio_pin_write(void *priv, int pin, int value) +{ + struct igpio_softc *sc = priv; + struct igpio_bank *ib = igpio_find_bank(sc, pin); + bus_addr_t cfg0; + uint32_t val, newval; + + pin = igpio_bank_pin(ib, pin); + cfg0 = igpio_pincfg(ib, pin, IGPIO_PADCFG0); + + mutex_enter(&ib->ib_mtx); + + val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0); + + if (value) + newval = val | IGPIO_PADCFG0_GPIOTXSTATE; + else + newval = val & ~IGPIO_PADCFG0_GPIOTXSTATE; + + DPRINTF(("%s: pin %d value %d val #%x -> #%x\n", + __func__, pin, value, val, newval)); + + bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0, newval); + + mutex_exit(&ib->ib_mtx); + + return; +} + +void +igpio_pin_ctl(void *priv, int pin, int flags) +{ + struct igpio_softc *sc = priv; + struct igpio_bank *ib = igpio_find_bank(sc, pin); + bus_addr_t cfg0; + uint32_t val, newval; + + pin = igpio_bank_pin(ib, pin); + cfg0 = igpio_pincfg(ib, pin, IGPIO_PADCFG0); + + mutex_enter(&ib->ib_mtx); + + val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0); + newval = val; + + newval &= ~IGPIO_PADCFG0_PMODE_MASK; + newval |= IGPIO_PADCFG0_PMODE_GPIO; + + newval |= IGPIO_PADCFG0_GPIORXDIS; + newval |= IGPIO_PADCFG0_GPIOTXDIS; + + newval &= ~(IGPIO_PADCFG0_GPIROUTIOXAPIC | IGPIO_PADCFG0_GPIROUTSCI); + newval &= ~(IGPIO_PADCFG0_GPIROUTSMI | IGPIO_PADCFG0_GPIROUTNMI); + + if (flags & GPIO_PIN_INPUT) { + newval &= ~IGPIO_PADCFG0_GPIORXDIS; + newval |= IGPIO_PADCFG0_GPIOTXDIS; + } + + if (flags & GPIO_PIN_OUTPUT) { + newval &= ~IGPIO_PADCFG0_GPIOTXDIS; + newval |= IGPIO_PADCFG0_GPIORXDIS; + } + + DPRINTF(("%s: pin %d flags #%x val #%x -> #%x\n", + __func__, pin, flags, val, newval)); + + bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0, newval); + + mutex_exit(&ib->ib_mtx); + + return; +} + +void * +igpio_intr_establish(void *priv, int pin, int ipl, int irqmode, + int (*func)(void *), void *arg) +{ + struct igpio_softc *sc = priv; + struct igpio_bank *ib = igpio_find_bank(sc, pin); + bus_addr_t cfg0; + uint32_t val, newval; + struct igpio_intr *ii; + + pin = igpio_bank_pin(ib, pin); + cfg0 = igpio_pincfg(ib, pin, IGPIO_PADCFG0); + + ii = &ib->ib_intr[pin]; + ii->ii_func = func; + ii->ii_arg = arg; + ii->ii_pin = pin; + ii->ii_bank = ib; + + mutex_enter(&ib->ib_mtx); + + val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0); + newval = val; + + newval &= ~IGPIO_PADCFG0_PMODE_MASK; + newval |= IGPIO_PADCFG0_PMODE_GPIO; + + newval &= ~IGPIO_PADCFG0_GPIORXDIS; + newval |= IGPIO_PADCFG0_GPIOTXDIS; + + newval |= (IGPIO_PADCFG0_GPIROUTIOXAPIC | IGPIO_PADCFG0_GPIROUTSCI); + newval |= (IGPIO_PADCFG0_GPIROUTSMI | IGPIO_PADCFG0_GPIROUTNMI); + + newval &= ~IGPIO_PADCFG0_RXINV; + newval &= ~IGPIO_PADCFG0_RXEVCFG_EDGE; + newval &= ~IGPIO_PADCFG0_RXEVCFG_LEVEL; + newval &= ~IGPIO_PADCFG0_RXEVCFG_DISABLED; + + switch (irqmode & GPIO_INTR_EDGE_MASK) { + case GPIO_INTR_DOUBLE_EDGE: + newval |= IGPIO_PADCFG0_RXEVCFG_EDGE_BOTH; + break; + case GPIO_INTR_NEG_EDGE: + newval |= IGPIO_PADCFG0_RXEVCFG_EDGE; + newval |= IGPIO_PADCFG0_RXINV; + break; + case GPIO_INTR_POS_EDGE: + newval |= IGPIO_PADCFG0_RXEVCFG_EDGE; + break; + default: + switch (irqmode & GPIO_INTR_LEVEL_MASK) { + case GPIO_INTR_HIGH_LEVEL: + newval |= IGPIO_PADCFG0_RXEVCFG_LEVEL; + break; + case GPIO_INTR_LOW_LEVEL: + newval |= IGPIO_PADCFG0_RXEVCFG_LEVEL; + newval |= IGPIO_PADCFG0_RXINV; + break; + default: + newval |= IGPIO_PADCFG0_RXEVCFG_DISABLED; + break; + } + break; + } + + + DPRINTF(("%s: pin %d val #%x -> #%x\n", __func__, pin, val, newval)); + + bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0, newval); + + mutex_exit(&ib->ib_mtx); + + return ii; +} + +void +igpio_intr_disestablish(void *priv, void *ih) +{ + struct igpio_softc *sc = priv; + struct igpio_bank *ib; + struct igpio_intr *ii = ih; + int pin = ii->ii_pin; + bus_addr_t cfg0; + uint32_t val, newval; + + ib = igpio_find_bank(sc, pin); + pin = igpio_bank_pin(ib, pin); + cfg0 = igpio_pincfg(ib, pin, IGPIO_PADCFG0); + + mutex_enter(&ib->ib_mtx); + + val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0); + newval = val; + + newval &= ~IGPIO_PADCFG0_PMODE_MASK; + newval |= IGPIO_PADCFG0_PMODE_GPIO; + + newval &= ~(IGPIO_PADCFG0_GPIROUTIOXAPIC | IGPIO_PADCFG0_GPIROUTSCI); + newval &= ~(IGPIO_PADCFG0_GPIROUTSMI | IGPIO_PADCFG0_GPIROUTNMI); + + DPRINTF(("%s: pin %d val #%x -> #%x\n", \ + __func__, pin, val, newval)); + + bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0, newval); + + mutex_exit(&ib->ib_mtx); + + ii->ii_func = NULL; + ii->ii_arg = NULL; + + return; +} + +bool +igpio_intr_str(void *priv, int pin, int irqmode, + char *buf, size_t buflen) +{ + struct igpio_softc *sc = priv; + const char *name = sc->sc_dev->dv_xname; + int rv; + + rv = snprintf(buf, buflen, "%s pin %d", name, pin); + + return (rv < buflen); +} + +int +igpio_intr(void *priv) +{ + struct igpio_softc *sc = priv; + int i; + int ret = 0; + + for (i = 0; i < sc->sc_nbar; i++) { + struct igpio_bank *ib = &sc->sc_banks[i]; + struct igpio_bank_setup *ibs = ib->ib_setup; + bus_space_handle_t bsh = sc->sc_bsh[i]; + struct igpio_pin_group *ipg; + + mutex_enter(&ib->ib_mtx); + + for (ipg = igpio_pin_group; ipg->ipg_acpi_hid; ipg++) { + int offset; + bus_addr_t is_reg; + bus_addr_t ie_reg; + uint32_t raised; + uint32_t pending; + uint32_t enabled; + int b; + + if (strcmp(ipg->ipg_acpi_hid, + ibs->ibs_acpi_hid) != 0) + continue; + + offset = ib->ib_padbar + ipg->ipg_groupno * 4; + is_reg = offset + ibs->ibs_gpi_is; + ie_reg = offset + ibs->ibs_gpi_ie; + + raised = bus_space_read_4(sc->sc_bst, bsh, is_reg); + enabled = bus_space_read_4(sc->sc_bst, bsh, ie_reg); + + /* + * find pins for which interupt is pending + * and enabled + */ + pending = raised & enabled; + + for (b = 0; b < 32; b++) { + int pin; + int (*func)(void *); + void *arg; + + if ((pending & (1 << b)) == 0) + continue; + + pin = ipg->ipg_first_pin + b; + func = ib->ib_intr[pin].ii_func; + arg = ib->ib_intr[pin].ii_arg; + + /* XXX ack intr, handled or not? */ + raised &= ~(1 << b); + + if (func == NULL) + continue; + + ret |= func(arg); + } + + bus_space_write_4(sc->sc_bst, bsh, is_reg, raised); + + } + + mutex_exit(&ib->ib_mtx); + + } + + return ret; +} --- sys/dev/ic/igpioreg.h.orig +++ sys/dev/ic/igpioreg.h @@ -0,0 +1,481 @@ +/* $NetBSD$ */ + +/* + * Copyright (c) 2021 Emmanuel Dreyfus + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _IGPIOREG_H +#define _IGPIOREG_H + +#define IGPIO_REVID 0x0000 +#define IGPIO_CAPLIST 0x0004 +#define IGPIO_PADBAR 0x000c + +#define IGPIO_PADCFG0 0x0000 + +#define IGPIO_PADCFG0_GPIORXDIS 0x200 +#define IGPIO_PADCFG0_GPIOTXDIS 0x100 +#define IGPIO_PADCFG0_GPIORXSTATE 0x002 +#define IGPIO_PADCFG0_GPIOTXSTATE 0x001 +#define IGPIO_PADCFG0_PMODE_MASK 0x3c0 +#define IGPIO_PADCFG0_PMODE_GPIO 0 +#define IGPIO_PADCFG0_GPIROUTIOXAPIC 0x100000 +#define IGPIO_PADCFG0_GPIROUTSCI 0x080000 +#define IGPIO_PADCFG0_GPIROUTSMI 0x040000 +#define IGPIO_PADCFG0_GPIROUTNMI 0x020000 +#define IGPIO_PADCFG0_RXEVCFG_LEVEL 0x2000000 +#define IGPIO_PADCFG0_RXEVCFG_EDGE 0x4000000 +#define IGPIO_PADCFG0_RXEVCFG_DISABLED 0x8000000 +#define IGPIO_PADCFG0_RXEVCFG_EDGE_BOTH 0xc000000 +#define IGPIO_PADCFG0_RXINV 0x0800000 + + +#define IGPIO_CAPLIST_ID_GPIO_HW_INFO 1 +#define IGPIO_CAPLIST_ID_PWM 2 +#define IGPIO_CAPLIST_ID_BLINK 3 +#define IGPIO_CAPLIST_ID_EXP 4 + + +#define IGPIO_PINCTRL_FEATURE_DEBOUNCE 0x001 +#define IGPIO_PINCTRL_FEATURE_1K_PD 0x002 +#define IGPIO_PINCTRL_FEATURE_GPIO_HW_INFO 0x004 +#define IGPIO_PINCTRL_FEATURE_PWM 0x010 +#define IGPIO_PINCTRL_FEATURE_BLINK 0x020 +#define IGPIO_PINCTRL_FEATURE_EXP 0x040 + +struct igpio_bank_setup { + const char *ibs_acpi_hid; + int ibs_barno; + int ibs_first_pin; + int ibs_last_pin; + int ibs_gpi_is; + int ibs_gpi_ie; +}; + +struct igpio_pin_group { + const char *ipg_acpi_hid; + int ipg_groupno; + int ipg_first_pin; + const char *ipg_name; +}; + +struct igpio_bank_setup igpio_bank_setup[] = { + /* Sunrisepoint-LP */ + { "INT344B", 0, 0, 47, 0x100, 0x120 }, + { "INT344B", 1, 48, 119, 0x100, 0x120 }, + { "INT344B", 2, 120, 151, 0x100, 0x120 }, + + /* Sunrisepoint-H */ + { "INT3451", 0, 0, 47, 0x100, 0x120 }, + { "INT3451", 1, 48, 180, 0x100, 0x120 }, + { "INT3451", 2, 181, 191, 0x100, 0x120 }, + + /* Sunrisepoint-H */ + { "INT345D", 0, 0, 47, 0x100, 0x120 }, + { "INT345D", 1, 48, 180, 0x100, 0x120 }, + { "INT345D", 2, 181, 191, 0x100, 0x120 }, + + /* Baytrail XXX GPI_IS and GPI_IE */ + { "INT33B2", 0, 0, 101, 0x000, 0x000 }, + { "INT33FC", 0, 0, 101, 0x000, 0x000 }, + + /* Lynxpoint XXX GPI_IS and GPI_IE */ + { "INT33C7", 0, 0, 94, 0x000, 0x000 }, + { "INT3437", 0, 0, 94, 0x000, 0x000 }, + + /* Cannonlake-H */ + { "INT3450", 0, 0, 50, 0x100, 0x120 }, + { "INT3450", 1, 51, 154, 0x100, 0x120 }, + { "INT3450", 2, 155, 248, 0x100, 0x120 }, + { "INT3450", 3, 249, 298, 0x100, 0x120 }, + + /* Cannonlake-LP */ + { "INT34BB", 0, 0, 67, 0x100, 0x120 }, + { "INT34BB", 1, 68, 180, 0x100, 0x120 }, + { "INT34BB", 2, 181, 243, 0x100, 0x120 }, + + /* Alderlake */ + { "INTC1056", 0, 0, 94, 0x200, 0x220 }, + { "INTC1056", 1, 95, 150, 0x200, 0x220 }, + { "INTC1056", 2, 151, 199, 0x200, 0x220 }, + { "INTC1056", 3, 200, 269, 0x200, 0x220 }, + { "INTC1056", 4, 270, 303, 0x200, 0x220 }, + + /* Icelake */ + { "INT3455", 0, 0, 58, 0x100, 0x110 }, + { "INT3455", 1, 59, 152, 0x100, 0x110 }, + { "INT3455", 2, 153, 215, 0x100, 0x110 }, + { "INT3455", 3, 216, 240, 0x100, 0x110 }, + + /* Lakefield */ + { "INT34C4", 0, 0, 59, 0x100, 0x110 }, + { "INT34C4", 1, 60, 148, 0x100, 0x110 }, + { "INT34C4", 2, 149, 237, 0x100, 0x110 }, + { "INT34C4", 3, 238, 266, 0x100, 0x110 }, + + /* Tigerlake-LP */ + { "INT34C5", 0, 0, 66, 0x100, 0x120 }, + { "INT34C5", 1, 67, 170, 0x100, 0x120 }, + { "INT34C5", 2, 171, 259, 0x100, 0x120 }, + { "INT34C5", 3, 260, 276, 0x100, 0x120 }, + + /* Tigerlake-LP */ + { "INTC1055", 0, 0, 66, 0x100, 0x120 }, + { "INTC1055", 1, 67, 170, 0x100, 0x120 }, + { "INTC1055", 2, 171, 259, 0x100, 0x120 }, + { "INTC1055", 3, 260, 276, 0x100, 0x120 }, + + /* Tigerlake-LP */ + { "INTC1057", 0, 0, 66, 0x100, 0x120 }, + { "INTC1057", 1, 67, 170, 0x100, 0x120 }, + { "INTC1057", 2, 171, 259, 0x100, 0x120 }, + { "INTC1057", 3, 260, 276, 0x100, 0x120 }, + + /* Tigerlake-H */ + { "INT34C6", 0, 0, 78, 0x100, 0x120 }, + { "INT34C6", 1, 79, 180, 0x100, 0x120 }, + { "INT34C6", 2, 181, 217, 0x100, 0x120 }, + { "INT34C6", 3, 218, 266, 0x100, 0x120 }, + { "INT34C6", 4, 267, 290, 0x100, 0x120 }, + + /* Jasperlake */ + { "INT34C8", 0, 0, 91, 0x100, 0x120 }, + { "INT34C8", 1, 92, 194, 0x100, 0x120 }, + { "INT34C8", 2, 195, 224, 0x100, 0x120 }, + { "INT34C8", 3, 225, 232, 0x100, 0x120 }, + + /* Lewisburg */ + { "INT3536", 0, 0, 7, 0x100, 0x110 }, + { "INT3536", 1, 72, 13, 0x100, 0x110 }, + { "INT3536", 3, 133, 14, 0x100, 0x110 }, + { "INT3536", 4, 144, 17, 0x100, 0x110 }, + { "INT3536", 5, 179, 246, 0x100, 0x110 }, + + /* Emmitsburg */ + { "INTC1071", 0, 0, 65, 0x200, 0x210 }, + { "INTC1071", 1, 66, 111, 0x200, 0x210 }, + { "INTC1071", 2, 112, 145, 0x200, 0x210 }, + { "INTC1071", 3, 146, 183, 0x200, 0x210 }, + { "INTC1071", 4, 184, 261, 0x200, 0x210 }, + + /* Denverton */ + { "INTC3000", 0, 0, 40, 0x100, 0x120 }, + { "INTC3000", 1, 41, 153, 0x100, 0x120 }, + + /* Cedarfork */ + { "INTC3001", 0, 0, 167, 0x200, 0x230 }, + { "INTC3001", 1, 168, 236, 0x200, 0x230 }, + + /* Geminilake */ + { "INT3453", 0, 0, 34, 0x100, 0x110 }, + +#ifdef notyet + /* + * BAR mappings not obvious, further studying required + */ + /* Broxton */ + { "apollolake-pinctrl", 0, 0, 0, 0x100, 0x110 }, + { "broxton-pinctrl", 0, 0, 0, 0x100, 0x110 }, + { "INT34D1", 0, 0, 0, 0x100, 0x110 }, + { "INT3452", 0, 0, 0, 0x100, 0x110 }, + + /* Cherryview */ + { "INT33FF", 0, 0, 0, 0x000, 0x000 }, +#endif + + { NULL, 0, 0, 0, 0x000, 0x000 }, +}; + +struct igpio_pin_group igpio_pin_group[] = { + /* Sunrisepoint-LP */ + { "INT344B", 0, 151, "A" }, + + /* Sunrisepoint-H */ + { "INT3451", 0, 0, "A" }, + { "INT3451", 1, 24, "B" }, + { "INT3451", 0, 48, "C" }, + { "INT3451", 1, 72, "D" }, + { "INT3451", 2, 96, "E" }, + { "INT3451", 3, 109, "F" }, + { "INT3451", 4, 133, "G" }, + { "INT3451", 5, 157, "H" }, + { "INT3451", 0, 181, "I" }, + + /* Sunrisepoint-H */ + { "INT345D", 0, 0, "A" }, + { "INT345D", 1, 24, "B" }, + { "INT345D", 0, 48, "C" }, + { "INT345D", 1, 72, "D" }, + { "INT345D", 2, 96, "E" }, + { "INT345D", 3, 109, "F" }, + { "INT345D", 4, 133, "G" }, + { "INT345D", 5, 157, "H" }, + { "INT345D", 0, 181, "I" }, + + + /* Baytrail */ + { "INT33B2", 0, 101, "A" }, + + /* Lynxpoint */ + { "INT33C7", 0, 94, "A" }, + { "INT3437", 0, 94, "A" }, + + /* Cannonlake-H */ + { "INT3450", 0, 0, "GPP_A" }, + { "INT3450", 1, 25, "GPP_B" }, + { "INT3450", 0, 51, "GPP_C" }, + { "INT3450", 1, 75, "GPP_D" }, + { "INT3450", 2, 99, "GPP_G" }, + { "INT3450", 3, 107, "AZA" }, + { "INT3450", 4, 115, "vGPIO_0" }, + { "INT3450", 5, 147, "vGPIO_1" }, + { "INT3450", 0, 155, "GPP_K" }, + { "INT3450", 1, 179, "GPP_H" }, + { "INT3450", 2, 203, "GPP_E" }, + { "INT3450", 3, 216, "GPP_F" }, + { "INT3450", 4, 240, "SPI" }, + { "INT3450", 0, 249, "CPU" }, + { "INT3450", 1, 260, "JTAG" }, + { "INT3450", 2, 269, "GPP_I" }, + { "INT3450", 3, 287, "GPP_J" }, + + /* Cannonlake-LP */ + { "INT34BB", 0, 0, "GPP_A" }, + { "INT34BB", 1, 25, "GPP_B" }, + { "INT34BB", 2, 51, "GPP_G" }, + { "INT34BB", 3, 59, "SPI" }, + { "INT34BB", 0, 68, "GPP_D" }, + { "INT34BB", 1, 93, "GPP_F" }, + { "INT34BB", 2, 117, "GPP_H" }, + { "INT34BB", 3, 141, "vGPIO" }, + { "INT34BB", 4, 173, "vGPIO" }, + { "INT34BB", 0, 181, "GPP_C" }, + { "INT34BB", 1, 205, "GPP_E" }, + { "INT34BB", 2, 229, "JTAG" }, + { "INT34BB", 3, 238, "HVCMOS" }, + + /* Alderlake */ + { "INTC1056", 0, 0, "GPP_I" }, + { "INTC1056", 1, 25, "GPP_R" }, + { "INTC1056", 2, 48, "GPP_J" }, + { "INTC1056", 3, 60, "vGPIO" }, + { "INTC1056", 4, 87, "vGPIO_0" }, + { "INTC1056", 0, 95, "GPP_B" }, + { "INTC1056", 1, 119, "GPP_G" }, + { "INTC1056", 2, 127, "GPP_H" }, + { "INTC1056", 0, 151, "SPI0" }, + { "INTC1056", 1, 160, "GPP_A" }, + { "INTC1056", 2, 176, "GPP_C" }, + { "INTC1056", 0, 200, "GPP_S" }, + { "INTC1056", 1, 208, "GPP_E" }, + { "INTC1056", 2, 231, "GPP_K" }, + { "INTC1056", 3, 246, "GPP_F" }, + { "INTC1056", 0, 270, "GPP_D" }, + { "INTC1056", 1, 295, "JTAG" }, + + + /* Icelake */ + { "INT3455", 0, 0, "GPP_G" }, + { "INT3455", 1, 8, "GPP_B" }, + { "INT3455", 2, 34, "GPP_A" }, + { "INT3455", 0, 59, "GPP_H" }, + { "INT3455", 1, 83, "GPP_D" }, + { "INT3455", 2, 104, "GPP_F" }, + { "INT3455", 3, 124, "vGPIO" }, + { "INT3455", 0, 153, "GPP_C" }, + { "INT3455", 1, 177, "HVCMOS" }, + { "INT3455", 2, 183, "GPP_E" }, + { "INT3455", 3, 207, "JTAG" }, + { "INT3455", 2, 232, "SPI" }, + + + /* Lakefield */ + { "INT34C4", 0, 0, "EAST_0" }, + { "INT34C4", 1, 32, "EAST_1" }, + { "INT34C4", 0, 60, "NORTHWEST_0" }, + { "INT34C4", 1, 92, "NORTHWEST_1" }, + { "INT34C4", 2, 124, "NORTHWEST_2" }, + { "INT34C4", 0, 149, "WEST_0" }, + { "INT34C4", 1, 181, "WEST_1" }, + { "INT34C4", 2, 213, "WEST_2" }, + { "INT34C4", 0, 238, "SOUTHEAST" }, + + + /* Tigerlake-LP */ + { "INT34C5", 0, 0, "GPP_A" }, + { "INT34C5", 1, 25, "GPP_R" }, + { "INT34C5", 2, 45, "GPP_B" }, + { "INT34C5", 3, 71, "vGPIO_0" }, + { "INT34C5", 0, 79, "GPP_D" }, + { "INT34C5", 1, 105, "GPP_C" }, + { "INT34C5", 2, 129, "GPP_S" }, + { "INT34C5", 3, 137, "GPP_G" }, + { "INT34C5", 4, 154, "vGPIO" }, + { "INT34C5", 0, 181, "GPP_E" }, + { "INT34C5", 1, 194, "GPP_F" }, + { "INT34C5", 0, 218, "GPP_H" }, + { "INT34C5", 1, 242, "GPP_J" }, + { "INT34C5", 2, 252, "GPP_K" }, + { "INT34C5", 0, 267, "GPP_I" }, + { "INT34C5", 1, 282, "JTAG" }, + + + /* Tigerlake-LP */ + { "INTC1055", 0, 0, "GPP_A" }, + { "INTC1055", 1, 25, "GPP_R" }, + { "INTC1055", 2, 45, "GPP_B" }, + { "INTC1055", 3, 71, "vGPIO_0" }, + { "INTC1055", 0, 79, "GPP_D" }, + { "INTC1055", 1, 105, "GPP_C" }, + { "INTC1055", 2, 129, "GPP_S" }, + { "INTC1055", 3, 137, "GPP_G" }, + { "INTC1055", 4, 154, "vGPIO" }, + { "INTC1055", 0, 181, "GPP_E" }, + { "INTC1055", 1, 194, "GPP_F" }, + { "INTC1055", 0, 218, "GPP_H" }, + { "INTC1055", 1, 242, "GPP_J" }, + { "INTC1055", 2, 252, "GPP_K" }, + { "INTC1055", 0, 267, "GPP_I" }, + { "INTC1055", 1, 282, "JTAG" }, + + + /* Tigerlake-LP */ + { "INTC1057", 0, 0, "GPP_A" }, + { "INTC1057", 1, 25, "GPP_R" }, + { "INTC1057", 2, 45, "GPP_B" }, + { "INTC1057", 3, 71, "vGPIO_0" }, + { "INTC1057", 0, 79, "GPP_D" }, + { "INTC1057", 1, 105, "GPP_C" }, + { "INTC1057", 2, 129, "GPP_S" }, + { "INTC1057", 3, 137, "GPP_G" }, + { "INTC1057", 4, 154, "vGPIO" }, + { "INTC1057", 0, 181, "GPP_E" }, + { "INTC1057", 1, 194, "GPP_F" }, + { "INTC1057", 0, 218, "GPP_H" }, + { "INTC1057", 1, 242, "GPP_J" }, + { "INTC1057", 2, 252, "GPP_K" }, + { "INTC1057", 0, 267, "GPP_I" }, + { "INTC1057", 1, 282, "JTAG" }, + + /* Tigerlake-H */ + { "INT34C6", 0, 0, "GPP_B" }, + { "INT34C6", 1, 26, "GPP_T" }, + { "INT34C6", 2, 42, "GPP_A" }, + { "INT34C6", 0, 67, "GPP_S" }, + { "INT34C6", 1, 75, "GPP_H" }, + { "INT34C6", 2, 99, "GPP_D" }, + { "INT34C6", 3, 120, "GPP_U" }, + { "INT34C6", 4, 144, "vGPIO" }, + { "INT34C6", 0, 171, "GPP_C" }, + { "INT34C6", 1, 195, "GPP_F" }, + { "INT34C6", 2, 220, "HVCMOS" }, + { "INT34C6", 3, 226, "GPP_E" }, + { "INT34C6", 4, 251, "JTAG" }, + { "INT34C6", 0, 260, "GPP_R" }, + { "INT34C6", 1, 268, "SPI" }, + + /* Jasperlake */ + { "INT34C8", 0, 0, "GPP_F" }, + { "INT34C8", 1, 20, "SPI" }, + { "INT34C8", 2, 29, "GPP_B" }, + { "INT34C8", 3, 55, "GPP_A" }, + { "INT34C8", 4, 76, "GPP_S" }, + { "INT34C8", 5, 84, "GPP_R" }, + { "INT34C8", 0, 92, "GPP_H" }, + { "INT34C8", 1, 116, "GPP_D" }, + { "INT34C8", 2, 142, "vGPIO" }, + { "INT34C8", 3, 171, "GPP_C" }, + { "INT34C8", 0, 195, "HVCMOS" }, + { "INT34C8", 1, 201, "GPP_E" }, + { "INT34C8", 0, 225, "GPP_G" }, + + + /* Lewisburg */ + { "INT3536", 0, 7, "" }, + + /* Emmitsburg */ + { "INTC1071", 0, 0, "GPP_A" }, + { "INTC1071", 1, 21, "GPP_B" }, + { "INTC1071", 2, 45, "SPI" }, + { "INTC1071", 0, 66, "GPP_C" }, + { "INTC1071", 1, 88, "GPP_D" }, + { "INTC1071", 0, 112, "GPP_E" }, + { "INTC1071", 1, 136, "JTAG" }, + { "INTC1071", 0, 146, "GPP_H" }, + { "INTC1071", 1, 166, "GPP_J" }, + { "INTC1071", 0, 184, "GPP_I" }, + { "INTC1071", 1, 208, "GPP_L" }, + { "INTC1071", 2, 226, "GPP_M" }, + { "INTC1071", 3, 244, "GPP_N" }, + + /* Denverton */ + { "INTC3000", 0, 0, "North" }, + { "INTC3000", 1, 32, "North" }, + { "INTC3000", 0, 41, "South" }, + { "INTC3000", 1, 59, "South" }, + { "INTC3000", 2, 91, "South" }, + { "INTC3000", 3, 112, "South" }, + { "INTC3000", 4, 144, "South" }, + + + /* Cedarfork */ + { "INTC3001", 0, 0, "WEST2" }, + { "INTC3001", 1, 24, "WEST3" }, + { "INTC3001", 2, 48, "WEST01" }, + { "INTC3001", 3, 71, "WEST5" }, + { "INTC3001", 4, 91, "WESTC" }, + { "INTC3001", 5, 97, "WESTC_DFX" }, + { "INTC3001", 6, 102, "WESTA" }, + { "INTC3001", 7, 112, "WESTB" }, + { "INTC3001", 8, 124, "WESTD" }, + { "INTC3001", 9, 144, "WESTD_PECI" }, + { "INTC3001", 10, 145, "WESTF" }, + { "INTC3001", 0, 168, "EAST2" }, + { "INTC3001", 1, 192, "EAST3" }, + { "INTC3001", 2, 203, "EAST0" }, + { "INTC3001", 3, 226, "EMMC" }, + + /* Geminilake */ + { "INT3453", 0, 34, "" }, + +#ifdef notyet + /* + * BAR mappings not obvious, further studying required + */ + /* Broxton */ + { "apollolake-pinctrl", 0, 0, "" }, + { "broxton-pinctrl", 0, 0, "" }, + { "INT34D1", 0, 0, "" }, + { "INT3452", 0, 0, "" }, + + /* Cherryview */ + { "INT33FF", 0, 0, "" }, +#endif + + { NULL, 0, 0, 0 }, +}; + +#endif /* _IGPIOREG_H */ + --- sys/dev/ic/igpiovar.h.orig +++ sys/dev/ic/igpiovar.h @@ -0,0 +1,63 @@ +/* $NetBSD$ */ + +/* + * Copyright (c) 2021 Emmanuel Dreyfus + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _IGPIOVAR_H +#define _IGPIOVAR_H + +struct igpio_softc { + device_t sc_dev; + const char *sc_acpi_hid; + bus_space_tag_t sc_bst; + int sc_nbar; + bus_addr_t *sc_base; + bus_size_t *sc_length; + bus_space_handle_t *sc_bsh; + + gpio_pin_t *sc_pins; + int sc_npins; + struct gpio_chipset_tag sc_gc; + + uint32_t sc_reserved_mask; + + struct igpio_bank *sc_banks; +}; + +void igpio_attach(struct igpio_softc *); +void igpio_detach(struct igpio_softc *); + +int igpio_pin_read(void *, int); +void igpio_pin_write(void *, int, int); +void igpio_pin_ctl(void *, int, int); +void *igpio_intr_establish(void *, int, int, int, int (*)(void *), void *); +void igpio_intr_disestablish(void *, void *); +bool igpio_intr_str(void *, int, int, char *, size_t); +int igpio_intr(void *); + + + +#endif /* !_IGPIOVAR_H */