0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kernel.h>
0010 #include <linux/module.h>
0011 #include <linux/err.h>
0012 #include <linux/mfd/syscon.h>
0013 #include <linux/of.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/regmap.h>
0016 #include <linux/regulator/consumer.h>
0017
0018 #define MAX_SUPPLIES 16
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #define MAX_VOLTAGE_1_8 1980000
0032 #define MAX_VOLTAGE_3_3 3600000
0033
0034 #define PX30_IO_VSEL 0x180
0035 #define PX30_IO_VSEL_VCCIO6_SRC BIT(0)
0036 #define PX30_IO_VSEL_VCCIO6_SUPPLY_NUM 1
0037
0038 #define RK3288_SOC_CON2 0x24c
0039 #define RK3288_SOC_CON2_FLASH0 BIT(7)
0040 #define RK3288_SOC_FLASH_SUPPLY_NUM 2
0041
0042 #define RK3328_SOC_CON4 0x410
0043 #define RK3328_SOC_CON4_VCCIO2 BIT(7)
0044 #define RK3328_SOC_VCCIO2_SUPPLY_NUM 1
0045
0046 #define RK3368_SOC_CON15 0x43c
0047 #define RK3368_SOC_CON15_FLASH0 BIT(14)
0048 #define RK3368_SOC_FLASH_SUPPLY_NUM 2
0049
0050 #define RK3399_PMUGRF_CON0 0x180
0051 #define RK3399_PMUGRF_CON0_VSEL BIT(8)
0052 #define RK3399_PMUGRF_VSEL_SUPPLY_NUM 9
0053
0054 #define RK3568_PMU_GRF_IO_VSEL0 (0x0140)
0055 #define RK3568_PMU_GRF_IO_VSEL1 (0x0144)
0056 #define RK3568_PMU_GRF_IO_VSEL2 (0x0148)
0057
0058 struct rockchip_iodomain;
0059
0060 struct rockchip_iodomain_supply {
0061 struct rockchip_iodomain *iod;
0062 struct regulator *reg;
0063 struct notifier_block nb;
0064 int idx;
0065 };
0066
0067 struct rockchip_iodomain_soc_data {
0068 int grf_offset;
0069 const char *supply_names[MAX_SUPPLIES];
0070 void (*init)(struct rockchip_iodomain *iod);
0071 int (*write)(struct rockchip_iodomain_supply *supply, int uV);
0072 };
0073
0074 struct rockchip_iodomain {
0075 struct device *dev;
0076 struct regmap *grf;
0077 const struct rockchip_iodomain_soc_data *soc_data;
0078 struct rockchip_iodomain_supply supplies[MAX_SUPPLIES];
0079 int (*write)(struct rockchip_iodomain_supply *supply, int uV);
0080 };
0081
0082 static int rk3568_iodomain_write(struct rockchip_iodomain_supply *supply, int uV)
0083 {
0084 struct rockchip_iodomain *iod = supply->iod;
0085 u32 is_3v3 = uV > MAX_VOLTAGE_1_8;
0086 u32 val0, val1;
0087 int b;
0088
0089 switch (supply->idx) {
0090 case 0:
0091 break;
0092 case 1:
0093 b = supply->idx;
0094 val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b));
0095 b = supply->idx + 4;
0096 val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0);
0097
0098 regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL2, val0);
0099 regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL2, val1);
0100 break;
0101 case 3:
0102 break;
0103 case 2:
0104 case 4:
0105 case 5:
0106 case 6:
0107 case 7:
0108 case 8:
0109 b = supply->idx - 1;
0110 val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b));
0111 val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0);
0112
0113 regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL0, val0);
0114 regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL1, val1);
0115 break;
0116 default:
0117 return -EINVAL;
0118 }
0119
0120 return 0;
0121 }
0122
0123 static int rockchip_iodomain_write(struct rockchip_iodomain_supply *supply,
0124 int uV)
0125 {
0126 struct rockchip_iodomain *iod = supply->iod;
0127 u32 val;
0128 int ret;
0129
0130
0131 val = (uV > MAX_VOLTAGE_1_8) ? 0 : 1;
0132 val <<= supply->idx;
0133
0134
0135 val |= (BIT(supply->idx) << 16);
0136
0137 ret = regmap_write(iod->grf, iod->soc_data->grf_offset, val);
0138 if (ret)
0139 dev_err(iod->dev, "Couldn't write to GRF\n");
0140
0141 return ret;
0142 }
0143
0144 static int rockchip_iodomain_notify(struct notifier_block *nb,
0145 unsigned long event,
0146 void *data)
0147 {
0148 struct rockchip_iodomain_supply *supply =
0149 container_of(nb, struct rockchip_iodomain_supply, nb);
0150 int uV;
0151 int ret;
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166 if (event & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) {
0167 struct pre_voltage_change_data *pvc_data = data;
0168
0169 uV = max_t(unsigned long, pvc_data->old_uV, pvc_data->max_uV);
0170 } else if (event & (REGULATOR_EVENT_VOLTAGE_CHANGE |
0171 REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE)) {
0172 uV = (unsigned long)data;
0173 } else {
0174 return NOTIFY_OK;
0175 }
0176
0177 dev_dbg(supply->iod->dev, "Setting to %d\n", uV);
0178
0179 if (uV > MAX_VOLTAGE_3_3) {
0180 dev_err(supply->iod->dev, "Voltage too high: %d\n", uV);
0181
0182 if (event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE)
0183 return NOTIFY_BAD;
0184 }
0185
0186 ret = supply->iod->write(supply, uV);
0187 if (ret && event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE)
0188 return NOTIFY_BAD;
0189
0190 dev_dbg(supply->iod->dev, "Setting to %d done\n", uV);
0191 return NOTIFY_OK;
0192 }
0193
0194 static void px30_iodomain_init(struct rockchip_iodomain *iod)
0195 {
0196 int ret;
0197 u32 val;
0198
0199
0200 if (!iod->supplies[PX30_IO_VSEL_VCCIO6_SUPPLY_NUM].reg)
0201 return;
0202
0203
0204
0205
0206
0207 val = PX30_IO_VSEL_VCCIO6_SRC | (PX30_IO_VSEL_VCCIO6_SRC << 16);
0208 ret = regmap_write(iod->grf, PX30_IO_VSEL, val);
0209 if (ret < 0)
0210 dev_warn(iod->dev, "couldn't update vccio6 ctrl\n");
0211 }
0212
0213 static void rk3288_iodomain_init(struct rockchip_iodomain *iod)
0214 {
0215 int ret;
0216 u32 val;
0217
0218
0219 if (!iod->supplies[RK3288_SOC_FLASH_SUPPLY_NUM].reg)
0220 return;
0221
0222
0223
0224
0225
0226 val = RK3288_SOC_CON2_FLASH0 | (RK3288_SOC_CON2_FLASH0 << 16);
0227 ret = regmap_write(iod->grf, RK3288_SOC_CON2, val);
0228 if (ret < 0)
0229 dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
0230 }
0231
0232 static void rk3328_iodomain_init(struct rockchip_iodomain *iod)
0233 {
0234 int ret;
0235 u32 val;
0236
0237
0238 if (!iod->supplies[RK3328_SOC_VCCIO2_SUPPLY_NUM].reg)
0239 return;
0240
0241
0242
0243
0244
0245 val = RK3328_SOC_CON4_VCCIO2 | (RK3328_SOC_CON4_VCCIO2 << 16);
0246 ret = regmap_write(iod->grf, RK3328_SOC_CON4, val);
0247 if (ret < 0)
0248 dev_warn(iod->dev, "couldn't update vccio2 vsel ctrl\n");
0249 }
0250
0251 static void rk3368_iodomain_init(struct rockchip_iodomain *iod)
0252 {
0253 int ret;
0254 u32 val;
0255
0256
0257 if (!iod->supplies[RK3368_SOC_FLASH_SUPPLY_NUM].reg)
0258 return;
0259
0260
0261
0262
0263
0264 val = RK3368_SOC_CON15_FLASH0 | (RK3368_SOC_CON15_FLASH0 << 16);
0265 ret = regmap_write(iod->grf, RK3368_SOC_CON15, val);
0266 if (ret < 0)
0267 dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
0268 }
0269
0270 static void rk3399_pmu_iodomain_init(struct rockchip_iodomain *iod)
0271 {
0272 int ret;
0273 u32 val;
0274
0275
0276 if (!iod->supplies[RK3399_PMUGRF_VSEL_SUPPLY_NUM].reg)
0277 return;
0278
0279
0280
0281
0282
0283 val = RK3399_PMUGRF_CON0_VSEL | (RK3399_PMUGRF_CON0_VSEL << 16);
0284 ret = regmap_write(iod->grf, RK3399_PMUGRF_CON0, val);
0285 if (ret < 0)
0286 dev_warn(iod->dev, "couldn't update pmu io iodomain ctrl\n");
0287 }
0288
0289 static const struct rockchip_iodomain_soc_data soc_data_px30 = {
0290 .grf_offset = 0x180,
0291 .supply_names = {
0292 NULL,
0293 "vccio6",
0294 "vccio1",
0295 "vccio2",
0296 "vccio3",
0297 "vccio4",
0298 "vccio5",
0299 "vccio-oscgpi",
0300 },
0301 .init = px30_iodomain_init,
0302 };
0303
0304 static const struct rockchip_iodomain_soc_data soc_data_px30_pmu = {
0305 .grf_offset = 0x100,
0306 .supply_names = {
0307 NULL,
0308 NULL,
0309 NULL,
0310 NULL,
0311 NULL,
0312 NULL,
0313 NULL,
0314 NULL,
0315 NULL,
0316 NULL,
0317 NULL,
0318 NULL,
0319 NULL,
0320 NULL,
0321 "pmuio1",
0322 "pmuio2",
0323 },
0324 };
0325
0326
0327
0328
0329
0330 static const struct rockchip_iodomain_soc_data soc_data_rk3188 = {
0331 .grf_offset = 0x104,
0332 .supply_names = {
0333 NULL,
0334 NULL,
0335 NULL,
0336 NULL,
0337 NULL,
0338 NULL,
0339 NULL,
0340 NULL,
0341 "ap0",
0342 "ap1",
0343 "cif",
0344 "flash",
0345 "vccio0",
0346 "vccio1",
0347 "lcdc0",
0348 "lcdc1",
0349 },
0350 };
0351
0352 static const struct rockchip_iodomain_soc_data soc_data_rk3228 = {
0353 .grf_offset = 0x418,
0354 .supply_names = {
0355 "vccio1",
0356 "vccio2",
0357 "vccio3",
0358 "vccio4",
0359 },
0360 };
0361
0362 static const struct rockchip_iodomain_soc_data soc_data_rk3288 = {
0363 .grf_offset = 0x380,
0364 .supply_names = {
0365 "lcdc",
0366 "dvp",
0367 "flash0",
0368 "flash1",
0369 "wifi",
0370 "bb",
0371 "audio",
0372 "sdcard",
0373 "gpio30",
0374 "gpio1830",
0375 },
0376 .init = rk3288_iodomain_init,
0377 };
0378
0379 static const struct rockchip_iodomain_soc_data soc_data_rk3328 = {
0380 .grf_offset = 0x410,
0381 .supply_names = {
0382 "vccio1",
0383 "vccio2",
0384 "vccio3",
0385 "vccio4",
0386 "vccio5",
0387 "vccio6",
0388 "pmuio",
0389 },
0390 .init = rk3328_iodomain_init,
0391 };
0392
0393 static const struct rockchip_iodomain_soc_data soc_data_rk3368 = {
0394 .grf_offset = 0x900,
0395 .supply_names = {
0396 NULL,
0397 "dvp",
0398 "flash0",
0399 "wifi",
0400 NULL,
0401 "audio",
0402 "sdcard",
0403 "gpio30",
0404 "gpio1830",
0405 },
0406 .init = rk3368_iodomain_init,
0407 };
0408
0409 static const struct rockchip_iodomain_soc_data soc_data_rk3368_pmu = {
0410 .grf_offset = 0x100,
0411 .supply_names = {
0412 NULL,
0413 NULL,
0414 NULL,
0415 NULL,
0416 "pmu",
0417 "vop",
0418 },
0419 };
0420
0421 static const struct rockchip_iodomain_soc_data soc_data_rk3399 = {
0422 .grf_offset = 0xe640,
0423 .supply_names = {
0424 "bt656",
0425 "audio",
0426 "sdmmc",
0427 "gpio1830",
0428 },
0429 };
0430
0431 static const struct rockchip_iodomain_soc_data soc_data_rk3399_pmu = {
0432 .grf_offset = 0x180,
0433 .supply_names = {
0434 NULL,
0435 NULL,
0436 NULL,
0437 NULL,
0438 NULL,
0439 NULL,
0440 NULL,
0441 NULL,
0442 NULL,
0443 "pmu1830",
0444 },
0445 .init = rk3399_pmu_iodomain_init,
0446 };
0447
0448 static const struct rockchip_iodomain_soc_data soc_data_rk3568_pmu = {
0449 .grf_offset = 0x140,
0450 .supply_names = {
0451 "pmuio1",
0452 "pmuio2",
0453 "vccio1",
0454 "vccio2",
0455 "vccio3",
0456 "vccio4",
0457 "vccio5",
0458 "vccio6",
0459 "vccio7",
0460 },
0461 .write = rk3568_iodomain_write,
0462 };
0463
0464 static const struct rockchip_iodomain_soc_data soc_data_rv1108 = {
0465 .grf_offset = 0x404,
0466 .supply_names = {
0467 NULL,
0468 NULL,
0469 NULL,
0470 NULL,
0471 NULL,
0472 NULL,
0473 NULL,
0474 NULL,
0475 NULL,
0476 NULL,
0477 NULL,
0478 "vccio1",
0479 "vccio2",
0480 "vccio3",
0481 "vccio5",
0482 "vccio6",
0483 },
0484
0485 };
0486
0487 static const struct rockchip_iodomain_soc_data soc_data_rv1108_pmu = {
0488 .grf_offset = 0x104,
0489 .supply_names = {
0490 "pmu",
0491 },
0492 };
0493
0494 static const struct of_device_id rockchip_iodomain_match[] = {
0495 {
0496 .compatible = "rockchip,px30-io-voltage-domain",
0497 .data = (void *)&soc_data_px30
0498 },
0499 {
0500 .compatible = "rockchip,px30-pmu-io-voltage-domain",
0501 .data = (void *)&soc_data_px30_pmu
0502 },
0503 {
0504 .compatible = "rockchip,rk3188-io-voltage-domain",
0505 .data = &soc_data_rk3188
0506 },
0507 {
0508 .compatible = "rockchip,rk3228-io-voltage-domain",
0509 .data = &soc_data_rk3228
0510 },
0511 {
0512 .compatible = "rockchip,rk3288-io-voltage-domain",
0513 .data = &soc_data_rk3288
0514 },
0515 {
0516 .compatible = "rockchip,rk3328-io-voltage-domain",
0517 .data = &soc_data_rk3328
0518 },
0519 {
0520 .compatible = "rockchip,rk3368-io-voltage-domain",
0521 .data = &soc_data_rk3368
0522 },
0523 {
0524 .compatible = "rockchip,rk3368-pmu-io-voltage-domain",
0525 .data = &soc_data_rk3368_pmu
0526 },
0527 {
0528 .compatible = "rockchip,rk3399-io-voltage-domain",
0529 .data = &soc_data_rk3399
0530 },
0531 {
0532 .compatible = "rockchip,rk3399-pmu-io-voltage-domain",
0533 .data = &soc_data_rk3399_pmu
0534 },
0535 {
0536 .compatible = "rockchip,rk3568-pmu-io-voltage-domain",
0537 .data = &soc_data_rk3568_pmu
0538 },
0539 {
0540 .compatible = "rockchip,rv1108-io-voltage-domain",
0541 .data = &soc_data_rv1108
0542 },
0543 {
0544 .compatible = "rockchip,rv1108-pmu-io-voltage-domain",
0545 .data = &soc_data_rv1108_pmu
0546 },
0547 { },
0548 };
0549 MODULE_DEVICE_TABLE(of, rockchip_iodomain_match);
0550
0551 static int rockchip_iodomain_probe(struct platform_device *pdev)
0552 {
0553 struct device_node *np = pdev->dev.of_node;
0554 const struct of_device_id *match;
0555 struct rockchip_iodomain *iod;
0556 struct device *parent;
0557 int i, ret = 0;
0558
0559 if (!np)
0560 return -ENODEV;
0561
0562 iod = devm_kzalloc(&pdev->dev, sizeof(*iod), GFP_KERNEL);
0563 if (!iod)
0564 return -ENOMEM;
0565
0566 iod->dev = &pdev->dev;
0567 platform_set_drvdata(pdev, iod);
0568
0569 match = of_match_node(rockchip_iodomain_match, np);
0570 iod->soc_data = match->data;
0571
0572 if (iod->soc_data->write)
0573 iod->write = iod->soc_data->write;
0574 else
0575 iod->write = rockchip_iodomain_write;
0576
0577 parent = pdev->dev.parent;
0578 if (parent && parent->of_node) {
0579 iod->grf = syscon_node_to_regmap(parent->of_node);
0580 } else {
0581 dev_dbg(&pdev->dev, "falling back to old binding\n");
0582 iod->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
0583 }
0584
0585 if (IS_ERR(iod->grf)) {
0586 dev_err(&pdev->dev, "couldn't find grf regmap\n");
0587 return PTR_ERR(iod->grf);
0588 }
0589
0590 for (i = 0; i < MAX_SUPPLIES; i++) {
0591 const char *supply_name = iod->soc_data->supply_names[i];
0592 struct rockchip_iodomain_supply *supply = &iod->supplies[i];
0593 struct regulator *reg;
0594 int uV;
0595
0596 if (!supply_name)
0597 continue;
0598
0599 reg = devm_regulator_get_optional(iod->dev, supply_name);
0600 if (IS_ERR(reg)) {
0601 ret = PTR_ERR(reg);
0602
0603
0604 if (ret == -ENODEV)
0605 continue;
0606 else if (ret != -EPROBE_DEFER)
0607 dev_err(iod->dev, "couldn't get regulator %s\n",
0608 supply_name);
0609 goto unreg_notify;
0610 }
0611
0612
0613 uV = regulator_get_voltage(reg);
0614
0615
0616 if (uV < 0) {
0617 dev_err(iod->dev, "Can't determine voltage: %s\n",
0618 supply_name);
0619 ret = uV;
0620 goto unreg_notify;
0621 }
0622
0623 if (uV > MAX_VOLTAGE_3_3) {
0624 dev_crit(iod->dev,
0625 "%d uV is too high. May damage SoC!\n",
0626 uV);
0627 ret = -EINVAL;
0628 goto unreg_notify;
0629 }
0630
0631
0632 supply->idx = i;
0633 supply->iod = iod;
0634 supply->reg = reg;
0635 supply->nb.notifier_call = rockchip_iodomain_notify;
0636
0637 ret = iod->write(supply, uV);
0638 if (ret) {
0639 supply->reg = NULL;
0640 goto unreg_notify;
0641 }
0642
0643
0644 ret = regulator_register_notifier(reg, &supply->nb);
0645 if (ret) {
0646 dev_err(&pdev->dev,
0647 "regulator notifier request failed\n");
0648 supply->reg = NULL;
0649 goto unreg_notify;
0650 }
0651 }
0652
0653 if (iod->soc_data->init)
0654 iod->soc_data->init(iod);
0655
0656 return 0;
0657
0658 unreg_notify:
0659 for (i = MAX_SUPPLIES - 1; i >= 0; i--) {
0660 struct rockchip_iodomain_supply *io_supply = &iod->supplies[i];
0661
0662 if (io_supply->reg)
0663 regulator_unregister_notifier(io_supply->reg,
0664 &io_supply->nb);
0665 }
0666
0667 return ret;
0668 }
0669
0670 static int rockchip_iodomain_remove(struct platform_device *pdev)
0671 {
0672 struct rockchip_iodomain *iod = platform_get_drvdata(pdev);
0673 int i;
0674
0675 for (i = MAX_SUPPLIES - 1; i >= 0; i--) {
0676 struct rockchip_iodomain_supply *io_supply = &iod->supplies[i];
0677
0678 if (io_supply->reg)
0679 regulator_unregister_notifier(io_supply->reg,
0680 &io_supply->nb);
0681 }
0682
0683 return 0;
0684 }
0685
0686 static struct platform_driver rockchip_iodomain_driver = {
0687 .probe = rockchip_iodomain_probe,
0688 .remove = rockchip_iodomain_remove,
0689 .driver = {
0690 .name = "rockchip-iodomain",
0691 .of_match_table = rockchip_iodomain_match,
0692 },
0693 };
0694
0695 module_platform_driver(rockchip_iodomain_driver);
0696
0697 MODULE_DESCRIPTION("Rockchip IO-domain driver");
0698 MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
0699 MODULE_AUTHOR("Doug Anderson <dianders@chromium.org>");
0700 MODULE_LICENSE("GPL v2");