Home | History | Annotate | Line # | Download | only in sunxi
sunxi_gpio.c revision 1.16
      1 /* $NetBSD: sunxi_gpio.c,v 1.16 2017/10/11 10:52:54 jmcneill Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2017 Jared McNeill <jmcneill (at) invisible.ca>
      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 AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include "opt_soc.h"
     30 
     31 #include <sys/cdefs.h>
     32 __KERNEL_RCSID(0, "$NetBSD: sunxi_gpio.c,v 1.16 2017/10/11 10:52:54 jmcneill Exp $");
     33 
     34 #include <sys/param.h>
     35 #include <sys/bus.h>
     36 #include <sys/device.h>
     37 #include <sys/intr.h>
     38 #include <sys/systm.h>
     39 #include <sys/mutex.h>
     40 #include <sys/kmem.h>
     41 #include <sys/gpio.h>
     42 #include <sys/bitops.h>
     43 #include <sys/lwp.h>
     44 
     45 #include <dev/fdt/fdtvar.h>
     46 #include <dev/gpio/gpiovar.h>
     47 
     48 #include <arm/sunxi/sunxi_gpio.h>
     49 
     50 #define	SUNXI_GPIO_MAX_EINT_BANK	5
     51 #define	SUNXI_GPIO_MAX_EINT		32
     52 
     53 #define	SUNXI_GPIO_PORT(port)		(0x24 * (port))
     54 #define SUNXI_GPIO_CFG(port, pin)	(SUNXI_GPIO_PORT(port) + 0x00 + (0x4 * ((pin) / 8)))
     55 #define  SUNXI_GPIO_CFG_PINMASK(pin)	(0x7 << (((pin) % 8) * 4))
     56 #define	SUNXI_GPIO_DATA(port)		(SUNXI_GPIO_PORT(port) + 0x10)
     57 #define	SUNXI_GPIO_DRV(port, pin)	(SUNXI_GPIO_PORT(port) + 0x14 + (0x4 * ((pin) / 16)))
     58 #define  SUNXI_GPIO_DRV_PINMASK(pin)	(0x3 << (((pin) % 16) * 2))
     59 #define	SUNXI_GPIO_PULL(port, pin)	(SUNXI_GPIO_PORT(port) + 0x1c + (0x4 * ((pin) / 16)))
     60 #define	 SUNXI_GPIO_PULL_DISABLE	0
     61 #define	 SUNXI_GPIO_PULL_UP		1
     62 #define	 SUNXI_GPIO_PULL_DOWN		2
     63 #define  SUNXI_GPIO_PULL_PINMASK(pin)	(0x3 << (((pin) % 16) * 2))
     64 #define	SUNXI_GPIO_INT_CFG(bank, eint)	(0x200 + (0x20 * (bank)) + (0x4 * ((eint) / 8)))
     65 #define	 SUNXI_GPIO_INT_MODEMASK(eint)	(0xf << (((eint) % 8) * 4))
     66 #define	  SUNXI_GPIO_INT_MODE_POS_EDGE		0x0
     67 #define	  SUNXI_GPIO_INT_MODE_NEG_EDGE		0x1
     68 #define	  SUNXI_GPIO_INT_MODE_HIGH_LEVEL	0x2
     69 #define	  SUNXI_GPIO_INT_MODE_LOW_LEVEL		0x3
     70 #define	  SUNXI_GPIO_INT_MODE_DOUBLE_EDGE	0x4
     71 #define	SUNXI_GPIO_INT_CTL(bank)	(0x210 + 0x20 * (bank))
     72 #define	SUNXI_GPIO_INT_STATUS(bank)	(0x214 + 0x20 * (bank))
     73 
     74 static const struct of_compat_data compat_data[] = {
     75 #ifdef SOC_SUN4I_A10
     76 	{ "allwinner,sun4i-a10-pinctrl",	(uintptr_t)&sun4i_a10_padconf },
     77 #endif
     78 #ifdef SOC_SUN5I_A13
     79 	{ "allwinner,sun5i-a13-pinctrl",	(uintptr_t)&sun5i_a13_padconf },
     80 #endif
     81 #ifdef SOC_SUN6I_A31
     82 	{ "allwinner,sun6i-a31-pinctrl",	(uintptr_t)&sun6i_a31_padconf },
     83 	{ "allwinner,sun6i-a31-r-pinctrl",	(uintptr_t)&sun6i_a31_r_padconf },
     84 #endif
     85 #ifdef SOC_SUN7I_A20
     86 	{ "allwinner,sun7i-a20-pinctrl",	(uintptr_t)&sun7i_a20_padconf },
     87 #endif
     88 #ifdef SOC_SUN8I_A83T
     89 	{ "allwinner,sun8i-a83t-pinctrl",	(uintptr_t)&sun8i_a83t_padconf },
     90 	{ "allwinner,sun8i-a83t-r-pinctrl",	(uintptr_t)&sun8i_a83t_r_padconf },
     91 #endif
     92 #ifdef SOC_SUN8I_H3
     93 	{ "allwinner,sun8i-h3-pinctrl",		(uintptr_t)&sun8i_h3_padconf },
     94 	{ "allwinner,sun8i-h3-r-pinctrl",	(uintptr_t)&sun8i_h3_r_padconf },
     95 #endif
     96 #ifdef SOC_SUN9I_A80
     97 	{ "allwinner,sun9i-a80-pinctrl",	(uintptr_t)&sun9i_a80_padconf },
     98 	{ "allwinner,sun9i-a80-r-pinctrl",	(uintptr_t)&sun9i_a80_r_padconf },
     99 #endif
    100 #ifdef SOC_SUN50I_A64
    101 	{ "allwinner,sun50i-a64-pinctrl",	(uintptr_t)&sun50i_a64_padconf },
    102 	{ "allwinner,sun50i-a64-r-pinctrl",	(uintptr_t)&sun50i_a64_r_padconf },
    103 #endif
    104 #ifdef SOC_SUN50I_H5
    105 	{ "allwinner,sun50i-h5-pinctrl",	(uintptr_t)&sun8i_h3_padconf },
    106 	{ "allwinner,sun50i-h5-r-pinctrl",	(uintptr_t)&sun8i_h3_r_padconf },
    107 #endif
    108 	{ NULL }
    109 };
    110 
    111 struct sunxi_gpio_eint {
    112 	int (*eint_func)(void *);
    113 	void *eint_arg;
    114 	int eint_flags;
    115 	int eint_bank;
    116 	int eint_num;
    117 };
    118 
    119 struct sunxi_gpio_softc {
    120 	device_t sc_dev;
    121 	bus_space_tag_t sc_bst;
    122 	bus_space_handle_t sc_bsh;
    123 	const struct sunxi_gpio_padconf *sc_padconf;
    124 	kmutex_t sc_lock;
    125 
    126 	struct gpio_chipset_tag sc_gp;
    127 	gpio_pin_t *sc_pins;
    128 	device_t sc_gpiodev;
    129 
    130 	u_int sc_eint_bank_max;
    131 
    132 	void *sc_ih;
    133 	struct sunxi_gpio_eint sc_eint[SUNXI_GPIO_MAX_EINT_BANK][SUNXI_GPIO_MAX_EINT];
    134 };
    135 
    136 struct sunxi_gpio_pin {
    137 	struct sunxi_gpio_softc *pin_sc;
    138 	const struct sunxi_gpio_pins *pin_def;
    139 	int pin_flags;
    140 	bool pin_actlo;
    141 };
    142 
    143 #define GPIO_READ(sc, reg) 		\
    144     bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
    145 #define GPIO_WRITE(sc, reg, val) 	\
    146     bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
    147 
    148 static int	sunxi_gpio_match(device_t, cfdata_t, void *);
    149 static void	sunxi_gpio_attach(device_t, device_t, void *);
    150 
    151 CFATTACH_DECL_NEW(sunxi_gpio, sizeof(struct sunxi_gpio_softc),
    152 	sunxi_gpio_match, sunxi_gpio_attach, NULL, NULL);
    153 
    154 static const struct sunxi_gpio_pins *
    155 sunxi_gpio_lookup(struct sunxi_gpio_softc *sc, uint8_t port, uint8_t pin)
    156 {
    157 	const struct sunxi_gpio_pins *pin_def;
    158 	u_int n;
    159 
    160 	for (n = 0; n < sc->sc_padconf->npins; n++) {
    161 		pin_def = &sc->sc_padconf->pins[n];
    162 		if (pin_def->port == port && pin_def->pin == pin)
    163 			return pin_def;
    164 	}
    165 
    166 	return NULL;
    167 }
    168 
    169 static const struct sunxi_gpio_pins *
    170 sunxi_gpio_lookup_byname(struct sunxi_gpio_softc *sc, const char *name)
    171 {
    172 	const struct sunxi_gpio_pins *pin_def;
    173 	u_int n;
    174 
    175 	for (n = 0; n < sc->sc_padconf->npins; n++) {
    176 		pin_def = &sc->sc_padconf->pins[n];
    177 		if (strcmp(pin_def->name, name) == 0)
    178 			return pin_def;
    179 	}
    180 
    181 	return NULL;
    182 }
    183 
    184 static int
    185 sunxi_gpio_setfunc(struct sunxi_gpio_softc *sc,
    186     const struct sunxi_gpio_pins *pin_def, const char *func)
    187 {
    188 	uint32_t cfg;
    189 	u_int n;
    190 
    191 	KASSERT(mutex_owned(&sc->sc_lock));
    192 
    193 	const bus_size_t cfg_reg = SUNXI_GPIO_CFG(pin_def->port, pin_def->pin);
    194 	const uint32_t cfg_mask = SUNXI_GPIO_CFG_PINMASK(pin_def->pin);
    195 
    196 	for (n = 0; n < SUNXI_GPIO_MAXFUNC; n++) {
    197 		if (pin_def->functions[n] == NULL)
    198 			continue;
    199 		if (strcmp(pin_def->functions[n], func) == 0) {
    200 			cfg = GPIO_READ(sc, cfg_reg);
    201 			cfg &= ~cfg_mask;
    202 			cfg |= __SHIFTIN(n, cfg_mask);
    203 #ifdef SUNXI_GPIO_DEBUG
    204 			device_printf(sc->sc_dev, "P%c%02d cfg %08x -> %08x\n",
    205 			    pin_def->port + 'A', pin_def->pin, GPIO_READ(sc, cfg_reg), cfg);
    206 #endif
    207 			GPIO_WRITE(sc, cfg_reg, cfg);
    208 			return 0;
    209 		}
    210 	}
    211 
    212 	/* Function not found */
    213 	device_printf(sc->sc_dev, "function '%s' not supported on P%c%02d\n",
    214 	    func, pin_def->port + 'A', pin_def->pin);
    215 
    216 	return ENXIO;
    217 }
    218 
    219 static int
    220 sunxi_gpio_setpull(struct sunxi_gpio_softc *sc,
    221     const struct sunxi_gpio_pins *pin_def, int flags)
    222 {
    223 	uint32_t pull;
    224 
    225 	KASSERT(mutex_owned(&sc->sc_lock));
    226 
    227 	const bus_size_t pull_reg = SUNXI_GPIO_PULL(pin_def->port, pin_def->pin);
    228 	const uint32_t pull_mask = SUNXI_GPIO_PULL_PINMASK(pin_def->pin);
    229 
    230 	pull = GPIO_READ(sc, pull_reg);
    231 	pull &= ~pull_mask;
    232 	if (flags & GPIO_PIN_PULLUP)
    233 		pull |= __SHIFTIN(SUNXI_GPIO_PULL_UP, pull_mask);
    234 	else if (flags & GPIO_PIN_PULLDOWN)
    235 		pull |= __SHIFTIN(SUNXI_GPIO_PULL_DOWN, pull_mask);
    236 	else
    237 		pull |= __SHIFTIN(SUNXI_GPIO_PULL_DISABLE, pull_mask);
    238 #ifdef SUNXI_GPIO_DEBUG
    239 	device_printf(sc->sc_dev, "P%c%02d pull %08x -> %08x\n",
    240 	    pin_def->port + 'A', pin_def->pin, GPIO_READ(sc, pull_reg), pull);
    241 #endif
    242 	GPIO_WRITE(sc, pull_reg, pull);
    243 
    244 	return 0;
    245 }
    246 
    247 static int
    248 sunxi_gpio_setdrv(struct sunxi_gpio_softc *sc,
    249     const struct sunxi_gpio_pins *pin_def, int drive_strength)
    250 {
    251 	uint32_t drv;
    252 
    253 	KASSERT(mutex_owned(&sc->sc_lock));
    254 
    255 	if (drive_strength < 10 || drive_strength > 40)
    256 		return EINVAL;
    257 
    258 	const bus_size_t drv_reg = SUNXI_GPIO_DRV(pin_def->port, pin_def->pin);
    259 	const uint32_t drv_mask = SUNXI_GPIO_DRV_PINMASK(pin_def->pin);
    260 
    261 	drv = GPIO_READ(sc, drv_reg);
    262 	drv &= ~drv_mask;
    263 	drv |= __SHIFTIN((drive_strength / 10) - 1, drv_mask);
    264 #ifdef SUNXI_GPIO_DEBUG
    265 	device_printf(sc->sc_dev, "P%c%02d drv %08x -> %08x\n",
    266 	    pin_def->port + 'A', pin_def->pin, GPIO_READ(sc, drv_reg), drv);
    267 #endif
    268 	GPIO_WRITE(sc, drv_reg, drv);
    269 
    270 	return 0;
    271 }
    272 
    273 static int
    274 sunxi_gpio_ctl(struct sunxi_gpio_softc *sc, const struct sunxi_gpio_pins *pin_def,
    275     int flags)
    276 {
    277 	KASSERT(mutex_owned(&sc->sc_lock));
    278 
    279 	if (flags & GPIO_PIN_INPUT)
    280 		return sunxi_gpio_setfunc(sc, pin_def, "gpio_in");
    281 	if (flags & GPIO_PIN_OUTPUT)
    282 		return sunxi_gpio_setfunc(sc, pin_def, "gpio_out");
    283 
    284 	return EINVAL;
    285 }
    286 
    287 static void *
    288 sunxi_gpio_acquire(device_t dev, const void *data, size_t len, int flags)
    289 {
    290 	struct sunxi_gpio_softc * const sc = device_private(dev);
    291 	const struct sunxi_gpio_pins *pin_def;
    292 	struct sunxi_gpio_pin *gpin;
    293 	const u_int *gpio = data;
    294 	int error;
    295 
    296 	if (len != 16)
    297 		return NULL;
    298 
    299 	const uint8_t port = be32toh(gpio[1]) & 0xff;
    300 	const uint8_t pin = be32toh(gpio[2]) & 0xff;
    301 	const bool actlo = be32toh(gpio[3]) & 1;
    302 
    303 	pin_def = sunxi_gpio_lookup(sc, port, pin);
    304 	if (pin_def == NULL)
    305 		return NULL;
    306 
    307 	mutex_enter(&sc->sc_lock);
    308 	error = sunxi_gpio_ctl(sc, pin_def, flags);
    309 	mutex_exit(&sc->sc_lock);
    310 
    311 	if (error != 0)
    312 		return NULL;
    313 
    314 	gpin = kmem_zalloc(sizeof(*gpin), KM_SLEEP);
    315 	gpin->pin_sc = sc;
    316 	gpin->pin_def = pin_def;
    317 	gpin->pin_flags = flags;
    318 	gpin->pin_actlo = actlo;
    319 
    320 	return gpin;
    321 }
    322 
    323 static void
    324 sunxi_gpio_release(device_t dev, void *priv)
    325 {
    326 	struct sunxi_gpio_pin *pin = priv;
    327 
    328 	sunxi_gpio_ctl(pin->pin_sc, pin->pin_def, GPIO_PIN_INPUT);
    329 
    330 	kmem_free(pin, sizeof(*pin));
    331 }
    332 
    333 static int
    334 sunxi_gpio_read(device_t dev, void *priv, bool raw)
    335 {
    336 	struct sunxi_gpio_softc * const sc = device_private(dev);
    337 	struct sunxi_gpio_pin *pin = priv;
    338 	const struct sunxi_gpio_pins *pin_def = pin->pin_def;
    339 	uint32_t data;
    340 	int val;
    341 
    342 	KASSERT(sc == pin->pin_sc);
    343 
    344 	const bus_size_t data_reg = SUNXI_GPIO_DATA(pin_def->port);
    345 	const uint32_t data_mask = __BIT(pin_def->pin);
    346 
    347 	/* No lock required for reads */
    348 	data = GPIO_READ(sc, data_reg);
    349 	val = __SHIFTOUT(data, data_mask);
    350 	if (!raw && pin->pin_actlo)
    351 		val = !val;
    352 
    353 #ifdef SUNXI_GPIO_DEBUG
    354 	device_printf(dev, "P%c%02d rd %08x (%d %d)\n",
    355 	    pin_def->port + 'A', pin_def->pin, data,
    356 	    __SHIFTOUT(val, data_mask), val);
    357 #endif
    358 
    359 	return val;
    360 }
    361 
    362 static void
    363 sunxi_gpio_write(device_t dev, void *priv, int val, bool raw)
    364 {
    365 	struct sunxi_gpio_softc * const sc = device_private(dev);
    366 	struct sunxi_gpio_pin *pin = priv;
    367 	const struct sunxi_gpio_pins *pin_def = pin->pin_def;
    368 	uint32_t data;
    369 
    370 	KASSERT(sc == pin->pin_sc);
    371 
    372 	const bus_size_t data_reg = SUNXI_GPIO_DATA(pin_def->port);
    373 	const uint32_t data_mask = __BIT(pin_def->pin);
    374 
    375 	if (!raw && pin->pin_actlo)
    376 		val = !val;
    377 
    378 	mutex_enter(&sc->sc_lock);
    379 	data = GPIO_READ(sc, data_reg);
    380 	data &= ~data_mask;
    381 	data |= __SHIFTIN(val, data_mask);
    382 #ifdef SUNXI_GPIO_DEBUG
    383 	device_printf(dev, "P%c%02d wr %08x -> %08x\n",
    384 	    pin_def->port + 'A', pin_def->pin, GPIO_READ(sc, data_reg), data);
    385 #endif
    386 	GPIO_WRITE(sc, data_reg, data);
    387 	mutex_exit(&sc->sc_lock);
    388 }
    389 
    390 static struct fdtbus_gpio_controller_func sunxi_gpio_funcs = {
    391 	.acquire = sunxi_gpio_acquire,
    392 	.release = sunxi_gpio_release,
    393 	.read = sunxi_gpio_read,
    394 	.write = sunxi_gpio_write,
    395 };
    396 
    397 static int
    398 sunxi_gpio_intr(void *priv)
    399 {
    400 	struct sunxi_gpio_softc * const sc = priv;
    401 	struct sunxi_gpio_eint *eint;
    402 	uint32_t status, bit;
    403 	u_int bank;
    404 	int ret = 0;
    405 
    406 	for (bank = 0; bank <= sc->sc_eint_bank_max; bank++) {
    407 		status = GPIO_READ(sc, SUNXI_GPIO_INT_STATUS(bank));
    408 		if (status == 0)
    409 			continue;
    410 		GPIO_WRITE(sc, SUNXI_GPIO_INT_STATUS(bank), status);
    411 
    412 		while ((bit = ffs32(status)) != 0) {
    413 			status &= ~__BIT(bit - 1);
    414 			eint = &sc->sc_eint[bank][bit - 1];
    415 			if (eint->eint_func == NULL)
    416 				continue;
    417 			const bool mpsafe = (eint->eint_flags & FDT_INTR_MPSAFE) != 0;
    418 			if (!mpsafe)
    419 				KERNEL_LOCK(1, curlwp);
    420 			ret |= eint->eint_func(eint->eint_arg);
    421 			if (!mpsafe)
    422 				KERNEL_UNLOCK_ONE(curlwp);
    423 		}
    424 	}
    425 
    426 	return ret;
    427 }
    428 
    429 static void *
    430 sunxi_gpio_establish(device_t dev, u_int *specifier, int ipl, int flags,
    431     int (*func)(void *), void *arg)
    432 {
    433 	struct sunxi_gpio_softc * const sc = device_private(dev);
    434 	const struct sunxi_gpio_pins *pin_def;
    435 	struct sunxi_gpio_eint *eint;
    436 	uint32_t val;
    437 	u_int mode;
    438 
    439 	if (ipl != IPL_VM) {
    440 		aprint_error_dev(dev, "%s: wrong IPL %d (expected %d)\n",
    441 		    __func__, ipl, IPL_VM);
    442 		return NULL;
    443 	}
    444 
    445 	/* 1st cell is the bank */
    446 	/* 2nd cell is the pin */
    447 	/* 3rd cell is flags */
    448 	const u_int port = be32toh(specifier[0]);
    449 	const u_int pin = be32toh(specifier[1]);
    450 	const u_int type = be32toh(specifier[2]) & 0xf;
    451 
    452 	switch (type) {
    453 	case 0x1:
    454 		mode = SUNXI_GPIO_INT_MODE_POS_EDGE;
    455 		break;
    456 	case 0x2:
    457 		mode = SUNXI_GPIO_INT_MODE_NEG_EDGE;
    458 		break;
    459 	case 0x3:
    460 		mode = SUNXI_GPIO_INT_MODE_DOUBLE_EDGE;
    461 		break;
    462 	case 0x4:
    463 		mode = SUNXI_GPIO_INT_MODE_HIGH_LEVEL;
    464 		break;
    465 	case 0x8:
    466 		mode = SUNXI_GPIO_INT_MODE_LOW_LEVEL;
    467 		break;
    468 	default:
    469 		aprint_error_dev(dev, "%s: unsupported irq type 0x%x\n",
    470 		    __func__, type);
    471 		return NULL;
    472 	}
    473 
    474 	pin_def = sunxi_gpio_lookup(sc, port, pin);
    475 	if (pin_def == NULL)
    476 		return NULL;
    477 	if (pin_def->functions[pin_def->eint_func] == NULL ||
    478 	    strcmp(pin_def->functions[pin_def->eint_func], "eint") != 0)
    479 		return NULL;
    480 
    481 	KASSERT(pin_def->eint_num < SUNXI_GPIO_MAX_EINT);
    482 
    483 	mutex_enter(&sc->sc_lock);
    484 
    485 	eint = &sc->sc_eint[pin_def->eint_bank][pin_def->eint_num];
    486 	if (eint->eint_func != NULL) {
    487 		mutex_exit(&sc->sc_lock);
    488 		return NULL;	/* in use */
    489 	}
    490 
    491 	/* Set function */
    492 	if (sunxi_gpio_setfunc(sc, pin_def, "eint") != 0) {
    493 		mutex_exit(&sc->sc_lock);
    494 		return NULL;
    495 	}
    496 
    497 	eint->eint_func = func;
    498 	eint->eint_arg = arg;
    499 	eint->eint_flags = flags;
    500 	eint->eint_bank = pin_def->eint_bank;
    501 	eint->eint_num = pin_def->eint_num;
    502 
    503 	/* Configure eint mode */
    504 	val = GPIO_READ(sc, SUNXI_GPIO_INT_CFG(eint->eint_bank, eint->eint_num));
    505 	val &= ~SUNXI_GPIO_INT_MODEMASK(eint->eint_num);
    506 	val |= __SHIFTIN(mode, SUNXI_GPIO_INT_MODEMASK(eint->eint_num));
    507 	GPIO_WRITE(sc, SUNXI_GPIO_INT_CFG(eint->eint_bank, eint->eint_num), val);
    508 
    509 	/* Enable eint */
    510 	val = GPIO_READ(sc, SUNXI_GPIO_INT_CTL(eint->eint_bank));
    511 	val |= __BIT(eint->eint_num);
    512 	GPIO_WRITE(sc, SUNXI_GPIO_INT_CTL(eint->eint_bank), val);
    513 
    514 	mutex_exit(&sc->sc_lock);
    515 
    516 	return eint;
    517 }
    518 
    519 static void
    520 sunxi_gpio_disestablish(device_t dev, void *ih)
    521 {
    522 	struct sunxi_gpio_softc * const sc = device_private(dev);
    523 	struct sunxi_gpio_eint * const eint = ih;
    524 	uint32_t val;
    525 
    526 	KASSERT(eint->eint_func != NULL);
    527 
    528 	mutex_enter(&sc->sc_lock);
    529 
    530 	/* Disable eint */
    531 	val = GPIO_READ(sc, SUNXI_GPIO_INT_CTL(eint->eint_bank));
    532 	val &= ~__BIT(eint->eint_num);
    533 	GPIO_WRITE(sc, SUNXI_GPIO_INT_CTL(eint->eint_bank), val);
    534 	GPIO_WRITE(sc, SUNXI_GPIO_INT_STATUS(eint->eint_bank), __BIT(eint->eint_num));
    535 
    536 	eint->eint_func = NULL;
    537 	eint->eint_arg = NULL;
    538 	eint->eint_flags = 0;
    539 
    540 	mutex_exit(&sc->sc_lock);
    541 }
    542 
    543 static bool
    544 sunxi_gpio_intrstr(device_t dev, u_int *specifier, char *buf, size_t buflen)
    545 {
    546 	struct sunxi_gpio_softc * const sc = device_private(dev);
    547 	const struct sunxi_gpio_pins *pin_def;
    548 
    549 	/* 1st cell is the bank */
    550 	/* 2nd cell is the pin */
    551 	/* 3rd cell is flags */
    552 	if (!specifier)
    553 		return false;
    554 	const u_int port = be32toh(specifier[0]);
    555 	const u_int pin = be32toh(specifier[1]);
    556 
    557 	pin_def = sunxi_gpio_lookup(sc, port, pin);
    558 	if (pin_def == NULL)
    559 		return false;
    560 
    561 	snprintf(buf, buflen, "GPIO %s", pin_def->name);
    562 
    563 	return true;
    564 }
    565 
    566 static struct fdtbus_interrupt_controller_func sunxi_gpio_intrfuncs = {
    567 	.establish = sunxi_gpio_establish,
    568 	.disestablish = sunxi_gpio_disestablish,
    569 	.intrstr = sunxi_gpio_intrstr,
    570 };
    571 
    572 static const char *
    573 sunxi_pinctrl_parse_function(int phandle)
    574 {
    575 	const char *function;
    576 
    577 	function = fdtbus_get_string(phandle, "function");
    578 	if (function != NULL)
    579 		return function;
    580 
    581 	return fdtbus_get_string(phandle, "allwinner,function");
    582 }
    583 
    584 static const char *
    585 sunxi_pinctrl_parse_pins(int phandle, int *pins_len)
    586 {
    587 	int len;
    588 
    589 	len = OF_getproplen(phandle, "pins");
    590 	if (len > 0) {
    591 		*pins_len = len;
    592 		return fdtbus_get_string(phandle, "pins");
    593 	}
    594 
    595 	len = OF_getproplen(phandle, "allwinner,pins");
    596 	if (len > 0) {
    597 		*pins_len = len;
    598 		return fdtbus_get_string(phandle, "allwinner,pins");
    599 	}
    600 
    601 	return NULL;
    602 }
    603 
    604 static int
    605 sunxi_pinctrl_parse_bias(int phandle)
    606 {
    607 	u_int pull;
    608 	int bias = -1;
    609 
    610 	if (of_hasprop(phandle, "bias-disable"))
    611 		bias = 0;
    612 	else if (of_hasprop(phandle, "bias-pull-up"))
    613 		bias = GPIO_PIN_PULLUP;
    614 	else if (of_hasprop(phandle, "bias-pull-down"))
    615 		bias = GPIO_PIN_PULLDOWN;
    616 	else if (of_getprop_uint32(phandle, "allwinner,pull", &pull) == 0) {
    617 		switch (pull) {
    618 		case 0:
    619 			bias = 0;
    620 			break;
    621 		case 1:
    622 			bias = GPIO_PIN_PULLUP;
    623 			break;
    624 		case 2:
    625 			bias = GPIO_PIN_PULLDOWN;
    626 			break;
    627 		}
    628 	}
    629 
    630 	return bias;
    631 }
    632 
    633 static int
    634 sunxi_pinctrl_parse_drive_strength(int phandle)
    635 {
    636 	int val;
    637 
    638 	if (of_getprop_uint32(phandle, "drive-strength", &val) == 0)
    639 		return val;
    640 
    641 	if (of_getprop_uint32(phandle, "allwinner,drive", &val) == 0)
    642 		return (val + 1) * 10;
    643 
    644 	return -1;
    645 }
    646 
    647 static int
    648 sunxi_pinctrl_set_config(device_t dev, const void *data, size_t len)
    649 {
    650 	struct sunxi_gpio_softc * const sc = device_private(dev);
    651 	const struct sunxi_gpio_pins *pin_def;
    652 	int pins_len;
    653 
    654 	if (len != 4)
    655 		return -1;
    656 
    657 	const int phandle = fdtbus_get_phandle_from_native(be32dec(data));
    658 
    659 	/*
    660 	 * Required: pins, function
    661 	 * Optional: bias, drive strength
    662 	 */
    663 
    664 	const char *function = sunxi_pinctrl_parse_function(phandle);
    665 	if (function == NULL)
    666 		return -1;
    667 	const char *pins = sunxi_pinctrl_parse_pins(phandle, &pins_len);
    668 	if (pins == NULL)
    669 		return -1;
    670 
    671 	const int bias = sunxi_pinctrl_parse_bias(phandle);
    672 	const int drive_strength = sunxi_pinctrl_parse_drive_strength(phandle);
    673 
    674 	mutex_enter(&sc->sc_lock);
    675 
    676 	for (; pins_len > 0;
    677 	    pins_len -= strlen(pins) + 1, pins += strlen(pins) + 1) {
    678 		pin_def = sunxi_gpio_lookup_byname(sc, pins);
    679 		if (pin_def == NULL) {
    680 			aprint_error_dev(dev, "unknown pin name '%s'\n", pins);
    681 			continue;
    682 		}
    683 		if (sunxi_gpio_setfunc(sc, pin_def, function) != 0)
    684 			continue;
    685 
    686 		if (bias != -1)
    687 			sunxi_gpio_setpull(sc, pin_def, bias);
    688 
    689 		if (drive_strength != -1)
    690 			sunxi_gpio_setdrv(sc, pin_def, drive_strength);
    691 	}
    692 
    693 	mutex_exit(&sc->sc_lock);
    694 
    695 	return 0;
    696 }
    697 
    698 static struct fdtbus_pinctrl_controller_func sunxi_pinctrl_funcs = {
    699 	.set_config = sunxi_pinctrl_set_config,
    700 };
    701 
    702 static int
    703 sunxi_gpio_pin_read(void *priv, int pin)
    704 {
    705 	struct sunxi_gpio_softc * const sc = priv;
    706 	const struct sunxi_gpio_pins *pin_def = &sc->sc_padconf->pins[pin];
    707 	uint32_t data;
    708 	int val;
    709 
    710 	KASSERT(pin < sc->sc_padconf->npins);
    711 
    712 	const bus_size_t data_reg = SUNXI_GPIO_DATA(pin_def->port);
    713 	const uint32_t data_mask = __BIT(pin_def->pin);
    714 
    715 	/* No lock required for reads */
    716 	data = GPIO_READ(sc, data_reg);
    717 	val = __SHIFTOUT(data, data_mask);
    718 
    719 	return val;
    720 }
    721 
    722 static void
    723 sunxi_gpio_pin_write(void *priv, int pin, int val)
    724 {
    725 	struct sunxi_gpio_softc * const sc = priv;
    726 	const struct sunxi_gpio_pins *pin_def = &sc->sc_padconf->pins[pin];
    727 	uint32_t data;
    728 
    729 	KASSERT(pin < sc->sc_padconf->npins);
    730 
    731 	const bus_size_t data_reg = SUNXI_GPIO_DATA(pin_def->port);
    732 	const uint32_t data_mask = __BIT(pin_def->pin);
    733 
    734 	mutex_enter(&sc->sc_lock);
    735 	data = GPIO_READ(sc, data_reg);
    736 	if (val)
    737 		data |= data_mask;
    738 	else
    739 		data &= ~data_mask;
    740 	GPIO_WRITE(sc, data_reg, data);
    741 	mutex_exit(&sc->sc_lock);
    742 }
    743 
    744 static void
    745 sunxi_gpio_pin_ctl(void *priv, int pin, int flags)
    746 {
    747 	struct sunxi_gpio_softc * const sc = priv;
    748 	const struct sunxi_gpio_pins *pin_def = &sc->sc_padconf->pins[pin];
    749 
    750 	KASSERT(pin < sc->sc_padconf->npins);
    751 
    752 	mutex_enter(&sc->sc_lock);
    753 	sunxi_gpio_ctl(sc, pin_def, flags);
    754 	sunxi_gpio_setpull(sc, pin_def, flags);
    755 	mutex_exit(&sc->sc_lock);
    756 }
    757 
    758 static void
    759 sunxi_gpio_attach_ports(struct sunxi_gpio_softc *sc)
    760 {
    761 	const struct sunxi_gpio_pins *pin_def;
    762 	struct gpio_chipset_tag *gp = &sc->sc_gp;
    763 	struct gpiobus_attach_args gba;
    764 	u_int pin;
    765 
    766 	gp->gp_cookie = sc;
    767 	gp->gp_pin_read = sunxi_gpio_pin_read;
    768 	gp->gp_pin_write = sunxi_gpio_pin_write;
    769 	gp->gp_pin_ctl = sunxi_gpio_pin_ctl;
    770 
    771 	const u_int npins = sc->sc_padconf->npins;
    772 	sc->sc_pins = kmem_zalloc(sizeof(*sc->sc_pins) * npins, KM_SLEEP);
    773 
    774 	for (pin = 0; pin < sc->sc_padconf->npins; pin++) {
    775 		pin_def = &sc->sc_padconf->pins[pin];
    776 		sc->sc_pins[pin].pin_num = pin;
    777 		sc->sc_pins[pin].pin_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |
    778 		    GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN;
    779 		sc->sc_pins[pin].pin_state = sunxi_gpio_pin_read(sc, pin);
    780 		strlcpy(sc->sc_pins[pin].pin_defname, pin_def->name,
    781 		    sizeof(sc->sc_pins[pin].pin_defname));
    782 	}
    783 
    784 	memset(&gba, 0, sizeof(gba));
    785 	gba.gba_gc = gp;
    786 	gba.gba_pins = sc->sc_pins;
    787 	gba.gba_npins = npins;
    788 	sc->sc_gpiodev = config_found_ia(sc->sc_dev, "gpiobus", &gba, NULL);
    789 }
    790 
    791 static int
    792 sunxi_gpio_match(device_t parent, cfdata_t cf, void *aux)
    793 {
    794 	struct fdt_attach_args * const faa = aux;
    795 
    796 	return of_match_compat_data(faa->faa_phandle, compat_data);
    797 }
    798 
    799 static void
    800 sunxi_gpio_attach(device_t parent, device_t self, void *aux)
    801 {
    802 	struct sunxi_gpio_softc * const sc = device_private(self);
    803 	struct fdt_attach_args * const faa = aux;
    804 	const int phandle = faa->faa_phandle;
    805 	char intrstr[128];
    806 	struct fdtbus_reset *rst;
    807 	struct clk *clk;
    808 	bus_addr_t addr;
    809 	bus_size_t size;
    810 	int child;
    811 
    812 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
    813 		aprint_error(": couldn't get registers\n");
    814 		return;
    815 	}
    816 
    817 	if ((clk = fdtbus_clock_get_index(phandle, 0)) != NULL)
    818 		if (clk_enable(clk) != 0) {
    819 			aprint_error(": couldn't enable clock\n");
    820 			return;
    821 		}
    822 
    823 	if ((rst = fdtbus_reset_get_index(phandle, 0)) != NULL)
    824 		if (fdtbus_reset_deassert(rst) != 0) {
    825 			aprint_error(": couldn't de-assert reset\n");
    826 			return;
    827 		}
    828 
    829 	sc->sc_dev = self;
    830 	sc->sc_bst = faa->faa_bst;
    831 	if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
    832 		aprint_error(": couldn't map registers\n");
    833 		return;
    834 	}
    835 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
    836 	sc->sc_padconf = (void *)of_search_compatible(phandle, compat_data)->data;
    837 
    838 	aprint_naive("\n");
    839 	aprint_normal(": PIO\n");
    840 
    841 	fdtbus_register_gpio_controller(self, phandle, &sunxi_gpio_funcs);
    842 
    843 	for (child = OF_child(phandle); child; child = OF_peer(child)) {
    844 		if (!of_hasprop(child, "function") || !of_hasprop(child, "pins"))
    845 			continue;
    846 		fdtbus_register_pinctrl_config(self, child, &sunxi_pinctrl_funcs);
    847 	}
    848 
    849 	fdtbus_pinctrl_configure();
    850 
    851 	sunxi_gpio_attach_ports(sc);
    852 
    853 	/* Disable all external interrupts */
    854 	for (int i = 0; i < sc->sc_padconf->npins; i++) {
    855 		const struct sunxi_gpio_pins *pin_def = &sc->sc_padconf->pins[i];
    856 		if (pin_def->eint_func == 0)
    857 			continue;
    858 		GPIO_WRITE(sc, SUNXI_GPIO_INT_CTL(pin_def->eint_bank), __BIT(pin_def->eint_num));
    859 		GPIO_WRITE(sc, SUNXI_GPIO_INT_STATUS(pin_def->eint_bank), __BIT(pin_def->eint_num));
    860 
    861 		if (sc->sc_eint_bank_max < pin_def->eint_bank)
    862 			sc->sc_eint_bank_max = pin_def->eint_bank;
    863 	}
    864 	KASSERT(sc->sc_eint_bank_max < SUNXI_GPIO_MAX_EINT_BANK);
    865 
    866 	if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
    867 		aprint_error_dev(self, "failed to decode interrupt\n");
    868 		return;
    869 	}
    870 	sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_VM, FDT_INTR_MPSAFE,
    871 	    sunxi_gpio_intr, sc);
    872 	if (sc->sc_ih == NULL) {
    873 		aprint_error_dev(self, "failed to establish interrupt on %s\n",
    874 		    intrstr);
    875 		return;
    876 	}
    877 	aprint_normal_dev(self, "interrupting on %s\n", intrstr);
    878 	fdtbus_register_interrupt_controller(self, phandle,
    879 	    &sunxi_gpio_intrfuncs);
    880 }
    881