diff options
Diffstat (limited to 'drivers/regulator')
44 files changed, 1543 insertions, 702 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index ee60a222f5eb..b7f249ee5e68 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -180,6 +180,17 @@ config REGULATOR_BCM590XX BCM590xx PMUs. This will enable support for the software controllable LDO/Switching regulators. +config REGULATOR_BD70528 + tristate "ROHM BD70528 Power Regulator" + depends on MFD_ROHM_BD70528 + help + This driver supports voltage regulators on ROHM BD70528 PMIC. + This will enable support for the software controllable buck + and LDO regulators. + + This driver can also be built as a module. If so, the module + will be called bd70528-regulator. + config REGULATOR_BD718XX tristate "ROHM BD71837 Power Regulator" depends on MFD_ROHM_BD718XX @@ -457,6 +468,14 @@ config REGULATOR_MAX77620 chip to control Step-Down DC-DC and LDOs. Say Y here to enable the regulator driver. +config REGULATOR_MAX77650 + tristate "Maxim MAX77650/77651 regulator support" + depends on MFD_MAX77650 + help + Regulator driver for MAX77650/77651 PMIC from Maxim + Semiconductor. This device has a SIMO with three independent + power rails and an LDO. + config REGULATOR_MAX8649 tristate "Maxim 8649 voltage regulator" depends on I2C @@ -484,7 +503,7 @@ config REGULATOR_MAX8925 tristate "Maxim MAX8925 Power Management IC" depends on MFD_MAX8925 help - Say y here to support the voltage regulaltor of Maxim MAX8925 PMIC. + Say y here to support the voltage regulator of Maxim MAX8925 PMIC. config REGULATOR_MAX8952 tristate "Maxim MAX8952 Power Management IC" @@ -501,7 +520,7 @@ config REGULATOR_MAX8973 select REGMAP_I2C help The MAXIM MAX8973 high-efficiency. three phase, DC-DC step-down - switching regulator delievers up to 9A of output current. Each + switching regulator delivers up to 9A of output current. Each phase operates at a 2MHz fixed frequency with a 120 deg shift from the adjacent phase, allowing the use of small magnetic component. @@ -646,7 +665,7 @@ config REGULATOR_PCF50633 tristate "NXP PCF50633 regulator driver" depends on MFD_PCF50633 help - Say Y here to support the voltage regulators and convertors + Say Y here to support the voltage regulators and converters on PCF50633 config REGULATOR_PFUZE100 @@ -924,7 +943,7 @@ config REGULATOR_TPS65132 select REGMAP_I2C help This driver supports TPS65132 single inductor - dual output - power supply specifcally designed for display panels. + power supply specifically designed for display panels. config REGULATOR_TPS65217 tristate "TI TPS65217 Power regulators" diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index b12e1c9b2118..1169f8a27d91 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o +obj-$(CONFIG_REGULATOR_BD70528) += bd70528-regulator.o obj-$(CONFIG_REGULATOR_BD718XX) += bd718x7-regulator.o obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o obj-$(CONFIG_REGULATOR_DA903X) += da903x.o @@ -60,6 +61,7 @@ obj-$(CONFIG_REGULATOR_LTC3676) += ltc3676.o obj-$(CONFIG_REGULATOR_MAX14577) += max14577-regulator.o obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o +obj-$(CONFIG_REGULATOR_MAX77650) += max77650-regulator.o obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o obj-$(CONFIG_REGULATOR_MAX8907) += max8907-regulator.o diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index 21e20483bd91..e0239cf3f56d 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -131,7 +131,7 @@ * ACT8865 voltage number */ #define ACT8865_VOLTAGE_NUM 64 -#define ACT8600_SUDCDC_VOLTAGE_NUM 255 +#define ACT8600_SUDCDC_VOLTAGE_NUM 256 struct act8865 { struct regmap *regmap; @@ -222,7 +222,8 @@ static const struct regulator_linear_range act8600_sudcdc_voltage_ranges[] = { REGULATOR_LINEAR_RANGE(3000000, 0, 63, 0), REGULATOR_LINEAR_RANGE(3000000, 64, 159, 100000), REGULATOR_LINEAR_RANGE(12600000, 160, 191, 200000), - REGULATOR_LINEAR_RANGE(19000000, 191, 255, 400000), + REGULATOR_LINEAR_RANGE(19000000, 192, 247, 400000), + REGULATOR_LINEAR_RANGE(41400000, 248, 255, 0), }; static struct regulator_ops act8865_ops = { diff --git a/drivers/regulator/act8945a-regulator.c b/drivers/regulator/act8945a-regulator.c index 603db77723b6..caa61d306a69 100644 --- a/drivers/regulator/act8945a-regulator.c +++ b/drivers/regulator/act8945a-regulator.c @@ -87,7 +87,8 @@ static const struct regulator_linear_range act8945a_voltage_ranges[] = { static int act8945a_set_suspend_state(struct regulator_dev *rdev, bool enable) { struct regmap *regmap = rdev->regmap; - int id = rdev->desc->id, reg, val; + int id = rdev_get_id(rdev); + int reg, val; switch (id) { case ACT8945A_ID_DCDC1: @@ -159,7 +160,7 @@ static int act8945a_set_mode(struct regulator_dev *rdev, unsigned int mode) { struct act8945a_pmic *act8945a = rdev_get_drvdata(rdev); struct regmap *regmap = rdev->regmap; - int id = rdev->desc->id; + int id = rdev_get_id(rdev); int reg, ret, val = 0; switch (id) { @@ -190,11 +191,11 @@ static int act8945a_set_mode(struct regulator_dev *rdev, unsigned int mode) switch (mode) { case REGULATOR_MODE_STANDBY: - if (rdev->desc->id > ACT8945A_ID_DCDC3) + if (id > ACT8945A_ID_DCDC3) val = BIT(5); break; case REGULATOR_MODE_NORMAL: - if (rdev->desc->id <= ACT8945A_ID_DCDC3) + if (id <= ACT8945A_ID_DCDC3) val = BIT(5); break; default: @@ -213,7 +214,7 @@ static int act8945a_set_mode(struct regulator_dev *rdev, unsigned int mode) static unsigned int act8945a_get_mode(struct regulator_dev *rdev) { struct act8945a_pmic *act8945a = rdev_get_drvdata(rdev); - int id = rdev->desc->id; + int id = rdev_get_id(rdev); if (id < ACT8945A_ID_DCDC1 || id >= ACT8945A_ID_MAX) return -EINVAL; diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index b9a93049e41e..dfed6d3f03ad 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c @@ -40,30 +40,6 @@ struct arizona_ldo1 { struct gpio_desc *ena_gpiod; }; -static int arizona_ldo1_hc_list_voltage(struct regulator_dev *rdev, - unsigned int selector) -{ - if (selector >= rdev->desc->n_voltages) - return -EINVAL; - - if (selector == rdev->desc->n_voltages - 1) - return 1800000; - else - return rdev->desc->min_uV + (rdev->desc->uV_step * selector); -} - -static int arizona_ldo1_hc_map_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - int sel; - - sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); - if (sel >= rdev->desc->n_voltages) - sel = rdev->desc->n_voltages - 1; - - return sel; -} - static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev, unsigned sel) { @@ -113,14 +89,19 @@ static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev) } static const struct regulator_ops arizona_ldo1_hc_ops = { - .list_voltage = arizona_ldo1_hc_list_voltage, - .map_voltage = arizona_ldo1_hc_map_voltage, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, .get_voltage_sel = arizona_ldo1_hc_get_voltage_sel, .set_voltage_sel = arizona_ldo1_hc_set_voltage_sel, .get_bypass = regulator_get_bypass_regmap, .set_bypass = regulator_set_bypass_regmap, }; +static const struct regulator_linear_range arizona_ldo1_hc_ranges[] = { + REGULATOR_LINEAR_RANGE(900000, 0, 0x6, 50000), + REGULATOR_LINEAR_RANGE(1800000, 0x7, 0x7, 0), +}; + static const struct regulator_desc arizona_ldo1_hc = { .name = "LDO1", .supply_name = "LDOVDD", @@ -129,8 +110,8 @@ static const struct regulator_desc arizona_ldo1_hc = { .bypass_reg = ARIZONA_LDO1_CONTROL_1, .bypass_mask = ARIZONA_LDO1_BYPASS, - .min_uV = 900000, - .uV_step = 50000, + .linear_ranges = arizona_ldo1_hc_ranges, + .n_linear_ranges = ARRAY_SIZE(arizona_ldo1_hc_ranges), .n_voltages = 8, .enable_time = 1500, .ramp_delay = 24000, diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c index 66337e12719b..e5fed289b52d 100644 --- a/drivers/regulator/as3722-regulator.c +++ b/drivers/regulator/as3722-regulator.c @@ -886,7 +886,7 @@ static int as3722_regulator_probe(struct platform_device *pdev) as3722_regs->desc[id].min_uV = 410000; } else { as3722_regs->desc[id].n_voltages = - AS3722_SD0_VSEL_MAX + 1, + AS3722_SD0_VSEL_MAX + 1; as3722_regs->desc[id].min_uV = 610000; } as3722_regs->desc[id].uV_step = 10000; diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index 62243957bd19..98efc28f65ed 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -367,7 +367,7 @@ static const int axp209_dcdc2_ldo3_slew_rates[] = { static int axp20x_set_ramp_delay(struct regulator_dev *rdev, int ramp) { struct axp20x_dev *axp20x = rdev_get_drvdata(rdev); - const struct regulator_desc *desc = rdev->desc; + const struct regulator_desc *desc; u8 reg, mask, enable, cfg = 0xff; const int *slew_rates; int rate_count = 0; @@ -375,6 +375,8 @@ static int axp20x_set_ramp_delay(struct regulator_dev *rdev, int ramp) if (!rdev) return -EINVAL; + desc = rdev->desc; + switch (axp20x->variant) { case AXP209_ID: if (desc->id == AXP20X_DCDC2) { @@ -436,11 +438,13 @@ static int axp20x_set_ramp_delay(struct regulator_dev *rdev, int ramp) static int axp20x_regulator_enable_regmap(struct regulator_dev *rdev) { struct axp20x_dev *axp20x = rdev_get_drvdata(rdev); - const struct regulator_desc *desc = rdev->desc; + const struct regulator_desc *desc; if (!rdev) return -EINVAL; + desc = rdev->desc; + switch (axp20x->variant) { case AXP209_ID: if ((desc->id == AXP20X_LDO3) && diff --git a/drivers/regulator/bd70528-regulator.c b/drivers/regulator/bd70528-regulator.c new file mode 100644 index 000000000000..30e3ed430a8a --- /dev/null +++ b/drivers/regulator/bd70528-regulator.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 ROHM Semiconductors +// bd70528-regulator.c ROHM BD70528MWV regulator driver + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/mfd/rohm-bd70528.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> +#include <linux/slab.h> + +#define BUCK_RAMPRATE_250MV 0 +#define BUCK_RAMPRATE_125MV 1 +#define BUCK_RAMP_MAX 250 + +static const struct regulator_linear_range bd70528_buck1_volts[] = { + REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 600000), + REGULATOR_LINEAR_RANGE(2750000, 0x2, 0xf, 50000), +}; +static const struct regulator_linear_range bd70528_buck2_volts[] = { + REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 300000), + REGULATOR_LINEAR_RANGE(1550000, 0x2, 0xd, 50000), + REGULATOR_LINEAR_RANGE(3000000, 0xe, 0xf, 300000), +}; +static const struct regulator_linear_range bd70528_buck3_volts[] = { + REGULATOR_LINEAR_RANGE(800000, 0x00, 0xd, 50000), + REGULATOR_LINEAR_RANGE(1800000, 0xe, 0xf, 0), +}; + +/* All LDOs have same voltage ranges */ +static const struct regulator_linear_range bd70528_ldo_volts[] = { + REGULATOR_LINEAR_RANGE(1650000, 0x0, 0x07, 50000), + REGULATOR_LINEAR_RANGE(2100000, 0x8, 0x0f, 100000), + REGULATOR_LINEAR_RANGE(2850000, 0x10, 0x19, 50000), + REGULATOR_LINEAR_RANGE(3300000, 0x19, 0x1f, 0), +}; + +/* Also both LEDs support same voltages */ +static const unsigned int led_volts[] = { + 20000, 30000 +}; + +static int bd70528_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) +{ + if (ramp_delay > 0 && ramp_delay <= BUCK_RAMP_MAX) { + unsigned int ramp_value = BUCK_RAMPRATE_250MV; + + if (ramp_delay <= 125) + ramp_value = BUCK_RAMPRATE_125MV; + + return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, + BD70528_MASK_BUCK_RAMP, + ramp_value << BD70528_SIFT_BUCK_RAMP); + } + dev_err(&rdev->dev, "%s: ramp_delay: %d not supported\n", + rdev->desc->name, ramp_delay); + return -EINVAL; +} + +static int bd70528_led_set_voltage_sel(struct regulator_dev *rdev, + unsigned int sel) +{ + int ret; + + ret = regulator_is_enabled_regmap(rdev); + if (ret < 0) + return ret; + + if (ret == 0) + return regulator_set_voltage_sel_regmap(rdev, sel); + + dev_err(&rdev->dev, + "LED voltage change not allowed when led is enabled\n"); + + return -EBUSY; +} + +static const struct regulator_ops bd70528_buck_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, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = bd70528_set_ramp_delay, +}; + +static const struct regulator_ops bd70528_ldo_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, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = bd70528_set_ramp_delay, +}; + +static const struct regulator_ops bd70528_led_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_table, + .set_voltage_sel = bd70528_led_set_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, +}; + +static const struct regulator_desc bd70528_desc[] = { + { + .name = "buck1", + .of_match = of_match_ptr("BUCK1"), + .regulators_node = of_match_ptr("regulators"), + .id = BD70528_BUCK1, + .ops = &bd70528_buck_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd70528_buck1_volts, + .n_linear_ranges = ARRAY_SIZE(bd70528_buck1_volts), + .n_voltages = BD70528_BUCK_VOLTS, + .enable_reg = BD70528_REG_BUCK1_EN, + .enable_mask = BD70528_MASK_RUN_EN, + .vsel_reg = BD70528_REG_BUCK1_VOLT, + .vsel_mask = BD70528_MASK_BUCK_VOLT, + .owner = THIS_MODULE, + }, + { + .name = "buck2", + .of_match = of_match_ptr("BUCK2"), + .regulators_node = of_match_ptr("regulators"), + .id = BD70528_BUCK2, + .ops = &bd70528_buck_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd70528_buck2_volts, + .n_linear_ranges = ARRAY_SIZE(bd70528_buck2_volts), + .n_voltages = BD70528_BUCK_VOLTS, + .enable_reg = BD70528_REG_BUCK2_EN, + .enable_mask = BD70528_MASK_RUN_EN, + .vsel_reg = BD70528_REG_BUCK2_VOLT, + .vsel_mask = BD70528_MASK_BUCK_VOLT, + .owner = THIS_MODULE, + }, + { + .name = "buck3", + .of_match = of_match_ptr("BUCK3"), + .regulators_node = of_match_ptr("regulators"), + .id = BD70528_BUCK3, + .ops = &bd70528_buck_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd70528_buck3_volts, + .n_linear_ranges = ARRAY_SIZE(bd70528_buck3_volts), + .n_voltages = BD70528_BUCK_VOLTS, + .enable_reg = BD70528_REG_BUCK3_EN, + .enable_mask = BD70528_MASK_RUN_EN, + .vsel_reg = BD70528_REG_BUCK3_VOLT, + .vsel_mask = BD70528_MASK_BUCK_VOLT, + .owner = THIS_MODULE, + }, + { + .name = "ldo1", + .of_match = of_match_ptr("LDO1"), + .regulators_node = of_match_ptr("regulators"), + .id = BD70528_LDO1, + .ops = &bd70528_ldo_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd70528_ldo_volts, + .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts), + .n_voltages = BD70528_LDO_VOLTS, + .enable_reg = BD70528_REG_LDO1_EN, + .enable_mask = BD70528_MASK_RUN_EN, + .vsel_reg = BD70528_REG_LDO1_VOLT, + .vsel_mask = BD70528_MASK_LDO_VOLT, + .owner = THIS_MODULE, + }, + { + .name = "ldo2", + .of_match = of_match_ptr("LDO2"), + .regulators_node = of_match_ptr("regulators"), + .id = BD70528_LDO2, + .ops = &bd70528_ldo_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd70528_ldo_volts, + .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts), + .n_voltages = BD70528_LDO_VOLTS, + .enable_reg = BD70528_REG_LDO2_EN, + .enable_mask = BD70528_MASK_RUN_EN, + .vsel_reg = BD70528_REG_LDO2_VOLT, + .vsel_mask = BD70528_MASK_LDO_VOLT, + .owner = THIS_MODULE, + }, + { + .name = "ldo3", + .of_match = of_match_ptr("LDO3"), + .regulators_node = of_match_ptr("regulators"), + .id = BD70528_LDO3, + .ops = &bd70528_ldo_ops, + .type = REGULATOR_VOLTAGE, + .linear_ranges = bd70528_ldo_volts, + .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts), + .n_voltages = BD70528_LDO_VOLTS, + .enable_reg = BD70528_REG_LDO3_EN, + .enable_mask = BD70528_MASK_RUN_EN, + .vsel_reg = BD70528_REG_LDO3_VOLT, + .vsel_mask = BD70528_MASK_LDO_VOLT, + .owner = THIS_MODULE, + }, + { + .name = "ldo_led1", + .of_match = of_match_ptr("LDO_LED1"), + .regulators_node = of_match_ptr("regulators"), + .id = BD70528_LED1, + .ops = &bd70528_led_ops, + .type = REGULATOR_VOLTAGE, + .volt_table = &led_volts[0], + .n_voltages = ARRAY_SIZE(led_volts), + .enable_reg = BD70528_REG_LED_EN, + .enable_mask = BD70528_MASK_LED1_EN, + .vsel_reg = BD70528_REG_LED_VOLT, + .vsel_mask = BD70528_MASK_LED1_VOLT, + .owner = THIS_MODULE, + }, + { + .name = "ldo_led2", + .of_match = of_match_ptr("LDO_LED2"), + .regulators_node = of_match_ptr("regulators"), + .id = BD70528_LED2, + .ops = &bd70528_led_ops, + .type = REGULATOR_VOLTAGE, + .volt_table = &led_volts[0], + .n_voltages = ARRAY_SIZE(led_volts), + .enable_reg = BD70528_REG_LED_EN, + .enable_mask = BD70528_MASK_LED2_EN, + .vsel_reg = BD70528_REG_LED_VOLT, + .vsel_mask = BD70528_MASK_LED2_VOLT, + .owner = THIS_MODULE, + }, + +}; + +static int bd70528_probe(struct platform_device *pdev) +{ + struct rohm_regmap_dev *bd70528; + int i; + struct regulator_config config = { + .dev = pdev->dev.parent, + }; + + bd70528 = dev_get_drvdata(pdev->dev.parent); + if (!bd70528) { + dev_err(&pdev->dev, "No MFD driver data\n"); + return -EINVAL; + } + + config.regmap = bd70528->regmap; + + for (i = 0; i < ARRAY_SIZE(bd70528_desc); i++) { + struct regulator_dev *rdev; + + rdev = devm_regulator_register(&pdev->dev, &bd70528_desc[i], + &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, + "failed to register %s regulator\n", + bd70528_desc[i].name); + return PTR_ERR(rdev); + } + } + return 0; +} + +static struct platform_driver bd70528_regulator = { + .driver = { + .name = "bd70528-pmic" + }, + .probe = bd70528_probe, +}; + +module_platform_driver(bd70528_regulator); + +MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); +MODULE_DESCRIPTION("BD70528 voltage regulator driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c index b8dcdc21dc22..b2191be49670 100644 --- a/drivers/regulator/bd718x7-regulator.c +++ b/drivers/regulator/bd718x7-regulator.c @@ -79,7 +79,7 @@ static int bd718xx_set_voltage_sel_pickable_restricted( return regulator_set_voltage_sel_pickable_regmap(rdev, sel); } -static struct regulator_ops bd718xx_pickable_range_ldo_ops = { +static const struct regulator_ops bd718xx_pickable_range_ldo_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -88,7 +88,7 @@ static struct regulator_ops bd718xx_pickable_range_ldo_ops = { .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, }; -static struct regulator_ops bd718xx_pickable_range_buck_ops = { +static const struct regulator_ops bd718xx_pickable_range_buck_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -98,7 +98,7 @@ static struct regulator_ops bd718xx_pickable_range_buck_ops = { .set_voltage_time_sel = regulator_set_voltage_time_sel, }; -static struct regulator_ops bd718xx_ldo_regulator_ops = { +static const struct regulator_ops bd718xx_ldo_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -107,7 +107,7 @@ static struct regulator_ops bd718xx_ldo_regulator_ops = { .get_voltage_sel = regulator_get_voltage_sel_regmap, }; -static struct regulator_ops bd718xx_ldo_regulator_nolinear_ops = { +static const struct regulator_ops bd718xx_ldo_regulator_nolinear_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -116,7 +116,7 @@ static struct regulator_ops bd718xx_ldo_regulator_nolinear_ops = { .get_voltage_sel = regulator_get_voltage_sel_regmap, }; -static struct regulator_ops bd718xx_buck_regulator_ops = { +static const struct regulator_ops bd718xx_buck_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -126,7 +126,7 @@ static struct regulator_ops bd718xx_buck_regulator_ops = { .set_voltage_time_sel = regulator_set_voltage_time_sel, }; -static struct regulator_ops bd718xx_buck_regulator_nolinear_ops = { +static const struct regulator_ops bd718xx_buck_regulator_nolinear_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -137,7 +137,7 @@ static struct regulator_ops bd718xx_buck_regulator_nolinear_ops = { .set_voltage_time_sel = regulator_set_voltage_time_sel, }; -static struct regulator_ops bd718xx_dvs_buck_regulator_ops = { +static const struct regulator_ops bd718xx_dvs_buck_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -350,6 +350,135 @@ static const struct reg_init bd71837_ldo6_inits[] = { }, }; +#define NUM_DVS_BUCKS 4 + +struct of_dvs_setting { + const char *prop; + unsigned int reg; +}; + +static int set_dvs_levels(const struct of_dvs_setting *dvs, + struct device_node *np, + const struct regulator_desc *desc, + struct regmap *regmap) +{ + int ret, i; + unsigned int uv; + + ret = of_property_read_u32(np, dvs->prop, &uv); + if (ret) { + if (ret != -EINVAL) + return ret; + return 0; + } + + for (i = 0; i < desc->n_voltages; i++) { + ret = regulator_desc_list_voltage_linear_range(desc, i); + if (ret < 0) + continue; + if (ret == uv) { + i <<= ffs(desc->vsel_mask) - 1; + ret = regmap_update_bits(regmap, dvs->reg, + DVS_BUCK_RUN_MASK, i); + break; + } + } + return ret; +} + +static int buck4_set_hw_dvs_levels(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *cfg) +{ + int ret, i; + const struct of_dvs_setting dvs[] = { + { + .prop = "rohm,dvs-run-voltage", + .reg = BD71837_REG_BUCK4_VOLT_RUN, + }, + }; + + for (i = 0; i < ARRAY_SIZE(dvs); i++) { + ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap); + if (ret) + break; + } + return ret; +} +static int buck3_set_hw_dvs_levels(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *cfg) +{ + int ret, i; + const struct of_dvs_setting dvs[] = { + { + .prop = "rohm,dvs-run-voltage", + .reg = BD71837_REG_BUCK3_VOLT_RUN, + }, + }; + + for (i = 0; i < ARRAY_SIZE(dvs); i++) { + ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap); + if (ret) + break; + } + return ret; +} + +static int buck2_set_hw_dvs_levels(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *cfg) +{ + int ret, i; + const struct of_dvs_setting dvs[] = { + { + .prop = "rohm,dvs-run-voltage", + .reg = BD718XX_REG_BUCK2_VOLT_RUN, + }, + { + .prop = "rohm,dvs-idle-voltage", + .reg = BD718XX_REG_BUCK2_VOLT_IDLE, + }, + }; + + + + for (i = 0; i < ARRAY_SIZE(dvs); i++) { + ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap); + if (ret) + break; + } + return ret; +} + +static int buck1_set_hw_dvs_levels(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *cfg) +{ + int ret, i; + const struct of_dvs_setting dvs[] = { + { + .prop = "rohm,dvs-run-voltage", + .reg = BD718XX_REG_BUCK1_VOLT_RUN, + }, + { + .prop = "rohm,dvs-idle-voltage", + .reg = BD718XX_REG_BUCK1_VOLT_IDLE, + }, + { + .prop = "rohm,dvs-suspend-voltage", + .reg = BD718XX_REG_BUCK1_VOLT_SUSP, + }, + }; + + for (i = 0; i < ARRAY_SIZE(dvs); i++) { + ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap); + if (ret) + break; + } + return ret; +} + static const struct bd718xx_regulator_data bd71847_regulators[] = { { .desc = { @@ -368,6 +497,7 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .enable_reg = BD718XX_REG_BUCK1_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, + .of_parse_cb = buck1_set_hw_dvs_levels, }, .init = { .reg = BD718XX_REG_BUCK1_CTRL, @@ -391,6 +521,7 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .enable_reg = BD718XX_REG_BUCK2_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, + .of_parse_cb = buck2_set_hw_dvs_levels, }, .init = { .reg = BD718XX_REG_BUCK2_CTRL, @@ -662,6 +793,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .enable_reg = BD718XX_REG_BUCK1_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, + .of_parse_cb = buck1_set_hw_dvs_levels, }, .init = { .reg = BD718XX_REG_BUCK1_CTRL, @@ -685,6 +817,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .enable_reg = BD718XX_REG_BUCK2_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, + .of_parse_cb = buck2_set_hw_dvs_levels, }, .init = { .reg = BD718XX_REG_BUCK2_CTRL, @@ -708,6 +841,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .enable_reg = BD71837_REG_BUCK3_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, + .of_parse_cb = buck3_set_hw_dvs_levels, }, .init = { .reg = BD71837_REG_BUCK3_CTRL, @@ -731,6 +865,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .enable_reg = BD71837_REG_BUCK4_CTRL, .enable_mask = BD718XX_BUCK_EN, .owner = THIS_MODULE, + .of_parse_cb = buck4_set_hw_dvs_levels, }, .init = { .reg = BD71837_REG_BUCK4_CTRL, @@ -1029,6 +1164,7 @@ static int bd718xx_probe(struct platform_device *pdev) }; int i, j, err; + bool use_snvs; mfd = dev_get_drvdata(pdev->dev.parent); if (!mfd) { @@ -1055,27 +1191,28 @@ static int bd718xx_probe(struct platform_device *pdev) BD718XX_REG_REGLOCK); } - /* At poweroff transition PMIC HW disables EN bit for regulators but - * leaves SEL bit untouched. So if state transition from POWEROFF - * is done to SNVS - then all power rails controlled by SW (having - * SEL bit set) stay disabled as EN is cleared. This may result boot - * failure if any crucial systems are powered by these rails. - * + use_snvs = of_property_read_bool(pdev->dev.parent->of_node, + "rohm,reset-snvs-powered"); + + /* * Change the next stage from poweroff to be READY instead of SNVS * for all reset types because OTP loading at READY will clear SEL * bit allowing HW defaults for power rails to be used */ - err = regmap_update_bits(mfd->regmap, BD718XX_REG_TRANS_COND1, - BD718XX_ON_REQ_POWEROFF_MASK | - BD718XX_SWRESET_POWEROFF_MASK | - BD718XX_WDOG_POWEROFF_MASK | - BD718XX_KEY_L_POWEROFF_MASK, - BD718XX_POWOFF_TO_RDY); - if (err) { - dev_err(&pdev->dev, "Failed to change reset target\n"); - goto err; - } else { - dev_dbg(&pdev->dev, "Changed all resets from SVNS to READY\n"); + if (!use_snvs) { + err = regmap_update_bits(mfd->regmap, BD718XX_REG_TRANS_COND1, + BD718XX_ON_REQ_POWEROFF_MASK | + BD718XX_SWRESET_POWEROFF_MASK | + BD718XX_WDOG_POWEROFF_MASK | + BD718XX_KEY_L_POWEROFF_MASK, + BD718XX_POWOFF_TO_RDY); + if (err) { + dev_err(&pdev->dev, "Failed to change reset target\n"); + goto err; + } else { + dev_dbg(&pdev->dev, + "Changed all resets from SVNS to READY\n"); + } } for (i = 0; i < pmic_regulators[mfd->chip_type].r_amount; i++) { @@ -1098,19 +1235,33 @@ static int bd718xx_probe(struct platform_device *pdev) err = PTR_ERR(rdev); goto err; } - /* Regulator register gets the regulator constraints and + + /* + * Regulator register gets the regulator constraints and * applies them (set_machine_constraints). This should have * turned the control register(s) to correct values and we * can now switch the control from PMIC state machine to the * register interface + * + * At poweroff transition PMIC HW disables EN bit for + * regulators but leaves SEL bit untouched. So if state + * transition from POWEROFF is done to SNVS - then all power + * rails controlled by SW (having SEL bit set) stay disabled + * as EN is cleared. This will result boot failure if any + * crucial systems are powered by these rails. We don't + * enable SW control for crucial regulators if snvs state is + * used */ - err = regmap_update_bits(mfd->regmap, r->init.reg, - r->init.mask, r->init.val); - if (err) { - dev_err(&pdev->dev, - "Failed to write BUCK/LDO SEL bit for (%s)\n", - desc->name); - goto err; + if (!use_snvs || !rdev->constraints->always_on || + !rdev->constraints->boot_on) { + err = regmap_update_bits(mfd->regmap, r->init.reg, + r->init.mask, r->init.val); + if (err) { + dev_err(&pdev->dev, + "Failed to take control for (%s)\n", + desc->name); + goto err; + } } for (j = 0; j < r->additional_init_amnt; j++) { err = regmap_update_bits(mfd->regmap, diff --git a/drivers/regulator/bd9571mwv-regulator.c b/drivers/regulator/bd9571mwv-regulator.c index e12dd1f750f3..e690c2ce5b3c 100644 --- a/drivers/regulator/bd9571mwv-regulator.c +++ b/drivers/regulator/bd9571mwv-regulator.c @@ -100,7 +100,7 @@ static int bd9571mwv_reg_set_voltage_sel_regmap(struct regulator_dev *rdev, } /* Operations permitted on AVS voltage regulator */ -static struct regulator_ops avs_ops = { +static const struct regulator_ops avs_ops = { .set_voltage_sel = bd9571mwv_avs_set_voltage_sel_regmap, .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = bd9571mwv_avs_get_voltage_sel_regmap, @@ -108,7 +108,7 @@ static struct regulator_ops avs_ops = { }; /* Operations permitted on voltage regulators */ -static struct regulator_ops reg_ops = { +static const struct regulator_ops reg_ops = { .set_voltage_sel = bd9571mwv_reg_set_voltage_sel_regmap, .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -116,13 +116,13 @@ static struct regulator_ops reg_ops = { }; /* Operations permitted on voltage monitors */ -static struct regulator_ops vid_ops = { +static const struct regulator_ops vid_ops = { .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = regulator_list_voltage_linear, }; -static struct regulator_desc regulators[] = { +static const struct regulator_desc regulators[] = { BD9571MWV_REG("VD09", "vd09", VD09, avs_ops, 0, 0x7f, 0x80, 600000, 10000, 0x3c), BD9571MWV_REG("VD18", "vd18", VD18, vid_ops, BD9571MWV_VD18_VID, 0xf, diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 19b35d9f3a97..9cf09666616f 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -23,7 +23,6 @@ #include <linux/mutex.h> #include <linux/suspend.h> #include <linux/delay.h> -#include <linux/gpio.h> #include <linux/gpio/consumer.h> #include <linux/of.h> #include <linux/regmap.h> @@ -82,7 +81,6 @@ struct regulator_enable_gpio { struct gpio_desc *gpiod; u32 enable_count; /* a number of enabled shared GPIO */ u32 request_count; /* a number of requested shared GPIO */ - unsigned int ena_gpio_invert:1; }; /* @@ -145,14 +143,6 @@ static bool regulator_ops_is_valid(struct regulator_dev *rdev, int ops) return false; } -static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev) -{ - if (rdev && rdev->supply) - return rdev->supply->rdev; - - return NULL; -} - /** * regulator_lock_nested - lock a single regulator * @rdev: regulator source @@ -326,7 +316,7 @@ err_unlock: * @rdev: regulator source * @ww_ctx: w/w mutex acquire context * - * Unlock all regulators related with rdev by coupling or suppling. + * Unlock all regulators related with rdev by coupling or supplying. */ static void regulator_unlock_dependent(struct regulator_dev *rdev, struct ww_acquire_ctx *ww_ctx) @@ -341,7 +331,7 @@ static void regulator_unlock_dependent(struct regulator_dev *rdev, * @ww_ctx: w/w mutex acquire context * * This function as a wrapper on regulator_lock_recursive(), which locks - * all regulators related with rdev by coupling or suppling. + * all regulators related with rdev by coupling or supplying. */ static void regulator_lock_dependent(struct regulator_dev *rdev, struct ww_acquire_ctx *ww_ctx) @@ -924,8 +914,6 @@ static int drms_uA_update(struct regulator_dev *rdev) int current_uA = 0, output_uV, input_uV, err; unsigned int mode; - lockdep_assert_held_once(&rdev->mutex.base); - /* * first check to see if we can set modes at all, otherwise just * tell the consumer everything is OK. @@ -1003,7 +991,7 @@ static int suspend_set_state(struct regulator_dev *rdev, if (rstate == NULL) return 0; - /* If we have no suspend mode configration don't set anything; + /* If we have no suspend mode configuration don't set anything; * only warn if the driver implements set_suspend_voltage or * set_suspend_mode callback. */ @@ -1131,7 +1119,7 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, int current_uV = _regulator_get_voltage(rdev); if (current_uV == -ENOTRECOVERABLE) { - /* This regulator can't be read and must be initted */ + /* This regulator can't be read and must be initialized */ rdev_info(rdev, "Setting %d-%duV\n", rdev->constraints->min_uV, rdev->constraints->max_uV); @@ -1782,7 +1770,7 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) struct device *dev = rdev->dev.parent; int ret; - /* No supply to resovle? */ + /* No supply to resolve? */ if (!rdev->supply_name) return 0; @@ -2231,38 +2219,21 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev, { struct regulator_enable_gpio *pin; struct gpio_desc *gpiod; - int ret; - if (config->ena_gpiod) - gpiod = config->ena_gpiod; - else - gpiod = gpio_to_desc(config->ena_gpio); + gpiod = config->ena_gpiod; list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { if (pin->gpiod == gpiod) { - rdev_dbg(rdev, "GPIO %d is already used\n", - config->ena_gpio); + rdev_dbg(rdev, "GPIO is already used\n"); goto update_ena_gpio_to_rdev; } } - if (!config->ena_gpiod) { - ret = gpio_request_one(config->ena_gpio, - GPIOF_DIR_OUT | config->ena_gpio_flags, - rdev_get_name(rdev)); - if (ret) - return ret; - } - pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL); - if (pin == NULL) { - if (!config->ena_gpiod) - gpio_free(config->ena_gpio); + if (pin == NULL) return -ENOMEM; - } pin->gpiod = gpiod; - pin->ena_gpio_invert = config->ena_gpio_invert; list_add(&pin->list, ®ulator_ena_gpio_list); update_ena_gpio_to_rdev: @@ -2283,7 +2254,6 @@ static void regulator_ena_gpio_free(struct regulator_dev *rdev) if (pin->gpiod == rdev->ena_pin->gpiod) { if (pin->request_count <= 1) { pin->request_count = 0; - gpiod_put(pin->gpiod); list_del(&pin->list); kfree(pin); rdev->ena_pin = NULL; @@ -2313,8 +2283,7 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) if (enable) { /* Enable GPIO at initial use */ if (pin->enable_count == 0) - gpiod_set_value_cansleep(pin->gpiod, - !pin->ena_gpio_invert); + gpiod_set_value_cansleep(pin->gpiod, 1); pin->enable_count++; } else { @@ -2325,8 +2294,7 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) /* Disable GPIO if not used */ if (pin->enable_count <= 1) { - gpiod_set_value_cansleep(pin->gpiod, - pin->ena_gpio_invert); + gpiod_set_value_cansleep(pin->gpiod, 0); pin->enable_count = 0; } } @@ -2403,7 +2371,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev) * timer wrapping. * in case of multiple timer wrapping, either it can be * detected by out-of-range remaining, or it cannot be - * detected and we gets a panelty of + * detected and we get a penalty of * _regulator_enable_delay(). */ remaining = intended - start_jiffy; @@ -2803,7 +2771,7 @@ static void regulator_disable_work(struct work_struct *work) /** * regulator_disable_deferred - disable regulator output with delay * @regulator: regulator source - * @ms: miliseconds until the regulator is disabled + * @ms: milliseconds until the regulator is disabled * * Execute regulator_disable() on the regulator after a delay. This * is intended for use with devices that require some time to quiesce. @@ -4937,7 +4905,7 @@ regulator_register(const struct regulator_desc *regulator_desc, * device tree until we have handled it over to the core. If the * config that was passed in to this function DOES NOT contain * a descriptor, and the config after this call DOES contain - * a descriptor, we definately got one from parsing the device + * a descriptor, we definitely got one from parsing the device * tree. */ if (!cfg->ena_gpiod && config->ena_gpiod) @@ -4969,15 +4937,13 @@ regulator_register(const struct regulator_desc *regulator_desc, goto clean; } - if (config->ena_gpiod || - ((config->ena_gpio || config->ena_gpio_initialized) && - gpio_is_valid(config->ena_gpio))) { + if (config->ena_gpiod) { mutex_lock(®ulator_list_mutex); ret = regulator_ena_gpio_request(rdev, config); mutex_unlock(®ulator_list_mutex); if (ret != 0) { - rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", - config->ena_gpio, ret); + rdev_err(rdev, "Failed to request enable GPIO: %d\n", + ret); goto clean; } /* The regulator core took over the GPIO descriptor */ @@ -5245,6 +5211,12 @@ struct device *rdev_get_dev(struct regulator_dev *rdev) } EXPORT_SYMBOL_GPL(rdev_get_dev); +struct regmap *rdev_get_regmap(struct regulator_dev *rdev) +{ + return rdev->regmap; +} +EXPORT_SYMBOL_GPL(rdev_get_regmap); + void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) { return reg_init_data->driver_data; diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c index 588c3d2445cf..417cafe2aba0 100644 --- a/drivers/regulator/da9055-regulator.c +++ b/drivers/regulator/da9055-regulator.c @@ -457,7 +457,6 @@ static int da9055_gpio_init(struct da9055_regulator *regulator, int gpio_mux = pdata->gpio_ren[id]; config->ena_gpiod = pdata->ena_gpiods[id]; - config->ena_gpio_invert = 1; /* * GPI pin is muxed with regulator to control the diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c index 34a70d9dc450..d06e9600fa18 100644 --- a/drivers/regulator/da9062-regulator.c +++ b/drivers/regulator/da9062-regulator.c @@ -1029,31 +1029,50 @@ static int da9062_regulator_probe(struct platform_device *pdev) regl->desc.type = REGULATOR_VOLTAGE; regl->desc.owner = THIS_MODULE; - if (regl->info->mode.reg) + if (regl->info->mode.reg) { regl->mode = devm_regmap_field_alloc( &pdev->dev, chip->regmap, regl->info->mode); - if (regl->info->suspend.reg) + if (IS_ERR(regl->mode)) + return PTR_ERR(regl->mode); + } + + if (regl->info->suspend.reg) { regl->suspend = devm_regmap_field_alloc( &pdev->dev, chip->regmap, regl->info->suspend); - if (regl->info->sleep.reg) + if (IS_ERR(regl->suspend)) + return PTR_ERR(regl->suspend); + } + + if (regl->info->sleep.reg) { regl->sleep = devm_regmap_field_alloc( &pdev->dev, chip->regmap, regl->info->sleep); - if (regl->info->suspend_sleep.reg) + if (IS_ERR(regl->sleep)) + return PTR_ERR(regl->sleep); + } + + if (regl->info->suspend_sleep.reg) { regl->suspend_sleep = devm_regmap_field_alloc( &pdev->dev, chip->regmap, regl->info->suspend_sleep); - if (regl->info->ilimit.reg) + if (IS_ERR(regl->suspend_sleep)) + return PTR_ERR(regl->suspend_sleep); + } + + if (regl->info->ilimit.reg) { regl->ilimit = devm_regmap_field_alloc( &pdev->dev, chip->regmap, regl->info->ilimit); + if (IS_ERR(regl->ilimit)) + return PTR_ERR(regl->ilimit); + } /* Register regulator */ memset(&config, 0, sizeof(config)); diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index 8cbcd2a3eb20..85c45577bad1 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -835,21 +835,40 @@ static int da9063_regulator_probe(struct platform_device *pdev) regl->desc.type = REGULATOR_VOLTAGE; regl->desc.owner = THIS_MODULE; - if (regl->info->mode.reg) + if (regl->info->mode.reg) { regl->mode = devm_regmap_field_alloc(&pdev->dev, da9063->regmap, regl->info->mode); - if (regl->info->suspend.reg) + if (IS_ERR(regl->mode)) + return PTR_ERR(regl->mode); + } + + if (regl->info->suspend.reg) { regl->suspend = devm_regmap_field_alloc(&pdev->dev, da9063->regmap, regl->info->suspend); - if (regl->info->sleep.reg) + if (IS_ERR(regl->suspend)) + return PTR_ERR(regl->suspend); + } + + if (regl->info->sleep.reg) { regl->sleep = devm_regmap_field_alloc(&pdev->dev, da9063->regmap, regl->info->sleep); - if (regl->info->suspend_sleep.reg) + if (IS_ERR(regl->sleep)) + return PTR_ERR(regl->sleep); + } + + if (regl->info->suspend_sleep.reg) { regl->suspend_sleep = devm_regmap_field_alloc(&pdev->dev, da9063->regmap, regl->info->suspend_sleep); - if (regl->info->ilimit.reg) + if (IS_ERR(regl->suspend_sleep)) + return PTR_ERR(regl->suspend_sleep); + } + + if (regl->info->ilimit.reg) { regl->ilimit = devm_regmap_field_alloc(&pdev->dev, da9063->regmap, regl->info->ilimit); + if (IS_ERR(regl->ilimit)) + return PTR_ERR(regl->ilimit); + } /* Register regulator */ memset(&config, 0, sizeof(config)); diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 9abdb9130766..b5afc9db2c61 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -79,15 +79,6 @@ of_get_fixed_voltage_config(struct device *dev, of_property_read_u32(np, "startup-delay-us", &config->startup_delay); - /* - * FIXME: we pulled active low/high and open drain handling into - * gpiolib so it will be handled there. Delete this in the second - * step when we also remove the custom inversion handling for all - * legacy boardfiles. - */ - config->enable_high = 1; - config->gpio_is_open_drain = 0; - if (of_find_property(np, "vin-supply", NULL)) config->input_supply = "vin"; @@ -151,24 +142,14 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) drvdata->desc.fixed_uV = config->microvolts; - cfg.ena_gpio_invert = !config->enable_high; - if (config->enabled_at_boot) { - if (config->enable_high) - gflags = GPIOD_OUT_HIGH; - else - gflags = GPIOD_OUT_LOW; - } else { - if (config->enable_high) - gflags = GPIOD_OUT_LOW; - else - gflags = GPIOD_OUT_HIGH; - } - if (config->gpio_is_open_drain) { - if (gflags == GPIOD_OUT_HIGH) - gflags = GPIOD_OUT_HIGH_OPEN_DRAIN; - else - gflags = GPIOD_OUT_LOW_OPEN_DRAIN; - } + /* + * The signal will be inverted by the GPIO core if flagged so in the + * decriptor. + */ + if (config->enabled_at_boot) + gflags = GPIOD_OUT_HIGH; + else + gflags = GPIOD_OUT_LOW; /* * Some fixed regulators share the enable line between two diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index b2f5ec4f658a..6157001df0a4 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -30,16 +30,15 @@ #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> #include <linux/regulator/gpio-regulator.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/slab.h> #include <linux/of.h> -#include <linux/of_gpio.h> struct gpio_regulator_data { struct regulator_desc desc; struct regulator_dev *dev; - struct gpio *gpios; + struct gpio_desc **gpiods; int nr_gpios; struct gpio_regulator_state *states; @@ -82,7 +81,7 @@ static int gpio_regulator_set_voltage(struct regulator_dev *dev, for (ptr = 0; ptr < data->nr_gpios; ptr++) { state = (target & (1 << ptr)) >> ptr; - gpio_set_value_cansleep(data->gpios[ptr].gpio, state); + gpiod_set_value_cansleep(data->gpiods[ptr], state); } data->state = target; @@ -119,7 +118,7 @@ static int gpio_regulator_set_current_limit(struct regulator_dev *dev, for (ptr = 0; ptr < data->nr_gpios; ptr++) { state = (target & (1 << ptr)) >> ptr; - gpio_set_value_cansleep(data->gpios[ptr].gpio, state); + gpiod_set_value_cansleep(data->gpiods[ptr], state); } data->state = target; @@ -138,7 +137,8 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np, { struct gpio_regulator_config *config; const char *regtype; - int proplen, gpio, i; + int proplen, i; + int ngpios; int ret; config = devm_kzalloc(dev, @@ -153,59 +153,36 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np, config->supply_name = config->init_data->constraints.name; - if (of_property_read_bool(np, "enable-active-high")) - config->enable_high = true; - if (of_property_read_bool(np, "enable-at-boot")) config->enabled_at_boot = true; of_property_read_u32(np, "startup-delay-us", &config->startup_delay); - config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0); - if (config->enable_gpio < 0 && config->enable_gpio != -ENOENT) - return ERR_PTR(config->enable_gpio); - - /* Fetch GPIOs. - optional property*/ - ret = of_gpio_count(np); - if ((ret < 0) && (ret != -ENOENT)) - return ERR_PTR(ret); - - if (ret > 0) { - config->nr_gpios = ret; - config->gpios = devm_kcalloc(dev, - config->nr_gpios, sizeof(struct gpio), - GFP_KERNEL); - if (!config->gpios) + /* Fetch GPIO init levels */ + ngpios = gpiod_count(dev, NULL); + if (ngpios > 0) { + config->gflags = devm_kzalloc(dev, + sizeof(enum gpiod_flags) + * ngpios, + GFP_KERNEL); + if (!config->gflags) return ERR_PTR(-ENOMEM); - proplen = of_property_count_u32_elems(np, "gpios-states"); - /* optional property */ - if (proplen < 0) - proplen = 0; + for (i = 0; i < ngpios; i++) { + u32 val; - if (proplen > 0 && proplen != config->nr_gpios) { - dev_warn(dev, "gpios <-> gpios-states mismatch\n"); - proplen = 0; - } + ret = of_property_read_u32_index(np, "gpios-states", i, + &val); - for (i = 0; i < config->nr_gpios; i++) { - gpio = of_get_named_gpio(np, "gpios", i); - if (gpio < 0) { - if (gpio != -ENOENT) - return ERR_PTR(gpio); - break; - } - config->gpios[i].gpio = gpio; - config->gpios[i].label = config->supply_name; - if (proplen > 0) { - of_property_read_u32_index(np, "gpios-states", - i, &ret); - if (ret) - config->gpios[i].flags = - GPIOF_OUT_INIT_HIGH; - } + /* Default to high per specification */ + if (ret) + config->gflags[i] = GPIOD_OUT_HIGH; + else + config->gflags[i] = + val ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; } } + config->ngpios = ngpios; /* Fetch states. */ proplen = of_property_count_u32_elems(np, "states"); @@ -251,59 +228,56 @@ static struct regulator_ops gpio_regulator_current_ops = { static int gpio_regulator_probe(struct platform_device *pdev) { - struct gpio_regulator_config *config = dev_get_platdata(&pdev->dev); - struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct gpio_regulator_config *config = dev_get_platdata(dev); + struct device_node *np = dev->of_node; struct gpio_regulator_data *drvdata; struct regulator_config cfg = { }; - int ptr, ret, state; + enum gpiod_flags gflags; + int ptr, ret, state, i; - drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data), + drvdata = devm_kzalloc(dev, sizeof(struct gpio_regulator_data), GFP_KERNEL); if (drvdata == NULL) return -ENOMEM; if (np) { - config = of_get_gpio_regulator_config(&pdev->dev, np, + config = of_get_gpio_regulator_config(dev, np, &drvdata->desc); if (IS_ERR(config)) return PTR_ERR(config); } - drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL); + drvdata->desc.name = devm_kstrdup(dev, config->supply_name, GFP_KERNEL); if (drvdata->desc.name == NULL) { - dev_err(&pdev->dev, "Failed to allocate supply name\n"); + dev_err(dev, "Failed to allocate supply name\n"); return -ENOMEM; } - if (config->nr_gpios != 0) { - drvdata->gpios = kmemdup(config->gpios, - config->nr_gpios * sizeof(struct gpio), - GFP_KERNEL); - if (drvdata->gpios == NULL) { - dev_err(&pdev->dev, "Failed to allocate gpio data\n"); - ret = -ENOMEM; - goto err_name; - } - - drvdata->nr_gpios = config->nr_gpios; - ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "Could not obtain regulator setting GPIOs: %d\n", - ret); - goto err_memgpio; - } + drvdata->gpiods = devm_kzalloc(dev, sizeof(struct gpio_desc *), + GFP_KERNEL); + if (!drvdata->gpiods) + return -ENOMEM; + for (i = 0; i < config->ngpios; i++) { + drvdata->gpiods[i] = devm_gpiod_get_index(dev, + NULL, + i, + config->gflags[i]); + if (IS_ERR(drvdata->gpiods[i])) + return PTR_ERR(drvdata->gpiods[i]); + /* This is good to know */ + gpiod_set_consumer_name(drvdata->gpiods[i], drvdata->desc.name); } + drvdata->nr_gpios = config->ngpios; - drvdata->states = kmemdup(config->states, - config->nr_states * - sizeof(struct gpio_regulator_state), - GFP_KERNEL); + drvdata->states = devm_kmemdup(dev, + config->states, + config->nr_states * + sizeof(struct gpio_regulator_state), + GFP_KERNEL); if (drvdata->states == NULL) { - dev_err(&pdev->dev, "Failed to allocate state data\n"); - ret = -ENOMEM; - goto err_stategpio; + dev_err(dev, "Failed to allocate state data\n"); + return -ENOMEM; } drvdata->nr_states = config->nr_states; @@ -322,61 +296,46 @@ static int gpio_regulator_probe(struct platform_device *pdev) drvdata->desc.ops = &gpio_regulator_current_ops; break; default: - dev_err(&pdev->dev, "No regulator type set\n"); - ret = -EINVAL; - goto err_memstate; + dev_err(dev, "No regulator type set\n"); + return -EINVAL; } /* build initial state from gpio init data. */ state = 0; for (ptr = 0; ptr < drvdata->nr_gpios; ptr++) { - if (config->gpios[ptr].flags & GPIOF_OUT_INIT_HIGH) + if (config->gflags[ptr] == GPIOD_OUT_HIGH) state |= (1 << ptr); } drvdata->state = state; - cfg.dev = &pdev->dev; + cfg.dev = dev; cfg.init_data = config->init_data; cfg.driver_data = drvdata; cfg.of_node = np; - if (gpio_is_valid(config->enable_gpio)) { - cfg.ena_gpio = config->enable_gpio; - cfg.ena_gpio_initialized = true; - } - cfg.ena_gpio_invert = !config->enable_high; - if (config->enabled_at_boot) { - if (config->enable_high) - cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH; - else - cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW; - } else { - if (config->enable_high) - cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW; - else - cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH; - } + /* + * The signal will be inverted by the GPIO core if flagged so in the + * decriptor. + */ + if (config->enabled_at_boot) + gflags = GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE; + else + gflags = GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE; + + cfg.ena_gpiod = gpiod_get_optional(dev, "enable", gflags); + if (IS_ERR(cfg.ena_gpiod)) + return PTR_ERR(cfg.ena_gpiod); drvdata->dev = regulator_register(&drvdata->desc, &cfg); if (IS_ERR(drvdata->dev)) { ret = PTR_ERR(drvdata->dev); - dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); - goto err_memstate; + dev_err(dev, "Failed to register regulator: %d\n", ret); + return ret; } platform_set_drvdata(pdev, drvdata); return 0; - -err_memstate: - kfree(drvdata->states); -err_stategpio: - gpio_free_array(drvdata->gpios, drvdata->nr_gpios); -err_memgpio: - kfree(drvdata->gpios); -err_name: - kfree(drvdata->desc.name); - return ret; } static int gpio_regulator_remove(struct platform_device *pdev) @@ -385,13 +344,6 @@ static int gpio_regulator_remove(struct platform_device *pdev) regulator_unregister(drvdata->dev); - gpio_free_array(drvdata->gpios, drvdata->nr_gpios); - - kfree(drvdata->states); - kfree(drvdata->gpios); - - kfree(drvdata->desc.name); - return 0; } diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c index 5686a1335bd3..68ac6017ef28 100644 --- a/drivers/regulator/helpers.c +++ b/drivers/regulator/helpers.c @@ -594,28 +594,30 @@ int regulator_list_voltage_pickable_linear_range(struct regulator_dev *rdev, EXPORT_SYMBOL_GPL(regulator_list_voltage_pickable_linear_range); /** - * regulator_list_voltage_linear_range - List voltages for linear ranges + * regulator_desc_list_voltage_linear_range - List voltages for linear ranges * - * @rdev: Regulator device + * @desc: Regulator desc for regulator which volatges are to be listed * @selector: Selector to convert into a voltage * * Regulators with a series of simple linear mappings between voltages - * and selectors can set linear_ranges in the regulator descriptor and - * then use this function as their list_voltage() operation, + * and selectors who have set linear_ranges in the regulator descriptor + * can use this function prior regulator registration to list voltages. + * This is useful when voltages need to be listed during device-tree + * parsing. */ -int regulator_list_voltage_linear_range(struct regulator_dev *rdev, - unsigned int selector) +int regulator_desc_list_voltage_linear_range(const struct regulator_desc *desc, + unsigned int selector) { const struct regulator_linear_range *range; int i; - if (!rdev->desc->n_linear_ranges) { - BUG_ON(!rdev->desc->n_linear_ranges); + if (!desc->n_linear_ranges) { + BUG_ON(!desc->n_linear_ranges); return -EINVAL; } - for (i = 0; i < rdev->desc->n_linear_ranges; i++) { - range = &rdev->desc->linear_ranges[i]; + for (i = 0; i < desc->n_linear_ranges; i++) { + range = &desc->linear_ranges[i]; if (!(selector >= range->min_sel && selector <= range->max_sel)) @@ -628,6 +630,23 @@ int regulator_list_voltage_linear_range(struct regulator_dev *rdev, return -EINVAL; } +EXPORT_SYMBOL_GPL(regulator_desc_list_voltage_linear_range); + +/** + * regulator_list_voltage_linear_range - List voltages for linear ranges + * + * @rdev: Regulator device + * @selector: Selector to convert into a voltage + * + * Regulators with a series of simple linear mappings between voltages + * and selectors can set linear_ranges in the regulator descriptor and + * then use this function as their list_voltage() operation, + */ +int regulator_list_voltage_linear_range(struct regulator_dev *rdev, + unsigned int selector) +{ + return regulator_desc_list_voltage_linear_range(rdev->desc, selector); +} EXPORT_SYMBOL_GPL(regulator_list_voltage_linear_range); /** diff --git a/drivers/regulator/hi655x-regulator.c b/drivers/regulator/hi655x-regulator.c index 36ae54b53814..bba24a6fdb1e 100644 --- a/drivers/regulator/hi655x-regulator.c +++ b/drivers/regulator/hi655x-regulator.c @@ -28,7 +28,6 @@ struct hi655x_regulator { unsigned int disable_reg; unsigned int status_reg; - unsigned int ctrl_regs; unsigned int ctrl_mask; struct regulator_desc rdesc; }; diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index 4abd8e9c81e5..6f28bba81d13 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -31,7 +31,6 @@ /* PMIC details */ struct isl_pmic { struct i2c_client *client; - struct regulator_dev *rdev[3]; struct mutex mtx; }; @@ -66,14 +65,14 @@ static int isl6271a_set_voltage_sel(struct regulator_dev *dev, return err; } -static struct regulator_ops isl_core_ops = { +static const struct regulator_ops isl_core_ops = { .get_voltage_sel = isl6271a_get_voltage_sel, .set_voltage_sel = isl6271a_set_voltage_sel, .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, }; -static struct regulator_ops isl_fixed_ops = { +static const struct regulator_ops isl_fixed_ops = { .list_voltage = regulator_list_voltage_linear, }; @@ -109,6 +108,7 @@ static const struct regulator_desc isl_rd[] = { static int isl6271a_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { + struct regulator_dev *rdev; struct regulator_config config = { }; struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev); struct isl_pmic *pmic; @@ -133,11 +133,10 @@ static int isl6271a_probe(struct i2c_client *i2c, config.init_data = NULL; config.driver_data = pmic; - pmic->rdev[i] = devm_regulator_register(&i2c->dev, &isl_rd[i], - &config); - if (IS_ERR(pmic->rdev[i])) { + rdev = devm_regulator_register(&i2c->dev, &isl_rd[i], &config); + if (IS_ERR(rdev)) { dev_err(&i2c->dev, "failed to register %s\n", id->name); - return PTR_ERR(pmic->rdev[i]); + return PTR_ERR(rdev); } } diff --git a/drivers/regulator/lm363x-regulator.c b/drivers/regulator/lm363x-regulator.c index 8c0e8419c43f..c876e161052a 100644 --- a/drivers/regulator/lm363x-regulator.c +++ b/drivers/regulator/lm363x-regulator.c @@ -258,6 +258,9 @@ static int lm363x_regulator_probe(struct platform_device *pdev) * Register update is required if the pin is used. */ gpiod = lm363x_regulator_of_get_enable_gpio(dev, id); + if (IS_ERR(gpiod)) + return PTR_ERR(gpiod); + if (gpiod) { cfg.ena_gpiod = gpiod; @@ -265,8 +268,7 @@ static int lm363x_regulator_probe(struct platform_device *pdev) LM3632_EXT_EN_MASK, LM3632_EXT_EN_MASK); if (ret) { - if (gpiod) - gpiod_put(gpiod); + gpiod_put(gpiod); dev_err(dev, "External pin err: %d\n", ret); return ret; } diff --git a/drivers/regulator/lochnagar-regulator.c b/drivers/regulator/lochnagar-regulator.c index 47f5663e99c8..ff97cc50f2eb 100644 --- a/drivers/regulator/lochnagar-regulator.c +++ b/drivers/regulator/lochnagar-regulator.c @@ -232,8 +232,9 @@ static const struct of_device_id lochnagar_of_match[] = { .compatible = "cirrus,lochnagar2-vddcore", .data = &lochnagar_regulators[LOCHNAGAR_VDDCORE], }, - {}, + {} }; +MODULE_DEVICE_TABLE(of, lochnagar_of_match); static int lochnagar_regulator_probe(struct platform_device *pdev) { diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 204b5c5270e0..9e45112658ba 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -159,7 +159,7 @@ static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev, selector << LDO_VOL_CONTR_SHIFT(ldo)); } -static struct regulator_ops lp3971_ldo_ops = { +static const struct regulator_ops lp3971_ldo_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .is_enabled = lp3971_ldo_is_enabled, @@ -233,7 +233,7 @@ static int lp3971_dcdc_set_voltage_sel(struct regulator_dev *dev, 0 << BUCK_VOL_CHANGE_SHIFT(buck)); } -static struct regulator_ops lp3971_dcdc_ops = { +static const struct regulator_ops lp3971_dcdc_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .is_enabled = lp3971_dcdc_is_enabled, diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index ff0c275f902e..fb098198b688 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -305,7 +305,7 @@ static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev, return ret; } -static struct regulator_ops lp3972_ldo_ops = { +static const struct regulator_ops lp3972_ldo_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .is_enabled = lp3972_ldo_is_enabled, @@ -386,7 +386,7 @@ static int lp3972_dcdc_set_voltage_sel(struct regulator_dev *dev, LP3972_VOL_CHANGE_FLAG_MASK, 0); } -static struct regulator_ops lp3972_dcdc_ops = { +static const struct regulator_ops lp3972_dcdc_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .is_enabled = lp3972_dcdc_is_enabled, diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 38992112fd6e..f8f875bad7dd 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -478,7 +478,7 @@ static unsigned int lp872x_buck_get_mode(struct regulator_dev *rdev) return val & mask ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; } -static struct regulator_ops lp872x_ldo_ops = { +static const struct regulator_ops lp872x_ldo_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .set_voltage_sel = regulator_set_voltage_sel_regmap, @@ -489,7 +489,7 @@ static struct regulator_ops lp872x_ldo_ops = { .enable_time = lp872x_regulator_enable_time, }; -static struct regulator_ops lp8720_buck_ops = { +static const struct regulator_ops lp8720_buck_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .set_voltage_sel = lp872x_buck_set_voltage_sel, @@ -502,7 +502,7 @@ static struct regulator_ops lp8720_buck_ops = { .get_mode = lp872x_buck_get_mode, }; -static struct regulator_ops lp8725_buck_ops = { +static const struct regulator_ops lp8725_buck_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .set_voltage_sel = lp872x_buck_set_voltage_sel, @@ -517,7 +517,7 @@ static struct regulator_ops lp8725_buck_ops = { .get_current_limit = lp8725_buck_get_current_limit, }; -static struct regulator_desc lp8720_regulator_desc[] = { +static const struct regulator_desc lp8720_regulator_desc[] = { { .name = "ldo1", .of_match = of_match_ptr("ldo1"), @@ -602,7 +602,7 @@ static struct regulator_desc lp8720_regulator_desc[] = { }, }; -static struct regulator_desc lp8725_regulator_desc[] = { +static const struct regulator_desc lp8725_regulator_desc[] = { { .name = "ldo1", .of_match = of_match_ptr("ldo1"), @@ -820,7 +820,7 @@ static struct regulator_init_data static int lp872x_regulator_register(struct lp872x *lp) { - struct regulator_desc *desc; + const struct regulator_desc *desc; struct regulator_config cfg = { }; struct regulator_dev *rdev; int i; diff --git a/drivers/regulator/lp873x-regulator.c b/drivers/regulator/lp873x-regulator.c index 70e3df653381..2ec5e833c379 100644 --- a/drivers/regulator/lp873x-regulator.c +++ b/drivers/regulator/lp873x-regulator.c @@ -146,7 +146,7 @@ static int lp873x_buck_get_current_limit(struct regulator_dev *rdev) } /* Operations permitted on BUCK0, BUCK1 */ -static struct regulator_ops lp873x_buck01_ops = { +static const struct regulator_ops lp873x_buck01_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -161,7 +161,7 @@ static struct regulator_ops lp873x_buck01_ops = { }; /* Operations permitted on LDO0 and LDO1 */ -static struct regulator_ops lp873x_ldo01_ops = { +static const struct regulator_ops lp873x_ldo01_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index 244822bb63cd..14fd38807134 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -315,7 +315,7 @@ out_i2c_error: .vsel_mask = LP8755_BUCK_VOUT_M,\ } -static struct regulator_desc lp8755_regulators[] = { +static const struct regulator_desc lp8755_regulators[] = { lp8755_buck_desc(0), lp8755_buck_desc(1), lp8755_buck_desc(2), @@ -386,7 +386,7 @@ static irqreturn_t lp8755_irq_handler(int irq, void *data) if (ret < 0) goto err_i2c; - /* send OCP event to all regualtor devices */ + /* send OCP event to all regulator devices */ if ((flag1 & 0x01) && (pchip->irqmask & 0x01)) for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) if (pchip->rdev[icnt] != NULL) @@ -394,7 +394,7 @@ static irqreturn_t lp8755_irq_handler(int irq, void *data) LP8755_EVENT_OCP, NULL); - /* send OVP event to all regualtor devices */ + /* send OVP event to all regulator devices */ if ((flag1 & 0x02) && (pchip->irqmask & 0x02)) for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) if (pchip->rdev[icnt] != NULL) diff --git a/drivers/regulator/lp87565-regulator.c b/drivers/regulator/lp87565-regulator.c index c192357d1dea..4ed41731a5b1 100644 --- a/drivers/regulator/lp87565-regulator.c +++ b/drivers/regulator/lp87565-regulator.c @@ -51,7 +51,7 @@ static const struct regulator_linear_range buck0_1_2_3_ranges[] = { REGULATOR_LINEAR_RANGE(1420000, 0x9e, 0xff, 20000), }; -static unsigned int lp87565_buck_ramp_delay[] = { +static const unsigned int lp87565_buck_ramp_delay[] = { 30000, 15000, 10000, 7500, 3800, 1900, 940, 470 }; @@ -140,7 +140,7 @@ static int lp87565_buck_get_current_limit(struct regulator_dev *rdev) } /* Operations permitted on BUCK0, BUCK1 */ -static struct regulator_ops lp87565_buck_ops = { +static const struct regulator_ops lp87565_buck_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c index ec46290b647e..a7d30550bb5f 100644 --- a/drivers/regulator/lp8788-buck.c +++ b/drivers/regulator/lp8788-buck.c @@ -95,12 +95,10 @@ struct lp8788_buck { void *dvs; }; -/* BUCK 1 ~ 4 voltage table */ -static const int lp8788_buck_vtbl[] = { - 500000, 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, - 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, - 1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, - 1950000, 2000000, +/* BUCK 1 ~ 4 voltage ranges */ +static const struct regulator_linear_range buck_volt_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 0, 0), + REGULATOR_LINEAR_RANGE(800000, 1, 25, 50000), }; static void lp8788_buck1_set_dvs(struct lp8788_buck *buck) @@ -345,8 +343,8 @@ static unsigned int lp8788_buck_get_mode(struct regulator_dev *rdev) } static const struct regulator_ops lp8788_buck12_ops = { - .list_voltage = regulator_list_voltage_table, - .map_voltage = regulator_map_voltage_ascend, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, .set_voltage_sel = lp8788_buck12_set_voltage_sel, .get_voltage_sel = lp8788_buck12_get_voltage_sel, .enable = regulator_enable_regmap, @@ -358,8 +356,8 @@ static const struct regulator_ops lp8788_buck12_ops = { }; static const struct regulator_ops lp8788_buck34_ops = { - .list_voltage = regulator_list_voltage_table, - .map_voltage = regulator_map_voltage_ascend, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .enable = regulator_enable_regmap, @@ -370,13 +368,14 @@ static const struct regulator_ops lp8788_buck34_ops = { .get_mode = lp8788_buck_get_mode, }; -static struct regulator_desc lp8788_buck_desc[] = { +static const struct regulator_desc lp8788_buck_desc[] = { { .name = "buck1", .id = BUCK1, .ops = &lp8788_buck12_ops, - .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl), - .volt_table = lp8788_buck_vtbl, + .n_voltages = 26, + .linear_ranges = buck_volt_ranges, + .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges), .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_BUCK, @@ -386,8 +385,9 @@ static struct regulator_desc lp8788_buck_desc[] = { .name = "buck2", .id = BUCK2, .ops = &lp8788_buck12_ops, - .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl), - .volt_table = lp8788_buck_vtbl, + .n_voltages = 26, + .linear_ranges = buck_volt_ranges, + .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges), .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .enable_reg = LP8788_EN_BUCK, @@ -397,8 +397,9 @@ static struct regulator_desc lp8788_buck_desc[] = { .name = "buck3", .id = BUCK3, .ops = &lp8788_buck34_ops, - .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl), - .volt_table = lp8788_buck_vtbl, + .n_voltages = 26, + .linear_ranges = buck_volt_ranges, + .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges), .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .vsel_reg = LP8788_BUCK3_VOUT, @@ -410,8 +411,9 @@ static struct regulator_desc lp8788_buck_desc[] = { .name = "buck4", .id = BUCK4, .ops = &lp8788_buck34_ops, - .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl), - .volt_table = lp8788_buck_vtbl, + .n_voltages = 26, + .linear_ranges = buck_volt_ranges, + .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges), .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .vsel_reg = LP8788_BUCK4_VOUT, diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c index 2ee22e7ea675..a2ef146e6b3a 100644 --- a/drivers/regulator/lp8788-ldo.c +++ b/drivers/regulator/lp8788-ldo.c @@ -186,7 +186,7 @@ static const struct regulator_ops lp8788_ldo_voltage_fixed_ops = { .enable_time = lp8788_ldo_enable_time, }; -static struct regulator_desc lp8788_dldo_desc[] = { +static const struct regulator_desc lp8788_dldo_desc[] = { { .name = "dldo1", .id = DLDO1, @@ -343,7 +343,7 @@ static struct regulator_desc lp8788_dldo_desc[] = { }, }; -static struct regulator_desc lp8788_aldo_desc[] = { +static const struct regulator_desc lp8788_aldo_desc[] = { { .name = "aldo1", .id = ALDO1, diff --git a/drivers/regulator/ltc3676.c b/drivers/regulator/ltc3676.c index 71fd0f2a4b76..e6d66e492b85 100644 --- a/drivers/regulator/ltc3676.c +++ b/drivers/regulator/ltc3676.c @@ -241,61 +241,10 @@ static struct regulator_desc ltc3676_regulators[LTC3676_NUM_REGULATORS] = { LTC3676_FIXED_REG(LDO4, ldo4, LDOB, 2), }; -static bool ltc3676_writeable_reg(struct device *dev, unsigned int reg) +static bool ltc3676_readable_writeable_reg(struct device *dev, unsigned int reg) { switch (reg) { - case LTC3676_IRQSTAT: - case LTC3676_BUCK1: - case LTC3676_BUCK2: - case LTC3676_BUCK3: - case LTC3676_BUCK4: - case LTC3676_LDOA: - case LTC3676_LDOB: - case LTC3676_SQD1: - case LTC3676_SQD2: - case LTC3676_CNTRL: - case LTC3676_DVB1A: - case LTC3676_DVB1B: - case LTC3676_DVB2A: - case LTC3676_DVB2B: - case LTC3676_DVB3A: - case LTC3676_DVB3B: - case LTC3676_DVB4A: - case LTC3676_DVB4B: - case LTC3676_MSKIRQ: - case LTC3676_MSKPG: - case LTC3676_USER: - case LTC3676_HRST: - case LTC3676_CLIRQ: - return true; - } - return false; -} - -static bool ltc3676_readable_reg(struct device *dev, unsigned int reg) -{ - switch (reg) { - case LTC3676_IRQSTAT: - case LTC3676_BUCK1: - case LTC3676_BUCK2: - case LTC3676_BUCK3: - case LTC3676_BUCK4: - case LTC3676_LDOA: - case LTC3676_LDOB: - case LTC3676_SQD1: - case LTC3676_SQD2: - case LTC3676_CNTRL: - case LTC3676_DVB1A: - case LTC3676_DVB1B: - case LTC3676_DVB2A: - case LTC3676_DVB2B: - case LTC3676_DVB3A: - case LTC3676_DVB3B: - case LTC3676_DVB4A: - case LTC3676_DVB4B: - case LTC3676_MSKIRQ: - case LTC3676_MSKPG: - case LTC3676_USER: + case LTC3676_BUCK1 ... LTC3676_IRQSTAT: case LTC3676_HRST: case LTC3676_CLIRQ: return true; @@ -306,9 +255,7 @@ static bool ltc3676_readable_reg(struct device *dev, unsigned int reg) static bool ltc3676_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { - case LTC3676_IRQSTAT: - case LTC3676_PGSTATL: - case LTC3676_PGSTATRT: + case LTC3676_IRQSTAT ... LTC3676_PGSTATRT: return true; } return false; @@ -317,8 +264,8 @@ static bool ltc3676_volatile_reg(struct device *dev, unsigned int reg) static const struct regmap_config ltc3676_regmap_config = { .reg_bits = 8, .val_bits = 8, - .writeable_reg = ltc3676_writeable_reg, - .readable_reg = ltc3676_readable_reg, + .writeable_reg = ltc3676_readable_writeable_reg, + .readable_reg = ltc3676_readable_writeable_reg, .volatile_reg = ltc3676_volatile_reg, .max_register = LTC3676_CLIRQ, .use_single_read = true, @@ -442,5 +389,5 @@ static struct i2c_driver ltc3676_driver = { module_i2c_driver(ltc3676_driver); MODULE_AUTHOR("Tim Harvey <tharvey@gateworks.com>"); -MODULE_DESCRIPTION("Regulator driver for Linear Technology LTC1376"); +MODULE_DESCRIPTION("Regulator driver for Linear Technology LTC3676"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/max14577-regulator.c b/drivers/regulator/max14577-regulator.c index bc7f4751bf9c..85a88a9e4d42 100644 --- a/drivers/regulator/max14577-regulator.c +++ b/drivers/regulator/max14577-regulator.c @@ -324,4 +324,3 @@ module_exit(max14577_regulator_exit); MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>"); MODULE_DESCRIPTION("Maxim 14577/77836 regulator driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:max14577-regulator"); diff --git a/drivers/regulator/max77650-regulator.c b/drivers/regulator/max77650-regulator.c new file mode 100644 index 000000000000..5afb91400832 --- /dev/null +++ b/drivers/regulator/max77650-regulator.c @@ -0,0 +1,518 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2018 BayLibre SAS +// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com> +// +// Regulator driver for MAXIM 77650/77651 charger/power-supply. + +#include <linux/of.h> +#include <linux/mfd/max77650.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> + +#define MAX77650_REGULATOR_EN_CTRL_MASK GENMASK(3, 0) +#define MAX77650_REGULATOR_EN_CTRL_BITS(_reg) \ + ((_reg) & MAX77650_REGULATOR_EN_CTRL_MASK) +#define MAX77650_REGULATOR_ENABLED GENMASK(2, 1) +#define MAX77650_REGULATOR_DISABLED BIT(2) + +#define MAX77650_REGULATOR_V_LDO_MASK GENMASK(6, 0) +#define MAX77650_REGULATOR_V_SBB_MASK GENMASK(5, 0) + +#define MAX77650_REGULATOR_AD_MASK BIT(3) +#define MAX77650_REGULATOR_AD_DISABLED 0x00 +#define MAX77650_REGULATOR_AD_ENABLED BIT(3) + +#define MAX77650_REGULATOR_CURR_LIM_MASK GENMASK(7, 6) +#define MAX77650_REGULATOR_CURR_LIM_BITS(_reg) \ + (((_reg) & MAX77650_REGULATOR_CURR_LIM_MASK) >> 6) +#define MAX77650_REGULATOR_CURR_LIM_SHIFT(_val) ((_val) << 6) + +enum { + MAX77650_REGULATOR_ID_LDO = 0, + MAX77650_REGULATOR_ID_SBB0, + MAX77650_REGULATOR_ID_SBB1, + MAX77650_REGULATOR_ID_SBB2, + MAX77650_REGULATOR_NUM_REGULATORS, +}; + +struct max77650_regulator_desc { + struct regulator_desc desc; + unsigned int regA; + unsigned int regB; +}; + +static const u32 max77651_sbb1_regulator_volt_table[] = { + 2400000, 3200000, 4000000, 4800000, + 2450000, 3250000, 4050000, 4850000, + 2500000, 3300000, 4100000, 4900000, + 2550000, 3350000, 4150000, 4950000, + 2600000, 3400000, 4200000, 5000000, + 2650000, 3450000, 4250000, 5050000, + 2700000, 3500000, 4300000, 5100000, + 2750000, 3550000, 4350000, 5150000, + 2800000, 3600000, 4400000, 5200000, + 2850000, 3650000, 4450000, 5250000, + 2900000, 3700000, 4500000, 0, + 2950000, 3750000, 4550000, 0, + 3000000, 3800000, 4600000, 0, + 3050000, 3850000, 4650000, 0, + 3100000, 3900000, 4700000, 0, + 3150000, 3950000, 4750000, 0, +}; + +#define MAX77651_REGULATOR_SBB1_SEL_DEC(_val) \ + (((_val & 0x3c) >> 2) | ((_val & 0x03) << 4)) +#define MAX77651_REGULATOR_SBB1_SEL_ENC(_val) \ + (((_val & 0x30) >> 4) | ((_val & 0x0f) << 2)) + +#define MAX77650_REGULATOR_SBB1_SEL_DECR(_val) \ + do { \ + _val = MAX77651_REGULATOR_SBB1_SEL_DEC(_val); \ + _val--; \ + _val = MAX77651_REGULATOR_SBB1_SEL_ENC(_val); \ + } while (0) + +#define MAX77650_REGULATOR_SBB1_SEL_INCR(_val) \ + do { \ + _val = MAX77651_REGULATOR_SBB1_SEL_DEC(_val); \ + _val++; \ + _val = MAX77651_REGULATOR_SBB1_SEL_ENC(_val); \ + } while (0) + +static const int max77650_current_limit_table[] = { + 1000000, 866000, 707000, 500000, +}; + +static int max77650_regulator_is_enabled(struct regulator_dev *rdev) +{ + struct max77650_regulator_desc *rdesc; + struct regmap *map; + int val, rv, en; + + rdesc = rdev_get_drvdata(rdev); + map = rdev_get_regmap(rdev); + + rv = regmap_read(map, rdesc->regB, &val); + if (rv) + return rv; + + en = MAX77650_REGULATOR_EN_CTRL_BITS(val); + + return en != MAX77650_REGULATOR_DISABLED; +} + +static int max77650_regulator_enable(struct regulator_dev *rdev) +{ + struct max77650_regulator_desc *rdesc; + struct regmap *map; + + rdesc = rdev_get_drvdata(rdev); + map = rdev_get_regmap(rdev); + + return regmap_update_bits(map, rdesc->regB, + MAX77650_REGULATOR_EN_CTRL_MASK, + MAX77650_REGULATOR_ENABLED); +} + +static int max77650_regulator_disable(struct regulator_dev *rdev) +{ + struct max77650_regulator_desc *rdesc; + struct regmap *map; + + rdesc = rdev_get_drvdata(rdev); + map = rdev_get_regmap(rdev); + + return regmap_update_bits(map, rdesc->regB, + MAX77650_REGULATOR_EN_CTRL_MASK, + MAX77650_REGULATOR_DISABLED); +} + +static int max77650_regulator_set_voltage_sel(struct regulator_dev *rdev, + unsigned int sel) +{ + int rv = 0, curr, diff; + bool ascending; + + /* + * If the regulator is disabled, we can program the desired + * voltage right away. + */ + if (!max77650_regulator_is_enabled(rdev)) + return regulator_set_voltage_sel_regmap(rdev, sel); + + /* + * Otherwise we need to manually ramp the output voltage up/down + * one step at a time. + */ + + curr = regulator_get_voltage_sel_regmap(rdev); + if (curr < 0) + return curr; + + diff = curr - sel; + if (diff == 0) + return 0; /* Already there. */ + else if (diff > 0) + ascending = false; + else + ascending = true; + + /* + * Make sure we'll get to the right voltage and break the loop even if + * the selector equals 0. + */ + for (ascending ? curr++ : curr--;; ascending ? curr++ : curr--) { + rv = regulator_set_voltage_sel_regmap(rdev, curr); + if (rv) + return rv; + + if (curr == sel) + break; + } + + return 0; +} + +/* + * Special case: non-linear voltage table for max77651 SBB1 - software + * must ensure the voltage is ramped in 50mV increments. + */ +static int max77651_regulator_sbb1_set_voltage_sel(struct regulator_dev *rdev, + unsigned int sel) +{ + int rv = 0, curr, vcurr, vdest, vdiff; + + /* + * If the regulator is disabled, we can program the desired + * voltage right away. + */ + if (!max77650_regulator_is_enabled(rdev)) + return regulator_set_voltage_sel_regmap(rdev, sel); + + curr = regulator_get_voltage_sel_regmap(rdev); + if (curr < 0) + return curr; + + if (curr == sel) + return 0; /* Already there. */ + + vcurr = max77651_sbb1_regulator_volt_table[curr]; + vdest = max77651_sbb1_regulator_volt_table[sel]; + vdiff = vcurr - vdest; + + for (;;) { + if (vdiff > 0) + MAX77650_REGULATOR_SBB1_SEL_DECR(curr); + else + MAX77650_REGULATOR_SBB1_SEL_INCR(curr); + + rv = regulator_set_voltage_sel_regmap(rdev, curr); + if (rv) + return rv; + + if (curr == sel) + break; + }; + + return 0; +} + +static int max77650_regulator_get_current_limit(struct regulator_dev *rdev) +{ + struct max77650_regulator_desc *rdesc; + struct regmap *map; + int val, rv, limit; + + rdesc = rdev_get_drvdata(rdev); + map = rdev_get_regmap(rdev); + + rv = regmap_read(map, rdesc->regA, &val); + if (rv) + return rv; + + limit = MAX77650_REGULATOR_CURR_LIM_BITS(val); + + return max77650_current_limit_table[limit]; +} + +static int max77650_regulator_set_current_limit(struct regulator_dev *rdev, + int min_uA, int max_uA) +{ + struct max77650_regulator_desc *rdesc; + struct regmap *map; + int rv, i, limit; + + rdesc = rdev_get_drvdata(rdev); + map = rdev_get_regmap(rdev); + + for (i = 0; i < ARRAY_SIZE(max77650_current_limit_table); i++) { + limit = max77650_current_limit_table[i]; + + if (limit >= min_uA && limit <= max_uA) { + rv = regmap_update_bits(map, rdesc->regA, + MAX77650_REGULATOR_CURR_LIM_MASK, + MAX77650_REGULATOR_CURR_LIM_SHIFT(i)); + if (rv) + return rv; + } + } + + return -EINVAL; +} + +static const struct regulator_ops max77650_regulator_LDO_ops = { + .is_enabled = max77650_regulator_is_enabled, + .enable = max77650_regulator_enable, + .disable = max77650_regulator_disable, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = max77650_regulator_set_voltage_sel, + .set_active_discharge = regulator_set_active_discharge_regmap, +}; + +static const struct regulator_ops max77650_regulator_SBB_ops = { + .is_enabled = max77650_regulator_is_enabled, + .enable = max77650_regulator_enable, + .disable = max77650_regulator_disable, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = max77650_regulator_set_voltage_sel, + .get_current_limit = max77650_regulator_get_current_limit, + .set_current_limit = max77650_regulator_set_current_limit, + .set_active_discharge = regulator_set_active_discharge_regmap, +}; + +/* Special case for max77651 SBB1 - non-linear voltage mapping. */ +static const struct regulator_ops max77651_SBB1_regulator_ops = { + .is_enabled = max77650_regulator_is_enabled, + .enable = max77650_regulator_enable, + .disable = max77650_regulator_disable, + .list_voltage = regulator_list_voltage_table, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = max77651_regulator_sbb1_set_voltage_sel, + .get_current_limit = max77650_regulator_get_current_limit, + .set_current_limit = max77650_regulator_set_current_limit, + .set_active_discharge = regulator_set_active_discharge_regmap, +}; + +static struct max77650_regulator_desc max77650_LDO_desc = { + .desc = { + .name = "ldo", + .of_match = of_match_ptr("ldo"), + .regulators_node = of_match_ptr("regulators"), + .supply_name = "in-ldo", + .id = MAX77650_REGULATOR_ID_LDO, + .ops = &max77650_regulator_LDO_ops, + .min_uV = 1350000, + .uV_step = 12500, + .n_voltages = 128, + .vsel_mask = MAX77650_REGULATOR_V_LDO_MASK, + .vsel_reg = MAX77650_REG_CNFG_LDO_A, + .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, + .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, + .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, + .active_discharge_reg = MAX77650_REG_CNFG_LDO_B, + .enable_time = 100, + .type = REGULATOR_VOLTAGE, + }, + .regA = MAX77650_REG_CNFG_LDO_A, + .regB = MAX77650_REG_CNFG_LDO_B, +}; + +static struct max77650_regulator_desc max77650_SBB0_desc = { + .desc = { + .name = "sbb0", + .of_match = of_match_ptr("sbb0"), + .regulators_node = of_match_ptr("regulators"), + .supply_name = "in-sbb0", + .id = MAX77650_REGULATOR_ID_SBB0, + .ops = &max77650_regulator_SBB_ops, + .min_uV = 800000, + .uV_step = 25000, + .n_voltages = 64, + .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, + .vsel_reg = MAX77650_REG_CNFG_SBB0_A, + .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, + .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, + .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, + .active_discharge_reg = MAX77650_REG_CNFG_SBB0_B, + .enable_time = 100, + .type = REGULATOR_VOLTAGE, + }, + .regA = MAX77650_REG_CNFG_SBB0_A, + .regB = MAX77650_REG_CNFG_SBB0_B, +}; + +static struct max77650_regulator_desc max77650_SBB1_desc = { + .desc = { + .name = "sbb1", + .of_match = of_match_ptr("sbb1"), + .regulators_node = of_match_ptr("regulators"), + .supply_name = "in-sbb1", + .id = MAX77650_REGULATOR_ID_SBB1, + .ops = &max77650_regulator_SBB_ops, + .min_uV = 800000, + .uV_step = 12500, + .n_voltages = 64, + .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, + .vsel_reg = MAX77650_REG_CNFG_SBB1_A, + .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, + .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, + .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, + .active_discharge_reg = MAX77650_REG_CNFG_SBB1_B, + .enable_time = 100, + .type = REGULATOR_VOLTAGE, + }, + .regA = MAX77650_REG_CNFG_SBB1_A, + .regB = MAX77650_REG_CNFG_SBB1_B, +}; + +static struct max77650_regulator_desc max77651_SBB1_desc = { + .desc = { + .name = "sbb1", + .of_match = of_match_ptr("sbb1"), + .regulators_node = of_match_ptr("regulators"), + .supply_name = "in-sbb1", + .id = MAX77650_REGULATOR_ID_SBB1, + .ops = &max77651_SBB1_regulator_ops, + .volt_table = max77651_sbb1_regulator_volt_table, + .n_voltages = ARRAY_SIZE(max77651_sbb1_regulator_volt_table), + .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, + .vsel_reg = MAX77650_REG_CNFG_SBB1_A, + .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, + .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, + .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, + .active_discharge_reg = MAX77650_REG_CNFG_SBB1_B, + .enable_time = 100, + .type = REGULATOR_VOLTAGE, + }, + .regA = MAX77650_REG_CNFG_SBB1_A, + .regB = MAX77650_REG_CNFG_SBB1_B, +}; + +static struct max77650_regulator_desc max77650_SBB2_desc = { + .desc = { + .name = "sbb2", + .of_match = of_match_ptr("sbb2"), + .regulators_node = of_match_ptr("regulators"), + .supply_name = "in-sbb0", + .id = MAX77650_REGULATOR_ID_SBB2, + .ops = &max77650_regulator_SBB_ops, + .min_uV = 800000, + .uV_step = 50000, + .n_voltages = 64, + .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, + .vsel_reg = MAX77650_REG_CNFG_SBB2_A, + .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, + .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, + .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, + .active_discharge_reg = MAX77650_REG_CNFG_SBB2_B, + .enable_time = 100, + .type = REGULATOR_VOLTAGE, + }, + .regA = MAX77650_REG_CNFG_SBB2_A, + .regB = MAX77650_REG_CNFG_SBB2_B, +}; + +static struct max77650_regulator_desc max77651_SBB2_desc = { + .desc = { + .name = "sbb2", + .of_match = of_match_ptr("sbb2"), + .regulators_node = of_match_ptr("regulators"), + .supply_name = "in-sbb0", + .id = MAX77650_REGULATOR_ID_SBB2, + .ops = &max77650_regulator_SBB_ops, + .min_uV = 2400000, + .uV_step = 50000, + .n_voltages = 64, + .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, + .vsel_reg = MAX77650_REG_CNFG_SBB2_A, + .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, + .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, + .active_discharge_mask = MAX77650_REGULATOR_AD_MASK, + .active_discharge_reg = MAX77650_REG_CNFG_SBB2_B, + .enable_time = 100, + .type = REGULATOR_VOLTAGE, + }, + .regA = MAX77650_REG_CNFG_SBB2_A, + .regB = MAX77650_REG_CNFG_SBB2_B, +}; + +static int max77650_regulator_probe(struct platform_device *pdev) +{ + struct max77650_regulator_desc **rdescs; + struct max77650_regulator_desc *rdesc; + struct regulator_config config = { }; + struct device *dev, *parent; + struct regulator_dev *rdev; + struct regmap *map; + unsigned int val; + int i, rv; + + dev = &pdev->dev; + parent = dev->parent; + + if (!dev->of_node) + dev->of_node = parent->of_node; + + rdescs = devm_kcalloc(dev, MAX77650_REGULATOR_NUM_REGULATORS, + sizeof(*rdescs), GFP_KERNEL); + if (!rdescs) + return -ENOMEM; + + map = dev_get_regmap(parent, NULL); + if (!map) + return -ENODEV; + + rv = regmap_read(map, MAX77650_REG_CID, &val); + if (rv) + return rv; + + rdescs[MAX77650_REGULATOR_ID_LDO] = &max77650_LDO_desc; + rdescs[MAX77650_REGULATOR_ID_SBB0] = &max77650_SBB0_desc; + + switch (MAX77650_CID_BITS(val)) { + case MAX77650_CID_77650A: + case MAX77650_CID_77650C: + rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77650_SBB1_desc; + rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77650_SBB2_desc; + break; + case MAX77650_CID_77651A: + case MAX77650_CID_77651B: + rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77651_SBB1_desc; + rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77651_SBB2_desc; + break; + default: + return -ENODEV; + } + + config.dev = parent; + + for (i = 0; i < MAX77650_REGULATOR_NUM_REGULATORS; i++) { + rdesc = rdescs[i]; + config.driver_data = rdesc; + + rdev = devm_regulator_register(dev, &rdesc->desc, &config); + if (IS_ERR(rdev)) + return PTR_ERR(rdev); + } + + return 0; +} + +static struct platform_driver max77650_regulator_driver = { + .driver = { + .name = "max77650-regulator", + }, + .probe = max77650_regulator_probe, +}; +module_platform_driver(max77650_regulator_driver); + +MODULE_DESCRIPTION("MAXIM 77650/77651 regulator driver"); +MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/max77802-regulator.c b/drivers/regulator/max77802-regulator.c index c30cf5c9f2de..ea7b50397300 100644 --- a/drivers/regulator/max77802-regulator.c +++ b/drivers/regulator/max77802-regulator.c @@ -248,9 +248,9 @@ static int max77802_set_ramp_delay_2bit(struct regulator_dev *rdev, unsigned int ramp_value; if (id > MAX77802_BUCK4) { - dev_warn(&rdev->dev, - "%s: regulator: ramp delay not supported\n", - rdev->desc->name); + dev_warn(&rdev->dev, + "%s: regulator: ramp delay not supported\n", + rdev->desc->name); return -EINVAL; } ramp_value = max77802_find_ramp_value(rdev, ramp_table_77802_2bit, diff --git a/drivers/regulator/mcp16502.c b/drivers/regulator/mcp16502.c index 3479ae009b0b..0fc4963bd5b0 100644 --- a/drivers/regulator/mcp16502.c +++ b/drivers/regulator/mcp16502.c @@ -17,6 +17,7 @@ #include <linux/regmap.h> #include <linux/regulator/driver.h> #include <linux/suspend.h> +#include <linux/gpio/consumer.h> #define VDD_LOW_SEL 0x0D #define VDD_HIGH_SEL 0x3F diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index ffa5fc3724e4..7b6bf3536271 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -255,7 +255,7 @@ static void of_get_regulation_constraints(struct device_node *np, * @desc: regulator description * * Populates regulator_init_data structure by extracting data from device - * tree node, returns a pointer to the populated struture or NULL if memory + * tree node, returns a pointer to the populated structure or NULL if memory * alloc fails. */ struct regulator_init_data *of_get_regulator_init_data(struct device *dev, @@ -547,7 +547,7 @@ bool of_check_coupling_data(struct regulator_dev *rdev) NULL); if (c_n_phandles != n_phandles) { - dev_err(&rdev->dev, "number of couped reg phandles mismatch\n"); + dev_err(&rdev->dev, "number of coupled reg phandles mismatch\n"); ret = false; goto clean; } diff --git a/drivers/regulator/pv88060-regulator.c b/drivers/regulator/pv88060-regulator.c index a9446056435f..d5dab9bef378 100644 --- a/drivers/regulator/pv88060-regulator.c +++ b/drivers/regulator/pv88060-regulator.c @@ -184,6 +184,12 @@ static const struct regulator_ops pv88060_ldo_ops = { .list_voltage = regulator_list_voltage_linear, }; +static const struct regulator_ops pv88060_sw_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + #define PV88060_BUCK(chip, regl_name, min, step, max, limits_array) \ {\ .desc = {\ @@ -237,9 +243,8 @@ static const struct regulator_ops pv88060_ldo_ops = { .regulators_node = of_match_ptr("regulators"),\ .type = REGULATOR_VOLTAGE,\ .owner = THIS_MODULE,\ - .ops = &pv88060_ldo_ops,\ - .min_uV = max,\ - .uV_step = 0,\ + .ops = &pv88060_sw_ops,\ + .fixed_uV = max,\ .n_voltages = 1,\ .enable_reg = PV88060_REG_##regl_name##_CONF,\ .enable_mask = PV88060_SW_EN,\ diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c index a2fd140eff81..3f53f9134b32 100644 --- a/drivers/regulator/pwm-regulator.c +++ b/drivers/regulator/pwm-regulator.c @@ -40,9 +40,6 @@ struct pwm_regulator_data { /* regulator descriptor */ struct regulator_desc desc; - /* Regulator ops */ - struct regulator_ops ops; - int state; /* Enable GPIO */ @@ -231,7 +228,7 @@ static int pwm_regulator_set_voltage(struct regulator_dev *rdev, return 0; } -static struct regulator_ops pwm_regulator_voltage_table_ops = { +static const struct regulator_ops pwm_regulator_voltage_table_ops = { .set_voltage_sel = pwm_regulator_set_voltage_sel, .get_voltage_sel = pwm_regulator_get_voltage_sel, .list_voltage = pwm_regulator_list_voltage, @@ -241,7 +238,7 @@ static struct regulator_ops pwm_regulator_voltage_table_ops = { .is_enabled = pwm_regulator_is_enabled, }; -static struct regulator_ops pwm_regulator_voltage_continuous_ops = { +static const struct regulator_ops pwm_regulator_voltage_continuous_ops = { .get_voltage = pwm_regulator_get_voltage, .set_voltage = pwm_regulator_set_voltage, .enable = pwm_regulator_enable, @@ -249,7 +246,7 @@ static struct regulator_ops pwm_regulator_voltage_continuous_ops = { .is_enabled = pwm_regulator_is_enabled, }; -static struct regulator_desc pwm_regulator_desc = { +static const struct regulator_desc pwm_regulator_desc = { .name = "pwm-regulator", .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, @@ -287,9 +284,7 @@ static int pwm_regulator_init_table(struct platform_device *pdev, drvdata->state = -EINVAL; drvdata->duty_cycle_table = duty_cycle_table; - memcpy(&drvdata->ops, &pwm_regulator_voltage_table_ops, - sizeof(drvdata->ops)); - drvdata->desc.ops = &drvdata->ops; + drvdata->desc.ops = &pwm_regulator_voltage_table_ops; drvdata->desc.n_voltages = length / sizeof(*duty_cycle_table); return 0; @@ -301,9 +296,7 @@ static int pwm_regulator_init_continuous(struct platform_device *pdev, u32 dutycycle_range[2] = { 0, 100 }; u32 dutycycle_unit = 100; - memcpy(&drvdata->ops, &pwm_regulator_voltage_continuous_ops, - sizeof(drvdata->ops)); - drvdata->desc.ops = &drvdata->ops; + drvdata->desc.ops = &pwm_regulator_voltage_continuous_ops; drvdata->desc.continuous_voltage_range = true; of_property_read_u32_array(pdev->dev.of_node, diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c index f5bca77d67c1..68bc23df4213 100644 --- a/drivers/regulator/qcom_smd-regulator.c +++ b/drivers/regulator/qcom_smd-regulator.c @@ -31,6 +31,11 @@ struct qcom_rpm_reg { int is_enabled; int uV; + u32 load; + + unsigned int enabled_updated:1; + unsigned int uv_updated:1; + unsigned int load_updated:1; }; struct rpm_regulator_req { @@ -43,30 +48,59 @@ struct rpm_regulator_req { #define RPM_KEY_UV 0x00007675 /* "uv" */ #define RPM_KEY_MA 0x0000616d /* "ma" */ -static int rpm_reg_write_active(struct qcom_rpm_reg *vreg, - struct rpm_regulator_req *req, - size_t size) +static int rpm_reg_write_active(struct qcom_rpm_reg *vreg) { - return qcom_rpm_smd_write(vreg->rpm, - QCOM_SMD_RPM_ACTIVE_STATE, - vreg->type, - vreg->id, - req, size); + struct rpm_regulator_req req[3]; + int reqlen = 0; + int ret; + + if (vreg->enabled_updated) { + req[reqlen].key = cpu_to_le32(RPM_KEY_SWEN); + req[reqlen].nbytes = cpu_to_le32(sizeof(u32)); + req[reqlen].value = cpu_to_le32(vreg->is_enabled); + reqlen++; + } + + if (vreg->uv_updated && vreg->is_enabled) { + req[reqlen].key = cpu_to_le32(RPM_KEY_UV); + req[reqlen].nbytes = cpu_to_le32(sizeof(u32)); + req[reqlen].value = cpu_to_le32(vreg->uV); + reqlen++; + } + + if (vreg->load_updated && vreg->is_enabled) { + req[reqlen].key = cpu_to_le32(RPM_KEY_MA); + req[reqlen].nbytes = cpu_to_le32(sizeof(u32)); + req[reqlen].value = cpu_to_le32(vreg->load / 1000); + reqlen++; + } + + if (!reqlen) + return 0; + + ret = qcom_rpm_smd_write(vreg->rpm, QCOM_SMD_RPM_ACTIVE_STATE, + vreg->type, vreg->id, + req, sizeof(req[0]) * reqlen); + if (!ret) { + vreg->enabled_updated = 0; + vreg->uv_updated = 0; + vreg->load_updated = 0; + } + + return ret; } static int rpm_reg_enable(struct regulator_dev *rdev) { struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); - struct rpm_regulator_req req; int ret; - req.key = cpu_to_le32(RPM_KEY_SWEN); - req.nbytes = cpu_to_le32(sizeof(u32)); - req.value = cpu_to_le32(1); + vreg->is_enabled = 1; + vreg->enabled_updated = 1; - ret = rpm_reg_write_active(vreg, &req, sizeof(req)); - if (!ret) - vreg->is_enabled = 1; + ret = rpm_reg_write_active(vreg); + if (ret) + vreg->is_enabled = 0; return ret; } @@ -81,16 +115,14 @@ static int rpm_reg_is_enabled(struct regulator_dev *rdev) static int rpm_reg_disable(struct regulator_dev *rdev) { struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); - struct rpm_regulator_req req; int ret; - req.key = cpu_to_le32(RPM_KEY_SWEN); - req.nbytes = cpu_to_le32(sizeof(u32)); - req.value = 0; + vreg->is_enabled = 0; + vreg->enabled_updated = 1; - ret = rpm_reg_write_active(vreg, &req, sizeof(req)); - if (!ret) - vreg->is_enabled = 0; + ret = rpm_reg_write_active(vreg); + if (ret) + vreg->is_enabled = 1; return ret; } @@ -108,16 +140,15 @@ static int rpm_reg_set_voltage(struct regulator_dev *rdev, unsigned *selector) { struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); - struct rpm_regulator_req req; - int ret = 0; + int ret; + int old_uV = vreg->uV; - req.key = cpu_to_le32(RPM_KEY_UV); - req.nbytes = cpu_to_le32(sizeof(u32)); - req.value = cpu_to_le32(min_uV); + vreg->uV = min_uV; + vreg->uv_updated = 1; - ret = rpm_reg_write_active(vreg, &req, sizeof(req)); - if (!ret) - vreg->uV = min_uV; + ret = rpm_reg_write_active(vreg); + if (ret) + vreg->uV = old_uV; return ret; } @@ -125,13 +156,16 @@ static int rpm_reg_set_voltage(struct regulator_dev *rdev, static int rpm_reg_set_load(struct regulator_dev *rdev, int load_uA) { struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); - struct rpm_regulator_req req; + u32 old_load = vreg->load; + int ret; - req.key = cpu_to_le32(RPM_KEY_MA); - req.nbytes = cpu_to_le32(sizeof(u32)); - req.value = cpu_to_le32(load_uA / 1000); + vreg->load = load_uA; + vreg->load_updated = 1; + ret = rpm_reg_write_active(vreg); + if (ret) + vreg->load = old_load; - return rpm_reg_write_active(vreg, &req, sizeof(req)); + return ret; } static const struct regulator_ops rpm_smps_ldo_ops = { diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 213b68743cc8..23713e16c286 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -1,5 +1,5 @@ /* - * Regulator driver for Rockchip RK808/RK818 + * Regulator driver for Rockchip RK805/RK808/RK818 * * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd * @@ -363,28 +363,28 @@ static int rk808_set_suspend_disable(struct regulator_dev *rdev) rdev->desc->enable_mask); } -static struct regulator_ops rk805_reg_ops = { - .list_voltage = regulator_list_voltage_linear, - .map_voltage = regulator_map_voltage_linear, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .set_suspend_voltage = rk808_set_suspend_voltage, - .set_suspend_enable = rk805_set_suspend_enable, - .set_suspend_disable = rk805_set_suspend_disable, +static const struct regulator_ops rk805_reg_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_suspend_voltage = rk808_set_suspend_voltage, + .set_suspend_enable = rk805_set_suspend_enable, + .set_suspend_disable = rk805_set_suspend_disable, }; -static struct regulator_ops rk805_switch_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .set_suspend_enable = rk805_set_suspend_enable, - .set_suspend_disable = rk805_set_suspend_disable, +static const struct regulator_ops rk805_switch_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_suspend_enable = rk805_set_suspend_enable, + .set_suspend_disable = rk805_set_suspend_disable, }; -static struct regulator_ops rk808_buck1_2_ops = { +static const struct regulator_ops rk808_buck1_2_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = rk808_buck1_2_get_voltage_sel_regmap, @@ -399,7 +399,7 @@ static struct regulator_ops rk808_buck1_2_ops = { .set_suspend_disable = rk808_set_suspend_disable, }; -static struct regulator_ops rk808_reg_ops = { +static const struct regulator_ops rk808_reg_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -412,7 +412,7 @@ static struct regulator_ops rk808_reg_ops = { .set_suspend_disable = rk808_set_suspend_disable, }; -static struct regulator_ops rk808_reg_ops_ranges = { +static const struct regulator_ops rk808_reg_ops_ranges = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -425,7 +425,7 @@ static struct regulator_ops rk808_reg_ops_ranges = { .set_suspend_disable = rk808_set_suspend_disable, }; -static struct regulator_ops rk808_switch_ops = { +static const struct regulator_ops rk808_switch_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -433,6 +433,12 @@ static struct regulator_ops rk808_switch_ops = { .set_suspend_disable = rk808_set_suspend_disable, }; +static const struct regulator_linear_range rk805_buck_1_2_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(712500, 0, 59, 12500), + REGULATOR_LINEAR_RANGE(1800000, 60, 62, 200000), + REGULATOR_LINEAR_RANGE(2300000, 63, 63, 0), +}; + static const struct regulator_desc rk805_reg[] = { { .name = "DCDC_REG1", @@ -440,11 +446,11 @@ static const struct regulator_desc rk805_reg[] = { .of_match = of_match_ptr("DCDC_REG1"), .regulators_node = of_match_ptr("regulators"), .id = RK805_ID_DCDC1, - .ops = &rk805_reg_ops, + .ops = &rk808_reg_ops_ranges, .type = REGULATOR_VOLTAGE, - .min_uV = 712500, - .uV_step = 12500, .n_voltages = 64, + .linear_ranges = rk805_buck_1_2_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk805_buck_1_2_voltage_ranges), .vsel_reg = RK805_BUCK1_ON_VSEL_REG, .vsel_mask = RK818_BUCK_VSEL_MASK, .enable_reg = RK805_DCDC_EN_REG, @@ -456,11 +462,11 @@ static const struct regulator_desc rk805_reg[] = { .of_match = of_match_ptr("DCDC_REG2"), .regulators_node = of_match_ptr("regulators"), .id = RK805_ID_DCDC2, - .ops = &rk805_reg_ops, + .ops = &rk808_reg_ops_ranges, .type = REGULATOR_VOLTAGE, - .min_uV = 712500, - .uV_step = 12500, .n_voltages = 64, + .linear_ranges = rk805_buck_1_2_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk805_buck_1_2_voltage_ranges), .vsel_reg = RK805_BUCK2_ON_VSEL_REG, .vsel_mask = RK818_BUCK_VSEL_MASK, .enable_reg = RK805_DCDC_EN_REG, @@ -796,7 +802,7 @@ static struct platform_driver rk808_regulator_driver = { module_platform_driver(rk808_regulator_driver); -MODULE_DESCRIPTION("regulator driver for the RK808/RK818 series PMICs"); +MODULE_DESCRIPTION("regulator driver for the RK805/RK808/RK818 series PMICs"); MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>"); MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>"); MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>"); diff --git a/drivers/regulator/rt5033-regulator.c b/drivers/regulator/rt5033-regulator.c index 96d2c18e051a..639cbadc044a 100644 --- a/drivers/regulator/rt5033-regulator.c +++ b/drivers/regulator/rt5033-regulator.c @@ -16,14 +16,14 @@ #include <linux/mfd/rt5033-private.h> #include <linux/regulator/of_regulator.h> -static struct regulator_ops rt5033_safe_ldo_ops = { +static const struct regulator_ops rt5033_safe_ldo_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .list_voltage = regulator_list_voltage_linear, }; -static struct regulator_ops rt5033_buck_ops = { +static const struct regulator_ops rt5033_buck_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, diff --git a/drivers/regulator/stpmic1_regulator.c b/drivers/regulator/stpmic1_regulator.c index a1f88e996cae..f09061473613 100644 --- a/drivers/regulator/stpmic1_regulator.c +++ b/drivers/regulator/stpmic1_regulator.c @@ -12,8 +12,10 @@ #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> +#include <dt-bindings/mfd/st,stpmic1.h> + /** - * stpmic1 regulator description + * stpmic1 regulator description: this structure is used as driver data * @desc: regulator framework description * @mask_reset_reg: mask reset register address * @mask_reset_mask: mask rank and mask reset register mask @@ -28,28 +30,9 @@ struct stpmic1_regulator_cfg { u8 icc_mask; }; -/** - * stpmic1 regulator data: this structure is used as driver data - * @regul_id: regulator id - * @reg_node: DT node of regulator (unused on non-DT platforms) - * @cfg: stpmic specific regulator description - * @mask_reset: mask_reset bit value - * @irq_curlim: current limit interrupt number - * @regmap: point to parent regmap structure - */ -struct stpmic1_regulator { - unsigned int regul_id; - struct device_node *reg_node; - struct stpmic1_regulator_cfg *cfg; - u8 mask_reset; - int irq_curlim; - struct regmap *regmap; -}; - static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode); static unsigned int stpmic1_get_mode(struct regulator_dev *rdev); static int stpmic1_set_icc(struct regulator_dev *rdev); -static int stpmic1_regulator_parse_dt(void *driver_data); static unsigned int stpmic1_map_mode(unsigned int mode); enum { @@ -72,16 +55,13 @@ enum { /* Enable time worst case is 5000mV/(2250uV/uS) */ #define PMIC_ENABLE_TIME_US 2200 -#define STPMIC1_BUCK_MODE_NORMAL 0 -#define STPMIC1_BUCK_MODE_LP BUCK_HPLP_ENABLE_MASK - static const struct regulator_linear_range buck1_ranges[] = { REGULATOR_LINEAR_RANGE(725000, 0, 4, 0), REGULATOR_LINEAR_RANGE(725000, 5, 36, 25000), REGULATOR_LINEAR_RANGE(1500000, 37, 63, 0), }; -struct regulator_linear_range buck2_ranges[] = { +static const struct regulator_linear_range buck2_ranges[] = { REGULATOR_LINEAR_RANGE(1000000, 0, 17, 0), REGULATOR_LINEAR_RANGE(1050000, 18, 19, 0), REGULATOR_LINEAR_RANGE(1100000, 20, 21, 0), @@ -95,7 +75,7 @@ struct regulator_linear_range buck2_ranges[] = { REGULATOR_LINEAR_RANGE(1500000, 36, 63, 0), }; -struct regulator_linear_range buck3_ranges[] = { +static const struct regulator_linear_range buck3_ranges[] = { REGULATOR_LINEAR_RANGE(1000000, 0, 19, 0), REGULATOR_LINEAR_RANGE(1100000, 20, 23, 0), REGULATOR_LINEAR_RANGE(1200000, 24, 27, 0), @@ -103,10 +83,9 @@ struct regulator_linear_range buck3_ranges[] = { REGULATOR_LINEAR_RANGE(1400000, 32, 35, 0), REGULATOR_LINEAR_RANGE(1500000, 36, 55, 100000), REGULATOR_LINEAR_RANGE(3400000, 56, 63, 0), - }; -struct regulator_linear_range buck4_ranges[] = { +static const struct regulator_linear_range buck4_ranges[] = { REGULATOR_LINEAR_RANGE(600000, 0, 27, 25000), REGULATOR_LINEAR_RANGE(1300000, 28, 29, 0), REGULATOR_LINEAR_RANGE(1350000, 30, 31, 0), @@ -114,24 +93,21 @@ struct regulator_linear_range buck4_ranges[] = { REGULATOR_LINEAR_RANGE(1450000, 34, 35, 0), REGULATOR_LINEAR_RANGE(1500000, 36, 60, 100000), REGULATOR_LINEAR_RANGE(3900000, 61, 63, 0), - }; -struct regulator_linear_range ldo1_ranges[] = { +static const struct regulator_linear_range ldo1_ranges[] = { REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0), REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000), REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0), - }; -struct regulator_linear_range ldo2_ranges[] = { +static const struct regulator_linear_range ldo2_ranges[] = { REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0), REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000), REGULATOR_LINEAR_RANGE(3300000, 25, 30, 0), - }; -struct regulator_linear_range ldo3_ranges[] = { +static const struct regulator_linear_range ldo3_ranges[] = { REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0), REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000), REGULATOR_LINEAR_RANGE(3300000, 25, 30, 0), @@ -139,18 +115,18 @@ struct regulator_linear_range ldo3_ranges[] = { REGULATOR_LINEAR_RANGE(500000, 31, 31, 0), }; -struct regulator_linear_range ldo5_ranges[] = { +static const struct regulator_linear_range ldo5_ranges[] = { REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0), REGULATOR_LINEAR_RANGE(1700000, 8, 30, 100000), REGULATOR_LINEAR_RANGE(3900000, 31, 31, 0), }; -struct regulator_linear_range ldo6_ranges[] = { +static const struct regulator_linear_range ldo6_ranges[] = { REGULATOR_LINEAR_RANGE(900000, 0, 24, 100000), REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0), }; -static struct regulator_ops stpmic1_ldo_ops = { +static const struct regulator_ops stpmic1_ldo_ops = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, .is_enabled = regulator_is_enabled_regmap, @@ -158,11 +134,10 @@ static struct regulator_ops stpmic1_ldo_ops = { .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .set_pull_down = regulator_set_pull_down_regmap, .set_over_current_protection = stpmic1_set_icc, }; -static struct regulator_ops stpmic1_ldo3_ops = { +static const struct regulator_ops stpmic1_ldo3_ops = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_iterate, .is_enabled = regulator_is_enabled_regmap, @@ -170,21 +145,19 @@ static struct regulator_ops stpmic1_ldo3_ops = { .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .set_pull_down = regulator_set_pull_down_regmap, .get_bypass = regulator_get_bypass_regmap, .set_bypass = regulator_set_bypass_regmap, .set_over_current_protection = stpmic1_set_icc, }; -static struct regulator_ops stpmic1_ldo4_fixed_regul_ops = { +static const struct regulator_ops stpmic1_ldo4_fixed_regul_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .set_pull_down = regulator_set_pull_down_regmap, .set_over_current_protection = stpmic1_set_icc, }; -static struct regulator_ops stpmic1_buck_ops = { +static const struct regulator_ops stpmic1_buck_ops = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, .is_enabled = regulator_is_enabled_regmap, @@ -198,20 +171,27 @@ static struct regulator_ops stpmic1_buck_ops = { .set_over_current_protection = stpmic1_set_icc, }; -static struct regulator_ops stpmic1_vref_ddr_ops = { +static const struct regulator_ops stpmic1_vref_ddr_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .set_pull_down = regulator_set_pull_down_regmap, }; -static struct regulator_ops stpmic1_switch_regul_ops = { +static const struct regulator_ops stpmic1_boost_regul_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .set_over_current_protection = stpmic1_set_icc, }; +static const struct regulator_ops stpmic1_switch_regul_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .set_over_current_protection = stpmic1_set_icc, + .set_active_discharge = regulator_set_active_discharge_regmap, +}; + #define REG_LDO(ids, base) { \ .name = #ids, \ .id = STPMIC1_##ids, \ @@ -228,8 +208,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = { .enable_val = 1, \ .disable_val = 0, \ .enable_time = PMIC_ENABLE_TIME_US, \ - .pull_down_reg = ids##_PULL_DOWN_REG, \ - .pull_down_mask = ids##_PULL_DOWN_MASK, \ .supply_name = #base, \ } @@ -253,8 +231,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = { .bypass_mask = LDO_BYPASS_MASK, \ .bypass_val_on = LDO_BYPASS_MASK, \ .bypass_val_off = 0, \ - .pull_down_reg = ids##_PULL_DOWN_REG, \ - .pull_down_mask = ids##_PULL_DOWN_MASK, \ .supply_name = #base, \ } @@ -272,8 +248,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = { .enable_val = 1, \ .disable_val = 0, \ .enable_time = PMIC_ENABLE_TIME_US, \ - .pull_down_reg = ids##_PULL_DOWN_REG, \ - .pull_down_mask = ids##_PULL_DOWN_MASK, \ .supply_name = #base, \ } @@ -313,12 +287,47 @@ static struct regulator_ops stpmic1_switch_regul_ops = { .enable_val = 1, \ .disable_val = 0, \ .enable_time = PMIC_ENABLE_TIME_US, \ - .pull_down_reg = ids##_PULL_DOWN_REG, \ - .pull_down_mask = ids##_PULL_DOWN_MASK, \ .supply_name = #base, \ } -#define REG_SWITCH(ids, base, reg, mask, val) { \ +#define REG_BOOST(ids, base) { \ + .name = #ids, \ + .id = STPMIC1_##ids, \ + .n_voltages = 1, \ + .ops = &stpmic1_boost_regul_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = 0, \ + .fixed_uV = 5000000, \ + .enable_reg = BST_SW_CR, \ + .enable_mask = BOOST_ENABLED, \ + .enable_val = BOOST_ENABLED, \ + .disable_val = 0, \ + .enable_time = PMIC_ENABLE_TIME_US, \ + .supply_name = #base, \ +} + +#define REG_VBUS_OTG(ids, base) { \ + .name = #ids, \ + .id = STPMIC1_##ids, \ + .n_voltages = 1, \ + .ops = &stpmic1_switch_regul_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = 0, \ + .fixed_uV = 5000000, \ + .enable_reg = BST_SW_CR, \ + .enable_mask = USBSW_OTG_SWITCH_ENABLED, \ + .enable_val = USBSW_OTG_SWITCH_ENABLED, \ + .disable_val = 0, \ + .enable_time = PMIC_ENABLE_TIME_US, \ + .supply_name = #base, \ + .active_discharge_reg = BST_SW_CR, \ + .active_discharge_mask = VBUS_OTG_DISCHARGE, \ + .active_discharge_on = VBUS_OTG_DISCHARGE, \ +} + +#define REG_SW_OUT(ids, base) { \ .name = #ids, \ .id = STPMIC1_##ids, \ .n_voltages = 1, \ @@ -327,15 +336,18 @@ static struct regulator_ops stpmic1_switch_regul_ops = { .owner = THIS_MODULE, \ .min_uV = 0, \ .fixed_uV = 5000000, \ - .enable_reg = (reg), \ - .enable_mask = (mask), \ - .enable_val = (val), \ + .enable_reg = BST_SW_CR, \ + .enable_mask = SWIN_SWOUT_ENABLED, \ + .enable_val = SWIN_SWOUT_ENABLED, \ .disable_val = 0, \ .enable_time = PMIC_ENABLE_TIME_US, \ .supply_name = #base, \ + .active_discharge_reg = BST_SW_CR, \ + .active_discharge_mask = SW_OUT_DISCHARGE, \ + .active_discharge_on = SW_OUT_DISCHARGE, \ } -struct stpmic1_regulator_cfg stpmic1_regulator_cfgs[] = { +static const struct stpmic1_regulator_cfg stpmic1_regulator_cfgs[] = { [STPMIC1_BUCK1] = { .desc = REG_BUCK(BUCK1, buck1), .icc_reg = BUCKS_ICCTO_CR, @@ -412,23 +424,17 @@ struct stpmic1_regulator_cfg stpmic1_regulator_cfgs[] = { .mask_reset_mask = BIT(6), }, [STPMIC1_BOOST] = { - .desc = REG_SWITCH(BOOST, boost, BST_SW_CR, - BOOST_ENABLED, - BOOST_ENABLED), + .desc = REG_BOOST(BOOST, boost), .icc_reg = BUCKS_ICCTO_CR, .icc_mask = BIT(6), }, [STPMIC1_VBUS_OTG] = { - .desc = REG_SWITCH(VBUS_OTG, pwr_sw1, BST_SW_CR, - USBSW_OTG_SWITCH_ENABLED, - USBSW_OTG_SWITCH_ENABLED), + .desc = REG_VBUS_OTG(VBUS_OTG, pwr_sw1), .icc_reg = BUCKS_ICCTO_CR, .icc_mask = BIT(4), }, [STPMIC1_SW_OUT] = { - .desc = REG_SWITCH(SW_OUT, pwr_sw2, BST_SW_CR, - SWIN_SWOUT_ENABLED, - SWIN_SWOUT_ENABLED), + .desc = REG_SW_OUT(SW_OUT, pwr_sw2), .icc_reg = BUCKS_ICCTO_CR, .icc_mask = BIT(5), }, @@ -449,8 +455,9 @@ static unsigned int stpmic1_map_mode(unsigned int mode) static unsigned int stpmic1_get_mode(struct regulator_dev *rdev) { int value; + struct regmap *regmap = rdev_get_regmap(rdev); - regmap_read(rdev->regmap, rdev->desc->enable_reg, &value); + regmap_read(regmap, rdev->desc->enable_reg, &value); if (value & STPMIC1_BUCK_MODE_LP) return REGULATOR_MODE_STANDBY; @@ -461,6 +468,7 @@ static unsigned int stpmic1_get_mode(struct regulator_dev *rdev) static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode) { int value; + struct regmap *regmap = rdev_get_regmap(rdev); switch (mode) { case REGULATOR_MODE_NORMAL: @@ -473,17 +481,18 @@ static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode) return -EINVAL; } - return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + return regmap_update_bits(regmap, rdev->desc->enable_reg, STPMIC1_BUCK_MODE_LP, value); } static int stpmic1_set_icc(struct regulator_dev *rdev) { - struct stpmic1_regulator *regul = rdev_get_drvdata(rdev); + struct stpmic1_regulator_cfg *cfg = rdev_get_drvdata(rdev); + struct regmap *regmap = rdev_get_regmap(rdev); /* enable switch off in case of over current */ - return regmap_update_bits(regul->regmap, regul->cfg->icc_reg, - regul->cfg->icc_mask, regul->cfg->icc_mask); + return regmap_update_bits(regmap, cfg->icc_reg, cfg->icc_mask, + cfg->icc_mask); } static irqreturn_t stpmic1_curlim_irq_handler(int irq, void *data) @@ -502,46 +511,13 @@ static irqreturn_t stpmic1_curlim_irq_handler(int irq, void *data) return IRQ_HANDLED; } -static int stpmic1_regulator_init(struct platform_device *pdev, - struct regulator_dev *rdev) -{ - struct stpmic1_regulator *regul = rdev_get_drvdata(rdev); - int ret = 0; - - /* set mask reset */ - if (regul->mask_reset && regul->cfg->mask_reset_reg != 0) { - ret = regmap_update_bits(regul->regmap, - regul->cfg->mask_reset_reg, - regul->cfg->mask_reset_mask, - regul->cfg->mask_reset_mask); - if (ret) { - dev_err(&pdev->dev, "set mask reset failed\n"); - return ret; - } - } - - /* setup an irq handler for over-current detection */ - if (regul->irq_curlim > 0) { - ret = devm_request_threaded_irq(&pdev->dev, - regul->irq_curlim, NULL, - stpmic1_curlim_irq_handler, - IRQF_ONESHOT | IRQF_SHARED, - pdev->name, rdev); - if (ret) { - dev_err(&pdev->dev, "Request IRQ failed\n"); - return ret; - } - } - return 0; -} - #define MATCH(_name, _id) \ [STPMIC1_##_id] = { \ .name = #_name, \ .desc = &stpmic1_regulator_cfgs[STPMIC1_##_id].desc, \ } -static struct of_regulator_match stpmic1_regulators_matches[] = { +static struct of_regulator_match stpmic1_matches[] = { MATCH(buck1, BUCK1), MATCH(buck2, BUCK2), MATCH(buck3, BUCK3), @@ -558,94 +534,75 @@ static struct of_regulator_match stpmic1_regulators_matches[] = { MATCH(pwr_sw2, SW_OUT), }; -static int stpmic1_regulator_parse_dt(void *driver_data) -{ - struct stpmic1_regulator *regul = - (struct stpmic1_regulator *)driver_data; - - if (!regul) - return -EINVAL; - - if (of_get_property(regul->reg_node, "st,mask-reset", NULL)) - regul->mask_reset = 1; - - regul->irq_curlim = of_irq_get(regul->reg_node, 0); - - return 0; -} - -static struct -regulator_dev *stpmic1_regulator_register(struct platform_device *pdev, int id, - struct regulator_init_data *init_data, - struct stpmic1_regulator *regul) +static int stpmic1_regulator_register(struct platform_device *pdev, int id, + struct of_regulator_match *match, + const struct stpmic1_regulator_cfg *cfg) { struct stpmic1 *pmic_dev = dev_get_drvdata(pdev->dev.parent); struct regulator_dev *rdev; struct regulator_config config = {}; + int ret = 0; + int irq; config.dev = &pdev->dev; - config.init_data = init_data; - config.of_node = stpmic1_regulators_matches[id].of_node; + config.init_data = match->init_data; + config.of_node = match->of_node; config.regmap = pmic_dev->regmap; - config.driver_data = regul; - - regul->regul_id = id; - regul->reg_node = config.of_node; - regul->cfg = &stpmic1_regulator_cfgs[id]; - regul->regmap = pmic_dev->regmap; + config.driver_data = (void *)cfg; - rdev = devm_regulator_register(&pdev->dev, ®ul->cfg->desc, &config); + rdev = devm_regulator_register(&pdev->dev, &cfg->desc, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register %s regulator\n", - regul->cfg->desc.name); + cfg->desc.name); + return PTR_ERR(rdev); + } + + /* set mask reset */ + if (of_get_property(config.of_node, "st,mask-reset", NULL) && + cfg->mask_reset_reg != 0) { + ret = regmap_update_bits(pmic_dev->regmap, + cfg->mask_reset_reg, + cfg->mask_reset_mask, + cfg->mask_reset_mask); + if (ret) { + dev_err(&pdev->dev, "set mask reset failed\n"); + return ret; + } } - return rdev; + /* setup an irq handler for over-current detection */ + irq = of_irq_get(config.of_node, 0); + if (irq > 0) { + ret = devm_request_threaded_irq(&pdev->dev, + irq, NULL, + stpmic1_curlim_irq_handler, + IRQF_ONESHOT | IRQF_SHARED, + pdev->name, rdev); + if (ret) { + dev_err(&pdev->dev, "Request IRQ failed\n"); + return ret; + } + } + return 0; } static int stpmic1_regulator_probe(struct platform_device *pdev) { - struct regulator_dev *rdev; - struct stpmic1_regulator *regul; - struct regulator_init_data *init_data; - struct device_node *np; int i, ret; - np = pdev->dev.of_node; - - ret = of_regulator_match(&pdev->dev, np, - stpmic1_regulators_matches, - ARRAY_SIZE(stpmic1_regulators_matches)); + ret = of_regulator_match(&pdev->dev, pdev->dev.of_node, stpmic1_matches, + ARRAY_SIZE(stpmic1_matches)); if (ret < 0) { dev_err(&pdev->dev, "Error in PMIC regulator device tree node"); return ret; } - regul = devm_kzalloc(&pdev->dev, ARRAY_SIZE(stpmic1_regulator_cfgs) * - sizeof(struct stpmic1_regulator), - GFP_KERNEL); - if (!regul) - return -ENOMEM; - for (i = 0; i < ARRAY_SIZE(stpmic1_regulator_cfgs); i++) { - /* Parse DT & find regulators to register */ - init_data = stpmic1_regulators_matches[i].init_data; - if (init_data) - init_data->regulator_init = &stpmic1_regulator_parse_dt; - - rdev = stpmic1_regulator_register(pdev, i, init_data, regul); - if (IS_ERR(rdev)) - return PTR_ERR(rdev); - - ret = stpmic1_regulator_init(pdev, rdev); - if (ret) { - dev_err(&pdev->dev, - "failed to initialize regulator %d\n", ret); + ret = stpmic1_regulator_register(pdev, i, &stpmic1_matches[i], + &stpmic1_regulator_cfgs[i]); + if (ret < 0) return ret; - } - - regul++; } dev_dbg(&pdev->dev, "stpmic1_regulator driver probed\n"); diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 884c7505ed91..402ea43c77d1 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -576,14 +576,9 @@ static int twlreg_probe(struct platform_device *pdev) struct regulator_init_data *initdata; struct regulation_constraints *c; struct regulator_dev *rdev; - const struct of_device_id *match; struct regulator_config config = { }; - match = of_match_device(twl_of_match, &pdev->dev); - if (!match) - return -ENODEV; - - template = match->data; + template = of_device_get_match_data(&pdev->dev); if (!template) return -ENODEV; diff --git a/drivers/regulator/twl6030-regulator.c b/drivers/regulator/twl6030-regulator.c index 219cbd910dbf..78b964539775 100644 --- a/drivers/regulator/twl6030-regulator.c +++ b/drivers/regulator/twl6030-regulator.c @@ -687,14 +687,9 @@ static int twlreg_probe(struct platform_device *pdev) struct regulator_init_data *initdata; struct regulation_constraints *c; struct regulator_dev *rdev; - const struct of_device_id *match; struct regulator_config config = { }; - match = of_match_device(twl_of_match, &pdev->dev); - if (!match) - return -ENODEV; - - template = match->data; + template = of_device_get_match_data(&pdev->dev); if (!template) return -ENODEV; diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 5a5bc4bb08d2..4a573eea284a 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -205,33 +205,10 @@ static irqreturn_t wm831x_dcdc_oc_irq(int irq, void *data) * BUCKV specifics */ -static int wm831x_buckv_list_voltage(struct regulator_dev *rdev, - unsigned selector) -{ - if (selector <= 0x8) - return 600000; - if (selector <= WM831X_BUCKV_MAX_SELECTOR) - return 600000 + ((selector - 0x8) * 12500); - return -EINVAL; -} - -static int wm831x_buckv_map_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - u16 vsel; - - if (min_uV < 600000) - vsel = 0; - else if (min_uV <= 1800000) - vsel = DIV_ROUND_UP(min_uV - 600000, 12500) + 8; - else - return -EINVAL; - - if (wm831x_buckv_list_voltage(rdev, vsel) > max_uV) - return -EINVAL; - - return vsel; -} +static const struct regulator_linear_range wm831x_buckv_ranges[] = { + REGULATOR_LINEAR_RANGE(600000, 0, 0x7, 0), + REGULATOR_LINEAR_RANGE(600000, 0x8, 0x68, 12500), +}; static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state) { @@ -309,7 +286,7 @@ static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev, u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL; int vsel; - vsel = wm831x_buckv_map_voltage(rdev, uV, uV); + vsel = regulator_map_voltage_linear_range(rdev, uV, uV); if (vsel < 0) return vsel; @@ -368,8 +345,8 @@ static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev) static const struct regulator_ops wm831x_buckv_ops = { .set_voltage_sel = wm831x_buckv_set_voltage_sel, .get_voltage_sel = wm831x_buckv_get_voltage_sel, - .list_voltage = wm831x_buckv_list_voltage, - .map_voltage = wm831x_buckv_map_voltage, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, .set_suspend_voltage = wm831x_buckv_set_suspend_voltage, .set_current_limit = wm831x_buckv_set_current_limit, .get_current_limit = wm831x_buckv_get_current_limit, @@ -492,6 +469,8 @@ static int wm831x_buckv_probe(struct platform_device *pdev) dcdc->desc.id = id; dcdc->desc.type = REGULATOR_VOLTAGE; dcdc->desc.n_voltages = WM831X_BUCKV_MAX_SELECTOR + 1; + dcdc->desc.linear_ranges = wm831x_buckv_ranges; + dcdc->desc.n_linear_ranges = ARRAY_SIZE(wm831x_buckv_ranges); dcdc->desc.ops = &wm831x_buckv_ops; dcdc->desc.owner = THIS_MODULE; dcdc->desc.enable_reg = WM831X_DCDC_ENABLE; |