1 /* $OpenBSD: sxipio.c,v 1.19 2024/02/08 00:00:16 jsg 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 const 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 const 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 const struct sxipio_pin *pins; 129 int npins; 130 }; 131 132 const 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-v3-pinctrl", 171 sun8i_v3_pins, nitems(sun8i_v3_pins) 172 }, 173 { 174 "allwinner,sun8i-v3s-pinctrl", 175 sun8i_v3s_pins, nitems(sun8i_v3s_pins) 176 }, 177 { 178 "allwinner,sun9i-a80-pinctrl", 179 sun9i_a80_pins, nitems(sun9i_a80_pins) 180 }, 181 { 182 "allwinner,sun9i-a80-r-pinctrl", 183 sun9i_a80_r_pins, nitems(sun9i_a80_r_pins) 184 }, 185 { 186 "allwinner,sun20i-d1-pinctrl", 187 sun20i_d1_pins, nitems(sun20i_d1_pins) 188 }, 189 { 190 "allwinner,sun50i-a64-pinctrl", 191 sun50i_a64_pins, nitems(sun50i_a64_pins) 192 }, 193 { 194 "allwinner,sun50i-a64-r-pinctrl", 195 sun50i_a64_r_pins, nitems(sun50i_a64_r_pins) 196 }, 197 { 198 "allwinner,sun50i-h5-pinctrl", 199 sun50i_h5_pins, nitems(sun50i_h5_pins) 200 }, 201 { 202 "allwinner,sun50i-h6-pinctrl", 203 sun50i_h6_pins, nitems(sun50i_h6_pins) 204 }, 205 { 206 "allwinner,sun50i-h6-r-pinctrl", 207 sun50i_h6_r_pins, nitems(sun50i_h6_r_pins) 208 }, 209 { 210 "allwinner,sun50i-h616-pinctrl", 211 sun50i_h616_pins, nitems(sun50i_h616_pins) 212 }, 213 { 214 "allwinner,sun50i-h616-r-pinctrl", 215 sun50i_h616_r_pins, nitems(sun50i_h616_r_pins) 216 }, 217 }; 218 219 int 220 sxipio_match(struct device *parent, void *match, void *aux) 221 { 222 struct fdt_attach_args *faa = aux; 223 int i; 224 225 for (i = 0; i < nitems(sxipio_pins); i++) { 226 if (OF_is_compatible(faa->fa_node, sxipio_pins[i].compat)) 227 return 1; 228 } 229 230 return 0; 231 } 232 233 void 234 sxipio_attach(struct device *parent, struct device *self, void *aux) 235 { 236 struct sxipio_softc *sc = (struct sxipio_softc *)self; 237 struct fdt_attach_args *faa = aux; 238 int i; 239 240 sc->sc_iot = faa->fa_iot; 241 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 242 faa->fa_reg[0].size, 0, &sc->sc_ioh)) 243 panic("%s: bus_space_map failed!", __func__); 244 sc->sc_node = faa->fa_node; 245 246 clock_enable_all(faa->fa_node); 247 reset_deassert_all(faa->fa_node); 248 249 for (i = 0; i < nitems(sxipio_pins); i++) { 250 if (OF_is_compatible(faa->fa_node, sxipio_pins[i].compat)) { 251 sc->sc_pins = sxipio_pins[i].pins; 252 sc->sc_npins = sxipio_pins[i].npins; 253 break; 254 } 255 } 256 257 /* Allwinner A80 needs IO pad bias configuration. */ 258 if (OF_is_compatible(faa->fa_node, "allwinner,sun9i-a80-pinctrl") || 259 OF_is_compatible(faa->fa_node, "allwinner,sun9i-a80-r-pinctrl")) 260 sc->sc_bias_cfg = sxipio_a80_bias_cfg; 261 262 KASSERT(sc->sc_pins); 263 pinctrl_register(faa->fa_node, sxipio_pinctrl, sc); 264 265 sc->sc_gc.gc_node = faa->fa_node; 266 sc->sc_gc.gc_cookie = sc; 267 sc->sc_gc.gc_config_pin = sxipio_config_pin; 268 sc->sc_gc.gc_get_pin = sxipio_get_pin; 269 sc->sc_gc.gc_set_pin = sxipio_set_pin; 270 gpio_controller_register(&sc->sc_gc); 271 272 config_defer(self, sxipio_attach_gpio); 273 274 printf(": %d pins\n", sc->sc_npins); 275 } 276 277 int 278 sxipio_drive(int node) 279 { 280 int drive; 281 282 drive = OF_getpropint(node, "allwinner,drive", -1); 283 if (drive >= 0) 284 return drive; 285 drive = OF_getpropint(node, "drive-strength", 0) - 10; 286 if (drive >= 0) 287 return (drive / 10); 288 return -1; 289 } 290 291 int 292 sxipio_pull(int node) 293 { 294 int pull; 295 296 pull = OF_getpropint(node, "allwinner,pull", -1); 297 if (pull >= 0) 298 return pull; 299 if (OF_getproplen(node, "bias-disable") == 0) 300 return 0; 301 if (OF_getproplen(node, "bias-pull-up") == 0) 302 return 1; 303 if (OF_getproplen(node, "bias-pull-down") == 0) 304 return 2; 305 return -1; 306 } 307 308 int 309 sxipio_pinctrl(uint32_t phandle, void *cookie) 310 { 311 struct sxipio_softc *sc = cookie; 312 char func[32]; 313 char vcc[16]; 314 char *names, *name; 315 uint32_t supply; 316 int group, port, pin, off, mask; 317 int mux, drive, pull; 318 int node; 319 int len; 320 int i, j; 321 int s; 322 323 node = OF_getnodebyphandle(phandle); 324 if (node == 0) 325 return -1; 326 327 len = OF_getprop(node, "allwinner,function", func, sizeof(func)); 328 if (len <= 0 || len >= sizeof(func)) { 329 len = OF_getprop(node, "function", func, sizeof(func)); 330 if (len <= 0 || len >= sizeof(func)) 331 return -1; 332 } 333 334 len = OF_getproplen(node, "allwinner,pins"); 335 if (len <= 0) { 336 len = OF_getproplen(node, "pins"); 337 if (len <= 0) 338 return -1; 339 } 340 341 names = malloc(len, M_TEMP, M_WAITOK); 342 if (OF_getprop(node, "allwinner,pins", names, len) <= 0) 343 OF_getprop(node, "pins", names, len); 344 345 drive = sxipio_drive(node); 346 pull = sxipio_pull(node); 347 348 name = names; 349 while (len > 0) { 350 /* Lookup the pin. */ 351 for (i = 0; i < sc->sc_npins; i++) { 352 if (strcmp(name, sc->sc_pins[i].name) == 0) 353 break; 354 } 355 if (i >= sc->sc_npins) 356 goto err; 357 358 /* Lookup the function of the pin. */ 359 for (j = 0; j < nitems(sc->sc_pins[i].funcs); j++) { 360 if (sc->sc_pins[i].funcs[j].name == NULL) 361 continue; 362 if (strcmp(func, sc->sc_pins[i].funcs[j].name) == 0) 363 break; 364 } 365 if (j >= nitems(sc->sc_pins[i].funcs)) 366 goto err; 367 368 group = sc->sc_pins[i].name[1] - 'A'; 369 port = sc->sc_pins[i].port; 370 pin = sc->sc_pins[i].pin; 371 mux = sc->sc_pins[i].funcs[j].mux; 372 373 snprintf(vcc, sizeof(vcc), "vcc-p%c-supply", 'a' + group); 374 supply = OF_getpropint(sc->sc_node, vcc, 0); 375 if (supply) { 376 regulator_enable(supply); 377 if (sc->sc_bias_cfg) 378 sc->sc_bias_cfg(sc, port, supply); 379 } 380 381 s = splhigh(); 382 off = (pin & 0x7) << 2, mask = (0x7 << off); 383 SXICMS4(sc, SXIPIO_CFG(port, pin), mask, mux << off); 384 off = (pin & 0xf) << 1, mask = (0x3 << off); 385 if (drive >= 0 && drive < 4) 386 SXICMS4(sc, SXIPIO_DRV(port, pin), mask, drive << off); 387 if (pull >= 0 && pull < 3) 388 SXICMS4(sc, SXIPIO_PUL(port, pin), mask, pull << off); 389 splx(s); 390 391 len -= strlen(name) + 1; 392 name += strlen(name) + 1; 393 } 394 395 free(names, M_TEMP, len); 396 return 0; 397 398 err: 399 free(names, M_TEMP, len); 400 return -1; 401 } 402 403 void 404 sxipio_config_pin(void *cookie, uint32_t *cells, int config) 405 { 406 struct sxipio_softc *sc = cookie; 407 uint32_t port = cells[0]; 408 uint32_t pin = cells[1]; 409 int mux, off; 410 411 if (port > SXIPIO_NPORT || pin >= 32) 412 return; 413 414 mux = (config & GPIO_CONFIG_OUTPUT) ? 1 : 0; 415 off = (pin & 0x7) << 2; 416 SXICMS4(sc, SXIPIO_CFG(port, pin), 0x7 << off, mux << off); 417 } 418 419 int 420 sxipio_get_pin(void *cookie, uint32_t *cells) 421 { 422 struct sxipio_softc *sc = cookie; 423 uint32_t port = cells[0]; 424 uint32_t pin = cells[1]; 425 uint32_t flags = cells[2]; 426 uint32_t reg; 427 int val; 428 429 if (port > SXIPIO_NPORT || pin >= 32) 430 return 0; 431 432 reg = SXIREAD4(sc, SXIPIO_DAT(port)); 433 reg &= (1 << pin); 434 val = (reg >> pin) & 1; 435 if (flags & GPIO_ACTIVE_LOW) 436 val = !val; 437 return val; 438 } 439 440 void 441 sxipio_set_pin(void *cookie, uint32_t *cells, int val) 442 { 443 struct sxipio_softc *sc = cookie; 444 uint32_t port = cells[0]; 445 uint32_t pin = cells[1]; 446 uint32_t flags = cells[2]; 447 uint32_t reg; 448 449 if (port > SXIPIO_NPORT || pin >= 32) 450 return; 451 452 reg = SXIREAD4(sc, SXIPIO_DAT(port)); 453 if (flags & GPIO_ACTIVE_LOW) 454 val = !val; 455 if (val) 456 reg |= (1 << pin); 457 else 458 reg &= ~(1 << pin); 459 SXIWRITE4(sc, SXIPIO_DAT(port), reg); 460 } 461 462 void 463 sxipio_a80_bias_cfg(struct sxipio_softc *sc, int port, uint32_t supply) 464 { 465 uint32_t voltage; 466 uint32_t bias; 467 468 voltage = regulator_get_voltage(supply); 469 if (voltage <= 1800000) 470 bias = SXIPIO_IO_BIAS_1_8V; 471 else if (voltage <= 2500000) 472 bias = SXIPIO_IO_BIAS_2_5V; 473 else if (voltage <= 2800000) 474 bias = SXIPIO_IO_BIAS_2_8V; 475 else if (voltage <= 3000000) 476 bias = SXIPIO_IO_BIAS_3_0V; 477 else 478 bias = SXIPIO_IO_BIAS_3_3V; 479 480 SXICMS4(sc, SXIPIO_GRP_CFG(port), SXIPIO_IO_BIAS_MASK, bias); 481 } 482 483 /* 484 * GPIO support code 485 */ 486 487 int sxipio_pin_read(void *, int); 488 void sxipio_pin_write(void *, int, int); 489 void sxipio_pin_ctl(void *, int, int); 490 491 static const struct gpio_chipset_tag sxipio_gpio_tag = { 492 .gp_pin_read = sxipio_pin_read, 493 .gp_pin_write = sxipio_pin_write, 494 .gp_pin_ctl = sxipio_pin_ctl 495 }; 496 497 int 498 sxipio_pin_read(void *cookie, int pin) 499 { 500 struct sxipio_gpio *gpio = cookie; 501 uint32_t cells[3]; 502 503 cells[0] = gpio->port; 504 cells[1] = pin; 505 cells[2] = 0; 506 507 return sxipio_get_pin(gpio->sc, cells) ? GPIO_PIN_HIGH : GPIO_PIN_LOW; 508 } 509 510 void 511 sxipio_pin_write(void *cookie, int pin, int val) 512 { 513 struct sxipio_gpio *gpio = cookie; 514 uint32_t cells[3]; 515 516 cells[0] = gpio->port; 517 cells[1] = pin; 518 cells[2] = 0; 519 520 sxipio_set_pin(gpio->sc, cells, val); 521 } 522 523 void 524 sxipio_pin_ctl(void *cookie, int pin, int flags) 525 { 526 struct sxipio_gpio *gpio = cookie; 527 uint32_t cells[3]; 528 529 cells[0] = gpio->port; 530 cells[1] = pin; 531 cells[2] = 0; 532 533 if (ISSET(flags, GPIO_PIN_OUTPUT)) 534 sxipio_config_pin(gpio->sc, cells, GPIO_CONFIG_OUTPUT); 535 else 536 sxipio_config_pin(gpio->sc, cells, 0); 537 } 538 539 void 540 sxipio_attach_gpio(struct device *parent) 541 { 542 struct sxipio_softc *sc = (struct sxipio_softc *)parent; 543 struct gpiobus_attach_args gba; 544 uint32_t reg; 545 int port, pin; 546 int off, mux; 547 int state, flags; 548 int i; 549 550 for (i = 0; i < sc->sc_npins; i++) { 551 /* Skip pins that have no gpio function. */ 552 if (strcmp(sc->sc_pins[i].funcs[0].name, "gpio_in") != 0 || 553 strcmp(sc->sc_pins[i].funcs[1].name, "gpio_out") != 0) 554 continue; 555 556 port = sc->sc_pins[i].port; 557 pin = sc->sc_pins[i].pin; 558 559 /* Get pin configuration. */ 560 reg = SXIREAD4(sc, SXIPIO_CFG(port, pin)); 561 off = (pin & 0x7) << 2; 562 mux = (reg >> off) & 0x7; 563 564 /* Skip pins that have been assigned other functions. */ 565 if (mux != SXIPIO_GPIO_IN && mux != SXIPIO_GPIO_OUT && 566 mux != SXIPIO_DISABLED) 567 continue; 568 569 switch (mux) { 570 case SXIPIO_GPIO_IN: 571 flags = GPIO_PIN_SET | GPIO_PIN_INPUT; 572 break; 573 case SXIPIO_GPIO_OUT: 574 flags = GPIO_PIN_SET | GPIO_PIN_OUTPUT; 575 break; 576 default: 577 flags = GPIO_PIN_SET; 578 } 579 580 /* Get pin state. */ 581 reg = SXIREAD4(sc, SXIPIO_DAT(port)); 582 state = (reg >> pin) & 1; 583 584 sc->sc_gpio_pins[port][pin].pin_caps = 585 GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; 586 sc->sc_gpio_pins[port][pin].pin_flags = flags; 587 sc->sc_gpio_pins[port][pin].pin_state = state; 588 sc->sc_gpio_pins[port][pin].pin_num = pin; 589 } 590 591 for (i = 0; i <= port; i++) { 592 memcpy(&sc->sc_gpio_tag[i], &sxipio_gpio_tag, sizeof(sxipio_gpio_tag)); 593 sc->sc_gpio_tag[i].gp_cookie = &sc->sc_gpio[i]; 594 sc->sc_gpio[i].sc = sc; 595 sc->sc_gpio[i].port = i; 596 597 gba.gba_name = "gpio"; 598 gba.gba_gc = &sc->sc_gpio_tag[i]; 599 gba.gba_pins = &sc->sc_gpio_pins[i][0]; 600 gba.gba_npins = 32; 601 602 #if NGPIO > 0 603 config_found(&sc->sc_dev, &gba, gpiobus_print); 604 #endif 605 } 606 } 607