[PATCH 3/4] regulator: Add regulator driver for ATC260x PMICs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <manivannan.sadhasivam@xxxxxxxxxx>
---
 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 <manivannan.sadhasivam@xxxxxxxxxx>
+ */
+
+#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 <manivannan.sadhasivam@xxxxxxxxxx>");
+MODULE_LICENSE("GPL");
-- 
2.17.1




[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux