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/intr.h> 48 49 #include <arm/mv/mvvar.h> 50 #include <arm/mv/mvreg.h> 51 52 #define GPIO_MAX_INTR_COUNT 8 53 #define GPIO_PINS_PER_REG 32 54 55 struct mv_gpio_softc { 56 struct resource * res[GPIO_MAX_INTR_COUNT + 1]; 57 void *ih_cookie[GPIO_MAX_INTR_COUNT]; 58 bus_space_tag_t bst; 59 bus_space_handle_t bsh; 60 uint8_t pin_num; /* number of GPIO pins */ 61 uint8_t irq_num; /* number of real IRQs occupied by GPIO controller */ 62 uint8_t use_high; 63 }; 64 65 extern struct resource_spec mv_gpio_res[]; 66 67 static struct mv_gpio_softc *mv_gpio_softc = NULL; 68 static uint32_t gpio_setup[MV_GPIO_MAX_NPINS]; 69 70 static int mv_gpio_probe(device_t); 71 static int mv_gpio_attach(device_t); 72 static void mv_gpio_intr(void *); 73 74 static void mv_gpio_intr_handler(int pin); 75 static uint32_t mv_gpio_reg_read(uint32_t reg); 76 static void mv_gpio_reg_write(uint32_t reg, uint32_t val); 77 static void mv_gpio_reg_set(uint32_t reg, uint32_t val); 78 static void mv_gpio_reg_clear(uint32_t reg, uint32_t val); 79 80 static void mv_gpio_blink(uint32_t pin, uint8_t enable); 81 static void mv_gpio_polarity(uint32_t pin, uint8_t enable); 82 static void mv_gpio_level(uint32_t pin, uint8_t enable); 83 static void mv_gpio_edge(uint32_t pin, uint8_t enable); 84 static void mv_gpio_out_en(uint32_t pin, uint8_t enable); 85 static void mv_gpio_int_ack(uint32_t pin); 86 static void mv_gpio_value_set(uint32_t pin, uint8_t val); 87 static uint32_t mv_gpio_value_get(uint32_t pin); 88 89 static device_method_t mv_gpio_methods[] = { 90 DEVMETHOD(device_probe, mv_gpio_probe), 91 DEVMETHOD(device_attach, mv_gpio_attach), 92 { 0, 0 } 93 }; 94 95 static driver_t mv_gpio_driver = { 96 "gpio", 97 mv_gpio_methods, 98 sizeof(struct mv_gpio_softc), 99 }; 100 101 static devclass_t mv_gpio_devclass; 102 103 DRIVER_MODULE(gpio, mbus, mv_gpio_driver, mv_gpio_devclass, 0, 0); 104 105 static int 106 mv_gpio_probe(device_t dev) 107 { 108 109 device_set_desc(dev, "Marvell Integrated GPIO Controller"); 110 return (0); 111 } 112 113 static int 114 mv_gpio_attach(device_t dev) 115 { 116 int error, i; 117 struct mv_gpio_softc *sc; 118 uint32_t dev_id, rev_id; 119 120 sc = (struct mv_gpio_softc *)device_get_softc(dev); 121 122 if (mv_gpio_softc != NULL) 123 return (ENXIO); 124 mv_gpio_softc = sc; 125 126 /* Get chip id and revision */ 127 soc_id(&dev_id, &rev_id); 128 129 if (dev_id == MV_DEV_88F5182 || 130 dev_id == MV_DEV_88F5281 || 131 dev_id == MV_DEV_MV78100 || 132 dev_id == MV_DEV_MV78100_Z0 ) { 133 sc->pin_num = 32; 134 sc->irq_num = 4; 135 sc->use_high = 0; 136 137 } else if (dev_id == MV_DEV_88F6281) { 138 sc->pin_num = 50; 139 sc->irq_num = 7; 140 sc->use_high = 1; 141 142 } else { 143 device_printf(dev, "unknown chip id=0x%x\n", dev_id); 144 return (ENXIO); 145 } 146 147 error = bus_alloc_resources(dev, mv_gpio_res, sc->res); 148 if (error) { 149 device_printf(dev, "could not allocate resources\n"); 150 return (ENXIO); 151 } 152 153 sc->bst = rman_get_bustag(sc->res[0]); 154 sc->bsh = rman_get_bushandle(sc->res[0]); 155 156 /* Disable and clear all interrupts */ 157 bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_EDGE_MASK, 0); 158 bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_LEV_MASK, 0); 159 bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_CAUSE, 0); 160 161 if (sc->use_high) { 162 bus_space_write_4(sc->bst, sc->bsh, 163 GPIO_HI_INT_EDGE_MASK, 0); 164 bus_space_write_4(sc->bst, sc->bsh, 165 GPIO_HI_INT_LEV_MASK, 0); 166 bus_space_write_4(sc->bst, sc->bsh, 167 GPIO_HI_INT_CAUSE, 0); 168 } 169 170 for (i = 0; i < sc->irq_num; i++) { 171 if (bus_setup_intr(dev, sc->res[1 + i], 172 INTR_TYPE_MISC | INTR_FAST, 173 (driver_filter_t *)mv_gpio_intr, NULL, 174 sc, &sc->ih_cookie[i]) != 0) { 175 bus_release_resources(dev, mv_gpio_res, sc->res); 176 device_printf(dev, "could not set up intr %d\n", i); 177 return (ENXIO); 178 } 179 } 180 181 /* Setup GPIO lines */ 182 for (i = 0; mv_gpio_config[i].gc_gpio >= 0; i++) { 183 mv_gpio_configure(mv_gpio_config[i].gc_gpio, 184 mv_gpio_config[i].gc_flags, ~0u); 185 186 if (mv_gpio_config[i].gc_output < 0) 187 mv_gpio_out_en(mv_gpio_config[i].gc_gpio, 0); 188 else 189 mv_gpio_out(mv_gpio_config[i].gc_gpio, 190 mv_gpio_config[i].gc_output, 1); 191 } 192 193 return (0); 194 } 195 196 static void 197 mv_gpio_intr(void *arg) 198 { 199 uint32_t int_cause, gpio_val; 200 uint32_t int_cause_hi, gpio_val_hi = 0; 201 int i; 202 203 int_cause = mv_gpio_reg_read(GPIO_INT_CAUSE); 204 gpio_val = mv_gpio_reg_read(GPIO_DATA_IN); 205 gpio_val &= int_cause; 206 if (mv_gpio_softc->use_high) { 207 int_cause_hi = mv_gpio_reg_read(GPIO_HI_INT_CAUSE); 208 gpio_val_hi = mv_gpio_reg_read(GPIO_HI_DATA_IN); 209 gpio_val_hi &= int_cause_hi; 210 } 211 212 i = 0; 213 while (gpio_val != 0) { 214 if (gpio_val & 1) 215 mv_gpio_intr_handler(i); 216 gpio_val >>= 1; 217 i++; 218 } 219 220 if (mv_gpio_softc->use_high) { 221 i = 0; 222 while (gpio_val_hi != 0) { 223 if (gpio_val_hi & 1) 224 mv_gpio_intr_handler(i + GPIO_PINS_PER_REG); 225 gpio_val_hi >>= 1; 226 i++; 227 } 228 } 229 } 230 231 /* 232 * GPIO interrupt handling 233 */ 234 235 static struct intr_event *gpio_events[MV_GPIO_MAX_NPINS]; 236 237 int 238 mv_gpio_setup_intrhandler(const char *name, driver_filter_t *filt, 239 void (*hand)(void *), void *arg, int pin, int flags, void **cookiep) 240 { 241 struct intr_event *event; 242 int error; 243 244 if (pin < 0 || pin >= mv_gpio_softc->pin_num) 245 return (ENXIO); 246 event = gpio_events[pin]; 247 if (event == NULL) { 248 error = intr_event_create(&event, (void *)pin, 0, pin, 249 (void (*)(void *))mv_gpio_intr_mask, 250 (void (*)(void *))mv_gpio_intr_unmask, 251 (void (*)(void *))mv_gpio_int_ack, 252 NULL, 253 "gpio%d:", pin); 254 if (error != 0) 255 return (error); 256 gpio_events[pin] = event; 257 } 258 259 intr_event_add_handler(event, name, filt, hand, arg, 260 intr_priority(flags), flags, cookiep); 261 return (0); 262 } 263 264 void 265 mv_gpio_intr_mask(int pin) 266 { 267 268 if (pin >= mv_gpio_softc->pin_num) 269 return; 270 271 if (gpio_setup[pin] & MV_GPIO_EDGE) 272 mv_gpio_edge(pin, 0); 273 else 274 mv_gpio_level(pin, 0); 275 } 276 277 void 278 mv_gpio_intr_unmask(int pin) 279 { 280 281 if (pin >= mv_gpio_softc->pin_num) 282 return; 283 284 if (gpio_setup[pin] & MV_GPIO_EDGE) 285 mv_gpio_edge(pin, 1); 286 else 287 mv_gpio_level(pin, 1); 288 } 289 290 static void 291 mv_gpio_intr_handler(int pin) 292 { 293 struct intr_event *event; 294 295 event = gpio_events[pin]; 296 if (event == NULL || TAILQ_EMPTY(&event->ie_handlers)) 297 return; 298 299 intr_event_handle(event, NULL); 300 } 301 302 int 303 mv_gpio_configure(uint32_t pin, uint32_t flags, uint32_t mask) 304 { 305 306 if (pin >= mv_gpio_softc->pin_num) 307 return (EINVAL); 308 309 if (mask & MV_GPIO_BLINK) 310 mv_gpio_blink(pin, flags & MV_GPIO_BLINK); 311 if (mask & MV_GPIO_POLAR_LOW) 312 mv_gpio_polarity(pin, flags & MV_GPIO_POLAR_LOW); 313 if (mask & MV_GPIO_EDGE) 314 mv_gpio_edge(pin, flags & MV_GPIO_EDGE); 315 if (mask & MV_GPIO_LEVEL) 316 mv_gpio_level(pin, flags & MV_GPIO_LEVEL); 317 318 gpio_setup[pin] &= ~(mask); 319 gpio_setup[pin] |= (flags & mask); 320 321 return (0); 322 } 323 324 void 325 mv_gpio_out(uint32_t pin, uint8_t val, uint8_t enable) 326 { 327 328 mv_gpio_value_set(pin, val); 329 mv_gpio_out_en(pin, enable); 330 } 331 332 uint8_t 333 mv_gpio_in(uint32_t pin) 334 { 335 336 return (mv_gpio_value_get(pin)); 337 } 338 339 static uint32_t 340 mv_gpio_reg_read(uint32_t reg) 341 { 342 343 return (bus_space_read_4(mv_gpio_softc->bst, 344 mv_gpio_softc->bsh, reg)); 345 } 346 347 static void 348 mv_gpio_reg_write(uint32_t reg, uint32_t val) 349 { 350 351 bus_space_write_4(mv_gpio_softc->bst, 352 mv_gpio_softc->bsh, reg, val); 353 } 354 355 static void 356 mv_gpio_reg_set(uint32_t reg, uint32_t pin) 357 { 358 uint32_t reg_val; 359 360 reg_val = mv_gpio_reg_read(reg); 361 reg_val |= GPIO(pin); 362 mv_gpio_reg_write(reg, reg_val); 363 } 364 365 static void 366 mv_gpio_reg_clear(uint32_t reg, uint32_t pin) 367 { 368 uint32_t reg_val; 369 370 reg_val = mv_gpio_reg_read(reg); 371 reg_val &= ~(GPIO(pin)); 372 mv_gpio_reg_write(reg, reg_val); 373 } 374 375 static void 376 mv_gpio_out_en(uint32_t pin, uint8_t enable) 377 { 378 uint32_t reg; 379 380 if (pin >= mv_gpio_softc->pin_num) 381 return; 382 383 if (pin >= GPIO_PINS_PER_REG) { 384 reg = GPIO_HI_DATA_OUT_EN_CTRL; 385 pin -= GPIO_PINS_PER_REG; 386 } else 387 reg = GPIO_DATA_OUT_EN_CTRL; 388 389 if (enable) 390 mv_gpio_reg_clear(reg, pin); 391 else 392 mv_gpio_reg_set(reg, pin); 393 } 394 395 static void 396 mv_gpio_blink(uint32_t pin, uint8_t enable) 397 { 398 uint32_t reg; 399 400 if (pin >= mv_gpio_softc->pin_num) 401 return; 402 403 if (pin >= GPIO_PINS_PER_REG) { 404 reg = GPIO_HI_BLINK_EN; 405 pin -= GPIO_PINS_PER_REG; 406 } else 407 reg = GPIO_BLINK_EN; 408 409 if (enable) 410 mv_gpio_reg_set(reg, pin); 411 else 412 mv_gpio_reg_clear(reg, pin); 413 } 414 415 static void 416 mv_gpio_polarity(uint32_t pin, uint8_t enable) 417 { 418 uint32_t reg; 419 420 if (pin >= mv_gpio_softc->pin_num) 421 return; 422 423 if (pin >= GPIO_PINS_PER_REG) { 424 reg = GPIO_HI_DATA_IN_POLAR; 425 pin -= GPIO_PINS_PER_REG; 426 } else 427 reg = GPIO_DATA_IN_POLAR; 428 429 if (enable) 430 mv_gpio_reg_set(reg, pin); 431 else 432 mv_gpio_reg_clear(reg, pin); 433 } 434 435 static void 436 mv_gpio_level(uint32_t pin, uint8_t enable) 437 { 438 uint32_t reg; 439 440 if (pin >= mv_gpio_softc->pin_num) 441 return; 442 443 if (pin >= GPIO_PINS_PER_REG) { 444 reg = GPIO_HI_INT_LEV_MASK; 445 pin -= GPIO_PINS_PER_REG; 446 } else 447 reg = GPIO_INT_LEV_MASK; 448 449 if (enable) 450 mv_gpio_reg_set(reg, pin); 451 else 452 mv_gpio_reg_clear(reg, pin); 453 } 454 455 static void 456 mv_gpio_edge(uint32_t pin, uint8_t enable) 457 { 458 uint32_t reg; 459 460 if (pin >= mv_gpio_softc->pin_num) 461 return; 462 463 if (pin >= GPIO_PINS_PER_REG) { 464 reg = GPIO_HI_INT_EDGE_MASK; 465 pin -= GPIO_PINS_PER_REG; 466 } else 467 reg = GPIO_INT_EDGE_MASK; 468 469 if (enable) 470 mv_gpio_reg_set(reg, pin); 471 else 472 mv_gpio_reg_clear(reg, pin); 473 } 474 475 static void 476 mv_gpio_int_ack(uint32_t pin) 477 { 478 uint32_t reg; 479 480 if (pin >= mv_gpio_softc->pin_num) 481 return; 482 483 if (pin >= GPIO_PINS_PER_REG) { 484 reg = GPIO_HI_INT_CAUSE; 485 pin -= GPIO_PINS_PER_REG; 486 } else 487 reg = GPIO_INT_CAUSE; 488 489 mv_gpio_reg_clear(reg, pin); 490 } 491 492 static uint32_t 493 mv_gpio_value_get(uint32_t pin) 494 { 495 uint32_t reg, reg_val; 496 497 if (pin >= mv_gpio_softc->pin_num) 498 return (0); 499 500 if (pin >= GPIO_PINS_PER_REG) { 501 reg = GPIO_HI_DATA_IN; 502 pin -= GPIO_PINS_PER_REG; 503 } else 504 reg = GPIO_DATA_IN; 505 506 reg_val = mv_gpio_reg_read(reg); 507 508 return (reg_val & GPIO(pin)); 509 } 510 511 static void 512 mv_gpio_value_set(uint32_t pin, uint8_t val) 513 { 514 uint32_t reg; 515 516 if (pin >= mv_gpio_softc->pin_num) 517 return; 518 519 if (pin >= GPIO_PINS_PER_REG) { 520 reg = GPIO_HI_DATA_OUT; 521 pin -= GPIO_PINS_PER_REG; 522 } else 523 reg = GPIO_DATA_OUT; 524 525 if (val) 526 mv_gpio_reg_set(reg, pin); 527 else 528 mv_gpio_reg_clear(reg, pin); 529 } 530