diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-05-14 14:36:09 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-05-14 14:36:09 -0700 |
commit | 07bbfc6aba1efe332d9994b2995c9bea0cd3b25f (patch) | |
tree | a3043f65004c7135e3f7ef62196a6a6215822a61 | |
parent | fffe418b2f97ebf1e65267852169a00c682152a5 (diff) | |
parent | 4e70b26c873dfff317039458a6ea66314bbdce99 (diff) | |
download | linux-stable-07bbfc6aba1efe332d9994b2995c9bea0cd3b25f.tar.gz linux-stable-07bbfc6aba1efe332d9994b2995c9bea0cd3b25f.tar.bz2 linux-stable-07bbfc6aba1efe332d9994b2995c9bea0cd3b25f.zip |
Merge tag 'regulator-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator
Pull regulator updates from Mark Brown:
"There's one API update here, a new API factoring out a common pattern
for reference voltage supplies. These are supplies used as a reference
by analogue circuits where the consumer requests and enables the
supply, reads the voltage to calibrate the user and then never touches
it again. This is factored out into a single operation which just
returns the voltage and uses devm_ to manage the request and enable
portion.
Otherwise this has been a very quiet release, we've got some new
device support, some small fixes, housekeeping and cleanup work but
nothing substantial.
There's also some non-regulator changes in here, a number of users for
the new reference voltage API were merged along with it and some MFD
changes were pulled in as dependencies for new driver work.
Highlights:
- Add a new API for single operation handling of reference voltages
- Support for Allwinner AXP717 and D1, and NXP PCA9561A"
* tag 'regulator-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (33 commits)
regulator: sun20i: Add Allwinner D1 LDOs driver
regulator: dt-bindings: Add Allwinner D1 system LDOs
regulator: Mention regulator id in error message about dummy supplies
staging: iio: impedance-analyzer: ad5933: Use devm_regulator_get_enable_read_voltage()
iio: frequency: admv1013: Use devm_regulator_get_enable_read_voltage()
iio: addac: ad74115: Use devm_regulator_get_enable_read_voltage()
hwmon: (adc128d818) simplify final return in probe
regulator: devres: fix devm_regulator_get_enable_read_voltage() return
hwmon: (da9052) Use devm_regulator_get_enable_read_voltage()
hwmon: (adc128d818) Use devm_regulator_get_enable_read_voltage()
regulator: devres: add API for reference voltage supplies
regulator: rtq2208: Fix LDO discharge register and add vsel setting
regulator: dt-bindings: fixed-regulator: Add a preferred node name
regulator: axp20x: add support for the AXP717
mfd: axp20x: Add support for AXP717 PMIC
dt-bindings: mfd: x-powers,axp152: Document AXP717
regulator: axp20x: fix typo-ed identifier
dt-bindings: regulator: qcom,usb-vbus-regulator: Add PM7250B compatible
regulator: pca9450: add pca9451a support
regulator: dt-bindings: pca9450: add pca9451a support
...
37 files changed, 879 insertions, 215 deletions
diff --git a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml index 06f1779835a1..b8e8db0d58e9 100644 --- a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml +++ b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml @@ -83,6 +83,7 @@ allOf: enum: - x-powers,axp313a - x-powers,axp15060 + - x-powers,axp717 then: properties: @@ -99,6 +100,7 @@ properties: - x-powers,axp221 - x-powers,axp223 - x-powers,axp313a + - x-powers,axp717 - x-powers,axp803 - x-powers,axp806 - x-powers,axp809 diff --git a/Documentation/devicetree/bindings/regulator/allwinner,sun20i-d1-system-ldos.yaml b/Documentation/devicetree/bindings/regulator/allwinner,sun20i-d1-system-ldos.yaml new file mode 100644 index 000000000000..ec6695c8d2e3 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/allwinner,sun20i-d1-system-ldos.yaml @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/allwinner,sun20i-d1-system-ldos.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner D1 System LDOs + +maintainers: + - Samuel Holland <samuel@sholland.org> + +description: + Allwinner D1 contains a pair of general-purpose LDOs which are designed to + supply power inside and outside the SoC. They are controlled by a register + within the system control MMIO space. + +properties: + compatible: + enum: + - allwinner,sun20i-d1-system-ldos + + reg: + maxItems: 1 + +patternProperties: + "^ldo[ab]$": + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + +required: + - compatible + - reg + +additionalProperties: false + +... diff --git a/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml b/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml index 9ff9abf2691a..51e2f6fb7a5a 100644 --- a/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml @@ -41,6 +41,13 @@ allOf: - gpios properties: + $nodename: + anyOf: + - description: Preferred name is 'regulator-[0-9]v[0-9]' + pattern: '^regulator(-[0-9]+v[0-9]+|-[0-9a-z-]+)?$' + - description: Any name allowed + deprecated: true + compatible: enum: - regulator-fixed diff --git a/Documentation/devicetree/bindings/regulator/nxp,pca9450-regulator.yaml b/Documentation/devicetree/bindings/regulator/nxp,pca9450-regulator.yaml index 3d469b8e9774..849bfa50bdba 100644 --- a/Documentation/devicetree/bindings/regulator/nxp,pca9450-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/nxp,pca9450-regulator.yaml @@ -28,6 +28,7 @@ properties: - nxp,pca9450a - nxp,pca9450b - nxp,pca9450c + - nxp,pca9451a reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml index 33ae1f786802..fcefc722ee2a 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml @@ -26,6 +26,7 @@ properties: - enum: - qcom,pm4125-vbus-reg - qcom,pm6150-vbus-reg + - qcom,pm7250b-vbus-reg - qcom,pmi632-vbus-reg - const: qcom,pm8150b-vbus-reg diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst index 7be8b8dd5f00..18caebad7376 100644 --- a/Documentation/driver-api/driver-model/devres.rst +++ b/Documentation/driver-api/driver-model/devres.rst @@ -433,6 +433,7 @@ REGULATOR devm_regulator_bulk_put() devm_regulator_get() devm_regulator_get_enable() + devm_regulator_get_enable_read_voltage() devm_regulator_get_enable_optional() devm_regulator_get_exclusive() devm_regulator_get_optional() diff --git a/drivers/hwmon/adc128d818.c b/drivers/hwmon/adc128d818.c index 46e3c8c50765..321a61977396 100644 --- a/drivers/hwmon/adc128d818.c +++ b/drivers/hwmon/adc128d818.c @@ -58,7 +58,6 @@ static const u8 num_inputs[] = { 7, 8, 4, 6 }; struct adc128_data { struct i2c_client *client; - struct regulator *regulator; int vref; /* Reference voltage in mV */ struct mutex update_lock; u8 mode; /* Operation mode */ @@ -389,7 +388,7 @@ static int adc128_detect(struct i2c_client *client, struct i2c_board_info *info) return 0; } -static int adc128_init_client(struct adc128_data *data) +static int adc128_init_client(struct adc128_data *data, bool external_vref) { struct i2c_client *client = data->client; int err; @@ -408,7 +407,7 @@ static int adc128_init_client(struct adc128_data *data) regval |= data->mode << 1; /* If external vref is selected, configure the chip to use it */ - if (data->regulator) + if (external_vref) regval |= 0x01; /* Write advanced configuration register */ @@ -430,9 +429,9 @@ static int adc128_init_client(struct adc128_data *data) static int adc128_probe(struct i2c_client *client) { struct device *dev = &client->dev; - struct regulator *regulator; struct device *hwmon_dev; struct adc128_data *data; + bool external_vref; int err, vref; data = devm_kzalloc(dev, sizeof(struct adc128_data), GFP_KERNEL); @@ -440,20 +439,15 @@ static int adc128_probe(struct i2c_client *client) return -ENOMEM; /* vref is optional. If specified, is used as chip reference voltage */ - regulator = devm_regulator_get_optional(dev, "vref"); - if (!IS_ERR(regulator)) { - data->regulator = regulator; - err = regulator_enable(regulator); - if (err < 0) - return err; - vref = regulator_get_voltage(regulator); - if (vref < 0) { - err = vref; - goto error; - } - data->vref = DIV_ROUND_CLOSEST(vref, 1000); - } else { + vref = devm_regulator_get_enable_read_voltage(dev, "vref"); + if (vref == -ENODEV) { + external_vref = false; data->vref = 2560; /* 2.56V, in mV */ + } else if (vref < 0) { + return vref; + } else { + external_vref = true; + data->vref = DIV_ROUND_CLOSEST(vref, 1000); } /* Operation mode is optional. If unspecified, keep current mode */ @@ -461,13 +455,12 @@ static int adc128_probe(struct i2c_client *client) if (data->mode > 3) { dev_err(dev, "invalid operation mode %d\n", data->mode); - err = -EINVAL; - goto error; + return -EINVAL; } } else { err = i2c_smbus_read_byte_data(client, ADC128_REG_CONFIG_ADV); if (err < 0) - goto error; + return err; data->mode = (err >> 1) & ADC128_REG_MASK; } @@ -476,31 +469,14 @@ static int adc128_probe(struct i2c_client *client) mutex_init(&data->update_lock); /* Initialize the chip */ - err = adc128_init_client(data); + err = adc128_init_client(data, external_vref); if (err < 0) - goto error; + return err; hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, data, adc128_groups); - if (IS_ERR(hwmon_dev)) { - err = PTR_ERR(hwmon_dev); - goto error; - } - - return 0; - -error: - if (data->regulator) - regulator_disable(data->regulator); - return err; -} - -static void adc128_remove(struct i2c_client *client) -{ - struct adc128_data *data = i2c_get_clientdata(client); - if (data->regulator) - regulator_disable(data->regulator); + return PTR_ERR_OR_ZERO(hwmon_dev); } static const struct i2c_device_id adc128_id[] = { @@ -522,7 +498,6 @@ static struct i2c_driver adc128_driver = { .of_match_table = of_match_ptr(adc128_of_match), }, .probe = adc128_probe, - .remove = adc128_remove, .id_table = adc128_id, .detect = adc128_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/da9052-hwmon.c b/drivers/hwmon/da9052-hwmon.c index 2bd7ae8100d7..7fb0c57dfef5 100644 --- a/drivers/hwmon/da9052-hwmon.c +++ b/drivers/hwmon/da9052-hwmon.c @@ -26,7 +26,6 @@ struct da9052_hwmon { struct mutex hwmon_lock; bool tsi_as_adc; int tsiref_mv; - struct regulator *tsiref; struct completion tsidone; }; @@ -397,7 +396,7 @@ static int da9052_hwmon_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct da9052_hwmon *hwmon; struct device *hwmon_dev; - int err; + int err, tsiref_uv; hwmon = devm_kzalloc(dev, sizeof(struct da9052_hwmon), GFP_KERNEL); if (!hwmon) @@ -414,32 +413,20 @@ static int da9052_hwmon_probe(struct platform_device *pdev) device_property_read_bool(pdev->dev.parent, "dlg,tsi-as-adc"); if (hwmon->tsi_as_adc) { - hwmon->tsiref = devm_regulator_get(pdev->dev.parent, "tsiref"); - if (IS_ERR(hwmon->tsiref)) { - err = PTR_ERR(hwmon->tsiref); - dev_err(&pdev->dev, "failed to get tsiref: %d", err); - return err; - } - - err = regulator_enable(hwmon->tsiref); - if (err) - return err; - - hwmon->tsiref_mv = regulator_get_voltage(hwmon->tsiref); - if (hwmon->tsiref_mv < 0) { - err = hwmon->tsiref_mv; - goto exit_regulator; - } + tsiref_uv = devm_regulator_get_enable_read_voltage(dev->parent, + "tsiref"); + if (tsiref_uv < 0) + return dev_err_probe(dev, tsiref_uv, + "failed to get tsiref voltage\n"); /* convert from microvolt (DT) to millivolt (hwmon) */ - hwmon->tsiref_mv /= 1000; + hwmon->tsiref_mv = tsiref_uv / 1000; /* TSIREF limits from datasheet */ if (hwmon->tsiref_mv < 1800 || hwmon->tsiref_mv > 2600) { dev_err(hwmon->da9052->dev, "invalid TSIREF voltage: %d", hwmon->tsiref_mv); - err = -ENXIO; - goto exit_regulator; + return -ENXIO; } /* disable touchscreen features */ @@ -456,7 +443,7 @@ static int da9052_hwmon_probe(struct platform_device *pdev) if (err) { dev_err(&pdev->dev, "Failed to register TSIRDY IRQ: %d", err); - goto exit_regulator; + return err; } } @@ -472,9 +459,6 @@ static int da9052_hwmon_probe(struct platform_device *pdev) exit_irq: if (hwmon->tsi_as_adc) da9052_free_irq(hwmon->da9052, DA9052_IRQ_TSIREADY, hwmon); -exit_regulator: - if (hwmon->tsiref) - regulator_disable(hwmon->tsiref); return err; } @@ -483,10 +467,8 @@ static void da9052_hwmon_remove(struct platform_device *pdev) { struct da9052_hwmon *hwmon = platform_get_drvdata(pdev); - if (hwmon->tsi_as_adc) { + if (hwmon->tsi_as_adc) da9052_free_irq(hwmon->da9052, DA9052_IRQ_TSIREADY, hwmon); - regulator_disable(hwmon->tsiref); - } } static struct platform_driver da9052_hwmon_driver = { diff --git a/drivers/iio/addac/ad74115.c b/drivers/iio/addac/ad74115.c index e6bc5eb3788d..12dc43d487b4 100644 --- a/drivers/iio/addac/ad74115.c +++ b/drivers/iio/addac/ad74115.c @@ -199,7 +199,6 @@ struct ad74115_state { struct spi_device *spi; struct regmap *regmap; struct iio_trigger *trig; - struct regulator *avdd; /* * Synchronize consecutive operations when doing a one-shot @@ -1672,13 +1671,9 @@ static int ad74115_setup(struct iio_dev *indio_dev) if (ret) return ret; - if (val == AD74115_DIN_THRESHOLD_MODE_AVDD) { - ret = regulator_get_voltage(st->avdd); - if (ret < 0) - return ret; - - st->avdd_mv = ret / 1000; - } + if (val == AD74115_DIN_THRESHOLD_MODE_AVDD && !st->avdd_mv) + return dev_err_probe(dev, -EINVAL, + "AVDD voltage is required for digital input threshold mode AVDD\n"); st->din_threshold_mode = val; @@ -1788,11 +1783,6 @@ static int ad74115_reset(struct ad74115_state *st) return 0; } -static void ad74115_regulator_disable(void *data) -{ - regulator_disable(data); -} - static int ad74115_setup_trigger(struct iio_dev *indio_dev) { struct ad74115_state *st = iio_priv(indio_dev); @@ -1855,20 +1845,20 @@ static int ad74115_probe(struct spi_device *spi) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &ad74115_info; - st->avdd = devm_regulator_get(dev, "avdd"); - if (IS_ERR(st->avdd)) - return PTR_ERR(st->avdd); - - ret = regulator_enable(st->avdd); - if (ret) { - dev_err(dev, "Failed to enable avdd regulator\n"); - return ret; + ret = devm_regulator_get_enable_read_voltage(dev, "avdd"); + if (ret < 0) { + /* + * Since this is both a power supply and only optionally a + * reference voltage, make sure to enable it even when the + * voltage is not available. + */ + ret = devm_regulator_get_enable(dev, "avdd"); + if (ret) + return dev_err_probe(dev, ret, "failed to enable avdd\n"); + } else { + st->avdd_mv = ret / 1000; } - ret = devm_add_action_or_reset(dev, ad74115_regulator_disable, st->avdd); - if (ret) - return ret; - ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulator_names), regulator_names); if (ret) diff --git a/drivers/iio/frequency/admv1013.c b/drivers/iio/frequency/admv1013.c index 92923074f930..c0cd5d9844fe 100644 --- a/drivers/iio/frequency/admv1013.c +++ b/drivers/iio/frequency/admv1013.c @@ -95,7 +95,6 @@ struct admv1013_state { struct clk *clkin; /* Protect against concurrent accesses to the device and to data */ struct mutex lock; - struct regulator *reg; struct notifier_block nb; unsigned int input_mode; unsigned int quad_se_mode; @@ -342,14 +341,9 @@ static int admv1013_update_quad_filters(struct admv1013_state *st) FIELD_PREP(ADMV1013_QUAD_FILTERS_MSK, filt_raw)); } -static int admv1013_update_mixer_vgate(struct admv1013_state *st) +static int admv1013_update_mixer_vgate(struct admv1013_state *st, int vcm) { unsigned int mixer_vgate; - int vcm; - - vcm = regulator_get_voltage(st->reg); - if (vcm < 0) - return vcm; if (vcm <= 1800000) mixer_vgate = (2389 * vcm / 1000000 + 8100) / 100; @@ -443,7 +437,7 @@ static const struct iio_chan_spec admv1013_channels[] = { ADMV1013_CHAN_CALIB(1, Q), }; -static int admv1013_init(struct admv1013_state *st) +static int admv1013_init(struct admv1013_state *st, int vcm_uv) { int ret; unsigned int data; @@ -483,7 +477,7 @@ static int admv1013_init(struct admv1013_state *st) if (ret) return ret; - ret = admv1013_update_mixer_vgate(st); + ret = admv1013_update_mixer_vgate(st, vcm_uv); if (ret) return ret; @@ -498,11 +492,6 @@ static int admv1013_init(struct admv1013_state *st) st->input_mode); } -static void admv1013_reg_disable(void *data) -{ - regulator_disable(data); -} - static void admv1013_powerdown(void *data) { unsigned int enable_reg, enable_reg_msk; @@ -557,11 +546,6 @@ static int admv1013_properties_parse(struct admv1013_state *st) else return -EINVAL; - st->reg = devm_regulator_get(&spi->dev, "vcm"); - if (IS_ERR(st->reg)) - return dev_err_probe(&spi->dev, PTR_ERR(st->reg), - "failed to get the common-mode voltage\n"); - ret = devm_regulator_bulk_get_enable(&st->spi->dev, ARRAY_SIZE(admv1013_vcc_regs), admv1013_vcc_regs); @@ -578,7 +562,7 @@ static int admv1013_probe(struct spi_device *spi) { struct iio_dev *indio_dev; struct admv1013_state *st; - int ret; + int ret, vcm_uv; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (!indio_dev) @@ -597,16 +581,12 @@ static int admv1013_probe(struct spi_device *spi) if (ret) return ret; - ret = regulator_enable(st->reg); - if (ret) { - dev_err(&spi->dev, "Failed to enable specified Common-Mode Voltage!\n"); - return ret; - } + ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vcm"); + if (ret < 0) + return dev_err_probe(&spi->dev, ret, + "failed to get the common-mode voltage\n"); - ret = devm_add_action_or_reset(&spi->dev, admv1013_reg_disable, - st->reg); - if (ret) - return ret; + vcm_uv = ret; st->clkin = devm_clk_get_enabled(&spi->dev, "lo_in"); if (IS_ERR(st->clkin)) @@ -620,7 +600,7 @@ static int admv1013_probe(struct spi_device *spi) mutex_init(&st->lock); - ret = admv1013_init(st); + ret = admv1013_init(st, vcm_uv); if (ret) { dev_err(&spi->dev, "admv1013 init failed\n"); return ret; diff --git a/drivers/mfd/axp20x-i2c.c b/drivers/mfd/axp20x-i2c.c index 68d3560cfe4a..b8e7ac89f697 100644 --- a/drivers/mfd/axp20x-i2c.c +++ b/drivers/mfd/axp20x-i2c.c @@ -65,6 +65,7 @@ static const struct of_device_id axp20x_i2c_of_match[] = { { .compatible = "x-powers,axp221", .data = (void *)AXP221_ID }, { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID }, { .compatible = "x-powers,axp313a", .data = (void *)AXP313A_ID }, + { .compatible = "x-powers,axp717", .data = (void *)AXP717_ID }, { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID }, { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID }, { .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID }, @@ -81,6 +82,7 @@ static const struct i2c_device_id axp20x_i2c_id[] = { { "axp221", 0 }, { "axp223", 0 }, { "axp313a", 0 }, + { "axp717", 0 }, { "axp803", 0 }, { "axp806", 0 }, { "axp15060", 0 }, diff --git a/drivers/mfd/axp20x-rsb.c b/drivers/mfd/axp20x-rsb.c index 214bc0d84d44..059656f2a1bd 100644 --- a/drivers/mfd/axp20x-rsb.c +++ b/drivers/mfd/axp20x-rsb.c @@ -58,6 +58,7 @@ static void axp20x_rsb_remove(struct sunxi_rsb_device *rdev) static const struct of_device_id axp20x_rsb_of_match[] = { { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID }, + { .compatible = "x-powers,axp717", .data = (void *)AXP717_ID }, { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID }, { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID }, { .compatible = "x-powers,axp809", .data = (void *)AXP809_ID }, diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index d8daa593ebd5..48ce6ea693ce 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -42,6 +42,7 @@ static const char * const axp20x_model_names[] = { "AXP223", "AXP288", "AXP313a", + "AXP717", "AXP803", "AXP806", "AXP809", @@ -207,6 +208,25 @@ static const struct regmap_access_table axp313a_volatile_table = { .n_yes_ranges = ARRAY_SIZE(axp313a_volatile_ranges), }; +static const struct regmap_range axp717_writeable_ranges[] = { + regmap_reg_range(AXP717_IRQ0_EN, AXP717_IRQ4_EN), + regmap_reg_range(AXP717_DCDC_OUTPUT_CONTROL, AXP717_CPUSLDO_CONTROL), +}; + +static const struct regmap_range axp717_volatile_ranges[] = { + regmap_reg_range(AXP717_IRQ0_STATE, AXP717_IRQ4_STATE), +}; + +static const struct regmap_access_table axp717_writeable_table = { + .yes_ranges = axp717_writeable_ranges, + .n_yes_ranges = ARRAY_SIZE(axp717_writeable_ranges), +}; + +static const struct regmap_access_table axp717_volatile_table = { + .yes_ranges = axp717_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(axp717_volatile_ranges), +}; + static const struct regmap_range axp806_volatile_ranges[] = { regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE), }; @@ -317,6 +337,11 @@ static const struct resource axp313a_pek_resources[] = { DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_FAL_EDGE, "PEK_DBF"), }; +static const struct resource axp717_pek_resources[] = { + DEFINE_RES_IRQ_NAMED(AXP717_IRQ_PEK_RIS_EDGE, "PEK_DBR"), + DEFINE_RES_IRQ_NAMED(AXP717_IRQ_PEK_FAL_EDGE, "PEK_DBF"), +}; + static const struct resource axp803_pek_resources[] = { DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_RIS_EDGE, "PEK_DBR"), DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"), @@ -391,6 +416,15 @@ static const struct regmap_config axp313a_regmap_config = { .cache_type = REGCACHE_MAPLE, }; +static const struct regmap_config axp717_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .wr_table = &axp717_writeable_table, + .volatile_table = &axp717_volatile_table, + .max_register = AXP717_CPUSLDO_CONTROL, + .cache_type = REGCACHE_RBTREE, +}; + static const struct regmap_config axp806_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -589,6 +623,40 @@ static const struct regmap_irq axp313a_regmap_irqs[] = { INIT_REGMAP_IRQ(AXP313A, DIE_TEMP_HIGH, 0, 0), }; +static const struct regmap_irq axp717_regmap_irqs[] = { + INIT_REGMAP_IRQ(AXP717, SOC_DROP_LVL2, 0, 7), + INIT_REGMAP_IRQ(AXP717, SOC_DROP_LVL1, 0, 6), + INIT_REGMAP_IRQ(AXP717, GAUGE_NEW_SOC, 0, 4), + INIT_REGMAP_IRQ(AXP717, BOOST_OVER_V, 0, 2), + INIT_REGMAP_IRQ(AXP717, VBUS_OVER_V, 0, 1), + INIT_REGMAP_IRQ(AXP717, VBUS_FAULT, 0, 0), + INIT_REGMAP_IRQ(AXP717, VBUS_PLUGIN, 1, 7), + INIT_REGMAP_IRQ(AXP717, VBUS_REMOVAL, 1, 6), + INIT_REGMAP_IRQ(AXP717, BATT_PLUGIN, 1, 5), + INIT_REGMAP_IRQ(AXP717, BATT_REMOVAL, 1, 4), + INIT_REGMAP_IRQ(AXP717, PEK_SHORT, 1, 3), + INIT_REGMAP_IRQ(AXP717, PEK_LONG, 1, 2), + INIT_REGMAP_IRQ(AXP717, PEK_FAL_EDGE, 1, 1), + INIT_REGMAP_IRQ(AXP717, PEK_RIS_EDGE, 1, 0), + INIT_REGMAP_IRQ(AXP717, WDOG_EXPIRE, 2, 7), + INIT_REGMAP_IRQ(AXP717, LDO_OVER_CURR, 2, 6), + INIT_REGMAP_IRQ(AXP717, BATT_OVER_CURR, 2, 5), + INIT_REGMAP_IRQ(AXP717, CHARG_DONE, 2, 4), + INIT_REGMAP_IRQ(AXP717, CHARG, 2, 3), + INIT_REGMAP_IRQ(AXP717, DIE_TEMP_HIGH, 2, 2), + INIT_REGMAP_IRQ(AXP717, CHARG_TIMER, 2, 1), + INIT_REGMAP_IRQ(AXP717, BATT_OVER_V, 2, 0), + INIT_REGMAP_IRQ(AXP717, BC_USB_DONE, 3, 7), + INIT_REGMAP_IRQ(AXP717, BC_USB_CHNG, 3, 6), + INIT_REGMAP_IRQ(AXP717, BATT_QUIT_TEMP_HIGH, 3, 4), + INIT_REGMAP_IRQ(AXP717, BATT_CHG_TEMP_HIGH, 3, 3), + INIT_REGMAP_IRQ(AXP717, BATT_CHG_TEMP_LOW, 3, 2), + INIT_REGMAP_IRQ(AXP717, BATT_ACT_TEMP_HIGH, 3, 1), + INIT_REGMAP_IRQ(AXP717, BATT_ACT_TEMP_LOW, 3, 0), + INIT_REGMAP_IRQ(AXP717, TYPEC_REMOVE, 4, 6), + INIT_REGMAP_IRQ(AXP717, TYPEC_PLUGIN, 4, 5), +}; + static const struct regmap_irq axp803_regmap_irqs[] = { INIT_REGMAP_IRQ(AXP803, ACIN_OVER_V, 0, 7), INIT_REGMAP_IRQ(AXP803, ACIN_PLUGIN, 0, 6), @@ -776,6 +844,17 @@ static const struct regmap_irq_chip axp313a_regmap_irq_chip = { .num_regs = 1, }; +static const struct regmap_irq_chip axp717_regmap_irq_chip = { + .name = "axp717_irq_chip", + .status_base = AXP717_IRQ0_STATE, + .ack_base = AXP717_IRQ0_STATE, + .unmask_base = AXP717_IRQ0_EN, + .init_ack_masked = true, + .irqs = axp717_regmap_irqs, + .num_irqs = ARRAY_SIZE(axp717_regmap_irqs), + .num_regs = 5, +}; + static const struct regmap_irq_chip axp803_regmap_irq_chip = { .name = "axp803", .status_base = AXP20X_IRQ1_STATE, @@ -941,6 +1020,11 @@ static struct mfd_cell axp313a_cells[] = { MFD_CELL_RES("axp313a-pek", axp313a_pek_resources), }; +static struct mfd_cell axp717_cells[] = { + MFD_CELL_NAME("axp20x-regulator"), + MFD_CELL_RES("axp20x-pek", axp717_pek_resources), +}; + static const struct resource axp288_adc_resources[] = { DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC"), }; @@ -1181,6 +1265,12 @@ int axp20x_match_device(struct axp20x_dev *axp20x) axp20x->regmap_cfg = &axp313a_regmap_config; axp20x->regmap_irq_chip = &axp313a_regmap_irq_chip; break; + case AXP717_ID: + axp20x->nr_cells = ARRAY_SIZE(axp717_cells); + axp20x->cells = axp717_cells; + axp20x->regmap_cfg = &axp717_regmap_config; + axp20x->regmap_irq_chip = &axp717_regmap_irq_chip; + break; case AXP803_ID: axp20x->nr_cells = ARRAY_SIZE(axp803_cells); axp20x->cells = axp803_cells; diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 7db0a29b5b8d..acdb02a4ac0c 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -1415,6 +1415,14 @@ config REGULATOR_STW481X_VMMC This driver supports the internal VMMC regulator in the STw481x PMIC chips. +config REGULATOR_SUN20I + tristate "Allwinner D1 internal LDOs" + depends on ARCH_SUNXI || COMPILE_TEST + select MFD_SYSCON + default ARCH_SUNXI + help + This driver supports the internal LDOs in the Allwinner D1 SoC. + config REGULATOR_SY7636A tristate "Silergy SY7636A voltage regulator" depends on MFD_SY7636A diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 46fb569e6be8..ba15fa5f30ad 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -163,6 +163,7 @@ obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o obj-$(CONFIG_REGULATOR_STM32_PWR) += stm32-pwr.o obj-$(CONFIG_REGULATOR_STPMIC1) += stpmic1_regulator.o obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o +obj-$(CONFIG_REGULATOR_SUN20I) += sun20i-regulator.o obj-$(CONFIG_REGULATOR_SY7636A) += sy7636a-regulator.o obj-$(CONFIG_REGULATOR_SY8106A) += sy8106a-regulator.o obj-$(CONFIG_REGULATOR_SY8824X) += sy8824x.o diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index c657820b0bbb..34fcdd82b2ea 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -138,6 +138,12 @@ #define AXP313A_DCDC_V_OUT_MASK GENMASK(6, 0) #define AXP313A_LDO_V_OUT_MASK GENMASK(4, 0) +#define AXP717_DCDC1_NUM_VOLTAGES 88 +#define AXP717_DCDC2_NUM_VOLTAGES 107 +#define AXP717_DCDC3_NUM_VOLTAGES 104 +#define AXP717_DCDC_V_OUT_MASK GENMASK(6, 0) +#define AXP717_LDO_V_OUT_MASK GENMASK(4, 0) + #define AXP803_PWR_OUT_DCDC1_MASK BIT_MASK(0) #define AXP803_PWR_OUT_DCDC2_MASK BIT_MASK(1) #define AXP803_PWR_OUT_DCDC3_MASK BIT_MASK(2) @@ -733,25 +739,98 @@ static const struct linear_range axp313a_dcdc3_ranges[] = { static const struct regulator_desc axp313a_regulators[] = { AXP_DESC_RANGES(AXP313A, DCDC1, "dcdc1", "vin1", axp313a_dcdc1_ranges, AXP313A_DCDC1_NUM_VOLTAGES, - AXP313A_DCDC1_CONRTOL, AXP313A_DCDC_V_OUT_MASK, + AXP313A_DCDC1_CONTROL, AXP313A_DCDC_V_OUT_MASK, AXP313A_OUTPUT_CONTROL, BIT(0)), AXP_DESC_RANGES(AXP313A, DCDC2, "dcdc2", "vin2", axp313a_dcdc2_ranges, AXP313A_DCDC23_NUM_VOLTAGES, - AXP313A_DCDC2_CONRTOL, AXP313A_DCDC_V_OUT_MASK, + AXP313A_DCDC2_CONTROL, AXP313A_DCDC_V_OUT_MASK, AXP313A_OUTPUT_CONTROL, BIT(1)), AXP_DESC_RANGES(AXP313A, DCDC3, "dcdc3", "vin3", axp313a_dcdc3_ranges, AXP313A_DCDC23_NUM_VOLTAGES, - AXP313A_DCDC3_CONRTOL, AXP313A_DCDC_V_OUT_MASK, + AXP313A_DCDC3_CONTROL, AXP313A_DCDC_V_OUT_MASK, AXP313A_OUTPUT_CONTROL, BIT(2)), AXP_DESC(AXP313A, ALDO1, "aldo1", "vin1", 500, 3500, 100, - AXP313A_ALDO1_CONRTOL, AXP313A_LDO_V_OUT_MASK, + AXP313A_ALDO1_CONTROL, AXP313A_LDO_V_OUT_MASK, AXP313A_OUTPUT_CONTROL, BIT(3)), AXP_DESC(AXP313A, DLDO1, "dldo1", "vin1", 500, 3500, 100, - AXP313A_DLDO1_CONRTOL, AXP313A_LDO_V_OUT_MASK, + AXP313A_DLDO1_CONTROL, AXP313A_LDO_V_OUT_MASK, AXP313A_OUTPUT_CONTROL, BIT(4)), AXP_DESC_FIXED(AXP313A, RTC_LDO, "rtc-ldo", "vin1", 1800), }; +static const struct linear_range axp717_dcdc1_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), + REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000), +}; + +static const struct linear_range axp717_dcdc2_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), + REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000), + REGULATOR_LINEAR_RANGE(1600000, 88, 107, 100000), +}; + +static const struct linear_range axp717_dcdc3_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), + REGULATOR_LINEAR_RANGE(1220000, 71, 102, 20000), +}; + +static const struct regulator_desc axp717_regulators[] = { + AXP_DESC_RANGES(AXP717, DCDC1, "dcdc1", "vin1", + axp717_dcdc1_ranges, AXP717_DCDC1_NUM_VOLTAGES, + AXP717_DCDC1_CONTROL, AXP717_DCDC_V_OUT_MASK, + AXP717_DCDC_OUTPUT_CONTROL, BIT(0)), + AXP_DESC_RANGES(AXP717, DCDC2, "dcdc2", "vin2", + axp717_dcdc2_ranges, AXP717_DCDC2_NUM_VOLTAGES, + AXP717_DCDC2_CONTROL, AXP717_DCDC_V_OUT_MASK, + AXP717_DCDC_OUTPUT_CONTROL, BIT(1)), + AXP_DESC_RANGES(AXP717, DCDC3, "dcdc3", "vin3", + axp717_dcdc3_ranges, AXP717_DCDC3_NUM_VOLTAGES, + AXP717_DCDC3_CONTROL, AXP717_DCDC_V_OUT_MASK, + AXP717_DCDC_OUTPUT_CONTROL, BIT(2)), + AXP_DESC(AXP717, DCDC4, "dcdc4", "vin4", 1000, 3700, 100, + AXP717_DCDC4_CONTROL, AXP717_DCDC_V_OUT_MASK, + AXP717_DCDC_OUTPUT_CONTROL, BIT(3)), + AXP_DESC(AXP717, ALDO1, "aldo1", "vin1", 500, 3500, 100, + AXP717_ALDO1_CONTROL, AXP717_LDO_V_OUT_MASK, + AXP717_LDO0_OUTPUT_CONTROL, BIT(0)), + AXP_DESC(AXP717, ALDO2, "aldo2", "vin1", 500, 3500, 100, + AXP717_ALDO2_CONTROL, AXP717_LDO_V_OUT_MASK, + AXP717_LDO0_OUTPUT_CONTROL, BIT(1)), + AXP_DESC(AXP717, ALDO3, "aldo3", "vin1", 500, 3500, 100, + AXP717_ALDO3_CONTROL, AXP717_LDO_V_OUT_MASK, + AXP717_LDO0_OUTPUT_CONTROL, BIT(2)), + AXP_DESC(AXP717, ALDO4, "aldo4", "vin1", 500, 3500, 100, + AXP717_ALDO4_CONTROL, AXP717_LDO_V_OUT_MASK, + AXP717_LDO0_OUTPUT_CONTROL, BIT(3)), + AXP_DESC(AXP717, BLDO1, "bldo1", "vin1", 500, 3500, 100, + AXP717_BLDO1_CONTROL, AXP717_LDO_V_OUT_MASK, + AXP717_LDO0_OUTPUT_CONTROL, BIT(4)), + AXP_DESC(AXP717, BLDO2, "bldo2", "vin1", 500, 3500, 100, + AXP717_BLDO2_CONTROL, AXP717_LDO_V_OUT_MASK, + AXP717_LDO0_OUTPUT_CONTROL, BIT(5)), + AXP_DESC(AXP717, BLDO3, "bldo3", "vin1", 500, 3500, 100, + AXP717_BLDO3_CONTROL, AXP717_LDO_V_OUT_MASK, + AXP717_LDO0_OUTPUT_CONTROL, BIT(6)), + AXP_DESC(AXP717, BLDO4, "bldo4", "vin1", 500, 3500, 100, + AXP717_BLDO4_CONTROL, AXP717_LDO_V_OUT_MASK, + AXP717_LDO0_OUTPUT_CONTROL, BIT(7)), + AXP_DESC(AXP717, CLDO1, "cldo1", "vin1", 500, 3500, 100, + AXP717_CLDO1_CONTROL, AXP717_LDO_V_OUT_MASK, + AXP717_LDO1_OUTPUT_CONTROL, BIT(0)), + AXP_DESC(AXP717, CLDO2, "cldo2", "vin1", 500, 3500, 100, + AXP717_CLDO2_CONTROL, AXP717_LDO_V_OUT_MASK, + AXP717_LDO1_OUTPUT_CONTROL, BIT(1)), + AXP_DESC(AXP717, CLDO3, "cldo3", "vin1", 500, 3500, 100, + AXP717_CLDO3_CONTROL, AXP717_LDO_V_OUT_MASK, + AXP717_LDO1_OUTPUT_CONTROL, BIT(2)), + AXP_DESC(AXP717, CLDO4, "cldo4", "vin1", 500, 3500, 100, + AXP717_CLDO4_CONTROL, AXP717_LDO_V_OUT_MASK, + AXP717_LDO1_OUTPUT_CONTROL, BIT(3)), + AXP_DESC(AXP717, CPUSLDO, "cpusldo", "vin1", 500, 1400, 50, + AXP717_CPUSLDO_CONTROL, AXP717_LDO_V_OUT_MASK, + AXP717_LDO1_OUTPUT_CONTROL, BIT(4)), +}; + /* DCDC ranges shared with AXP813 */ static const struct linear_range axp803_dcdc234_ranges[] = { REGULATOR_LINEAR_RANGE(500000, @@ -1253,6 +1332,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) step = 150; break; case AXP313A_ID: + case AXP717_ID: case AXP15060_ID: /* The DCDC PWM frequency seems to be fixed to 3 MHz. */ if (dcdcfreq != 0) { @@ -1479,6 +1559,10 @@ static int axp20x_regulator_probe(struct platform_device *pdev) regulators = axp313a_regulators; nregulators = AXP313A_REG_ID_MAX; break; + case AXP717_ID: + regulators = axp717_regulators; + nregulators = AXP717_REG_ID_MAX; + break; case AXP803_ID: regulators = axp803_regulators; nregulators = AXP803_REG_ID_MAX; diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 2c33653ffdea..5794f4e9dd52 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2200,7 +2200,7 @@ struct regulator *_regulator_get(struct device *dev, const char *id, if (!have_full_constraints()) { dev_warn(dev, - "incomplete constraints, dummy supplies not allowed\n"); + "incomplete constraints, dummy supplies not allowed (id=%s)\n", id); return ERR_PTR(-ENODEV); } @@ -2218,7 +2218,7 @@ struct regulator *_regulator_get(struct device *dev, const char *id, case EXCLUSIVE_GET: dev_warn(dev, - "dummy supplies not allowed for exclusive requests\n"); + "dummy supplies not allowed for exclusive requests (id=%s)\n", id); fallthrough; default: diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c index 5ee76b533576..96257551bb12 100644 --- a/drivers/regulator/da9121-regulator.c +++ b/drivers/regulator/da9121-regulator.c @@ -872,7 +872,7 @@ static struct regmap_config da9121_1ch_regmap_config = { .rd_table = &da9121_1ch_readable_table, .wr_table = &da9121_1ch_writeable_table, .volatile_table = &da9121_volatile_table, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; /* DA9121 regmap config for 2 channel variants */ @@ -883,7 +883,7 @@ static struct regmap_config da9121_2ch_regmap_config = { .rd_table = &da9121_2ch_readable_table, .wr_table = &da9121_2ch_writeable_table, .volatile_table = &da9121_volatile_table, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static int da9121_check_device_type(struct i2c_client *i2c, struct da9121 *chip) diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c index af383ff0fe57..d8b39ea3de0e 100644 --- a/drivers/regulator/da9211-regulator.c +++ b/drivers/regulator/da9211-regulator.c @@ -68,7 +68,7 @@ static const struct regmap_config da9211_regmap_config = { .val_bits = 8, .max_register = 5 * 128, .volatile_reg = da9211_volatile_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .ranges = da9211_regmap_range, .num_ranges = ARRAY_SIZE(da9211_regmap_range), }; diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c index 90bb0d178885..7111c46e9de1 100644 --- a/drivers/regulator/devres.c +++ b/drivers/regulator/devres.c @@ -145,6 +145,65 @@ struct regulator *devm_regulator_get_optional(struct device *dev, } EXPORT_SYMBOL_GPL(devm_regulator_get_optional); +/** + * devm_regulator_get_enable_read_voltage - Resource managed regulator get and + * enable that returns the voltage + * @dev: device to supply + * @id: supply name or regulator ID. + * + * Get and enable regulator for duration of the device life-time. + * regulator_disable() and regulator_put() are automatically called on driver + * detach. See regulator_get_optional(), regulator_enable(), and + * regulator_get_voltage() for more information. + * + * This is a convenience function for supplies that provide a reference voltage + * where the consumer driver just needs to know the voltage and keep the + * regulator enabled. + * + * In cases where the supply is not strictly required, callers can check for + * -ENODEV error and handle it accordingly. + * + * Returns: voltage in microvolts on success, or an error code on failure. + */ +int devm_regulator_get_enable_read_voltage(struct device *dev, const char *id) +{ + struct regulator *r; + int ret; + + /* + * Since we need a real voltage, we use devm_regulator_get_optional() + * rather than getting a dummy regulator with devm_regulator_get() and + * then letting regulator_get_voltage() fail with -EINVAL. This way, the + * caller can handle the -ENODEV error code if needed instead of the + * ambiguous -EINVAL. + */ + r = devm_regulator_get_optional(dev, id); + if (IS_ERR(r)) + return PTR_ERR(r); + + ret = regulator_enable(r); + if (ret) + goto err_regulator_put; + + ret = devm_add_action_or_reset(dev, regulator_action_disable, r); + if (ret) + goto err_regulator_put; + + ret = regulator_get_voltage(r); + if (ret < 0) + goto err_release_action; + + return ret; + +err_release_action: + devm_release_action(dev, regulator_action_disable, r); +err_regulator_put: + devm_regulator_put(r); + + return ret; +} +EXPORT_SYMBOL_GPL(devm_regulator_get_enable_read_voltage); + static int devm_regulator_match(struct device *dev, void *res, void *data) { struct regulator **r = res; diff --git a/drivers/regulator/isl9305.c b/drivers/regulator/isl9305.c index 0f7560093091..5a234f25e6bb 100644 --- a/drivers/regulator/isl9305.c +++ b/drivers/regulator/isl9305.c @@ -134,7 +134,7 @@ static const struct regmap_config isl9305_regmap = { .val_bits = 8, .max_register = ISL9305_MAX_REG, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static int isl9305_i2c_probe(struct i2c_client *i2c) diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c index f8bb6828feef..96ca146281d6 100644 --- a/drivers/regulator/max8973-regulator.c +++ b/drivers/regulator/max8973-regulator.c @@ -510,7 +510,7 @@ static const struct regmap_config max8973_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = MAX8973_CHIPID2, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static struct max8973_regulator_platform_data *max8973_parse_dt( diff --git a/drivers/regulator/mt6311-regulator.c b/drivers/regulator/mt6311-regulator.c index 63a51485f2cc..c00638cd2d1e 100644 --- a/drivers/regulator/mt6311-regulator.c +++ b/drivers/regulator/mt6311-regulator.c @@ -20,7 +20,7 @@ static const struct regmap_config mt6311_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = MT6311_FQMTR_CON4, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; /* Default limits measured in millivolts and milliamps */ diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c index 2ab365d2749f..be488c5dff14 100644 --- a/drivers/regulator/pca9450-regulator.c +++ b/drivers/regulator/pca9450-regulator.c @@ -53,7 +53,7 @@ static const struct regmap_config pca9450_regmap_config = { .val_bits = 8, .volatile_table = &pca9450_volatile_regs, .max_register = PCA9450_MAX_REGISTER - 1, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; /* @@ -107,6 +107,14 @@ static const struct linear_range pca9450_dvs_buck_volts[] = { }; /* + * BUCK1/3 + * 0.65 to 2.2375V (12.5mV step) + */ +static const struct linear_range pca9451a_dvs_buck_volts[] = { + REGULATOR_LINEAR_RANGE(650000, 0x00, 0x7F, 12500), +}; + +/* * BUCK4/5/6 * 0.6V to 3.4V (25mV step) */ @@ -662,6 +670,178 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = { }, }; +static const struct pca9450_regulator_desc pca9451a_regulators[] = { + { + .desc = { + .name = "buck1", + .of_match = of_match_ptr("BUCK1"), + .regulators_node = of_match_ptr("regulators"), + .id = PCA9450_BUCK1, + .ops = &pca9450_dvs_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = PCA9450_BUCK1_VOLTAGE_NUM, + .linear_ranges = pca9451a_dvs_buck_volts, + .n_linear_ranges = ARRAY_SIZE(pca9451a_dvs_buck_volts), + .vsel_reg = PCA9450_REG_BUCK1OUT_DVS0, + .vsel_mask = BUCK1OUT_DVS0_MASK, + .enable_reg = PCA9450_REG_BUCK1CTRL, + .enable_mask = BUCK1_ENMODE_MASK, + .enable_val = BUCK_ENMODE_ONREQ, + .ramp_mask = BUCK1_RAMP_MASK, + .ramp_delay_table = pca9450_dvs_buck_ramp_table, + .n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table), + .owner = THIS_MODULE, + .of_parse_cb = pca9450_set_dvs_levels, + }, + .dvs = { + .run_reg = PCA9450_REG_BUCK1OUT_DVS0, + .run_mask = BUCK1OUT_DVS0_MASK, + .standby_reg = PCA9450_REG_BUCK1OUT_DVS1, + .standby_mask = BUCK1OUT_DVS1_MASK, + }, + }, + { + .desc = { + .name = "buck2", + .of_match = of_match_ptr("BUCK2"), + .regulators_node = of_match_ptr("regulators"), + .id = PCA9450_BUCK2, + .ops = &pca9450_dvs_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = PCA9450_BUCK2_VOLTAGE_NUM, + .linear_ranges = pca9450_dvs_buck_volts, + .n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts), + .vsel_reg = PCA9450_REG_BUCK2OUT_DVS0, + .vsel_mask = BUCK2OUT_DVS0_MASK, + .enable_reg = PCA9450_REG_BUCK2CTRL, + .enable_mask = BUCK2_ENMODE_MASK, + .enable_val = BUCK_ENMODE_ONREQ_STBYREQ, + .ramp_mask = BUCK2_RAMP_MASK, + .ramp_delay_table = pca9450_dvs_buck_ramp_table, + .n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table), + .owner = THIS_MODULE, + .of_parse_cb = pca9450_set_dvs_levels, + }, + .dvs = { + .run_reg = PCA9450_REG_BUCK2OUT_DVS0, + .run_mask = BUCK2OUT_DVS0_MASK, + .standby_reg = PCA9450_REG_BUCK2OUT_DVS1, + .standby_mask = BUCK2OUT_DVS1_MASK, + }, + }, + { + .desc = { + .name = "buck4", + .of_match = of_match_ptr("BUCK4"), + .regulators_node = of_match_ptr("regulators"), + .id = PCA9450_BUCK4, + .ops = &pca9450_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = PCA9450_BUCK4_VOLTAGE_NUM, + .linear_ranges = pca9450_buck_volts, + .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts), + .vsel_reg = PCA9450_REG_BUCK4OUT, + .vsel_mask = BUCK4OUT_MASK, + .enable_reg = PCA9450_REG_BUCK4CTRL, + .enable_mask = BUCK4_ENMODE_MASK, + .enable_val = BUCK_ENMODE_ONREQ, + .owner = THIS_MODULE, + }, + }, + { + .desc = { + .name = "buck5", + .of_match = of_match_ptr("BUCK5"), + .regulators_node = of_match_ptr("regulators"), + .id = PCA9450_BUCK5, + .ops = &pca9450_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = PCA9450_BUCK5_VOLTAGE_NUM, + .linear_ranges = pca9450_buck_volts, + .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts), + .vsel_reg = PCA9450_REG_BUCK5OUT, + .vsel_mask = BUCK5OUT_MASK, + .enable_reg = PCA9450_REG_BUCK5CTRL, + .enable_mask = BUCK5_ENMODE_MASK, + .enable_val = BUCK_ENMODE_ONREQ, + .owner = THIS_MODULE, + }, + }, + { + .desc = { + .name = "buck6", + .of_match = of_match_ptr("BUCK6"), + .regulators_node = of_match_ptr("regulators"), + .id = PCA9450_BUCK6, + .ops = &pca9450_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = PCA9450_BUCK6_VOLTAGE_NUM, + .linear_ranges = pca9450_buck_volts, + .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts), + .vsel_reg = PCA9450_REG_BUCK6OUT, + .vsel_mask = BUCK6OUT_MASK, + .enable_reg = PCA9450_REG_BUCK6CTRL, + .enable_mask = BUCK6_ENMODE_MASK, + .enable_val = BUCK_ENMODE_ONREQ, + .owner = THIS_MODULE, + }, + }, + { + .desc = { + .name = "ldo1", + .of_match = of_match_ptr("LDO1"), + .regulators_node = of_match_ptr("regulators"), + .id = PCA9450_LDO1, + .ops = &pca9450_ldo_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = PCA9450_LDO1_VOLTAGE_NUM, + .linear_ranges = pca9450_ldo1_volts, + .n_linear_ranges = ARRAY_SIZE(pca9450_ldo1_volts), + .vsel_reg = PCA9450_REG_LDO1CTRL, + .vsel_mask = LDO1OUT_MASK, + .enable_reg = PCA9450_REG_LDO1CTRL, + .enable_mask = LDO1_EN_MASK, + .owner = THIS_MODULE, + }, + }, + { + .desc = { + .name = "ldo4", + .of_match = of_match_ptr("LDO4"), + .regulators_node = of_match_ptr("regulators"), + .id = PCA9450_LDO4, + .ops = &pca9450_ldo_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = PCA9450_LDO4_VOLTAGE_NUM, + .linear_ranges = pca9450_ldo34_volts, + .n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts), + .vsel_reg = PCA9450_REG_LDO4CTRL, + .vsel_mask = LDO4OUT_MASK, + .enable_reg = PCA9450_REG_LDO4CTRL, + .enable_mask = LDO4_EN_MASK, + .owner = THIS_MODULE, + }, + }, + { + .desc = { + .name = "ldo5", + .of_match = of_match_ptr("LDO5"), + .regulators_node = of_match_ptr("regulators"), + .id = PCA9450_LDO5, + .ops = &pca9450_ldo_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = PCA9450_LDO5_VOLTAGE_NUM, + .linear_ranges = pca9450_ldo5_volts, + .n_linear_ranges = ARRAY_SIZE(pca9450_ldo5_volts), + .vsel_reg = PCA9450_REG_LDO5CTRL_H, + .vsel_mask = LDO5HOUT_MASK, + .enable_reg = PCA9450_REG_LDO5CTRL_H, + .enable_mask = LDO5H_EN_MASK, + .owner = THIS_MODULE, + }, + }, +}; + static irqreturn_t pca9450_irq_handler(int irq, void *data) { struct pca9450 *pca9450 = data; @@ -729,6 +909,10 @@ static int pca9450_i2c_probe(struct i2c_client *i2c) regulator_desc = pca9450bc_regulators; pca9450->rcnt = ARRAY_SIZE(pca9450bc_regulators); break; + case PCA9450_TYPE_PCA9451A: + regulator_desc = pca9451a_regulators; + pca9450->rcnt = ARRAY_SIZE(pca9451a_regulators); + break; default: dev_err(&i2c->dev, "Unknown device type"); return -EINVAL; @@ -755,7 +939,8 @@ static int pca9450_i2c_probe(struct i2c_client *i2c) /* Check your board and dts for match the right pmic */ if (((device_id >> 4) != 0x1 && type == PCA9450_TYPE_PCA9450A) || - ((device_id >> 4) != 0x3 && type == PCA9450_TYPE_PCA9450BC)) { + ((device_id >> 4) != 0x3 && type == PCA9450_TYPE_PCA9450BC) || + ((device_id >> 4) != 0x9 && type == PCA9450_TYPE_PCA9451A)) { dev_err(&i2c->dev, "Device id(%x) mismatched\n", device_id >> 4); return -EINVAL; @@ -846,7 +1031,8 @@ static int pca9450_i2c_probe(struct i2c_client *i2c) } dev_info(&i2c->dev, "%s probed.\n", - type == PCA9450_TYPE_PCA9450A ? "pca9450a" : "pca9450bc"); + type == PCA9450_TYPE_PCA9450A ? "pca9450a" : + (type == PCA9450_TYPE_PCA9451A ? "pca9451a" : "pca9450bc")); return 0; } @@ -864,6 +1050,10 @@ static const struct of_device_id pca9450_of_match[] = { .compatible = "nxp,pca9450c", .data = (void *)PCA9450_TYPE_PCA9450BC, }, + { + .compatible = "nxp,pca9451a", + .data = (void *)PCA9450_TYPE_PCA9451A, + }, { } }; MODULE_DEVICE_TABLE(of, pca9450_of_match); diff --git a/drivers/regulator/pf8x00-regulator.c b/drivers/regulator/pf8x00-regulator.c index b0781d9a1058..9fd8e0949b32 100644 --- a/drivers/regulator/pf8x00-regulator.c +++ b/drivers/regulator/pf8x00-regulator.c @@ -142,7 +142,7 @@ static const struct regmap_config pf8x00_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = PF8X00_PAGE_SELECT, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; /* VLDOx output: 1.5V to 5.0V */ diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index 46854602b3ea..7c04870442d3 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -680,7 +680,7 @@ static const struct regmap_config pfuze_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = PFUZE_NUMREGS - 1, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static int pfuze100_regulator_probe(struct i2c_client *client) diff --git a/drivers/regulator/rpi-panel-attiny-regulator.c b/drivers/regulator/rpi-panel-attiny-regulator.c index f52c3d47ecea..6c3b6bfac961 100644 --- a/drivers/regulator/rpi-panel-attiny-regulator.c +++ b/drivers/regulator/rpi-panel-attiny-regulator.c @@ -75,7 +75,7 @@ static const struct regmap_config attiny_regmap_config = { .val_bits = 8, .disable_locking = 1, .max_register = REG_WRITE_DATA_L, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static int attiny_set_port_state(struct attiny_lcd *state, int reg, u8 val) diff --git a/drivers/regulator/rtmv20-regulator.c b/drivers/regulator/rtmv20-regulator.c index dfd1522637e4..3d8d29f87b58 100644 --- a/drivers/regulator/rtmv20-regulator.c +++ b/drivers/regulator/rtmv20-regulator.c @@ -312,7 +312,7 @@ static bool rtmv20_is_volatile_reg(struct device *dev, unsigned int reg) static const struct regmap_config rtmv20_regmap_config = { .reg_bits = 8, .val_bits = 8, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .max_register = RTMV20_REG_LDMASK, .num_reg_defaults_raw = RTMV20_MAX_REGS, diff --git a/drivers/regulator/rtq2208-regulator.c b/drivers/regulator/rtq2208-regulator.c index 3079de41ef3f..b90e53d922d6 100644 --- a/drivers/regulator/rtq2208-regulator.c +++ b/drivers/regulator/rtq2208-regulator.c @@ -26,6 +26,7 @@ #define RTQ2208_REG_BUCK_H_CFG0 0xA2 #define RTQ2208_REG_LDO1_CFG 0xB1 #define RTQ2208_REG_LDO2_CFG 0xC1 +#define RTQ2208_REG_LDO_DVS_CTRL 0xD0 /* Mask */ #define RTQ2208_BUCK_NR_MTP_SEL_MASK GENMASK(7, 0) @@ -40,6 +41,10 @@ #define RTQ2208_EN_DIS_MASK BIT(0) #define RTQ2208_BUCK_RAMP_SEL_MASK GENMASK(2, 0) #define RTQ2208_HD_INT_MASK BIT(0) +#define RTQ2208_LDO1_DISCHG_EN_MASK BIT(4) +#define RTQ2208_LDO1_VOSEL_SD_MASK BIT(5) +#define RTQ2208_LDO2_DISCHG_EN_MASK BIT(6) +#define RTQ2208_LDO2_VOSEL_SD_MASK BIT(7) /* Size */ #define RTQ2208_VOUT_MAXNUM 256 @@ -317,23 +322,6 @@ static irqreturn_t rtq2208_irq_handler(int irqno, void *devid) return IRQ_HANDLED; } -#define RTQ2208_REGULATOR_INFO(_name, _base) \ -{ \ - .name = #_name, \ - .base = _base, \ -} -#define BUCK_RG_BASE(_id) RTQ2208_REG_BUCK_##_id##_CFG0 -#define BUCK_RG_SHIFT(_base, _shift) (_base + _shift) -#define LDO_RG_BASE(_id) RTQ2208_REG_LDO##_id##_CFG -#define LDO_RG_SHIFT(_base, _shift) (_base + _shift) -#define VSEL_SHIFT(_sel) (_sel ? 3 : 1) -#define MTP_SEL_MASK(_sel) RTQ2208_BUCK_EN_NR_MTP_SEL##_sel##_MASK - -static const struct linear_range rtq2208_vout_range[] = { - REGULATOR_LINEAR_RANGE(400000, 0, 180, 5000), - REGULATOR_LINEAR_RANGE(1310000, 181, 255, 10000), -}; - static int rtq2208_of_get_fixed_voltage(struct device *dev, struct of_regulator_match *rtq2208_ldo_match, int n_fixed) { @@ -372,6 +360,34 @@ static int rtq2208_of_get_fixed_voltage(struct device *dev, return 0; } + +#define BUCK_INFO(_name, _id) \ +{ \ + .name = _name, \ + .base = RTQ2208_REG_BUCK_##_id##_CFG0, \ + .enable_reg = BUCK_RG_SHIFT(RTQ2208_REG_BUCK_##_id##_CFG0, 2), \ + .dis_reg = RTQ2208_REG_BUCK_##_id##_CFG0, \ +} + +#define LDO_INFO(_name, _id) \ +{ \ + .name = _name, \ + .base = RTQ2208_REG_LDO##_id##_CFG, \ + .enable_reg = RTQ2208_REG_LDO##_id##_CFG, \ + .dis_mask = RTQ2208_LDO##_id##_DISCHG_EN_MASK, \ + .dis_on = RTQ2208_LDO##_id##_DISCHG_EN_MASK, \ + .vsel_mask = RTQ2208_LDO##_id##_VOSEL_SD_MASK, \ +} + +#define BUCK_RG_SHIFT(_base, _shift) (_base + _shift) +#define VSEL_SHIFT(_sel) (_sel ? 3 : 1) +#define MTP_SEL_MASK(_sel) RTQ2208_BUCK_EN_NR_MTP_SEL##_sel##_MASK + +static const struct linear_range rtq2208_vout_range[] = { + REGULATOR_LINEAR_RANGE(400000, 0, 180, 5000), + REGULATOR_LINEAR_RANGE(1310000, 181, 255, 10000), +}; + static void rtq2208_init_regulator_desc(struct rtq2208_regulator_desc *rdesc, int mtp_sel, int idx, struct of_regulator_match *rtq2208_ldo_match, int *ldo_idx) { @@ -379,17 +395,22 @@ static void rtq2208_init_regulator_desc(struct rtq2208_regulator_desc *rdesc, in static const struct { char *name; int base; + int enable_reg; + int dis_reg; + int dis_mask; + int dis_on; + int vsel_mask; } regulator_info[] = { - RTQ2208_REGULATOR_INFO(buck-b, BUCK_RG_BASE(B)), - RTQ2208_REGULATOR_INFO(buck-c, BUCK_RG_BASE(C)), - RTQ2208_REGULATOR_INFO(buck-d, BUCK_RG_BASE(D)), - RTQ2208_REGULATOR_INFO(buck-a, BUCK_RG_BASE(A)), - RTQ2208_REGULATOR_INFO(buck-f, BUCK_RG_BASE(F)), - RTQ2208_REGULATOR_INFO(buck-g, BUCK_RG_BASE(G)), - RTQ2208_REGULATOR_INFO(buck-h, BUCK_RG_BASE(H)), - RTQ2208_REGULATOR_INFO(buck-e, BUCK_RG_BASE(E)), - RTQ2208_REGULATOR_INFO(ldo2, LDO_RG_BASE(2)), - RTQ2208_REGULATOR_INFO(ldo1, LDO_RG_BASE(1)), + BUCK_INFO("buck-b", B), + BUCK_INFO("buck-c", C), + BUCK_INFO("buck-d", D), + BUCK_INFO("buck-a", A), + BUCK_INFO("buck-f", F), + BUCK_INFO("buck-g", G), + BUCK_INFO("buck-h", H), + BUCK_INFO("buck-e", E), + LDO_INFO("ldo2", 2), + LDO_INFO("ldo1", 1), }, *curr_info; curr_info = regulator_info + idx; @@ -401,15 +422,13 @@ static void rtq2208_init_regulator_desc(struct rtq2208_regulator_desc *rdesc, in desc->owner = THIS_MODULE; desc->type = REGULATOR_VOLTAGE; desc->enable_mask = mtp_sel ? MTP_SEL_MASK(1) : MTP_SEL_MASK(0); - desc->active_discharge_on = RTQ2208_EN_DIS_MASK; + desc->enable_reg = curr_info->enable_reg; desc->active_discharge_off = 0; - desc->active_discharge_mask = RTQ2208_EN_DIS_MASK; rdesc->mode_mask = RTQ2208_BUCK_NRMODE_MASK; if (idx >= RTQ2208_BUCK_B && idx <= RTQ2208_BUCK_E) { /* init buck desc */ - desc->enable_reg = BUCK_RG_SHIFT(curr_info->base, 2); desc->ops = &rtq2208_regulator_buck_ops; desc->vsel_reg = curr_info->base + VSEL_SHIFT(mtp_sel); desc->vsel_mask = RTQ2208_BUCK_NR_MTP_SEL_MASK; @@ -417,8 +436,10 @@ static void rtq2208_init_regulator_desc(struct rtq2208_regulator_desc *rdesc, in desc->linear_ranges = rtq2208_vout_range; desc->n_linear_ranges = ARRAY_SIZE(rtq2208_vout_range); desc->ramp_reg = BUCK_RG_SHIFT(curr_info->base, 5); - desc->active_discharge_reg = curr_info->base; desc->of_map_mode = rtq2208_of_map_mode; + desc->active_discharge_reg = curr_info->dis_reg; + desc->active_discharge_on = RTQ2208_EN_DIS_MASK; + desc->active_discharge_mask = RTQ2208_EN_DIS_MASK; rdesc->mode_reg = BUCK_RG_SHIFT(curr_info->base, 2); rdesc->suspend_config_reg = BUCK_RG_SHIFT(curr_info->base, 4); @@ -426,14 +447,11 @@ static void rtq2208_init_regulator_desc(struct rtq2208_regulator_desc *rdesc, in rdesc->suspend_mode_mask = RTQ2208_BUCK_STRMODE_MASK; } else { /* init ldo desc */ - desc->enable_reg = curr_info->base; - desc->ops = &rtq2208_regulator_ldo_ops; - desc->n_voltages = 1; - desc->active_discharge_reg = LDO_RG_SHIFT(curr_info->base, 2); - - rtq2208_ldo_match[*ldo_idx].name = desc->name; - rtq2208_ldo_match[*ldo_idx].driver_data = rdesc; - rtq2208_ldo_match[(*ldo_idx)++].desc = desc; + desc->active_discharge_reg = RTQ2208_REG_LDO_DVS_CTRL; + desc->active_discharge_on = curr_info->dis_on; + desc->active_discharge_mask = curr_info->dis_mask; + desc->vsel_reg = RTQ2208_REG_LDO_DVS_CTRL; + desc->vsel_mask = curr_info->vsel_mask; rdesc->suspend_config_reg = curr_info->base; rdesc->suspend_enable_mask = RTQ2208_LDO_EN_STR_MASK; @@ -457,6 +475,10 @@ static int rtq2208_parse_regulator_dt_data(int n_regulator, const unsigned int * return -ENOMEM; rtq2208_init_regulator_desc(rdesc[i], mtp_sel, idx, rtq2208_ldo_match, &ldo_idx); + + /* init ldo dvs ability */ + if (idx >= RTQ2208_LDO2) + rtq2208_ldo_match[idx - RTQ2208_LDO2].desc = &rdesc[i]->desc; } /* init ldo fixed_uV */ diff --git a/drivers/regulator/rtq6752-regulator.c b/drivers/regulator/rtq6752-regulator.c index 8176e5ab0683..d35d844eff3b 100644 --- a/drivers/regulator/rtq6752-regulator.c +++ b/drivers/regulator/rtq6752-regulator.c @@ -209,7 +209,7 @@ static const struct reg_default rtq6752_reg_defaults[] = { static const struct regmap_config rtq6752_regmap_config = { .reg_bits = 8, .val_bits = 8, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .max_register = RTQ6752_REG_FAULT, .reg_defaults = rtq6752_reg_defaults, .num_reg_defaults = ARRAY_SIZE(rtq6752_reg_defaults), diff --git a/drivers/regulator/sun20i-regulator.c b/drivers/regulator/sun20i-regulator.c new file mode 100644 index 000000000000..e09be44859e7 --- /dev/null +++ b/drivers/regulator/sun20i-regulator.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021-2022 Samuel Holland <samuel@sholland.org> +// + +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> + +#define SUN20I_SYS_LDO_CTRL_REG 0x150 + +struct sun20i_regulator_data { + const struct regulator_desc *descs; + unsigned int ndescs; +}; + +/* regulator_list_voltage_linear() modified for the non-integral uV_step. */ +static int sun20i_d1_system_ldo_list_voltage(struct regulator_dev *rdev, + unsigned int selector) +{ + const struct regulator_desc *desc = rdev->desc; + unsigned int fraction, uV; + + if (selector >= desc->n_voltages) + return -EINVAL; + + uV = desc->min_uV + (desc->uV_step * selector); + fraction = selector + (desc->min_uV % 4); + + if (uV > 1606667) + uV += 6667; + else + fraction++; + + /* Produce correctly-rounded absolute voltages. */ + return uV + (fraction / 3); +} + +static const struct regulator_ops sun20i_d1_system_ldo_ops = { + .list_voltage = sun20i_d1_system_ldo_list_voltage, + .map_voltage = regulator_map_voltage_ascend, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, +}; + +static const struct regulator_desc sun20i_d1_system_ldo_descs[] = { + { + .name = "ldoa", + .supply_name = "ldo-in", + .of_match = "ldoa", + .ops = &sun20i_d1_system_ldo_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .n_voltages = 32, + .min_uV = 1593333, + .uV_step = 13333, /* repeating */ + .vsel_reg = SUN20I_SYS_LDO_CTRL_REG, + .vsel_mask = GENMASK(7, 0), + }, + { + .name = "ldob", + .supply_name = "ldo-in", + .of_match = "ldob", + .ops = &sun20i_d1_system_ldo_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .n_voltages = 64, + .min_uV = 1166666, + .uV_step = 13333, /* repeating */ + .vsel_reg = SUN20I_SYS_LDO_CTRL_REG, + .vsel_mask = GENMASK(15, 8), + }, +}; + +static const struct sun20i_regulator_data sun20i_d1_system_ldos = { + .descs = sun20i_d1_system_ldo_descs, + .ndescs = ARRAY_SIZE(sun20i_d1_system_ldo_descs), +}; + +static struct regmap *sun20i_regulator_get_regmap(struct device *dev) +{ + struct regmap *regmap; + + /* + * First try the syscon interface. The system control device is not + * compatible with "syscon", so fall back to getting the regmap from + * its platform device. This is ugly, but required for devicetree + * backward compatibility. + */ + regmap = syscon_node_to_regmap(dev->parent->of_node); + if (!IS_ERR(regmap)) + return regmap; + + regmap = dev_get_regmap(dev->parent, NULL); + if (regmap) + return regmap; + + return ERR_PTR(-EPROBE_DEFER); +} + +static int sun20i_regulator_probe(struct platform_device *pdev) +{ + const struct sun20i_regulator_data *data; + struct device *dev = &pdev->dev; + struct regulator_config config; + struct regmap *regmap; + + data = of_device_get_match_data(dev); + if (!data) + return -EINVAL; + + regmap = sun20i_regulator_get_regmap(dev); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), "Failed to get regmap\n"); + + config = (struct regulator_config) { + .dev = dev, + .regmap = regmap, + }; + + for (unsigned int i = 0; i < data->ndescs; ++i) { + const struct regulator_desc *desc = &data->descs[i]; + struct regulator_dev *rdev; + + rdev = devm_regulator_register(dev, desc, &config); + if (IS_ERR(rdev)) + return PTR_ERR(rdev); + } + + return 0; +} + +static const struct of_device_id sun20i_regulator_of_match[] = { + { + .compatible = "allwinner,sun20i-d1-system-ldos", + .data = &sun20i_d1_system_ldos, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, sun20i_regulator_of_match); + +static struct platform_driver sun20i_regulator_driver = { + .probe = sun20i_regulator_probe, + .driver = { + .name = "sun20i-regulator", + .of_match_table = sun20i_regulator_of_match, + }, +}; +module_platform_driver(sun20i_regulator_driver); + +MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>"); +MODULE_DESCRIPTION("Allwinner D1 internal LDO driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c index 5199e0437388..3a384bf9d2c5 100644 --- a/drivers/regulator/tps51632-regulator.c +++ b/drivers/regulator/tps51632-regulator.c @@ -199,7 +199,7 @@ static const struct regmap_config tps51632_regmap_config = { .readable_reg = is_read_reg, .volatile_reg = is_volatile_reg, .max_register = TPS51632_MAX_REG - 1, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; #if defined(CONFIG_OF) diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index 32e1a05a57fd..be6a6702cbfa 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -275,7 +275,7 @@ static const struct regmap_config tps62360_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = REG_CHIPID, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static struct tps62360_regulator_platform_data * diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 9149d41fe65b..b7af5fe63e09 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -84,7 +84,6 @@ struct ad5933_state { struct i2c_client *client; - struct regulator *reg; struct clk *mclk; struct delayed_work work; struct mutex lock; /* Protect sensor state */ @@ -660,13 +659,6 @@ static void ad5933_work(struct work_struct *work) } } -static void ad5933_reg_disable(void *data) -{ - struct ad5933_state *st = data; - - regulator_disable(st->reg); -} - static int ad5933_probe(struct i2c_client *client) { const struct i2c_device_id *id = i2c_client_get_device_id(client); @@ -685,23 +677,9 @@ static int ad5933_probe(struct i2c_client *client) mutex_init(&st->lock); - st->reg = devm_regulator_get(&client->dev, "vdd"); - if (IS_ERR(st->reg)) - return PTR_ERR(st->reg); - - ret = regulator_enable(st->reg); - if (ret) { - dev_err(&client->dev, "Failed to enable specified VDD supply\n"); - return ret; - } - - ret = devm_add_action_or_reset(&client->dev, ad5933_reg_disable, st); - if (ret) - return ret; - - ret = regulator_get_voltage(st->reg); + ret = devm_regulator_get_enable_read_voltage(&client->dev, "vdd"); if (ret < 0) - return ret; + return dev_err_probe(&client->dev, ret, "failed to get vdd voltage\n"); st->vref_mv = ret / 1000; diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h index f1755163dd9f..8c0a33a2e9ce 100644 --- a/include/linux/mfd/axp20x.h +++ b/include/linux/mfd/axp20x.h @@ -19,6 +19,7 @@ enum axp20x_variants { AXP223_ID, AXP288_ID, AXP313A_ID, + AXP717_ID, AXP803_ID, AXP806_ID, AXP809_ID, @@ -104,15 +105,47 @@ enum axp20x_variants { #define AXP313A_ON_INDICATE 0x00 #define AXP313A_OUTPUT_CONTROL 0x10 -#define AXP313A_DCDC1_CONRTOL 0x13 -#define AXP313A_DCDC2_CONRTOL 0x14 -#define AXP313A_DCDC3_CONRTOL 0x15 -#define AXP313A_ALDO1_CONRTOL 0x16 -#define AXP313A_DLDO1_CONRTOL 0x17 +#define AXP313A_DCDC1_CONTROL 0x13 +#define AXP313A_DCDC2_CONTROL 0x14 +#define AXP313A_DCDC3_CONTROL 0x15 +#define AXP313A_ALDO1_CONTROL 0x16 +#define AXP313A_DLDO1_CONTROL 0x17 #define AXP313A_SHUTDOWN_CTRL 0x1a #define AXP313A_IRQ_EN 0x20 #define AXP313A_IRQ_STATE 0x21 +#define AXP717_ON_INDICATE 0x00 +#define AXP717_IRQ0_EN 0x40 +#define AXP717_IRQ1_EN 0x41 +#define AXP717_IRQ2_EN 0x42 +#define AXP717_IRQ3_EN 0x43 +#define AXP717_IRQ4_EN 0x44 +#define AXP717_IRQ0_STATE 0x48 +#define AXP717_IRQ1_STATE 0x49 +#define AXP717_IRQ2_STATE 0x4a +#define AXP717_IRQ3_STATE 0x4b +#define AXP717_IRQ4_STATE 0x4c +#define AXP717_DCDC_OUTPUT_CONTROL 0x80 +#define AXP717_DCDC1_CONTROL 0x83 +#define AXP717_DCDC2_CONTROL 0x84 +#define AXP717_DCDC3_CONTROL 0x85 +#define AXP717_DCDC4_CONTROL 0x86 +#define AXP717_LDO0_OUTPUT_CONTROL 0x90 +#define AXP717_LDO1_OUTPUT_CONTROL 0x91 +#define AXP717_ALDO1_CONTROL 0x93 +#define AXP717_ALDO2_CONTROL 0x94 +#define AXP717_ALDO3_CONTROL 0x95 +#define AXP717_ALDO4_CONTROL 0x96 +#define AXP717_BLDO1_CONTROL 0x97 +#define AXP717_BLDO2_CONTROL 0x98 +#define AXP717_BLDO3_CONTROL 0x99 +#define AXP717_BLDO4_CONTROL 0x9a +#define AXP717_CLDO1_CONTROL 0x9b +#define AXP717_CLDO2_CONTROL 0x9c +#define AXP717_CLDO3_CONTROL 0x9d +#define AXP717_CLDO4_CONTROL 0x9e +#define AXP717_CPUSLDO_CONTROL 0x9f + #define AXP806_STARTUP_SRC 0x00 #define AXP806_CHIP_ID 0x03 #define AXP806_PWR_OUT_CTRL1 0x10 @@ -434,6 +467,27 @@ enum { }; enum { + AXP717_DCDC1 = 0, + AXP717_DCDC2, + AXP717_DCDC3, + AXP717_DCDC4, + AXP717_ALDO1, + AXP717_ALDO2, + AXP717_ALDO3, + AXP717_ALDO4, + AXP717_BLDO1, + AXP717_BLDO2, + AXP717_BLDO3, + AXP717_BLDO4, + AXP717_CLDO1, + AXP717_CLDO2, + AXP717_CLDO3, + AXP717_CLDO4, + AXP717_CPUSLDO, + AXP717_REG_ID_MAX, +}; + +enum { AXP806_DCDCA = 0, AXP806_DCDCB, AXP806_DCDCC, @@ -732,6 +786,40 @@ enum axp313a_irqs { AXP313A_IRQ_PEK_RIS_EDGE, }; +enum axp717_irqs { + AXP717_IRQ_VBUS_FAULT, + AXP717_IRQ_VBUS_OVER_V, + AXP717_IRQ_BOOST_OVER_V, + AXP717_IRQ_GAUGE_NEW_SOC = 4, + AXP717_IRQ_SOC_DROP_LVL1 = 6, + AXP717_IRQ_SOC_DROP_LVL2, + AXP717_IRQ_PEK_RIS_EDGE, + AXP717_IRQ_PEK_FAL_EDGE, + AXP717_IRQ_PEK_LONG, + AXP717_IRQ_PEK_SHORT, + AXP717_IRQ_BATT_REMOVAL, + AXP717_IRQ_BATT_PLUGIN, + AXP717_IRQ_VBUS_REMOVAL, + AXP717_IRQ_VBUS_PLUGIN, + AXP717_IRQ_BATT_OVER_V, + AXP717_IRQ_CHARG_TIMER, + AXP717_IRQ_DIE_TEMP_HIGH, + AXP717_IRQ_CHARG, + AXP717_IRQ_CHARG_DONE, + AXP717_IRQ_BATT_OVER_CURR, + AXP717_IRQ_LDO_OVER_CURR, + AXP717_IRQ_WDOG_EXPIRE, + AXP717_IRQ_BATT_ACT_TEMP_LOW, + AXP717_IRQ_BATT_ACT_TEMP_HIGH, + AXP717_IRQ_BATT_CHG_TEMP_LOW, + AXP717_IRQ_BATT_CHG_TEMP_HIGH, + AXP717_IRQ_BATT_QUIT_TEMP_HIGH, + AXP717_IRQ_BC_USB_CHNG = 30, + AXP717_IRQ_BC_USB_DONE, + AXP717_IRQ_TYPEC_PLUGIN = 37, + AXP717_IRQ_TYPEC_REMOVE, +}; + enum axp803_irqs { AXP803_IRQ_ACIN_OVER_V = 1, AXP803_IRQ_ACIN_PLUGIN, diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index ed180ca419da..59d0b9a79e6e 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -164,6 +164,7 @@ struct regulator *__must_check devm_regulator_get_optional(struct device *dev, const char *id); int devm_regulator_get_enable(struct device *dev, const char *id); int devm_regulator_get_enable_optional(struct device *dev, const char *id); +int devm_regulator_get_enable_read_voltage(struct device *dev, const char *id); void regulator_put(struct regulator *regulator); void devm_regulator_put(struct regulator *regulator); @@ -329,6 +330,12 @@ static inline int devm_regulator_get_enable_optional(struct device *dev, return 0; } +static inline int devm_regulator_get_enable_read_voltage(struct device *dev, + const char *id) +{ + return -ENODEV; +} + static inline struct regulator *__must_check regulator_get_optional(struct device *dev, const char *id) { diff --git a/include/linux/regulator/pca9450.h b/include/linux/regulator/pca9450.h index 505c908dbb81..243633c8dceb 100644 --- a/include/linux/regulator/pca9450.h +++ b/include/linux/regulator/pca9450.h @@ -9,6 +9,7 @@ enum pca9450_chip_type { PCA9450_TYPE_PCA9450A = 0, PCA9450_TYPE_PCA9450BC, + PCA9450_TYPE_PCA9451A, PCA9450_TYPE_AMOUNT, }; |