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