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