1 /* SPDX-License-Identifier: GPL-2.0+ */ 2 /* 3 * (C) Copyright 2018 Rockchip Electronics Co., Ltd 4 */ 5 6 #include <common.h> 7 #include <dm.h> 8 #include <dm/of_access.h> 9 #include <regmap.h> 10 #include <syscon.h> 11 #include <asm/arch/clock.h> 12 #include <fdtdec.h> 13 #include <linux/compat.h> 14 #include <linux/err.h> 15 #include <power/regulator.h> 16 17 #define MAX_SUPPLIES 16 18 19 /* 20 * The max voltage for 1.8V and 3.3V come from the Rockchip datasheet under 21 * "Recommended Operating Conditions" for "Digital GPIO". When the typical 22 * is 3.3V the max is 3.6V. When the typical is 1.8V the max is 1.98V. 23 * 24 * They are used like this: 25 * - If the voltage on a rail is above the "1.8" voltage (1.98V) we'll tell the 26 * SoC we're at 3.3. 27 * - If the voltage on a rail is above the "3.3" voltage (3.6V) we'll consider 28 * that to be an error. 29 */ 30 #define MAX_VOLTAGE_1_8 1980000 31 #define MAX_VOLTAGE_3_3 3600000 32 33 #define PX30_IO_VSEL 0x180 34 #define PX30_IO_VSEL_VCCIO6_SRC BIT(0) 35 #define PX30_IO_VSEL_VCCIO6_SUPPLY_NUM 1 36 37 #define RK3288_SOC_CON2 0x24c 38 #define RK3288_SOC_CON2_FLASH0 BIT(7) 39 #define RK3288_SOC_FLASH_SUPPLY_NUM 2 40 41 #define RK3308_SOC_CON0 0x300 42 #define RK3308_SOC_CON0_VCCIO3 BIT(8) 43 #define RK3308_SOC_VCCIO3_SUPPLY_NUM 3 44 45 #define RK3328_SOC_CON4 0x410 46 #define RK3328_SOC_CON4_VCCIO2 BIT(7) 47 #define RK3328_SOC_VCCIO2_SUPPLY_NUM 1 48 49 #define RK3366_SOC_CON6 0x418 50 #define RK3366_SOC_CON6_FLASH0 BIT(14) 51 #define RK3366_SOC_FLASH_SUPPLY_NUM 2 52 53 #define RK3368_SOC_CON15 0x43c 54 #define RK3368_SOC_CON15_FLASH0 BIT(14) 55 #define RK3368_SOC_FLASH_SUPPLY_NUM 2 56 57 #define RK3399_PMUGRF_CON0 0x180 58 #define RK3399_PMUGRF_CON0_VSEL BIT(8) 59 #define RK3399_PMUGRF_VSEL_SUPPLY_NUM 9 60 61 struct rockchip_iodomain_priv; 62 63 /** 64 * @supplies: voltage settings matching the register bits. 65 */ 66 struct rockchip_iodomain_soc_data { 67 int grf_offset; 68 const char *supply_names[MAX_SUPPLIES]; 69 void (*init)(struct rockchip_iodomain_priv *iod); 70 }; 71 72 struct rockchip_iodomain_supply { 73 struct rockchip_iodomain_priv *iod; 74 struct udevice *reg; 75 int idx; 76 }; 77 78 struct rockchip_iodomain_priv { 79 struct regmap *regmap_base; 80 struct rockchip_iodomain_soc_data *sdata; 81 struct rockchip_iodomain_supply supplies[MAX_SUPPLIES]; 82 }; 83 84 static int rockchip_ofdata_to_platdata(struct udevice *dev) 85 { 86 struct rockchip_iodomain_priv *priv = dev_get_priv(dev); 87 struct regmap *regmap; 88 89 /* get grf-reg base address */ 90 regmap = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_GRF); 91 if (IS_ERR(regmap)) 92 return PTR_ERR(regmap); 93 94 priv->regmap_base = regmap; 95 96 return 0; 97 } 98 99 static int rockchip_iodomain_write(struct rockchip_iodomain_supply *supply, 100 int uV) 101 { 102 struct rockchip_iodomain_priv *priv = supply->iod; 103 struct regmap *regmap = priv->regmap_base; 104 u32 val; 105 int ret; 106 107 /* set value bit */ 108 val = (uV > MAX_VOLTAGE_1_8) ? 0 : 1; 109 val <<= supply->idx; 110 111 /* apply hiword-mask */ 112 val |= (BIT(supply->idx) << 16); 113 114 ret = regmap_write(regmap, priv->sdata->grf_offset, val); 115 if (ret) { 116 dev_err(priv->dev, "Couldn't write to GRF\n"); 117 return ret; 118 } 119 120 return 0; 121 } 122 123 static void px30_iodomain_init(struct rockchip_iodomain_priv *iod) 124 { 125 int ret; 126 u32 val; 127 128 /* if no VCCIO0 supply we should leave things alone */ 129 if (!iod->supplies[PX30_IO_VSEL_VCCIO6_SUPPLY_NUM].reg) 130 return; 131 132 /* 133 * set vccio0 iodomain to also use this framework 134 * instead of a special gpio. 135 */ 136 val = PX30_IO_VSEL_VCCIO6_SRC | (PX30_IO_VSEL_VCCIO6_SRC << 16); 137 ret = regmap_write(iod->regmap_base, PX30_IO_VSEL, val); 138 if (ret < 0) 139 dev_warn(iod->dev, "couldn't update vccio0 ctrl\n"); 140 } 141 142 static void rk3288_iodomain_init(struct rockchip_iodomain_priv *iod) 143 { 144 int ret; 145 u32 val; 146 147 /* if no flash supply we should leave things alone */ 148 if (!iod->supplies[RK3288_SOC_FLASH_SUPPLY_NUM].reg) 149 return; 150 151 /* 152 * set flash0 iodomain to also use this framework 153 * instead of a special gpio. 154 */ 155 val = RK3288_SOC_CON2_FLASH0 | (RK3288_SOC_CON2_FLASH0 << 16); 156 ret = regmap_write(iod->regmap_base, RK3288_SOC_CON2, val); 157 if (ret < 0) 158 dev_warn(iod->dev, "couldn't update flash0 ctrl\n"); 159 } 160 161 static void rk3308_iodomain_init(struct rockchip_iodomain_priv *iod) 162 { 163 int ret; 164 u32 val; 165 166 /* if no vccio3 supply we should leave things alone */ 167 if (!iod->supplies[RK3308_SOC_VCCIO3_SUPPLY_NUM].reg) 168 return; 169 170 /* 171 * set vccio3 iodomain to also use this framework 172 * instead of a special gpio. 173 */ 174 val = RK3308_SOC_CON0_VCCIO3 | (RK3308_SOC_CON0_VCCIO3 << 16); 175 ret = regmap_write(iod->regmap_base, RK3308_SOC_CON0, val); 176 if (ret < 0) 177 dev_warn(iod->dev, "couldn't update vccio3 vsel ctrl\n"); 178 } 179 180 static void rk3328_iodomain_init(struct rockchip_iodomain_priv *iod) 181 { 182 int ret; 183 u32 val; 184 185 /* if no vccio2 supply we should leave things alone */ 186 if (!iod->supplies[RK3328_SOC_VCCIO2_SUPPLY_NUM].reg) 187 return; 188 189 /* 190 * set vccio2 iodomain to also use this framework 191 * instead of a special gpio. 192 */ 193 val = RK3328_SOC_CON4_VCCIO2 | (RK3328_SOC_CON4_VCCIO2 << 16); 194 ret = regmap_write(iod->regmap_base, RK3328_SOC_CON4, val); 195 if (ret < 0) 196 dev_warn(iod->dev, "couldn't update vccio2 vsel ctrl\n"); 197 } 198 199 static void rk3366_iodomain_init(struct rockchip_iodomain_priv *iod) 200 { 201 int ret; 202 u32 val; 203 204 /* if no flash supply we should leave things alone */ 205 if (!iod->supplies[RK3366_SOC_FLASH_SUPPLY_NUM].reg) 206 return; 207 208 /* 209 * set flash0 iodomain to also use this framework 210 * instead of a special gpio. 211 */ 212 val = RK3366_SOC_CON6_FLASH0 | (RK3366_SOC_CON6_FLASH0 << 16); 213 ret = regmap_write(iod->regmap_base, RK3368_SOC_CON15, val); 214 if (ret < 0) 215 dev_warn(iod->dev, "couldn't update flash0 ctrl\n"); 216 } 217 218 static void rk3368_iodomain_init(struct rockchip_iodomain_priv *iod) 219 { 220 int ret; 221 u32 val; 222 223 /* if no flash supply we should leave things alone */ 224 if (!iod->supplies[RK3368_SOC_FLASH_SUPPLY_NUM].reg) 225 return; 226 227 /* 228 * set flash0 iodomain to also use this framework 229 * instead of a special gpio. 230 */ 231 val = RK3368_SOC_CON15_FLASH0 | (RK3368_SOC_CON15_FLASH0 << 16); 232 ret = regmap_write(iod->regmap_base, RK3368_SOC_CON15, val); 233 if (ret < 0) 234 dev_warn(iod->dev, "couldn't update flash0 ctrl\n"); 235 } 236 237 static void rk3399_pmu_iodomain_init(struct rockchip_iodomain_priv *iod) 238 { 239 int ret; 240 u32 val; 241 242 /* if no pmu io supply we should leave things alone */ 243 if (!iod->supplies[RK3399_PMUGRF_VSEL_SUPPLY_NUM].reg) 244 return; 245 246 /* 247 * set pmu io iodomain to also use this framework 248 * instead of a special gpio. 249 */ 250 val = RK3399_PMUGRF_CON0_VSEL | (RK3399_PMUGRF_CON0_VSEL << 16); 251 ret = regmap_write(iod->regmap_base, RK3399_PMUGRF_CON0, val); 252 if (ret < 0) 253 dev_warn(iod->dev, "couldn't update pmu io iodomain ctrl\n"); 254 } 255 256 static const struct rockchip_iodomain_soc_data soc_data_px30 = { 257 .grf_offset = 0x180, 258 .supply_names = { 259 NULL, 260 "vccio6", 261 "vccio1", 262 "vccio2", 263 "vccio3", 264 "vccio4", 265 "vccio5", 266 "vccio-oscgpi", 267 }, 268 .init = px30_iodomain_init, 269 }; 270 271 static const struct rockchip_iodomain_soc_data soc_data_px30_pmu = { 272 .grf_offset = 0x100, 273 .supply_names = { 274 NULL, 275 NULL, 276 NULL, 277 NULL, 278 NULL, 279 NULL, 280 NULL, 281 NULL, 282 NULL, 283 NULL, 284 NULL, 285 NULL, 286 NULL, 287 NULL, 288 "pmuio1", 289 "pmuio2", 290 }, 291 }; 292 293 /* 294 * On the rk3188 the io-domains are handled by a shared register with the 295 * lower 8 bits being still being continuing drive-strength settings. 296 */ 297 static const struct rockchip_iodomain_soc_data soc_data_rk3188 = { 298 .grf_offset = 0x104, 299 .supply_names = { 300 NULL, 301 NULL, 302 NULL, 303 NULL, 304 NULL, 305 NULL, 306 NULL, 307 NULL, 308 "ap0", 309 "ap1", 310 "cif", 311 "flash", 312 "vccio0", 313 "vccio1", 314 "lcdc0", 315 "lcdc1", 316 }, 317 }; 318 319 static const struct rockchip_iodomain_soc_data soc_data_rk322x = { 320 .grf_offset = 0x418, 321 .supply_names = { 322 "vccio1", 323 "vccio2", 324 "vccio3", 325 "vccio4", 326 }, 327 }; 328 329 static const struct rockchip_iodomain_soc_data soc_data_rk3288 = { 330 .grf_offset = 0x380, 331 .supply_names = { 332 "lcdc", /* LCDC_VDD */ 333 "dvp", /* DVPIO_VDD */ 334 "flash0", /* FLASH0_VDD (emmc) */ 335 "flash1", /* FLASH1_VDD (sdio1) */ 336 "wifi", /* APIO3_VDD (sdio0) */ 337 "bb", /* APIO5_VDD */ 338 "audio", /* APIO4_VDD */ 339 "sdcard", /* SDMMC0_VDD (sdmmc) */ 340 "gpio30", /* APIO1_VDD */ 341 "gpio1830", /* APIO2_VDD */ 342 }, 343 .init = rk3288_iodomain_init, 344 }; 345 346 static const struct rockchip_iodomain_soc_data soc_data_rk3308 = { 347 .grf_offset = 0x300, 348 .supply_names = { 349 "vccio0", 350 "vccio1", 351 "vccio2", 352 "vccio3", 353 "vccio4", 354 "vccio5", 355 }, 356 .init = rk3308_iodomain_init, 357 }; 358 359 static const struct rockchip_iodomain_soc_data soc_data_rk3328 = { 360 .grf_offset = 0x410, 361 .supply_names = { 362 "vccio1", 363 "vccio2", 364 "vccio3", 365 "vccio4", 366 "vccio5", 367 "vccio6", 368 "pmuio", 369 }, 370 .init = rk3328_iodomain_init, 371 }; 372 373 static const struct rockchip_iodomain_soc_data soc_data_rk3366 = { 374 .grf_offset = 0x900, 375 .supply_names = { 376 "lcdc", /* LCDC_IOVDD */ 377 "dvpts", /* DVP_IOVDD */ 378 "flash", /* FLASH_IOVDD (emmc) */ 379 "wifibt", /* APIO1_IOVDD */ 380 NULL, 381 "audio", /* AUDIO_IODVDD */ 382 "sdcard", /* SDMMC_IOVDD (sdmmc) */ 383 "tphdsor", /* APIO2_IOVDD */ 384 }, 385 .init = rk3366_iodomain_init, 386 }; 387 388 static const struct rockchip_iodomain_soc_data soc_data_rk3368 = { 389 .grf_offset = 0x900, 390 .supply_names = { 391 NULL, /* reserved */ 392 "dvp", /* DVPIO_VDD */ 393 "flash0", /* FLASH0_VDD (emmc) */ 394 "wifi", /* APIO2_VDD (sdio0) */ 395 NULL, 396 "audio", /* APIO3_VDD */ 397 "sdcard", /* SDMMC0_VDD (sdmmc) */ 398 "gpio30", /* APIO1_VDD */ 399 "gpio1830", /* APIO4_VDD (gpujtag) */ 400 }, 401 .init = rk3368_iodomain_init, 402 }; 403 404 static const struct rockchip_iodomain_soc_data soc_data_rk3368_pmu = { 405 .grf_offset = 0x100, 406 .supply_names = { 407 NULL, 408 NULL, 409 NULL, 410 NULL, 411 "pmu", /*PMU IO domain*/ 412 "vop", /*LCDC IO domain*/ 413 }, 414 }; 415 416 static const struct rockchip_iodomain_soc_data soc_data_rk3399 = { 417 .grf_offset = 0xe640, 418 .supply_names = { 419 "bt656", /* APIO2_VDD */ 420 "audio", /* APIO5_VDD */ 421 "sdmmc", /* SDMMC0_VDD */ 422 "gpio1830", /* APIO4_VDD */ 423 }, 424 }; 425 426 static const struct rockchip_iodomain_soc_data soc_data_rk3399_pmu = { 427 .grf_offset = 0x180, 428 .supply_names = { 429 NULL, 430 NULL, 431 NULL, 432 NULL, 433 NULL, 434 NULL, 435 NULL, 436 NULL, 437 NULL, 438 "pmu1830", /* PMUIO2_VDD */ 439 }, 440 .init = rk3399_pmu_iodomain_init, 441 }; 442 443 static const struct rockchip_iodomain_soc_data soc_data_rv1108 = { 444 .grf_offset = 0x404, 445 .supply_names = { 446 NULL, 447 NULL, 448 NULL, 449 NULL, 450 NULL, 451 NULL, 452 NULL, 453 NULL, 454 NULL, 455 NULL, 456 NULL, 457 "vccio1", 458 "vccio2", 459 "vccio3", 460 "vccio5", 461 "vccio6", 462 }, 463 464 }; 465 466 static const struct rockchip_iodomain_soc_data soc_data_rv1108_pmu = { 467 .grf_offset = 0x104, 468 .supply_names = { 469 "pmu", 470 }, 471 }; 472 473 static const struct rockchip_iodomain_soc_data soc_data_rv1126_pmu = { 474 .grf_offset = 0x140, 475 .supply_names = { 476 NULL, 477 "vccio1", 478 "vccio2", 479 "vccio3", 480 "vccio4", 481 "vccio5", 482 "vccio6", 483 "vccio7", 484 "pmuio0", 485 "pmuio1", 486 }, 487 }; 488 489 static struct udevice *of_get_regulator(ofnode node, const char *supply) 490 { 491 char sname[32]; /* 32 is max size of property name */ 492 struct udevice *sudev; 493 ofnode snode; 494 u32 phandle; 495 int ret; 496 497 snprintf(sname, 32, "%s-supply", supply); 498 499 /* Get regulator and clk */ 500 if (!ofnode_read_u32(node, sname, &phandle)) { 501 snode = ofnode_get_by_phandle(phandle); 502 ret = regulator_get_by_devname(snode.np->name, &sudev); 503 if (ret) { 504 printf("%s: Get (%s) regulator: %s failed, ret=%d\n", 505 __func__, 506 sname, snode.np->full_name, ret); 507 return NULL; 508 } 509 debug("IO-DOMAIN: supply: %s\n", snode.np->full_name); 510 } 511 512 return sudev; 513 } 514 515 static int rockchip_iodomain_probe(struct udevice *dev) 516 { 517 struct rockchip_iodomain_priv *priv = dev_get_priv(dev); 518 struct rockchip_iodomain_soc_data *sdata; 519 int i, ret; 520 521 sdata = (struct rockchip_iodomain_soc_data *)dev_get_driver_data(dev); 522 priv->sdata = sdata; 523 524 if (!priv->regmap_base) 525 return -1; 526 527 for (i = 0; i < MAX_SUPPLIES; i++) { 528 const char *supply_name = priv->sdata->supply_names[i]; 529 struct rockchip_iodomain_supply *supply = &priv->supplies[i]; 530 struct udevice *reg; 531 u32 uV; 532 533 if (!supply_name) 534 continue; 535 536 reg = of_get_regulator(dev_ofnode(dev), supply_name); 537 if (!reg) 538 continue; 539 540 uV = regulator_get_value(reg); 541 if (uV <= 0) { 542 printf("voltage(%d uV) is invalid from %s\n", uV, reg->name); 543 continue; 544 } 545 546 if (uV > MAX_VOLTAGE_3_3) { 547 printf("%d uV is too high from %s\n", uV, reg->name); 548 continue; 549 } 550 551 /* setup our supply */ 552 supply->idx = i; 553 supply->iod = priv; 554 supply->reg = reg; 555 556 ret = rockchip_iodomain_write(supply, uV); 557 if (ret) 558 supply->reg = NULL; 559 } 560 561 if (priv->sdata->init) 562 priv->sdata->init(priv); 563 564 return 0; 565 } 566 567 static const struct udevice_id rockchip_iodomain_match[] = { 568 { 569 .compatible = "rockchip,px30-io-voltage-domain", 570 .data = (ulong)&soc_data_px30 571 }, 572 { 573 .compatible = "rockchip,px30-pmu-io-voltage-domain", 574 .data = (ulong)&soc_data_px30_pmu 575 }, 576 { 577 .compatible = "rockchip,rk3188-io-voltage-domain", 578 .data = (ulong)&soc_data_rk3188 579 }, 580 { 581 .compatible = "rockchip,rk322x-io-voltage-domain", 582 .data = (ulong)&soc_data_rk322x 583 }, 584 { 585 .compatible = "rockchip,rk3288-io-voltage-domain", 586 .data = (ulong)&soc_data_rk3288 587 }, 588 { 589 .compatible = "rockchip,rk3308-io-voltage-domain", 590 .data = (ulong)&soc_data_rk3308 591 }, 592 { 593 .compatible = "rockchip,rk3328-io-voltage-domain", 594 .data = (ulong)&soc_data_rk3328 595 }, 596 { 597 .compatible = "rockchip,rk3366-io-voltage-domain", 598 .data = (ulong)&soc_data_rk3366 599 }, 600 { 601 .compatible = "rockchip,rk3368-io-voltage-domain", 602 .data = (ulong)&soc_data_rk3368 603 }, 604 { 605 .compatible = "rockchip,rk3368-pmu-io-voltage-domain", 606 .data = (ulong)&soc_data_rk3368_pmu 607 }, 608 { 609 .compatible = "rockchip,rk3399-io-voltage-domain", 610 .data = (ulong)&soc_data_rk3399 611 }, 612 { 613 .compatible = "rockchip,rk3399-pmu-io-voltage-domain", 614 .data = (ulong)&soc_data_rk3399_pmu 615 }, 616 { 617 .compatible = "rockchip,rv1108-io-voltage-domain", 618 .data = (ulong)&soc_data_rv1108 619 }, 620 { 621 .compatible = "rockchip,rv1108-pmu-io-voltage-domain", 622 .data = (ulong)&soc_data_rv1108_pmu 623 }, 624 { 625 .compatible = "rockchip,rv1126-pmu-io-voltage-domain", 626 .data = (ulong)&soc_data_rv1126_pmu 627 }, 628 { /* sentinel */ }, 629 }; 630 631 U_BOOT_DRIVER(io_domain) = { 632 .name = "io_domain", 633 .id = UCLASS_IO_DOMAIN, 634 .of_match = rockchip_iodomain_match, 635 .priv_auto_alloc_size = sizeof(struct rockchip_iodomain_priv), 636 .ofdata_to_platdata = rockchip_ofdata_to_platdata, 637 .probe = rockchip_iodomain_probe, 638 }; 639