1 /* $OpenBSD: rkpinctrl.c,v 1.5 2018/02/25 13:26:44 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2017, 2018 Mark Kettenis <kettenis@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/device.h> 21 #include <sys/malloc.h> 22 23 #include <machine/intr.h> 24 #include <machine/bus.h> 25 #include <machine/fdt.h> 26 27 #include <dev/ofw/openfirm.h> 28 #include <dev/ofw/ofw_misc.h> 29 #include <dev/ofw/ofw_pinctrl.h> 30 #include <dev/ofw/fdt.h> 31 32 #ifdef __armv7__ 33 #include <arm/simplebus/simplebusvar.h> 34 #else 35 #include <arm64/dev/simplebusvar.h> 36 #endif 37 38 /* RK3288 registers */ 39 #define RK3288_GRF_GPIO1A_IOMUX 0x0000 40 #define RK3288_PMUGRF_GPIO0A_IOMUX 0x0084 41 42 /* RK3328 registers */ 43 #define RK3328_GRF_GPIO0A_IOMUX 0x0000 44 45 /* RK3399 registers */ 46 #define RK3399_GRF_GPIO2A_IOMUX 0xe000 47 #define RK3399_PMUGRF_GPIO0A_IOMUX 0x0000 48 49 struct rkpinctrl_softc { 50 struct simplebus_softc sc_sbus; 51 52 struct regmap *sc_grf; 53 struct regmap *sc_pmu; 54 }; 55 56 int rkpinctrl_match(struct device *, void *, void *); 57 void rkpinctrl_attach(struct device *, struct device *, void *); 58 59 struct cfattach rkpinctrl_ca = { 60 sizeof (struct rkpinctrl_softc), rkpinctrl_match, rkpinctrl_attach 61 }; 62 63 struct cfdriver rkpinctrl_cd = { 64 NULL, "rkpinctrl", DV_DULL 65 }; 66 67 int rk3288_pinctrl(uint32_t, void *); 68 int rk3328_pinctrl(uint32_t, void *); 69 int rk3399_pinctrl(uint32_t, void *); 70 71 int 72 rkpinctrl_match(struct device *parent, void *match, void *aux) 73 { 74 struct fdt_attach_args *faa = aux; 75 76 return (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl") || 77 OF_is_compatible(faa->fa_node, "rockchip,rk3328-pinctrl") || 78 OF_is_compatible(faa->fa_node, "rockchip,rk3399-pinctrl")); 79 } 80 81 void 82 rkpinctrl_attach(struct device *parent, struct device *self, void *aux) 83 { 84 struct rkpinctrl_softc *sc = (struct rkpinctrl_softc *)self; 85 struct fdt_attach_args *faa = aux; 86 uint32_t grf, pmu; 87 88 grf = OF_getpropint(faa->fa_node, "rockchip,grf", 0); 89 pmu = OF_getpropint(faa->fa_node, "rockchip,pmu", 0); 90 sc->sc_grf = regmap_byphandle(grf); 91 sc->sc_pmu = regmap_byphandle(pmu); 92 93 if (sc->sc_grf == NULL && sc->sc_pmu == NULL) { 94 printf(": no registers\n"); 95 return; 96 } 97 98 if (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl")) 99 pinctrl_register(faa->fa_node, rk3288_pinctrl, sc); 100 else if (OF_is_compatible(faa->fa_node, "rockchip,rk3328-pinctrl")) 101 pinctrl_register(faa->fa_node, rk3328_pinctrl, sc); 102 else 103 pinctrl_register(faa->fa_node, rk3399_pinctrl, sc); 104 105 /* Attach GPIO banks. */ 106 simplebus_attach(parent, &sc->sc_sbus.sc_dev, faa); 107 } 108 109 /* 110 * Rockchip RK3288 111 */ 112 113 int 114 rk3288_pull(uint32_t bank, uint32_t idx, uint32_t phandle) 115 { 116 int node; 117 118 node = OF_getnodebyphandle(phandle); 119 if (node == 0) 120 return -1; 121 122 /* XXX */ 123 if (bank == 0) 124 return -1; 125 126 if (OF_getproplen(node, "bias-disable") == 0) 127 return 0; 128 if (OF_getproplen(node, "bias-pull-up") == 0) 129 return 1; 130 if (OF_getproplen(node, "bias-pull-down") == 0) 131 return 2; 132 133 return -1; 134 } 135 136 int 137 rk3288_strength(uint32_t bank, uint32_t idx, uint32_t phandle) 138 { 139 int strength, level; 140 int levels[4] = { 2, 4, 8, 12 }; 141 int node; 142 143 node = OF_getnodebyphandle(phandle); 144 if (node == 0) 145 return -1; 146 147 /* XXX */ 148 if (bank == 0) 149 return -1; 150 151 strength = OF_getpropint(node, "drive-strength", -1); 152 if (strength == -1) 153 return -1; 154 155 /* Convert drive strength to level. */ 156 for (level = 3; level >= 0; level--) { 157 if (strength >= levels[level]) 158 break; 159 } 160 return level; 161 } 162 163 int 164 rk3288_pinctrl(uint32_t phandle, void *cookie) 165 { 166 struct rkpinctrl_softc *sc = cookie; 167 uint32_t *pins; 168 int node, len, i; 169 170 KASSERT(sc->sc_grf); 171 KASSERT(sc->sc_pmu); 172 173 node = OF_getnodebyphandle(phandle); 174 if (node == 0) 175 return -1; 176 177 len = OF_getproplen(node, "rockchip,pins"); 178 if (len <= 0) 179 return -1; 180 181 pins = malloc(len, M_TEMP, M_WAITOK); 182 if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len) 183 goto fail; 184 185 for (i = 0; i < len / sizeof(uint32_t); i += 4) { 186 struct regmap *rm; 187 bus_size_t base, off; 188 uint32_t bank, idx, mux; 189 int pull, strength; 190 uint32_t mask, bits; 191 int s; 192 193 bank = pins[i]; 194 idx = pins[i + 1]; 195 mux = pins[i + 2]; 196 pull = rk3288_pull(bank, idx, pins[i + 3]); 197 strength = rk3288_strength(bank, idx, pins[i + 3]); 198 199 if (bank > 8 || idx > 32 || mux > 7) 200 continue; 201 202 /* Bank 0 lives in the PMU. */ 203 if (bank < 1) { 204 rm = sc->sc_pmu; 205 base = RK3288_PMUGRF_GPIO0A_IOMUX; 206 } else { 207 rm = sc->sc_grf; 208 base = RK3288_GRF_GPIO1A_IOMUX - 0x10; 209 } 210 211 s = splhigh(); 212 213 /* IOMUX control */ 214 off = bank * 0x10 + (idx / 8) * 0x04; 215 216 /* GPIO3D, GPIO4A and GPIO4B are special. */ 217 if ((bank == 3 && idx >= 24) || (bank == 4 && idx < 16)) { 218 mask = (0x7 << ((idx % 4) * 4)); 219 bits = (mux << ((idx % 4) * 4)); 220 } else { 221 mask = (0x3 << ((idx % 8) * 2)); 222 bits = (mux << ((idx % 8) * 2)); 223 } 224 if (bank > 3 || (bank == 3 && idx >= 28)) 225 off += 0x04; 226 if (bank > 4 || (bank == 4 && idx >= 4)) 227 off += 0x04; 228 if (bank > 4 || (bank == 4 && idx >= 12)) 229 off += 0x04; 230 regmap_write_4(rm, base + off, mask << 16 | bits); 231 232 /* GPIO pad pull down and pull up control */ 233 if (pull >= 0) { 234 off = 0x140 + bank * 0x10 + (idx / 8) * 0x04; 235 mask = (0x3 << ((idx % 8) * 2)); 236 bits = (pull << ((idx % 8) * 2)); 237 regmap_write_4(rm, base + off, mask << 16 | bits); 238 } 239 240 /* GPIO drive strength control */ 241 if (strength >= 0) { 242 off = 0x1c0 + bank * 0x10 + (idx / 8) * 0x04; 243 mask = (0x3 << ((idx % 8) * 2)); 244 bits = (strength << ((idx % 8) * 2)); 245 regmap_write_4(rm, base + off, mask << 16 | bits); 246 } 247 248 splx(s); 249 } 250 251 free(pins, M_TEMP, len); 252 return 0; 253 254 fail: 255 free(pins, M_TEMP, len); 256 return -1; 257 } 258 259 /* 260 * Rockchip RK3328 261 */ 262 263 int 264 rk3328_pull(uint32_t bank, uint32_t idx, uint32_t phandle) 265 { 266 int node; 267 268 node = OF_getnodebyphandle(phandle); 269 if (node == 0) 270 return -1; 271 272 if (OF_getproplen(node, "bias-disable") == 0) 273 return 0; 274 if (OF_getproplen(node, "bias-pull-up") == 0) 275 return 1; 276 if (OF_getproplen(node, "bias-pull-down") == 0) 277 return 2; 278 279 return -1; 280 } 281 282 int 283 rk3328_strength(uint32_t bank, uint32_t idx, uint32_t phandle) 284 { 285 int strength, level; 286 int levels[4] = { 2, 4, 8, 12 }; 287 int node; 288 289 node = OF_getnodebyphandle(phandle); 290 if (node == 0) 291 return -1; 292 293 strength = OF_getpropint(node, "drive-strength", -1); 294 if (strength == -1) 295 return -1; 296 297 /* Convert drive strength to level. */ 298 for (level = 3; level >= 0; level--) { 299 if (strength >= levels[level]) 300 break; 301 } 302 return level; 303 } 304 305 int 306 rk3328_pinctrl(uint32_t phandle, void *cookie) 307 { 308 struct rkpinctrl_softc *sc = cookie; 309 uint32_t *pins; 310 int node, len, i; 311 312 KASSERT(sc->sc_grf); 313 314 node = OF_getnodebyphandle(phandle); 315 if (node == 0) 316 return -1; 317 318 len = OF_getproplen(node, "rockchip,pins"); 319 if (len <= 0) 320 return -1; 321 322 pins = malloc(len, M_TEMP, M_WAITOK); 323 if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len) 324 goto fail; 325 326 for (i = 0; i < len / sizeof(uint32_t); i += 4) { 327 struct regmap *rm = sc->sc_grf; 328 bus_size_t base, off; 329 uint32_t bank, idx, mux; 330 int pull, strength; 331 uint32_t mask, bits; 332 int s; 333 334 bank = pins[i]; 335 idx = pins[i + 1]; 336 mux = pins[i + 2]; 337 pull = rk3288_pull(bank, idx, pins[i + 3]); 338 strength = rk3288_strength(bank, idx, pins[i + 3]); 339 340 if (bank > 3 || idx > 32 || mux > 3) 341 continue; 342 343 base = RK3328_GRF_GPIO0A_IOMUX; 344 345 s = splhigh(); 346 347 /* IOMUX control */ 348 off = bank * 0x10 + (idx / 8) * 0x04; 349 350 /* GPIO2B, GPIO2C, GPIO3A and GPIO3B are special. */ 351 if (bank == 2 && idx == 15) { 352 mask = 0x7; 353 bits = mux; 354 } else if (bank == 2 && idx >= 16 && idx <= 20) { 355 mask = (0x7 << ((idx - 16) * 3)); 356 bits = (mux << ((idx - 16) * 3)); 357 } else if (bank == 2 && idx >= 21 && idx <= 23) { 358 mask = (0x7 << ((idx - 21) * 3)); 359 bits = (mux << ((idx - 21) * 3)); 360 } else if (bank == 3 && idx <= 4) { 361 mask = (0x7 << (idx * 3)); 362 bits = (mux << (idx * 3)); 363 } else if (bank == 3 && idx >= 5 && idx <= 7) { 364 mask = (0x7 << ((idx - 5) * 3)); 365 bits = (mux << ((idx - 5) * 3)); 366 } else if (bank == 3 && idx >= 8 && idx <= 12) { 367 mask = (0x7 << ((idx - 8) * 3)); 368 bits = (mux << ((idx - 8) * 3)); 369 } else if (bank == 3 && idx >= 13 && idx <= 15) { 370 mask = (0x7 << ((idx - 13) * 3)); 371 bits = (mux << ((idx - 13) * 3)); 372 } else { 373 mask = (0x3 << ((idx % 8) * 2)); 374 bits = (mux << ((idx % 8) * 2)); 375 } 376 if (bank > 2 || (bank == 2 && idx >= 15)) 377 off += 0x04; 378 if (bank > 2 || (bank == 2 && idx >= 21)) 379 off += 0x04; 380 if (bank > 3 || (bank == 3 && idx >= 5)) 381 off += 0x04; 382 if (bank > 3 || (bank == 3 && idx >= 13)) 383 off += 0x04; 384 regmap_write_4(rm, base + off, mask << 16 | bits); 385 386 /* GPIO pad pull down and pull up control */ 387 if (pull >= 0) { 388 off = 0x100 + bank * 0x10 + (idx / 8) * 0x04; 389 mask = (0x3 << ((idx % 8) * 2)); 390 bits = (pull << ((idx % 8) * 2)); 391 regmap_write_4(rm, base + off, mask << 16 | bits); 392 } 393 394 /* GPIO drive strength control */ 395 if (strength >= 0) { 396 off = 0x200 + bank * 0x10 + (idx / 8) * 0x04; 397 mask = (0x3 << ((idx % 8) * 2)); 398 bits = (strength << ((idx % 8) * 2)); 399 regmap_write_4(rm, base + off, mask << 16 | bits); 400 } 401 402 splx(s); 403 } 404 405 free(pins, M_TEMP, len); 406 return 0; 407 408 fail: 409 free(pins, M_TEMP, len); 410 return -1; 411 } 412 413 /* 414 * Rockchip RK3399 415 */ 416 417 int 418 rk3399_pull(uint32_t bank, uint32_t idx, uint32_t phandle) 419 { 420 int pull_up, pull_down; 421 int node; 422 423 node = OF_getnodebyphandle(phandle); 424 if (node == 0) 425 return -1; 426 427 if (bank == 2 && idx >= 16) { 428 pull_up = 3; 429 pull_down = 1; 430 } else { 431 pull_up = 1; 432 pull_down = 2; 433 } 434 435 if (OF_getproplen(node, "bias-disable") == 0) 436 return 0; 437 if (OF_getproplen(node, "bias-pull-up") == 0) 438 return pull_up; 439 if (OF_getproplen(node, "bias-pull-down") == 0) 440 return pull_down; 441 442 return -1; 443 } 444 445 /* Magic because the drive strength configurations vary wildly. */ 446 447 int rk3399_strength_levels[][8] = { 448 { 2, 4, 8, 12 }, /* default */ 449 { 3, 6, 9, 12 }, /* 1.8V or 3.0V */ 450 { 5, 10, 15, 20 }, /* 1.8V only */ 451 { 4, 6, 8, 10, 12, 14, 16, 18 }, /* 1.8V or 3.0V auto */ 452 { 4, 7, 10, 13, 16, 19, 22, 26 }, /* 3.3V */ 453 }; 454 455 int rk3399_strength_types[][4] = { 456 { 2, 2, 0, 0 }, 457 { 1, 1, 1, 1 }, 458 { 1, 1, 2, 2 }, 459 { 4, 4, 4, 1 }, 460 { 1, 3, 1, 1 }, 461 }; 462 463 int rk3399_strength_regs[][4] = { 464 { 0x0080, 0x0088, 0x0090, 0x0098 }, 465 { 0x00a0, 0x00a8, 0x00b0, 0x00b8 }, 466 { 0x0100, 0x0104, 0x0108, 0x010c }, 467 { 0x0110, 0x0118, 0x0120, 0x0128 }, 468 { 0x012c, 0x0130, 0x0138, 0x013c }, 469 }; 470 471 int 472 rk3399_strength(uint32_t bank, uint32_t idx, uint32_t phandle) 473 { 474 int strength, type, level; 475 int *levels; 476 int node; 477 478 node = OF_getnodebyphandle(phandle); 479 if (node == 0) 480 return -1; 481 482 strength = OF_getpropint(node, "drive-strength", -1); 483 if (strength == -1) 484 return -1; 485 486 /* Convert drive strength to level. */ 487 type = rk3399_strength_types[bank][idx / 8]; 488 levels = rk3399_strength_levels[type]; 489 for (level = 7; level >= 0; level--) { 490 if (strength >= levels[level] && levels[level] > 0) 491 break; 492 } 493 return level; 494 } 495 496 int 497 rk3399_pinctrl(uint32_t phandle, void *cookie) 498 { 499 struct rkpinctrl_softc *sc = cookie; 500 uint32_t *pins; 501 int node, len, i; 502 503 KASSERT(sc->sc_grf); 504 KASSERT(sc->sc_pmu); 505 506 node = OF_getnodebyphandle(phandle); 507 if (node == 0) 508 return -1; 509 510 len = OF_getproplen(node, "rockchip,pins"); 511 if (len <= 0) 512 return -1; 513 514 pins = malloc(len, M_TEMP, M_WAITOK); 515 if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len) 516 goto fail; 517 518 for (i = 0; i < len / sizeof(uint32_t); i += 4) { 519 struct regmap *rm; 520 bus_size_t base, off; 521 uint32_t bank, idx, mux; 522 int pull, strength, type, shift; 523 uint32_t mask, bits; 524 int s; 525 526 bank = pins[i]; 527 idx = pins[i + 1]; 528 mux = pins[i + 2]; 529 pull = rk3399_pull(bank, idx, pins[i + 3]); 530 strength = rk3399_strength(bank, idx, pins[i + 3]); 531 532 if (bank > 5 || idx > 32 || mux > 3) 533 continue; 534 535 /* Bank 0 and 1 live in the PMU. */ 536 if (bank < 2) { 537 rm = sc->sc_pmu; 538 base = RK3399_PMUGRF_GPIO0A_IOMUX; 539 } else { 540 rm = sc->sc_grf; 541 base = RK3399_GRF_GPIO2A_IOMUX - 0x20; 542 } 543 544 s = splhigh(); 545 546 /* IOMUX control */ 547 off = bank * 0x10 + (idx / 8) * 0x04; 548 mask = (0x3 << ((idx % 8) * 2)); 549 bits = (mux << ((idx % 8) * 2)); 550 regmap_write_4(rm, base + off, mask << 16 | bits); 551 552 /* GPIO pad pull down and pull up control */ 553 if (pull >= 0) { 554 off = 0x40 + bank * 0x10 + (idx / 8) * 0x04; 555 mask = (0x3 << ((idx % 8) * 2)); 556 bits = (pull << ((idx % 8) * 2)); 557 regmap_write_4(rm, base + off, mask << 16 | bits); 558 } 559 560 /* GPIO drive strength control */ 561 if (strength >= 0) { 562 off = rk3399_strength_regs[bank][idx / 8]; 563 type = rk3399_strength_types[bank][idx / 8]; 564 shift = (type > 2) ? 3 : 2; 565 mask = (((1 << shift) - 1) << ((idx % 8) * shift)); 566 bits = (strength << ((idx % 8) * shift)); 567 if (mask & 0x0000ffff) { 568 regmap_write_4(rm, base + off, 569 mask << 16 | (bits & 0x0000ffff)); 570 } 571 if (mask & 0xffff0000) { 572 regmap_write_4(rm, base + off + 0x04, 573 (mask & 0xffff0000) | bits >> 16); 574 } 575 } 576 577 splx(s); 578 } 579 580 free(pins, M_TEMP, len); 581 return 0; 582 583 fail: 584 free(pins, M_TEMP, len); 585 return -1; 586 } 587