summaryrefslogtreecommitdiff
path: root/drivers/regulator
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-04-27 02:24:42 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2021-04-27 02:24:42 +0300
commitca62e9090d229926f43f20291bb44d67897baab7 (patch)
tree16c4f978a272ac307c661995c6bc968de6457aec /drivers/regulator
parentfed584c408c123e2a0a7dd1f630d96b84e7f9e97 (diff)
parent4dd1c95306980c997b9a32e72877e060c25dc6f3 (diff)
downloadlinux-ca62e9090d229926f43f20291bb44d67897baab7.tar.xz
Merge tag 'regulator-v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator
Pull regulator updates from Mark Brown: "Not much going on with regulator this cycle, even in terms of cleanups and fixes things were fairly quiet. - New helper for setting ramp delay - Conversion of the Qualcomm RPMH bindings to YAML - Support for Tang Cheng TCS4525" * tag 'regulator-v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (26 commits) regulator: Add binding for TCS4525 regulator: fan53555: Add TCS4525 DCDC support dt-bindings: vendor-prefixes: Add Tang Cheng (TCS) regulator: core: Fix off_on_delay handling regulator: core: Respect off_on_delay at startup regulator: core.c: Improve a comment regulator: Avoid a double 'of_node_get' in 'regulator_of_get_init_node()' regulator: core.c: Fix indentation of comment regulator: s2mps11: Drop initialization via platform data regulator: s2mpa01: Drop initialization via platform data regulator: da9121: automotive variants identity fix regulator: Add regmap helper for ramp-delay setting regulator: helpers: Export helper voltage listing regulator: Add compatibles for PM7325/PMR735A regulator: Convert RPMh regulator bindings to YAML regulator: qcom-rpmh: Add PM7325/PMR735A regulator support regulator: qcom-rpmh: Add pmic5_ftsmps520 buck regulator: mt6360: remove redundant error print regulator: bd9576: Fix return from bd957x_probe() regulator: add missing call to of_node_put() ...
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/bd9576-regulator.c11
-rw-r--r--drivers/regulator/core.c59
-rw-r--r--drivers/regulator/da9121-regulator.c80
-rw-r--r--drivers/regulator/da9121-regulator.h13
-rw-r--r--drivers/regulator/fan53555.c136
-rw-r--r--drivers/regulator/helpers.c101
-rw-r--r--drivers/regulator/mt6360-regulator.c4
-rw-r--r--drivers/regulator/of_regulator.c6
-rw-r--r--drivers/regulator/pf8x00-regulator.c1
-rw-r--r--drivers/regulator/qcom-rpmh-regulator.c62
-rw-r--r--drivers/regulator/qcom_spmi-regulator.c2
-rw-r--r--drivers/regulator/s2mpa01.c4
-rw-r--r--drivers/regulator/s2mps11.c22
-rw-r--r--drivers/regulator/scmi-regulator.c4
14 files changed, 386 insertions, 119 deletions
diff --git a/drivers/regulator/bd9576-regulator.c b/drivers/regulator/bd9576-regulator.c
index a8b5832a5a1b..204a2da054f5 100644
--- a/drivers/regulator/bd9576-regulator.c
+++ b/drivers/regulator/bd9576-regulator.c
@@ -206,7 +206,7 @@ static int bd957x_probe(struct platform_device *pdev)
{
struct regmap *regmap;
struct regulator_config config = { 0 };
- int i, err;
+ int i;
bool vout_mode, ddr_sel;
const struct bd957x_regulator_data *reg_data = &bd9576_regulators[0];
unsigned int num_reg_data = ARRAY_SIZE(bd9576_regulators);
@@ -279,8 +279,7 @@ static int bd957x_probe(struct platform_device *pdev)
break;
default:
dev_err(&pdev->dev, "Unsupported chip type\n");
- err = -EINVAL;
- goto err;
+ return -EINVAL;
}
config.dev = pdev->dev.parent;
@@ -300,8 +299,7 @@ static int bd957x_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"failed to register %s regulator\n",
desc->name);
- err = PTR_ERR(rdev);
- goto err;
+ return PTR_ERR(rdev);
}
/*
* Clear the VOUT1 GPIO setting - rest of the regulators do not
@@ -310,8 +308,7 @@ static int bd957x_probe(struct platform_device *pdev)
config.ena_gpiod = NULL;
}
-err:
- return err;
+ return 0;
}
static const struct platform_device_id bd957x_pmic_id[] = {
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 16114aea099a..f192bf19492e 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -538,7 +538,8 @@ static int regulator_mode_constrain(struct regulator_dev *rdev,
/* The modes are bitmasks, the most power hungry modes having
* the lowest values. If the requested mode isn't supported
- * try higher modes. */
+ * try higher modes.
+ */
while (*mode) {
if (rdev->constraints->valid_modes_mask & *mode)
return 0;
@@ -931,7 +932,8 @@ static DEVICE_ATTR(bypass, 0444,
regulator_bypass_show, NULL);
/* Calculate the new optimum regulator operating mode based on the new total
- * consumer load. All locks held by caller */
+ * consumer load. All locks held by caller
+ */
static int drms_uA_update(struct regulator_dev *rdev)
{
struct regulator *sibling;
@@ -1219,7 +1221,8 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
int cmax = constraints->max_uV;
/* it's safe to autoconfigure fixed-voltage supplies
- and the constraints are used by list_voltage. */
+ * and the constraints are used by list_voltage.
+ */
if (count == 1 && !cmin) {
cmin = 1;
cmax = INT_MAX;
@@ -1439,6 +1442,8 @@ static int set_machine_constraints(struct regulator_dev *rdev)
if (rdev->constraints->always_on)
rdev->use_count++;
+ } else if (rdev->desc->off_on_delay) {
+ rdev->last_off = ktime_get();
}
print_constraints(rdev);
@@ -2483,29 +2488,15 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
trace_regulator_enable(rdev_get_name(rdev));
- if (rdev->desc->off_on_delay) {
+ if (rdev->desc->off_on_delay && rdev->last_off) {
/* if needed, keep a distance of off_on_delay from last time
* this regulator was disabled.
*/
- unsigned long start_jiffy = jiffies;
- unsigned long intended, max_delay, remaining;
-
- max_delay = usecs_to_jiffies(rdev->desc->off_on_delay);
- intended = rdev->last_off_jiffy + max_delay;
-
- if (time_before(start_jiffy, intended)) {
- /* calc remaining jiffies to deal with one-time
- * 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 get a penalty of
- * _regulator_enable_delay().
- */
- remaining = intended - start_jiffy;
- if (remaining <= max_delay)
- _regulator_enable_delay(
- jiffies_to_usecs(remaining));
- }
+ ktime_t end = ktime_add_us(rdev->last_off, rdev->desc->off_on_delay);
+ s64 remaining = ktime_us_delta(end, ktime_get());
+
+ if (remaining > 0)
+ _regulator_enable_delay(remaining);
}
if (rdev->ena_pin) {
@@ -2525,7 +2516,8 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
/* Allow the regulator to ramp; it would be useful to extend
* this for bulk operations so that the regulators can ramp
- * together. */
+ * together.
+ */
trace_regulator_enable_delay(rdev_get_name(rdev));
/* If poll_enabled_time is set, poll upto the delay calculated
@@ -2650,7 +2642,10 @@ static int _regulator_enable(struct regulator *regulator)
goto err_disable_supply;
if (rdev->use_count == 0) {
- /* The regulator may on if it's not switchable or left on */
+ /*
+ * The regulator may already be enabled if it's not switchable
+ * or was left on
+ */
ret = _regulator_is_enabled(rdev);
if (ret == -EINVAL || ret == 0) {
if (!regulator_ops_is_valid(rdev,
@@ -2731,11 +2726,8 @@ static int _regulator_do_disable(struct regulator_dev *rdev)
return ret;
}
- /* cares about last_off_jiffy only if off_on_delay is required by
- * device.
- */
if (rdev->desc->off_on_delay)
- rdev->last_off_jiffy = jiffies;
+ rdev->last_off = ktime_get();
trace_regulator_disable_complete(rdev_get_name(rdev));
@@ -5337,10 +5329,12 @@ regulator_register(const struct regulator_desc *regulator_desc,
ret = set_machine_constraints(rdev);
if (ret == -EPROBE_DEFER) {
/* Regulator might be in bypass mode and so needs its supply
- * to set the constraints */
+ * to set the constraints
+ */
/* FIXME: this currently triggers a chicken-and-egg problem
* when creating -SUPPLY symlink in sysfs to a regulator
- * that is just being created */
+ * that is just being created
+ */
rdev_dbg(rdev, "will resolve supply early: %s\n",
rdev->supply_name);
ret = regulator_resolve_supply(rdev);
@@ -5899,7 +5893,8 @@ static int regulator_late_cleanup(struct device *dev, void *data)
if (have_full_constraints()) {
/* We log since this may kill the system if it goes
- * wrong. */
+ * wrong.
+ */
rdev_info(rdev, "disabling\n");
ret = _regulator_do_disable(rdev);
if (ret != 0)
diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c
index a2ede7d7897e..08cbf688e14d 100644
--- a/drivers/regulator/da9121-regulator.c
+++ b/drivers/regulator/da9121-regulator.c
@@ -40,6 +40,7 @@ struct da9121 {
unsigned int passive_delay;
int chip_irq;
int variant_id;
+ int subvariant_id;
};
/* Define ranges for different variants, enabling translation to/from
@@ -812,7 +813,6 @@ static struct regmap_config da9121_2ch_regmap_config = {
static int da9121_check_device_type(struct i2c_client *i2c, struct da9121 *chip)
{
u32 device_id;
- u8 chip_id = chip->variant_id;
u32 variant_id;
u8 variant_mrc, variant_vrc;
char *type;
@@ -839,22 +839,34 @@ static int da9121_check_device_type(struct i2c_client *i2c, struct da9121 *chip)
variant_vrc = variant_id & DA9121_MASK_OTP_VARIANT_ID_VRC;
- switch (variant_vrc) {
- case DA9121_VARIANT_VRC:
- type = "DA9121/DA9130";
- config_match = (chip_id == DA9121_TYPE_DA9121_DA9130);
+ switch (chip->subvariant_id) {
+ case DA9121_SUBTYPE_DA9121:
+ type = "DA9121";
+ config_match = (variant_vrc == DA9121_VARIANT_VRC);
break;
- case DA9220_VARIANT_VRC:
- type = "DA9220/DA9132";
- config_match = (chip_id == DA9121_TYPE_DA9220_DA9132);
+ case DA9121_SUBTYPE_DA9130:
+ type = "DA9130";
+ config_match = (variant_vrc == DA9130_VARIANT_VRC);
break;
- case DA9122_VARIANT_VRC:
- type = "DA9122/DA9131";
- config_match = (chip_id == DA9121_TYPE_DA9122_DA9131);
+ case DA9121_SUBTYPE_DA9220:
+ type = "DA9220";
+ config_match = (variant_vrc == DA9220_VARIANT_VRC);
break;
- case DA9217_VARIANT_VRC:
+ case DA9121_SUBTYPE_DA9132:
+ type = "DA9132";
+ config_match = (variant_vrc == DA9132_VARIANT_VRC);
+ break;
+ case DA9121_SUBTYPE_DA9122:
+ type = "DA9122";
+ config_match = (variant_vrc == DA9122_VARIANT_VRC);
+ break;
+ case DA9121_SUBTYPE_DA9131:
+ type = "DA9131";
+ config_match = (variant_vrc == DA9131_VARIANT_VRC);
+ break;
+ case DA9121_SUBTYPE_DA9217:
type = "DA9217";
- config_match = (chip_id == DA9121_TYPE_DA9217);
+ config_match = (variant_vrc == DA9217_VARIANT_VRC);
break;
default:
type = "Unknown";
@@ -892,15 +904,27 @@ static int da9121_assign_chip_model(struct i2c_client *i2c,
chip->dev = &i2c->dev;
- switch (chip->variant_id) {
- case DA9121_TYPE_DA9121_DA9130:
- fallthrough;
- case DA9121_TYPE_DA9217:
+ /* Use configured subtype to select the regulator descriptor index and
+ * register map, common to both consumer and automotive grade variants
+ */
+ switch (chip->subvariant_id) {
+ case DA9121_SUBTYPE_DA9121:
+ case DA9121_SUBTYPE_DA9130:
+ chip->variant_id = DA9121_TYPE_DA9121_DA9130;
regmap = &da9121_1ch_regmap_config;
break;
- case DA9121_TYPE_DA9122_DA9131:
- fallthrough;
- case DA9121_TYPE_DA9220_DA9132:
+ case DA9121_SUBTYPE_DA9217:
+ chip->variant_id = DA9121_TYPE_DA9217;
+ regmap = &da9121_1ch_regmap_config;
+ break;
+ case DA9121_SUBTYPE_DA9122:
+ case DA9121_SUBTYPE_DA9131:
+ chip->variant_id = DA9121_TYPE_DA9122_DA9131;
+ regmap = &da9121_2ch_regmap_config;
+ break;
+ case DA9121_SUBTYPE_DA9220:
+ case DA9121_SUBTYPE_DA9132:
+ chip->variant_id = DA9121_TYPE_DA9220_DA9132;
regmap = &da9121_2ch_regmap_config;
break;
}
@@ -975,13 +999,13 @@ regmap_error:
}
static const struct of_device_id da9121_dt_ids[] = {
- { .compatible = "dlg,da9121", .data = (void *) DA9121_TYPE_DA9121_DA9130 },
- { .compatible = "dlg,da9130", .data = (void *) DA9121_TYPE_DA9121_DA9130 },
- { .compatible = "dlg,da9217", .data = (void *) DA9121_TYPE_DA9217 },
- { .compatible = "dlg,da9122", .data = (void *) DA9121_TYPE_DA9122_DA9131 },
- { .compatible = "dlg,da9131", .data = (void *) DA9121_TYPE_DA9122_DA9131 },
- { .compatible = "dlg,da9220", .data = (void *) DA9121_TYPE_DA9220_DA9132 },
- { .compatible = "dlg,da9132", .data = (void *) DA9121_TYPE_DA9220_DA9132 },
+ { .compatible = "dlg,da9121", .data = (void *) DA9121_SUBTYPE_DA9121 },
+ { .compatible = "dlg,da9130", .data = (void *) DA9121_SUBTYPE_DA9130 },
+ { .compatible = "dlg,da9217", .data = (void *) DA9121_SUBTYPE_DA9217 },
+ { .compatible = "dlg,da9122", .data = (void *) DA9121_SUBTYPE_DA9122 },
+ { .compatible = "dlg,da9131", .data = (void *) DA9121_SUBTYPE_DA9131 },
+ { .compatible = "dlg,da9220", .data = (void *) DA9121_SUBTYPE_DA9220 },
+ { .compatible = "dlg,da9132", .data = (void *) DA9121_SUBTYPE_DA9132 },
{ }
};
MODULE_DEVICE_TABLE(of, da9121_dt_ids);
@@ -1011,7 +1035,7 @@ static int da9121_i2c_probe(struct i2c_client *i2c,
}
chip->pdata = i2c->dev.platform_data;
- chip->variant_id = da9121_of_get_id(&i2c->dev);
+ chip->subvariant_id = da9121_of_get_id(&i2c->dev);
ret = da9121_assign_chip_model(i2c, chip);
if (ret < 0)
diff --git a/drivers/regulator/da9121-regulator.h b/drivers/regulator/da9121-regulator.h
index 3c34cb889ca8..357f416e17c1 100644
--- a/drivers/regulator/da9121-regulator.h
+++ b/drivers/regulator/da9121-regulator.h
@@ -29,6 +29,16 @@ enum da9121_variant {
DA9121_TYPE_DA9217
};
+enum da9121_subvariant {
+ DA9121_SUBTYPE_DA9121,
+ DA9121_SUBTYPE_DA9130,
+ DA9121_SUBTYPE_DA9220,
+ DA9121_SUBTYPE_DA9132,
+ DA9121_SUBTYPE_DA9122,
+ DA9121_SUBTYPE_DA9131,
+ DA9121_SUBTYPE_DA9217
+};
+
/* Minimum, maximum and default polling millisecond periods are provided
* here as an example. It is expected that any final implementation will
* include a modification of these settings to match the required
@@ -279,6 +289,9 @@ enum da9121_variant {
#define DA9220_VARIANT_VRC 0x0
#define DA9122_VARIANT_VRC 0x2
#define DA9217_VARIANT_VRC 0x7
+#define DA9130_VARIANT_VRC 0x0
+#define DA9131_VARIANT_VRC 0x1
+#define DA9132_VARIANT_VRC 0x2
/* DA9121_REG_OTP_CUSTOMER_ID */
diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
index aa426183b6a1..f3918f03aaf3 100644
--- a/drivers/regulator/fan53555.c
+++ b/drivers/regulator/fan53555.c
@@ -24,6 +24,12 @@
/* Voltage setting */
#define FAN53555_VSEL0 0x00
#define FAN53555_VSEL1 0x01
+
+#define TCS4525_VSEL0 0x11
+#define TCS4525_VSEL1 0x10
+#define TCS4525_TIME 0x13
+#define TCS4525_COMMAND 0x14
+
/* Control register */
#define FAN53555_CONTROL 0x02
/* IC Type */
@@ -49,11 +55,20 @@
#define FAN53555_NVOLTAGES 64 /* Numbers of voltages */
#define FAN53526_NVOLTAGES 128
+#define TCS4525_NVOLTAGES 127 /* Numbers of voltages */
+
+#define TCS_VSEL_NSEL_MASK 0x7f
+#define TCS_VSEL0_MODE (1 << 7)
+#define TCS_VSEL1_MODE (1 << 6)
+
+#define TCS_SLEW_SHIFT 3
+#define TCS_SLEW_MASK (0x3 < 3)
enum fan53555_vendor {
FAN53526_VENDOR_FAIRCHILD = 0,
FAN53555_VENDOR_FAIRCHILD,
FAN53555_VENDOR_SILERGY,
+ FAN53555_VENDOR_TCS,
};
enum {
@@ -106,6 +121,11 @@ struct fan53555_device_info {
unsigned int mode_mask;
/* Sleep voltage cache */
unsigned int sleep_vol_cache;
+ /* Slew rate */
+ unsigned int slew_reg;
+ unsigned int slew_mask;
+ unsigned int slew_shift;
+ unsigned int slew_rate;
};
static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV)
@@ -189,13 +209,37 @@ static const int slew_rates[] = {
500,
};
+static const int tcs_slew_rates[] = {
+ 18700,
+ 9300,
+ 4600,
+ 2300,
+};
+
static int fan53555_set_ramp(struct regulator_dev *rdev, int ramp)
{
struct fan53555_device_info *di = rdev_get_drvdata(rdev);
int regval = -1, i;
+ const int *slew_rate_t;
+ int slew_rate_n;
- for (i = 0; i < ARRAY_SIZE(slew_rates); i++) {
- if (ramp <= slew_rates[i])
+ switch (di->vendor) {
+ case FAN53526_VENDOR_FAIRCHILD:
+ case FAN53555_VENDOR_FAIRCHILD:
+ case FAN53555_VENDOR_SILERGY:
+ slew_rate_t = slew_rates;
+ slew_rate_n = ARRAY_SIZE(slew_rates);
+ break;
+ case FAN53555_VENDOR_TCS:
+ slew_rate_t = tcs_slew_rates;
+ slew_rate_n = ARRAY_SIZE(tcs_slew_rates);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < slew_rate_n; i++) {
+ if (ramp <= slew_rate_t[i])
regval = i;
else
break;
@@ -206,8 +250,8 @@ static int fan53555_set_ramp(struct regulator_dev *rdev, int ramp)
return -EINVAL;
}
- return regmap_update_bits(rdev->regmap, FAN53555_CONTROL,
- CTL_SLEW_MASK, regval << CTL_SLEW_SHIFT);
+ return regmap_update_bits(rdev->regmap, di->slew_reg,
+ di->slew_mask, regval << di->slew_shift);
}
static const struct regulator_ops fan53555_regulator_ops = {
@@ -292,7 +336,9 @@ static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di)
"Chip ID %d not supported!\n", di->chip_id);
return -EINVAL;
}
-
+ di->slew_reg = FAN53555_CONTROL;
+ di->slew_mask = CTL_SLEW_MASK;
+ di->slew_shift = CTL_SLEW_SHIFT;
di->vsel_count = FAN53555_NVOLTAGES;
return 0;
@@ -312,12 +358,29 @@ static int fan53555_voltages_setup_silergy(struct fan53555_device_info *di)
"Chip ID %d not supported!\n", di->chip_id);
return -EINVAL;
}
-
+ di->slew_reg = FAN53555_CONTROL;
+ di->slew_reg = FAN53555_CONTROL;
+ di->slew_mask = CTL_SLEW_MASK;
+ di->slew_shift = CTL_SLEW_SHIFT;
di->vsel_count = FAN53555_NVOLTAGES;
return 0;
}
+static int fan53555_voltages_setup_tcs(struct fan53555_device_info *di)
+{
+ di->slew_reg = TCS4525_TIME;
+ di->slew_mask = TCS_SLEW_MASK;
+ di->slew_shift = TCS_SLEW_MASK;
+
+ /* Init voltage range and step */
+ di->vsel_min = 600000;
+ di->vsel_step = 6250;
+ di->vsel_count = TCS4525_NVOLTAGES;
+
+ return 0;
+}
+
/* For 00,01,03,05 options:
* VOUT = 0.60V + NSELx * 10mV, from 0.60 to 1.23V.
* For 04 option:
@@ -329,17 +392,41 @@ static int fan53555_device_setup(struct fan53555_device_info *di,
int ret = 0;
/* Setup voltage control register */
- switch (pdata->sleep_vsel_id) {
- case FAN53555_VSEL_ID_0:
- di->sleep_reg = FAN53555_VSEL0;
- di->vol_reg = FAN53555_VSEL1;
+ switch (di->vendor) {
+ case FAN53526_VENDOR_FAIRCHILD:
+ case FAN53555_VENDOR_FAIRCHILD:
+ case FAN53555_VENDOR_SILERGY:
+ switch (pdata->sleep_vsel_id) {
+ case FAN53555_VSEL_ID_0:
+ di->sleep_reg = FAN53555_VSEL0;
+ di->vol_reg = FAN53555_VSEL1;
+ break;
+ case FAN53555_VSEL_ID_1:
+ di->sleep_reg = FAN53555_VSEL1;
+ di->vol_reg = FAN53555_VSEL0;
+ break;
+ default:
+ dev_err(di->dev, "Invalid VSEL ID!\n");
+ return -EINVAL;
+ }
break;
- case FAN53555_VSEL_ID_1:
- di->sleep_reg = FAN53555_VSEL1;
- di->vol_reg = FAN53555_VSEL0;
+ case FAN53555_VENDOR_TCS:
+ switch (pdata->sleep_vsel_id) {
+ case FAN53555_VSEL_ID_0:
+ di->sleep_reg = TCS4525_VSEL0;
+ di->vol_reg = TCS4525_VSEL1;
+ break;
+ case FAN53555_VSEL_ID_1:
+ di->sleep_reg = TCS4525_VSEL1;
+ di->vol_reg = TCS4525_VSEL0;
+ break;
+ default:
+ dev_err(di->dev, "Invalid VSEL ID!\n");
+ return -EINVAL;
+ }
break;
default:
- dev_err(di->dev, "Invalid VSEL ID!\n");
+ dev_err(di->dev, "vendor %d not supported!\n", di->vendor);
return -EINVAL;
}
@@ -362,6 +449,18 @@ static int fan53555_device_setup(struct fan53555_device_info *di,
di->mode_reg = di->vol_reg;
di->mode_mask = VSEL_MODE;
break;
+ case FAN53555_VENDOR_TCS:
+ di->mode_reg = TCS4525_COMMAND;
+
+ switch (pdata->sleep_vsel_id) {
+ case FAN53555_VSEL_ID_0:
+ di->mode_mask = TCS_VSEL1_MODE;
+ break;
+ case FAN53555_VSEL_ID_1:
+ di->mode_mask = TCS_VSEL0_MODE;
+ break;
+ }
+ break;
default:
dev_err(di->dev, "vendor %d not supported!\n", di->vendor);
return -EINVAL;
@@ -378,6 +477,9 @@ static int fan53555_device_setup(struct fan53555_device_info *di,
case FAN53555_VENDOR_SILERGY:
ret = fan53555_voltages_setup_silergy(di);
break;
+ case FAN53555_VENDOR_TCS:
+ ret = fan53555_voltages_setup_tcs(di);
+ break;
default:
dev_err(di->dev, "vendor %d not supported!\n", di->vendor);
return -EINVAL;
@@ -449,6 +551,9 @@ static const struct of_device_id __maybe_unused fan53555_dt_ids[] = {
}, {
.compatible = "silergy,syr828",
.data = (void *)FAN53555_VENDOR_SILERGY,
+ }, {
+ .compatible = "tcs,tcs4525",
+ .data = (void *)FAN53555_VENDOR_TCS
},
{ }
};
@@ -554,6 +659,9 @@ static const struct i2c_device_id fan53555_id[] = {
}, {
.name = "syr828",
.driver_data = FAN53555_VENDOR_SILERGY
+ }, {
+ .name = "tcs4525",
+ .driver_data = FAN53555_VENDOR_TCS
},
{ },
};
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index f42b394a0c46..0e16e31c968f 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -509,6 +509,33 @@ int regulator_map_voltage_pickable_linear_range(struct regulator_dev *rdev,
EXPORT_SYMBOL_GPL(regulator_map_voltage_pickable_linear_range);
/**
+ * regulator_desc_list_voltage_linear - List voltages with simple calculation
+ *
+ * @desc: Regulator desc for regulator which volatges are to be listed
+ * @selector: Selector to convert into a voltage
+ *
+ * Regulators with a simple linear mapping between voltages and
+ * selectors can set min_uV and uV_step in the regulator descriptor
+ * and then use this function prior regulator registration to list
+ * the voltages. This is useful when voltages need to be listed during
+ * device-tree parsing.
+ */
+int regulator_desc_list_voltage_linear(const struct regulator_desc *desc,
+ unsigned int selector)
+{
+ if (selector >= desc->n_voltages)
+ return -EINVAL;
+
+ if (selector < desc->linear_min_sel)
+ return 0;
+
+ selector -= desc->linear_min_sel;
+
+ return desc->min_uV + (desc->uV_step * selector);
+}
+EXPORT_SYMBOL_GPL(regulator_desc_list_voltage_linear);
+
+/**
* regulator_list_voltage_linear - List voltages with simple calculation
*
* @rdev: Regulator device
@@ -521,14 +548,7 @@ EXPORT_SYMBOL_GPL(regulator_map_voltage_pickable_linear_range);
int regulator_list_voltage_linear(struct regulator_dev *rdev,
unsigned int selector)
{
- if (selector >= rdev->desc->n_voltages)
- return -EINVAL;
- if (selector < rdev->desc->linear_min_sel)
- return 0;
-
- selector -= rdev->desc->linear_min_sel;
-
- return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
+ return regulator_desc_list_voltage_linear(rdev->desc, selector);
}
EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
@@ -881,3 +901,68 @@ bool regulator_is_equal(struct regulator *reg1, struct regulator *reg2)
return reg1->rdev == reg2->rdev;
}
EXPORT_SYMBOL_GPL(regulator_is_equal);
+
+static int find_closest_bigger(unsigned int target, const unsigned int *table,
+ unsigned int num_sel, unsigned int *sel)
+{
+ unsigned int s, tmp, max, maxsel = 0;
+ bool found = false;
+
+ max = table[0];
+
+ for (s = 0; s < num_sel; s++) {
+ if (table[s] > max) {
+ max = table[s];
+ maxsel = s;
+ }
+ if (table[s] >= target) {
+ if (!found || table[s] - target < tmp - target) {
+ tmp = table[s];
+ *sel = s;
+ found = true;
+ if (tmp == target)
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ *sel = maxsel;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * regulator_set_ramp_delay_regmap - set_ramp_delay() helper
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the ramp_reg
+ * and ramp_mask fields in their descriptor and then use this as their
+ * set_ramp_delay operation, saving some code.
+ */
+int regulator_set_ramp_delay_regmap(struct regulator_dev *rdev, int ramp_delay)
+{
+ int ret;
+ unsigned int sel;
+
+ if (!rdev->desc->n_ramp_values)
+ return -EINVAL;
+
+ ret = find_closest_bigger(ramp_delay, rdev->desc->ramp_delay_table,
+ rdev->desc->n_ramp_values, &sel);
+
+ if (ret) {
+ dev_warn(rdev_get_dev(rdev),
+ "Can't set ramp-delay %u, setting %u\n", ramp_delay,
+ rdev->desc->ramp_delay_table[sel]);
+ }
+
+ sel <<= ffs(rdev->desc->ramp_mask) - 1;
+
+ return regmap_update_bits(rdev->regmap, rdev->desc->ramp_reg,
+ rdev->desc->ramp_mask, sel);
+}
+EXPORT_SYMBOL_GPL(regulator_set_ramp_delay_regmap);
diff --git a/drivers/regulator/mt6360-regulator.c b/drivers/regulator/mt6360-regulator.c
index 15308ee29c13..4d34be94d166 100644
--- a/drivers/regulator/mt6360-regulator.c
+++ b/drivers/regulator/mt6360-regulator.c
@@ -380,10 +380,8 @@ static int mt6360_regulator_irq_register(struct platform_device *pdev,
const struct mt6360_irq_mapping *irq_desc = tbls + i;
irq = platform_get_irq_byname(pdev, irq_desc->name);
- if (irq < 0) {
- dev_err(&pdev->dev, "Fail to get %s irq\n", irq_desc->name);
+ if (irq < 0)
return irq;
- }
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, irq_desc->handler, 0,
irq_desc->name, rdev);
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 564f928eb1db..49f6c05fee34 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -422,7 +422,11 @@ device_node *regulator_of_get_init_node(struct device *dev,
if (!strcmp(desc->of_match, name)) {
of_node_put(search);
- return of_node_get(child);
+ /*
+ * 'of_node_get(child)' is already performed by the
+ * for_each loop.
+ */
+ return child;
}
}
diff --git a/drivers/regulator/pf8x00-regulator.c b/drivers/regulator/pf8x00-regulator.c
index 9b28bd63208d..5d319fb81288 100644
--- a/drivers/regulator/pf8x00-regulator.c
+++ b/drivers/regulator/pf8x00-regulator.c
@@ -359,6 +359,7 @@ static const struct regulator_ops pf8x00_buck7_ops = {
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.get_current_limit = regulator_get_current_limit_regmap,
diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c
index 65a108c9121f..22fec370fa61 100644
--- a/drivers/regulator/qcom-rpmh-regulator.c
+++ b/drivers/regulator/qcom-rpmh-regulator.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-// Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+// Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
#define pr_fmt(fmt) "%s: " fmt, __func__
@@ -723,6 +723,15 @@ static const struct rpmh_vreg_hw_data pmic5_ftsmps510 = {
.of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode,
};
+static const struct rpmh_vreg_hw_data pmic5_ftsmps520 = {
+ .regulator_type = VRM,
+ .ops = &rpmh_regulator_vrm_ops,
+ .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 263, 4000),
+ .n_voltages = 264,
+ .pmic_mode_map = pmic_mode_map_pmic5_smps,
+ .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode,
+};
+
static const struct rpmh_vreg_hw_data pmic5_hfsmps515 = {
.regulator_type = VRM,
.ops = &rpmh_regulator_vrm_ops,
@@ -1033,6 +1042,49 @@ static const struct rpmh_vreg_init_data pmx55_vreg_data[] = {
{},
};
+static const struct rpmh_vreg_init_data pm7325_vreg_data[] = {
+ RPMH_VREG("smps1", "smp%s1", &pmic5_hfsmps510, "vdd-s1"),
+ RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps520, "vdd-s2"),
+ RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps520, "vdd-s3"),
+ RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps520, "vdd-s4"),
+ RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps520, "vdd-s5"),
+ RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps520, "vdd-s6"),
+ RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps520, "vdd-s7"),
+ RPMH_VREG("smps8", "smp%s8", &pmic5_hfsmps510, "vdd-s8"),
+ RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1-l4-l12-l15"),
+ RPMH_VREG("ldo2", "ldo%s2", &pmic5_pldo, "vdd-l2-l7"),
+ RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"),
+ RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l1-l4-l12-l15"),
+ RPMH_VREG("ldo5", "ldo%s5", &pmic5_nldo, "vdd-l5"),
+ RPMH_VREG("ldo6", "ldo%s6", &pmic5_nldo, "vdd-l6-l9-l10"),
+ RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l2-l7"),
+ RPMH_VREG("ldo8", "ldo%s8", &pmic5_nldo, "vdd-l8"),
+ RPMH_VREG("ldo9", "ldo%s9", &pmic5_nldo, "vdd-l6-l9-l10"),
+ RPMH_VREG("ldo10", "ldo%s10", &pmic5_nldo, "vdd-l6-l9-l10"),
+ RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo_lv, "vdd-l11-l17-l18-l19"),
+ RPMH_VREG("ldo12", "ldo%s12", &pmic5_nldo, "vdd-l1-l4-l12-l15"),
+ RPMH_VREG("ldo13", "ldo%s13", &pmic5_nldo, "vdd-l13"),
+ RPMH_VREG("ldo14", "ldo%s14", &pmic5_nldo, "vdd-l14-l16"),
+ RPMH_VREG("ldo15", "ldo%s15", &pmic5_nldo, "vdd-l1-l4-l12-l15"),
+ RPMH_VREG("ldo16", "ldo%s16", &pmic5_nldo, "vdd-l14-l16"),
+ RPMH_VREG("ldo17", "ldo%s17", &pmic5_pldo_lv, "vdd-l11-l17-l18-l19"),
+ RPMH_VREG("ldo18", "ldo%s18", &pmic5_pldo_lv, "vdd-l11-l17-l18-l19"),
+ RPMH_VREG("ldo19", "ldo%s19", &pmic5_pldo_lv, "vdd-l11-l17-l18-l19"),
+};
+
+static const struct rpmh_vreg_init_data pmr735a_vreg_data[] = {
+ RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps520, "vdd-s1"),
+ RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps520, "vdd-s2"),
+ RPMH_VREG("smps3", "smp%s3", &pmic5_hfsmps510, "vdd-s3"),
+ RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1-l2"),
+ RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l1-l2"),
+ RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"),
+ RPMH_VREG("ldo4", "ldo%s4", &pmic5_pldo_lv, "vdd-l4"),
+ RPMH_VREG("ldo5", "ldo%s5", &pmic5_nldo, "vdd-l5-l6"),
+ RPMH_VREG("ldo6", "ldo%s6", &pmic5_nldo, "vdd-l5-l6"),
+ RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l7-bob"),
+};
+
static int rpmh_regulator_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1127,6 +1179,14 @@ static const struct of_device_id __maybe_unused rpmh_regulator_match_table[] = {
.compatible = "qcom,pmx55-rpmh-regulators",
.data = pmx55_vreg_data,
},
+ {
+ .compatible = "qcom,pm7325-rpmh-regulators",
+ .data = pm7325_vreg_data,
+ },
+ {
+ .compatible = "qcom,pmr735a-rpmh-regulators",
+ .data = pmr735a_vreg_data,
+ },
{}
};
MODULE_DEVICE_TABLE(of, rpmh_regulator_match_table);
diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c
index c2442d7798ab..95677c51c1fa 100644
--- a/drivers/regulator/qcom_spmi-regulator.c
+++ b/drivers/regulator/qcom_spmi-regulator.c
@@ -1523,10 +1523,12 @@ static const struct spmi_regulator_mapping supported_regulators[] = {
SPMI_VREG(ULT_LDO, N600_ST, 0, INF, ULT_LDO, ult_ldo, ult_nldo, 10000),
SPMI_VREG(ULT_LDO, N900_ST, 0, INF, ULT_LDO, ult_ldo, ult_nldo, 10000),
SPMI_VREG(ULT_LDO, N1200_ST, 0, INF, ULT_LDO, ult_ldo, ult_nldo, 10000),
+ SPMI_VREG(ULT_LDO, LV_P50, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000),
SPMI_VREG(ULT_LDO, LV_P150, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000),
SPMI_VREG(ULT_LDO, LV_P300, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000),
SPMI_VREG(ULT_LDO, LV_P450, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000),
SPMI_VREG(ULT_LDO, P600, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000),
+ SPMI_VREG(ULT_LDO, P300, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000),
SPMI_VREG(ULT_LDO, P150, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000),
SPMI_VREG(ULT_LDO, P50, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 5000),
};
diff --git a/drivers/regulator/s2mpa01.c b/drivers/regulator/s2mpa01.c
index 115f59530852..28b424fe7bea 100644
--- a/drivers/regulator/s2mpa01.c
+++ b/drivers/regulator/s2mpa01.c
@@ -340,7 +340,6 @@ static const struct regulator_desc regulators[] = {
static int s2mpa01_pmic_probe(struct platform_device *pdev)
{
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
- struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
struct regulator_config config = { };
struct s2mpa01_info *s2mpa01;
int i;
@@ -356,9 +355,6 @@ static int s2mpa01_pmic_probe(struct platform_device *pdev)
for (i = 0; i < S2MPA01_REGULATOR_MAX; i++) {
struct regulator_dev *rdev;
- if (pdata)
- config.init_data = pdata->regulators[i].initdata;
-
rdev = devm_regulator_register(&pdev->dev,
&regulators[i], &config);
if (IS_ERR(rdev)) {
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 33cf84bce05a..ebc67e3ddd4f 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -1120,7 +1120,6 @@ static const struct regulator_desc s2mpu02_regulators[] = {
static int s2mps11_pmic_probe(struct platform_device *pdev)
{
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
- struct sec_platform_data *pdata = NULL;
struct of_regulator_match *rdata = NULL;
struct regulator_config config = { };
struct s2mps11_info *s2mps11;
@@ -1171,17 +1170,6 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
if (!s2mps11->ext_control_gpiod)
return -ENOMEM;
- if (!iodev->dev->of_node) {
- if (iodev->pdata) {
- pdata = iodev->pdata;
- goto common_reg;
- } else {
- dev_err(pdev->dev.parent,
- "Platform data or DT node not supplied\n");
- return -ENODEV;
- }
- }
-
rdata = kcalloc(rdev_num, sizeof(*rdata), GFP_KERNEL);
if (!rdata)
return -ENOMEM;
@@ -1193,7 +1181,6 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
if (ret)
goto out;
-common_reg:
platform_set_drvdata(pdev, s2mps11);
config.dev = &pdev->dev;
@@ -1202,13 +1189,8 @@ common_reg:
for (i = 0; i < rdev_num; i++) {
struct regulator_dev *regulator;
- if (pdata) {
- config.init_data = pdata->regulators[i].initdata;
- config.of_node = pdata->regulators[i].reg_node;
- } else {
- config.init_data = rdata[i].init_data;
- config.of_node = rdata[i].of_node;
- }
+ config.init_data = rdata[i].init_data;
+ config.of_node = rdata[i].of_node;
config.ena_gpiod = s2mps11->ext_control_gpiod[i];
/*
* Hand the GPIO descriptor management over to the regulator
diff --git a/drivers/regulator/scmi-regulator.c b/drivers/regulator/scmi-regulator.c
index a38343f8c843..bbadf72b94e8 100644
--- a/drivers/regulator/scmi-regulator.c
+++ b/drivers/regulator/scmi-regulator.c
@@ -347,8 +347,10 @@ static int scmi_regulator_probe(struct scmi_device *sdev)
for_each_child_of_node(np, child) {
ret = process_scmi_regulator_of_node(sdev, ph, child, rinfo);
/* abort on any mem issue */
- if (ret == -ENOMEM)
+ if (ret == -ENOMEM) {
+ of_node_put(child);
return ret;
+ }
}
/*