1 /* $OpenBSD: sxipio.c,v 1.11 2019/09/05 12:00:09 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/fdt.h> 36 37 #include <dev/fdt/sunxireg.h> 38 #include <dev/fdt/sxipiovar.h> 39 40 #include "gpio.h" 41 42 #define SXIPIO_NPORT 9 43 44 struct sxipio_softc; 45 46 struct sxipio_gpio { 47 struct sxipio_softc *sc; 48 int port; 49 }; 50 51 struct intrhand { 52 int (*ih_func)(void *); /* handler */ 53 void *ih_arg; /* arg for handler */ 54 int ih_ipl; /* IPL_* */ 55 int ih_irq; /* IRQ number */ 56 int ih_gpio; /* gpio pin */ 57 struct evcount ih_count; 58 char *ih_name; 59 }; 60 61 struct sxipio_softc { 62 struct device sc_dev; 63 bus_space_tag_t sc_iot; 64 bus_space_handle_t sc_ioh; 65 void *sc_ih_h; 66 void *sc_ih_l; 67 int sc_max_il; 68 int sc_min_il; 69 70 struct sxipio_pin *sc_pins; 71 int sc_npins; 72 struct gpio_controller sc_gc; 73 74 struct sxipio_gpio sc_gpio[SXIPIO_NPORT]; 75 struct gpio_chipset_tag sc_gpio_tag[SXIPIO_NPORT]; 76 gpio_pin_t sc_gpio_pins[SXIPIO_NPORT][32]; 77 78 struct intrhand *sc_handlers[32]; 79 }; 80 81 #define SXIPIO_CFG(port, pin) 0x00 + ((port) * 0x24) + (((pin) >> 3) * 0x04) 82 #define SXIPIO_DAT(port) 0x10 + ((port) * 0x24) 83 #define SXIPIO_DRV(port, pin) 0x14 + ((port) * 0x24) + (((pin) >> 4) * 0x04) 84 #define SXIPIO_PUL(port, pin) 0x1c + ((port) * 0x24) + (((pin) >> 4) * 0x04) 85 #define SXIPIO_INT_CFG0(port) 0x0200 + ((port) * 0x04) 86 #define SXIPIO_INT_CTL 0x0210 87 #define SXIPIO_INT_STA 0x0214 88 #define SXIPIO_INT_DEB 0x0218 /* debounce register */ 89 90 #define SXIPIO_GPIO_IN 0 91 #define SXIPIO_GPIO_OUT 1 92 #define SXIPIO_DISABLED 7 93 94 int sxipio_match(struct device *, void *, void *); 95 void sxipio_attach(struct device *, struct device *, void *); 96 97 struct cfattach sxipio_ca = { 98 sizeof (struct sxipio_softc), sxipio_match, sxipio_attach 99 }; 100 101 struct cfdriver sxipio_cd = { 102 NULL, "sxipio", DV_DULL 103 }; 104 105 void sxipio_attach_gpio(struct device *); 106 int sxipio_pinctrl(uint32_t, void *); 107 void sxipio_config_pin(void *, uint32_t *, int); 108 int sxipio_get_pin(void *, uint32_t *); 109 void sxipio_set_pin(void *, uint32_t *, int); 110 111 #include "sxipio_pins.h" 112 113 struct sxipio_pins { 114 const char *compat; 115 struct sxipio_pin *pins; 116 int npins; 117 }; 118 119 struct sxipio_pins sxipio_pins[] = { 120 { 121 "allwinner,sun4i-a10-pinctrl", 122 sun4i_a10_pins, nitems(sun4i_a10_pins) 123 }, 124 { 125 "allwinner,sun5i-a10s-pinctrl", 126 sun5i_a10s_pins, nitems(sun5i_a10s_pins) 127 }, 128 { 129 "allwinner,sun5i-a13-pinctrl", 130 sun5i_a13_pins, nitems(sun5i_a13_pins) 131 }, 132 { 133 "allwinner,sun5i-gr8-pinctrl", 134 sun5i_gr8_pins, nitems(sun5i_gr8_pins) 135 }, 136 { 137 "allwinner,sun7i-a20-pinctrl", 138 sun7i_a20_pins, nitems(sun7i_a20_pins) 139 }, 140 { 141 "allwinner,sun8i-r40-pinctrl", 142 sun8i_r40_pins, nitems(sun8i_r40_pins) 143 }, 144 { 145 "allwinner,sun8i-a33-pinctrl", 146 sun8i_a33_pins, nitems(sun8i_a33_pins) 147 }, 148 { 149 "allwinner,sun8i-h3-pinctrl", 150 sun8i_h3_pins, nitems(sun8i_h3_pins) 151 }, 152 { 153 "allwinner,sun8i-h3-r-pinctrl", 154 sun8i_h3_r_pins, nitems(sun8i_h3_r_pins) 155 }, 156 { 157 "allwinner,sun8i-v3s-pinctrl", 158 sun8i_v3s_pins, nitems(sun8i_v3s_pins) 159 }, 160 { 161 "allwinner,sun9i-a80-pinctrl", 162 sun9i_a80_pins, nitems(sun9i_a80_pins) 163 }, 164 { 165 "allwinner,sun9i-a80-r-pinctrl", 166 sun9i_a80_r_pins, nitems(sun9i_a80_r_pins) 167 }, 168 { 169 "allwinner,sun50i-a64-pinctrl", 170 sun50i_a64_pins, nitems(sun50i_a64_pins) 171 }, 172 { 173 "allwinner,sun50i-a64-r-pinctrl", 174 sun50i_a64_r_pins, nitems(sun50i_a64_r_pins) 175 }, 176 { 177 "allwinner,sun50i-h5-pinctrl", 178 sun50i_h5_pins, nitems(sun50i_h5_pins) 179 }, 180 { 181 "allwinner,sun50i-h6-pinctrl", 182 sun50i_h6_pins, nitems(sun50i_h6_pins) 183 }, 184 { 185 "allwinner,sun50i-h6-r-pinctrl", 186 sun50i_h6_r_pins, nitems(sun50i_h6_r_pins) 187 }, 188 }; 189 190 int 191 sxipio_match(struct device *parent, void *match, void *aux) 192 { 193 struct fdt_attach_args *faa = aux; 194 int i; 195 196 for (i = 0; i < nitems(sxipio_pins); i++) { 197 if (OF_is_compatible(faa->fa_node, sxipio_pins[i].compat)) 198 return 1; 199 } 200 201 return 0; 202 } 203 204 void 205 sxipio_attach(struct device *parent, struct device *self, void *aux) 206 { 207 struct sxipio_softc *sc = (struct sxipio_softc *)self; 208 struct fdt_attach_args *faa = aux; 209 int i; 210 211 sc->sc_iot = faa->fa_iot; 212 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 213 faa->fa_reg[0].size, 0, &sc->sc_ioh)) 214 panic("%s: bus_space_map failed!", __func__); 215 216 clock_enable_all(faa->fa_node); 217 reset_deassert_all(faa->fa_node); 218 219 for (i = 0; i < nitems(sxipio_pins); i++) { 220 if (OF_is_compatible(faa->fa_node, sxipio_pins[i].compat)) { 221 sc->sc_pins = sxipio_pins[i].pins; 222 sc->sc_npins = sxipio_pins[i].npins; 223 break; 224 } 225 } 226 227 KASSERT(sc->sc_pins); 228 pinctrl_register(faa->fa_node, sxipio_pinctrl, sc); 229 230 sc->sc_gc.gc_node = faa->fa_node; 231 sc->sc_gc.gc_cookie = sc; 232 sc->sc_gc.gc_config_pin = sxipio_config_pin; 233 sc->sc_gc.gc_get_pin = sxipio_get_pin; 234 sc->sc_gc.gc_set_pin = sxipio_set_pin; 235 gpio_controller_register(&sc->sc_gc); 236 237 config_defer(self, sxipio_attach_gpio); 238 239 printf(": %d pins\n", sc->sc_npins); 240 } 241 242 int 243 sxipio_drive(int node) 244 { 245 int drive; 246 247 drive = OF_getpropint(node, "allwinner,drive", -1); 248 if (drive >= 0) 249 return drive; 250 drive = OF_getpropint(node, "drive-strength", 0) - 10; 251 if (drive >= 0) 252 return (drive / 10); 253 return -1; 254 } 255 256 int 257 sxipio_pull(int node) 258 { 259 int pull; 260 261 pull = OF_getpropint(node, "allwinner,pull", -1); 262 if (pull >= 0) 263 return pull; 264 if (OF_getproplen(node, "bias-disable") == 0) 265 return 0; 266 if (OF_getproplen(node, "bias-pull-up") == 0) 267 return 1; 268 if (OF_getproplen(node, "bias-pull-down") == 0) 269 return 2; 270 return -1; 271 } 272 273 int 274 sxipio_pinctrl(uint32_t phandle, void *cookie) 275 { 276 struct sxipio_softc *sc = cookie; 277 char func[32]; 278 char *names, *name; 279 int port, pin, off, mask; 280 int mux, drive, pull; 281 int node; 282 int len; 283 int i, j; 284 int s; 285 286 node = OF_getnodebyphandle(phandle); 287 if (node == 0) 288 return -1; 289 290 len = OF_getprop(node, "allwinner,function", func, sizeof(func)); 291 if (len <= 0 || len >= sizeof(func)) { 292 len = OF_getprop(node, "function", func, sizeof(func)); 293 if (len <= 0 || len >= sizeof(func)) 294 return -1; 295 } 296 297 len = OF_getproplen(node, "allwinner,pins"); 298 if (len <= 0) { 299 len = OF_getproplen(node, "pins"); 300 if (len <= 0) 301 return -1; 302 } 303 304 names = malloc(len, M_TEMP, M_WAITOK); 305 if (OF_getprop(node, "allwinner,pins", names, len) <= 0) 306 OF_getprop(node, "pins", names, len); 307 308 drive = sxipio_drive(node); 309 pull = sxipio_pull(node); 310 311 name = names; 312 while (len > 0) { 313 /* Lookup the pin. */ 314 for (i = 0; i < sc->sc_npins; i++) { 315 if (strcmp(name, sc->sc_pins[i].name) == 0) 316 break; 317 } 318 if (i >= sc->sc_npins) 319 goto err; 320 321 /* Lookup the function of the pin. */ 322 for (j = 0; j < nitems(sc->sc_pins[i].funcs); j++) { 323 if (sc->sc_pins[i].funcs[j].name == NULL) 324 continue; 325 if (strcmp(func, sc->sc_pins[i].funcs[j].name) == 0) 326 break; 327 } 328 if (j > nitems(sc->sc_pins[i].funcs)) 329 goto err; 330 331 port = sc->sc_pins[i].port; 332 pin = sc->sc_pins[i].pin; 333 mux = sc->sc_pins[i].funcs[j].mux; 334 335 s = splhigh(); 336 off = (pin & 0x7) << 2, mask = (0x7 << off); 337 SXICMS4(sc, SXIPIO_CFG(port, pin), mask, mux << off); 338 off = (pin & 0xf) << 1, mask = (0x3 << off); 339 if (drive >= 0 && drive < 4) 340 SXICMS4(sc, SXIPIO_DRV(port, pin), mask, drive << off); 341 if (pull >= 0 && pull < 3) 342 SXICMS4(sc, SXIPIO_PUL(port, pin), mask, pull << off); 343 splx(s); 344 345 len -= strlen(name) + 1; 346 name += strlen(name) + 1; 347 } 348 349 free(names, M_TEMP, len); 350 return 0; 351 352 err: 353 free(names, M_TEMP, len); 354 return -1; 355 } 356 357 void 358 sxipio_config_pin(void *cookie, uint32_t *cells, int config) 359 { 360 struct sxipio_softc *sc = cookie; 361 uint32_t port = cells[0]; 362 uint32_t pin = cells[1]; 363 int mux, off; 364 365 if (port > SXIPIO_NPORT || pin > 32) 366 return; 367 368 mux = (config & GPIO_CONFIG_OUTPUT) ? 1 : 0; 369 off = (pin & 0x7) << 2; 370 SXICMS4(sc, SXIPIO_CFG(port, pin), 0x7 << off, mux << off); 371 } 372 373 int 374 sxipio_get_pin(void *cookie, uint32_t *cells) 375 { 376 struct sxipio_softc *sc = cookie; 377 uint32_t port = cells[0]; 378 uint32_t pin = cells[1]; 379 uint32_t flags = cells[2]; 380 uint32_t reg; 381 int val; 382 383 if (port > SXIPIO_NPORT || pin > 32) 384 return 0; 385 386 reg = SXIREAD4(sc, SXIPIO_DAT(port)); 387 reg &= (1 << pin); 388 val = (reg >> pin) & 1; 389 if (flags & GPIO_ACTIVE_LOW) 390 val = !val; 391 return val; 392 } 393 394 void 395 sxipio_set_pin(void *cookie, uint32_t *cells, int val) 396 { 397 struct sxipio_softc *sc = cookie; 398 uint32_t port = cells[0]; 399 uint32_t pin = cells[1]; 400 uint32_t flags = cells[2]; 401 uint32_t reg; 402 403 if (port > SXIPIO_NPORT || pin > 32) 404 return; 405 406 reg = SXIREAD4(sc, SXIPIO_DAT(port)); 407 if (flags & GPIO_ACTIVE_LOW) 408 val = !val; 409 if (val) 410 reg |= (1 << pin); 411 else 412 reg &= ~(1 << pin); 413 SXIWRITE4(sc, SXIPIO_DAT(port), reg); 414 } 415 416 /* 417 * GPIO support code 418 */ 419 420 int sxipio_pin_read(void *, int); 421 void sxipio_pin_write(void *, int, int); 422 void sxipio_pin_ctl(void *, int, int); 423 424 static const struct gpio_chipset_tag sxipio_gpio_tag = { 425 .gp_pin_read = sxipio_pin_read, 426 .gp_pin_write = sxipio_pin_write, 427 .gp_pin_ctl = sxipio_pin_ctl 428 }; 429 430 int 431 sxipio_pin_read(void *cookie, int pin) 432 { 433 struct sxipio_gpio *gpio = cookie; 434 uint32_t cells[3]; 435 436 cells[0] = gpio->port; 437 cells[1] = pin; 438 cells[2] = 0; 439 440 return sxipio_get_pin(gpio->sc, cells) ? GPIO_PIN_HIGH : GPIO_PIN_LOW; 441 } 442 443 void 444 sxipio_pin_write(void *cookie, int pin, int val) 445 { 446 struct sxipio_gpio *gpio = cookie; 447 uint32_t cells[3]; 448 449 cells[0] = gpio->port; 450 cells[1] = pin; 451 cells[2] = 0; 452 453 sxipio_set_pin(gpio->sc, cells, val); 454 } 455 456 void 457 sxipio_pin_ctl(void *cookie, int pin, int flags) 458 { 459 struct sxipio_gpio *gpio = cookie; 460 uint32_t cells[3]; 461 462 cells[0] = gpio->port; 463 cells[1] = pin; 464 cells[2] = 0; 465 466 if (ISSET(flags, GPIO_PIN_OUTPUT)) 467 sxipio_config_pin(gpio->sc, cells, GPIO_CONFIG_OUTPUT); 468 else 469 sxipio_config_pin(gpio->sc, cells, 0); 470 } 471 472 void 473 sxipio_attach_gpio(struct device *parent) 474 { 475 struct sxipio_softc *sc = (struct sxipio_softc *)parent; 476 struct gpiobus_attach_args gba; 477 uint32_t reg; 478 int port, pin; 479 int off, mux; 480 int state, flags; 481 int i; 482 483 for (i = 0; i < sc->sc_npins; i++) { 484 /* Skip pins that have no gpio function. */ 485 if (strcmp(sc->sc_pins[i].funcs[0].name, "gpio_in") != 0 || 486 strcmp(sc->sc_pins[i].funcs[1].name, "gpio_out") != 0) 487 continue; 488 489 port = sc->sc_pins[i].port; 490 pin = sc->sc_pins[i].pin; 491 492 /* Get pin configuration. */ 493 reg = SXIREAD4(sc, SXIPIO_CFG(port, pin)); 494 off = (pin & 0x7) << 2; 495 mux = (reg >> off) & 0x7; 496 497 /* Skip pins that have been assigned other functions. */ 498 if (mux != SXIPIO_GPIO_IN && mux != SXIPIO_GPIO_OUT && 499 mux != SXIPIO_DISABLED) 500 continue; 501 502 switch (mux) { 503 case SXIPIO_GPIO_IN: 504 flags = GPIO_PIN_SET | GPIO_PIN_INPUT; 505 break; 506 case SXIPIO_GPIO_OUT: 507 flags = GPIO_PIN_SET | GPIO_PIN_OUTPUT; 508 break; 509 default: 510 flags = GPIO_PIN_SET; 511 } 512 513 /* Get pin state. */ 514 reg = SXIREAD4(sc, SXIPIO_DAT(port)); 515 state = (reg >> pin) & 1; 516 517 sc->sc_gpio_pins[port][pin].pin_caps = 518 GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; 519 sc->sc_gpio_pins[port][pin].pin_flags = flags; 520 sc->sc_gpio_pins[port][pin].pin_state = state; 521 sc->sc_gpio_pins[port][pin].pin_num = pin; 522 } 523 524 for (i = 0; i <= port; i++) { 525 memcpy(&sc->sc_gpio_tag[i], &sxipio_gpio_tag, sizeof(sxipio_gpio_tag)); 526 sc->sc_gpio_tag[i].gp_cookie = &sc->sc_gpio[i]; 527 sc->sc_gpio[i].sc = sc; 528 sc->sc_gpio[i].port = i; 529 530 gba.gba_name = "gpio"; 531 gba.gba_gc = &sc->sc_gpio_tag[i]; 532 gba.gba_pins = &sc->sc_gpio_pins[i][0]; 533 gba.gba_npins = 32; 534 535 #if NGPIO > 0 536 config_found(&sc->sc_dev, &gba, gpiobus_print); 537 #endif 538 } 539 } 540