root/drivers/power/avs/rockchip-io-domain.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rockchip_iodomain_write
  2. rockchip_iodomain_notify
  3. px30_iodomain_init
  4. rk3288_iodomain_init
  5. rk3328_iodomain_init
  6. rk3368_iodomain_init
  7. rk3399_pmu_iodomain_init
  8. rockchip_iodomain_probe
  9. rockchip_iodomain_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Rockchip IO Voltage Domain driver
   4  *
   5  * Copyright 2014 MundoReader S.L.
   6  * Copyright 2014 Google, Inc.
   7  */
   8 
   9 #include <linux/kernel.h>
  10 #include <linux/module.h>
  11 #include <linux/err.h>
  12 #include <linux/mfd/syscon.h>
  13 #include <linux/of.h>
  14 #include <linux/platform_device.h>
  15 #include <linux/regmap.h>
  16 #include <linux/regulator/consumer.h>
  17 
  18 #define MAX_SUPPLIES            16
  19 
  20 /*
  21  * The max voltage for 1.8V and 3.3V come from the Rockchip datasheet under
  22  * "Recommended Operating Conditions" for "Digital GPIO".   When the typical
  23  * is 3.3V the max is 3.6V.  When the typical is 1.8V the max is 1.98V.
  24  *
  25  * They are used like this:
  26  * - If the voltage on a rail is above the "1.8" voltage (1.98V) we'll tell the
  27  *   SoC we're at 3.3.
  28  * - If the voltage on a rail is above the "3.3" voltage (3.6V) we'll consider
  29  *   that to be an error.
  30  */
  31 #define MAX_VOLTAGE_1_8         1980000
  32 #define MAX_VOLTAGE_3_3         3600000
  33 
  34 #define PX30_IO_VSEL                    0x180
  35 #define PX30_IO_VSEL_VCCIO6_SRC         BIT(0)
  36 #define PX30_IO_VSEL_VCCIO6_SUPPLY_NUM  1
  37 
  38 #define RK3288_SOC_CON2                 0x24c
  39 #define RK3288_SOC_CON2_FLASH0          BIT(7)
  40 #define RK3288_SOC_FLASH_SUPPLY_NUM     2
  41 
  42 #define RK3328_SOC_CON4                 0x410
  43 #define RK3328_SOC_CON4_VCCIO2          BIT(7)
  44 #define RK3328_SOC_VCCIO2_SUPPLY_NUM    1
  45 
  46 #define RK3368_SOC_CON15                0x43c
  47 #define RK3368_SOC_CON15_FLASH0         BIT(14)
  48 #define RK3368_SOC_FLASH_SUPPLY_NUM     2
  49 
  50 #define RK3399_PMUGRF_CON0              0x180
  51 #define RK3399_PMUGRF_CON0_VSEL         BIT(8)
  52 #define RK3399_PMUGRF_VSEL_SUPPLY_NUM   9
  53 
  54 struct rockchip_iodomain;
  55 
  56 /**
  57  * @supplies: voltage settings matching the register bits.
  58  */
  59 struct rockchip_iodomain_soc_data {
  60         int grf_offset;
  61         const char *supply_names[MAX_SUPPLIES];
  62         void (*init)(struct rockchip_iodomain *iod);
  63 };
  64 
  65 struct rockchip_iodomain_supply {
  66         struct rockchip_iodomain *iod;
  67         struct regulator *reg;
  68         struct notifier_block nb;
  69         int idx;
  70 };
  71 
  72 struct rockchip_iodomain {
  73         struct device *dev;
  74         struct regmap *grf;
  75         const struct rockchip_iodomain_soc_data *soc_data;
  76         struct rockchip_iodomain_supply supplies[MAX_SUPPLIES];
  77 };
  78 
  79 static int rockchip_iodomain_write(struct rockchip_iodomain_supply *supply,
  80                                    int uV)
  81 {
  82         struct rockchip_iodomain *iod = supply->iod;
  83         u32 val;
  84         int ret;
  85 
  86         /* set value bit */
  87         val = (uV > MAX_VOLTAGE_1_8) ? 0 : 1;
  88         val <<= supply->idx;
  89 
  90         /* apply hiword-mask */
  91         val |= (BIT(supply->idx) << 16);
  92 
  93         ret = regmap_write(iod->grf, iod->soc_data->grf_offset, val);
  94         if (ret)
  95                 dev_err(iod->dev, "Couldn't write to GRF\n");
  96 
  97         return ret;
  98 }
  99 
 100 static int rockchip_iodomain_notify(struct notifier_block *nb,
 101                                     unsigned long event,
 102                                     void *data)
 103 {
 104         struct rockchip_iodomain_supply *supply =
 105                         container_of(nb, struct rockchip_iodomain_supply, nb);
 106         int uV;
 107         int ret;
 108 
 109         /*
 110          * According to Rockchip it's important to keep the SoC IO domain
 111          * higher than (or equal to) the external voltage.  That means we need
 112          * to change it before external voltage changes happen in the case
 113          * of an increase.
 114          *
 115          * Note that in the "pre" change we pick the max possible voltage that
 116          * the regulator might end up at (the client requests a range and we
 117          * don't know for certain the exact voltage).  Right now we rely on the
 118          * slop in MAX_VOLTAGE_1_8 and MAX_VOLTAGE_3_3 to save us if clients
 119          * request something like a max of 3.6V when they really want 3.3V.
 120          * We could attempt to come up with better rules if this fails.
 121          */
 122         if (event & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) {
 123                 struct pre_voltage_change_data *pvc_data = data;
 124 
 125                 uV = max_t(unsigned long, pvc_data->old_uV, pvc_data->max_uV);
 126         } else if (event & (REGULATOR_EVENT_VOLTAGE_CHANGE |
 127                             REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE)) {
 128                 uV = (unsigned long)data;
 129         } else {
 130                 return NOTIFY_OK;
 131         }
 132 
 133         dev_dbg(supply->iod->dev, "Setting to %d\n", uV);
 134 
 135         if (uV > MAX_VOLTAGE_3_3) {
 136                 dev_err(supply->iod->dev, "Voltage too high: %d\n", uV);
 137 
 138                 if (event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE)
 139                         return NOTIFY_BAD;
 140         }
 141 
 142         ret = rockchip_iodomain_write(supply, uV);
 143         if (ret && event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE)
 144                 return NOTIFY_BAD;
 145 
 146         dev_dbg(supply->iod->dev, "Setting to %d done\n", uV);
 147         return NOTIFY_OK;
 148 }
 149 
 150 static void px30_iodomain_init(struct rockchip_iodomain *iod)
 151 {
 152         int ret;
 153         u32 val;
 154 
 155         /* if no VCCIO0 supply we should leave things alone */
 156         if (!iod->supplies[PX30_IO_VSEL_VCCIO6_SUPPLY_NUM].reg)
 157                 return;
 158 
 159         /*
 160          * set vccio0 iodomain to also use this framework
 161          * instead of a special gpio.
 162          */
 163         val = PX30_IO_VSEL_VCCIO6_SRC | (PX30_IO_VSEL_VCCIO6_SRC << 16);
 164         ret = regmap_write(iod->grf, PX30_IO_VSEL, val);
 165         if (ret < 0)
 166                 dev_warn(iod->dev, "couldn't update vccio0 ctrl\n");
 167 }
 168 
 169 static void rk3288_iodomain_init(struct rockchip_iodomain *iod)
 170 {
 171         int ret;
 172         u32 val;
 173 
 174         /* if no flash supply we should leave things alone */
 175         if (!iod->supplies[RK3288_SOC_FLASH_SUPPLY_NUM].reg)
 176                 return;
 177 
 178         /*
 179          * set flash0 iodomain to also use this framework
 180          * instead of a special gpio.
 181          */
 182         val = RK3288_SOC_CON2_FLASH0 | (RK3288_SOC_CON2_FLASH0 << 16);
 183         ret = regmap_write(iod->grf, RK3288_SOC_CON2, val);
 184         if (ret < 0)
 185                 dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
 186 }
 187 
 188 static void rk3328_iodomain_init(struct rockchip_iodomain *iod)
 189 {
 190         int ret;
 191         u32 val;
 192 
 193         /* if no vccio2 supply we should leave things alone */
 194         if (!iod->supplies[RK3328_SOC_VCCIO2_SUPPLY_NUM].reg)
 195                 return;
 196 
 197         /*
 198          * set vccio2 iodomain to also use this framework
 199          * instead of a special gpio.
 200          */
 201         val = RK3328_SOC_CON4_VCCIO2 | (RK3328_SOC_CON4_VCCIO2 << 16);
 202         ret = regmap_write(iod->grf, RK3328_SOC_CON4, val);
 203         if (ret < 0)
 204                 dev_warn(iod->dev, "couldn't update vccio2 vsel ctrl\n");
 205 }
 206 
 207 static void rk3368_iodomain_init(struct rockchip_iodomain *iod)
 208 {
 209         int ret;
 210         u32 val;
 211 
 212         /* if no flash supply we should leave things alone */
 213         if (!iod->supplies[RK3368_SOC_FLASH_SUPPLY_NUM].reg)
 214                 return;
 215 
 216         /*
 217          * set flash0 iodomain to also use this framework
 218          * instead of a special gpio.
 219          */
 220         val = RK3368_SOC_CON15_FLASH0 | (RK3368_SOC_CON15_FLASH0 << 16);
 221         ret = regmap_write(iod->grf, RK3368_SOC_CON15, val);
 222         if (ret < 0)
 223                 dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
 224 }
 225 
 226 static void rk3399_pmu_iodomain_init(struct rockchip_iodomain *iod)
 227 {
 228         int ret;
 229         u32 val;
 230 
 231         /* if no pmu io supply we should leave things alone */
 232         if (!iod->supplies[RK3399_PMUGRF_VSEL_SUPPLY_NUM].reg)
 233                 return;
 234 
 235         /*
 236          * set pmu io iodomain to also use this framework
 237          * instead of a special gpio.
 238          */
 239         val = RK3399_PMUGRF_CON0_VSEL | (RK3399_PMUGRF_CON0_VSEL << 16);
 240         ret = regmap_write(iod->grf, RK3399_PMUGRF_CON0, val);
 241         if (ret < 0)
 242                 dev_warn(iod->dev, "couldn't update pmu io iodomain ctrl\n");
 243 }
 244 
 245 static const struct rockchip_iodomain_soc_data soc_data_px30 = {
 246         .grf_offset = 0x180,
 247         .supply_names = {
 248                 NULL,
 249                 "vccio6",
 250                 "vccio1",
 251                 "vccio2",
 252                 "vccio3",
 253                 "vccio4",
 254                 "vccio5",
 255                 "vccio-oscgpi",
 256         },
 257         .init = px30_iodomain_init,
 258 };
 259 
 260 static const struct rockchip_iodomain_soc_data soc_data_px30_pmu = {
 261         .grf_offset = 0x100,
 262         .supply_names = {
 263                 NULL,
 264                 NULL,
 265                 NULL,
 266                 NULL,
 267                 NULL,
 268                 NULL,
 269                 NULL,
 270                 NULL,
 271                 NULL,
 272                 NULL,
 273                 NULL,
 274                 NULL,
 275                 NULL,
 276                 NULL,
 277                 "pmuio1",
 278                 "pmuio2",
 279         },
 280 };
 281 
 282 /*
 283  * On the rk3188 the io-domains are handled by a shared register with the
 284  * lower 8 bits being still being continuing drive-strength settings.
 285  */
 286 static const struct rockchip_iodomain_soc_data soc_data_rk3188 = {
 287         .grf_offset = 0x104,
 288         .supply_names = {
 289                 NULL,
 290                 NULL,
 291                 NULL,
 292                 NULL,
 293                 NULL,
 294                 NULL,
 295                 NULL,
 296                 NULL,
 297                 "ap0",
 298                 "ap1",
 299                 "cif",
 300                 "flash",
 301                 "vccio0",
 302                 "vccio1",
 303                 "lcdc0",
 304                 "lcdc1",
 305         },
 306 };
 307 
 308 static const struct rockchip_iodomain_soc_data soc_data_rk3228 = {
 309         .grf_offset = 0x418,
 310         .supply_names = {
 311                 "vccio1",
 312                 "vccio2",
 313                 "vccio3",
 314                 "vccio4",
 315         },
 316 };
 317 
 318 static const struct rockchip_iodomain_soc_data soc_data_rk3288 = {
 319         .grf_offset = 0x380,
 320         .supply_names = {
 321                 "lcdc",         /* LCDC_VDD */
 322                 "dvp",          /* DVPIO_VDD */
 323                 "flash0",       /* FLASH0_VDD (emmc) */
 324                 "flash1",       /* FLASH1_VDD (sdio1) */
 325                 "wifi",         /* APIO3_VDD  (sdio0) */
 326                 "bb",           /* APIO5_VDD */
 327                 "audio",        /* APIO4_VDD */
 328                 "sdcard",       /* SDMMC0_VDD (sdmmc) */
 329                 "gpio30",       /* APIO1_VDD */
 330                 "gpio1830",     /* APIO2_VDD */
 331         },
 332         .init = rk3288_iodomain_init,
 333 };
 334 
 335 static const struct rockchip_iodomain_soc_data soc_data_rk3328 = {
 336         .grf_offset = 0x410,
 337         .supply_names = {
 338                 "vccio1",
 339                 "vccio2",
 340                 "vccio3",
 341                 "vccio4",
 342                 "vccio5",
 343                 "vccio6",
 344                 "pmuio",
 345         },
 346         .init = rk3328_iodomain_init,
 347 };
 348 
 349 static const struct rockchip_iodomain_soc_data soc_data_rk3368 = {
 350         .grf_offset = 0x900,
 351         .supply_names = {
 352                 NULL,           /* reserved */
 353                 "dvp",          /* DVPIO_VDD */
 354                 "flash0",       /* FLASH0_VDD (emmc) */
 355                 "wifi",         /* APIO2_VDD (sdio0) */
 356                 NULL,
 357                 "audio",        /* APIO3_VDD */
 358                 "sdcard",       /* SDMMC0_VDD (sdmmc) */
 359                 "gpio30",       /* APIO1_VDD */
 360                 "gpio1830",     /* APIO4_VDD (gpujtag) */
 361         },
 362         .init = rk3368_iodomain_init,
 363 };
 364 
 365 static const struct rockchip_iodomain_soc_data soc_data_rk3368_pmu = {
 366         .grf_offset = 0x100,
 367         .supply_names = {
 368                 NULL,
 369                 NULL,
 370                 NULL,
 371                 NULL,
 372                 "pmu",          /*PMU IO domain*/
 373                 "vop",          /*LCDC IO domain*/
 374         },
 375 };
 376 
 377 static const struct rockchip_iodomain_soc_data soc_data_rk3399 = {
 378         .grf_offset = 0xe640,
 379         .supply_names = {
 380                 "bt656",                /* APIO2_VDD */
 381                 "audio",                /* APIO5_VDD */
 382                 "sdmmc",                /* SDMMC0_VDD */
 383                 "gpio1830",             /* APIO4_VDD */
 384         },
 385 };
 386 
 387 static const struct rockchip_iodomain_soc_data soc_data_rk3399_pmu = {
 388         .grf_offset = 0x180,
 389         .supply_names = {
 390                 NULL,
 391                 NULL,
 392                 NULL,
 393                 NULL,
 394                 NULL,
 395                 NULL,
 396                 NULL,
 397                 NULL,
 398                 NULL,
 399                 "pmu1830",              /* PMUIO2_VDD */
 400         },
 401         .init = rk3399_pmu_iodomain_init,
 402 };
 403 
 404 static const struct rockchip_iodomain_soc_data soc_data_rv1108 = {
 405         .grf_offset = 0x404,
 406         .supply_names = {
 407                 NULL,
 408                 NULL,
 409                 NULL,
 410                 NULL,
 411                 NULL,
 412                 NULL,
 413                 NULL,
 414                 NULL,
 415                 NULL,
 416                 NULL,
 417                 NULL,
 418                 "vccio1",
 419                 "vccio2",
 420                 "vccio3",
 421                 "vccio5",
 422                 "vccio6",
 423         },
 424 
 425 };
 426 
 427 static const struct rockchip_iodomain_soc_data soc_data_rv1108_pmu = {
 428         .grf_offset = 0x104,
 429         .supply_names = {
 430                 "pmu",
 431         },
 432 };
 433 
 434 static const struct of_device_id rockchip_iodomain_match[] = {
 435         {
 436                 .compatible = "rockchip,px30-io-voltage-domain",
 437                 .data = (void *)&soc_data_px30
 438         },
 439         {
 440                 .compatible = "rockchip,px30-pmu-io-voltage-domain",
 441                 .data = (void *)&soc_data_px30_pmu
 442         },
 443         {
 444                 .compatible = "rockchip,rk3188-io-voltage-domain",
 445                 .data = &soc_data_rk3188
 446         },
 447         {
 448                 .compatible = "rockchip,rk3228-io-voltage-domain",
 449                 .data = &soc_data_rk3228
 450         },
 451         {
 452                 .compatible = "rockchip,rk3288-io-voltage-domain",
 453                 .data = &soc_data_rk3288
 454         },
 455         {
 456                 .compatible = "rockchip,rk3328-io-voltage-domain",
 457                 .data = &soc_data_rk3328
 458         },
 459         {
 460                 .compatible = "rockchip,rk3368-io-voltage-domain",
 461                 .data = &soc_data_rk3368
 462         },
 463         {
 464                 .compatible = "rockchip,rk3368-pmu-io-voltage-domain",
 465                 .data = &soc_data_rk3368_pmu
 466         },
 467         {
 468                 .compatible = "rockchip,rk3399-io-voltage-domain",
 469                 .data = &soc_data_rk3399
 470         },
 471         {
 472                 .compatible = "rockchip,rk3399-pmu-io-voltage-domain",
 473                 .data = &soc_data_rk3399_pmu
 474         },
 475         {
 476                 .compatible = "rockchip,rv1108-io-voltage-domain",
 477                 .data = &soc_data_rv1108
 478         },
 479         {
 480                 .compatible = "rockchip,rv1108-pmu-io-voltage-domain",
 481                 .data = &soc_data_rv1108_pmu
 482         },
 483         { /* sentinel */ },
 484 };
 485 MODULE_DEVICE_TABLE(of, rockchip_iodomain_match);
 486 
 487 static int rockchip_iodomain_probe(struct platform_device *pdev)
 488 {
 489         struct device_node *np = pdev->dev.of_node;
 490         const struct of_device_id *match;
 491         struct rockchip_iodomain *iod;
 492         struct device *parent;
 493         int i, ret = 0;
 494 
 495         if (!np)
 496                 return -ENODEV;
 497 
 498         iod = devm_kzalloc(&pdev->dev, sizeof(*iod), GFP_KERNEL);
 499         if (!iod)
 500                 return -ENOMEM;
 501 
 502         iod->dev = &pdev->dev;
 503         platform_set_drvdata(pdev, iod);
 504 
 505         match = of_match_node(rockchip_iodomain_match, np);
 506         iod->soc_data = match->data;
 507 
 508         parent = pdev->dev.parent;
 509         if (parent && parent->of_node) {
 510                 iod->grf = syscon_node_to_regmap(parent->of_node);
 511         } else {
 512                 dev_dbg(&pdev->dev, "falling back to old binding\n");
 513                 iod->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
 514         }
 515 
 516         if (IS_ERR(iod->grf)) {
 517                 dev_err(&pdev->dev, "couldn't find grf regmap\n");
 518                 return PTR_ERR(iod->grf);
 519         }
 520 
 521         for (i = 0; i < MAX_SUPPLIES; i++) {
 522                 const char *supply_name = iod->soc_data->supply_names[i];
 523                 struct rockchip_iodomain_supply *supply = &iod->supplies[i];
 524                 struct regulator *reg;
 525                 int uV;
 526 
 527                 if (!supply_name)
 528                         continue;
 529 
 530                 reg = devm_regulator_get_optional(iod->dev, supply_name);
 531                 if (IS_ERR(reg)) {
 532                         ret = PTR_ERR(reg);
 533 
 534                         /* If a supply wasn't specified, that's OK */
 535                         if (ret == -ENODEV)
 536                                 continue;
 537                         else if (ret != -EPROBE_DEFER)
 538                                 dev_err(iod->dev, "couldn't get regulator %s\n",
 539                                         supply_name);
 540                         goto unreg_notify;
 541                 }
 542 
 543                 /* set initial correct value */
 544                 uV = regulator_get_voltage(reg);
 545 
 546                 /* must be a regulator we can get the voltage of */
 547                 if (uV < 0) {
 548                         dev_err(iod->dev, "Can't determine voltage: %s\n",
 549                                 supply_name);
 550                         goto unreg_notify;
 551                 }
 552 
 553                 if (uV > MAX_VOLTAGE_3_3) {
 554                         dev_crit(iod->dev,
 555                                  "%d uV is too high. May damage SoC!\n",
 556                                  uV);
 557                         ret = -EINVAL;
 558                         goto unreg_notify;
 559                 }
 560 
 561                 /* setup our supply */
 562                 supply->idx = i;
 563                 supply->iod = iod;
 564                 supply->reg = reg;
 565                 supply->nb.notifier_call = rockchip_iodomain_notify;
 566 
 567                 ret = rockchip_iodomain_write(supply, uV);
 568                 if (ret) {
 569                         supply->reg = NULL;
 570                         goto unreg_notify;
 571                 }
 572 
 573                 /* register regulator notifier */
 574                 ret = regulator_register_notifier(reg, &supply->nb);
 575                 if (ret) {
 576                         dev_err(&pdev->dev,
 577                                 "regulator notifier request failed\n");
 578                         supply->reg = NULL;
 579                         goto unreg_notify;
 580                 }
 581         }
 582 
 583         if (iod->soc_data->init)
 584                 iod->soc_data->init(iod);
 585 
 586         return 0;
 587 
 588 unreg_notify:
 589         for (i = MAX_SUPPLIES - 1; i >= 0; i--) {
 590                 struct rockchip_iodomain_supply *io_supply = &iod->supplies[i];
 591 
 592                 if (io_supply->reg)
 593                         regulator_unregister_notifier(io_supply->reg,
 594                                                       &io_supply->nb);
 595         }
 596 
 597         return ret;
 598 }
 599 
 600 static int rockchip_iodomain_remove(struct platform_device *pdev)
 601 {
 602         struct rockchip_iodomain *iod = platform_get_drvdata(pdev);
 603         int i;
 604 
 605         for (i = MAX_SUPPLIES - 1; i >= 0; i--) {
 606                 struct rockchip_iodomain_supply *io_supply = &iod->supplies[i];
 607 
 608                 if (io_supply->reg)
 609                         regulator_unregister_notifier(io_supply->reg,
 610                                                       &io_supply->nb);
 611         }
 612 
 613         return 0;
 614 }
 615 
 616 static struct platform_driver rockchip_iodomain_driver = {
 617         .probe   = rockchip_iodomain_probe,
 618         .remove  = rockchip_iodomain_remove,
 619         .driver  = {
 620                 .name  = "rockchip-iodomain",
 621                 .of_match_table = rockchip_iodomain_match,
 622         },
 623 };
 624 
 625 module_platform_driver(rockchip_iodomain_driver);
 626 
 627 MODULE_DESCRIPTION("Rockchip IO-domain driver");
 628 MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
 629 MODULE_AUTHOR("Doug Anderson <dianders@chromium.org>");
 630 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */