aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-10-07 11:35:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-07 11:35:35 -0400
commitd042380886fb2fc6c4b0fcfe1214ba473769a8e9 (patch)
tree61e29ff167e0f83f67930ee9911062415030e1ef /drivers/regulator
parent3477d168ba61c5b0ca42d3d4642f3463609a5417 (diff)
parentb8d336ed90f541097a2ce583be430bb3e895dfbd (diff)
Merge tag 'mfd-for-linus-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones: "Core framework: - Add the MFD bindings doc to MAINTAINERS New drivers: - X-Powers AC100 Audio CODEC and RTC - TI LP873x PMIC - Rockchip RK808 PMIC - Samsung Exynos Low Power Audio New device support: - Add support for STMPE1600 variant to stmpe - Add support for PM8018 PMIC to pm8921-core - Add support for AXP806 PMIC in axp20x - Add support for AXP209 GPIO in axp20x New functionality: - Add support for Reset to all STMPE variants - Add support for MKBP event support to cros_ec - Add support for USB to intel_soc_pmic_bxtwc - Add support for IRQs and Power Button to tps65217 Fix-ups: - Clean-up defunct author emails (da9063, max14577) - Kconfig fixups (wm8350-i2c, as37220 - Constify (altera-a10sr, sm501) - Supply PCI IDs (intel-lpss-pci) - Improve clocking (qcom_rpm) - Fix IRQ probing (ucb1x00-core) - Ensure fault log is cleared (da9052) - Remove NO_IRQ check (ucb1x00-core) - Supply I2C properties (intel-lpss-acpi, intel-lpss-pci) - Non standard declaration (tps65217, max8997-irq) - Remove unused code (lp873x, db8500-prcmu, ab8500-debugfs, cros_ec_spi) - Make non-modular (altera-a10sr, intel_msic, smsc-ece1099, sun6i-prcm, twl-core) - OF bindings (ac100, stmpe, qcom-pm8xxx, qcom-rpm, rk808, axp20x, lp873x, exynos5433-lpass, act8945a, aspeed-scu, twl6040, arizona) Bugfixes: - Release OF pointer (qcom_rpm) - Avoid double shifting in suspend/resume (88pm80x) - Fix 'defined but not used' error (exynos-lpass) - Fix 'sleeping whilst attomic' (atmel-hlcdc)" * tag 'mfd-for-linus-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (69 commits) mfd: arizona: Handle probe deferral for reset GPIO mfd: arizona: Remove arizona_of_get_named_gpio helper function mfd: arizona: Add DT options for max_channels_clocked and PDM speaker config mfd: twl6040: Register child device for twl6040-pdmclk mfd: cros_ec_spi: Remove unused variable 'request' mfd: omap-usb-host: Return value is not 'const int' mfd: ab8500-debugfs: Remove 'weak' function suspend_test_wake_cause_interrupt_is_mine() mfd: ab8500-debugfs: Remove ab8500_dump_all_banks_to_mem() mfd: db8500-prcmu: Remove unused *prcmu_set_ddr_opp() calls mfd: ab8500-debugfs: Prevent initialised field from being over-written mfd: max8997-irq: 'inline' should be at the beginning of the declaration mfd: rk808: Fix RK818_IRQ_DISCHG_ILIM initializer mfd: tps65217: Fix nonstandard declaration mfd: lp873x: Remove unused mutex lock from struct lp873x mfd: atmel-hlcdc: Do not sleep in atomic context mfd: exynos-lpass: Mark PM functions as __maybe_unused mfd: intel-lpss: Add default I2C device properties for Apollo Lake mfd: twl-core: Make it explicitly non-modular mfd: sun6i-prcm: Make it explicitly non-modular mfd: smsc-ece1099: Make it explicitly non-modular ...
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/Kconfig4
-rw-r--r--drivers/regulator/axp20x-regulator.c118
-rw-r--r--drivers/regulator/qcom_rpm-regulator.c66
-rw-r--r--drivers/regulator/rk808-regulator.c143
4 files changed, 315 insertions, 16 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 06c75186af80..936f7ccc9736 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -643,11 +643,11 @@ config REGULATOR_RC5T583
643 outputs which can be controlled by i2c communication. 643 outputs which can be controlled by i2c communication.
644 644
645config REGULATOR_RK808 645config REGULATOR_RK808
646 tristate "Rockchip RK808 Power regulators" 646 tristate "Rockchip RK808/RK818 Power regulators"
647 depends on MFD_RK808 647 depends on MFD_RK808
648 help 648 help
649 Select this option to enable the power regulator of ROCKCHIP 649 Select this option to enable the power regulator of ROCKCHIP
650 PMIC RK808. 650 PMIC RK808 and RK818.
651 This driver supports the control of different power rails of device 651 This driver supports the control of different power rails of device
652 through regulator interface. The device supports multiple DCDC/LDO 652 through regulator interface. The device supports multiple DCDC/LDO
653 outputs which can be controlled by i2c communication. 653 outputs which can be controlled by i2c communication.
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 6d9ac76a772f..54382ef902c6 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -244,16 +244,64 @@ static const struct regulator_desc axp22x_drivevbus_regulator = {
244 .ops = &axp20x_ops_sw, 244 .ops = &axp20x_ops_sw,
245}; 245};
246 246
247static const struct regulator_linear_range axp809_dcdc4_ranges[] = { 247static const struct regulator_linear_range axp806_dcdca_ranges[] = {
248 REGULATOR_LINEAR_RANGE(600000, 0x0, 0x2f, 20000), 248 REGULATOR_LINEAR_RANGE(600000, 0x0, 0x32, 10000),
249 REGULATOR_LINEAR_RANGE(1800000, 0x30, 0x38, 100000), 249 REGULATOR_LINEAR_RANGE(1120000, 0x33, 0x47, 20000),
250}; 250};
251 251
252static const struct regulator_linear_range axp809_dldo1_ranges[] = { 252static const struct regulator_linear_range axp806_dcdcd_ranges[] = {
253 REGULATOR_LINEAR_RANGE(600000, 0x0, 0x2d, 20000),
254 REGULATOR_LINEAR_RANGE(1600000, 0x2e, 0x3f, 100000),
255};
256
257static const struct regulator_linear_range axp806_cldo2_ranges[] = {
253 REGULATOR_LINEAR_RANGE(700000, 0x0, 0x1a, 100000), 258 REGULATOR_LINEAR_RANGE(700000, 0x0, 0x1a, 100000),
254 REGULATOR_LINEAR_RANGE(3400000, 0x1b, 0x1f, 200000), 259 REGULATOR_LINEAR_RANGE(3400000, 0x1b, 0x1f, 200000),
255}; 260};
256 261
262static const struct regulator_desc axp806_regulators[] = {
263 AXP_DESC_RANGES(AXP806, DCDCA, "dcdca", "vina", axp806_dcdca_ranges,
264 72, AXP806_DCDCA_V_CTRL, 0x7f, AXP806_PWR_OUT_CTRL1,
265 BIT(0)),
266 AXP_DESC(AXP806, DCDCB, "dcdcb", "vinb", 1000, 2550, 50,
267 AXP806_DCDCB_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(1)),
268 AXP_DESC_RANGES(AXP806, DCDCC, "dcdcc", "vinc", axp806_dcdca_ranges,
269 72, AXP806_DCDCC_V_CTRL, 0x7f, AXP806_PWR_OUT_CTRL1,
270 BIT(2)),
271 AXP_DESC_RANGES(AXP806, DCDCD, "dcdcd", "vind", axp806_dcdcd_ranges,
272 64, AXP806_DCDCD_V_CTRL, 0x3f, AXP806_PWR_OUT_CTRL1,
273 BIT(3)),
274 AXP_DESC(AXP806, DCDCE, "dcdce", "vine", 1100, 3400, 100,
275 AXP806_DCDCB_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(4)),
276 AXP_DESC(AXP806, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
277 AXP806_ALDO1_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(5)),
278 AXP_DESC(AXP806, ALDO2, "aldo2", "aldoin", 700, 3400, 100,
279 AXP806_ALDO2_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(6)),
280 AXP_DESC(AXP806, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
281 AXP806_ALDO3_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(7)),
282 AXP_DESC(AXP806, BLDO1, "bldo1", "bldoin", 700, 1900, 100,
283 AXP806_BLDO1_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(0)),
284 AXP_DESC(AXP806, BLDO2, "bldo2", "bldoin", 700, 1900, 100,
285 AXP806_BLDO2_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(1)),
286 AXP_DESC(AXP806, BLDO3, "bldo3", "bldoin", 700, 1900, 100,
287 AXP806_BLDO3_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(2)),
288 AXP_DESC(AXP806, BLDO4, "bldo4", "bldoin", 700, 1900, 100,
289 AXP806_BLDO4_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(3)),
290 AXP_DESC(AXP806, CLDO1, "cldo1", "cldoin", 700, 3300, 100,
291 AXP806_CLDO1_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2, BIT(4)),
292 AXP_DESC_RANGES(AXP806, CLDO2, "cldo2", "cldoin", axp806_cldo2_ranges,
293 32, AXP806_CLDO2_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2,
294 BIT(5)),
295 AXP_DESC(AXP806, CLDO3, "cldo3", "cldoin", 700, 3300, 100,
296 AXP806_CLDO3_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2, BIT(6)),
297 AXP_DESC_SW(AXP806, SW, "sw", "swin", AXP806_PWR_OUT_CTRL2, BIT(7)),
298};
299
300static const struct regulator_linear_range axp809_dcdc4_ranges[] = {
301 REGULATOR_LINEAR_RANGE(600000, 0x0, 0x2f, 20000),
302 REGULATOR_LINEAR_RANGE(1800000, 0x30, 0x38, 100000),
303};
304
257static const struct regulator_desc axp809_regulators[] = { 305static const struct regulator_desc axp809_regulators[] = {
258 AXP_DESC(AXP809, DCDC1, "dcdc1", "vin1", 1600, 3400, 100, 306 AXP_DESC(AXP809, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
259 AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(1)), 307 AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(1)),
@@ -278,7 +326,7 @@ static const struct regulator_desc axp809_regulators[] = {
278 AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(7)), 326 AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(7)),
279 AXP_DESC(AXP809, ALDO3, "aldo3", "aldoin", 700, 3300, 100, 327 AXP_DESC(AXP809, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
280 AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)), 328 AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
281 AXP_DESC_RANGES(AXP809, DLDO1, "dldo1", "dldoin", axp809_dldo1_ranges, 329 AXP_DESC_RANGES(AXP809, DLDO1, "dldo1", "dldoin", axp806_cldo2_ranges,
282 32, AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, 330 32, AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
283 BIT(3)), 331 BIT(3)),
284 AXP_DESC(AXP809, DLDO2, "dldo2", "dldoin", 700, 3300, 100, 332 AXP_DESC(AXP809, DLDO2, "dldo2", "dldoin", 700, 3300, 100,
@@ -302,6 +350,7 @@ static const struct regulator_desc axp809_regulators[] = {
302static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) 350static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
303{ 351{
304 struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); 352 struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
353 unsigned int reg = AXP20X_DCDC_FREQ;
305 u32 min, max, def, step; 354 u32 min, max, def, step;
306 355
307 switch (axp20x->variant) { 356 switch (axp20x->variant) {
@@ -312,6 +361,14 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
312 def = 1500; 361 def = 1500;
313 step = 75; 362 step = 75;
314 break; 363 break;
364 case AXP806_ID:
365 /*
366 * AXP806 DCDC work frequency setting has the same range and
367 * step as AXP22X, but at a different register.
368 * Fall through to the check below.
369 * (See include/linux/mfd/axp20x.h)
370 */
371 reg = AXP806_DCDC_FREQ_CTRL;
315 case AXP221_ID: 372 case AXP221_ID:
316 case AXP223_ID: 373 case AXP223_ID:
317 case AXP809_ID: 374 case AXP809_ID:
@@ -343,7 +400,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
343 400
344 dcdcfreq = (dcdcfreq - min) / step; 401 dcdcfreq = (dcdcfreq - min) / step;
345 402
346 return regmap_update_bits(axp20x->regmap, AXP20X_DCDC_FREQ, 403 return regmap_update_bits(axp20x->regmap, reg,
347 AXP20X_FREQ_DCDC_MASK, dcdcfreq); 404 AXP20X_FREQ_DCDC_MASK, dcdcfreq);
348} 405}
349 406
@@ -377,6 +434,7 @@ static int axp20x_regulator_parse_dt(struct platform_device *pdev)
377static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode) 434static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode)
378{ 435{
379 struct axp20x_dev *axp20x = rdev_get_drvdata(rdev); 436 struct axp20x_dev *axp20x = rdev_get_drvdata(rdev);
437 unsigned int reg = AXP20X_DCDC_MODE;
380 unsigned int mask; 438 unsigned int mask;
381 439
382 switch (axp20x->variant) { 440 switch (axp20x->variant) {
@@ -392,6 +450,13 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work
392 workmode <<= ffs(mask) - 1; 450 workmode <<= ffs(mask) - 1;
393 break; 451 break;
394 452
453 case AXP806_ID:
454 reg = AXP806_DCDC_MODE_CTRL2;
455 /*
456 * AXP806 DCDC regulator IDs have the same range as AXP22X.
457 * Fall through to the check below.
458 * (See include/linux/mfd/axp20x.h)
459 */
395 case AXP221_ID: 460 case AXP221_ID:
396 case AXP223_ID: 461 case AXP223_ID:
397 case AXP809_ID: 462 case AXP809_ID:
@@ -408,7 +473,34 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work
408 return -EINVAL; 473 return -EINVAL;
409 } 474 }
410 475
411 return regmap_update_bits(rdev->regmap, AXP20X_DCDC_MODE, mask, workmode); 476 return regmap_update_bits(rdev->regmap, reg, mask, workmode);
477}
478
479/*
480 * This function checks whether a regulator is part of a poly-phase
481 * output setup based on the registers settings. Returns true if it is.
482 */
483static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id)
484{
485 u32 reg = 0;
486
487 /* Only AXP806 has poly-phase outputs */
488 if (axp20x->variant != AXP806_ID)
489 return false;
490
491 regmap_read(axp20x->regmap, AXP806_DCDC_MODE_CTRL2, &reg);
492
493 switch (id) {
494 case AXP806_DCDCB:
495 return (((reg & GENMASK(7, 6)) == BIT(6)) ||
496 ((reg & GENMASK(7, 6)) == BIT(7)));
497 case AXP806_DCDCC:
498 return ((reg & GENMASK(7, 6)) == BIT(7));
499 case AXP806_DCDCE:
500 return !!(reg & BIT(5));
501 }
502
503 return false;
412} 504}
413 505
414static int axp20x_regulator_probe(struct platform_device *pdev) 506static int axp20x_regulator_probe(struct platform_device *pdev)
@@ -440,6 +532,10 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
440 drivevbus = of_property_read_bool(pdev->dev.parent->of_node, 532 drivevbus = of_property_read_bool(pdev->dev.parent->of_node,
441 "x-powers,drive-vbus-en"); 533 "x-powers,drive-vbus-en");
442 break; 534 break;
535 case AXP806_ID:
536 regulators = axp806_regulators;
537 nregulators = AXP806_REG_ID_MAX;
538 break;
443 case AXP809_ID: 539 case AXP809_ID:
444 regulators = axp809_regulators; 540 regulators = axp809_regulators;
445 nregulators = AXP809_REG_ID_MAX; 541 nregulators = AXP809_REG_ID_MAX;
@@ -458,6 +554,14 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
458 struct regulator_desc *new_desc; 554 struct regulator_desc *new_desc;
459 555
460 /* 556 /*
557 * If this regulator is a slave in a poly-phase setup,
558 * skip it, as its controls are bound to the master
559 * regulator and won't work.
560 */
561 if (axp20x_is_polyphase_slave(axp20x, i))
562 continue;
563
564 /*
461 * Regulators DC1SW and DC5LDO are connected internally, 565 * Regulators DC1SW and DC5LDO are connected internally,
462 * so we have to handle their supply names separately. 566 * so we have to handle their supply names separately.
463 * 567 *
diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c
index e254272585b2..1b2acc43fea1 100644
--- a/drivers/regulator/qcom_rpm-regulator.c
+++ b/drivers/regulator/qcom_rpm-regulator.c
@@ -448,6 +448,44 @@ static struct regulator_ops switch_ops = {
448}; 448};
449 449
450/* 450/*
451 * PM8018 regulators
452 */
453static const struct qcom_rpm_reg pm8018_pldo = {
454 .desc.linear_ranges = pldo_ranges,
455 .desc.n_linear_ranges = ARRAY_SIZE(pldo_ranges),
456 .desc.n_voltages = 161,
457 .desc.ops = &uV_ops,
458 .parts = &rpm8960_ldo_parts,
459 .supports_force_mode_auto = false,
460 .supports_force_mode_bypass = false,
461};
462
463static const struct qcom_rpm_reg pm8018_nldo = {
464 .desc.linear_ranges = nldo_ranges,
465 .desc.n_linear_ranges = ARRAY_SIZE(nldo_ranges),
466 .desc.n_voltages = 64,
467 .desc.ops = &uV_ops,
468 .parts = &rpm8960_ldo_parts,
469 .supports_force_mode_auto = false,
470 .supports_force_mode_bypass = false,
471};
472
473static const struct qcom_rpm_reg pm8018_smps = {
474 .desc.linear_ranges = smps_ranges,
475 .desc.n_linear_ranges = ARRAY_SIZE(smps_ranges),
476 .desc.n_voltages = 154,
477 .desc.ops = &uV_ops,
478 .parts = &rpm8960_smps_parts,
479 .supports_force_mode_auto = false,
480 .supports_force_mode_bypass = false,
481};
482
483static const struct qcom_rpm_reg pm8018_switch = {
484 .desc.ops = &switch_ops,
485 .parts = &rpm8960_switch_parts,
486};
487
488/*
451 * PM8058 regulators 489 * PM8058 regulators
452 */ 490 */
453static const struct qcom_rpm_reg pm8058_pldo = { 491static const struct qcom_rpm_reg pm8058_pldo = {
@@ -755,6 +793,32 @@ struct rpm_regulator_data {
755 const char *supply; 793 const char *supply;
756}; 794};
757 795
796static const struct rpm_regulator_data rpm_pm8018_regulators[] = {
797 { "s1", QCOM_RPM_PM8018_SMPS1, &pm8018_smps, "vdd_s1" },
798 { "s2", QCOM_RPM_PM8018_SMPS2, &pm8018_smps, "vdd_s2" },
799 { "s3", QCOM_RPM_PM8018_SMPS3, &pm8018_smps, "vdd_s3" },
800 { "s4", QCOM_RPM_PM8018_SMPS4, &pm8018_smps, "vdd_s4" },
801 { "s5", QCOM_RPM_PM8018_SMPS5, &pm8018_smps, "vdd_s5" },
802
803 { "l2", QCOM_RPM_PM8018_LDO2, &pm8018_pldo, "vdd_l2" },
804 { "l3", QCOM_RPM_PM8018_LDO3, &pm8018_pldo, "vdd_l3" },
805 { "l4", QCOM_RPM_PM8018_LDO4, &pm8018_pldo, "vdd_l4" },
806 { "l5", QCOM_RPM_PM8018_LDO5, &pm8018_pldo, "vdd_l5" },
807 { "l6", QCOM_RPM_PM8018_LDO6, &pm8018_pldo, "vdd_l7" },
808 { "l7", QCOM_RPM_PM8018_LDO7, &pm8018_pldo, "vdd_l7" },
809 { "l8", QCOM_RPM_PM8018_LDO8, &pm8018_nldo, "vdd_l8" },
810 { "l9", QCOM_RPM_PM8018_LDO9, &pm8921_nldo1200,
811 "vdd_l9_l10_l11_l12" },
812 { "l10", QCOM_RPM_PM8018_LDO10, &pm8018_nldo, "vdd_l9_l10_l11_l12" },
813 { "l11", QCOM_RPM_PM8018_LDO11, &pm8018_nldo, "vdd_l9_l10_l11_l12" },
814 { "l12", QCOM_RPM_PM8018_LDO12, &pm8018_nldo, "vdd_l9_l10_l11_l12" },
815 { "l14", QCOM_RPM_PM8018_LDO14, &pm8018_pldo, "vdd_l14" },
816
817 { "lvs1", QCOM_RPM_PM8018_LVS1, &pm8018_switch, "lvs1_in" },
818
819 { }
820};
821
758static const struct rpm_regulator_data rpm_pm8058_regulators[] = { 822static const struct rpm_regulator_data rpm_pm8058_regulators[] = {
759 { "l0", QCOM_RPM_PM8058_LDO0, &pm8058_nldo, "vdd_l0_l1_lvs" }, 823 { "l0", QCOM_RPM_PM8058_LDO0, &pm8058_nldo, "vdd_l0_l1_lvs" },
760 { "l1", QCOM_RPM_PM8058_LDO1, &pm8058_nldo, "vdd_l0_l1_lvs" }, 824 { "l1", QCOM_RPM_PM8058_LDO1, &pm8058_nldo, "vdd_l0_l1_lvs" },
@@ -870,6 +934,8 @@ static const struct rpm_regulator_data rpm_pm8921_regulators[] = {
870}; 934};
871 935
872static const struct of_device_id rpm_of_match[] = { 936static const struct of_device_id rpm_of_match[] = {
937 { .compatible = "qcom,rpm-pm8018-regulators",
938 .data = &rpm_pm8018_regulators },
873 { .compatible = "qcom,rpm-pm8058-regulators", .data = &rpm_pm8058_regulators }, 939 { .compatible = "qcom,rpm-pm8058-regulators", .data = &rpm_pm8058_regulators },
874 { .compatible = "qcom,rpm-pm8901-regulators", .data = &rpm_pm8901_regulators }, 940 { .compatible = "qcom,rpm-pm8901-regulators", .data = &rpm_pm8901_regulators },
875 { .compatible = "qcom,rpm-pm8921-regulators", .data = &rpm_pm8921_regulators }, 941 { .compatible = "qcom,rpm-pm8921-regulators", .data = &rpm_pm8921_regulators },
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index a6767494d39b..3314bf299a51 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -1,11 +1,15 @@
1/* 1/*
2 * Regulator driver for Rockchip RK808 2 * Regulator driver for Rockchip RK808/RK818
3 * 3 *
4 * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd 4 * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
5 * 5 *
6 * Author: Chris Zhong <zyw@rock-chips.com> 6 * Author: Chris Zhong <zyw@rock-chips.com>
7 * Author: Zhang Qing <zhangqing@rock-chips.com> 7 * Author: Zhang Qing <zhangqing@rock-chips.com>
8 * 8 *
9 * Copyright (C) 2016 PHYTEC Messtechnik GmbH
10 *
11 * Author: Wadim Egorov <w.egorov@phytec.de>
12 *
9 * This program is free software; you can redistribute it and/or modify it 13 * This program is free software; you can redistribute it and/or modify it
10 * under the terms and conditions of the GNU General Public License, 14 * under the terms and conditions of the GNU General Public License,
11 * version 2, as published by the Free Software Foundation. 15 * version 2, as published by the Free Software Foundation.
@@ -32,6 +36,12 @@
32#define RK808_BUCK4_VSEL_MASK 0xf 36#define RK808_BUCK4_VSEL_MASK 0xf
33#define RK808_LDO_VSEL_MASK 0x1f 37#define RK808_LDO_VSEL_MASK 0x1f
34 38
39#define RK818_BUCK_VSEL_MASK 0x3f
40#define RK818_BUCK4_VSEL_MASK 0x1f
41#define RK818_LDO_VSEL_MASK 0x1f
42#define RK818_LDO3_ON_VSEL_MASK 0xf
43#define RK818_BOOST_ON_VSEL_MASK 0xe0
44
35/* Ramp rate definitions for buck1 / buck2 only */ 45/* Ramp rate definitions for buck1 / buck2 only */
36#define RK808_RAMP_RATE_OFFSET 3 46#define RK808_RAMP_RATE_OFFSET 3
37#define RK808_RAMP_RATE_MASK (3 << RK808_RAMP_RATE_OFFSET) 47#define RK808_RAMP_RATE_MASK (3 << RK808_RAMP_RATE_OFFSET)
@@ -454,6 +464,108 @@ static const struct regulator_desc rk808_reg[] = {
454 RK808_DCDC_EN_REG, BIT(6)), 464 RK808_DCDC_EN_REG, BIT(6)),
455}; 465};
456 466
467static const struct regulator_desc rk818_reg[] = {
468 {
469 .name = "DCDC_REG1",
470 .supply_name = "vcc1",
471 .of_match = of_match_ptr("DCDC_REG1"),
472 .regulators_node = of_match_ptr("regulators"),
473 .id = RK818_ID_DCDC1,
474 .ops = &rk808_reg_ops,
475 .type = REGULATOR_VOLTAGE,
476 .min_uV = 712500,
477 .uV_step = 12500,
478 .n_voltages = 64,
479 .vsel_reg = RK818_BUCK1_ON_VSEL_REG,
480 .vsel_mask = RK818_BUCK_VSEL_MASK,
481 .enable_reg = RK818_DCDC_EN_REG,
482 .enable_mask = BIT(0),
483 .owner = THIS_MODULE,
484 }, {
485 .name = "DCDC_REG2",
486 .supply_name = "vcc2",
487 .of_match = of_match_ptr("DCDC_REG2"),
488 .regulators_node = of_match_ptr("regulators"),
489 .id = RK818_ID_DCDC2,
490 .ops = &rk808_reg_ops,
491 .type = REGULATOR_VOLTAGE,
492 .min_uV = 712500,
493 .uV_step = 12500,
494 .n_voltages = 64,
495 .vsel_reg = RK818_BUCK2_ON_VSEL_REG,
496 .vsel_mask = RK818_BUCK_VSEL_MASK,
497 .enable_reg = RK818_DCDC_EN_REG,
498 .enable_mask = BIT(1),
499 .owner = THIS_MODULE,
500 }, {
501 .name = "DCDC_REG3",
502 .supply_name = "vcc3",
503 .of_match = of_match_ptr("DCDC_REG3"),
504 .regulators_node = of_match_ptr("regulators"),
505 .id = RK818_ID_DCDC3,
506 .ops = &rk808_switch_ops,
507 .type = REGULATOR_VOLTAGE,
508 .n_voltages = 1,
509 .enable_reg = RK818_DCDC_EN_REG,
510 .enable_mask = BIT(2),
511 .owner = THIS_MODULE,
512 },
513 RK8XX_DESC(RK818_ID_DCDC4, "DCDC_REG4", "vcc4", 1800, 3600, 100,
514 RK818_BUCK4_ON_VSEL_REG, RK818_BUCK4_VSEL_MASK,
515 RK818_DCDC_EN_REG, BIT(3), 0),
516 RK8XX_DESC(RK818_ID_BOOST, "DCDC_BOOST", "boost", 4700, 5400, 100,
517 RK818_BOOST_LDO9_ON_VSEL_REG, RK818_BOOST_ON_VSEL_MASK,
518 RK818_DCDC_EN_REG, BIT(4), 0),
519 RK8XX_DESC(RK818_ID_LDO1, "LDO_REG1", "vcc6", 1800, 3400, 100,
520 RK818_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
521 BIT(0), 400),
522 RK8XX_DESC(RK818_ID_LDO2, "LDO_REG2", "vcc6", 1800, 3400, 100,
523 RK818_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
524 BIT(1), 400),
525 {
526 .name = "LDO_REG3",
527 .supply_name = "vcc7",
528 .of_match = of_match_ptr("LDO_REG3"),
529 .regulators_node = of_match_ptr("regulators"),
530 .id = RK818_ID_LDO3,
531 .ops = &rk808_reg_ops_ranges,
532 .type = REGULATOR_VOLTAGE,
533 .n_voltages = 16,
534 .linear_ranges = rk808_ldo3_voltage_ranges,
535 .n_linear_ranges = ARRAY_SIZE(rk808_ldo3_voltage_ranges),
536 .vsel_reg = RK818_LDO3_ON_VSEL_REG,
537 .vsel_mask = RK818_LDO3_ON_VSEL_MASK,
538 .enable_reg = RK818_LDO_EN_REG,
539 .enable_mask = BIT(2),
540 .enable_time = 400,
541 .owner = THIS_MODULE,
542 },
543 RK8XX_DESC(RK818_ID_LDO4, "LDO_REG4", "vcc8", 1800, 3400, 100,
544 RK818_LDO4_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
545 BIT(3), 400),
546 RK8XX_DESC(RK818_ID_LDO5, "LDO_REG5", "vcc7", 1800, 3400, 100,
547 RK818_LDO5_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
548 BIT(4), 400),
549 RK8XX_DESC(RK818_ID_LDO6, "LDO_REG6", "vcc8", 800, 2500, 100,
550 RK818_LDO6_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
551 BIT(5), 400),
552 RK8XX_DESC(RK818_ID_LDO7, "LDO_REG7", "vcc7", 800, 2500, 100,
553 RK818_LDO7_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
554 BIT(6), 400),
555 RK8XX_DESC(RK818_ID_LDO8, "LDO_REG8", "vcc8", 1800, 3400, 100,
556 RK818_LDO8_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
557 BIT(7), 400),
558 RK8XX_DESC(RK818_ID_LDO9, "LDO_REG9", "vcc9", 1800, 3400, 100,
559 RK818_BOOST_LDO9_ON_VSEL_REG, RK818_LDO_VSEL_MASK,
560 RK818_DCDC_EN_REG, BIT(5), 400),
561 RK8XX_DESC_SWITCH(RK818_ID_SWITCH, "SWITCH_REG", "vcc9",
562 RK818_DCDC_EN_REG, BIT(6)),
563 RK8XX_DESC_SWITCH(RK818_ID_HDMI_SWITCH, "HDMI_SWITCH", "h_5v",
564 RK818_H5V_EN_REG, BIT(0)),
565 RK8XX_DESC_SWITCH(RK818_ID_OTG_SWITCH, "OTG_SWITCH", "usb",
566 RK818_DCDC_EN_REG, BIT(7)),
567};
568
457static int rk808_regulator_dt_parse_pdata(struct device *dev, 569static int rk808_regulator_dt_parse_pdata(struct device *dev,
458 struct device *client_dev, 570 struct device *client_dev,
459 struct regmap *map, 571 struct regmap *map,
@@ -499,7 +611,8 @@ static int rk808_regulator_probe(struct platform_device *pdev)
499 struct regulator_config config = {}; 611 struct regulator_config config = {};
500 struct regulator_dev *rk808_rdev; 612 struct regulator_dev *rk808_rdev;
501 struct rk808_regulator_data *pdata; 613 struct rk808_regulator_data *pdata;
502 int ret, i; 614 const struct regulator_desc *regulators;
615 int ret, i, nregulators;
503 616
504 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); 617 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
505 if (!pdata) 618 if (!pdata)
@@ -512,14 +625,29 @@ static int rk808_regulator_probe(struct platform_device *pdev)
512 625
513 platform_set_drvdata(pdev, pdata); 626 platform_set_drvdata(pdev, pdata);
514 627
628 switch (rk808->variant) {
629 case RK808_ID:
630 regulators = rk808_reg;
631 nregulators = RK808_NUM_REGULATORS;
632 break;
633 case RK818_ID:
634 regulators = rk818_reg;
635 nregulators = RK818_NUM_REGULATORS;
636 break;
637 default:
638 dev_err(&client->dev, "unsupported RK8XX ID %lu\n",
639 rk808->variant);
640 return -EINVAL;
641 }
642
515 config.dev = &client->dev; 643 config.dev = &client->dev;
516 config.driver_data = pdata; 644 config.driver_data = pdata;
517 config.regmap = rk808->regmap; 645 config.regmap = rk808->regmap;
518 646
519 /* Instantiate the regulators */ 647 /* Instantiate the regulators */
520 for (i = 0; i < RK808_NUM_REGULATORS; i++) { 648 for (i = 0; i < nregulators; i++) {
521 rk808_rdev = devm_regulator_register(&pdev->dev, 649 rk808_rdev = devm_regulator_register(&pdev->dev,
522 &rk808_reg[i], &config); 650 &regulators[i], &config);
523 if (IS_ERR(rk808_rdev)) { 651 if (IS_ERR(rk808_rdev)) {
524 dev_err(&client->dev, 652 dev_err(&client->dev,
525 "failed to register %d regulator\n", i); 653 "failed to register %d regulator\n", i);
@@ -539,8 +667,9 @@ static struct platform_driver rk808_regulator_driver = {
539 667
540module_platform_driver(rk808_regulator_driver); 668module_platform_driver(rk808_regulator_driver);
541 669
542MODULE_DESCRIPTION("regulator driver for the rk808 series PMICs"); 670MODULE_DESCRIPTION("regulator driver for the RK808/RK818 series PMICs");
543MODULE_AUTHOR("Chris Zhong<zyw@rock-chips.com>"); 671MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
544MODULE_AUTHOR("Zhang Qing<zhangqing@rock-chips.com>"); 672MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
673MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
545MODULE_LICENSE("GPL"); 674MODULE_LICENSE("GPL");
546MODULE_ALIAS("platform:rk808-regulator"); 675MODULE_ALIAS("platform:rk808-regulator");