1 /*- 2 * Copyright (c) 2006 Benno Rice. 3 * Copyright (C) 2008 MARVELL INTERNATIONAL LTD. 4 * All rights reserved. 5 * 6 * Adapted and extended for Marvell SoCs by Semihalf. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * from: FreeBSD: //depot/projects/arm/src/sys/arm/xscale/pxa2x0/pxa2x0_gpio.c, rev 1 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/bus.h> 37 #include <sys/kernel.h> 38 #include <sys/lock.h> 39 #include <sys/interrupt.h> 40 #include <sys/module.h> 41 #include <sys/malloc.h> 42 #include <sys/mutex.h> 43 #include <sys/rman.h> 44 #include <sys/queue.h> 45 #include <sys/timetc.h> 46 #include <machine/bus.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 <arm/mv/mvvar.h> 55 #include <arm/mv/mvreg.h> 56 57 #define GPIO_MAX_INTR_COUNT 8 58 #define GPIO_PINS_PER_REG 32 59 60 struct mv_gpio_softc { 61 struct resource * res[GPIO_MAX_INTR_COUNT + 1]; 62 void *ih_cookie[GPIO_MAX_INTR_COUNT]; 63 bus_space_tag_t bst; 64 bus_space_handle_t bsh; 65 uint8_t pin_num; /* number of GPIO pins */ 66 uint8_t irq_num; /* number of real IRQs occupied by GPIO controller */ 67 }; 68 69 extern struct resource_spec mv_gpio_res[]; 70 71 static struct mv_gpio_softc *mv_gpio_softc = NULL; 72 static uint32_t gpio_setup[MV_GPIO_MAX_NPINS]; 73 74 static int mv_gpio_probe(device_t); 75 static int mv_gpio_attach(device_t); 76 static int mv_gpio_intr(void *); 77 static int mv_gpio_init(void); 78 79 static void mv_gpio_intr_handler(int pin); 80 static uint32_t mv_gpio_reg_read(uint32_t reg); 81 static void mv_gpio_reg_write(uint32_t reg, uint32_t val); 82 static void mv_gpio_reg_set(uint32_t reg, uint32_t val); 83 static void mv_gpio_reg_clear(uint32_t reg, uint32_t val); 84 85 static void mv_gpio_blink(uint32_t pin, uint8_t enable); 86 static void mv_gpio_polarity(uint32_t pin, uint8_t enable); 87 static void mv_gpio_level(uint32_t pin, uint8_t enable); 88 static void mv_gpio_edge(uint32_t pin, uint8_t enable); 89 static void mv_gpio_out_en(uint32_t pin, uint8_t enable); 90 static void mv_gpio_int_ack(uint32_t pin); 91 static void mv_gpio_value_set(uint32_t pin, uint8_t val); 92 static uint32_t mv_gpio_value_get(uint32_t pin); 93 94 static device_method_t mv_gpio_methods[] = { 95 DEVMETHOD(device_probe, mv_gpio_probe), 96 DEVMETHOD(device_attach, mv_gpio_attach), 97 { 0, 0 } 98 }; 99 100 static driver_t mv_gpio_driver = { 101 "gpio", 102 mv_gpio_methods, 103 sizeof(struct mv_gpio_softc), 104 }; 105 106 static devclass_t mv_gpio_devclass; 107 108 DRIVER_MODULE(gpio, simplebus, mv_gpio_driver, mv_gpio_devclass, 0, 0); 109 110 typedef int (*gpios_phandler_t)(phandle_t, pcell_t *, int); 111 112 struct gpio_ctrl_entry { 113 const char *compat; 114 gpios_phandler_t handler; 115 }; 116 117 int mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len); 118 int gpio_get_config_from_dt(void); 119 120 struct gpio_ctrl_entry gpio_controllers[] = { 121 { "mrvl,gpio", &mv_handle_gpios_prop }, 122 { NULL, NULL } 123 }; 124 125 static int 126 mv_gpio_probe(device_t dev) 127 { 128 129 if (!ofw_bus_status_okay(dev)) 130 return (ENXIO); 131 132 if (!ofw_bus_is_compatible(dev, "mrvl,gpio")) 133 return (ENXIO); 134 135 device_set_desc(dev, "Marvell Integrated GPIO Controller"); 136 return (0); 137 } 138 139 static int 140 mv_gpio_attach(device_t dev) 141 { 142 int error, i; 143 struct mv_gpio_softc *sc; 144 uint32_t dev_id, rev_id; 145 146 sc = (struct mv_gpio_softc *)device_get_softc(dev); 147 if (sc == NULL) 148 return (ENXIO); 149 150 mv_gpio_softc = sc; 151 152 /* Get chip id and revision */ 153 soc_id(&dev_id, &rev_id); 154 155 if (dev_id == MV_DEV_88F5182 || 156 dev_id == MV_DEV_88F5281 || 157 dev_id == MV_DEV_MV78100 || 158 dev_id == MV_DEV_MV78100_Z0 ) { 159 sc->pin_num = 32; 160 sc->irq_num = 4; 161 162 } else if (dev_id == MV_DEV_88F6281 || 163 dev_id == MV_DEV_88F6282) { 164 sc->pin_num = 50; 165 sc->irq_num = 7; 166 167 } else { 168 device_printf(dev, "unknown chip id=0x%x\n", dev_id); 169 return (ENXIO); 170 } 171 172 error = bus_alloc_resources(dev, mv_gpio_res, sc->res); 173 if (error) { 174 device_printf(dev, "could not allocate resources\n"); 175 return (ENXIO); 176 } 177 178 sc->bst = rman_get_bustag(sc->res[0]); 179 sc->bsh = rman_get_bushandle(sc->res[0]); 180 181 /* Disable and clear all interrupts */ 182 bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_EDGE_MASK, 0); 183 bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_LEV_MASK, 0); 184 bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_CAUSE, 0); 185 186 if (sc->pin_num > GPIO_PINS_PER_REG) { 187 bus_space_write_4(sc->bst, sc->bsh, 188 GPIO_HI_INT_EDGE_MASK, 0); 189 bus_space_write_4(sc->bst, sc->bsh, 190 GPIO_HI_INT_LEV_MASK, 0); 191 bus_space_write_4(sc->bst, sc->bsh, 192 GPIO_HI_INT_CAUSE, 0); 193 } 194 195 for (i = 0; i < sc->irq_num; i++) { 196 if (bus_setup_intr(dev, sc->res[1 + i], 197 INTR_TYPE_MISC, mv_gpio_intr, NULL, 198 sc, &sc->ih_cookie[i]) != 0) { 199 bus_release_resources(dev, mv_gpio_res, sc->res); 200 device_printf(dev, "could not set up intr %d\n", i); 201 return (ENXIO); 202 } 203 } 204 205 return (mv_gpio_init()); 206 } 207 208 static int 209 mv_gpio_intr(void *arg) 210 { 211 uint32_t int_cause, gpio_val; 212 uint32_t int_cause_hi, gpio_val_hi = 0; 213 int i; 214 215 int_cause = mv_gpio_reg_read(GPIO_INT_CAUSE); 216 gpio_val = mv_gpio_reg_read(GPIO_DATA_IN); 217 gpio_val &= int_cause; 218 if (mv_gpio_softc->pin_num > GPIO_PINS_PER_REG) { 219 int_cause_hi = mv_gpio_reg_read(GPIO_HI_INT_CAUSE); 220 gpio_val_hi = mv_gpio_reg_read(GPIO_HI_DATA_IN); 221 gpio_val_hi &= int_cause_hi; 222 } 223 224 i = 0; 225 while (gpio_val != 0) { 226 if (gpio_val & 1) 227 mv_gpio_intr_handler(i); 228 gpio_val >>= 1; 229 i++; 230 } 231 232 if (mv_gpio_softc->pin_num > GPIO_PINS_PER_REG) { 233 i = 0; 234 while (gpio_val_hi != 0) { 235 if (gpio_val_hi & 1) 236 mv_gpio_intr_handler(i + GPIO_PINS_PER_REG); 237 gpio_val_hi >>= 1; 238 i++; 239 } 240 } 241 242 return (FILTER_HANDLED); 243 } 244 245 /* 246 * GPIO interrupt handling 247 */ 248 249 static struct intr_event *gpio_events[MV_GPIO_MAX_NPINS]; 250 251 int 252 mv_gpio_setup_intrhandler(const char *name, driver_filter_t *filt, 253 void (*hand)(void *), void *arg, int pin, int flags, void **cookiep) 254 { 255 struct intr_event *event; 256 int error; 257 258 if (pin < 0 || pin >= mv_gpio_softc->pin_num) 259 return (ENXIO); 260 event = gpio_events[pin]; 261 if (event == NULL) { 262 error = intr_event_create(&event, (void *)pin, 0, pin, 263 (void (*)(void *))mv_gpio_intr_mask, 264 (void (*)(void *))mv_gpio_intr_unmask, 265 (void (*)(void *))mv_gpio_int_ack, 266 NULL, 267 "gpio%d:", pin); 268 if (error != 0) 269 return (error); 270 gpio_events[pin] = event; 271 } 272 273 intr_event_add_handler(event, name, filt, hand, arg, 274 intr_priority(flags), flags, cookiep); 275 return (0); 276 } 277 278 void 279 mv_gpio_intr_mask(int pin) 280 { 281 282 if (pin >= mv_gpio_softc->pin_num) 283 return; 284 285 if (gpio_setup[pin] & MV_GPIO_IN_IRQ_EDGE) 286 mv_gpio_edge(pin, 0); 287 else 288 mv_gpio_level(pin, 0); 289 } 290 291 void 292 mv_gpio_intr_unmask(int pin) 293 { 294 295 if (pin >= mv_gpio_softc->pin_num) 296 return; 297 298 if (gpio_setup[pin] & MV_GPIO_IN_IRQ_EDGE) 299 mv_gpio_edge(pin, 1); 300 else 301 mv_gpio_level(pin, 1); 302 } 303 304 static void 305 mv_gpio_intr_handler(int pin) 306 { 307 struct intr_event *event; 308 309 event = gpio_events[pin]; 310 if (event == NULL || TAILQ_EMPTY(&event->ie_handlers)) 311 return; 312 313 intr_event_handle(event, NULL); 314 } 315 316 static int 317 mv_gpio_configure(uint32_t pin, uint32_t flags) 318 { 319 320 if (pin >= mv_gpio_softc->pin_num) 321 return (EINVAL); 322 323 if (flags & MV_GPIO_OUT_BLINK) 324 mv_gpio_blink(pin, 1); 325 if (flags & MV_GPIO_IN_POL_LOW) 326 mv_gpio_polarity(pin, 1); 327 if (flags & MV_GPIO_IN_IRQ_EDGE) 328 mv_gpio_edge(pin, 1); 329 if (flags & MV_GPIO_IN_IRQ_LEVEL) 330 mv_gpio_level(pin, 1); 331 332 gpio_setup[pin] = flags; 333 334 return (0); 335 } 336 337 void 338 mv_gpio_out(uint32_t pin, uint8_t val, uint8_t enable) 339 { 340 341 mv_gpio_value_set(pin, val); 342 mv_gpio_out_en(pin, enable); 343 } 344 345 uint8_t 346 mv_gpio_in(uint32_t pin) 347 { 348 349 return (mv_gpio_value_get(pin) ? 1 : 0); 350 } 351 352 static uint32_t 353 mv_gpio_reg_read(uint32_t reg) 354 { 355 356 return (bus_space_read_4(mv_gpio_softc->bst, 357 mv_gpio_softc->bsh, reg)); 358 } 359 360 static void 361 mv_gpio_reg_write(uint32_t reg, uint32_t val) 362 { 363 364 bus_space_write_4(mv_gpio_softc->bst, 365 mv_gpio_softc->bsh, reg, val); 366 } 367 368 static void 369 mv_gpio_reg_set(uint32_t reg, uint32_t pin) 370 { 371 uint32_t reg_val; 372 373 reg_val = mv_gpio_reg_read(reg); 374 reg_val |= GPIO(pin); 375 mv_gpio_reg_write(reg, reg_val); 376 } 377 378 static void 379 mv_gpio_reg_clear(uint32_t reg, uint32_t pin) 380 { 381 uint32_t reg_val; 382 383 reg_val = mv_gpio_reg_read(reg); 384 reg_val &= ~(GPIO(pin)); 385 mv_gpio_reg_write(reg, reg_val); 386 } 387 388 static void 389 mv_gpio_out_en(uint32_t pin, uint8_t enable) 390 { 391 uint32_t reg; 392 393 if (pin >= mv_gpio_softc->pin_num) 394 return; 395 396 if (pin >= GPIO_PINS_PER_REG) { 397 reg = GPIO_HI_DATA_OUT_EN_CTRL; 398 pin -= GPIO_PINS_PER_REG; 399 } else 400 reg = GPIO_DATA_OUT_EN_CTRL; 401 402 if (enable) 403 mv_gpio_reg_clear(reg, pin); 404 else 405 mv_gpio_reg_set(reg, pin); 406 } 407 408 static void 409 mv_gpio_blink(uint32_t pin, uint8_t enable) 410 { 411 uint32_t reg; 412 413 if (pin >= mv_gpio_softc->pin_num) 414 return; 415 416 if (pin >= GPIO_PINS_PER_REG) { 417 reg = GPIO_HI_BLINK_EN; 418 pin -= GPIO_PINS_PER_REG; 419 } else 420 reg = GPIO_BLINK_EN; 421 422 if (enable) 423 mv_gpio_reg_set(reg, pin); 424 else 425 mv_gpio_reg_clear(reg, pin); 426 } 427 428 static void 429 mv_gpio_polarity(uint32_t pin, uint8_t enable) 430 { 431 uint32_t reg; 432 433 if (pin >= mv_gpio_softc->pin_num) 434 return; 435 436 if (pin >= GPIO_PINS_PER_REG) { 437 reg = GPIO_HI_DATA_IN_POLAR; 438 pin -= GPIO_PINS_PER_REG; 439 } else 440 reg = GPIO_DATA_IN_POLAR; 441 442 if (enable) 443 mv_gpio_reg_set(reg, pin); 444 else 445 mv_gpio_reg_clear(reg, pin); 446 } 447 448 static void 449 mv_gpio_level(uint32_t pin, uint8_t enable) 450 { 451 uint32_t reg; 452 453 if (pin >= mv_gpio_softc->pin_num) 454 return; 455 456 if (pin >= GPIO_PINS_PER_REG) { 457 reg = GPIO_HI_INT_LEV_MASK; 458 pin -= GPIO_PINS_PER_REG; 459 } else 460 reg = GPIO_INT_LEV_MASK; 461 462 if (enable) 463 mv_gpio_reg_set(reg, pin); 464 else 465 mv_gpio_reg_clear(reg, pin); 466 } 467 468 static void 469 mv_gpio_edge(uint32_t pin, uint8_t enable) 470 { 471 uint32_t reg; 472 473 if (pin >= mv_gpio_softc->pin_num) 474 return; 475 476 if (pin >= GPIO_PINS_PER_REG) { 477 reg = GPIO_HI_INT_EDGE_MASK; 478 pin -= GPIO_PINS_PER_REG; 479 } else 480 reg = GPIO_INT_EDGE_MASK; 481 482 if (enable) 483 mv_gpio_reg_set(reg, pin); 484 else 485 mv_gpio_reg_clear(reg, pin); 486 } 487 488 static void 489 mv_gpio_int_ack(uint32_t pin) 490 { 491 uint32_t reg; 492 493 if (pin >= mv_gpio_softc->pin_num) 494 return; 495 496 if (pin >= GPIO_PINS_PER_REG) { 497 reg = GPIO_HI_INT_CAUSE; 498 pin -= GPIO_PINS_PER_REG; 499 } else 500 reg = GPIO_INT_CAUSE; 501 502 mv_gpio_reg_clear(reg, pin); 503 } 504 505 static uint32_t 506 mv_gpio_value_get(uint32_t pin) 507 { 508 uint32_t reg, reg_val; 509 510 if (pin >= mv_gpio_softc->pin_num) 511 return (0); 512 513 if (pin >= GPIO_PINS_PER_REG) { 514 reg = GPIO_HI_DATA_IN; 515 pin -= GPIO_PINS_PER_REG; 516 } else 517 reg = GPIO_DATA_IN; 518 519 reg_val = mv_gpio_reg_read(reg); 520 521 return (reg_val & GPIO(pin)); 522 } 523 524 static void 525 mv_gpio_value_set(uint32_t pin, uint8_t val) 526 { 527 uint32_t reg; 528 529 if (pin >= mv_gpio_softc->pin_num) 530 return; 531 532 if (pin >= GPIO_PINS_PER_REG) { 533 reg = GPIO_HI_DATA_OUT; 534 pin -= GPIO_PINS_PER_REG; 535 } else 536 reg = GPIO_DATA_OUT; 537 538 if (val) 539 mv_gpio_reg_set(reg, pin); 540 else 541 mv_gpio_reg_clear(reg, pin); 542 } 543 544 int 545 mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len) 546 { 547 pcell_t gpio_cells, pincnt; 548 int inc, t, tuples, tuple_size; 549 int dir, flags, pin; 550 u_long gpio_ctrl, size; 551 struct mv_gpio_softc sc; 552 553 pincnt = 0; 554 if (!OF_hasprop(ctrl, "gpio-controller")) 555 /* Node is not a GPIO controller. */ 556 return (ENXIO); 557 558 if (OF_getprop(ctrl, "#gpio-cells", &gpio_cells, sizeof(pcell_t)) < 0) 559 return (ENXIO); 560 561 gpio_cells = fdt32_to_cpu(gpio_cells); 562 if (gpio_cells != 3) 563 return (ENXIO); 564 565 tuple_size = gpio_cells * sizeof(pcell_t) + sizeof(phandle_t); 566 tuples = len / tuple_size; 567 568 if (fdt_regsize(ctrl, &gpio_ctrl, &size)) 569 return (ENXIO); 570 571 if (OF_getprop(ctrl, "pin-count", &pincnt, sizeof(pcell_t)) < 0) 572 return (ENXIO); 573 sc.pin_num = fdt32_to_cpu(pincnt); 574 575 /* 576 * Skip controller reference, since controller's phandle is given 577 * explicitly (in a function argument). 578 */ 579 inc = sizeof(ihandle_t) / sizeof(pcell_t); 580 gpios += inc; 581 582 for (t = 0; t < tuples; t++) { 583 pin = fdt32_to_cpu(gpios[0]); 584 dir = fdt32_to_cpu(gpios[1]); 585 flags = fdt32_to_cpu(gpios[2]); 586 587 mv_gpio_configure(pin, flags); 588 589 if (dir == 1) 590 /* Input. */ 591 mv_gpio_out_en(pin, 0); 592 else { 593 /* Output. */ 594 if (flags & MV_GPIO_OUT_OPEN_DRAIN) 595 mv_gpio_out(pin, 0, 1); 596 597 if (flags & MV_GPIO_OUT_OPEN_SRC) 598 mv_gpio_out(pin, 1, 1); 599 } 600 gpios += gpio_cells + inc; 601 } 602 603 return (0); 604 } 605 606 #define MAX_PINS_PER_NODE 5 607 #define GPIOS_PROP_CELLS 4 608 static int 609 mv_gpio_init(void) 610 { 611 phandle_t child, parent, root, ctrl; 612 pcell_t gpios[MAX_PINS_PER_NODE * GPIOS_PROP_CELLS]; 613 struct gpio_ctrl_entry *e; 614 int len, rv; 615 616 root = OF_finddevice("/"); 617 len = 0; 618 parent = root; 619 620 /* Traverse through entire tree to find nodes with 'gpios' prop */ 621 for (child = OF_child(parent); child != 0; child = OF_peer(child)) { 622 623 /* Find a 'leaf'. Start the search from this node. */ 624 while (OF_child(child)) { 625 parent = child; 626 child = OF_child(child); 627 } 628 if ((len = OF_getproplen(child, "gpios")) > 0) { 629 630 if (len > sizeof(gpios)) 631 return (ENXIO); 632 633 /* Get 'gpios' property. */ 634 OF_getprop(child, "gpios", &gpios, len); 635 636 e = (struct gpio_ctrl_entry *)&gpio_controllers; 637 638 /* Find and call a handler. */ 639 for (; e->compat; e++) { 640 /* 641 * First cell of 'gpios' property should 642 * contain a ref. to a node defining GPIO 643 * controller. 644 */ 645 ctrl = OF_node_from_xref(fdt32_to_cpu(gpios[0])); 646 647 if (fdt_is_compatible(ctrl, e->compat)) 648 /* Call a handler. */ 649 if ((rv = e->handler(ctrl, 650 (pcell_t *)&gpios, len))) 651 return (rv); 652 } 653 } 654 655 if (OF_peer(child) == 0) { 656 /* No more siblings. */ 657 child = parent; 658 parent = OF_parent(child); 659 } 660 } 661 return (0); 662 } 663