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, + ®ulators[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