Add regulator driver for Actions Semi ATC260x PMICs. This driver
supports 5 DC-DC converters and 10 LDO regulators found in ATC2609A
PMIC variant.

Signed-off-by: Manivannan Sadhasivam <[email protected]>
---
 drivers/regulator/Kconfig             |   8 +
 drivers/regulator/Makefile            |   1 +
 drivers/regulator/atc260x-regulator.c | 389 ++++++++++++++++++++++++++
 3 files changed, 398 insertions(+)
 create mode 100644 drivers/regulator/atc260x-regulator.c

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 8553bdf87c1d..acaf447ecdc6 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -166,6 +166,14 @@ config REGULATOR_AS3722
          AS3722 PMIC. This will enable support for all the software
          controllable DCDC/LDO regulators.
 
+config REGULATOR_ATC260X
+       tristate "Actions Semi ATC260x PMIC Regulators"
+       depends on MFD_ATC260X
+       help
+         This driver provides support for the voltage regulators on the
+         ATC260x PMICs. This will enable support for all the software
+         controllable DCDC/LDO regulators.
+
 config REGULATOR_AXP20X
        tristate "X-POWERS AXP20X PMIC Regulators"
        depends on MFD_AXP20X
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 93f53840e8f1..600d01d082a3 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_REGULATOR_ARIZONA_LDO1) += arizona-ldo1.o
 obj-$(CONFIG_REGULATOR_ARIZONA_MICSUPP) += arizona-micsupp.o
 obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
 obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
+obj-$(CONFIG_REGULATOR_ATC260X) += atc260x-regulator.o
 obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o
 obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
 obj-$(CONFIG_REGULATOR_BD70528) += bd70528-regulator.o
diff --git a/drivers/regulator/atc260x-regulator.c 
b/drivers/regulator/atc260x-regulator.c
new file mode 100644
index 000000000000..e9e11f2567b2
--- /dev/null
+++ b/drivers/regulator/atc260x-regulator.c
@@ -0,0 +1,389 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Regulator driver for ATC260x PMICs
+ *
+ * Copyright (C) 2019 Manivannan Sadhasivam <[email protected]>
+ */
+
+#include <linux/mfd/atc260x/core.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+
+#define ATC2609A_DCDC_VSEL_MASK 0xff00
+#define ATC2609A_DCDC_MIN_UV 600000
+#define ATC2609A_DCDC_UV_STEP 6250
+#define ATC2609A_DCDC_NR_VOLT 256
+
+#define ATC2609A_LDO_VSEL_MASK0 0x003c
+#define ATC2609A_LDO_VSEL_MASK1 0x001e
+#define ATC2609A_LDO_VSEL_MASK2 0xe000
+#define ATC2609A_LDO_VSEL_RANGE_MASK 0x0020
+
+static const struct regulator_linear_range atc260x_ldo_voltage_ranges0[] = {
+       REGULATOR_LINEAR_RANGE(700000, 0, 15, 100000),
+       REGULATOR_LINEAR_RANGE(2100000, 16, 28, 100000),
+};
+
+static const struct regulator_linear_range atc260x_ldo_voltage_ranges1[] = {
+       REGULATOR_LINEAR_RANGE(850000, 0, 15, 100000),
+       REGULATOR_LINEAR_RANGE(2100000, 16, 27, 100000),
+};
+
+static const unsigned int atc260x_ldo_voltage_range_sel[] = {
+       0x0, 0x1,
+};
+
+static const struct regulator_linear_range atc260x_dcdc_voltage_ranges[] = {
+       REGULATOR_LINEAR_RANGE(600000, 0, 127, 6250),
+       REGULATOR_LINEAR_RANGE(1400000, 128, 232, 25000),
+};
+
+static const struct regulator_ops atc260x_reg_ops = {
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+       .list_voltage = regulator_list_voltage_linear,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+static const struct regulator_ops atc260x_reg_fixed_ops = {
+       .list_voltage = regulator_list_voltage_linear,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+static const struct regulator_ops atc260x_reg_range0_ops = {
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+       .list_voltage = regulator_list_voltage_pickable_linear_range,
+       .set_voltage_sel = regulator_set_voltage_sel_pickable_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
+};
+
+static const struct regulator_ops atc260x_reg_range1_ops = {
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+       .list_voltage = regulator_list_voltage_linear_range,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+static const struct regulator_desc atc2609a_reg[] = {
+       {
+               .name = "DCDC_REG0",
+               .supply_name = "vcc0",
+               .of_match = of_match_ptr("DCDC_REG0"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = ATC2609A_ID_DCDC0,
+               .ops = &atc260x_reg_ops,
+               .type = REGULATOR_VOLTAGE,
+               .min_uV = ATC2609A_DCDC_MIN_UV,
+               .uV_step = ATC2609A_DCDC_UV_STEP,
+               .n_voltages = ATC2609A_DCDC_NR_VOLT,
+               .vsel_reg = ATC2609A_PMU_DC0_CTL0,
+               .vsel_mask = ATC2609A_DCDC_VSEL_MASK,
+               .enable_reg = ATC2609A_PMU_DC_OSC,
+               .enable_mask = BIT(4),
+               .enable_time = 800,
+               .owner = THIS_MODULE,
+       }, {
+               .name = "DCDC_REG1",
+               .supply_name = "vcc1",
+               .of_match = of_match_ptr("DCDC_REG1"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = ATC2609A_ID_DCDC1,
+               .ops = &atc260x_reg_ops,
+               .type = REGULATOR_VOLTAGE,
+               .min_uV = ATC2609A_DCDC_MIN_UV,
+               .uV_step = ATC2609A_DCDC_UV_STEP,
+               .n_voltages = ATC2609A_DCDC_NR_VOLT,
+               .vsel_reg = ATC2609A_PMU_DC1_CTL0,
+               .vsel_mask = ATC2609A_DCDC_VSEL_MASK,
+               .enable_reg = ATC2609A_PMU_DC_OSC,
+               .enable_mask = BIT(5),
+               .enable_time = 800,
+               .owner = THIS_MODULE,
+       }, {
+               .name = "DCDC_REG2",
+               .supply_name = "vcc2",
+               .of_match = of_match_ptr("DCDC_REG2"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = ATC2609A_ID_DCDC2,
+               .ops = &atc260x_reg_ops,
+               .type = REGULATOR_VOLTAGE,
+               .min_uV = ATC2609A_DCDC_MIN_UV,
+               .uV_step = ATC2609A_DCDC_UV_STEP,
+               .n_voltages = ATC2609A_DCDC_NR_VOLT,
+               .vsel_reg = ATC2609A_PMU_DC2_CTL0,
+               .vsel_mask = ATC2609A_DCDC_VSEL_MASK,
+               .enable_reg = ATC2609A_PMU_DC_OSC,
+               .enable_mask = BIT(6),
+               .enable_time = 800,
+               .owner = THIS_MODULE,
+       }, {
+               .name = "DCDC_REG3",
+               .supply_name = "vcc3",
+               .of_match = of_match_ptr("DCDC_REG3"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = ATC2609A_ID_DCDC3,
+               .ops = &atc260x_reg_range1_ops,
+               .type = REGULATOR_VOLTAGE,
+               .n_voltages = 233,
+               .linear_ranges = atc260x_dcdc_voltage_ranges,
+               .n_linear_ranges = ARRAY_SIZE(atc260x_dcdc_voltage_ranges),
+               .vsel_reg = ATC2609A_PMU_DC3_CTL0,
+               .vsel_mask = ATC2609A_DCDC_VSEL_MASK,
+               .enable_reg = ATC2609A_PMU_DC_OSC,
+               .enable_mask = BIT(7),
+               .enable_time = 800,
+               .owner = THIS_MODULE,
+       }, {
+               .name = "DCDC_REG4",
+               .supply_name = "vcc4",
+               .of_match = of_match_ptr("DCDC_REG4"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = ATC2609A_ID_DCDC4,
+               .ops = &atc260x_reg_ops,
+               .type = REGULATOR_VOLTAGE,
+               .min_uV = ATC2609A_DCDC_MIN_UV,
+               .uV_step = ATC2609A_DCDC_UV_STEP,
+               .n_voltages = ATC2609A_DCDC_NR_VOLT,
+               .vsel_reg = ATC2609A_PMU_DC4_CTL0,
+               .vsel_mask = ATC2609A_DCDC_VSEL_MASK,
+               .enable_reg = ATC2609A_PMU_DC_OSC,
+               .enable_mask = BIT(8),
+               .enable_time = 800,
+               .owner = THIS_MODULE,
+       }, {
+               .name = "LDO_REG0",
+               .supply_name = "vcc5",
+               .of_match = of_match_ptr("LDO_REG0"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = ATC2609A_ID_LDO0,
+               .ops = &atc260x_reg_ops,
+               .type = REGULATOR_VOLTAGE,
+               .min_uV = 2300000,
+               .uV_step = 100000,
+               .n_voltages = 12,
+               .vsel_reg = ATC2609A_PMU_LDO0_CTL0,
+               .vsel_mask = ATC2609A_LDO_VSEL_MASK0,
+               .enable_reg = ATC2609A_PMU_LDO0_CTL0,
+               .enable_mask = BIT(0),
+               .enable_time = 2000,
+               .owner = THIS_MODULE,
+       }, {
+               .name = "LDO_REG1",
+               .supply_name = "vcc6",
+               .of_match = of_match_ptr("LDO_REG1"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = ATC2609A_ID_LDO1,
+               .ops = &atc260x_reg_ops,
+               .type = REGULATOR_VOLTAGE,
+               .min_uV = 2300000,
+               .uV_step = 100000,
+               .n_voltages = 12,
+               .vsel_reg = ATC2609A_PMU_LDO1_CTL0,
+               .vsel_mask = ATC2609A_LDO_VSEL_MASK0,
+               .enable_reg = ATC2609A_PMU_LDO1_CTL0,
+               .enable_mask = BIT(0),
+               .enable_time = 2000,
+               .owner = THIS_MODULE,
+       }, {
+               .name = "LDO_REG2",
+               .supply_name = "vcc7",
+               .of_match = of_match_ptr("LDO_REG2"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = ATC2609A_ID_LDO2,
+               .ops = &atc260x_reg_ops,
+               .type = REGULATOR_VOLTAGE,
+               .min_uV = 2300000,
+               .uV_step = 100000,
+               .n_voltages = 12,
+               .vsel_reg = ATC2609A_PMU_LDO2_CTL0,
+               .vsel_mask = ATC2609A_LDO_VSEL_MASK0,
+               .enable_reg = ATC2609A_PMU_LDO2_CTL0,
+               .enable_mask = BIT(0),
+               .enable_time = 2000,
+               .owner = THIS_MODULE,
+       }, {
+               .name = "LDO_REG3",
+               .supply_name = "vcc8",
+               .of_match = of_match_ptr("LDO_REG3"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = ATC2609A_ID_LDO3,
+               .ops = &atc260x_reg_range0_ops,
+               .type = REGULATOR_VOLTAGE,
+               .linear_ranges = atc260x_ldo_voltage_ranges0,
+               .n_linear_ranges = ARRAY_SIZE(atc260x_ldo_voltage_ranges0),
+               .vsel_reg = ATC2609A_PMU_LDO3_CTL0,
+               .vsel_mask = ATC2609A_LDO_VSEL_MASK1,
+               .vsel_range_reg = ATC2609A_PMU_LDO3_CTL0,
+               .vsel_range_mask = ATC2609A_LDO_VSEL_RANGE_MASK,
+               .linear_range_selectors = atc260x_ldo_voltage_range_sel,
+               .enable_reg = ATC2609A_PMU_LDO3_CTL0,
+               .enable_mask = BIT(0),
+               .enable_time = 2000,
+               .owner = THIS_MODULE,
+       }, {
+               .name = "LDO_REG4",
+               .supply_name = "vcc9",
+               .of_match = of_match_ptr("LDO_REG4"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = ATC2609A_ID_LDO4,
+               .ops = &atc260x_reg_range0_ops,
+               .type = REGULATOR_VOLTAGE,
+               .linear_ranges = atc260x_ldo_voltage_ranges0,
+               .n_linear_ranges = ARRAY_SIZE(atc260x_ldo_voltage_ranges0),
+               .vsel_reg = ATC2609A_PMU_LDO4_CTL0,
+               .vsel_mask = ATC2609A_LDO_VSEL_MASK1,
+               .vsel_range_reg = ATC2609A_PMU_LDO4_CTL0,
+               .vsel_range_mask = ATC2609A_LDO_VSEL_RANGE_MASK,
+               .linear_range_selectors = atc260x_ldo_voltage_range_sel,
+               .enable_reg = ATC2609A_PMU_LDO4_CTL0,
+               .enable_mask = BIT(0),
+               .enable_time = 2000,
+               .owner = THIS_MODULE,
+       }, {
+               .name = "LDO_REG5",
+               .supply_name = "vcc10",
+               .of_match = of_match_ptr("LDO_REG5"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = ATC2609A_ID_LDO5,
+               .ops = &atc260x_reg_ops,
+               .type = REGULATOR_VOLTAGE,
+               .min_uV = 700000,
+               .uV_step = 100000,
+               .n_voltages = 16,
+               .vsel_reg = ATC2609A_PMU_LDO5_CTL0,
+               .vsel_mask = ATC2609A_LDO_VSEL_MASK1,
+               .enable_reg = ATC2609A_PMU_LDO5_CTL0,
+               .enable_mask = BIT(0),
+               .enable_time = 2000,
+               .owner = THIS_MODULE,
+       }, {
+               .name = "LDO_REG6",
+               .supply_name = "vcc11",
+               .of_match = of_match_ptr("LDO_REG6"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = ATC2609A_ID_LDO6,
+               .ops = &atc260x_reg_range0_ops,
+               .type = REGULATOR_VOLTAGE,
+               .linear_ranges = atc260x_ldo_voltage_ranges1,
+               .n_linear_ranges = ARRAY_SIZE(atc260x_ldo_voltage_ranges1),
+               .vsel_reg = ATC2609A_PMU_LDO6_CTL0,
+               .vsel_mask = ATC2609A_LDO_VSEL_MASK1,
+               .vsel_range_reg = ATC2609A_PMU_LDO6_CTL0,
+               .vsel_range_mask = ATC2609A_LDO_VSEL_RANGE_MASK,
+               .linear_range_selectors = atc260x_ldo_voltage_range_sel,
+               .enable_reg = ATC2609A_PMU_LDO6_CTL0,
+               .enable_mask = BIT(0),
+               .enable_time = 2000,
+               .owner = THIS_MODULE,
+       }, {
+               .name = "LDO_REG7",
+               .supply_name = "vcc12",
+               .of_match = of_match_ptr("LDO_REG7"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = ATC2609A_ID_LDO7,
+               .ops = &atc260x_reg_range0_ops,
+               .type = REGULATOR_VOLTAGE,
+               .linear_ranges = atc260x_ldo_voltage_ranges0,
+               .n_linear_ranges = ARRAY_SIZE(atc260x_ldo_voltage_ranges0),
+               .vsel_reg = ATC2609A_PMU_LDO7_CTL0,
+               .vsel_mask = ATC2609A_LDO_VSEL_MASK1,
+               .vsel_range_reg = ATC2609A_PMU_LDO7_CTL0,
+               .vsel_range_mask = ATC2609A_LDO_VSEL_RANGE_MASK,
+               .linear_range_selectors = atc260x_ldo_voltage_range_sel,
+               .enable_reg = ATC2609A_PMU_LDO7_CTL0,
+               .enable_mask = BIT(0),
+               .enable_time = 2000,
+               .owner = THIS_MODULE,
+       }, {
+               .name = "LDO_REG8",
+               .supply_name = "vcc13",
+               .of_match = of_match_ptr("LDO_REG8"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = ATC2609A_ID_LDO8,
+               .ops = &atc260x_reg_range0_ops,
+               .type = REGULATOR_VOLTAGE,
+               .linear_ranges = atc260x_ldo_voltage_ranges0,
+               .n_linear_ranges = ARRAY_SIZE(atc260x_ldo_voltage_ranges0),
+               .vsel_reg = ATC2609A_PMU_LDO8_CTL0,
+               .vsel_mask = ATC2609A_LDO_VSEL_MASK1,
+               .vsel_range_reg = ATC2609A_PMU_LDO8_CTL0,
+               .vsel_range_mask = ATC2609A_LDO_VSEL_RANGE_MASK,
+               .linear_range_selectors = atc260x_ldo_voltage_range_sel,
+               .enable_reg = ATC2609A_PMU_LDO8_CTL0,
+               .enable_mask = BIT(0),
+               .enable_time = 2000,
+               .owner = THIS_MODULE,
+       }, {
+               .name = "LDO_REG9",
+               .supply_name = "vcc14",
+               .of_match = of_match_ptr("LDO_REG9"),
+               .regulators_node = of_match_ptr("regulators"),
+               .id = ATC2609A_ID_LDO9,
+               .ops = &atc260x_reg_fixed_ops,
+               .type = REGULATOR_VOLTAGE,
+               .min_uV = 2600000,
+               .uV_step = 100000,
+               .n_voltages = 8,
+               .vsel_reg = ATC2609A_PMU_LDO9_CTL,
+               .vsel_mask = ATC2609A_LDO_VSEL_MASK2,
+               .enable_time = 2000,
+               .owner = THIS_MODULE,
+       },
+};
+
+static int atc260x_regulator_probe(struct platform_device *pdev)
+{
+       struct atc260x *atc260x = dev_get_drvdata(pdev->dev.parent);
+       struct device *dev = atc260x->dev;
+       struct regulator_config config = {};
+       struct regulator_dev *atc260x_rdev;
+       const struct regulator_desc *regulators;
+       int i, nregulators;
+
+       switch (atc260x->type) {
+       case ATC2609A:
+               regulators = atc2609a_reg;
+               nregulators = ATC2609A_ID_MAX;
+               break;
+       default:
+               dev_err(dev, "unsupported ATC260X ID %d\n", atc260x->type);
+               return -EINVAL;
+       }
+
+       config.dev = dev;
+       config.regmap = atc260x->regmap;
+
+       /* Instantiate the regulators */
+       for (i = 0; i < nregulators; i++) {
+               atc260x_rdev = devm_regulator_register(&pdev->dev,
+                                                      &regulators[i], &config);
+               if (IS_ERR(atc260x_rdev)) {
+                       dev_err(dev, "failed to register regulator: %d\n", i);
+                       return PTR_ERR(atc260x_rdev);
+               }
+       }
+
+       return 0;
+}
+
+static struct platform_driver atc260x_regulator_driver = {
+       .probe = atc260x_regulator_probe,
+       .driver = {
+               .name = "atc260x-regulator"
+       },
+};
+
+module_platform_driver(atc260x_regulator_driver);
+
+MODULE_DESCRIPTION("Regulator driver for ATC260x PMICs");
+MODULE_AUTHOR("Manivannan Sadhasivam <[email protected]>");
+MODULE_LICENSE("GPL");
-- 
2.17.1

Reply via email to