a10_gpio.c revision 305436
1/*- 2 * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold@freebsd.org> 3 * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org> 4 * Copyright (c) 2012 Luiz Otavio O Souza. 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 AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, 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 <sys/cdefs.h> 30__FBSDID("$FreeBSD: stable/11/sys/arm/allwinner/a10_gpio.c 305436 2016-09-05 20:17:18Z manu $"); 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/bus.h> 35 36#include <sys/kernel.h> 37#include <sys/module.h> 38#include <sys/rman.h> 39#include <sys/lock.h> 40#include <sys/mutex.h> 41#include <sys/gpio.h> 42 43#include <machine/bus.h> 44#include <machine/cpu.h> 45#include <machine/cpufunc.h> 46#include <machine/resource.h> 47#include <machine/intr.h> 48 49#include <dev/fdt/fdt_common.h> 50#include <dev/fdt/fdt_pinctrl.h> 51#include <dev/gpio/gpiobusvar.h> 52#include <dev/ofw/ofw_bus.h> 53#include <dev/ofw/ofw_bus_subr.h> 54 55#include <arm/allwinner/allwinner_machdep.h> 56#include <arm/allwinner/allwinner_pinctrl.h> 57#include <dev/extres/clk/clk.h> 58#include <dev/extres/hwreset/hwreset.h> 59 60#include "gpio_if.h" 61 62#define A10_GPIO_DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \ 63 GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN) 64 65#define A10_GPIO_NONE 0 66#define A10_GPIO_PULLUP 1 67#define A10_GPIO_PULLDOWN 2 68 69#define A10_GPIO_INPUT 0 70#define A10_GPIO_OUTPUT 1 71 72#define AW_GPIO_DRV_MASK 0x3 73#define AW_GPIO_PUD_MASK 0x3 74 75#define AW_PINCTRL 1 76#define AW_R_PINCTRL 2 77 78/* Defined in a10_padconf.c */ 79#ifdef SOC_ALLWINNER_A10 80extern const struct allwinner_padconf a10_padconf; 81#endif 82 83/* Defined in a13_padconf.c */ 84#ifdef SOC_ALLWINNER_A13 85extern const struct allwinner_padconf a13_padconf; 86#endif 87 88/* Defined in a20_padconf.c */ 89#ifdef SOC_ALLWINNER_A20 90extern const struct allwinner_padconf a20_padconf; 91#endif 92 93/* Defined in a31_padconf.c */ 94#ifdef SOC_ALLWINNER_A31 95extern const struct allwinner_padconf a31_padconf; 96#endif 97 98/* Defined in a31s_padconf.c */ 99#ifdef SOC_ALLWINNER_A31S 100extern const struct allwinner_padconf a31s_padconf; 101#endif 102 103#if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S) 104extern const struct allwinner_padconf a31_r_padconf; 105#endif 106 107/* Defined in h3_padconf.c */ 108#ifdef SOC_ALLWINNER_H3 109extern const struct allwinner_padconf h3_padconf; 110extern const struct allwinner_padconf h3_r_padconf; 111#endif 112 113/* Defined in a83t_padconf.c */ 114#ifdef SOC_ALLWINNER_A83T 115extern const struct allwinner_padconf a83t_padconf; 116extern const struct allwinner_padconf a83t_r_padconf; 117#endif 118 119static struct ofw_compat_data compat_data[] = { 120#ifdef SOC_ALLWINNER_A10 121 {"allwinner,sun4i-a10-pinctrl", (uintptr_t)&a10_padconf}, 122#endif 123#ifdef SOC_ALLWINNER_A13 124 {"allwinner,sun5i-a13-pinctrl", (uintptr_t)&a13_padconf}, 125#endif 126#ifdef SOC_ALLWINNER_A20 127 {"allwinner,sun7i-a20-pinctrl", (uintptr_t)&a20_padconf}, 128#endif 129#ifdef SOC_ALLWINNER_A31 130 {"allwinner,sun6i-a31-pinctrl", (uintptr_t)&a31_padconf}, 131#endif 132#ifdef SOC_ALLWINNER_A31S 133 {"allwinner,sun6i-a31s-pinctrl", (uintptr_t)&a31s_padconf}, 134#endif 135#if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S) 136 {"allwinner,sun6i-a31-r-pinctrl", (uintptr_t)&a31_r_padconf}, 137#endif 138#ifdef SOC_ALLWINNER_A83T 139 {"allwinner,sun8i-a83t-pinctrl", (uintptr_t)&a83t_padconf}, 140 {"allwinner,sun8i-a83t-r-pinctrl", (uintptr_t)&a83t_r_padconf}, 141#endif 142#ifdef SOC_ALLWINNER_H3 143 {"allwinner,sun8i-h3-pinctrl", (uintptr_t)&h3_padconf}, 144 {"allwinner,sun8i-h3-r-pinctrl", (uintptr_t)&h3_r_padconf}, 145#endif 146 {NULL, 0} 147}; 148 149struct a10_gpio_softc { 150 device_t sc_dev; 151 device_t sc_busdev; 152 struct mtx sc_mtx; 153 struct resource * sc_mem_res; 154 struct resource * sc_irq_res; 155 bus_space_tag_t sc_bst; 156 bus_space_handle_t sc_bsh; 157 void * sc_intrhand; 158 const struct allwinner_padconf * padconf; 159}; 160 161#define A10_GPIO_LOCK(_sc) mtx_lock_spin(&(_sc)->sc_mtx) 162#define A10_GPIO_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->sc_mtx) 163#define A10_GPIO_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED) 164 165#define A10_GPIO_GP_CFG(_bank, _idx) 0x00 + ((_bank) * 0x24) + ((_idx) << 2) 166#define A10_GPIO_GP_DAT(_bank) 0x10 + ((_bank) * 0x24) 167#define A10_GPIO_GP_DRV(_bank, _idx) 0x14 + ((_bank) * 0x24) + ((_idx) << 2) 168#define A10_GPIO_GP_PUL(_bank, _idx) 0x1c + ((_bank) * 0x24) + ((_idx) << 2) 169 170#define A10_GPIO_GP_INT_CFG0 0x200 171#define A10_GPIO_GP_INT_CFG1 0x204 172#define A10_GPIO_GP_INT_CFG2 0x208 173#define A10_GPIO_GP_INT_CFG3 0x20c 174 175#define A10_GPIO_GP_INT_CTL 0x210 176#define A10_GPIO_GP_INT_STA 0x214 177#define A10_GPIO_GP_INT_DEB 0x218 178 179#define A10_GPIO_WRITE(_sc, _off, _val) \ 180 bus_space_write_4(_sc->sc_bst, _sc->sc_bsh, _off, _val) 181#define A10_GPIO_READ(_sc, _off) \ 182 bus_space_read_4(_sc->sc_bst, _sc->sc_bsh, _off) 183 184static uint32_t 185a10_gpio_get_function(struct a10_gpio_softc *sc, uint32_t pin) 186{ 187 uint32_t bank, func, offset; 188 189 /* Must be called with lock held. */ 190 A10_GPIO_LOCK_ASSERT(sc); 191 192 if (pin > sc->padconf->npins) 193 return (0); 194 bank = sc->padconf->pins[pin].port; 195 pin = sc->padconf->pins[pin].pin; 196 offset = ((pin & 0x07) << 2); 197 198 func = A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, pin >> 3)); 199 switch ((func >> offset) & 0x7) { 200 case A10_GPIO_INPUT: 201 return (GPIO_PIN_INPUT); 202 case A10_GPIO_OUTPUT: 203 return (GPIO_PIN_OUTPUT); 204 } 205 206 return (0); 207} 208 209static int 210a10_gpio_set_function(struct a10_gpio_softc *sc, uint32_t pin, uint32_t f) 211{ 212 uint32_t bank, data, offset; 213 214 /* Check if the function exists in the padconf data */ 215 if (sc->padconf->pins[pin].functions[f] == NULL) 216 return (EINVAL); 217 218 /* Must be called with lock held. */ 219 A10_GPIO_LOCK_ASSERT(sc); 220 221 bank = sc->padconf->pins[pin].port; 222 pin = sc->padconf->pins[pin].pin; 223 offset = ((pin & 0x07) << 2); 224 225 data = A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, pin >> 3)); 226 data &= ~(7 << offset); 227 data |= (f << offset); 228 A10_GPIO_WRITE(sc, A10_GPIO_GP_CFG(bank, pin >> 3), data); 229 230 return (0); 231} 232 233static uint32_t 234a10_gpio_get_pud(struct a10_gpio_softc *sc, uint32_t pin) 235{ 236 uint32_t bank, offset, val; 237 238 /* Must be called with lock held. */ 239 A10_GPIO_LOCK_ASSERT(sc); 240 241 bank = sc->padconf->pins[pin].port; 242 pin = sc->padconf->pins[pin].pin; 243 offset = ((pin & 0x0f) << 1); 244 245 val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pin >> 4)); 246 switch ((val >> offset) & 0x3) { 247 case A10_GPIO_PULLDOWN: 248 return (GPIO_PIN_PULLDOWN); 249 case A10_GPIO_PULLUP: 250 return (GPIO_PIN_PULLUP); 251 } 252 253 return (0); 254} 255 256static void 257a10_gpio_set_pud(struct a10_gpio_softc *sc, uint32_t pin, uint32_t state) 258{ 259 uint32_t bank, offset, val; 260 261 /* Must be called with lock held. */ 262 A10_GPIO_LOCK_ASSERT(sc); 263 264 bank = sc->padconf->pins[pin].port; 265 pin = sc->padconf->pins[pin].pin; 266 offset = ((pin & 0x0f) << 1); 267 268 val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pin >> 4)); 269 val &= ~(AW_GPIO_PUD_MASK << offset); 270 val |= (state << offset); 271 A10_GPIO_WRITE(sc, A10_GPIO_GP_PUL(bank, pin >> 4), val); 272} 273 274static void 275a10_gpio_set_drv(struct a10_gpio_softc *sc, uint32_t pin, uint32_t drive) 276{ 277 uint32_t bank, offset, val; 278 279 /* Must be called with lock held. */ 280 A10_GPIO_LOCK_ASSERT(sc); 281 282 bank = sc->padconf->pins[pin].port; 283 pin = sc->padconf->pins[pin].pin; 284 offset = ((pin & 0x0f) << 1); 285 286 val = A10_GPIO_READ(sc, A10_GPIO_GP_DRV(bank, pin >> 4)); 287 val &= ~(AW_GPIO_DRV_MASK << offset); 288 val |= (drive << offset); 289 A10_GPIO_WRITE(sc, A10_GPIO_GP_DRV(bank, pin >> 4), val); 290} 291 292static int 293a10_gpio_pin_configure(struct a10_gpio_softc *sc, uint32_t pin, uint32_t flags) 294{ 295 int err = 0; 296 297 /* Must be called with lock held. */ 298 A10_GPIO_LOCK_ASSERT(sc); 299 300 /* Manage input/output. */ 301 if (flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) { 302 if (flags & GPIO_PIN_OUTPUT) 303 err = a10_gpio_set_function(sc, pin, A10_GPIO_OUTPUT); 304 else 305 err = a10_gpio_set_function(sc, pin, A10_GPIO_INPUT); 306 } 307 308 if (err) 309 return (err); 310 311 /* Manage Pull-up/pull-down. */ 312 if (flags & (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)) { 313 if (flags & GPIO_PIN_PULLUP) 314 a10_gpio_set_pud(sc, pin, A10_GPIO_PULLUP); 315 else 316 a10_gpio_set_pud(sc, pin, A10_GPIO_PULLDOWN); 317 } else 318 a10_gpio_set_pud(sc, pin, A10_GPIO_NONE); 319 320 return (0); 321} 322 323static device_t 324a10_gpio_get_bus(device_t dev) 325{ 326 struct a10_gpio_softc *sc; 327 328 sc = device_get_softc(dev); 329 330 return (sc->sc_busdev); 331} 332 333static int 334a10_gpio_pin_max(device_t dev, int *maxpin) 335{ 336 struct a10_gpio_softc *sc; 337 338 sc = device_get_softc(dev); 339 340 *maxpin = sc->padconf->npins - 1; 341 return (0); 342} 343 344static int 345a10_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 346{ 347 struct a10_gpio_softc *sc; 348 349 sc = device_get_softc(dev); 350 if (pin >= sc->padconf->npins) 351 return (EINVAL); 352 353 *caps = A10_GPIO_DEFAULT_CAPS; 354 355 return (0); 356} 357 358static int 359a10_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 360{ 361 struct a10_gpio_softc *sc; 362 363 sc = device_get_softc(dev); 364 if (pin >= sc->padconf->npins) 365 return (EINVAL); 366 367 A10_GPIO_LOCK(sc); 368 *flags = a10_gpio_get_function(sc, pin); 369 *flags |= a10_gpio_get_pud(sc, pin); 370 A10_GPIO_UNLOCK(sc); 371 372 return (0); 373} 374 375static int 376a10_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 377{ 378 struct a10_gpio_softc *sc; 379 380 sc = device_get_softc(dev); 381 if (pin >= sc->padconf->npins) 382 return (EINVAL); 383 384 snprintf(name, GPIOMAXNAME - 1, "%s", 385 sc->padconf->pins[pin].name); 386 name[GPIOMAXNAME - 1] = '\0'; 387 388 return (0); 389} 390 391static int 392a10_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 393{ 394 struct a10_gpio_softc *sc; 395 int err; 396 397 sc = device_get_softc(dev); 398 if (pin > sc->padconf->npins) 399 return (EINVAL); 400 401 A10_GPIO_LOCK(sc); 402 err = a10_gpio_pin_configure(sc, pin, flags); 403 A10_GPIO_UNLOCK(sc); 404 405 return (err); 406} 407 408static int 409a10_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 410{ 411 struct a10_gpio_softc *sc; 412 uint32_t bank, data; 413 414 sc = device_get_softc(dev); 415 if (pin > sc->padconf->npins) 416 return (EINVAL); 417 418 bank = sc->padconf->pins[pin].port; 419 pin = sc->padconf->pins[pin].pin; 420 421 A10_GPIO_LOCK(sc); 422 data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank)); 423 if (value) 424 data |= (1 << pin); 425 else 426 data &= ~(1 << pin); 427 A10_GPIO_WRITE(sc, A10_GPIO_GP_DAT(bank), data); 428 A10_GPIO_UNLOCK(sc); 429 430 return (0); 431} 432 433static int 434a10_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) 435{ 436 struct a10_gpio_softc *sc; 437 uint32_t bank, reg_data; 438 439 sc = device_get_softc(dev); 440 if (pin > sc->padconf->npins) 441 return (EINVAL); 442 443 bank = sc->padconf->pins[pin].port; 444 pin = sc->padconf->pins[pin].pin; 445 446 A10_GPIO_LOCK(sc); 447 reg_data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank)); 448 A10_GPIO_UNLOCK(sc); 449 *val = (reg_data & (1 << pin)) ? 1 : 0; 450 451 return (0); 452} 453 454static int 455a10_gpio_pin_toggle(device_t dev, uint32_t pin) 456{ 457 struct a10_gpio_softc *sc; 458 uint32_t bank, data; 459 460 sc = device_get_softc(dev); 461 if (pin > sc->padconf->npins) 462 return (EINVAL); 463 464 bank = sc->padconf->pins[pin].port; 465 pin = sc->padconf->pins[pin].pin; 466 467 A10_GPIO_LOCK(sc); 468 data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank)); 469 if (data & (1 << pin)) 470 data &= ~(1 << pin); 471 else 472 data |= (1 << pin); 473 A10_GPIO_WRITE(sc, A10_GPIO_GP_DAT(bank), data); 474 A10_GPIO_UNLOCK(sc); 475 476 return (0); 477} 478 479static int 480aw_find_pinnum_by_name(struct a10_gpio_softc *sc, const char *pinname) 481{ 482 int i; 483 484 for (i = 0; i < sc->padconf->npins; i++) 485 if (!strcmp(pinname, sc->padconf->pins[i].name)) 486 return i; 487 488 return (-1); 489} 490 491static int 492aw_find_pin_func(struct a10_gpio_softc *sc, int pin, const char *func) 493{ 494 int i; 495 496 for (i = 0; i < AW_MAX_FUNC_BY_PIN; i++) 497 if (sc->padconf->pins[pin].functions[i] && 498 !strcmp(func, sc->padconf->pins[pin].functions[i])) 499 return (i); 500 501 return (-1); 502} 503 504static int 505aw_fdt_configure_pins(device_t dev, phandle_t cfgxref) 506{ 507 struct a10_gpio_softc *sc; 508 phandle_t node; 509 const char **pinlist = NULL; 510 char *pin_function = NULL; 511 uint32_t pin_drive, pin_pull; 512 int pins_nb, pin_num, pin_func, i, ret; 513 514 sc = device_get_softc(dev); 515 node = OF_node_from_xref(cfgxref); 516 ret = 0; 517 518 /* Getting all prop for configuring pins */ 519 pins_nb = ofw_bus_string_list_to_array(node, "allwinner,pins", &pinlist); 520 if (pins_nb <= 0) 521 return (ENOENT); 522 if (OF_getprop_alloc(node, "allwinner,function", 523 sizeof(*pin_function), 524 (void **)&pin_function) == -1) { 525 ret = ENOENT; 526 goto out; 527 } 528 if (OF_getencprop(node, "allwinner,drive", 529 &pin_drive, sizeof(pin_drive)) == -1) { 530 ret = ENOENT; 531 goto out; 532 } 533 if (OF_getencprop(node, "allwinner,pull", 534 &pin_pull, sizeof(pin_pull)) == -1) { 535 ret = ENOENT; 536 goto out; 537 } 538 539 /* Configure each pin to the correct function, drive and pull */ 540 for (i = 0; i < pins_nb; i++) { 541 pin_num = aw_find_pinnum_by_name(sc, pinlist[i]); 542 if (pin_num == -1) { 543 ret = ENOENT; 544 goto out; 545 } 546 pin_func = aw_find_pin_func(sc, pin_num, pin_function); 547 if (pin_func == -1) { 548 ret = ENOENT; 549 goto out; 550 } 551 552 A10_GPIO_LOCK(sc); 553 a10_gpio_set_function(sc, pin_num, pin_func); 554 a10_gpio_set_drv(sc, pin_num, pin_drive); 555 a10_gpio_set_pud(sc, pin_num, pin_pull); 556 A10_GPIO_UNLOCK(sc); 557 } 558 559 out: 560 OF_prop_free(pinlist); 561 OF_prop_free(pin_function); 562 return (ret); 563} 564 565static int 566a10_gpio_probe(device_t dev) 567{ 568 569 if (!ofw_bus_status_okay(dev)) 570 return (ENXIO); 571 572 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 573 return (ENXIO); 574 575 device_set_desc(dev, "Allwinner GPIO/Pinmux controller"); 576 return (BUS_PROBE_DEFAULT); 577} 578 579static int 580a10_gpio_attach(device_t dev) 581{ 582 int rid, error; 583 phandle_t gpio; 584 struct a10_gpio_softc *sc; 585 clk_t clk; 586 hwreset_t rst; 587 588 sc = device_get_softc(dev); 589 sc->sc_dev = dev; 590 591 mtx_init(&sc->sc_mtx, "a10 gpio", "gpio", MTX_SPIN); 592 593 rid = 0; 594 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 595 RF_ACTIVE); 596 if (!sc->sc_mem_res) { 597 device_printf(dev, "cannot allocate memory window\n"); 598 goto fail; 599 } 600 601 sc->sc_bst = rman_get_bustag(sc->sc_mem_res); 602 sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res); 603 604 rid = 0; 605 sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 606 RF_ACTIVE); 607 if (!sc->sc_irq_res) { 608 device_printf(dev, "cannot allocate interrupt\n"); 609 goto fail; 610 } 611 612 /* Find our node. */ 613 gpio = ofw_bus_get_node(sc->sc_dev); 614 if (!OF_hasprop(gpio, "gpio-controller")) 615 /* Node is not a GPIO controller. */ 616 goto fail; 617 618 /* Use the right pin data for the current SoC */ 619 sc->padconf = (struct allwinner_padconf *)ofw_bus_search_compatible(dev, 620 compat_data)->ocd_data; 621 622 if (hwreset_get_by_ofw_idx(dev, 0, &rst) == 0) { 623 error = hwreset_deassert(rst); 624 if (error != 0) { 625 device_printf(dev, "cannot de-assert reset\n"); 626 return (error); 627 } 628 } 629 630 if (clk_get_by_ofw_index(dev, 0, &clk) == 0) { 631 error = clk_enable(clk); 632 if (error != 0) { 633 device_printf(dev, "could not enable clock\n"); 634 return (error); 635 } 636 } 637 638 sc->sc_busdev = gpiobus_attach_bus(dev); 639 if (sc->sc_busdev == NULL) 640 goto fail; 641 642 /* 643 * Register as a pinctrl device 644 */ 645 fdt_pinctrl_register(dev, "allwinner,pins"); 646 fdt_pinctrl_configure_tree(dev); 647 648 return (0); 649 650fail: 651 if (sc->sc_irq_res) 652 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res); 653 if (sc->sc_mem_res) 654 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); 655 mtx_destroy(&sc->sc_mtx); 656 657 return (ENXIO); 658} 659 660static int 661a10_gpio_detach(device_t dev) 662{ 663 664 return (EBUSY); 665} 666 667static phandle_t 668a10_gpio_get_node(device_t dev, device_t bus) 669{ 670 671 /* We only have one child, the GPIO bus, which needs our own node. */ 672 return (ofw_bus_get_node(dev)); 673} 674 675static int 676a10_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells, 677 pcell_t *gpios, uint32_t *pin, uint32_t *flags) 678{ 679 struct a10_gpio_softc *sc; 680 int i; 681 682 sc = device_get_softc(bus); 683 684 /* The GPIO pins are mapped as: <gpio-phandle bank pin flags>. */ 685 for (i = 0; i < sc->padconf->npins; i++) 686 if (sc->padconf->pins[i].port == gpios[0] && 687 sc->padconf->pins[i].pin == gpios[1]) { 688 *pin = i; 689 break; 690 } 691 *flags = gpios[gcells - 1]; 692 693 return (0); 694} 695 696static device_method_t a10_gpio_methods[] = { 697 /* Device interface */ 698 DEVMETHOD(device_probe, a10_gpio_probe), 699 DEVMETHOD(device_attach, a10_gpio_attach), 700 DEVMETHOD(device_detach, a10_gpio_detach), 701 702 /* GPIO protocol */ 703 DEVMETHOD(gpio_get_bus, a10_gpio_get_bus), 704 DEVMETHOD(gpio_pin_max, a10_gpio_pin_max), 705 DEVMETHOD(gpio_pin_getname, a10_gpio_pin_getname), 706 DEVMETHOD(gpio_pin_getflags, a10_gpio_pin_getflags), 707 DEVMETHOD(gpio_pin_getcaps, a10_gpio_pin_getcaps), 708 DEVMETHOD(gpio_pin_setflags, a10_gpio_pin_setflags), 709 DEVMETHOD(gpio_pin_get, a10_gpio_pin_get), 710 DEVMETHOD(gpio_pin_set, a10_gpio_pin_set), 711 DEVMETHOD(gpio_pin_toggle, a10_gpio_pin_toggle), 712 DEVMETHOD(gpio_map_gpios, a10_gpio_map_gpios), 713 714 /* ofw_bus interface */ 715 DEVMETHOD(ofw_bus_get_node, a10_gpio_get_node), 716 717 /* fdt_pinctrl interface */ 718 DEVMETHOD(fdt_pinctrl_configure,aw_fdt_configure_pins), 719 720 DEVMETHOD_END 721}; 722 723static devclass_t a10_gpio_devclass; 724 725static driver_t a10_gpio_driver = { 726 "gpio", 727 a10_gpio_methods, 728 sizeof(struct a10_gpio_softc), 729}; 730 731EARLY_DRIVER_MODULE(a10_gpio, simplebus, a10_gpio_driver, a10_gpio_devclass, 0, 0, 732 BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); 733