1 /* $OpenBSD: rkpinctrl.c,v 1.6 2020/09/04 01:11:16 jmatthew 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 /* RK3308 registers */ 43 #define RK3308_GRF_GPIO0A_IOMUX 0x0000 44 45 /* RK3328 registers */ 46 #define RK3328_GRF_GPIO0A_IOMUX 0x0000 47 48 /* RK3399 registers */ 49 #define RK3399_GRF_GPIO2A_IOMUX 0xe000 50 #define RK3399_PMUGRF_GPIO0A_IOMUX 0x0000 51 52 struct rkpinctrl_softc { 53 struct simplebus_softc sc_sbus; 54 55 struct regmap *sc_grf; 56 struct regmap *sc_pmu; 57 }; 58 59 int rkpinctrl_match(struct device *, void *, void *); 60 void rkpinctrl_attach(struct device *, struct device *, void *); 61 62 struct cfattach rkpinctrl_ca = { 63 sizeof (struct rkpinctrl_softc), rkpinctrl_match, rkpinctrl_attach 64 }; 65 66 struct cfdriver rkpinctrl_cd = { 67 NULL, "rkpinctrl", DV_DULL 68 }; 69 70 int rk3288_pinctrl(uint32_t, void *); 71 int rk3308_pinctrl(uint32_t, void *); 72 int rk3328_pinctrl(uint32_t, void *); 73 int rk3399_pinctrl(uint32_t, void *); 74 75 int 76 rkpinctrl_match(struct device *parent, void *match, void *aux) 77 { 78 struct fdt_attach_args *faa = aux; 79 80 return (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl") || 81 OF_is_compatible(faa->fa_node, "rockchip,rk3308-pinctrl") || 82 OF_is_compatible(faa->fa_node, "rockchip,rk3328-pinctrl") || 83 OF_is_compatible(faa->fa_node, "rockchip,rk3399-pinctrl")); 84 } 85 86 void 87 rkpinctrl_attach(struct device *parent, struct device *self, void *aux) 88 { 89 struct rkpinctrl_softc *sc = (struct rkpinctrl_softc *)self; 90 struct fdt_attach_args *faa = aux; 91 uint32_t grf, pmu; 92 93 grf = OF_getpropint(faa->fa_node, "rockchip,grf", 0); 94 pmu = OF_getpropint(faa->fa_node, "rockchip,pmu", 0); 95 sc->sc_grf = regmap_byphandle(grf); 96 sc->sc_pmu = regmap_byphandle(pmu); 97 98 if (sc->sc_grf == NULL && sc->sc_pmu == NULL) { 99 printf(": no registers\n"); 100 return; 101 } 102 103 if (OF_is_compatible(faa->fa_node, "rockchip,rk3288-pinctrl")) 104 pinctrl_register(faa->fa_node, rk3288_pinctrl, sc); 105 else if (OF_is_compatible(faa->fa_node, "rockchip,rk3308-pinctrl")) 106 pinctrl_register(faa->fa_node, rk3308_pinctrl, sc); 107 else if (OF_is_compatible(faa->fa_node, "rockchip,rk3328-pinctrl")) 108 pinctrl_register(faa->fa_node, rk3328_pinctrl, sc); 109 else 110 pinctrl_register(faa->fa_node, rk3399_pinctrl, sc); 111 112 /* Attach GPIO banks. */ 113 simplebus_attach(parent, &sc->sc_sbus.sc_dev, faa); 114 } 115 116 /* 117 * Rockchip RK3288 118 */ 119 120 int 121 rk3288_pull(uint32_t bank, uint32_t idx, uint32_t phandle) 122 { 123 int node; 124 125 node = OF_getnodebyphandle(phandle); 126 if (node == 0) 127 return -1; 128 129 /* XXX */ 130 if (bank == 0) 131 return -1; 132 133 if (OF_getproplen(node, "bias-disable") == 0) 134 return 0; 135 if (OF_getproplen(node, "bias-pull-up") == 0) 136 return 1; 137 if (OF_getproplen(node, "bias-pull-down") == 0) 138 return 2; 139 140 return -1; 141 } 142 143 int 144 rk3288_strength(uint32_t bank, uint32_t idx, uint32_t phandle) 145 { 146 int strength, level; 147 int levels[4] = { 2, 4, 8, 12 }; 148 int node; 149 150 node = OF_getnodebyphandle(phandle); 151 if (node == 0) 152 return -1; 153 154 /* XXX */ 155 if (bank == 0) 156 return -1; 157 158 strength = OF_getpropint(node, "drive-strength", -1); 159 if (strength == -1) 160 return -1; 161 162 /* Convert drive strength to level. */ 163 for (level = 3; level >= 0; level--) { 164 if (strength >= levels[level]) 165 break; 166 } 167 return level; 168 } 169 170 int 171 rk3288_pinctrl(uint32_t phandle, void *cookie) 172 { 173 struct rkpinctrl_softc *sc = cookie; 174 uint32_t *pins; 175 int node, len, i; 176 177 KASSERT(sc->sc_grf); 178 KASSERT(sc->sc_pmu); 179 180 node = OF_getnodebyphandle(phandle); 181 if (node == 0) 182 return -1; 183 184 len = OF_getproplen(node, "rockchip,pins"); 185 if (len <= 0) 186 return -1; 187 188 pins = malloc(len, M_TEMP, M_WAITOK); 189 if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len) 190 goto fail; 191 192 for (i = 0; i < len / sizeof(uint32_t); i += 4) { 193 struct regmap *rm; 194 bus_size_t base, off; 195 uint32_t bank, idx, mux; 196 int pull, strength; 197 uint32_t mask, bits; 198 int s; 199 200 bank = pins[i]; 201 idx = pins[i + 1]; 202 mux = pins[i + 2]; 203 pull = rk3288_pull(bank, idx, pins[i + 3]); 204 strength = rk3288_strength(bank, idx, pins[i + 3]); 205 206 if (bank > 8 || idx > 32 || mux > 7) 207 continue; 208 209 /* Bank 0 lives in the PMU. */ 210 if (bank < 1) { 211 rm = sc->sc_pmu; 212 base = RK3288_PMUGRF_GPIO0A_IOMUX; 213 } else { 214 rm = sc->sc_grf; 215 base = RK3288_GRF_GPIO1A_IOMUX - 0x10; 216 } 217 218 s = splhigh(); 219 220 /* IOMUX control */ 221 off = bank * 0x10 + (idx / 8) * 0x04; 222 223 /* GPIO3D, GPIO4A and GPIO4B are special. */ 224 if ((bank == 3 && idx >= 24) || (bank == 4 && idx < 16)) { 225 mask = (0x7 << ((idx % 4) * 4)); 226 bits = (mux << ((idx % 4) * 4)); 227 } else { 228 mask = (0x3 << ((idx % 8) * 2)); 229 bits = (mux << ((idx % 8) * 2)); 230 } 231 if (bank > 3 || (bank == 3 && idx >= 28)) 232 off += 0x04; 233 if (bank > 4 || (bank == 4 && idx >= 4)) 234 off += 0x04; 235 if (bank > 4 || (bank == 4 && idx >= 12)) 236 off += 0x04; 237 regmap_write_4(rm, base + off, mask << 16 | bits); 238 239 /* GPIO pad pull down and pull up control */ 240 if (pull >= 0) { 241 off = 0x140 + bank * 0x10 + (idx / 8) * 0x04; 242 mask = (0x3 << ((idx % 8) * 2)); 243 bits = (pull << ((idx % 8) * 2)); 244 regmap_write_4(rm, base + off, mask << 16 | bits); 245 } 246 247 /* GPIO drive strength control */ 248 if (strength >= 0) { 249 off = 0x1c0 + bank * 0x10 + (idx / 8) * 0x04; 250 mask = (0x3 << ((idx % 8) * 2)); 251 bits = (strength << ((idx % 8) * 2)); 252 regmap_write_4(rm, base + off, mask << 16 | bits); 253 } 254 255 splx(s); 256 } 257 258 free(pins, M_TEMP, len); 259 return 0; 260 261 fail: 262 free(pins, M_TEMP, len); 263 return -1; 264 } 265 266 /* 267 * Rockchip RK3308 268 */ 269 270 int 271 rk3308_pull(uint32_t bank, uint32_t idx, uint32_t phandle) 272 { 273 int node; 274 275 node = OF_getnodebyphandle(phandle); 276 if (node == 0) 277 return -1; 278 279 if (OF_getproplen(node, "bias-disable") == 0) 280 return 0; 281 if (OF_getproplen(node, "bias-pull-up") == 0) 282 return 1; 283 if (OF_getproplen(node, "bias-pull-down") == 0) 284 return 2; 285 286 return -1; 287 } 288 289 int 290 rk3308_strength(uint32_t bank, uint32_t idx, uint32_t phandle) 291 { 292 int strength, level; 293 int levels[4] = { 2, 4, 8, 12 }; 294 int node; 295 296 node = OF_getnodebyphandle(phandle); 297 if (node == 0) 298 return -1; 299 300 strength = OF_getpropint(node, "drive-strength", -1); 301 if (strength == -1) 302 return -1; 303 304 /* Convert drive strength to level. */ 305 for (level = 3; level >= 0; level--) { 306 if (strength >= levels[level]) 307 break; 308 } 309 return level; 310 } 311 312 int 313 rk3308_pinctrl(uint32_t phandle, void *cookie) 314 { 315 struct rkpinctrl_softc *sc = cookie; 316 uint32_t *pins; 317 int node, len, i; 318 319 KASSERT(sc->sc_grf); 320 321 node = OF_getnodebyphandle(phandle); 322 if (node == 0) 323 return -1; 324 325 len = OF_getproplen(node, "rockchip,pins"); 326 if (len <= 0) 327 return -1; 328 329 pins = malloc(len, M_TEMP, M_WAITOK); 330 if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len) 331 goto fail; 332 333 for (i = 0; i < len / sizeof(uint32_t); i += 4) { 334 struct regmap *rm = sc->sc_grf; 335 bus_size_t base, off; 336 uint32_t bank, idx, mux; 337 int pull, strength; 338 uint32_t mask, bits; 339 int s; 340 341 bank = pins[i]; 342 idx = pins[i + 1]; 343 mux = pins[i + 2]; 344 pull = rk3308_pull(bank, idx, pins[i + 3]); 345 strength = rk3308_strength(bank, idx, pins[i + 3]); 346 347 if (bank > 4 || idx > 32 || mux > 7) 348 continue; 349 350 base = RK3308_GRF_GPIO0A_IOMUX; 351 352 s = splhigh(); 353 354 /* IOMUX control */ 355 off = bank * 0x20 + (idx / 8) * 0x08; 356 357 /* GPIO1B, GPIO1C and GPIO3B are special. */ 358 if ((bank == 1) && (idx == 14)) { 359 mask = (0xf << 12); 360 bits = (mux << 12); 361 } else if ((bank == 1) && (idx == 15)) { 362 off += 4; 363 mask = 0x3; 364 bits = mux; 365 } else if ((bank == 1) && (idx >= 16 && idx <= 17)) { 366 mask = (0x3 << ((idx - 16) * 2)); 367 bits = (mux << ((idx - 16) * 2)); 368 } else if ((bank == 1) && (idx >= 18 && idx <= 20)) { 369 mask = (0xf << (((idx - 18) * 4) + 4)); 370 bits = (mux << (((idx - 18) * 4) + 4)); 371 } else if ((bank == 1) && (idx >= 21 && idx <= 23)) { 372 off += 4; 373 mask = (0xf << ((idx - 21) * 4)); 374 bits = (mux << ((idx - 21) * 4)); 375 } else if ((bank == 3) && (idx >= 12 && idx <= 13)) { 376 mask = (0xf << (((idx - 12) * 4) + 8)); 377 bits = (mux << (((idx - 12) * 4) + 8)); 378 } else { 379 mask = (0x3 << ((idx % 8) * 2)); 380 bits = (mux << ((idx % 8) * 2)); 381 } 382 regmap_write_4(rm, base + off, mask << 16 | bits); 383 384 /* GPIO pad pull down and pull up control */ 385 if (pull >= 0) { 386 off = 0xa0 + bank * 0x10 + (idx / 8) * 0x04; 387 mask = (0x3 << ((idx % 8) * 2)); 388 bits = (pull << ((idx % 8) * 2)); 389 regmap_write_4(rm, base + off, mask << 16 | bits); 390 } 391 392 /* GPIO drive strength control */ 393 if (strength >= 0) { 394 off = 0x100 + bank * 0x10 + (idx / 8) * 0x04; 395 mask = (0x3 << ((idx % 8) * 2)); 396 bits = (strength << ((idx % 8) * 2)); 397 regmap_write_4(rm, base + off, mask << 16 | bits); 398 } 399 400 splx(s); 401 } 402 403 free(pins, M_TEMP, len); 404 return 0; 405 406 fail: 407 free(pins, M_TEMP, len); 408 return -1; 409 } 410 411 /* 412 * Rockchip RK3328 413 */ 414 415 int 416 rk3328_pull(uint32_t bank, uint32_t idx, uint32_t phandle) 417 { 418 int node; 419 420 node = OF_getnodebyphandle(phandle); 421 if (node == 0) 422 return -1; 423 424 if (OF_getproplen(node, "bias-disable") == 0) 425 return 0; 426 if (OF_getproplen(node, "bias-pull-up") == 0) 427 return 1; 428 if (OF_getproplen(node, "bias-pull-down") == 0) 429 return 2; 430 431 return -1; 432 } 433 434 int 435 rk3328_strength(uint32_t bank, uint32_t idx, uint32_t phandle) 436 { 437 int strength, level; 438 int levels[4] = { 2, 4, 8, 12 }; 439 int node; 440 441 node = OF_getnodebyphandle(phandle); 442 if (node == 0) 443 return -1; 444 445 strength = OF_getpropint(node, "drive-strength", -1); 446 if (strength == -1) 447 return -1; 448 449 /* Convert drive strength to level. */ 450 for (level = 3; level >= 0; level--) { 451 if (strength >= levels[level]) 452 break; 453 } 454 return level; 455 } 456 457 int 458 rk3328_pinctrl(uint32_t phandle, void *cookie) 459 { 460 struct rkpinctrl_softc *sc = cookie; 461 uint32_t *pins; 462 int node, len, i; 463 464 KASSERT(sc->sc_grf); 465 466 node = OF_getnodebyphandle(phandle); 467 if (node == 0) 468 return -1; 469 470 len = OF_getproplen(node, "rockchip,pins"); 471 if (len <= 0) 472 return -1; 473 474 pins = malloc(len, M_TEMP, M_WAITOK); 475 if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len) 476 goto fail; 477 478 for (i = 0; i < len / sizeof(uint32_t); i += 4) { 479 struct regmap *rm = sc->sc_grf; 480 bus_size_t base, off; 481 uint32_t bank, idx, mux; 482 int pull, strength; 483 uint32_t mask, bits; 484 int s; 485 486 bank = pins[i]; 487 idx = pins[i + 1]; 488 mux = pins[i + 2]; 489 pull = rk3288_pull(bank, idx, pins[i + 3]); 490 strength = rk3288_strength(bank, idx, pins[i + 3]); 491 492 if (bank > 3 || idx > 32 || mux > 3) 493 continue; 494 495 base = RK3328_GRF_GPIO0A_IOMUX; 496 497 s = splhigh(); 498 499 /* IOMUX control */ 500 off = bank * 0x10 + (idx / 8) * 0x04; 501 502 /* GPIO2B, GPIO2C, GPIO3A and GPIO3B are special. */ 503 if (bank == 2 && idx == 15) { 504 mask = 0x7; 505 bits = mux; 506 } else if (bank == 2 && idx >= 16 && idx <= 20) { 507 mask = (0x7 << ((idx - 16) * 3)); 508 bits = (mux << ((idx - 16) * 3)); 509 } else if (bank == 2 && idx >= 21 && idx <= 23) { 510 mask = (0x7 << ((idx - 21) * 3)); 511 bits = (mux << ((idx - 21) * 3)); 512 } else if (bank == 3 && idx <= 4) { 513 mask = (0x7 << (idx * 3)); 514 bits = (mux << (idx * 3)); 515 } else if (bank == 3 && idx >= 5 && idx <= 7) { 516 mask = (0x7 << ((idx - 5) * 3)); 517 bits = (mux << ((idx - 5) * 3)); 518 } else if (bank == 3 && idx >= 8 && idx <= 12) { 519 mask = (0x7 << ((idx - 8) * 3)); 520 bits = (mux << ((idx - 8) * 3)); 521 } else if (bank == 3 && idx >= 13 && idx <= 15) { 522 mask = (0x7 << ((idx - 13) * 3)); 523 bits = (mux << ((idx - 13) * 3)); 524 } else { 525 mask = (0x3 << ((idx % 8) * 2)); 526 bits = (mux << ((idx % 8) * 2)); 527 } 528 if (bank > 2 || (bank == 2 && idx >= 15)) 529 off += 0x04; 530 if (bank > 2 || (bank == 2 && idx >= 21)) 531 off += 0x04; 532 if (bank > 3 || (bank == 3 && idx >= 5)) 533 off += 0x04; 534 if (bank > 3 || (bank == 3 && idx >= 13)) 535 off += 0x04; 536 regmap_write_4(rm, base + off, mask << 16 | bits); 537 538 /* GPIO pad pull down and pull up control */ 539 if (pull >= 0) { 540 off = 0x100 + bank * 0x10 + (idx / 8) * 0x04; 541 mask = (0x3 << ((idx % 8) * 2)); 542 bits = (pull << ((idx % 8) * 2)); 543 regmap_write_4(rm, base + off, mask << 16 | bits); 544 } 545 546 /* GPIO drive strength control */ 547 if (strength >= 0) { 548 off = 0x200 + bank * 0x10 + (idx / 8) * 0x04; 549 mask = (0x3 << ((idx % 8) * 2)); 550 bits = (strength << ((idx % 8) * 2)); 551 regmap_write_4(rm, base + off, mask << 16 | bits); 552 } 553 554 splx(s); 555 } 556 557 free(pins, M_TEMP, len); 558 return 0; 559 560 fail: 561 free(pins, M_TEMP, len); 562 return -1; 563 } 564 565 /* 566 * Rockchip RK3399 567 */ 568 569 int 570 rk3399_pull(uint32_t bank, uint32_t idx, uint32_t phandle) 571 { 572 int pull_up, pull_down; 573 int node; 574 575 node = OF_getnodebyphandle(phandle); 576 if (node == 0) 577 return -1; 578 579 if (bank == 2 && idx >= 16) { 580 pull_up = 3; 581 pull_down = 1; 582 } else { 583 pull_up = 1; 584 pull_down = 2; 585 } 586 587 if (OF_getproplen(node, "bias-disable") == 0) 588 return 0; 589 if (OF_getproplen(node, "bias-pull-up") == 0) 590 return pull_up; 591 if (OF_getproplen(node, "bias-pull-down") == 0) 592 return pull_down; 593 594 return -1; 595 } 596 597 /* Magic because the drive strength configurations vary wildly. */ 598 599 int rk3399_strength_levels[][8] = { 600 { 2, 4, 8, 12 }, /* default */ 601 { 3, 6, 9, 12 }, /* 1.8V or 3.0V */ 602 { 5, 10, 15, 20 }, /* 1.8V only */ 603 { 4, 6, 8, 10, 12, 14, 16, 18 }, /* 1.8V or 3.0V auto */ 604 { 4, 7, 10, 13, 16, 19, 22, 26 }, /* 3.3V */ 605 }; 606 607 int rk3399_strength_types[][4] = { 608 { 2, 2, 0, 0 }, 609 { 1, 1, 1, 1 }, 610 { 1, 1, 2, 2 }, 611 { 4, 4, 4, 1 }, 612 { 1, 3, 1, 1 }, 613 }; 614 615 int rk3399_strength_regs[][4] = { 616 { 0x0080, 0x0088, 0x0090, 0x0098 }, 617 { 0x00a0, 0x00a8, 0x00b0, 0x00b8 }, 618 { 0x0100, 0x0104, 0x0108, 0x010c }, 619 { 0x0110, 0x0118, 0x0120, 0x0128 }, 620 { 0x012c, 0x0130, 0x0138, 0x013c }, 621 }; 622 623 int 624 rk3399_strength(uint32_t bank, uint32_t idx, uint32_t phandle) 625 { 626 int strength, type, level; 627 int *levels; 628 int node; 629 630 node = OF_getnodebyphandle(phandle); 631 if (node == 0) 632 return -1; 633 634 strength = OF_getpropint(node, "drive-strength", -1); 635 if (strength == -1) 636 return -1; 637 638 /* Convert drive strength to level. */ 639 type = rk3399_strength_types[bank][idx / 8]; 640 levels = rk3399_strength_levels[type]; 641 for (level = 7; level >= 0; level--) { 642 if (strength >= levels[level] && levels[level] > 0) 643 break; 644 } 645 return level; 646 } 647 648 int 649 rk3399_pinctrl(uint32_t phandle, void *cookie) 650 { 651 struct rkpinctrl_softc *sc = cookie; 652 uint32_t *pins; 653 int node, len, i; 654 655 KASSERT(sc->sc_grf); 656 KASSERT(sc->sc_pmu); 657 658 node = OF_getnodebyphandle(phandle); 659 if (node == 0) 660 return -1; 661 662 len = OF_getproplen(node, "rockchip,pins"); 663 if (len <= 0) 664 return -1; 665 666 pins = malloc(len, M_TEMP, M_WAITOK); 667 if (OF_getpropintarray(node, "rockchip,pins", pins, len) != len) 668 goto fail; 669 670 for (i = 0; i < len / sizeof(uint32_t); i += 4) { 671 struct regmap *rm; 672 bus_size_t base, off; 673 uint32_t bank, idx, mux; 674 int pull, strength, type, shift; 675 uint32_t mask, bits; 676 int s; 677 678 bank = pins[i]; 679 idx = pins[i + 1]; 680 mux = pins[i + 2]; 681 pull = rk3399_pull(bank, idx, pins[i + 3]); 682 strength = rk3399_strength(bank, idx, pins[i + 3]); 683 684 if (bank > 5 || idx > 32 || mux > 3) 685 continue; 686 687 /* Bank 0 and 1 live in the PMU. */ 688 if (bank < 2) { 689 rm = sc->sc_pmu; 690 base = RK3399_PMUGRF_GPIO0A_IOMUX; 691 } else { 692 rm = sc->sc_grf; 693 base = RK3399_GRF_GPIO2A_IOMUX - 0x20; 694 } 695 696 s = splhigh(); 697 698 /* IOMUX control */ 699 off = bank * 0x10 + (idx / 8) * 0x04; 700 mask = (0x3 << ((idx % 8) * 2)); 701 bits = (mux << ((idx % 8) * 2)); 702 regmap_write_4(rm, base + off, mask << 16 | bits); 703 704 /* GPIO pad pull down and pull up control */ 705 if (pull >= 0) { 706 off = 0x40 + bank * 0x10 + (idx / 8) * 0x04; 707 mask = (0x3 << ((idx % 8) * 2)); 708 bits = (pull << ((idx % 8) * 2)); 709 regmap_write_4(rm, base + off, mask << 16 | bits); 710 } 711 712 /* GPIO drive strength control */ 713 if (strength >= 0) { 714 off = rk3399_strength_regs[bank][idx / 8]; 715 type = rk3399_strength_types[bank][idx / 8]; 716 shift = (type > 2) ? 3 : 2; 717 mask = (((1 << shift) - 1) << ((idx % 8) * shift)); 718 bits = (strength << ((idx % 8) * shift)); 719 if (mask & 0x0000ffff) { 720 regmap_write_4(rm, base + off, 721 mask << 16 | (bits & 0x0000ffff)); 722 } 723 if (mask & 0xffff0000) { 724 regmap_write_4(rm, base + off + 0x04, 725 (mask & 0xffff0000) | bits >> 16); 726 } 727 } 728 729 splx(s); 730 } 731 732 free(pins, M_TEMP, len); 733 return 0; 734 735 fail: 736 free(pins, M_TEMP, len); 737 return -1; 738 } 739