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