a10_gpio.c revision 305439
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 305439 2016-09-05 20:46:45Z 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 200 return ((func >> offset) & 0x7); 201} 202 203static int 204a10_gpio_set_function(struct a10_gpio_softc *sc, uint32_t pin, uint32_t f) 205{ 206 uint32_t bank, data, offset; 207 208 /* Check if the function exists in the padconf data */ 209 if (sc->padconf->pins[pin].functions[f] == NULL) 210 return (EINVAL); 211 212 /* Must be called with lock held. */ 213 A10_GPIO_LOCK_ASSERT(sc); 214 215 bank = sc->padconf->pins[pin].port; 216 pin = sc->padconf->pins[pin].pin; 217 offset = ((pin & 0x07) << 2); 218 219 data = A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, pin >> 3)); 220 data &= ~(7 << offset); 221 data |= (f << offset); 222 A10_GPIO_WRITE(sc, A10_GPIO_GP_CFG(bank, pin >> 3), data); 223 224 return (0); 225} 226 227static uint32_t 228a10_gpio_get_pud(struct a10_gpio_softc *sc, uint32_t pin) 229{ 230 uint32_t bank, offset, val; 231 232 /* Must be called with lock held. */ 233 A10_GPIO_LOCK_ASSERT(sc); 234 235 bank = sc->padconf->pins[pin].port; 236 pin = sc->padconf->pins[pin].pin; 237 offset = ((pin & 0x0f) << 1); 238 239 val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pin >> 4)); 240 241 return ((val >> offset) & AW_GPIO_PUD_MASK); 242} 243 244static void 245a10_gpio_set_pud(struct a10_gpio_softc *sc, uint32_t pin, uint32_t state) 246{ 247 uint32_t bank, offset, val; 248 249 /* Must be called with lock held. */ 250 A10_GPIO_LOCK_ASSERT(sc); 251 252 bank = sc->padconf->pins[pin].port; 253 pin = sc->padconf->pins[pin].pin; 254 offset = ((pin & 0x0f) << 1); 255 256 val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pin >> 4)); 257 val &= ~(AW_GPIO_PUD_MASK << offset); 258 val |= (state << offset); 259 A10_GPIO_WRITE(sc, A10_GPIO_GP_PUL(bank, pin >> 4), val); 260} 261 262static uint32_t 263a10_gpio_get_drv(struct a10_gpio_softc *sc, uint32_t pin) 264{ 265 uint32_t bank, offset, val; 266 267 /* Must be called with lock held. */ 268 A10_GPIO_LOCK_ASSERT(sc); 269 270 bank = sc->padconf->pins[pin].port; 271 pin = sc->padconf->pins[pin].pin; 272 offset = ((pin & 0x0f) << 1); 273 274 val = A10_GPIO_READ(sc, A10_GPIO_GP_DRV(bank, pin >> 4)); 275 276 return ((val >> offset) & AW_GPIO_DRV_MASK); 277} 278 279static void 280a10_gpio_set_drv(struct a10_gpio_softc *sc, uint32_t pin, uint32_t drive) 281{ 282 uint32_t bank, offset, val; 283 284 /* Must be called with lock held. */ 285 A10_GPIO_LOCK_ASSERT(sc); 286 287 bank = sc->padconf->pins[pin].port; 288 pin = sc->padconf->pins[pin].pin; 289 offset = ((pin & 0x0f) << 1); 290 291 val = A10_GPIO_READ(sc, A10_GPIO_GP_DRV(bank, pin >> 4)); 292 val &= ~(AW_GPIO_DRV_MASK << offset); 293 val |= (drive << offset); 294 A10_GPIO_WRITE(sc, A10_GPIO_GP_DRV(bank, pin >> 4), val); 295} 296 297static int 298a10_gpio_pin_configure(struct a10_gpio_softc *sc, uint32_t pin, uint32_t flags) 299{ 300 int err = 0; 301 302 /* Must be called with lock held. */ 303 A10_GPIO_LOCK_ASSERT(sc); 304 305 /* Manage input/output. */ 306 if (flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) { 307 if (flags & GPIO_PIN_OUTPUT) 308 err = a10_gpio_set_function(sc, pin, A10_GPIO_OUTPUT); 309 else 310 err = a10_gpio_set_function(sc, pin, A10_GPIO_INPUT); 311 } 312 313 if (err) 314 return (err); 315 316 /* Manage Pull-up/pull-down. */ 317 if (flags & (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)) { 318 if (flags & GPIO_PIN_PULLUP) 319 a10_gpio_set_pud(sc, pin, A10_GPIO_PULLUP); 320 else 321 a10_gpio_set_pud(sc, pin, A10_GPIO_PULLDOWN); 322 } else 323 a10_gpio_set_pud(sc, pin, A10_GPIO_NONE); 324 325 return (0); 326} 327 328static device_t 329a10_gpio_get_bus(device_t dev) 330{ 331 struct a10_gpio_softc *sc; 332 333 sc = device_get_softc(dev); 334 335 return (sc->sc_busdev); 336} 337 338static int 339a10_gpio_pin_max(device_t dev, int *maxpin) 340{ 341 struct a10_gpio_softc *sc; 342 343 sc = device_get_softc(dev); 344 345 *maxpin = sc->padconf->npins - 1; 346 return (0); 347} 348 349static int 350a10_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 351{ 352 struct a10_gpio_softc *sc; 353 354 sc = device_get_softc(dev); 355 if (pin >= sc->padconf->npins) 356 return (EINVAL); 357 358 *caps = A10_GPIO_DEFAULT_CAPS; 359 360 return (0); 361} 362 363static int 364a10_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 365{ 366 struct a10_gpio_softc *sc; 367 uint32_t func; 368 uint32_t pud; 369 370 sc = device_get_softc(dev); 371 if (pin >= sc->padconf->npins) 372 return (EINVAL); 373 374 A10_GPIO_LOCK(sc); 375 func = a10_gpio_get_function(sc, pin); 376 switch (func) { 377 case A10_GPIO_INPUT: 378 *flags = GPIO_PIN_INPUT; 379 break; 380 case A10_GPIO_OUTPUT: 381 *flags = GPIO_PIN_OUTPUT; 382 break; 383 default: 384 *flags = 0; 385 break; 386 } 387 388 pud = a10_gpio_get_pud(sc, pin); 389 switch (pud) { 390 case A10_GPIO_PULLDOWN: 391 *flags |= GPIO_PIN_PULLDOWN; 392 break; 393 case A10_GPIO_PULLUP: 394 *flags |= GPIO_PIN_PULLUP; 395 break; 396 default: 397 break; 398 } 399 400 A10_GPIO_UNLOCK(sc); 401 402 return (0); 403} 404 405static int 406a10_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 407{ 408 struct a10_gpio_softc *sc; 409 410 sc = device_get_softc(dev); 411 if (pin >= sc->padconf->npins) 412 return (EINVAL); 413 414 snprintf(name, GPIOMAXNAME - 1, "%s", 415 sc->padconf->pins[pin].name); 416 name[GPIOMAXNAME - 1] = '\0'; 417 418 return (0); 419} 420 421static int 422a10_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 423{ 424 struct a10_gpio_softc *sc; 425 int err; 426 427 sc = device_get_softc(dev); 428 if (pin > sc->padconf->npins) 429 return (EINVAL); 430 431 A10_GPIO_LOCK(sc); 432 err = a10_gpio_pin_configure(sc, pin, flags); 433 A10_GPIO_UNLOCK(sc); 434 435 return (err); 436} 437 438static int 439a10_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 440{ 441 struct a10_gpio_softc *sc; 442 uint32_t bank, data; 443 444 sc = device_get_softc(dev); 445 if (pin > sc->padconf->npins) 446 return (EINVAL); 447 448 bank = sc->padconf->pins[pin].port; 449 pin = sc->padconf->pins[pin].pin; 450 451 A10_GPIO_LOCK(sc); 452 data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank)); 453 if (value) 454 data |= (1 << pin); 455 else 456 data &= ~(1 << pin); 457 A10_GPIO_WRITE(sc, A10_GPIO_GP_DAT(bank), data); 458 A10_GPIO_UNLOCK(sc); 459 460 return (0); 461} 462 463static int 464a10_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) 465{ 466 struct a10_gpio_softc *sc; 467 uint32_t bank, reg_data; 468 469 sc = device_get_softc(dev); 470 if (pin > sc->padconf->npins) 471 return (EINVAL); 472 473 bank = sc->padconf->pins[pin].port; 474 pin = sc->padconf->pins[pin].pin; 475 476 A10_GPIO_LOCK(sc); 477 reg_data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank)); 478 A10_GPIO_UNLOCK(sc); 479 *val = (reg_data & (1 << pin)) ? 1 : 0; 480 481 return (0); 482} 483 484static int 485a10_gpio_pin_toggle(device_t dev, uint32_t pin) 486{ 487 struct a10_gpio_softc *sc; 488 uint32_t bank, data; 489 490 sc = device_get_softc(dev); 491 if (pin > sc->padconf->npins) 492 return (EINVAL); 493 494 bank = sc->padconf->pins[pin].port; 495 pin = sc->padconf->pins[pin].pin; 496 497 A10_GPIO_LOCK(sc); 498 data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank)); 499 if (data & (1 << pin)) 500 data &= ~(1 << pin); 501 else 502 data |= (1 << pin); 503 A10_GPIO_WRITE(sc, A10_GPIO_GP_DAT(bank), data); 504 A10_GPIO_UNLOCK(sc); 505 506 return (0); 507} 508 509static int 510aw_find_pinnum_by_name(struct a10_gpio_softc *sc, const char *pinname) 511{ 512 int i; 513 514 for (i = 0; i < sc->padconf->npins; i++) 515 if (!strcmp(pinname, sc->padconf->pins[i].name)) 516 return i; 517 518 return (-1); 519} 520 521static int 522aw_find_pin_func(struct a10_gpio_softc *sc, int pin, const char *func) 523{ 524 int i; 525 526 for (i = 0; i < AW_MAX_FUNC_BY_PIN; i++) 527 if (sc->padconf->pins[pin].functions[i] && 528 !strcmp(func, sc->padconf->pins[pin].functions[i])) 529 return (i); 530 531 return (-1); 532} 533 534static int 535aw_fdt_configure_pins(device_t dev, phandle_t cfgxref) 536{ 537 struct a10_gpio_softc *sc; 538 phandle_t node; 539 const char **pinlist = NULL; 540 char *pin_function = NULL; 541 uint32_t pin_drive, pin_pull; 542 int pins_nb, pin_num, pin_func, i, ret; 543 544 sc = device_get_softc(dev); 545 node = OF_node_from_xref(cfgxref); 546 ret = 0; 547 548 /* Getting all prop for configuring pins */ 549 pins_nb = ofw_bus_string_list_to_array(node, "allwinner,pins", &pinlist); 550 if (pins_nb <= 0) 551 return (ENOENT); 552 if (OF_getprop_alloc(node, "allwinner,function", 553 sizeof(*pin_function), 554 (void **)&pin_function) == -1) { 555 ret = ENOENT; 556 goto out; 557 } 558 if (OF_getencprop(node, "allwinner,drive", 559 &pin_drive, sizeof(pin_drive)) == -1) { 560 ret = ENOENT; 561 goto out; 562 } 563 if (OF_getencprop(node, "allwinner,pull", 564 &pin_pull, sizeof(pin_pull)) == -1) { 565 ret = ENOENT; 566 goto out; 567 } 568 569 /* Configure each pin to the correct function, drive and pull */ 570 for (i = 0; i < pins_nb; i++) { 571 pin_num = aw_find_pinnum_by_name(sc, pinlist[i]); 572 if (pin_num == -1) { 573 ret = ENOENT; 574 goto out; 575 } 576 pin_func = aw_find_pin_func(sc, pin_num, pin_function); 577 if (pin_func == -1) { 578 ret = ENOENT; 579 goto out; 580 } 581 582 A10_GPIO_LOCK(sc); 583 584 if (a10_gpio_get_function(sc, pin_num) != pin_func) 585 a10_gpio_set_function(sc, pin_num, pin_func); 586 if (a10_gpio_get_drv(sc, pin_num) != pin_drive) 587 a10_gpio_set_drv(sc, pin_num, pin_drive); 588 if (a10_gpio_get_pud(sc, pin_num) != pin_pull && 589 (pin_pull == A10_GPIO_PULLUP || 590 pin_pull == A10_GPIO_PULLDOWN)) 591 a10_gpio_set_pud(sc, pin_num, pin_pull); 592 A10_GPIO_UNLOCK(sc); 593 } 594 595 out: 596 OF_prop_free(pinlist); 597 OF_prop_free(pin_function); 598 return (ret); 599} 600 601static int 602a10_gpio_probe(device_t dev) 603{ 604 605 if (!ofw_bus_status_okay(dev)) 606 return (ENXIO); 607 608 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 609 return (ENXIO); 610 611 device_set_desc(dev, "Allwinner GPIO/Pinmux controller"); 612 return (BUS_PROBE_DEFAULT); 613} 614 615static int 616a10_gpio_attach(device_t dev) 617{ 618 int rid, error; 619 phandle_t gpio; 620 struct a10_gpio_softc *sc; 621 clk_t clk; 622 hwreset_t rst; 623 624 sc = device_get_softc(dev); 625 sc->sc_dev = dev; 626 627 mtx_init(&sc->sc_mtx, "a10 gpio", "gpio", MTX_SPIN); 628 629 rid = 0; 630 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 631 RF_ACTIVE); 632 if (!sc->sc_mem_res) { 633 device_printf(dev, "cannot allocate memory window\n"); 634 goto fail; 635 } 636 637 sc->sc_bst = rman_get_bustag(sc->sc_mem_res); 638 sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res); 639 640 rid = 0; 641 sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 642 RF_ACTIVE); 643 if (!sc->sc_irq_res) { 644 device_printf(dev, "cannot allocate interrupt\n"); 645 goto fail; 646 } 647 648 /* Find our node. */ 649 gpio = ofw_bus_get_node(sc->sc_dev); 650 if (!OF_hasprop(gpio, "gpio-controller")) 651 /* Node is not a GPIO controller. */ 652 goto fail; 653 654 /* Use the right pin data for the current SoC */ 655 sc->padconf = (struct allwinner_padconf *)ofw_bus_search_compatible(dev, 656 compat_data)->ocd_data; 657 658 if (hwreset_get_by_ofw_idx(dev, 0, &rst) == 0) { 659 error = hwreset_deassert(rst); 660 if (error != 0) { 661 device_printf(dev, "cannot de-assert reset\n"); 662 return (error); 663 } 664 } 665 666 if (clk_get_by_ofw_index(dev, 0, &clk) == 0) { 667 error = clk_enable(clk); 668 if (error != 0) { 669 device_printf(dev, "could not enable clock\n"); 670 return (error); 671 } 672 } 673 674 sc->sc_busdev = gpiobus_attach_bus(dev); 675 if (sc->sc_busdev == NULL) 676 goto fail; 677 678 /* 679 * Register as a pinctrl device 680 */ 681 fdt_pinctrl_register(dev, "allwinner,pins"); 682 fdt_pinctrl_configure_tree(dev); 683 684 return (0); 685 686fail: 687 if (sc->sc_irq_res) 688 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res); 689 if (sc->sc_mem_res) 690 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); 691 mtx_destroy(&sc->sc_mtx); 692 693 return (ENXIO); 694} 695 696static int 697a10_gpio_detach(device_t dev) 698{ 699 700 return (EBUSY); 701} 702 703static phandle_t 704a10_gpio_get_node(device_t dev, device_t bus) 705{ 706 707 /* We only have one child, the GPIO bus, which needs our own node. */ 708 return (ofw_bus_get_node(dev)); 709} 710 711static int 712a10_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells, 713 pcell_t *gpios, uint32_t *pin, uint32_t *flags) 714{ 715 struct a10_gpio_softc *sc; 716 int i; 717 718 sc = device_get_softc(bus); 719 720 /* The GPIO pins are mapped as: <gpio-phandle bank pin flags>. */ 721 for (i = 0; i < sc->padconf->npins; i++) 722 if (sc->padconf->pins[i].port == gpios[0] && 723 sc->padconf->pins[i].pin == gpios[1]) { 724 *pin = i; 725 break; 726 } 727 *flags = gpios[gcells - 1]; 728 729 return (0); 730} 731 732static device_method_t a10_gpio_methods[] = { 733 /* Device interface */ 734 DEVMETHOD(device_probe, a10_gpio_probe), 735 DEVMETHOD(device_attach, a10_gpio_attach), 736 DEVMETHOD(device_detach, a10_gpio_detach), 737 738 /* GPIO protocol */ 739 DEVMETHOD(gpio_get_bus, a10_gpio_get_bus), 740 DEVMETHOD(gpio_pin_max, a10_gpio_pin_max), 741 DEVMETHOD(gpio_pin_getname, a10_gpio_pin_getname), 742 DEVMETHOD(gpio_pin_getflags, a10_gpio_pin_getflags), 743 DEVMETHOD(gpio_pin_getcaps, a10_gpio_pin_getcaps), 744 DEVMETHOD(gpio_pin_setflags, a10_gpio_pin_setflags), 745 DEVMETHOD(gpio_pin_get, a10_gpio_pin_get), 746 DEVMETHOD(gpio_pin_set, a10_gpio_pin_set), 747 DEVMETHOD(gpio_pin_toggle, a10_gpio_pin_toggle), 748 DEVMETHOD(gpio_map_gpios, a10_gpio_map_gpios), 749 750 /* ofw_bus interface */ 751 DEVMETHOD(ofw_bus_get_node, a10_gpio_get_node), 752 753 /* fdt_pinctrl interface */ 754 DEVMETHOD(fdt_pinctrl_configure,aw_fdt_configure_pins), 755 756 DEVMETHOD_END 757}; 758 759static devclass_t a10_gpio_devclass; 760 761static driver_t a10_gpio_driver = { 762 "gpio", 763 a10_gpio_methods, 764 sizeof(struct a10_gpio_softc), 765}; 766 767EARLY_DRIVER_MODULE(a10_gpio, simplebus, a10_gpio_driver, a10_gpio_devclass, 0, 0, 768 BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); 769