diff options
author | Linus Torvalds | 2021-08-30 11:37:15 -0700 |
---|---|---|
committer | Linus Torvalds | 2021-08-30 11:37:15 -0700 |
commit | d46e0d335497d89e36a8dab3ce5b605d7088c67a (patch) | |
tree | c4e3ab76b1efaf0b41391ad091bd54f231990fc1 /drivers | |
parent | 4aed6ee53fcc012ea599f1be6b2c8d76cb7f7354 (diff) | |
parent | 7aa6d700b089d960a03f6459898c096f4346990c (diff) |
Merge tag 'regulator-v5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator
Pull regulator updates from Mark Brown:
"A very quiet releases, some fixes and cleanups but not really that
many of them. There were a couple of new driver specific pieces:
- Support for controlling the over/under voltage protection on
BD718xx devices
- New drivers for Richtek RTQ2134, and RTQ6752"
* tag 'regulator-v5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (37 commits)
regulator: vctrl: Avoid lockdep warning in enable/disable ops
regulator: vctrl: Use locked regulator_get_voltage in probe path
regulator: Documentation fix for regulator error notification helper
regulator: Minor regulator documentation fixes.
regulator: sy7636a: Use the regmap directly
regulator: sy7636a: Store the epd-pwr-good GPIO locally
regulator: sy7636a: Use the parent driver data
regulator: sy7636a: Remove the poll_enable_time
regulator: sy8827n: Enable REGCACHE_FLAT
regulator: sy8824x: Enable REGCACHE_FLAT
regulator: rtq2134: Fix coding style
regulator: hi6421v600: rename voltage range arrays
regulator: hi6421v600: use lowercase for ldo
regulator: fixed: use dev_err_probe for register
regulator: rtq2134: Add support for Richtek RTQ2134 SubPMIC
regulator: rtq2134: Add binding document for Richtek RTQ2134 SubPMIC
regulator: Fix a couple of spelling mistakes in Kconfig
regulator: rtq6752: fix reg reset behavior
regulator: da9063: Add support for full-current mode.
regulator: rt6245: make a const array func_base static, makes object smaller
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/regulator/Kconfig | 24 | ||||
-rw-r--r-- | drivers/regulator/Makefile | 2 | ||||
-rw-r--r-- | drivers/regulator/bd718x7-regulator.c | 369 | ||||
-rw-r--r-- | drivers/regulator/da9063-regulator.c | 132 | ||||
-rw-r--r-- | drivers/regulator/dbx500-prcmu.c | 4 | ||||
-rw-r--r-- | drivers/regulator/devres.c | 69 | ||||
-rw-r--r-- | drivers/regulator/fixed.c | 5 | ||||
-rw-r--r-- | drivers/regulator/hi6421v600-regulator.c | 50 | ||||
-rw-r--r-- | drivers/regulator/irq_helpers.c | 2 | ||||
-rw-r--r-- | drivers/regulator/mt6358-regulator.c | 87 | ||||
-rw-r--r-- | drivers/regulator/mt6359-regulator.c | 19 | ||||
-rw-r--r-- | drivers/regulator/mt6397-regulator.c | 15 | ||||
-rw-r--r-- | drivers/regulator/rt5033-regulator.c | 21 | ||||
-rw-r--r-- | drivers/regulator/rt6245-regulator.c | 2 | ||||
-rw-r--r-- | drivers/regulator/rtq2134-regulator.c | 373 | ||||
-rw-r--r-- | drivers/regulator/rtq6752-regulator.c | 289 | ||||
-rw-r--r-- | drivers/regulator/sy7636a-regulator.c | 41 | ||||
-rw-r--r-- | drivers/regulator/sy8824x.c | 16 | ||||
-rw-r--r-- | drivers/regulator/sy8827n.c | 14 | ||||
-rw-r--r-- | drivers/regulator/tps65910-regulator.c | 10 | ||||
-rw-r--r-- | drivers/regulator/vctrl-regulator.c | 73 |
21 files changed, 1281 insertions, 336 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 24ce9a17ab4f..4fd13b06231f 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -1044,7 +1044,7 @@ config REGULATOR_RT6160 help This adds support for voltage regulator in Richtek RT6160. This device automatically change voltage output mode from - Buck or Boost. The mode transistion depend on the input source voltage. + Buck or Boost. The mode transition depend on the input source voltage. The wide output range is from 2025mV to 5200mV and can be used on most common application scenario. @@ -1053,10 +1053,21 @@ config REGULATOR_RT6245 depends on I2C select REGMAP_I2C help - This adds supprot for Richtek RT6245 voltage regulator. + This adds support for Richtek RT6245 voltage regulator. It can support up to 14A output current and adjustable output voltage from 0.4375V to 1.3875V, per step 12.5mV. +config REGULATOR_RTQ2134 + tristate "Richtek RTQ2134 SubPMIC Regulator" + depends on I2C + select REGMAP_I2C + help + This driver adds support for RTQ2134 SubPMIC regulators. + The RTQ2134 is a multi-phase, programmable power management IC that + integrate with four high efficient, synchronous step-down converter + cores. It features wide output voltage range and the capability to + configure the corresponding power stages. + config REGULATOR_RTMV20 tristate "Richtek RTMV20 Laser Diode Regulator" depends on I2C @@ -1066,6 +1077,15 @@ config REGULATOR_RTMV20 the Richtek RTMV20. It can support the load current up to 6A and integrate strobe/vsync/fsin signal to synchronize the IR camera. +config REGULATOR_RTQ6752 + tristate "Richtek RTQ6752 TFT LCD voltage regulator" + depends on I2C + select REGMAP_I2C + help + This driver adds support for Richtek RTQ6752. RTQ6752 includes two + synchronous boost converters for PAVDD, and one synchronous NAVDD + buck-boost. This device is suitable for automotive TFT-LCD panel. + config REGULATOR_S2MPA01 tristate "Samsung S2MPA01 voltage regulator" depends on MFD_SEC_CORE || COMPILE_TEST diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 8c2f82206b94..9e382b50a5ef 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -128,6 +128,8 @@ obj-$(CONFIG_REGULATOR_RT5033) += rt5033-regulator.o obj-$(CONFIG_REGULATOR_RT6160) += rt6160-regulator.o obj-$(CONFIG_REGULATOR_RT6245) += rt6245-regulator.o obj-$(CONFIG_REGULATOR_RTMV20) += rtmv20-regulator.o +obj-$(CONFIG_REGULATOR_RTQ2134) += rtq2134-regulator.o +obj-$(CONFIG_REGULATOR_RTQ6752) += rtq6752-regulator.o obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c index b1eb46961993..d60fccedb250 100644 --- a/drivers/regulator/bd718x7-regulator.c +++ b/drivers/regulator/bd718x7-regulator.c @@ -55,7 +55,8 @@ #define BD718XX_HWOPNAME(swopname) swopname##_hwcontrol #define BD718XX_OPS(name, _list_voltage, _map_voltage, _set_voltage_sel, \ - _get_voltage_sel, _set_voltage_time_sel, _set_ramp_delay) \ + _get_voltage_sel, _set_voltage_time_sel, _set_ramp_delay, \ + _set_uvp, _set_ovp) \ static const struct regulator_ops name = { \ .enable = regulator_enable_regmap, \ .disable = regulator_disable_regmap, \ @@ -66,6 +67,8 @@ static const struct regulator_ops name = { \ .get_voltage_sel = (_get_voltage_sel), \ .set_voltage_time_sel = (_set_voltage_time_sel), \ .set_ramp_delay = (_set_ramp_delay), \ + .set_under_voltage_protection = (_set_uvp), \ + .set_over_voltage_protection = (_set_ovp), \ }; \ \ static const struct regulator_ops BD718XX_HWOPNAME(name) = { \ @@ -76,6 +79,8 @@ static const struct regulator_ops BD718XX_HWOPNAME(name) = { \ .get_voltage_sel = (_get_voltage_sel), \ .set_voltage_time_sel = (_set_voltage_time_sel), \ .set_ramp_delay = (_set_ramp_delay), \ + .set_under_voltage_protection = (_set_uvp), \ + .set_over_voltage_protection = (_set_ovp), \ } \ /* @@ -154,17 +159,9 @@ static void voltage_change_done(struct regulator_dev *rdev, unsigned int sel, * exceed it due to the scheduling. */ msleep(1); - /* - * Note for next hacker. The PWRGOOD should not be masked on - * BD71847 so we will just unconditionally enable detection - * when voltage is set. - * If someone want's to disable PWRGOOD he must implement - * caching and restoring the old value here. I am not - * aware of such use-cases so for the sake of the simplicity - * we just always enable PWRGOOD here. - */ - ret = regmap_update_bits(rdev->regmap, BD718XX_REG_MVRFLTMASK2, - *mask, 0); + + ret = regmap_clear_bits(rdev->regmap, BD718XX_REG_MVRFLTMASK2, + *mask); if (ret) dev_err(&rdev->dev, "Failed to re-enable voltage monitoring (%d)\n", @@ -208,12 +205,27 @@ static int voltage_change_prepare(struct regulator_dev *rdev, unsigned int sel, * time configurable. */ if (new > now) { + int tmp; + int prot_bit; int ldo_offset = rdev->desc->id - BD718XX_LDO1; - *mask = BD718XX_LDO1_VRMON80 << ldo_offset; - ret = regmap_update_bits(rdev->regmap, - BD718XX_REG_MVRFLTMASK2, - *mask, *mask); + prot_bit = BD718XX_LDO1_VRMON80 << ldo_offset; + ret = regmap_read(rdev->regmap, BD718XX_REG_MVRFLTMASK2, + &tmp); + if (ret) { + dev_err(&rdev->dev, + "Failed to read voltage monitoring state\n"); + return ret; + } + + if (!(tmp & prot_bit)) { + /* We disable protection if it was enabled... */ + ret = regmap_set_bits(rdev->regmap, + BD718XX_REG_MVRFLTMASK2, + prot_bit); + /* ...and we also want to re-enable it */ + *mask = prot_bit; + } if (ret) { dev_err(&rdev->dev, "Failed to stop voltage monitoring\n"); @@ -267,99 +279,6 @@ static int bd71837_set_voltage_sel_pickable_restricted( } /* - * OPS common for BD71847 and BD71850 - */ -BD718XX_OPS(bd718xx_pickable_range_ldo_ops, - regulator_list_voltage_pickable_linear_range, NULL, - bd718xx_set_voltage_sel_pickable_restricted, - regulator_get_voltage_sel_pickable_regmap, NULL, NULL); - -/* BD71847 and BD71850 LDO 5 is by default OFF at RUN state */ -static const struct regulator_ops bd718xx_ldo5_ops_hwstate = { - .is_enabled = never_enabled_by_hwstate, - .list_voltage = regulator_list_voltage_pickable_linear_range, - .set_voltage_sel = bd718xx_set_voltage_sel_pickable_restricted, - .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, -}; - -BD718XX_OPS(bd718xx_pickable_range_buck_ops, - regulator_list_voltage_pickable_linear_range, NULL, - regulator_set_voltage_sel_pickable_regmap, - regulator_get_voltage_sel_pickable_regmap, - regulator_set_voltage_time_sel, NULL); - -BD718XX_OPS(bd718xx_ldo_regulator_ops, regulator_list_voltage_linear_range, - NULL, bd718xx_set_voltage_sel_restricted, - regulator_get_voltage_sel_regmap, NULL, NULL); - -BD718XX_OPS(bd718xx_ldo_regulator_nolinear_ops, regulator_list_voltage_table, - NULL, bd718xx_set_voltage_sel_restricted, - regulator_get_voltage_sel_regmap, NULL, NULL); - -BD718XX_OPS(bd718xx_buck_regulator_ops, regulator_list_voltage_linear_range, - NULL, regulator_set_voltage_sel_regmap, - regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel, - NULL); - -BD718XX_OPS(bd718xx_buck_regulator_nolinear_ops, regulator_list_voltage_table, - regulator_map_voltage_ascend, regulator_set_voltage_sel_regmap, - regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel, - NULL); - -/* - * OPS for BD71837 - */ -BD718XX_OPS(bd71837_pickable_range_ldo_ops, - regulator_list_voltage_pickable_linear_range, NULL, - bd71837_set_voltage_sel_pickable_restricted, - regulator_get_voltage_sel_pickable_regmap, NULL, NULL); - -BD718XX_OPS(bd71837_pickable_range_buck_ops, - regulator_list_voltage_pickable_linear_range, NULL, - bd71837_set_voltage_sel_pickable_restricted, - regulator_get_voltage_sel_pickable_regmap, - regulator_set_voltage_time_sel, NULL); - -BD718XX_OPS(bd71837_ldo_regulator_ops, regulator_list_voltage_linear_range, - NULL, bd71837_set_voltage_sel_restricted, - regulator_get_voltage_sel_regmap, NULL, NULL); - -BD718XX_OPS(bd71837_ldo_regulator_nolinear_ops, regulator_list_voltage_table, - NULL, bd71837_set_voltage_sel_restricted, - regulator_get_voltage_sel_regmap, NULL, NULL); - -BD718XX_OPS(bd71837_buck_regulator_ops, regulator_list_voltage_linear_range, - NULL, bd71837_set_voltage_sel_restricted, - regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel, - NULL); - -BD718XX_OPS(bd71837_buck_regulator_nolinear_ops, regulator_list_voltage_table, - regulator_map_voltage_ascend, bd71837_set_voltage_sel_restricted, - regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel, - NULL); -/* - * BD71837 bucks 3 and 4 support defining their enable/disable state also - * when buck enable state is under HW state machine control. In that case the - * bit [2] in CTRL register is used to indicate if regulator should be ON. - */ -static const struct regulator_ops bd71837_buck34_ops_hwctrl = { - .is_enabled = bd71837_get_buck34_enable_hwctrl, - .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 = regulator_set_ramp_delay_regmap, -}; - -/* - * OPS for all of the ICs - BD718(37/47/50) - */ -BD718XX_OPS(bd718xx_dvs_buck_regulator_ops, regulator_list_voltage_linear_range, - NULL, regulator_set_voltage_sel_regmap, - regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel, - /* bd718xx_buck1234_set_ramp_delay */ regulator_set_ramp_delay_regmap); - -/* * BD71837 BUCK1/2/3/4 * BD71847 BUCK1/2 * 0.70 to 1.30V (10mV step) @@ -536,6 +455,238 @@ struct bd718xx_regulator_data { int additional_init_amnt; }; +static int bd718x7_xvp_sanity_check(struct regulator_dev *rdev, int lim_uV, + int severity) +{ + /* + * BD71837/47/50 ... (ICs supported by this driver) do not provide + * warnings, only protection + */ + if (severity != REGULATOR_SEVERITY_PROT) { + dev_err(&rdev->dev, + "Unsupported Under Voltage protection level\n"); + return -EINVAL; + } + + /* + * And protection limit is not changeable. It can only be enabled + * or disabled + */ + if (lim_uV) + return -EINVAL; + + return 0; +} + +static int bd718x7_set_ldo_uvp(struct regulator_dev *rdev, int lim_uV, + int severity, bool enable) +{ + int ldo_offset = rdev->desc->id - BD718XX_LDO1; + int prot_bit, ret; + + ret = bd718x7_xvp_sanity_check(rdev, lim_uV, severity); + if (ret) + return ret; + + prot_bit = BD718XX_LDO1_VRMON80 << ldo_offset; + + if (enable) + return regmap_clear_bits(rdev->regmap, BD718XX_REG_MVRFLTMASK2, + prot_bit); + + return regmap_set_bits(rdev->regmap, BD718XX_REG_MVRFLTMASK2, + prot_bit); +} + +static int bd718x7_get_buck_prot_reg(int id, int *reg) +{ + + if (id > BD718XX_BUCK8) { + WARN_ON(id > BD718XX_BUCK8); + return -EINVAL; + } + + if (id > BD718XX_BUCK4) + *reg = BD718XX_REG_MVRFLTMASK0; + else + *reg = BD718XX_REG_MVRFLTMASK1; + + return 0; +} + +static int bd718x7_get_buck_ovp_info(int id, int *reg, int *bit) +{ + int ret; + + ret = bd718x7_get_buck_prot_reg(id, reg); + if (ret) + return ret; + + *bit = BIT((id % 4) * 2 + 1); + + return 0; +} + +static int bd718x7_get_buck_uvp_info(int id, int *reg, int *bit) +{ + int ret; + + ret = bd718x7_get_buck_prot_reg(id, reg); + if (ret) + return ret; + + *bit = BIT((id % 4) * 2); + + return 0; +} + +static int bd718x7_set_buck_uvp(struct regulator_dev *rdev, int lim_uV, + int severity, bool enable) +{ + int bit, reg, ret; + + ret = bd718x7_xvp_sanity_check(rdev, lim_uV, severity); + if (ret) + return ret; + + ret = bd718x7_get_buck_uvp_info(rdev->desc->id, ®, &bit); + if (ret) + return ret; + + if (enable) + return regmap_clear_bits(rdev->regmap, reg, bit); + + return regmap_set_bits(rdev->regmap, reg, bit); + +} + +static int bd718x7_set_buck_ovp(struct regulator_dev *rdev, int lim_uV, + int severity, + bool enable) +{ + int bit, reg, ret; + + ret = bd718x7_xvp_sanity_check(rdev, lim_uV, severity); + if (ret) + return ret; + + ret = bd718x7_get_buck_ovp_info(rdev->desc->id, ®, &bit); + if (ret) + return ret; + + if (enable) + return regmap_clear_bits(rdev->regmap, reg, bit); + + return regmap_set_bits(rdev->regmap, reg, bit); +} + +/* + * OPS common for BD71847 and BD71850 + */ +BD718XX_OPS(bd718xx_pickable_range_ldo_ops, + regulator_list_voltage_pickable_linear_range, NULL, + bd718xx_set_voltage_sel_pickable_restricted, + regulator_get_voltage_sel_pickable_regmap, NULL, NULL, + bd718x7_set_ldo_uvp, NULL); + +/* BD71847 and BD71850 LDO 5 is by default OFF at RUN state */ +static const struct regulator_ops bd718xx_ldo5_ops_hwstate = { + .is_enabled = never_enabled_by_hwstate, + .list_voltage = regulator_list_voltage_pickable_linear_range, + .set_voltage_sel = bd718xx_set_voltage_sel_pickable_restricted, + .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, + .set_under_voltage_protection = bd718x7_set_ldo_uvp, +}; + +BD718XX_OPS(bd718xx_pickable_range_buck_ops, + regulator_list_voltage_pickable_linear_range, NULL, + regulator_set_voltage_sel_pickable_regmap, + regulator_get_voltage_sel_pickable_regmap, + regulator_set_voltage_time_sel, NULL, bd718x7_set_buck_uvp, + bd718x7_set_buck_ovp); + +BD718XX_OPS(bd718xx_ldo_regulator_ops, regulator_list_voltage_linear_range, + NULL, bd718xx_set_voltage_sel_restricted, + regulator_get_voltage_sel_regmap, NULL, NULL, bd718x7_set_ldo_uvp, + NULL); + +BD718XX_OPS(bd718xx_ldo_regulator_nolinear_ops, regulator_list_voltage_table, + NULL, bd718xx_set_voltage_sel_restricted, + regulator_get_voltage_sel_regmap, NULL, NULL, bd718x7_set_ldo_uvp, + NULL); + +BD718XX_OPS(bd718xx_buck_regulator_ops, regulator_list_voltage_linear_range, + NULL, regulator_set_voltage_sel_regmap, + regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel, + NULL, bd718x7_set_buck_uvp, bd718x7_set_buck_ovp); + +BD718XX_OPS(bd718xx_buck_regulator_nolinear_ops, regulator_list_voltage_table, + regulator_map_voltage_ascend, regulator_set_voltage_sel_regmap, + regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel, + NULL, bd718x7_set_buck_uvp, bd718x7_set_buck_ovp); + +/* + * OPS for BD71837 + */ +BD718XX_OPS(bd71837_pickable_range_ldo_ops, + regulator_list_voltage_pickable_linear_range, NULL, + bd71837_set_voltage_sel_pickable_restricted, + regulator_get_voltage_sel_pickable_regmap, NULL, NULL, + bd718x7_set_ldo_uvp, NULL); + +BD718XX_OPS(bd71837_pickable_range_buck_ops, + regulator_list_voltage_pickable_linear_range, NULL, + bd71837_set_voltage_sel_pickable_restricted, + regulator_get_voltage_sel_pickable_regmap, + regulator_set_voltage_time_sel, NULL, bd718x7_set_buck_uvp, + bd718x7_set_buck_ovp); + +BD718XX_OPS(bd71837_ldo_regulator_ops, regulator_list_voltage_linear_range, + NULL, bd71837_set_voltage_sel_restricted, + regulator_get_voltage_sel_regmap, NULL, NULL, bd718x7_set_ldo_uvp, + NULL); + +BD718XX_OPS(bd71837_ldo_regulator_nolinear_ops, regulator_list_voltage_table, + NULL, bd71837_set_voltage_sel_restricted, + regulator_get_voltage_sel_regmap, NULL, NULL, bd718x7_set_ldo_uvp, + NULL); + +BD718XX_OPS(bd71837_buck_regulator_ops, regulator_list_voltage_linear_range, + NULL, bd71837_set_voltage_sel_restricted, + regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel, + NULL, bd718x7_set_buck_uvp, bd718x7_set_buck_ovp); + +BD718XX_OPS(bd71837_buck_regulator_nolinear_ops, regulator_list_voltage_table, + regulator_map_voltage_ascend, bd71837_set_voltage_sel_restricted, + regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel, + NULL, bd718x7_set_buck_uvp, bd718x7_set_buck_ovp); +/* + * BD71837 bucks 3 and 4 support defining their enable/disable state also + * when buck enable state is under HW state machine control. In that case the + * bit [2] in CTRL register is used to indicate if regulator should be ON. + */ +static const struct regulator_ops bd71837_buck34_ops_hwctrl = { + .is_enabled = bd71837_get_buck34_enable_hwctrl, + .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 = regulator_set_ramp_delay_regmap, + .set_under_voltage_protection = bd718x7_set_buck_uvp, + .set_over_voltage_protection = bd718x7_set_buck_ovp, +}; + +/* + * OPS for all of the ICs - BD718(37/47/50) + */ +BD718XX_OPS(bd718xx_dvs_buck_regulator_ops, regulator_list_voltage_linear_range, + NULL, regulator_set_voltage_sel_regmap, + regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel, + regulator_set_ramp_delay_regmap, bd718x7_set_buck_uvp, + bd718x7_set_buck_ovp); + + + /* * There is a HW quirk in BD71837. The shutdown sequence timings for * bucks/LDOs which are controlled via register interface are changed. diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index cf7d5341750e..82f52a2a031a 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -412,6 +412,134 @@ static int da9063_ldo_set_suspend_mode(struct regulator_dev *rdev, return regmap_field_write(regl->suspend_sleep, val); } +static unsigned int da9063_get_overdrive_mask(const struct regulator_desc *desc) +{ + switch (desc->id) { + case DA9063_ID_BCORES_MERGED: + case DA9063_ID_BCORE1: + return DA9063_BCORE1_OD; + case DA9063_ID_BCORE2: + return DA9063_BCORE2_OD; + case DA9063_ID_BPRO: + return DA9063_BPRO_OD; + default: + return 0; + } +} + +static int da9063_buck_set_limit_set_overdrive(struct regulator_dev *rdev, + int min_uA, int max_uA, + unsigned int overdrive_mask) +{ + /* + * When enabling overdrive, do it before changing the current limit to + * ensure sufficient supply throughout the switch. + */ + struct da9063_regulator *regl = rdev_get_drvdata(rdev); + int ret; + unsigned int orig_overdrive; + + ret = regmap_read(regl->hw->regmap, DA9063_REG_CONFIG_H, + &orig_overdrive); + if (ret < 0) + return ret; + orig_overdrive &= overdrive_mask; + + if (orig_overdrive == 0) { + ret = regmap_set_bits(regl->hw->regmap, DA9063_REG_CONFIG_H, + overdrive_mask); + if (ret < 0) + return ret; + } + + ret = regulator_set_current_limit_regmap(rdev, min_uA / 2, max_uA / 2); + if (ret < 0 && orig_overdrive == 0) + /* + * regulator_set_current_limit_regmap may have rejected the + * change because of unusable min_uA and/or max_uA inputs. + * Attempt to restore original overdrive state, ignore failure- + * on-failure. + */ + regmap_clear_bits(regl->hw->regmap, DA9063_REG_CONFIG_H, + overdrive_mask); + + return ret; +} + +static int da9063_buck_set_limit_clear_overdrive(struct regulator_dev *rdev, + int min_uA, int max_uA, + unsigned int overdrive_mask) +{ + /* + * When disabling overdrive, do it after changing the current limit to + * ensure sufficient supply throughout the switch. + */ + struct da9063_regulator *regl = rdev_get_drvdata(rdev); + int ret, orig_limit; + + ret = regmap_read(rdev->regmap, rdev->desc->csel_reg, &orig_limit); + if (ret < 0) + return ret; + + ret = regulator_set_current_limit_regmap(rdev, min_uA, max_uA); + if (ret < 0) + return ret; + + ret = regmap_clear_bits(regl->hw->regmap, DA9063_REG_CONFIG_H, + overdrive_mask); + if (ret < 0) + /* + * Attempt to restore original current limit, ignore failure- + * on-failure. + */ + regmap_write(rdev->regmap, rdev->desc->csel_reg, orig_limit); + + return ret; +} + +static int da9063_buck_set_current_limit(struct regulator_dev *rdev, + int min_uA, int max_uA) +{ + unsigned int overdrive_mask, n_currents; + + overdrive_mask = da9063_get_overdrive_mask(rdev->desc); + if (overdrive_mask) { + n_currents = rdev->desc->n_current_limits; + if (n_currents == 0) + return -EINVAL; + + if (max_uA > rdev->desc->curr_table[n_currents - 1]) + return da9063_buck_set_limit_set_overdrive(rdev, min_uA, + max_uA, + overdrive_mask); + + return da9063_buck_set_limit_clear_overdrive(rdev, min_uA, + max_uA, + overdrive_mask); + } + return regulator_set_current_limit_regmap(rdev, min_uA, max_uA); +} + +static int da9063_buck_get_current_limit(struct regulator_dev *rdev) +{ + struct da9063_regulator *regl = rdev_get_drvdata(rdev); + int val, ret, limit; + unsigned int mask; + + limit = regulator_get_current_limit_regmap(rdev); + if (limit < 0) + return limit; + mask = da9063_get_overdrive_mask(rdev->desc); + if (mask) { + ret = regmap_read(regl->hw->regmap, DA9063_REG_CONFIG_H, &val); + if (ret < 0) + return ret; + if (val & mask) + limit *= 2; + } + return limit; +} + static const struct regulator_ops da9063_buck_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -419,8 +547,8 @@ static const struct regulator_ops da9063_buck_ops = { .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, .list_voltage = regulator_list_voltage_linear, - .set_current_limit = regulator_set_current_limit_regmap, - .get_current_limit = regulator_get_current_limit_regmap, + .set_current_limit = da9063_buck_set_current_limit, + .get_current_limit = da9063_buck_get_current_limit, .set_mode = da9063_buck_set_mode, .get_mode = da9063_buck_get_mode, .get_status = da9063_buck_get_status, diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c index 8b70bfe88019..a45c1e1ac7ef 100644 --- a/drivers/regulator/dbx500-prcmu.c +++ b/drivers/regulator/dbx500-prcmu.c @@ -117,11 +117,11 @@ ux500_regulator_debug_init(struct platform_device *pdev, rdebug.dir = debugfs_create_dir("ux500-regulator", NULL); /* create "status" file */ - debugfs_create_file("status", S_IRUGO, rdebug.dir, &pdev->dev, + debugfs_create_file("status", 0444, rdebug.dir, &pdev->dev, &ux500_regulator_status_fops); /* create "power-state-count" file */ - debugfs_create_file("power-state-count", S_IRUGO, rdebug.dir, + debugfs_create_file("power-state-count", 0444, rdebug.dir, &pdev->dev, &ux500_regulator_power_state_cnt_fops); rdebug.regulator_array = regulator_info; diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c index a8de0aa88bad..9113233f41cd 100644 --- a/drivers/regulator/devres.c +++ b/drivers/regulator/devres.c @@ -205,35 +205,6 @@ struct regulator_dev *devm_regulator_register(struct device *dev, } EXPORT_SYMBOL_GPL(devm_regulator_register); -static int devm_rdev_match(struct device *dev, void *res, void *data) -{ - struct regulator_dev **r = res; - if (!r || !*r) { - WARN_ON(!r || !*r); - return 0; - } - return *r == data; -} - -/** - * devm_regulator_unregister - Resource managed regulator_unregister() - * @dev: device to supply - * @rdev: regulator to free - * - * Unregister a regulator registered with devm_regulator_register(). - * Normally this function will not need to be called and the resource - * management code will ensure that the resource is freed. - */ -void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev) -{ - int rc; - - rc = devres_release(dev, devm_rdev_release, devm_rdev_match, rdev); - if (rc != 0) - WARN_ON(rc); -} -EXPORT_SYMBOL_GPL(devm_regulator_unregister); - struct regulator_supply_alias_match { struct device *dev; const char *id; @@ -296,19 +267,8 @@ int devm_regulator_register_supply_alias(struct device *dev, const char *id, } EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias); -/** - * devm_regulator_unregister_supply_alias - Resource managed - * regulator_unregister_supply_alias() - * - * @dev: device to supply - * @id: supply name or regulator ID - * - * Unregister an alias registered with - * devm_regulator_register_supply_alias(). Normally this function - * will not need to be called and the resource management code - * will ensure that the resource is freed. - */ -void devm_regulator_unregister_supply_alias(struct device *dev, const char *id) +static void devm_regulator_unregister_supply_alias(struct device *dev, + const char *id) { struct regulator_supply_alias_match match; int rc; @@ -321,7 +281,6 @@ void devm_regulator_unregister_supply_alias(struct device *dev, const char *id) if (rc != 0) WARN_ON(rc); } -EXPORT_SYMBOL_GPL(devm_regulator_unregister_supply_alias); /** * devm_regulator_bulk_register_supply_alias - Managed register @@ -373,30 +332,6 @@ err: } EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias); -/** - * devm_regulator_bulk_unregister_supply_alias - Managed unregister - * multiple aliases - * - * @dev: device to supply - * @id: list of supply names or regulator IDs - * @num_id: number of aliases to unregister - * - * Unregister aliases registered with - * devm_regulator_bulk_register_supply_alias(). Normally this function - * will not need to be called and the resource management code - * will ensure that the resource is freed. - */ -void devm_regulator_bulk_unregister_supply_alias(struct device *dev, - const char *const *id, - int num_id) -{ - int i; - - for (i = 0; i < num_id; ++i) - devm_regulator_unregister_supply_alias(dev, id[i]); -} -EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias); - struct regulator_notifier_match { struct regulator *regulator; struct notifier_block *nb; diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 39284610a536..599ad201dca7 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -287,8 +287,9 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) drvdata->dev = devm_regulator_register(&pdev->dev, &drvdata->desc, &cfg); if (IS_ERR(drvdata->dev)) { - ret = PTR_ERR(drvdata->dev); - dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); + ret = dev_err_probe(&pdev->dev, PTR_ERR(drvdata->dev), + "Failed to register regulator: %ld\n", + PTR_ERR(drvdata->dev)); return ret; } diff --git a/drivers/regulator/hi6421v600-regulator.c b/drivers/regulator/hi6421v600-regulator.c index 845bc3b4026d..662d87ae61cb 100644 --- a/drivers/regulator/hi6421v600-regulator.c +++ b/drivers/regulator/hi6421v600-regulator.c @@ -4,7 +4,7 @@ // // Copyright (c) 2013 Linaro Ltd. // Copyright (c) 2011 HiSilicon Ltd. -// Copyright (c) 2020-2021 Huawei Technologies Co., Ltd +// Copyright (c) 2020-2021 Huawei Technologies Co., Ltd. // // Guodong Xu <guodong.xu@linaro.org> @@ -27,34 +27,34 @@ struct hi6421_spmi_reg_info { u32 eco_uA; }; -static const unsigned int ldo3_voltages[] = { +static const unsigned int range_1v5_to_2v0[] = { 1500000, 1550000, 1600000, 1650000, 1700000, 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000, 1900000, 1925000, 1950000, 2000000 }; -static const unsigned int ldo4_voltages[] = { +static const unsigned int range_1v725_to_1v9[] = { 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000, 1900000 }; -static const unsigned int ldo9_voltages[] = { +static const unsigned int range_1v75_to_3v3[] = { 1750000, 1800000, 1825000, 2800000, 2850000, 2950000, 3000000, 3300000 }; -static const unsigned int ldo15_voltages[] = { +static const unsigned int range_1v8_to_3v0[] = { 1800000, 1850000, 2400000, 2600000, 2700000, 2850000, 2950000, 3000000 }; -static const unsigned int ldo17_voltages[] = { +static const unsigned int range_2v5_to_3v3[] = { 2500000, 2600000, 2700000, 2800000, 3000000, 3100000, 3200000, 3300000 }; -static const unsigned int ldo34_voltages[] = { +static const unsigned int range_2v6_to_3v3[] = { 2600000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000 }; @@ -73,14 +73,14 @@ static const unsigned int ldo34_voltages[] = { */ #define HI6421V600_LDO(_id, vtable, ereg, emask, vreg, \ odelay, etime, ecomask, ecoamp) \ - [HI6421V600_##_id] = { \ + [hi6421v600_##_id] = { \ .desc = { \ .name = #_id, \ .of_match = of_match_ptr(#_id), \ .regulators_node = of_match_ptr("regulators"), \ .ops = &hi6421_spmi_ldo_rops, \ .type = REGULATOR_VOLTAGE, \ - .id = HI6421V600_##_id, \ + .id = hi6421v600_##_id, \ .owner = THIS_MODULE, \ .volt_table = vtable, \ .n_voltages = ARRAY_SIZE(vtable), \ @@ -185,46 +185,46 @@ static const struct regulator_ops hi6421_spmi_ldo_rops = { /* HI6421v600 regulators with known registers */ enum hi6421_spmi_regulator_id { - HI6421V600_LDO3, - HI6421V600_LDO4, - HI6421V600_LDO9, - HI6421V600_LDO15, - HI6421V600_LDO16, - HI6421V600_LDO17, - HI6421V600_LDO33, - HI6421V600_LDO34, + hi6421v600_ldo3, + hi6421v600_ldo4, + hi6421v600_ldo9, + hi6421v600_ldo15, + hi6421v600_ldo16, + hi6421v600_ldo17, + hi6421v600_ldo33, + hi6421v600_ldo34, }; static struct hi6421_spmi_reg_info regulator_info[] = { - HI6421V600_LDO(LDO3, ldo3_voltages, + HI6421V600_LDO(ldo3, range_1v5_to_2v0, 0x16, 0x01, 0x51, 20000, 120, 0, 0), - HI6421V600_LDO(LDO4, ldo4_voltages, + HI6421V600_LDO(ldo4, range_1v725_to_1v9, 0x17, 0x01, 0x52, 20000, 120, 0x10, 10000), - HI6421V600_LDO(LDO9, ldo9_voltages, + HI6421V600_LDO(ldo9, range_1v75_to_3v3, 0x1c, 0x01, 0x57, 20000, 360, 0x10, 10000), - HI6421V600_LDO(LDO15, ldo15_voltages, + HI6421V600_LDO(ldo15, range_1v8_to_3v0, 0x21, 0x01, 0x5c, 20000, 360, 0x10, 10000), - HI6421V600_LDO(LDO16, ldo15_voltages, + HI6421V600_LDO(ldo16, range_1v8_to_3v0, 0x22, 0x01, 0x5d, 20000, 360, 0x10, 10000), - HI6421V600_LDO(LDO17, ldo17_voltages, + HI6421V600_LDO(ldo17, range_2v5_to_3v3, 0x23, 0x01, 0x5e, 20000, 120, 0x10, 10000), - HI6421V600_LDO(LDO33, ldo17_voltages, + HI6421V600_LDO(ldo33, range_2v5_to_3v3, 0x32, 0x01, 0x6d, 20000, 120, 0, 0), - HI6421V600_LDO(LDO34, ldo34_voltages, + HI6421V600_LDO(ldo34, range_2v6_to_3v3, 0x33, 0x01, 0x6e, 20000, 120, 0, 0), diff --git a/drivers/regulator/irq_helpers.c b/drivers/regulator/irq_helpers.c index fabe2e53093e..522764435575 100644 --- a/drivers/regulator/irq_helpers.c +++ b/drivers/regulator/irq_helpers.c @@ -184,7 +184,7 @@ static irqreturn_t regulator_notifier_isr(int irq, void *data) * If retry_count exceeds the given safety limit we call IC specific die * handler which can try disabling regulator(s). * - * If no die handler is given we will just bug() as a last resort. + * If no die handler is given we will just power-off as a last resort. * * We could try disabling all associated rdevs - but we might shoot * ourselves in the head and leave the problematic regulator enabled. So diff --git a/drivers/regulator/mt6358-regulator.c b/drivers/regulator/mt6358-regulator.c index 0d35be4e0e5a..eb8027813b99 100644 --- a/drivers/regulator/mt6358-regulator.c +++ b/drivers/regulator/mt6358-regulator.c @@ -28,18 +28,15 @@ struct mt6358_regulator_info { u32 qi; const u32 *index_table; unsigned int n_table; - u32 vsel_shift; u32 da_vsel_reg; u32 da_vsel_mask; - u32 da_vsel_shift; u32 modeset_reg; u32 modeset_mask; - u32 modeset_shift; }; #define MT6358_BUCK(match, vreg, min, max, step, \ volt_ranges, vosel_mask, _da_vsel_reg, _da_vsel_mask, \ - _da_vsel_shift, _modeset_reg, _modeset_shift) \ + _modeset_reg, _modeset_shift) \ [MT6358_ID_##vreg] = { \ .desc = { \ .name = #vreg, \ @@ -61,15 +58,13 @@ struct mt6358_regulator_info { .qi = BIT(0), \ .da_vsel_reg = _da_vsel_reg, \ .da_vsel_mask = _da_vsel_mask, \ - .da_vsel_shift = _da_vsel_shift, \ .modeset_reg = _modeset_reg, \ .modeset_mask = BIT(_modeset_shift), \ - .modeset_shift = _modeset_shift \ } #define MT6358_LDO(match, vreg, ldo_volt_table, \ ldo_index_table, enreg, enbit, vosel, \ - vosel_mask, vosel_shift) \ + vosel_mask) \ [MT6358_ID_##vreg] = { \ .desc = { \ .name = #vreg, \ @@ -89,12 +84,11 @@ struct mt6358_regulator_info { .qi = BIT(15), \ .index_table = ldo_index_table, \ .n_table = ARRAY_SIZE(ldo_index_table), \ - .vsel_shift = vosel_shift, \ } #define MT6358_LDO1(match, vreg, min, max, step, \ volt_ranges, _da_vsel_reg, _da_vsel_mask, \ - _da_vsel_shift, vosel, vosel_mask) \ + vosel, vosel_mask) \ [MT6358_ID_##vreg] = { \ .desc = { \ .name = #vreg, \ @@ -113,7 +107,6 @@ struct mt6358_regulator_info { }, \ .da_vsel_reg = _da_vsel_reg, \ .da_vsel_mask = _da_vsel_mask, \ - .da_vsel_shift = _da_vsel_shift, \ .status_reg = MT6358_LDO_##vreg##_DBG1, \ .qi = BIT(0), \ } @@ -260,9 +253,9 @@ static int mt6358_set_voltage_sel(struct regulator_dev *rdev, pvol = info->index_table; idx = pvol[selector]; + idx <<= ffs(info->desc.vsel_mask) - 1; ret = regmap_update_bits(rdev->regmap, info->desc.vsel_reg, - info->desc.vsel_mask, - idx << info->vsel_shift); + info->desc.vsel_mask, idx); return ret; } @@ -282,7 +275,8 @@ static int mt6358_get_voltage_sel(struct regulator_dev *rdev) return ret; } - selector = (selector & info->desc.vsel_mask) >> info->vsel_shift; + selector = (selector & info->desc.vsel_mask) >> + (ffs(info->desc.vsel_mask) - 1); pvol = info->index_table; for (idx = 0; idx < info->desc.n_voltages; idx++) { if (pvol[idx] == selector) @@ -305,7 +299,7 @@ static int mt6358_get_buck_voltage_sel(struct regulator_dev *rdev) return ret; } - ret = (regval >> info->da_vsel_shift) & info->da_vsel_mask; + ret = (regval & info->da_vsel_mask) >> (ffs(info->da_vsel_mask) - 1); return ret; } @@ -342,11 +336,10 @@ static int mt6358_regulator_set_mode(struct regulator_dev *rdev, return -EINVAL; } - dev_dbg(&rdev->dev, "mt6358 buck set_mode %#x, %#x, %#x, %#x\n", - info->modeset_reg, info->modeset_mask, - info->modeset_shift, val); + dev_dbg(&rdev->dev, "mt6358 buck set_mode %#x, %#x, %#x\n", + info->modeset_reg, info->modeset_mask, val); - val <<= info->modeset_shift; + val <<= ffs(info->modeset_mask) - 1; return regmap_update_bits(rdev->regmap, info->modeset_reg, info->modeset_mask, val); @@ -364,7 +357,7 @@ static unsigned int mt6358_regulator_get_mode(struct regulator_dev *rdev) return ret; } - switch ((regval & info->modeset_mask) >> info->modeset_shift) { + switch ((regval & info->modeset_mask) >> (ffs(info->modeset_mask) - 1)) { case MT6358_BUCK_MODE_AUTO: return REGULATOR_MODE_NORMAL; case MT6358_BUCK_MODE_FORCE_PWM: @@ -412,30 +405,30 @@ static const struct regulator_ops mt6358_volt_fixed_ops = { static struct mt6358_regulator_info mt6358_regulators[] = { MT6358_BUCK("buck_vdram1", VDRAM1, 500000, 2087500, 12500, buck_volt_range2, 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f, - 0, MT6358_VDRAM1_ANA_CON0, 8), + MT6358_VDRAM1_ANA_CON0, 8), MT6358_BUCK("buck_vcore", VCORE, 500000, 1293750, 6250, buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f, - 0, MT6358_VCORE_VGPU_ANA_CON0, 1), + MT6358_VCORE_VGPU_ANA_CON0, 1), MT6358_BUCK("buck_vpa", VPA, 500000, 3650000, 50000, - buck_volt_range3, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, 0, + buck_volt_range3, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, MT6358_VPA_ANA_CON0, 3), MT6358_BUCK("buck_vproc11", VPROC11, 500000, 1293750, 6250, buck_volt_range1, 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f, - 0, MT6358_VPROC_ANA_CON0, 1), + MT6358_VPROC_ANA_CON0, 1), MT6358_BUCK("buck_vproc12", VPROC12, 500000, 1293750, 6250, buck_volt_range1, 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f, - 0, MT6358_VPROC_ANA_CON0, 2), + MT6358_VPROC_ANA_CON0, 2), MT6358_BUCK("buck_vgpu", VGPU, 500000, 1293750, 6250, - buck_volt_range1, 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f, 0, + buck_volt_range1, 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f, MT6358_VCORE_VGPU_ANA_CON0, 2), MT6358_BUCK("buck_vs2", VS2, 500000, 2087500, 12500, - buck_volt_range2, 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f, 0, + buck_volt_range2, 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f, MT6358_VS2_ANA_CON0, 8), MT6358_BUCK("buck_vmodem", VMODEM, 500000, 1293750, 6250, buck_volt_range1, 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f, - 0, MT6358_VMODEM_ANA_CON0, 8), + MT6358_VMODEM_ANA_CON0, 8), MT6358_BUCK("buck_vs1", VS1, 1000000, 2587500, 12500, - buck_volt_range4, 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f, 0, + buck_volt_range4, 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f, MT6358_VS1_ANA_CON0, 8), MT6358_REG_FIXED("ldo_vrf12", VRF12, MT6358_LDO_VRF12_CON0, 0, 1200000), @@ -457,49 +450,49 @@ static struct mt6358_regulator_info mt6358_regulators[] = { MT6358_REG_FIXED("ldo_vaud28", VAUD28, MT6358_LDO_VAUD28_CON0, 0, 2800000), MT6358_LDO("ldo_vdram2", VDRAM2, vdram2_voltages, vdram2_idx, - MT6358_LDO_VDRAM2_CON0, 0, MT6358_LDO_VDRAM2_ELR0, 0xf, 0), + MT6358_LDO_VDRAM2_CON0, 0, MT6358_LDO_VDRAM2_ELR0, 0xf), MT6358_LDO("ldo_vsim1", VSIM1, vsim_voltages, vsim_idx, - MT6358_LDO_VSIM1_CON0, 0, MT6358_VSIM1_ANA_CON0, 0xf00, 8), + MT6358_LDO_VSIM1_CON0, 0, MT6358_VSIM1_ANA_CON0, 0xf00), MT6358_LDO("ldo_vibr", VIBR, vibr_voltages, vibr_idx, - MT6358_LDO_VIBR_CON0, 0, MT6358_VIBR_ANA_CON0, 0xf00, 8), + MT6358_LDO_VIBR_CON0, 0, MT6358_VIBR_ANA_CON0, 0xf00), MT6358_LDO("ldo_vusb", VUSB, vusb_voltages, vusb_idx, - MT6358_LDO_VUSB_CON0_0, 0, MT6358_VUSB_ANA_CON0, 0x700, 8), + MT6358_LDO_VUSB_CON0_0, 0, MT6358_VUSB_ANA_CON0, 0x700), MT6358_LDO("ldo_vcamd", VCAMD, vcamd_voltages, vcamd_idx, - MT6358_LDO_VCAMD_CON0, 0, MT6358_VCAMD_ANA_CON0, 0xf00, 8), + MT6358_LDO_VCAMD_CON0, 0, MT6358_VCAMD_ANA_CON0, 0xf00), MT6358_LDO("ldo_vefuse", VEFUSE, vefuse_voltages, vefuse_idx, - MT6358_LDO_VEFUSE_CON0, 0, MT6358_VEFUSE_ANA_CON0, 0xf00, 8), + MT6358_LDO_VEFUSE_CON0, 0, MT6358_VEFUSE_ANA_CON0, 0xf00), MT6358_LDO("ldo_vmch", VMCH, vmch_vemc_voltages, vmch_vemc_idx, - MT6358_LDO_VMCH_CON0, 0, MT6358_VMCH_ANA_CON0, 0x700, 8), + MT6358_LDO_VMCH_CON0, 0, MT6358_VMCH_ANA_CON0, 0x700), MT6358_LDO("ldo_vcama1", VCAMA1, vcama_voltages, vcama_idx, - MT6358_LDO_VCAMA1_CON0, 0, MT6358_VCAMA1_ANA_CON0, 0xf00, 8), + MT6358_LDO_VCAMA1_CON0, 0, MT6358_VCAMA1_ANA_CON0, 0xf00), MT6358_LDO("ldo_vemc", VEMC, vmch_vemc_voltages, vmch_vemc_idx, - MT6358_LDO_VEMC_CON0, 0, MT6358_VEMC_ANA_CON0, 0x700, 8), + MT6358_LDO_VEMC_CON0, 0, MT6358_VEMC_ANA_CON0, 0x700), MT6358_LDO("ldo_vcn33_bt", VCN33_BT, vcn33_bt_wifi_voltages, vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_0, - 0, MT6358_VCN33_ANA_CON0, 0x300, 8), + 0, MT6358_VCN33_ANA_CON0, 0x300), MT6358_LDO("ldo_vcn33_wifi", VCN33_WIFI, vcn33_bt_wifi_voltages, vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_1, - 0, MT6358_VCN33_ANA_CON0, 0x300, 8), + 0, MT6358_VCN33_ANA_CON0, 0x300), MT6358_LDO("ldo_vcama2", VCAMA2, vcama_voltages, vcama_idx, - MT6358_LDO_VCAMA2_CON0, 0, MT6358_VCAMA2_ANA_CON0, 0xf00, 8), + MT6358_LDO_VCAMA2_CON0, 0, MT6358_VCAMA2_ANA_CON0, 0xf00), MT6358_LDO("ldo_vmc", VMC, vmc_voltages, vmc_idx, - MT6358_LDO_VMC_CON0, 0, MT6358_VMC_ANA_CON0, 0xf00, 8), + MT6358_LDO_VMC_CON0, 0, MT6358_VMC_ANA_CON0, 0xf00), MT6358_LDO("ldo_vldo28", VLDO28, vldo28_voltages, vldo28_idx, MT6358_LDO_VLDO28_CON0_0, 0, - MT6358_VLDO28_ANA_CON0, 0x300, 8), + MT6358_VLDO28_ANA_CON0, 0x300), MT6358_LDO("ldo_vsim2", VSIM2, vsim_voltages, vsim_idx, - MT6358_LDO_VSIM2_CON0, 0, MT6358_VSIM2_ANA_CON0, 0xf00, 8), + MT6358_LDO_VSIM2_CON0, 0, MT6358_VSIM2_ANA_CON0, 0xf00), MT6358_LDO1("ldo_vsram_proc11", VSRAM_PROC11, 500000, 1293750, 6250, - buck_volt_range1, MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f, 8, + buck_volt_range1, MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON0, 0x7f), MT6358_LDO1("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250, - buck_volt_range1, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f, 8, + buck_volt_range1, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON2, 0x7f), MT6358_LDO1("ldo_vsram_gpu", VSRAM_GPU, 500000, 1293750, 6250, - buck_volt_range1, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f, 8, + buck_volt_range1, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON3, 0x7f), MT6358_LDO1("ldo_vsram_proc12", VSRAM_PROC12, 500000, 1293750, 6250, - buck_volt_range1, MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f, 8, + buck_volt_range1, MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON1, 0x7f), }; diff --git a/drivers/regulator/mt6359-regulator.c b/drivers/regulator/mt6359-regulator.c index 7ce0bd377a08..de3b0462832c 100644 --- a/drivers/regulator/mt6359-regulator.c +++ b/drivers/regulator/mt6359-regulator.c @@ -27,7 +27,6 @@ * @qi: Mask for query enable signal status of regulators. * @modeset_reg: for operating AUTO/PWM mode register. * @modeset_mask: MASK for operating modeset register. - * @modeset_shift: SHIFT for operating modeset register. */ struct mt6359_regulator_info { struct regulator_desc desc; @@ -35,10 +34,8 @@ struct mt6359_regulator_info { u32 qi; u32 modeset_reg; u32 modeset_mask; - u32 modeset_shift; u32 lp_mode_reg; u32 lp_mode_mask; - u32 lp_mode_shift; }; #define MT6359_BUCK(match, _name, min, max, step, \ @@ -68,10 +65,8 @@ struct mt6359_regulator_info { .qi = BIT(0), \ .lp_mode_reg = _lp_mode_reg, \ .lp_mode_mask = BIT(_lp_mode_shift), \ - .lp_mode_shift = _lp_mode_shift, \ .modeset_reg = _modeset_reg, \ .modeset_mask = BIT(_modeset_shift), \ - .modeset_shift = _modeset_shift \ } #define MT6359_LDO_LINEAR(match, _name, min, max, step, \ @@ -282,8 +277,10 @@ static unsigned int mt6359_regulator_get_mode(struct regulator_dev *rdev) return ret; } - if ((regval & info->modeset_mask) >> info->modeset_shift == - MT6359_BUCK_MODE_FORCE_PWM) + regval &= info->modeset_mask; + regval >>= ffs(info->modeset_mask) - 1; + + if (regval == MT6359_BUCK_MODE_FORCE_PWM) return REGULATOR_MODE_FAST; ret = regmap_read(rdev->regmap, info->lp_mode_reg, ®val); @@ -310,7 +307,7 @@ static int mt6359_regulator_set_mode(struct regulator_dev *rdev, switch (mode) { case REGULATOR_MODE_FAST: val = MT6359_BUCK_MODE_FORCE_PWM; - val <<= info->modeset_shift; + val <<= ffs(info->modeset_mask) - 1; ret = regmap_update_bits(rdev->regmap, info->modeset_reg, info->modeset_mask, @@ -319,14 +316,14 @@ static int mt6359_regulator_set_mode(struct regulator_dev *rdev, case REGULATOR_MODE_NORMAL: if (curr_mode == REGULATOR_MODE_FAST) { val = MT6359_BUCK_MODE_AUTO; - val <<= info->modeset_shift; + val <<= ffs(info->modeset_mask) - 1; ret = regmap_update_bits(rdev->regmap, info->modeset_reg, info->modeset_mask, val); } else if (curr_mode == REGULATOR_MODE_IDLE) { val = MT6359_BUCK_MODE_NORMAL; - val <<= info->lp_mode_shift; + val <<= ffs(info->lp_mode_mask) - 1; ret = regmap_update_bits(rdev->regmap, info->lp_mode_reg, info->lp_mode_mask, @@ -336,7 +333,7 @@ static int mt6359_regulator_set_mode(struct regulator_dev *rdev, break; case REGULATOR_MODE_IDLE: val = MT6359_BUCK_MODE_LP >> 1; - val <<= info->lp_mode_shift; + val <<= ffs(info->lp_mode_mask) - 1; ret = regmap_update_bits(rdev->regmap, info->lp_mode_reg, info->lp_mode_mask, diff --git a/drivers/regulator/mt6397-regulator.c b/drivers/regulator/mt6397-regulator.c index 0a30df5e414f..b9bf7ade1f8a 100644 --- a/drivers/regulator/mt6397-regulator.c +++ b/drivers/regulator/mt6397-regulator.c @@ -32,7 +32,6 @@ struct mt6397_regulator_info { u32 vselctrl_mask; u32 modeset_reg; u32 modeset_mask; - u32 modeset_shift; }; #define MT6397_BUCK(match, vreg, min, max, step, volt_ranges, enreg, \ @@ -61,7 +60,6 @@ struct mt6397_regulator_info { .vselctrl_mask = BIT(1), \ .modeset_reg = _modeset_reg, \ .modeset_mask = BIT(_modeset_shift), \ - .modeset_shift = _modeset_shift \ } #define MT6397_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel, \ @@ -175,11 +173,11 @@ static int mt6397_regulator_set_mode(struct regulator_dev *rdev, goto err_mode; } - dev_dbg(&rdev->dev, "mt6397 buck set_mode %#x, %#x, %#x, %#x\n", - info->modeset_reg, info->modeset_mask, - info->modeset_shift, val); + dev_dbg(&rdev->dev, "mt6397 buck set_mode %#x, %#x, %#x\n", + info->modeset_reg, info->modeset_mask, val); + + val <<= ffs(info->modeset_mask) - 1; - val <<= info->modeset_shift; ret = regmap_update_bits(rdev->regmap, info->modeset_reg, info->modeset_mask, val); err_mode: @@ -204,7 +202,10 @@ static unsigned int mt6397_regulator_get_mode(struct regulator_dev *rdev) return ret; } - switch ((regval & info->modeset_mask) >> info->modeset_shift) { + regval &= info->modeset_mask; + regval >>= ffs(info->modeset_mask) - 1; + + switch (regval) { case MT6397_BUCK_MODE_AUTO: return REGULATOR_MODE_NORMAL; case MT6397_BUCK_MODE_FORCE_PWM: diff --git a/drivers/regulator/rt5033-regulator.c b/drivers/regulator/rt5033-regulator.c index 0e7311629165..da4cf5a6acc2 100644 --- a/drivers/regulator/rt5033-regulator.c +++ b/drivers/regulator/rt5033-regulator.c @@ -13,6 +13,16 @@ #include <linux/mfd/rt5033-private.h> #include <linux/regulator/of_regulator.h> +static const struct linear_range rt5033_buck_ranges[] = { + REGULATOR_LINEAR_RANGE(1000000, 0, 20, 100000), + REGULATOR_LINEAR_RANGE(3000000, 21, 31, 0), +}; + +static const struct linear_range rt5033_ldo_ranges[] = { + REGULATOR_LINEAR_RANGE(1200000, 0, 18, 100000), + REGULATOR_LINEAR_RANGE(3000000, 19, 31, 0), +}; + static const struct regulator_ops rt5033_safe_ldo_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, @@ -24,8 +34,7 @@ static const struct regulator_ops rt5033_buck_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .list_voltage = regulator_list_voltage_linear, - .map_voltage = regulator_map_voltage_linear, + .list_voltage = regulator_list_voltage_linear_range, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, }; @@ -40,8 +49,8 @@ static const struct regulator_desc rt5033_supported_regulators[] = { .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .n_voltages = RT5033_REGULATOR_BUCK_VOLTAGE_STEP_NUM, - .min_uV = RT5033_REGULATOR_BUCK_VOLTAGE_MIN, - .uV_step = RT5033_REGULATOR_BUCK_VOLTAGE_STEP, + .linear_ranges = rt5033_buck_ranges, + .n_linear_ranges = ARRAY_SIZE(rt5033_buck_ranges), .enable_reg = RT5033_REG_CTRL, .enable_mask = RT5033_CTRL_EN_BUCK_MASK, .vsel_reg = RT5033_REG_BUCK_CTRL, @@ -56,8 +65,8 @@ static const struct regulator_desc rt5033_supported_regulators[] = { .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .n_voltages = RT5033_REGULATOR_LDO_VOLTAGE_STEP_NUM, - .min_uV = RT5033_REGULATOR_LDO_VOLTAGE_MIN, - .uV_step = RT5033_REGULATOR_LDO_VOLTAGE_STEP, + .linear_ranges = rt5033_ldo_ranges, + .n_linear_ranges = ARRAY_SIZE(rt5033_ldo_ranges), .enable_reg = RT5033_REG_CTRL, .enable_mask = RT5033_CTRL_EN_LDO_MASK, .vsel_reg = RT5033_REG_LDO_CTRL, diff --git a/drivers/regulator/rt6245-regulator.c b/drivers/regulator/rt6245-regulator.c index d3299a72fd10..cb22a207e9ff 100644 --- a/drivers/regulator/rt6245-regulator.c +++ b/drivers/regulator/rt6245-regulator.c @@ -144,7 +144,7 @@ static int rt6245_init_device_properties(struct device *dev) static int rt6245_reg_write(void *context, unsigned int reg, unsigned int val) { struct i2c_client *i2c = context; - const u8 func_base[] = { 0x6F, 0x73, 0x78, 0x61, 0x7C, 0 }; + static const u8 func_base[] = { 0x6F, 0x73, 0x78, 0x61, 0x7C, 0 }; unsigned int code, bit_count; code = func_base[reg]; diff --git a/drivers/regulator/rtq2134-regulator.c b/drivers/regulator/rtq2134-regulator.c new file mode 100644 index 000000000000..f21e3f8b21f2 --- /dev/null +++ b/drivers/regulator/rtq2134-regulator.c @@ -0,0 +1,373 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <linux/bitops.h> +#include <linux/i2c.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> + +enum { + RTQ2134_IDX_BUCK1 = 0, + RTQ2134_IDX_BUCK2, + RTQ2134_IDX_BUCK3, + RTQ2134_IDX_MAX +}; + +#define RTQ2134_AUTO_MODE 0 +#define RTQ2134_FCCM_MODE 1 + +#define RTQ2134_BUCK_DVS0_CTRL 0 +#define RTQ2134_BUCK_VSEL_CTRL 2 + +#define RTQ2134_REG_IO_CHIPNAME 0x01 +#define RTQ2134_REG_FLT_RECORDTEMP 0x13 +#define RTQ2134_REG_FLT_RECORDBUCK(_id) (0x14 + (_id)) +#define RTQ2134_REG_FLT_BUCKCTRL(_id) (0x37 + (_id)) +#define RTQ2134_REG_BUCK1_CFG0 0x42 +#define RTQ2134_REG_BUCK1_DVS0CFG1 0x48 +#define RTQ2134_REG_BUCK1_DVS0CFG0 0x49 +#define RTQ2134_REG_BUCK1_DVS1CFG1 0x4A +#define RTQ2134_REG_BUCK1_DVS1CFG0 0x4B +#define RTQ2134_REG_BUCK1_DVSCFG 0x52 +#define RTQ2134_REG_BUCK1_RSPCFG 0x54 +#define RTQ2134_REG_BUCK2_CFG0 0x5F +#define RTQ2134_REG_BUCK2_DVS0CFG1 0x62 +#define RTQ2134_REG_BUCK2_DVS0CFG0 0x63 +#define RTQ2134_REG_BUCK2_DVS1CFG1 0x64 +#define RTQ2134_REG_BUCK2_DVS1CFG0 0x65 +#define RTQ2134_REG_BUCK2_DVSCFG 0x6C +#define RTQ2134_REG_BUCK2_RSPCFG 0x6E +#define RTQ2134_REG_BUCK3_CFG0 0x79 +#define RTQ2134_REG_BUCK3_DVS0CFG1 0x7C +#define RTQ2134_REG_BUCK3_DVS0CFG0 0x7D +#define RTQ2134_REG_BUCK3_DVS1CFG1 0x7E +#define RTQ2134_REG_BUCK3_DVS1CFG0 0x7F +#define RTQ2134_REG_BUCK3_DVSCFG 0x86 +#define RTQ2134_REG_BUCK3_RSPCFG 0x88 +#define RTQ2134_REG_BUCK3_SLEWCTRL 0x89 + +#define RTQ2134_VOUT_MAXNUM 256 +#define RTQ2134_VOUT_MASK 0xFF +#define RTQ2134_VOUTEN_MASK BIT(0) +#define RTQ2134_ACTDISCHG_MASK BIT(0) +#define RTQ2134_RSPUP_MASK GENMASK(6, 4) +#define RTQ2134_FCCM_MASK BIT(5) +#define RTQ2134_UVHICCUP_MASK BIT(3) +#define RTQ2134_BUCKDVS_CTRL_MASK GENMASK(1, 0) +#define RTQ2134_CHIPOT_MASK BIT(2) +#define RTQ2134_BUCKOV_MASK BIT(5) +#define RTQ2134_BUCKUV_MASK BIT(4) + +struct rtq2134_regulator_desc { + struct regulator_desc desc; + /* Extension for proprietary register and mask */ + unsigned int mode_reg; + unsigned int mode_mask; + unsigned int suspend_enable_reg; + unsigned int suspend_enable_mask; + unsigned int suspend_vsel_reg; + unsigned int suspend_vsel_mask; + unsigned int suspend_mode_reg; + unsigned int suspend_mode_mask; + unsigned int dvs_ctrl_reg; +}; + +static int rtq2134_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + struct rtq2134_regulator_desc *desc = + (struct rtq2134_regulator_desc *)rdev->desc; + unsigned int val; + + if (mode == REGULATOR_MODE_NORMAL) + val = RTQ2134_AUTO_MODE; + else if (mode == REGULATOR_MODE_FAST) + val = RTQ2134_FCCM_MODE; + else + return -EINVAL; + + val <<= ffs(desc->mode_mask) - 1; + return regmap_update_bits(rdev->regmap, desc->mode_reg, desc->mode_mask, + val); +} + +static unsigned int rtq2134_buck_get_mode(struct regulator_dev *rdev) +{ + struct rtq2134_regulator_desc *desc = + (struct rtq2134_regulator_desc *)rdev->desc; + unsigned int mode; + int ret; + + ret = regmap_read(rdev->regmap, desc->mode_reg, &mode); + if (ret) + return ret; + + if (mode & desc->mode_mask) + return REGULATOR_MODE_FAST; + return REGULATOR_MODE_NORMAL; +} + +static int rtq2134_buck_set_suspend_voltage(struct regulator_dev *rdev, int uV) +{ + struct rtq2134_regulator_desc *desc = + (struct rtq2134_regulator_desc *)rdev->desc; + int sel; + + sel = regulator_map_voltage_linear_range(rdev, uV, uV); + if (sel < 0) + return sel; + + sel <<= ffs(desc->suspend_vsel_mask) - 1; + + return regmap_update_bits(rdev->regmap, desc->suspend_vsel_reg, + desc->suspend_vsel_mask, sel); +} + +static int rtq2134_buck_set_suspend_enable(struct regulator_dev *rdev) +{ + struct rtq2134_regulator_desc *desc = + (struct rtq2134_regulator_desc *)rdev->desc; + unsigned int val = desc->suspend_enable_mask; + + return regmap_update_bits(rdev->regmap, desc->suspend_enable_reg, + desc->suspend_enable_mask, val); +} + +static int rtq2134_buck_set_suspend_disable(struct regulator_dev *rdev) +{ + struct rtq2134_regulator_desc *desc = + (struct rtq2134_regulator_desc *)rdev->desc; + + return regmap_update_bits(rdev->regmap, desc->suspend_enable_reg, + desc->suspend_enable_mask, 0); +} + +static int rtq2134_buck_set_suspend_mode(struct regulator_dev *rdev, + unsigned int mode) +{ + struct rtq2134_regulator_desc *desc = + (struct rtq2134_regulator_desc *)rdev->desc; + unsigned int val; + + if (mode == REGULATOR_MODE_NORMAL) + val = RTQ2134_AUTO_MODE; + else if (mode == REGULATOR_MODE_FAST) + val = RTQ2134_FCCM_MODE; + else + return -EINVAL; + + val <<= ffs(desc->suspend_mode_mask) - 1; + return regmap_update_bits(rdev->regmap, desc->suspend_mode_reg, + desc->suspend_mode_mask, val); +} + +static int rtq2134_buck_get_error_flags(struct regulator_dev *rdev, + unsigned int *flags) +{ + int rid = rdev_get_id(rdev); + unsigned int chip_error, buck_error, events = 0; + int ret; + + ret = regmap_read(rdev->regmap, RTQ2134_REG_FLT_RECORDTEMP, + &chip_error); + if (ret) { + dev_err(&rdev->dev, "Failed to get chip error flag\n"); + return ret; + } + + ret = regmap_read(rdev->regmap, RTQ2134_REG_FLT_RECORDBUCK(rid), + &buck_error); + if (ret) { + dev_err(&rdev->dev, "Failed to get buck error flag\n"); + return ret; + } + + if (chip_error & RTQ2134_CHIPOT_MASK) + events |= REGULATOR_ERROR_OVER_TEMP; + + if (buck_error & RTQ2134_BUCKUV_MASK) + events |= REGULATOR_ERROR_UNDER_VOLTAGE; + + if (buck_error & RTQ2134_BUCKOV_MASK) + events |= REGULATOR_ERROR_REGULATION_OUT; + + *flags = events; + return 0; +} + +static const struct regulator_ops rtq2134_buck_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_active_discharge = regulator_set_active_discharge_regmap, + .set_ramp_delay = regulator_set_ramp_delay_regmap, + .set_mode = rtq2134_buck_set_mode, + .get_mode = rtq2134_buck_get_mode, + .set_suspend_voltage = rtq2134_buck_set_suspend_voltage, + .set_suspend_enable = rtq2134_buck_set_suspend_enable, + .set_suspend_disable = rtq2134_buck_set_suspend_disable, + .set_suspend_mode = rtq2134_buck_set_suspend_mode, + .get_error_flags = rtq2134_buck_get_error_flags, +}; + +static const struct linear_range rtq2134_buck_vout_ranges[] = { + REGULATOR_LINEAR_RANGE(300000, 0, 200, 5000), + REGULATOR_LINEAR_RANGE(1310000, 201, 255, 10000) +}; + +static unsigned int rtq2134_buck_of_map_mode(unsigned int mode) +{ + switch (mode) { + case RTQ2134_AUTO_MODE: + return REGULATOR_MODE_NORMAL; + case RTQ2134_FCCM_MODE: + return REGULATOR_MODE_FAST; + } + + return REGULATOR_MODE_INVALID; +} + +static int rtq2134_buck_of_parse_cb(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *cfg) +{ + struct rtq2134_regulator_desc *rdesc = + (struct rtq2134_regulator_desc *)desc; + int rid = desc->id; + bool uv_shutdown, vsel_dvs; + unsigned int val; + int ret; + + vsel_dvs = of_property_read_bool(np, "richtek,use-vsel-dvs"); + if (vsel_dvs) + val = RTQ2134_BUCK_VSEL_CTRL; + else + val = RTQ2134_BUCK_DVS0_CTRL; + + ret = regmap_update_bits(cfg->regmap, rdesc->dvs_ctrl_reg, + RTQ2134_BUCKDVS_CTRL_MASK, val); + if (ret) + return ret; + + uv_shutdown = of_property_read_bool(np, "richtek,uv-shutdown"); + if (uv_shutdown) + val = 0; + else + val = RTQ2134_UVHICCUP_MASK; + + return regmap_update_bits(cfg->regmap, RTQ2134_REG_FLT_BUCKCTRL(rid), + RTQ2134_UVHICCUP_MASK, val); +} + +static const unsigned int rtq2134_buck_ramp_delay_table[] = { + 0, 16000, 0, 8000, 4000, 2000, 1000, 500 +}; + +#define RTQ2134_BUCK_DESC(_id) { \ + .desc = { \ + .name = "rtq2134_buck" #_id, \ + .of_match = of_match_ptr("buck" #_id), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = RTQ2134_IDX_BUCK##_id, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .ops = &rtq2134_buck_ops, \ + .n_voltages = RTQ2134_VOUT_MAXNUM, \ + .linear_ranges = rtq2134_buck_vout_ranges, \ + .n_linear_ranges = ARRAY_SIZE(rtq2134_buck_vout_ranges), \ + .vsel_reg = RTQ2134_REG_BUCK##_id##_DVS0CFG1, \ + .vsel_mask = RTQ2134_VOUT_MASK, \ + .enable_reg = RTQ2134_REG_BUCK##_id##_DVS0CFG0, \ + .enable_mask = RTQ2134_VOUTEN_MASK, \ + .active_discharge_reg = RTQ2134_REG_BUCK##_id##_CFG0, \ + .active_discharge_mask = RTQ2134_ACTDISCHG_MASK, \ + .ramp_reg = RTQ2134_REG_BUCK##_id##_RSPCFG, \ + .ramp_mask = RTQ2134_RSPUP_MASK, \ + .ramp_delay_table = rtq2134_buck_ramp_delay_table, \ + .n_ramp_values = ARRAY_SIZE(rtq2134_buck_ramp_delay_table), \ + .of_map_mode = rtq2134_buck_of_map_mode, \ + .of_parse_cb = rtq2134_buck_of_parse_cb, \ + }, \ + .mode_reg = RTQ2134_REG_BUCK##_id##_DVS0CFG0, \ + .mode_mask = RTQ2134_FCCM_MASK, \ + .suspend_mode_reg = RTQ2134_REG_BUCK##_id##_DVS1CFG0, \ + .suspend_mode_mask = RTQ2134_FCCM_MASK, \ + .suspend_enable_reg = RTQ2134_REG_BUCK##_id##_DVS1CFG0, \ + .suspend_enable_mask = RTQ2134_VOUTEN_MASK, \ + .suspend_vsel_reg = RTQ2134_REG_BUCK##_id##_DVS1CFG1, \ + .suspend_vsel_mask = RTQ2134_VOUT_MASK, \ + .dvs_ctrl_reg = RTQ2134_REG_BUCK##_id##_DVSCFG, \ +} + +static const struct rtq2134_regulator_desc rtq2134_regulator_descs[] = { + RTQ2134_BUCK_DESC(1), + RTQ2134_BUCK_DESC(2), + RTQ2134_BUCK_DESC(3) +}; + +static bool rtq2134_is_accissible_reg(struct device *dev, unsigned int reg) +{ + if (reg >= RTQ2134_REG_IO_CHIPNAME && reg <= RTQ2134_REG_BUCK3_SLEWCTRL) + return true; + return false; +} + +static const struct regmap_config rtq2134_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RTQ2134_REG_BUCK3_SLEWCTRL, + + .readable_reg = rtq2134_is_accissible_reg, + .writeable_reg = rtq2134_is_accissible_reg, +}; + +static int rtq2134_probe(struct i2c_client *i2c) +{ + struct regmap *regmap; + struct regulator_dev *rdev; + struct regulator_config regulator_cfg = {}; + int i; + + regmap = devm_regmap_init_i2c(i2c, &rtq2134_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&i2c->dev, "Failed to allocate regmap\n"); + return PTR_ERR(regmap); + } + + regulator_cfg.dev = &i2c->dev; + regulator_cfg.regmap = regmap; + for (i = 0; i < ARRAY_SIZE(rtq2134_regulator_descs); i++) { + rdev = devm_regulator_register(&i2c->dev, + &rtq2134_regulator_descs[i].desc, + ®ulator_cfg); + if (IS_ERR(rdev)) { + dev_err(&i2c->dev, "Failed to init %d regulator\n", i); + return PTR_ERR(rdev); + } + } + + return 0; +} + +static const struct of_device_id __maybe_unused rtq2134_device_tables[] = { + { .compatible = "richtek,rtq2134", }, + {} +}; +MODULE_DEVICE_TABLE(of, rtq2134_device_tables); + +static struct i2c_driver rtq2134_driver = { + .driver = { + .name = "rtq2134", + .of_match_table = rtq2134_device_tables, + }, + .probe_new = rtq2134_probe, +}; +module_i2c_driver(rtq2134_driver); + +MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); +MODULE_DESCRIPTION("Richtek RTQ2134 Regulator Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/rtq6752-regulator.c b/drivers/regulator/rtq6752-regulator.c new file mode 100644 index 000000000000..609d3fcf4923 --- /dev/null +++ b/drivers/regulator/rtq6752-regulator.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> + +enum { + RTQ6752_IDX_PAVDD = 0, + RTQ6752_IDX_NAVDD = 1, + RTQ6752_IDX_MAX +}; + +#define RTQ6752_REG_PAVDD 0x00 +#define RTQ6752_REG_NAVDD 0x01 +#define RTQ6752_REG_PAVDDONDLY 0x07 +#define RTQ6752_REG_PAVDDSSTIME 0x08 +#define RTQ6752_REG_NAVDDONDLY 0x0D +#define RTQ6752_REG_NAVDDSSTIME 0x0E +#define RTQ6752_REG_OPTION1 0x12 +#define RTQ6752_REG_CHSWITCH 0x16 +#define RTQ6752_REG_FAULT 0x1D + +#define RTQ6752_VOUT_MASK GENMASK(5, 0) +#define RTQ6752_NAVDDEN_MASK BIT(3) +#define RTQ6752_PAVDDEN_MASK BIT(0) +#define RTQ6752_PAVDDAD_MASK BIT(4) +#define RTQ6752_NAVDDAD_MASK BIT(3) +#define RTQ6752_PAVDDF_MASK BIT(3) +#define RTQ6752_NAVDDF_MASK BIT(0) +#define RTQ6752_ENABLE_MASK (BIT(RTQ6752_IDX_MAX) - 1) + +#define RTQ6752_VOUT_MINUV 5000000 +#define RTQ6752_VOUT_STEPUV 50000 +#define RTQ6752_VOUT_NUM 47 +#define RTQ6752_I2CRDY_TIMEUS 1000 +#define RTQ6752_MINSS_TIMEUS 5000 + +struct rtq6752_priv { + struct regmap *regmap; + struct gpio_desc *enable_gpio; + struct mutex lock; + unsigned char enable_flag; +}; + +static int rtq6752_set_vdd_enable(struct regulator_dev *rdev) +{ + struct rtq6752_priv *priv = rdev_get_drvdata(rdev); + int rid = rdev_get_id(rdev), ret; + + mutex_lock(&priv->lock); + if (priv->enable_gpio) { + gpiod_set_value(priv->enable_gpio, 1); + + usleep_range(RTQ6752_I2CRDY_TIMEUS, + RTQ6752_I2CRDY_TIMEUS + 100); + } + + if (!priv->enable_flag) { + regcache_cache_only(priv->regmap, false); + ret = regcache_sync(priv->regmap); + if (ret) { + mutex_unlock(&priv->lock); + return ret; + } + } + + priv->enable_flag |= BIT(rid); + mutex_unlock(&priv->lock); + + return regulator_enable_regmap(rdev); +} + +static int rtq6752_set_vdd_disable(struct regulator_dev *rdev) +{ + struct rtq6752_priv *priv = rdev_get_drvdata(rdev); + int rid = rdev_get_id(rdev), ret; + + ret = regulator_disable_regmap(rdev); + if (ret) + return ret; + + mutex_lock(&priv->lock); + priv->enable_flag &= ~BIT(rid); + + if (!priv->enable_flag) { + regcache_cache_only(priv->regmap, true); + regcache_mark_dirty(priv->regmap); + } + + if (priv->enable_gpio) + gpiod_set_value(priv->enable_gpio, 0); + + mutex_unlock(&priv->lock); + + return 0; +} + +static int rtq6752_get_error_flags(struct regulator_dev *rdev, + unsigned int *flags) +{ + unsigned int val, events = 0; + const unsigned int fault_mask[] = { + RTQ6752_PAVDDF_MASK, RTQ6752_NAVDDF_MASK }; + int rid = rdev_get_id(rdev), ret; + + ret = regmap_read(rdev->regmap, RTQ6752_REG_FAULT, &val); + if (ret) + return ret; + + if (val & fault_mask[rid]) + events = REGULATOR_ERROR_REGULATION_OUT; + + *flags = events; + return 0; +} + +static const struct regulator_ops rtq6752_regulator_ops = { + .list_voltage = regulator_list_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .enable = rtq6752_set_vdd_enable, + .disable = rtq6752_set_vdd_disable, + .is_enabled = regulator_is_enabled_regmap, + .set_active_discharge = regulator_set_active_discharge_regmap, + .get_error_flags = rtq6752_get_error_flags, +}; + +static const struct regulator_desc rtq6752_regulator_descs[] = { + { + .name = "rtq6752-pavdd", + .of_match = of_match_ptr("pavdd"), + .regulators_node = of_match_ptr("regulators"), + .id = RTQ6752_IDX_PAVDD, + .n_voltages = RTQ6752_VOUT_NUM, + .ops = &rtq6752_regulator_ops, + .owner = THIS_MODULE, + .min_uV = RTQ6752_VOUT_MINUV, + .uV_step = RTQ6752_VOUT_STEPUV, + .enable_time = RTQ6752_MINSS_TIMEUS, + .vsel_reg = RTQ6752_REG_PAVDD, + .vsel_mask = RTQ6752_VOUT_MASK, + .enable_reg = RTQ6752_REG_CHSWITCH, + .enable_mask = RTQ6752_PAVDDEN_MASK, + .active_discharge_reg = RTQ6752_REG_OPTION1, + .active_discharge_mask = RTQ6752_PAVDDAD_MASK, + .active_discharge_off = RTQ6752_PAVDDAD_MASK, + }, + { + .name = "rtq6752-navdd", + .of_match = of_match_ptr("navdd"), + .regulators_node = of_match_ptr("regulators"), + .id = RTQ6752_IDX_NAVDD, + .n_voltages = RTQ6752_VOUT_NUM, + .ops = &rtq6752_regulator_ops, + .owner = THIS_MODULE, + .min_uV = RTQ6752_VOUT_MINUV, + .uV_step = RTQ6752_VOUT_STEPUV, + .enable_time = RTQ6752_MINSS_TIMEUS, + .vsel_reg = RTQ6752_REG_NAVDD, + .vsel_mask = RTQ6752_VOUT_MASK, + .enable_reg = RTQ6752_REG_CHSWITCH, + .enable_mask = RTQ6752_NAVDDEN_MASK, + .active_discharge_reg = RTQ6752_REG_OPTION1, + .active_discharge_mask = RTQ6752_NAVDDAD_MASK, + .active_discharge_off = RTQ6752_NAVDDAD_MASK, + } +}; + +static int rtq6752_init_device_properties(struct rtq6752_priv *priv) +{ + u8 raw_vals[] = { 0, 0 }; + int ret; + + /* Configure PAVDD on and softstart delay time to the minimum */ + ret = regmap_raw_write(priv->regmap, RTQ6752_REG_PAVDDONDLY, raw_vals, + ARRAY_SIZE(raw_vals)); + if (ret) + return ret; + + /* Configure NAVDD on and softstart delay time to the minimum */ + return regmap_raw_write(priv->regmap, RTQ6752_REG_NAVDDONDLY, raw_vals, + ARRAY_SIZE(raw_vals)); +} + +static bool rtq6752_is_volatile_reg(struct device *dev, unsigned int reg) +{ + if (reg == RTQ6752_REG_FAULT) + return true; + return false; +} + +static const struct reg_default rtq6752_reg_defaults[] = { + { RTQ6752_REG_PAVDD, 0x14 }, + { RTQ6752_REG_NAVDD, 0x14 }, + { RTQ6752_REG_PAVDDONDLY, 0x01 }, + { RTQ6752_REG_PAVDDSSTIME, 0x01 }, + { RTQ6752_REG_NAVDDONDLY, 0x01 }, + { RTQ6752_REG_NAVDDSSTIME, 0x01 }, + { RTQ6752_REG_OPTION1, 0x07 }, + { RTQ6752_REG_CHSWITCH, 0x29 }, +}; + +static const struct regmap_config rtq6752_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .cache_type = REGCACHE_RBTREE, + .max_register = RTQ6752_REG_FAULT, + .reg_defaults = rtq6752_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(rtq6752_reg_defaults), + .volatile_reg = rtq6752_is_volatile_reg, +}; + +static int rtq6752_probe(struct i2c_client *i2c) +{ + struct rtq6752_priv *priv; + struct regulator_config reg_cfg = {}; + struct regulator_dev *rdev; + int i, ret; + + priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + mutex_init(&priv->lock); + + priv->enable_gpio = devm_gpiod_get_optional(&i2c->dev, "enable", + GPIOD_OUT_HIGH); + if (IS_ERR(priv->enable_gpio)) { + dev_err(&i2c->dev, "Failed to get 'enable' gpio\n"); + return PTR_ERR(priv->enable_gpio); + } + + usleep_range(RTQ6752_I2CRDY_TIMEUS, RTQ6752_I2CRDY_TIMEUS + 100); + /* Default EN pin to high, PAVDD and NAVDD will be on */ + priv->enable_flag = RTQ6752_ENABLE_MASK; + + priv->regmap = devm_regmap_init_i2c(i2c, &rtq6752_regmap_config); + if (IS_ERR(priv->regmap)) { + dev_err(&i2c->dev, "Failed to init regmap\n"); + return PTR_ERR(priv->regmap); + } + + ret = rtq6752_init_device_properties(priv); + if (ret) { + dev_err(&i2c->dev, "Failed to init device properties\n"); + return ret; + } + + reg_cfg.dev = &i2c->dev; + reg_cfg.regmap = priv->regmap; + reg_cfg.driver_data = priv; + + for (i = 0; i < ARRAY_SIZE(rtq6752_regulator_descs); i++) { + rdev = devm_regulator_register(&i2c->dev, + rtq6752_regulator_descs + i, + ®_cfg); + if (IS_ERR(rdev)) { + dev_err(&i2c->dev, "Failed to init %d regulator\n", i); + return PTR_ERR(rdev); + } + } + + return 0; +} + +static const struct of_device_id __maybe_unused rtq6752_device_table[] = { + { .compatible = "richtek,rtq6752", }, + {} +}; +MODULE_DEVICE_TABLE(of, rtq6752_device_table); + +static struct i2c_driver rtq6752_driver = { + .driver = { + .name = "rtq6752", + .of_match_table = rtq6752_device_table, + }, + .probe_new = rtq6752_probe, +}; +module_i2c_driver(rtq6752_driver); + +MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); +MODULE_DESCRIPTION("Richtek RTQ6752 Regulator Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/sy7636a-regulator.c b/drivers/regulator/sy7636a-regulator.c index e021ae08cbaa..8360b3947ead 100644 --- a/drivers/regulator/sy7636a-regulator.c +++ b/drivers/regulator/sy7636a-regulator.c @@ -13,7 +13,10 @@ #include <linux/gpio/consumer.h> #include <linux/mfd/sy7636a.h> -#define SY7636A_POLL_ENABLED_TIME 500 +struct sy7636a_data { + struct regmap *regmap; + struct gpio_desc *pgood_gpio; +}; static int sy7636a_get_vcom_voltage_op(struct regulator_dev *rdev) { @@ -35,10 +38,10 @@ static int sy7636a_get_vcom_voltage_op(struct regulator_dev *rdev) static int sy7636a_get_status(struct regulator_dev *rdev) { - struct sy7636a *sy7636a = rdev_get_drvdata(rdev); + struct sy7636a_data *data = dev_get_drvdata(rdev->dev.parent); int ret = 0; - ret = gpiod_get_value_cansleep(sy7636a->pgood_gpio); + ret = gpiod_get_value_cansleep(data->pgood_gpio); if (ret < 0) dev_err(&rdev->dev, "Failed to read pgood gpio: %d\n", ret); @@ -61,46 +64,50 @@ static const struct regulator_desc desc = { .owner = THIS_MODULE, .enable_reg = SY7636A_REG_OPERATION_MODE_CRL, .enable_mask = SY7636A_OPERATION_MODE_CRL_ONOFF, - .poll_enabled_time = SY7636A_POLL_ENABLED_TIME, .regulators_node = of_match_ptr("regulators"), .of_match = of_match_ptr("vcom"), }; static int sy7636a_regulator_probe(struct platform_device *pdev) { - struct sy7636a *sy7636a = dev_get_drvdata(pdev->dev.parent); + struct regmap *regmap = dev_get_drvdata(pdev->dev.parent); struct regulator_config config = { }; struct regulator_dev *rdev; struct gpio_desc *gdp; + struct sy7636a_data *data; int ret; - if (!sy7636a) + if (!regmap) return -EPROBE_DEFER; - platform_set_drvdata(pdev, sy7636a); - - gdp = devm_gpiod_get(sy7636a->dev, "epd-pwr-good", GPIOD_IN); + gdp = devm_gpiod_get(pdev->dev.parent, "epd-pwr-good", GPIOD_IN); if (IS_ERR(gdp)) { - dev_err(sy7636a->dev, "Power good GPIO fault %ld\n", PTR_ERR(gdp)); + dev_err(pdev->dev.parent, "Power good GPIO fault %ld\n", PTR_ERR(gdp)); return PTR_ERR(gdp); } - sy7636a->pgood_gpio = gdp; + data = devm_kzalloc(&pdev->dev, sizeof(struct sy7636a_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->regmap = regmap; + data->pgood_gpio = gdp; + + platform_set_drvdata(pdev, data); - ret = regmap_write(sy7636a->regmap, SY7636A_REG_POWER_ON_DELAY_TIME, 0x0); + ret = regmap_write(regmap, SY7636A_REG_POWER_ON_DELAY_TIME, 0x0); if (ret) { - dev_err(sy7636a->dev, "Failed to initialize regulator: %d\n", ret); + dev_err(pdev->dev.parent, "Failed to initialize regulator: %d\n", ret); return ret; } config.dev = &pdev->dev; - config.dev->of_node = sy7636a->dev->of_node; - config.driver_data = sy7636a; - config.regmap = sy7636a->regmap; + config.dev->of_node = pdev->dev.parent->of_node; + config.regmap = regmap; rdev = devm_regulator_register(&pdev->dev, &desc, &config); if (IS_ERR(rdev)) { - dev_err(sy7636a->dev, "Failed to register %s regulator\n", + dev_err(pdev->dev.parent, "Failed to register %s regulator\n", pdev->name); return PTR_ERR(rdev); } diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c index 62d243f3b904..5e915cf307b3 100644 --- a/drivers/regulator/sy8824x.c +++ b/drivers/regulator/sy8824x.c @@ -25,6 +25,7 @@ struct sy8824_config { unsigned int vsel_min; unsigned int vsel_step; unsigned int vsel_count; + const struct regmap_config *config; }; struct sy8824_device_info { @@ -110,6 +111,15 @@ static int sy8824_regulator_register(struct sy8824_device_info *di, static const struct regmap_config sy8824_regmap_config = { .reg_bits = 8, .val_bits = 8, + .num_reg_defaults_raw = 1, + .cache_type = REGCACHE_FLAT, +}; + +static const struct regmap_config sy20276_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .num_reg_defaults_raw = 2, + .cache_type = REGCACHE_FLAT, }; static int sy8824_i2c_probe(struct i2c_client *client) @@ -134,7 +144,7 @@ static int sy8824_i2c_probe(struct i2c_client *client) di->dev = dev; di->cfg = of_device_get_match_data(dev); - regmap = devm_regmap_init_i2c(client, &sy8824_regmap_config); + regmap = devm_regmap_init_i2c(client, di->cfg->config); if (IS_ERR(regmap)) { dev_err(dev, "Failed to allocate regmap!\n"); return PTR_ERR(regmap); @@ -160,6 +170,7 @@ static const struct sy8824_config sy8824c_cfg = { .vsel_min = 762500, .vsel_step = 12500, .vsel_count = 64, + .config = &sy8824_regmap_config, }; static const struct sy8824_config sy8824e_cfg = { @@ -169,6 +180,7 @@ static const struct sy8824_config sy8824e_cfg = { .vsel_min = 700000, .vsel_step = 12500, .vsel_count = 64, + .config = &sy8824_regmap_config, }; static const struct sy8824_config sy20276_cfg = { @@ -178,6 +190,7 @@ static const struct sy8824_config sy20276_cfg = { .vsel_min = 600000, .vsel_step = 10000, .vsel_count = 128, + .config = &sy20276_regmap_config, }; static const struct sy8824_config sy20278_cfg = { @@ -187,6 +200,7 @@ static const struct sy8824_config sy20278_cfg = { .vsel_min = 762500, .vsel_step = 12500, .vsel_count = 64, + .config = &sy20276_regmap_config, }; static const struct of_device_id sy8824_dt_ids[] = { diff --git a/drivers/regulator/sy8827n.c b/drivers/regulator/sy8827n.c index 52e8c17afe24..7d5d9f879ce3 100644 --- a/drivers/regulator/sy8827n.c +++ b/drivers/regulator/sy8827n.c @@ -19,6 +19,10 @@ #define SY8827N_MODE (1 << 6) #define SY8827N_VSEL1 1 #define SY8827N_CTRL 2 +#define SY8827N_ID1 3 +#define SY8827N_ID2 4 +#define SY8827N_PGOOD 5 +#define SY8827N_MAX (SY8827N_PGOOD + 1) #define SY8827N_NVOLTAGES 64 #define SY8827N_VSELMIN 600000 @@ -102,9 +106,19 @@ static int sy8827n_regulator_register(struct sy8827n_device_info *di, return PTR_ERR_OR_ZERO(rdev); } +static bool sy8827n_volatile_reg(struct device *dev, unsigned int reg) +{ + if (reg == SY8827N_PGOOD) + return true; + return false; +} + static const struct regmap_config sy8827n_regmap_config = { .reg_bits = 8, .val_bits = 8, + .volatile_reg = sy8827n_volatile_reg, + .num_reg_defaults_raw = SY8827N_MAX, + .cache_type = REGCACHE_FLAT, }; static int sy8827n_i2c_probe(struct i2c_client *client) diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 1d5b0a1b86f7..06cbe60c990f 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -1211,12 +1211,10 @@ static int tps65910_probe(struct platform_device *pdev) rdev = devm_regulator_register(&pdev->dev, &pmic->desc[i], &config); - if (IS_ERR(rdev)) { - dev_err(tps65910->dev, - "failed to register %s regulator\n", - pdev->name); - return PTR_ERR(rdev); - } + if (IS_ERR(rdev)) + return dev_err_probe(tps65910->dev, PTR_ERR(rdev), + "failed to register %s regulator\n", + pdev->name); /* Save regulator for cleanup */ pmic->rdev[i] = rdev; diff --git a/drivers/regulator/vctrl-regulator.c b/drivers/regulator/vctrl-regulator.c index cbadb1c99679..d2a37978fc3a 100644 --- a/drivers/regulator/vctrl-regulator.c +++ b/drivers/regulator/vctrl-regulator.c @@ -37,7 +37,6 @@ struct vctrl_voltage_table { struct vctrl_data { struct regulator_dev *rdev; struct regulator_desc desc; - struct regulator *ctrl_reg; bool enabled; unsigned int min_slew_down_rate; unsigned int ovp_threshold; @@ -82,7 +81,12 @@ static int vctrl_calc_output_voltage(struct vctrl_data *vctrl, int ctrl_uV) static int vctrl_get_voltage(struct regulator_dev *rdev) { struct vctrl_data *vctrl = rdev_get_drvdata(rdev); - int ctrl_uV = regulator_get_voltage_rdev(vctrl->ctrl_reg->rdev); + int ctrl_uV; + + if (!rdev->supply) + return -EPROBE_DEFER; + + ctrl_uV = regulator_get_voltage_rdev(rdev->supply->rdev); return vctrl_calc_output_voltage(vctrl, ctrl_uV); } @@ -92,14 +96,19 @@ static int vctrl_set_voltage(struct regulator_dev *rdev, unsigned int *selector) { struct vctrl_data *vctrl = rdev_get_drvdata(rdev); - struct regulator *ctrl_reg = vctrl->ctrl_reg; - int orig_ctrl_uV = regulator_get_voltage_rdev(ctrl_reg->rdev); - int uV = vctrl_calc_output_voltage(vctrl, orig_ctrl_uV); + int orig_ctrl_uV; + int uV; int ret; + if (!rdev->supply) + return -EPROBE_DEFER; + + orig_ctrl_uV = regulator_get_voltage_rdev(rdev->supply->rdev); + uV = vctrl_calc_output_voltage(vctrl, orig_ctrl_uV); + if (req_min_uV >= uV || !vctrl->ovp_threshold) /* voltage rising or no OVP */ - return regulator_set_voltage_rdev(ctrl_reg->rdev, + return regulator_set_voltage_rdev(rdev->supply->rdev, vctrl_calc_ctrl_voltage(vctrl, req_min_uV), vctrl_calc_ctrl_voltage(vctrl, req_max_uV), PM_SUSPEND_ON); @@ -117,7 +126,7 @@ static int vctrl_set_voltage(struct regulator_dev *rdev, next_uV = max_t(int, req_min_uV, uV - max_drop_uV); next_ctrl_uV = vctrl_calc_ctrl_voltage(vctrl, next_uV); - ret = regulator_set_voltage_rdev(ctrl_reg->rdev, + ret = regulator_set_voltage_rdev(rdev->supply->rdev, next_ctrl_uV, next_ctrl_uV, PM_SUSPEND_ON); @@ -134,7 +143,7 @@ static int vctrl_set_voltage(struct regulator_dev *rdev, err: /* Try to go back to original voltage */ - regulator_set_voltage_rdev(ctrl_reg->rdev, orig_ctrl_uV, orig_ctrl_uV, + regulator_set_voltage_rdev(rdev->supply->rdev, orig_ctrl_uV, orig_ctrl_uV, PM_SUSPEND_ON); return ret; @@ -151,16 +160,18 @@ static int vctrl_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector) { struct vctrl_data *vctrl = rdev_get_drvdata(rdev); - struct regulator *ctrl_reg = vctrl->ctrl_reg; unsigned int orig_sel = vctrl->sel; int ret; + if (!rdev->supply) + return -EPROBE_DEFER; + if (selector >= rdev->desc->n_voltages) return -EINVAL; if (selector >= vctrl->sel || !vctrl->ovp_threshold) { /* voltage rising or no OVP */ - ret = regulator_set_voltage_rdev(ctrl_reg->rdev, + ret = regulator_set_voltage_rdev(rdev->supply->rdev, vctrl->vtable[selector].ctrl, vctrl->vtable[selector].ctrl, PM_SUSPEND_ON); @@ -179,7 +190,7 @@ static int vctrl_set_voltage_sel(struct regulator_dev *rdev, else next_sel = vctrl->vtable[vctrl->sel].ovp_min_sel; - ret = regulator_set_voltage_rdev(ctrl_reg->rdev, + ret = regulator_set_voltage_rdev(rdev->supply->rdev, vctrl->vtable[next_sel].ctrl, vctrl->vtable[next_sel].ctrl, PM_SUSPEND_ON); @@ -202,7 +213,7 @@ static int vctrl_set_voltage_sel(struct regulator_dev *rdev, err: if (vctrl->sel != orig_sel) { /* Try to go back to original voltage */ - if (!regulator_set_voltage_rdev(ctrl_reg->rdev, + if (!regulator_set_voltage_rdev(rdev->supply->rdev, vctrl->vtable[orig_sel].ctrl, vctrl->vtable[orig_sel].ctrl, PM_SUSPEND_ON)) @@ -234,10 +245,6 @@ static int vctrl_parse_dt(struct platform_device *pdev, u32 pval; u32 vrange_ctrl[2]; - vctrl->ctrl_reg = devm_regulator_get(&pdev->dev, "ctrl"); - if (IS_ERR(vctrl->ctrl_reg)) - return PTR_ERR(vctrl->ctrl_reg); - ret = of_property_read_u32(np, "ovp-threshold-percent", &pval); if (!ret) { vctrl->ovp_threshold = pval; @@ -315,11 +322,11 @@ static int vctrl_cmp_ctrl_uV(const void *a, const void *b) return at->ctrl - bt->ctrl; } -static int vctrl_init_vtable(struct platform_device *pdev) +static int vctrl_init_vtable(struct platform_device *pdev, + struct regulator *ctrl_reg) { struct vctrl_data *vctrl = platform_get_drvdata(pdev); struct regulator_desc *rdesc = &vctrl->desc; - struct regulator *ctrl_reg = vctrl->ctrl_reg; struct vctrl_voltage_range *vrange_ctrl = &vctrl->vrange.ctrl; int n_voltages; int ctrl_uV; @@ -395,23 +402,19 @@ static int vctrl_init_vtable(struct platform_device *pdev) static int vctrl_enable(struct regulator_dev *rdev) { struct vctrl_data *vctrl = rdev_get_drvdata(rdev); - int ret = regulator_enable(vctrl->ctrl_reg); - if (!ret) - vctrl->enabled = true; + vctrl->enabled = true; - return ret; + return 0; } static int vctrl_disable(struct regulator_dev *rdev) { struct vctrl_data *vctrl = rdev_get_drvdata(rdev); - int ret = regulator_disable(vctrl->ctrl_reg); - if (!ret) - vctrl->enabled = false; + vctrl->enabled = false; - return ret; + return 0; } static int vctrl_is_enabled(struct regulator_dev *rdev) @@ -447,6 +450,7 @@ static int vctrl_probe(struct platform_device *pdev) struct regulator_desc *rdesc; struct regulator_config cfg = { }; struct vctrl_voltage_range *vrange_ctrl; + struct regulator *ctrl_reg; int ctrl_uV; int ret; @@ -461,15 +465,20 @@ static int vctrl_probe(struct platform_device *pdev) if (ret) return ret; + ctrl_reg = devm_regulator_get(&pdev->dev, "ctrl"); + if (IS_ERR(ctrl_reg)) + return PTR_ERR(ctrl_reg); + vrange_ctrl = &vctrl->vrange.ctrl; rdesc = &vctrl->desc; rdesc->name = "vctrl"; rdesc->type = REGULATOR_VOLTAGE; rdesc->owner = THIS_MODULE; + rdesc->supply_name = "ctrl"; - if ((regulator_get_linear_step(vctrl->ctrl_reg) == 1) || - (regulator_count_voltages(vctrl->ctrl_reg) == -EINVAL)) { + if ((regulator_get_linear_step(ctrl_reg) == 1) || + (regulator_count_voltages(ctrl_reg) == -EINVAL)) { rdesc->continuous_voltage_range = true; rdesc->ops = &vctrl_ops_cont; } else { @@ -486,11 +495,12 @@ static int vctrl_probe(struct platform_device *pdev) cfg.init_data = init_data; if (!rdesc->continuous_voltage_range) { - ret = vctrl_init_vtable(pdev); + ret = vctrl_init_vtable(pdev, ctrl_reg); if (ret) return ret; - ctrl_uV = regulator_get_voltage_rdev(vctrl->ctrl_reg->rdev); + /* Use locked consumer API when not in regulator framework */ + ctrl_uV = regulator_get_voltage(ctrl_reg); if (ctrl_uV < 0) { dev_err(&pdev->dev, "failed to get control voltage\n"); return ctrl_uV; @@ -513,6 +523,9 @@ static int vctrl_probe(struct platform_device *pdev) } } + /* Drop ctrl-supply here in favor of regulator core managed supply */ + devm_regulator_put(ctrl_reg); + vctrl->rdev = devm_regulator_register(&pdev->dev, rdesc, &cfg); if (IS_ERR(vctrl->rdev)) { ret = PTR_ERR(vctrl->rdev); |