1 /* $OpenBSD: sxipio.c,v 1.12 2020/03/29 09:35:10 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2010 Miodrag Vallat. 4 * Copyright (c) 2013 Artturi Alm 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 #include <sys/systm.h> 21 #include <sys/device.h> 22 #include <sys/gpio.h> 23 #include <sys/evcount.h> 24 #include <sys/malloc.h> 25 26 #include <machine/bus.h> 27 #include <machine/fdt.h> 28 #include <machine/intr.h> 29 30 #include <dev/gpio/gpiovar.h> 31 #include <dev/ofw/openfirm.h> 32 #include <dev/ofw/ofw_clock.h> 33 #include <dev/ofw/ofw_gpio.h> 34 #include <dev/ofw/ofw_pinctrl.h> 35 #include <dev/ofw/ofw_regulator.h> 36 #include <dev/ofw/fdt.h> 37 38 #include <dev/fdt/sunxireg.h> 39 #include <dev/fdt/sxipiovar.h> 40 41 #include "gpio.h" 42 43 #define SXIPIO_NPORT 9 44 45 struct sxipio_softc; 46 47 struct sxipio_gpio { 48 struct sxipio_softc *sc; 49 int port; 50 }; 51 52 struct intrhand { 53 int (*ih_func)(void *); /* handler */ 54 void *ih_arg; /* arg for handler */ 55 int ih_ipl; /* IPL_* */ 56 int ih_irq; /* IRQ number */ 57 int ih_gpio; /* gpio pin */ 58 struct evcount ih_count; 59 char *ih_name; 60 }; 61 62 struct sxipio_softc { 63 struct device sc_dev; 64 bus_space_tag_t sc_iot; 65 bus_space_handle_t sc_ioh; 66 int sc_node; 67 void *sc_ih_h; 68 void *sc_ih_l; 69 int sc_max_il; 70 int sc_min_il; 71 72 struct sxipio_pin *sc_pins; 73 int sc_npins; 74 struct gpio_controller sc_gc; 75 76 struct sxipio_gpio sc_gpio[SXIPIO_NPORT]; 77 struct gpio_chipset_tag sc_gpio_tag[SXIPIO_NPORT]; 78 gpio_pin_t sc_gpio_pins[SXIPIO_NPORT][32]; 79 80 struct intrhand *sc_handlers[32]; 81 82 void (*sc_bias_cfg)(struct sxipio_softc *, 83 int, uint32_t); 84 }; 85 86 #define SXIPIO_CFG(port, pin) 0x00 + ((port) * 0x24) + (((pin) >> 3) * 0x04) 87 #define SXIPIO_DAT(port) 0x10 + ((port) * 0x24) 88 #define SXIPIO_DRV(port, pin) 0x14 + ((port) * 0x24) + (((pin) >> 4) * 0x04) 89 #define SXIPIO_PUL(port, pin) 0x1c + ((port) * 0x24) + (((pin) >> 4) * 0x04) 90 #define SXIPIO_INT_CFG0(port) 0x0200 + ((port) * 0x04) 91 #define SXIPIO_INT_CTL 0x0210 92 #define SXIPIO_INT_STA 0x0214 93 #define SXIPIO_INT_DEB 0x0218 /* debounce register */ 94 #define SXIPIO_GRP_CFG(port) 0x0300 + ((port) * 0x04) 95 #define SXIPIO_IO_BIAS_MASK (0xf << 0) 96 #define SXIPIO_IO_BIAS_1_8V 0x0 97 #define SXIPIO_IO_BIAS_2_5V 0x6 98 #define SXIPIO_IO_BIAS_2_8V 0x9 99 #define SXIPIO_IO_BIAS_3_0V 0xa 100 #define SXIPIO_IO_BIAS_3_3V 0xd 101 102 #define SXIPIO_GPIO_IN 0 103 #define SXIPIO_GPIO_OUT 1 104 #define SXIPIO_DISABLED 7 105 106 int sxipio_match(struct device *, void *, void *); 107 void sxipio_attach(struct device *, struct device *, void *); 108 109 struct cfattach sxipio_ca = { 110 sizeof (struct sxipio_softc), sxipio_match, sxipio_attach 111 }; 112 113 struct cfdriver sxipio_cd = { 114 NULL, "sxipio", DV_DULL 115 }; 116 117 void sxipio_attach_gpio(struct device *); 118 int sxipio_pinctrl(uint32_t, void *); 119 void sxipio_config_pin(void *, uint32_t *, int); 120 int sxipio_get_pin(void *, uint32_t *); 121 void sxipio_set_pin(void *, uint32_t *, int); 122 void sxipio_a80_bias_cfg(struct sxipio_softc *, int, uint32_t); 123 124 #include "sxipio_pins.h" 125 126 struct sxipio_pins { 127 const char *compat; 128 struct sxipio_pin *pins; 129 int npins; 130 }; 131 132 struct sxipio_pins sxipio_pins[] = { 133 { 134 "allwinner,sun4i-a10-pinctrl", 135 sun4i_a10_pins, nitems(sun4i_a10_pins) 136 }, 137 { 138 "allwinner,sun5i-a10s-pinctrl", 139 sun5i_a10s_pins, nitems(sun5i_a10s_pins) 140 }, 141 { 142 "allwinner,sun5i-a13-pinctrl", 143 sun5i_a13_pins, nitems(sun5i_a13_pins) 144 }, 145 { 146 "allwinner,sun5i-gr8-pinctrl", 147 sun5i_gr8_pins, nitems(sun5i_gr8_pins) 148 }, 149 { 150 "allwinner,sun7i-a20-pinctrl", 151 sun7i_a20_pins, nitems(sun7i_a20_pins) 152 }, 153 { 154 "allwinner,sun8i-r40-pinctrl", 155 sun8i_r40_pins, nitems(sun8i_r40_pins) 156 }, 157 { 158 "allwinner,sun8i-a33-pinctrl", 159 sun8i_a33_pins, nitems(sun8i_a33_pins) 160 }, 161 { 162 "allwinner,sun8i-h3-pinctrl", 163 sun8i_h3_pins, nitems(sun8i_h3_pins) 164 }, 165 { 166 "allwinner,sun8i-h3-r-pinctrl", 167 sun8i_h3_r_pins, nitems(sun8i_h3_r_pins) 168 }, 169 { 170 "allwinner,sun8i-v3s-pinctrl", 171 sun8i_v3s_pins, nitems(sun8i_v3s_pins) 172 }, 173 { 174 "allwinner,sun9i-a80-pinctrl", 175 sun9i_a80_pins, nitems(sun9i_a80_pins) 176 }, 177 { 178 "allwinner,sun9i-a80-r-pinctrl", 179 sun9i_a80_r_pins, nitems(sun9i_a80_r_pins) 180 }, 181 { 182 "allwinner,sun50i-a64-pinctrl", 183 sun50i_a64_pins, nitems(sun50i_a64_pins) 184 }, 185 { 186 "allwinner,sun50i-a64-r-pinctrl", 187 sun50i_a64_r_pins, nitems(sun50i_a64_r_pins) 188 }, 189 { 190 "allwinner,sun50i-h5-pinctrl", 191 sun50i_h5_pins, nitems(sun50i_h5_pins) 192 }, 193 { 194 "allwinner,sun50i-h6-pinctrl", 195 sun50i_h6_pins, nitems(sun50i_h6_pins) 196 }, 197 { 198 "allwinner,sun50i-h6-r-pinctrl", 199 sun50i_h6_r_pins, nitems(sun50i_h6_r_pins) 200 }, 201 }; 202 203 int 204 sxipio_match(struct device *parent, void *match, void *aux) 205 { 206 struct fdt_attach_args *faa = aux; 207 int i; 208 209 for (i = 0; i < nitems(sxipio_pins); i++) { 210 if (OF_is_compatible(faa->fa_node, sxipio_pins[i].compat)) 211 return 1; 212 } 213 214 return 0; 215 } 216 217 void 218 sxipio_attach(struct device *parent, struct device *self, void *aux) 219 { 220 struct sxipio_softc *sc = (struct sxipio_softc *)self; 221 struct fdt_attach_args *faa = aux; 222 int i; 223 224 sc->sc_iot = faa->fa_iot; 225 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 226 faa->fa_reg[0].size, 0, &sc->sc_ioh)) 227 panic("%s: bus_space_map failed!", __func__); 228 sc->sc_node = faa->fa_node; 229 230 clock_enable_all(faa->fa_node); 231 reset_deassert_all(faa->fa_node); 232 233 for (i = 0; i < nitems(sxipio_pins); i++) { 234 if (OF_is_compatible(faa->fa_node, sxipio_pins[i].compat)) { 235 sc->sc_pins = sxipio_pins[i].pins; 236 sc->sc_npins = sxipio_pins[i].npins; 237 break; 238 } 239 } 240 241 /* Allwinner A80 needs IO pad bias configuration. */ 242 if (OF_is_compatible(faa->fa_node, "allwinner,sun9i-a80-pinctrl") || 243 OF_is_compatible(faa->fa_node, "allwinner,sun9i-a80-r-pinctrl")) 244 sc->sc_bias_cfg = sxipio_a80_bias_cfg; 245 246 KASSERT(sc->sc_pins); 247 pinctrl_register(faa->fa_node, sxipio_pinctrl, sc); 248 249 sc->sc_gc.gc_node = faa->fa_node; 250 sc->sc_gc.gc_cookie = sc; 251 sc->sc_gc.gc_config_pin = sxipio_config_pin; 252 sc->sc_gc.gc_get_pin = sxipio_get_pin; 253 sc->sc_gc.gc_set_pin = sxipio_set_pin; 254 gpio_controller_register(&sc->sc_gc); 255 256 config_defer(self, sxipio_attach_gpio); 257 258 printf(": %d pins\n", sc->sc_npins); 259 } 260 261 int 262 sxipio_drive(int node) 263 { 264 int drive; 265 266 drive = OF_getpropint(node, "allwinner,drive", -1); 267 if (drive >= 0) 268 return drive; 269 drive = OF_getpropint(node, "drive-strength", 0) - 10; 270 if (drive >= 0) 271 return (drive / 10); 272 return -1; 273 } 274 275 int 276 sxipio_pull(int node) 277 { 278 int pull; 279 280 pull = OF_getpropint(node, "allwinner,pull", -1); 281 if (pull >= 0) 282 return pull; 283 if (OF_getproplen(node, "bias-disable") == 0) 284 return 0; 285 if (OF_getproplen(node, "bias-pull-up") == 0) 286 return 1; 287 if (OF_getproplen(node, "bias-pull-down") == 0) 288 return 2; 289 return -1; 290 } 291 292 int 293 sxipio_pinctrl(uint32_t phandle, void *cookie) 294 { 295 struct sxipio_softc *sc = cookie; 296 char func[32]; 297 char vcc[16]; 298 char *names, *name; 299 uint32_t supply; 300 int group, port, pin, off, mask; 301 int mux, drive, pull; 302 int node; 303 int len; 304 int i, j; 305 int s; 306 307 node = OF_getnodebyphandle(phandle); 308 if (node == 0) 309 return -1; 310 311 len = OF_getprop(node, "allwinner,function", func, sizeof(func)); 312 if (len <= 0 || len >= sizeof(func)) { 313 len = OF_getprop(node, "function", func, sizeof(func)); 314 if (len <= 0 || len >= sizeof(func)) 315 return -1; 316 } 317 318 len = OF_getproplen(node, "allwinner,pins"); 319 if (len <= 0) { 320 len = OF_getproplen(node, "pins"); 321 if (len <= 0) 322 return -1; 323 } 324 325 names = malloc(len, M_TEMP, M_WAITOK); 326 if (OF_getprop(node, "allwinner,pins", names, len) <= 0) 327 OF_getprop(node, "pins", names, len); 328 329 drive = sxipio_drive(node); 330 pull = sxipio_pull(node); 331 332 name = names; 333 while (len > 0) { 334 /* Lookup the pin. */ 335 for (i = 0; i < sc->sc_npins; i++) { 336 if (strcmp(name, sc->sc_pins[i].name) == 0) 337 break; 338 } 339 if (i >= sc->sc_npins) 340 goto err; 341 342 /* Lookup the function of the pin. */ 343 for (j = 0; j < nitems(sc->sc_pins[i].funcs); j++) { 344 if (sc->sc_pins[i].funcs[j].name == NULL) 345 continue; 346 if (strcmp(func, sc->sc_pins[i].funcs[j].name) == 0) 347 break; 348 } 349 if (j > nitems(sc->sc_pins[i].funcs)) 350 goto err; 351 352 group = sc->sc_pins[i].name[1] - 'A'; 353 port = sc->sc_pins[i].port; 354 pin = sc->sc_pins[i].pin; 355 mux = sc->sc_pins[i].funcs[j].mux; 356 357 snprintf(vcc, sizeof(vcc), "vcc-p%c-supply", 'a' + group); 358 supply = OF_getpropint(sc->sc_node, vcc, 0); 359 if (supply) { 360 regulator_enable(supply); 361 if (sc->sc_bias_cfg) 362 sc->sc_bias_cfg(sc, port, supply); 363 } 364 365 s = splhigh(); 366 off = (pin & 0x7) << 2, mask = (0x7 << off); 367 SXICMS4(sc, SXIPIO_CFG(port, pin), mask, mux << off); 368 off = (pin & 0xf) << 1, mask = (0x3 << off); 369 if (drive >= 0 && drive < 4) 370 SXICMS4(sc, SXIPIO_DRV(port, pin), mask, drive << off); 371 if (pull >= 0 && pull < 3) 372 SXICMS4(sc, SXIPIO_PUL(port, pin), mask, pull << off); 373 splx(s); 374 375 len -= strlen(name) + 1; 376 name += strlen(name) + 1; 377 } 378 379 free(names, M_TEMP, len); 380 return 0; 381 382 err: 383 free(names, M_TEMP, len); 384 return -1; 385 } 386 387 void 388 sxipio_config_pin(void *cookie, uint32_t *cells, int config) 389 { 390 struct sxipio_softc *sc = cookie; 391 uint32_t port = cells[0]; 392 uint32_t pin = cells[1]; 393 int mux, off; 394 395 if (port > SXIPIO_NPORT || pin > 32) 396 return; 397 398 mux = (config & GPIO_CONFIG_OUTPUT) ? 1 : 0; 399 off = (pin & 0x7) << 2; 400 SXICMS4(sc, SXIPIO_CFG(port, pin), 0x7 << off, mux << off); 401 } 402 403 int 404 sxipio_get_pin(void *cookie, uint32_t *cells) 405 { 406 struct sxipio_softc *sc = cookie; 407 uint32_t port = cells[0]; 408 uint32_t pin = cells[1]; 409 uint32_t flags = cells[2]; 410 uint32_t reg; 411 int val; 412 413 if (port > SXIPIO_NPORT || pin > 32) 414 return 0; 415 416 reg = SXIREAD4(sc, SXIPIO_DAT(port)); 417 reg &= (1 << pin); 418 val = (reg >> pin) & 1; 419 if (flags & GPIO_ACTIVE_LOW) 420 val = !val; 421 return val; 422 } 423 424 void 425 sxipio_set_pin(void *cookie, uint32_t *cells, int val) 426 { 427 struct sxipio_softc *sc = cookie; 428 uint32_t port = cells[0]; 429 uint32_t pin = cells[1]; 430 uint32_t flags = cells[2]; 431 uint32_t reg; 432 433 if (port > SXIPIO_NPORT || pin > 32) 434 return; 435 436 reg = SXIREAD4(sc, SXIPIO_DAT(port)); 437 if (flags & GPIO_ACTIVE_LOW) 438 val = !val; 439 if (val) 440 reg |= (1 << pin); 441 else 442 reg &= ~(1 << pin); 443 SXIWRITE4(sc, SXIPIO_DAT(port), reg); 444 } 445 446 void 447 sxipio_a80_bias_cfg(struct sxipio_softc *sc, int port, uint32_t supply) 448 { 449 uint32_t voltage; 450 uint32_t bias; 451 452 voltage = regulator_get_voltage(supply); 453 if (voltage <= 1800000) 454 bias = SXIPIO_IO_BIAS_1_8V; 455 else if (voltage <= 2500000) 456 bias = SXIPIO_IO_BIAS_2_5V; 457 else if (voltage <= 2800000) 458 bias = SXIPIO_IO_BIAS_2_8V; 459 else if (voltage <= 3000000) 460 bias = SXIPIO_IO_BIAS_3_0V; 461 else 462 bias = SXIPIO_IO_BIAS_3_3V; 463 464 SXICMS4(sc, SXIPIO_GRP_CFG(port), SXIPIO_IO_BIAS_MASK, bias); 465 } 466 467 /* 468 * GPIO support code 469 */ 470 471 int sxipio_pin_read(void *, int); 472 void sxipio_pin_write(void *, int, int); 473 void sxipio_pin_ctl(void *, int, int); 474 475 static const struct gpio_chipset_tag sxipio_gpio_tag = { 476 .gp_pin_read = sxipio_pin_read, 477 .gp_pin_write = sxipio_pin_write, 478 .gp_pin_ctl = sxipio_pin_ctl 479 }; 480 481 int 482 sxipio_pin_read(void *cookie, int pin) 483 { 484 struct sxipio_gpio *gpio = cookie; 485 uint32_t cells[3]; 486 487 cells[0] = gpio->port; 488 cells[1] = pin; 489 cells[2] = 0; 490 491 return sxipio_get_pin(gpio->sc, cells) ? GPIO_PIN_HIGH : GPIO_PIN_LOW; 492 } 493 494 void 495 sxipio_pin_write(void *cookie, int pin, int val) 496 { 497 struct sxipio_gpio *gpio = cookie; 498 uint32_t cells[3]; 499 500 cells[0] = gpio->port; 501 cells[1] = pin; 502 cells[2] = 0; 503 504 sxipio_set_pin(gpio->sc, cells, val); 505 } 506 507 void 508 sxipio_pin_ctl(void *cookie, int pin, int flags) 509 { 510 struct sxipio_gpio *gpio = cookie; 511 uint32_t cells[3]; 512 513 cells[0] = gpio->port; 514 cells[1] = pin; 515 cells[2] = 0; 516 517 if (ISSET(flags, GPIO_PIN_OUTPUT)) 518 sxipio_config_pin(gpio->sc, cells, GPIO_CONFIG_OUTPUT); 519 else 520 sxipio_config_pin(gpio->sc, cells, 0); 521 } 522 523 void 524 sxipio_attach_gpio(struct device *parent) 525 { 526 struct sxipio_softc *sc = (struct sxipio_softc *)parent; 527 struct gpiobus_attach_args gba; 528 uint32_t reg; 529 int port, pin; 530 int off, mux; 531 int state, flags; 532 int i; 533 534 for (i = 0; i < sc->sc_npins; i++) { 535 /* Skip pins that have no gpio function. */ 536 if (strcmp(sc->sc_pins[i].funcs[0].name, "gpio_in") != 0 || 537 strcmp(sc->sc_pins[i].funcs[1].name, "gpio_out") != 0) 538 continue; 539 540 port = sc->sc_pins[i].port; 541 pin = sc->sc_pins[i].pin; 542 543 /* Get pin configuration. */ 544 reg = SXIREAD4(sc, SXIPIO_CFG(port, pin)); 545 off = (pin & 0x7) << 2; 546 mux = (reg >> off) & 0x7; 547 548 /* Skip pins that have been assigned other functions. */ 549 if (mux != SXIPIO_GPIO_IN && mux != SXIPIO_GPIO_OUT && 550 mux != SXIPIO_DISABLED) 551 continue; 552 553 switch (mux) { 554 case SXIPIO_GPIO_IN: 555 flags = GPIO_PIN_SET | GPIO_PIN_INPUT; 556 break; 557 case SXIPIO_GPIO_OUT: 558 flags = GPIO_PIN_SET | GPIO_PIN_OUTPUT; 559 break; 560 default: 561 flags = GPIO_PIN_SET; 562 } 563 564 /* Get pin state. */ 565 reg = SXIREAD4(sc, SXIPIO_DAT(port)); 566 state = (reg >> pin) & 1; 567 568 sc->sc_gpio_pins[port][pin].pin_caps = 569 GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; 570 sc->sc_gpio_pins[port][pin].pin_flags = flags; 571 sc->sc_gpio_pins[port][pin].pin_state = state; 572 sc->sc_gpio_pins[port][pin].pin_num = pin; 573 } 574 575 for (i = 0; i <= port; i++) { 576 memcpy(&sc->sc_gpio_tag[i], &sxipio_gpio_tag, sizeof(sxipio_gpio_tag)); 577 sc->sc_gpio_tag[i].gp_cookie = &sc->sc_gpio[i]; 578 sc->sc_gpio[i].sc = sc; 579 sc->sc_gpio[i].port = i; 580 581 gba.gba_name = "gpio"; 582 gba.gba_gc = &sc->sc_gpio_tag[i]; 583 gba.gba_pins = &sc->sc_gpio_pins[i][0]; 584 gba.gba_npins = 32; 585 586 #if NGPIO > 0 587 config_found(&sc->sc_dev, &gba, gpiobus_print); 588 #endif 589 } 590 } 591