Home | History | Annotate | Line # | Download | only in ic
      1 /* $NetBSD: igpio.c,v 1.5 2023/01/07 03:27:01 msaitoh Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2021,2022 Emmanuel Dreyfus
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     23  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     25  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     26  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 
     31 #include <sys/param.h>
     32 #include <sys/bus.h>
     33 #include <sys/device.h>
     34 #include <sys/intr.h>
     35 #include <sys/systm.h>
     36 #include <sys/kernel.h>
     37 #include <sys/kmem.h>
     38 #include <sys/endian.h>
     39 #include <sys/gpio.h>
     40 
     41 #include <dev/gpio/gpiovar.h>
     42 #include "gpio.h"
     43 
     44 #include <dev/ic/igpiovar.h>
     45 #include <dev/ic/igpioreg.h>
     46 
     47 struct igpio_intr {
     48 	int (*ii_func)(void *);
     49 	void *ii_arg;
     50 	struct igpio_bank *ii_bank;
     51 	int ii_pin;
     52 };
     53 
     54 struct igpio_bank {
     55 	int ib_barno;
     56 	int ib_revid;
     57 	int ib_cap;
     58 	int ib_padbar;
     59 	struct igpio_bank_setup *ib_setup;
     60 	struct igpio_softc *ib_sc;
     61 	struct igpio_intr *ib_intr;
     62 	kmutex_t ib_mtx;
     63 };
     64 
     65 
     66 static int igpio_debug = 0;
     67 #define DPRINTF(x) if (igpio_debug) printf x;
     68 
     69 static char *
     70 igpio_padcfg0_print(uint32_t val, int idx)
     71 {
     72 	uint32_t rxev, pmode;
     73 	static char buf0[256];
     74 	static char buf1[256];
     75 	char *buf = (idx % 2) ? &buf0[0] : &buf1[0];
     76 	size_t len = sizeof(buf0) - 1;
     77 	size_t wr = 0;
     78 	uint32_t unknown_bits =
     79 	    __BITS(3,7)|__BITS(14,16)|__BITS(21,22)|__BITS(27,31);
     80 	int b;
     81 
     82 	rxev =
     83 	    (val & IGPIO_PADCFG0_RXEVCFG_MASK) >> IGPIO_PADCFG0_RXEVCFG_SHIFT;
     84 	wr += snprintf(buf + wr, len - wr, "rxev ");
     85 	switch (rxev) {
     86 	case IGPIO_PADCFG0_RXEVCFG_LEVEL:
     87 		wr += snprintf(buf + wr, len - wr, "level");
     88 		break;
     89 	case IGPIO_PADCFG0_RXEVCFG_EDGE:
     90 		wr += snprintf(buf + wr, len - wr, "edge");
     91 		break;
     92 	case IGPIO_PADCFG0_RXEVCFG_DISABLED:
     93 		wr += snprintf(buf + wr, len - wr, "disabled");
     94 		break;
     95 	case IGPIO_PADCFG0_RXEVCFG_EDGE_BOTH:
     96 		wr += snprintf(buf + wr, len - wr, "edge both");
     97 		break;
     98 	default:
     99 		break;
    100 	}
    101 
    102 	if (val & IGPIO_PADCFG0_PREGFRXSEL)
    103 		wr += snprintf(buf + wr, len - wr, ", pregfrxsel");
    104 
    105 	if (val & IGPIO_PADCFG0_RXINV)
    106 		wr += snprintf(buf + wr, len - wr, ", rxinv");
    107 
    108 	if (val & (IGPIO_PADCFG0_GPIROUTIOXAPIC|IGPIO_PADCFG0_GPIROUTSCI|
    109 		   IGPIO_PADCFG0_GPIROUTSMI|IGPIO_PADCFG0_GPIROUTNMI)) {
    110 		wr += snprintf(buf + wr, len - wr, ", gpirout");
    111 
    112 		if (val & IGPIO_PADCFG0_GPIROUTIOXAPIC)
    113 			wr += snprintf(buf + wr, len - wr, " ioxapic");
    114 
    115 		if (val & IGPIO_PADCFG0_GPIROUTSCI)
    116 			wr += snprintf(buf + wr, len - wr, " sci");
    117 
    118 		if (val & IGPIO_PADCFG0_GPIROUTSMI)
    119 			wr += snprintf(buf + wr, len - wr, " smi");
    120 
    121 		if (val & IGPIO_PADCFG0_GPIROUTNMI)
    122 			wr += snprintf(buf + wr, len - wr, " nmi");
    123 	}
    124 
    125 	pmode =
    126 	    (val & IGPIO_PADCFG0_PMODE_MASK) >> IGPIO_PADCFG0_PMODE_SHIFT;
    127 	switch (pmode) {
    128 	case IGPIO_PADCFG0_PMODE_GPIO:
    129 		wr += snprintf(buf + wr, len - wr, ", pmode gpio");
    130 		break;
    131 	default:
    132 		wr += snprintf(buf + wr, len - wr, ", pmode %d", pmode);
    133 		break;
    134 	}
    135 
    136 	if (val & IGPIO_PADCFG0_GPIORXDIS)
    137 		wr += snprintf(buf + wr, len - wr, ", rx disabled");
    138 	else
    139 		wr += snprintf(buf + wr, len - wr, ", rx %d",
    140 		    !!(val & IGPIO_PADCFG0_GPIORXSTATE));
    141 
    142 	if (val & IGPIO_PADCFG0_GPIOTXDIS)
    143 		wr += snprintf(buf + wr, len - wr, ", tx disabled");
    144 	else
    145 		wr += snprintf(buf + wr, len - wr, ", tx %d",
    146 		    !!(val & IGPIO_PADCFG0_GPIOTXSTATE));
    147 
    148 	if (val & unknown_bits) {
    149 		wr += snprintf(buf + wr, len - wr, ", unknown bits");
    150 		for (b = 0; b < 32; b++) {
    151 			if (!(__BIT(b) & unknown_bits & val))
    152 				continue;
    153 			wr += snprintf(buf + wr, len - wr, " %d", b);
    154 		}
    155 	}
    156 
    157 	return buf;
    158 }
    159 
    160 
    161 static struct igpio_bank_setup *
    162 igpio_find_bank_setup(struct igpio_bank *ib, int barno)
    163 {
    164 	struct igpio_bank_setup *ibs;
    165 
    166 	for (ibs = igpio_bank_setup; ibs->ibs_acpi_hid; ibs++) {
    167 		if (strcmp(ib->ib_sc->sc_acpi_hid, ibs->ibs_acpi_hid) != 0)
    168 			continue;
    169 		if (ibs->ibs_barno != barno)
    170 			continue;
    171 
    172 		return ibs;
    173 	}
    174 
    175 	return NULL;
    176 }
    177 
    178 static struct igpio_bank *
    179 igpio_find_bank(struct igpio_softc *sc, int pin)
    180 {
    181 	int i;
    182 	struct igpio_bank *ib;
    183 
    184 	for (i = 0; i < sc->sc_nbar; i++) {
    185 		ib = &sc->sc_banks[i];
    186 		if (pin >= ib->ib_setup->ibs_first_pin &&
    187 		    pin <= ib->ib_setup->ibs_last_pin)
    188 			goto out;
    189 	}
    190 
    191 	ib = NULL;
    192 out:
    193 	return ib;
    194 }
    195 
    196 static int
    197 igpio_bank_pin(struct igpio_bank *ib, int pin)
    198 {
    199 	return pin - ib->ib_setup->ibs_first_pin;
    200 }
    201 
    202 #if 0
    203 static void
    204 igpio_hexdump(struct igpio_softc *sc, int n)
    205 {
    206 	int i, j;
    207 	uint8_t v;
    208 	size_t len = MIN(sc->sc_length[n], 2048);
    209 
    210 	printf("bar %d\n", n);
    211 	for (j = 0; j < len; j += 16) {
    212 		printf("%04x ", j);
    213 		for (i = 0; i < 16 && i + j < len; i++) {
    214 			v = bus_space_read_1(sc->sc_bst, sc->sc_bsh[n], i + j);
    215 			printf("%02x ", v);
    216 		}
    217 		printf("\n");
    218 	}
    219 }
    220 #endif
    221 
    222 void
    223 igpio_attach(struct igpio_softc *sc)
    224 {
    225 	device_t self = sc->sc_dev;
    226 	int i,j;
    227 	struct gpiobus_attach_args gba;
    228 	int success = 0;
    229 
    230 	sc->sc_banks =
    231 	    kmem_zalloc(sizeof(*sc->sc_banks) * sc->sc_nbar, KM_SLEEP);
    232 
    233 	sc->sc_npins = 0;
    234 
    235 	for (i = 0; i < sc->sc_nbar; i++) {
    236 		struct igpio_bank *ib = &sc->sc_banks[i];
    237 		struct igpio_bank_setup *ibs;
    238 		bus_size_t reg;
    239 		uint32_t val;
    240 		int error;
    241 		int npins;
    242 
    243 		ib->ib_barno = i;
    244 		ib->ib_sc = sc;
    245 
    246 		mutex_init(&ib->ib_mtx, MUTEX_DEFAULT, IPL_VM);
    247 
    248 		error = bus_space_map(sc->sc_bst, sc->sc_base[i],
    249 		    sc->sc_length[i], 0, &sc->sc_bsh[i]);
    250 		if (error) {
    251 			aprint_error_dev(self, "couldn't map registers\n");
    252 			goto out;
    253 		}
    254 
    255 		reg = IGPIO_REVID;
    256 		val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[i], reg);
    257 		if (val == 0) {
    258 			aprint_error_dev(self, "couldn't find revid\n");
    259 			goto out;
    260 		}
    261 		ib->ib_revid = val >> 16;
    262 
    263 		DPRINTF(("revid[%d] = #%x\n", i, ib->ib_revid));
    264 
    265 		if (ib->ib_revid > 0x94) {
    266 			ib->ib_cap |= IGPIO_PINCTRL_FEATURE_DEBOUNCE;
    267 			ib->ib_cap |= IGPIO_PINCTRL_FEATURE_1K_PD;
    268 		}
    269 
    270 		reg = IGPIO_CAPLIST;
    271 		do {
    272 			/* higher 16 bits: value, lower 16 bits, next reg */
    273 			val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[i], reg);
    274 
    275 			reg = val & 0xffff;
    276 			val = val >> 16;
    277 
    278 			switch (val) {
    279 			case IGPIO_CAPLIST_ID_GPIO_HW_INFO:
    280 				ib->ib_cap |=
    281 				    IGPIO_PINCTRL_FEATURE_GPIO_HW_INFO;
    282 				break;
    283 			case IGPIO_CAPLIST_ID_PWM:
    284 				ib->ib_cap |= IGPIO_PINCTRL_FEATURE_PWM;
    285 				break;
    286 			case IGPIO_CAPLIST_ID_BLINK:
    287 				ib->ib_cap |= IGPIO_PINCTRL_FEATURE_BLINK;
    288 				break;
    289 			case IGPIO_CAPLIST_ID_EXP:
    290 				ib->ib_cap |= IGPIO_PINCTRL_FEATURE_EXP;
    291 				break;
    292 			default:
    293 				break;
    294 			}
    295 		} while (reg);
    296 		DPRINTF(("cap[%d] = #%x\n", i, ib->ib_cap));
    297 
    298 		reg = IGPIO_PADBAR;
    299 		val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[i], reg);
    300 		ib->ib_padbar = val;
    301 		DPRINTF(("padbar[%d] = #%x\n", i, ib->ib_padbar));
    302 		if (ib->ib_padbar > sc->sc_length[i]) {
    303 			printf("PADBAR = #%x higher than max #%lx\n",
    304 			    ib->ib_padbar, sc->sc_length[i]);
    305 			goto out;
    306 		}
    307 
    308 		ib->ib_setup = igpio_find_bank_setup(ib, i);
    309 		if (ib->ib_setup == NULL) {
    310 			printf("Missing BAR %d\n", i);
    311 			goto out;
    312 		}
    313 
    314 		ibs = ib->ib_setup;
    315 
    316 		DPRINTF(("setup[%d] = "
    317 		    "{ barno = %d, first_pin = %d, last_pin = %d }\n",
    318 		    i, ibs->ibs_barno, ibs->ibs_first_pin, ibs->ibs_last_pin));
    319 
    320 		npins = 1 + ibs->ibs_last_pin - ibs->ibs_first_pin;
    321 
    322 		ib->ib_intr =
    323 		    kmem_zalloc(sizeof(*ib->ib_intr) * npins, KM_SLEEP);
    324 
    325 		sc->sc_npins += npins;
    326 	}
    327 
    328 	if (sc->sc_npins < 1 || sc->sc_npins > 4096) {
    329 		printf("Unexpected pin count %d\n", sc->sc_npins);
    330 		goto out;
    331 	}
    332 
    333 	sc->sc_pins =
    334 	    kmem_zalloc(sizeof(*sc->sc_pins) * sc->sc_npins, KM_SLEEP);
    335 
    336 	for (j = 0; j < sc->sc_npins; j++) {
    337 		sc->sc_pins[j].pin_num = j;
    338 		sc->sc_pins[j].pin_caps =
    339 		    GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_INOUT |
    340 		    GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN | GPIO_PIN_INVIN;
    341 		sc->sc_pins[j].pin_intrcaps =
    342 		    GPIO_INTR_POS_EDGE | GPIO_INTR_NEG_EDGE |
    343 		    GPIO_INTR_DOUBLE_EDGE | GPIO_INTR_HIGH_LEVEL |
    344 		    GPIO_INTR_LOW_LEVEL | GPIO_INTR_MPSAFE;
    345 		sc->sc_pins[j].pin_state = igpio_pin_read(sc, j);
    346 	}
    347 
    348 	sc->sc_gc.gp_cookie = sc;
    349 	sc->sc_gc.gp_pin_read = igpio_pin_read;
    350 	sc->sc_gc.gp_pin_write = igpio_pin_write;
    351 	sc->sc_gc.gp_pin_ctl = igpio_pin_ctl;
    352 	sc->sc_gc.gp_intr_establish = igpio_intr_establish;
    353 	sc->sc_gc.gp_intr_disestablish = igpio_intr_disestablish;
    354 	sc->sc_gc.gp_intr_str = igpio_intr_str;
    355 
    356 	memset(&gba, 0, sizeof(gba));
    357 	gba.gba_gc = &sc->sc_gc;
    358 	gba.gba_pins = sc->sc_pins;
    359 	gba.gba_npins = sc->sc_npins;
    360 
    361 #if NGPIO > 0
    362 	config_found(sc->sc_dev, &gba, gpiobus_print, CFARGS_NONE);
    363 #endif
    364 
    365 	success = 1;
    366 out:
    367 	if (!success)
    368 		igpio_detach(sc);
    369 
    370 	return;
    371 }
    372 
    373 void
    374 igpio_detach(struct igpio_softc *sc)
    375 {
    376 	int i;
    377 
    378 	for (i = 0; i < sc->sc_nbar; i++) {
    379 		struct igpio_bank *ib = &sc->sc_banks[i];
    380 		struct igpio_bank_setup *ibs = ib->ib_setup;
    381 		int npins = 1 + ibs->ibs_last_pin - ibs->ibs_first_pin;
    382 
    383 		if (ib->ib_intr != NULL) {
    384 			kmem_free(ib->ib_intr, sizeof(*ib->ib_intr) * npins);
    385 			ib->ib_intr = NULL;
    386 		}
    387 	}
    388 
    389 	if (sc->sc_pins != NULL) {
    390 		kmem_free(sc->sc_pins, sizeof(*sc->sc_pins) * sc->sc_npins);
    391 		sc->sc_pins = NULL;
    392 	}
    393 
    394 	if (sc->sc_banks != NULL) {
    395 		kmem_free(sc->sc_banks, sizeof(*sc->sc_banks) * sc->sc_nbar);
    396 		sc->sc_banks = NULL;
    397 	}
    398 
    399 	return;
    400 }
    401 
    402 static bus_addr_t
    403 igpio_pincfg(struct igpio_bank *ib, int pin, int reg)
    404 {
    405 	int nregs = (ib->ib_cap & IGPIO_PINCTRL_FEATURE_DEBOUNCE) ? 4 : 2;
    406 	bus_addr_t pincfg;
    407 
    408 	pincfg = ib->ib_padbar + reg + (pin * nregs * 4);
    409 #if 0
    410 	DPRINTF(("%s bar %d pin %d reg #%x pincfg = %p\n",
    411 	    __func__, ib->ib_barno, pin, reg, (void *)pincfg));
    412 #endif
    413 	return pincfg;
    414 }
    415 
    416 #if notyet
    417 static struct igpio_pin_group *
    418 igpio_find_group(struct igpio_bank *ib, int pin)
    419 {
    420 	struct igpio_bank_setup *ibs = ib->ib_setup;
    421 	struct igpio_pin_group *found_ipg = NULL;
    422 	struct igpio_pin_group *ipg;
    423 
    424 	if (pin > ibs->ibs_last_pin) {
    425 		DPRINTF(("%s: barno %d, pin = %d > past pin = %d\n", __func__,
    426 		    ibs->ibs_barno, pin, ibs->ibs_last_pin));
    427 		return NULL;
    428 	}
    429 
    430 	for (ipg = igpio_pin_group; ipg->ipg_acpi_hid; ipg++) {
    431 		if (strcmp(ipg->ipg_acpi_hid, ibs->ibs_acpi_hid) != 0)
    432 			continue;
    433 
    434 		if (pin > ipg->ipg_first_pin) {
    435 			found_ipg = ipg;
    436 			continue;
    437 		}
    438 	}
    439 
    440 	return found_ipg;
    441 }
    442 
    443 static bus_addr_t
    444 igpio_groupcfg(struct igpio_bank *ib, int pin)
    445 {
    446 	struct igpio_bank_setup *ibs = ib->ib_setup;
    447 	struct igpio_pin_group *ipg;
    448 	bus_addr_t groupcfg;
    449 
    450 	if ((ipg = igpio_find_group(ib, pin)) == NULL)
    451 		return (bus_addr_t)NULL;
    452 
    453 	groupcfg = ib->ib_padbar
    454 		 + (ipg->ipg_groupno * 4)
    455 		 + (pin - ipg->ipg_first_pin) / 2;
    456 
    457 	DPRINTF(("%s: barno %d, pin = %d, found group %d \"%s\", cfg %p\n", \
    458 	    __func__, ibs->ibs_barno, pin, ipg->ipg_groupno,		    \
    459 	    ipg->ipg_name, (void *)groupcfg));
    460 
    461 	return groupcfg;
    462 }
    463 #endif
    464 
    465 
    466 int
    467 igpio_pin_read(void *priv, int pin)
    468 {
    469 	struct igpio_softc *sc = priv;
    470 	struct igpio_bank *ib = igpio_find_bank(sc, pin);
    471 	bus_addr_t cfg0;
    472 	uint32_t val;
    473 
    474 	pin = igpio_bank_pin(ib, pin);
    475 	cfg0  = igpio_pincfg(ib, pin, IGPIO_PADCFG0);
    476 
    477 	mutex_enter(&ib->ib_mtx);
    478 
    479 	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0);
    480 	DPRINTF(("%s: bar %d pin %d val #%x (%s)\n", __func__,
    481 	    ib->ib_barno, pin, val, igpio_padcfg0_print(val, 0)));
    482 
    483 	if (val & IGPIO_PADCFG0_GPIOTXDIS)
    484 		val = (val & IGPIO_PADCFG0_GPIORXSTATE) ? 1 : 0;
    485 	else
    486 		val = (val & IGPIO_PADCFG0_GPIOTXSTATE) ? 1 : 0;
    487 
    488 	mutex_exit(&ib->ib_mtx);
    489 
    490 	return val;
    491 }
    492 
    493 void
    494 igpio_pin_write(void *priv, int pin, int value)
    495 {
    496 	struct igpio_softc *sc = priv;
    497 	struct igpio_bank *ib = igpio_find_bank(sc, pin);
    498 	bus_addr_t cfg0;
    499 	uint32_t val, newval;
    500 
    501 	pin = igpio_bank_pin(ib, pin);
    502 	cfg0 = igpio_pincfg(ib, pin, IGPIO_PADCFG0);
    503 
    504 	mutex_enter(&ib->ib_mtx);
    505 
    506 	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0);
    507 
    508 	if (value)
    509 		newval = val |  IGPIO_PADCFG0_GPIOTXSTATE;
    510 	else
    511 		newval = val & ~IGPIO_PADCFG0_GPIOTXSTATE;
    512 
    513 	DPRINTF(("%s: bar %d pin %d value %d val #%x (%s) -> #%x (%s)\n",
    514 	    __func__, ib->ib_barno, pin, value,
    515 	    val, igpio_padcfg0_print(val, 0),
    516 	    newval, igpio_padcfg0_print(newval, 1)));
    517 
    518 	bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0, newval);
    519 
    520 	mutex_exit(&ib->ib_mtx);
    521 
    522 	return;
    523 }
    524 
    525 void
    526 igpio_pin_ctl(void *priv, int pin, int flags)
    527 {
    528 	struct igpio_softc *sc = priv;
    529 	struct igpio_bank *ib = igpio_find_bank(sc, pin);
    530 	bus_addr_t cfg0, cfg1;
    531 	uint32_t val0, newval0;
    532 	uint32_t val1, newval1;
    533 
    534 	pin = igpio_bank_pin(ib, pin);
    535 	cfg0  = igpio_pincfg(ib, pin, IGPIO_PADCFG0);
    536 	cfg1  = igpio_pincfg(ib, pin, IGPIO_PADCFG1);
    537 
    538 	mutex_enter(&ib->ib_mtx);
    539 
    540 	val0 = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0);
    541 	val1 = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg1);
    542 
    543 	newval0 = val0;
    544 	newval1 = val1;
    545 
    546 	newval0 &= ~IGPIO_PADCFG0_PMODE_MASK;
    547 	newval0 |=  IGPIO_PADCFG0_PMODE_GPIO;
    548 
    549 	newval0 |= IGPIO_PADCFG0_GPIORXDIS;
    550 	newval0 |= IGPIO_PADCFG0_GPIOTXDIS;
    551 
    552 	newval0 &= ~(IGPIO_PADCFG0_GPIROUTIOXAPIC | IGPIO_PADCFG0_GPIROUTSCI);
    553 	newval0 &= ~(IGPIO_PADCFG0_GPIROUTSMI | IGPIO_PADCFG0_GPIROUTNMI);
    554 
    555 	if (flags & GPIO_PIN_INPUT) {
    556 		newval0 &= ~IGPIO_PADCFG0_GPIORXDIS;
    557 		newval0 |=  IGPIO_PADCFG0_GPIOTXDIS;
    558 	}
    559 
    560 	if (flags & GPIO_PIN_OUTPUT) {
    561 		newval0 &= ~IGPIO_PADCFG0_GPIOTXDIS;
    562 		newval0 |=  IGPIO_PADCFG0_GPIORXDIS;
    563 	}
    564 
    565 	if (flags & GPIO_PIN_INOUT) {
    566 		newval0 &= ~IGPIO_PADCFG0_GPIOTXDIS;
    567 		newval0 &= ~IGPIO_PADCFG0_GPIORXDIS;
    568 	}
    569 
    570 	if (flags & GPIO_PIN_INVIN)
    571 		newval0 |=  IGPIO_PADCFG0_RXINV;
    572 	else
    573 		newval0 &= ~IGPIO_PADCFG0_RXINV;
    574 
    575 	newval1 &= ~IGPIO_PADCFG1_TERM_MASK;
    576 	if (flags & GPIO_PIN_PULLUP) {
    577 		newval1 |=  IGPIO_PADCFG1_TERM_UP;
    578 		newval1 |=  IGPIO_PADCFG1_TERM_5K;
    579 	}
    580 
    581 	if (flags & GPIO_PIN_PULLDOWN) {
    582 		newval1 &= ~IGPIO_PADCFG1_TERM_UP;
    583 		newval1 |=  IGPIO_PADCFG1_TERM_5K;
    584 	}
    585 
    586 	DPRINTF(("%s: bar %d pin %d flags #%x val0 #%x (%s) -> #%x (%s), "
    587 	    "val1 #%x -> #%x\n", __func__, ib->ib_barno, pin, flags,
    588 	    val0, igpio_padcfg0_print(val0, 0),
    589 	    newval0, igpio_padcfg0_print(newval0, 1),
    590 	    val1, newval1));
    591 
    592 	bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0, newval0);
    593 	bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg1, newval1);
    594 
    595 	mutex_exit(&ib->ib_mtx);
    596 
    597 	return;
    598 }
    599 
    600 void *
    601 igpio_intr_establish(void *priv, int pin, int ipl, int irqmode,
    602     int (*func)(void *), void *arg)
    603 {
    604 	struct igpio_softc *sc = priv;
    605 	struct igpio_bank *ib = igpio_find_bank(sc, pin);
    606 	bus_addr_t cfg0;
    607 	uint32_t val, newval;
    608 	struct igpio_intr *ii;
    609 
    610 	pin = igpio_bank_pin(ib, pin);
    611 	cfg0 = igpio_pincfg(ib, pin, IGPIO_PADCFG0);
    612 
    613 	ii = &ib->ib_intr[pin];
    614 	ii->ii_func = func;
    615 	ii->ii_arg = arg;
    616 	ii->ii_pin = pin;
    617 	ii->ii_bank = ib;
    618 
    619 	mutex_enter(&ib->ib_mtx);
    620 
    621 	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0);
    622 	newval = val;
    623 
    624 	newval &= ~IGPIO_PADCFG0_PMODE_MASK;
    625 	newval |=  IGPIO_PADCFG0_PMODE_GPIO;
    626 
    627 	newval &= ~IGPIO_PADCFG0_GPIORXDIS;
    628 	newval |=  IGPIO_PADCFG0_GPIOTXDIS;
    629 
    630 	newval |= (IGPIO_PADCFG0_GPIROUTIOXAPIC | IGPIO_PADCFG0_GPIROUTSCI);
    631 	newval |= (IGPIO_PADCFG0_GPIROUTSMI | IGPIO_PADCFG0_GPIROUTNMI);
    632 
    633 	newval &= ~IGPIO_PADCFG0_RXINV;
    634 	newval &= ~IGPIO_PADCFG0_RXEVCFG_EDGE;
    635 	newval &= ~IGPIO_PADCFG0_RXEVCFG_LEVEL;
    636 	newval &= ~IGPIO_PADCFG0_RXEVCFG_DISABLED;
    637 
    638 	switch (irqmode & GPIO_INTR_EDGE_MASK) {
    639 	case GPIO_INTR_DOUBLE_EDGE:
    640 		newval |= IGPIO_PADCFG0_RXEVCFG_EDGE_BOTH;
    641 		break;
    642 	case GPIO_INTR_NEG_EDGE:
    643 		newval |= IGPIO_PADCFG0_RXEVCFG_EDGE;
    644 		newval |= IGPIO_PADCFG0_RXINV;
    645 		break;
    646 	case GPIO_INTR_POS_EDGE:
    647 		newval |= IGPIO_PADCFG0_RXEVCFG_EDGE;
    648 		break;
    649 	default:
    650 		switch (irqmode & GPIO_INTR_LEVEL_MASK) {
    651 		case GPIO_INTR_HIGH_LEVEL:
    652 			newval |= IGPIO_PADCFG0_RXEVCFG_LEVEL;
    653 			break;
    654 		case GPIO_INTR_LOW_LEVEL:
    655 			newval |= IGPIO_PADCFG0_RXEVCFG_LEVEL;
    656 			newval |= IGPIO_PADCFG0_RXINV;
    657 			break;
    658 		default:
    659 			newval |= IGPIO_PADCFG0_RXEVCFG_DISABLED;
    660 			break;
    661 		}
    662 		break;
    663 	}
    664 
    665 
    666 	DPRINTF(("%s: bar %d pin %d val #%x (%s) -> #%x (%s)\n",
    667 	    __func__, ib->ib_barno, pin,
    668 	    val, igpio_padcfg0_print(val, 0),
    669 	    newval, igpio_padcfg0_print(newval, 1)));
    670 
    671 	bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0, newval);
    672 
    673 	mutex_exit(&ib->ib_mtx);
    674 
    675 	return ii;
    676 }
    677 
    678 void
    679 igpio_intr_disestablish(void *priv, void *ih)
    680 {
    681 	struct igpio_softc *sc = priv;
    682 	struct igpio_bank *ib;
    683 	struct igpio_intr *ii = ih;
    684 	int pin;
    685 	bus_addr_t cfg0;
    686 	uint32_t val, newval;
    687 
    688 	if (ih == NULL)
    689 		return;
    690 
    691 	pin = ii->ii_pin;
    692 	ib = igpio_find_bank(sc, pin);
    693 	pin = igpio_bank_pin(ib, pin);
    694 	cfg0  = igpio_pincfg(ib, pin, IGPIO_PADCFG0);
    695 
    696 	mutex_enter(&ib->ib_mtx);
    697 
    698 	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0);
    699 	newval = val;
    700 
    701 	newval &= ~IGPIO_PADCFG0_PMODE_MASK;
    702 	newval |=  IGPIO_PADCFG0_PMODE_GPIO;
    703 
    704 	newval &= ~(IGPIO_PADCFG0_GPIROUTIOXAPIC | IGPIO_PADCFG0_GPIROUTSCI);
    705 	newval &= ~(IGPIO_PADCFG0_GPIROUTSMI | IGPIO_PADCFG0_GPIROUTNMI);
    706 
    707 	DPRINTF(("%s: bar %d pin %d val #%x (%s) -> #%x (%s)\n", \
    708 	    __func__, ib->ib_barno, pin,
    709 	    val, igpio_padcfg0_print(val, 0),
    710 	    newval, igpio_padcfg0_print(newval, 1)));
    711 
    712 	bus_space_write_4(sc->sc_bst, sc->sc_bsh[ib->ib_barno], cfg0, newval);
    713 
    714 	mutex_exit(&ib->ib_mtx);
    715 
    716 	ii->ii_func = NULL;
    717 	ii->ii_arg = NULL;
    718 
    719 	return;
    720 }
    721 
    722 bool
    723 igpio_intr_str(void *priv, int pin, int irqmode,
    724     char *buf, size_t buflen)
    725 {
    726 	struct igpio_softc *sc = priv;
    727 	const char *name = device_xname(sc->sc_dev);
    728 	int rv;
    729 
    730 	rv = snprintf(buf, buflen, "%s pin %d", name, pin);
    731 
    732 	return (rv < buflen);
    733 }
    734 
    735 int
    736 igpio_intr(void *priv)
    737 {
    738 	struct igpio_softc *sc = priv;
    739 	int i;
    740 	int ret = 0;
    741 
    742 	for (i = 0; i < sc->sc_nbar; i++) {
    743 		struct igpio_bank *ib = &sc->sc_banks[i];
    744 		struct igpio_bank_setup *ibs = ib->ib_setup;
    745 		bus_space_handle_t bsh = sc->sc_bsh[i];
    746 		struct igpio_pin_group *ipg;
    747 
    748 		mutex_enter(&ib->ib_mtx);
    749 
    750 		for (ipg = igpio_pin_group; ipg->ipg_acpi_hid; ipg++) {
    751 			int offset;
    752 			bus_addr_t is_reg;
    753 			bus_addr_t ie_reg;
    754 			uint32_t raised;
    755 			uint32_t pending;
    756 			uint32_t enabled;
    757 			int b;
    758 
    759 			if (strcmp(ipg->ipg_acpi_hid,
    760 			    ibs->ibs_acpi_hid) != 0)
    761 				continue;
    762 
    763 			offset = ib->ib_padbar + ipg->ipg_groupno * 4;
    764 			is_reg = offset + ibs->ibs_gpi_is;
    765 			ie_reg = offset + ibs->ibs_gpi_ie;
    766 
    767 			raised = bus_space_read_4(sc->sc_bst, bsh, is_reg);
    768 			enabled = bus_space_read_4(sc->sc_bst, bsh, ie_reg);
    769 
    770 			/*
    771 			 * find pins for which interrupt is pending
    772 			 * and enabled
    773 			 */
    774 			pending = raised & enabled;
    775 
    776 			for (b = 0; b < 32; b++) {
    777 				int pin;
    778 				int (*func)(void *);
    779 				void *arg;
    780 
    781 				if ((pending & (1 << b)) == 0)
    782 					continue;
    783 
    784 				pin = ipg->ipg_first_pin + b;
    785 				func = ib->ib_intr[pin].ii_func;
    786 				arg = ib->ib_intr[pin].ii_arg;
    787 
    788 				/* XXX ack intr, handled or not? */
    789 				raised &= ~(1 << b);
    790 
    791 				if (func == NULL)
    792 					continue;
    793 
    794 				ret |= func(arg);
    795 			}
    796 
    797 			bus_space_write_4(sc->sc_bst, bsh, is_reg, raised);
    798 
    799 		}
    800 
    801 		mutex_exit(&ib->ib_mtx);
    802 
    803 	}
    804 
    805 	return ret;
    806 }
    807