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>
|
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/fdt.h> 48#include <machine/intr.h> 49 50#include <dev/fdt/fdt_common.h> 51#include <dev/ofw/ofw_bus.h> 52#include <dev/ofw/ofw_bus_subr.h> 53 54#include "gpio_if.h" 55 56#include "rk30xx_grf.h" 57#include "rk30xx_pmu.h" 58 59/* 60 * RK3188 has 4 banks of gpio. 61 * 32 pins per bank 62 * PA0 - PA7 | PB0 - PB7 63 * PC0 - PC7 | PD0 - PD7 64 */ 65 66#define RK30_GPIO_PINS 128 67#define RK30_GPIO_DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \ 68 GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN) 69 70#define RK30_GPIO_NONE 0 71#define RK30_GPIO_PULLUP 1 72#define RK30_GPIO_PULLDOWN 2 73 74#define RK30_GPIO_INPUT 0 75#define RK30_GPIO_OUTPUT 1 76 77struct rk30_gpio_softc { 78 device_t sc_dev; 79 struct mtx sc_mtx; 80 struct resource * sc_mem_res; 81 struct resource * sc_irq_res; 82 bus_space_tag_t sc_bst; 83 bus_space_handle_t sc_bsh; 84 void * sc_intrhand; 85 int sc_gpio_npins; 86 struct gpio_pin sc_gpio_pins[RK30_GPIO_PINS]; 87}; 88 89static struct rk30_gpio_softc *rk30_gpio_sc = NULL; 90 91typedef int (*gpios_phandler_t)(phandle_t, pcell_t *, int); 92 93struct gpio_ctrl_entry { 94 const char *compat; 95 gpios_phandler_t handler; 96}; 97 98int rk30_gpios_prop_handle(phandle_t ctrl, pcell_t *gpios, int len); 99static int rk30_gpio_init(void); 100 101struct gpio_ctrl_entry gpio_controllers[] = { 102 { "rockchip,rk30xx-gpio", &rk30_gpios_prop_handle }, 103 { "rockchip,rk30xx-gpio", &rk30_gpios_prop_handle }, 104 { "rockchip,rk30xx-gpio", &rk30_gpios_prop_handle }, 105 { "rockchip,rk30xx-gpio", &rk30_gpios_prop_handle }, 106 { NULL, NULL } 107}; 108 109#define RK30_GPIO_LOCK(_sc) mtx_lock(&_sc->sc_mtx) 110#define RK30_GPIO_UNLOCK(_sc) mtx_unlock(&_sc->sc_mtx) 111#define RK30_GPIO_LOCK_ASSERT(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED) 112 113#define RK30_GPIO_SWPORT_DR 0x00 114#define RK30_GPIO_SWPORT_DDR 0x04 115#define RK30_GPIO_INTEN 0x30 116#define RK30_GPIO_INTMASK 0x34 117#define RK30_GPIO_INTTYPE_LEVEL 0x38 118#define RK30_GPIO_INT_POLARITY 0x3c 119#define RK30_GPIO_INT_STATUS 0x40 120#define RK30_GPIO_INT_RAWSTATUS 0x44 121#define RK30_GPIO_DEBOUNCE 0x48 122#define RK30_GPIO_PORTS_EOI 0x4c 123#define RK30_GPIO_EXT_PORT 0x50 124#define RK30_GPIO_LS_SYNC 0x60 125 126#define RK30_GPIO_WRITE(_sc, _off, _val) \ 127 bus_space_write_4(_sc->sc_bst, _sc->sc_bsh, _off, _val) 128#define RK30_GPIO_READ(_sc, _off) \ 129 bus_space_read_4(_sc->sc_bst, _sc->sc_bsh, _off) 130 131static uint32_t 132rk30_gpio_get_function(struct rk30_gpio_softc *sc, uint32_t pin) 133{ 134 uint32_t bank, func, offset; 135 136 bank = pin / 32; 137 pin = pin % 32; 138 offset = 1 << pin; 139 140 func = RK30_GPIO_READ(sc, RK30_GPIO_SWPORT_DDR); 141 func &= offset; 142 143 return (func); 144} 145 146static uint32_t 147rk30_gpio_func_flag(uint32_t nfunc) 148{ 149 150 switch (nfunc) { 151 case RK30_GPIO_INPUT: 152 return (GPIO_PIN_INPUT); 153 case RK30_GPIO_OUTPUT: 154 return (GPIO_PIN_OUTPUT); 155 } 156 return (0); 157} 158 159static void 160rk30_gpio_set_function(struct rk30_gpio_softc *sc, uint32_t pin, uint32_t f) 161{ 162 uint32_t bank, data, offset; 163 164 /* Must be called with lock held. */ 165 RK30_GPIO_LOCK_ASSERT(sc); 166 167 bank = pin / 32; 168 pin = pin % 32; 169 offset = 1 << pin; 170 171 data = RK30_GPIO_READ(sc, RK30_GPIO_SWPORT_DDR); 172 if (f) 173 data |= offset; 174 else 175 data &= ~offset; 176 RK30_GPIO_WRITE(sc, RK30_GPIO_SWPORT_DDR, data); 177} 178 179static void 180rk30_gpio_set_pud(struct rk30_gpio_softc *sc, uint32_t pin, uint32_t state) 181{ 182 uint32_t bank; 183 184 bank = pin / 32; 185 186 /* Must be called with lock held. */ 187 RK30_GPIO_LOCK_ASSERT(sc); 188 189 if (bank == 0 && pin < 12) 190 rk30_pmu_gpio_pud(pin, state); 191 else 192 rk30_grf_gpio_pud(bank, pin, state); 193} 194 195static void 196rk30_gpio_pin_configure(struct rk30_gpio_softc *sc, struct gpio_pin *pin, 197 unsigned int flags) 198{ 199 200 RK30_GPIO_LOCK(sc); 201 202 /* 203 * Manage input/output. 204 */ 205 if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) { 206 pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT); 207 if (flags & GPIO_PIN_OUTPUT) { 208 pin->gp_flags |= GPIO_PIN_OUTPUT; 209 rk30_gpio_set_function(sc, pin->gp_pin, 210 RK30_GPIO_OUTPUT); 211 } else { 212 pin->gp_flags |= GPIO_PIN_INPUT; 213 rk30_gpio_set_function(sc, pin->gp_pin, 214 RK30_GPIO_INPUT); 215 } 216 } 217 218 /* Manage Pull-up/pull-down. */ 219 pin->gp_flags &= ~(GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN); 220 if (flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) { 221 if (flags & GPIO_PIN_PULLUP) { 222 pin->gp_flags |= GPIO_PIN_PULLUP; 223 rk30_gpio_set_pud(sc, pin->gp_pin, 224 RK30_GPIO_PULLUP); 225 } else { 226 pin->gp_flags |= GPIO_PIN_PULLDOWN; 227 rk30_gpio_set_pud(sc, pin->gp_pin, 228 RK30_GPIO_PULLDOWN); 229 } 230 } else 231 rk30_gpio_set_pud(sc, pin->gp_pin, RK30_GPIO_NONE); 232 233 RK30_GPIO_UNLOCK(sc); 234} 235 236static int 237rk30_gpio_pin_max(device_t dev, int *maxpin) 238{ 239 240 *maxpin = RK30_GPIO_PINS - 1; 241 return (0); 242} 243 244static int 245rk30_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 246{ 247 struct rk30_gpio_softc *sc = device_get_softc(dev); 248 int i; 249 250 for (i = 0; i < sc->sc_gpio_npins; i++) { 251 if (sc->sc_gpio_pins[i].gp_pin == pin) 252 break; 253 } 254 255 if (i >= sc->sc_gpio_npins) 256 return (EINVAL); 257 258 RK30_GPIO_LOCK(sc); 259 *caps = sc->sc_gpio_pins[i].gp_caps; 260 RK30_GPIO_UNLOCK(sc); 261 262 return (0); 263} 264 265static int 266rk30_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 267{ 268 struct rk30_gpio_softc *sc = device_get_softc(dev); 269 int i; 270 271 for (i = 0; i < sc->sc_gpio_npins; i++) { 272 if (sc->sc_gpio_pins[i].gp_pin == pin) 273 break; 274 } 275 276 if (i >= sc->sc_gpio_npins) 277 return (EINVAL); 278 279 RK30_GPIO_LOCK(sc); 280 *flags = sc->sc_gpio_pins[i].gp_flags; 281 RK30_GPIO_UNLOCK(sc); 282 283 return (0); 284} 285 286static int 287rk30_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 288{ 289 struct rk30_gpio_softc *sc = device_get_softc(dev); 290 int i; 291 292 for (i = 0; i < sc->sc_gpio_npins; i++) { 293 if (sc->sc_gpio_pins[i].gp_pin == pin) 294 break; 295 } 296 297 if (i >= sc->sc_gpio_npins) 298 return (EINVAL); 299 300 RK30_GPIO_LOCK(sc); 301 memcpy(name, sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME); 302 RK30_GPIO_UNLOCK(sc); 303 304 return (0); 305} 306 307static int 308rk30_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 309{ 310 struct rk30_gpio_softc *sc = device_get_softc(dev); 311 int i; 312 313 for (i = 0; i < sc->sc_gpio_npins; i++) { 314 if (sc->sc_gpio_pins[i].gp_pin == pin) 315 break; 316 } 317 318 if (i >= sc->sc_gpio_npins) 319 return (EINVAL); 320 321 /* Check for unwanted flags. */ 322 if ((flags & sc->sc_gpio_pins[i].gp_caps) != flags) 323 return (EINVAL); 324 325 /* Can't mix input/output together. */ 326 if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == 327 (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) 328 return (EINVAL); 329 330 /* Can't mix pull-up/pull-down together. */ 331 if ((flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) == 332 (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) 333 return (EINVAL); 334 335 rk30_gpio_pin_configure(sc, &sc->sc_gpio_pins[i], flags); 336 337 return (0); 338} 339 340static int 341rk30_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 342{ 343 struct rk30_gpio_softc *sc = device_get_softc(dev); 344 uint32_t bank, offset, data; 345 int i; 346 347 for (i = 0; i < sc->sc_gpio_npins; i++) { 348 if (sc->sc_gpio_pins[i].gp_pin == pin) 349 break; 350 } 351 352 if (i >= sc->sc_gpio_npins) 353 return (EINVAL); 354 355 bank = pin / 32; 356 pin = pin % 32; 357 offset = 1 << pin; 358 359 RK30_GPIO_LOCK(sc); 360 data = RK30_GPIO_READ(sc, RK30_GPIO_SWPORT_DDR); 361 data |= offset; 362 RK30_GPIO_WRITE(sc, RK30_GPIO_SWPORT_DDR, data); 363 364 data = RK30_GPIO_READ(sc, RK30_GPIO_SWPORT_DR); 365 if (value) 366 data |= offset; 367 else 368 data &= ~offset; 369 RK30_GPIO_WRITE(sc, RK30_GPIO_SWPORT_DR, data); 370 RK30_GPIO_UNLOCK(sc); 371 372 return (0); 373} 374 375static int 376rk30_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) 377{ 378 struct rk30_gpio_softc *sc = device_get_softc(dev); 379 uint32_t bank, offset, reg_data; 380 int i; 381 382 for (i = 0; i < sc->sc_gpio_npins; i++) { 383 if (sc->sc_gpio_pins[i].gp_pin == pin) 384 break; 385 } 386 387 if (i >= sc->sc_gpio_npins) 388 return (EINVAL); 389 390 bank = pin / 32; 391 pin = pin % 32; 392 offset = 1 << pin; 393 394 RK30_GPIO_LOCK(sc); 395 reg_data = RK30_GPIO_READ(sc, RK30_GPIO_EXT_PORT); 396 RK30_GPIO_UNLOCK(sc); 397 *val = (reg_data & offset) ? 1 : 0; 398 399 return (0); 400} 401 402static int 403rk30_gpio_pin_toggle(device_t dev, uint32_t pin) 404{ 405 struct rk30_gpio_softc *sc = device_get_softc(dev); 406 uint32_t bank, data, offset; 407 int i; 408 409 for (i = 0; i < sc->sc_gpio_npins; i++) { 410 if (sc->sc_gpio_pins[i].gp_pin == pin) 411 break; 412 } 413 414 if (i >= sc->sc_gpio_npins) 415 return (EINVAL); 416 417 bank = pin / 32; 418 pin = pin % 32; 419 offset = 1 << pin; 420 421 RK30_GPIO_LOCK(sc); 422 data = RK30_GPIO_READ(sc, RK30_GPIO_SWPORT_DDR); 423 if (data & offset) 424 data &= ~offset; 425 else 426 data |= offset; 427 RK30_GPIO_WRITE(sc, RK30_GPIO_SWPORT_DDR, data); 428 429 data = RK30_GPIO_READ(sc, RK30_GPIO_SWPORT_DR); 430 if (data & offset) 431 data &= ~offset; 432 else 433 data |= offset; 434 RK30_GPIO_WRITE(sc, RK30_GPIO_SWPORT_DR, data); 435 RK30_GPIO_UNLOCK(sc); 436 437 return (0); 438} 439 440static int 441rk30_gpio_probe(device_t dev) 442{ 443 444 if (!ofw_bus_status_okay(dev)) 445 return (ENXIO); 446 447 if (!ofw_bus_is_compatible(dev, "rockchip,rk30xx-gpio")) 448 return (ENXIO); 449 450 device_set_desc(dev, "Rockchip RK30XX GPIO controller"); 451 return (BUS_PROBE_DEFAULT); 452} 453 454static int 455rk30_gpio_attach(device_t dev) 456{ 457 struct rk30_gpio_softc *sc = device_get_softc(dev); 458 uint32_t func; 459 int i, rid; 460 phandle_t gpio; 461 462 if (rk30_gpio_sc) 463 return (ENXIO); 464 465 sc->sc_dev = dev; 466 467 mtx_init(&sc->sc_mtx, "rk30 gpio", "gpio", MTX_DEF); 468 469 rid = 0; 470 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 471 RF_ACTIVE); 472 if (!sc->sc_mem_res) { 473 device_printf(dev, "cannot allocate memory window\n"); 474 return (ENXIO); 475 } 476 477 sc->sc_bst = rman_get_bustag(sc->sc_mem_res); 478 sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res); 479 480 rid = 0; 481 sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 482 RF_ACTIVE); 483 if (!sc->sc_irq_res) { 484 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); 485 device_printf(dev, "cannot allocate interrupt\n"); 486 return (ENXIO); 487 } 488 489 /* Find our node. */ 490 gpio = ofw_bus_get_node(sc->sc_dev); 491 492 if (!OF_hasprop(gpio, "gpio-controller")) 493 /* Node is not a GPIO controller. */ 494 goto fail; 495 496 /* Initialize the software controlled pins. */ 497 for (i = 0; i < RK30_GPIO_PINS; i++) { 498 snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME, 499 "pin %d", i); 500 func = rk30_gpio_get_function(sc, i); 501 sc->sc_gpio_pins[i].gp_pin = i; 502 sc->sc_gpio_pins[i].gp_caps = RK30_GPIO_DEFAULT_CAPS; 503 sc->sc_gpio_pins[i].gp_flags = rk30_gpio_func_flag(func); 504 } 505 sc->sc_gpio_npins = i; 506
|
509 510 rk30_gpio_sc = sc; 511 512 rk30_gpio_init(); 513 514 return (bus_generic_attach(dev)); 515 516fail: 517 if (sc->sc_irq_res) 518 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res); 519 if (sc->sc_mem_res) 520 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); 521 return (ENXIO); 522} 523 524static int 525rk30_gpio_detach(device_t dev) 526{ 527 528 return (EBUSY); 529} 530 531static device_method_t rk30_gpio_methods[] = { 532 /* Device interface */ 533 DEVMETHOD(device_probe, rk30_gpio_probe), 534 DEVMETHOD(device_attach, rk30_gpio_attach), 535 DEVMETHOD(device_detach, rk30_gpio_detach), 536 537 /* GPIO protocol */ 538 DEVMETHOD(gpio_pin_max, rk30_gpio_pin_max), 539 DEVMETHOD(gpio_pin_getname, rk30_gpio_pin_getname), 540 DEVMETHOD(gpio_pin_getflags, rk30_gpio_pin_getflags), 541 DEVMETHOD(gpio_pin_getcaps, rk30_gpio_pin_getcaps), 542 DEVMETHOD(gpio_pin_setflags, rk30_gpio_pin_setflags), 543 DEVMETHOD(gpio_pin_get, rk30_gpio_pin_get), 544 DEVMETHOD(gpio_pin_set, rk30_gpio_pin_set), 545 DEVMETHOD(gpio_pin_toggle, rk30_gpio_pin_toggle), 546 547 DEVMETHOD_END 548}; 549 550static devclass_t rk30_gpio_devclass; 551 552static driver_t rk30_gpio_driver = { 553 "gpio", 554 rk30_gpio_methods, 555 sizeof(struct rk30_gpio_softc), 556}; 557 558DRIVER_MODULE(rk30_gpio, simplebus, rk30_gpio_driver, rk30_gpio_devclass, 0, 0); 559 560int 561rk30_gpios_prop_handle(phandle_t ctrl, pcell_t *gpios, int len) 562{ 563 struct rk30_gpio_softc *sc; 564 pcell_t gpio_cells; 565 int inc, t, tuples, tuple_size; 566 int dir, flags, pin, i; 567 u_long gpio_ctrl, size; 568 569 sc = rk30_gpio_sc; 570 if (sc == NULL) 571 return ENXIO; 572 573 if (OF_getprop(ctrl, "#gpio-cells", &gpio_cells, sizeof(pcell_t)) < 0) 574 return (ENXIO); 575 576 gpio_cells = fdt32_to_cpu(gpio_cells); 577 if (gpio_cells != 2) 578 return (ENXIO); 579 580 tuple_size = gpio_cells * sizeof(pcell_t) + sizeof(phandle_t); 581 tuples = len / tuple_size; 582 583 if (fdt_regsize(ctrl, &gpio_ctrl, &size)) 584 return (ENXIO); 585 586 /* 587 * Skip controller reference, since controller's phandle is given 588 * explicitly (in a function argument). 589 */ 590 inc = sizeof(ihandle_t) / sizeof(pcell_t); 591 gpios += inc; 592 for (t = 0; t < tuples; t++) { 593 pin = fdt32_to_cpu(gpios[0]); 594 dir = fdt32_to_cpu(gpios[1]); 595 flags = fdt32_to_cpu(gpios[2]); 596 597 for (i = 0; i < sc->sc_gpio_npins; i++) { 598 if (sc->sc_gpio_pins[i].gp_pin == pin) 599 break; 600 } 601 if (i >= sc->sc_gpio_npins) 602 return (EINVAL); 603 604 rk30_gpio_pin_configure(sc, &sc->sc_gpio_pins[i], flags); 605 606 if (dir == 1) { 607 /* Input. */ 608 rk30_gpio_pin_set(sc->sc_dev, pin, RK30_GPIO_INPUT); 609 } else { 610 /* Output. */ 611 rk30_gpio_pin_set(sc->sc_dev, pin, RK30_GPIO_OUTPUT); 612 } 613 gpios += gpio_cells + inc; 614 } 615 616 return (0); 617} 618 619#define MAX_PINS_PER_NODE 5 620#define GPIOS_PROP_CELLS 4 621 622static int 623rk30_gpio_init(void) 624{ 625 phandle_t child, parent, root, ctrl; 626 pcell_t gpios[MAX_PINS_PER_NODE * GPIOS_PROP_CELLS]; 627 struct gpio_ctrl_entry *e; 628 int len, rv; 629 630 root = OF_finddevice("/"); 631 len = 0; 632 parent = root; 633 634 /* Traverse through entire tree to find nodes with 'gpios' prop */ 635 for (child = OF_child(parent); child != 0; child = OF_peer(child)) { 636 637 /* Find a 'leaf'. Start the search from this node. */ 638 while (OF_child(child)) { 639 parent = child; 640 child = OF_child(child); 641 } 642 if ((len = OF_getproplen(child, "gpios")) > 0) { 643 644 if (len > sizeof(gpios)) 645 return (ENXIO); 646 647 /* Get 'gpios' property. */ 648 OF_getprop(child, "gpios", &gpios, len); 649 650 e = (struct gpio_ctrl_entry *)&gpio_controllers; 651 652 /* Find and call a handler. */ 653 for (; e->compat; e++) { 654 /* 655 * First cell of 'gpios' property should 656 * contain a ref. to a node defining GPIO 657 * controller. 658 */ 659 ctrl = OF_node_from_xref(fdt32_to_cpu(gpios[0])); 660 661 if (fdt_is_compatible(ctrl, e->compat)) 662 /* Call a handler. */ 663 if ((rv = e->handler(ctrl, 664 (pcell_t *)&gpios, len))) 665 return (rv); 666 } 667 } 668 669 if (OF_peer(child) == 0) { 670 /* No more siblings. */ 671 child = parent; 672 parent = OF_parent(child); 673 } 674 } 675 return (0); 676}
|