regulator: Updates for v6.13

This was a quite quiet release for regulators on the drivers front, but
 we do have two small but useful core improvements:
 
  - Improve handling of cases where DT platforms specify both DT and
    init_data based configuration for a single regulator.
  - A helper of_regulator_get_optional() to simplify writing generic
    bindings for regulator consumers in subsystems.
 
 There's also some YAML conversions for the DT bindings which are a big
 part of the diffstat.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmc7O2AACgkQJNaLcl1U
 h9C3Zwf/ZfnNpSjd6hWtsPQROmOXNvVJDvXeyC6ZWQPjBU31VAFt+6rtk/xMVTIp
 cxaHG3PzeYkIk1VTm6yO5m3/kalIt4ECsJf62sfNNoltRcl0sJExt6ewKF6QjCN7
 9OOAANJIWliApPj1ZQ+IIvddsF2Q0IqyioDLX+suGdNmNaZx4KnLP7dIAcluj3/d
 w+pC/CbrrUy2ScFgxLUm3dH16nV8hYm/F9f5Dsob9AV7IpMN0suMwbAd6uq2+KZT
 lLUw+kpkASetifhAfCjUGj8PIF+lMwW4WsuWgu4I0qiA9+FRDEyb6f0LQahs3d2G
 NO98rrcS9kVYaJ1z83KuMHeYBI44sQ==
 =AihX
 -----END PGP SIGNATURE-----

Merge tag 'regulator-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator

Pull regulator updates from Mark Brown:
 "This was a quite quiet release for regulators on the drivers front,
  but we do have two small but useful core improvements:

   - Improve handling of cases where DT platforms specify both DT and
     init_data based configuration for a single regulator.

   - A helper of_regulator_get_optional() to simplify writing generic
     bindings for regulator consumers in subsystems.

  There's also some YAML conversions for the DT bindings which are a big
  part of the diffstat"

* tag 'regulator-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator:
  regulator: dt-bindings: qcom,rpmh: Correct PM8550VE supplies
  regulator: Switch back to struct platform_driver::remove()
  regulator: doc: remove documentation comment for regulator_init
  regulator: doc: add missing documentation for init_cb
  regulator: rk808: Restrict DVS GPIOs to the RK808 variant only
  regulator: rk808: Use dev_err_probe() in the probe path
  regulator: rk808: Perform trivial code cleanups
  regulator: dt-bindings: qcom,qca6390-pmu: add more properties for wcn6855
  regulator: dt-bindings: lltc,ltc3676: convert to YAML
  regulator: core: Use fsleep() to get best sleep mechanism
  regulator: core: remove machine init callback from config
  regulator: core: add callback to perform runtime init
  regulator: core: do not silently ignore provided init_data
  regulator: max5970: Drop unused structs
  regulator: dt-bindings: vctrl-regulator: convert to YAML
  regulator: qcom-smd: make smd_vreg_rpm static
  regulator: Call of_node_put() only once in rzg2l_usb_vbus_regulator_probe()
  regulator: isl6271a: Drop explicit initialization of struct i2c_device_id::driver_data to 0
  regulator: Add devres version of of_regulator_get_optional()
  regulator: Add of_regulator_get_optional() for pure DT regulator lookup
This commit is contained in:
Linus Torvalds 2024-11-20 12:18:50 -08:00
commit 4bd37a902a
27 changed files with 490 additions and 309 deletions

View File

@ -0,0 +1,167 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/lltc,ltc3676.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Linear Technology LTC3676 8-output regulators
maintainers:
- Tim Harvey <tharvey@gateworks.com>
description: |
LTC3676 contains eight regulators, 4 switching SW1..SW4 and four LDO1..4 .
properties:
compatible:
const: lltc,ltc3676
reg:
maxItems: 1
interrupts:
maxItems: 1
regulators:
type: object
additionalProperties: false
description: |
List of regulators provided by this controller, must be named
after their hardware counterparts (SW|LDO)[1-4].
patternProperties:
"^(sw[1-4]|ldo[24])$":
type: object
unevaluatedProperties: false
$ref: regulator.yaml#
description:
Properties for single SW or LDO regulator. Regulators SW1..SW4 can
regulate the feedback reference from 412.5mV to 800mV in 12.5 mV
steps. The output voltage thus ranges between 0.4125 * (1 + R1/R2) V
and 0.8 * (1 + R1/R2) V.
Regulators LDO1, LDO2, LDO4 have a fixed 0.725 V reference and thus
output 0.725 * (1 + R1/R2) V.
The LDO1 standby regulator can not be disabled and thus should have
the regulator-always-on property set.
properties:
lltc,fb-voltage-divider:
description:
An array of two integers containing the resistor values
R1 and R2 of the feedback voltage divider in ohms.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 2
maxItems: 2
required:
- lltc,fb-voltage-divider
properties:
ldo1:
type: object
unevaluatedProperties: false
$ref: regulator.yaml#
description:
The LDO1 standby regulator can not be disabled and thus should
have the regulator-always-on property set. See patternProperties
description above for the rest of the details.
properties:
lltc,fb-voltage-divider:
description:
An array of two integers containing the resistor values
R1 and R2 of the feedback voltage divider in ohms.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 2
maxItems: 2
required:
- lltc,fb-voltage-divider
- regulator-always-on
ldo3:
type: object
unevaluatedProperties: false
$ref: regulator.yaml#
description:
The LDO3 regulator is fixed to 1.8 V. See patternProperties
description above for the rest of the details.
required:
- compatible
- reg
- regulators
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@3c {
compatible = "lltc,ltc3676";
reg = <0x3c>;
regulators {
sw1_reg: sw1 {
regulator-min-microvolt = <674400>;
regulator-max-microvolt = <1308000>;
lltc,fb-voltage-divider = <127000 200000>;
regulator-ramp-delay = <7000>;
regulator-boot-on;
regulator-always-on;
};
sw2_reg: sw2 {
regulator-min-microvolt = <1033310>;
regulator-max-microvolt = <200400>;
lltc,fb-voltage-divider = <301000 200000>;
regulator-ramp-delay = <7000>;
regulator-boot-on;
regulator-always-on;
};
sw3_reg: sw3 {
regulator-min-microvolt = <674400>;
regulator-max-microvolt = <130800>;
lltc,fb-voltage-divider = <127000 200000>;
regulator-ramp-delay = <7000>;
regulator-boot-on;
regulator-always-on;
};
sw4_reg: sw4 {
regulator-min-microvolt = <868310>;
regulator-max-microvolt = <168400>;
lltc,fb-voltage-divider = <221000 200000>;
regulator-ramp-delay = <7000>;
regulator-boot-on;
regulator-always-on;
};
ldo2_reg: ldo2 {
regulator-min-microvolt = <2490375>;
regulator-max-microvolt = <2490375>;
lltc,fb-voltage-divider = <487000 200000>;
regulator-boot-on;
regulator-always-on;
};
ldo3_reg: ldo3 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
};
ldo4_reg: ldo4 {
regulator-min-microvolt = <3023250>;
regulator-max-microvolt = <3023250>;
lltc,fb-voltage-divider = <634000 200000>;
regulator-boot-on;
regulator-always-on;
};
};
};
};

View File

@ -1,94 +0,0 @@
Linear Technology LTC3676 8-output regulators
Required properties:
- compatible: "lltc,ltc3676"
- reg: I2C slave address
Required child node:
- regulators: Contains eight regulator child nodes sw1, sw2, sw3, sw4,
ldo1, ldo2, ldo3, and ldo4, specifying the initialization data as
documented in Documentation/devicetree/bindings/regulator/regulator.txt.
Each regulator is defined using the standard binding for regulators. The
nodes for sw1, sw2, sw3, sw4, ldo1, ldo2 and ldo4 additionally need to specify
the resistor values of their external feedback voltage dividers:
Required properties (not on ldo3):
- lltc,fb-voltage-divider: An array of two integers containing the resistor
values R1 and R2 of the feedback voltage divider in ohms.
Regulators sw1, sw2, sw3, sw4 can regulate the feedback reference from:
412.5mV to 800mV in 12.5 mV steps. The output voltage thus ranges between
0.4125 * (1 + R1/R2) V and 0.8 * (1 + R1/R2) V.
Regulators ldo1, ldo2, and ldo4 have a fixed 0.725 V reference and thus output
0.725 * (1 + R1/R2) V. The ldo3 regulator is fixed to 1.8 V. The ldo1 standby
regulator can not be disabled and thus should have the regulator-always-on
property set.
Example:
ltc3676: pmic@3c {
compatible = "lltc,ltc3676";
reg = <0x3c>;
regulators {
sw1_reg: sw1 {
regulator-min-microvolt = <674400>;
regulator-max-microvolt = <1308000>;
lltc,fb-voltage-divider = <127000 200000>;
regulator-ramp-delay = <7000>;
regulator-boot-on;
regulator-always-on;
};
sw2_reg: sw2 {
regulator-min-microvolt = <1033310>;
regulator-max-microvolt = <200400>;
lltc,fb-voltage-divider = <301000 200000>;
regulator-ramp-delay = <7000>;
regulator-boot-on;
regulator-always-on;
};
sw3_reg: sw3 {
regulator-min-microvolt = <674400>;
regulator-max-microvolt = <130800>;
lltc,fb-voltage-divider = <127000 200000>;
regulator-ramp-delay = <7000>;
regulator-boot-on;
regulator-always-on;
};
sw4_reg: sw4 {
regulator-min-microvolt = <868310>;
regulator-max-microvolt = <168400>;
lltc,fb-voltage-divider = <221000 200000>;
regulator-ramp-delay = <7000>;
regulator-boot-on;
regulator-always-on;
};
ldo2_reg: ldo2 {
regulator-min-microvolt = <2490375>;
regulator-max-microvolt = <2490375>;
lltc,fb-voltage-divider = <487000 200000>;
regulator-boot-on;
regulator-always-on;
};
ldo3_reg: ldo3 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
};
ldo4_reg: ldo4 {
regulator-min-microvolt = <3023250>;
regulator-max-microvolt = <3023250>;
lltc,fb-voltage-divider = <634000 200000>;
regulator-boot-on;
regulator-always-on;
};
};
};

View File

@ -33,6 +33,12 @@ properties:
vddpmu-supply:
description: VDD_PMU supply regulator handle
vddpmumx-supply:
description: VDD_PMU_MX supply regulator handle
vddpmucx-supply:
description: VDD_PMU_CX supply regulator handle
vddio1p2-supply:
description: VDD_IO_1P2 supply regulator handle
@ -72,6 +78,10 @@ properties:
maxItems: 1
description: GPIO line indicating the state of the clock supply to the BT module
xo-clk-gpios:
maxItems: 1
description: GPIO line allowing to select the XO clock configuration for the module
clocks:
maxItems: 1
description: Reference clock handle
@ -119,6 +129,8 @@ allOf:
- vddio-supply
- vddaon-supply
- vddpmu-supply
- vddpmumx-supply
- vddpmucx-supply
- vddrfa0p95-supply
- vddrfa1p3-supply
- vddrfa1p9-supply

View File

@ -349,7 +349,6 @@ allOf:
properties:
compatible:
enum:
- qcom,pm8550ve-rpmh-regulators
- qcom,pm8550vs-rpmh-regulators
then:
patternProperties:
@ -385,6 +384,7 @@ allOf:
compatible:
enum:
- qcom,pmc8380-rpmh-regulators
- qcom,pm8550ve-rpmh-regulators
then:
patternProperties:
"^vdd-l[1-3]-supply$": true

View File

@ -0,0 +1,80 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/vctrl-regulator.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Voltage controlled regulators
maintainers:
- Heiko Stuebner <heiko@sntech.de>
allOf:
- $ref: regulator.yaml#
properties:
compatible:
const: vctrl-regulator
ctrl-supply:
description: Regulator supplying the control voltage
ctrl-voltage-range:
description:
Array of two integer values describing the range (min/max) of the
control voltage. The values specify the control voltage needed to
generate the corresponding regulator-min/max-microvolt output
voltage.
minItems: 2
maxItems: 2
$ref: /schemas/types.yaml#/definitions/uint32-array
min-slew-down-rate:
description:
Describes how slowly the regulator voltage will decay down in the
worst case (lightest expected load). Specified in uV / us (like
main regulator ramp rate). This value is required when
ovp-threshold-percent is specified.
$ref: /schemas/types.yaml#/definitions/uint32
ovp-threshold-percent:
description:
Overvoltage protection (OVP) threshold of the regulator in percent.
Some regulators have an OVP circuitry which shuts down the regulator
when the actual output voltage deviates beyond a certain margin from
the expected value for a given control voltage. On larger voltage
decreases this can occur undesiredly since the output voltage does
not adjust immediately to changes in the control voltage. To avoid
this situation the vctrl driver breaks down larger voltage decreases
into multiple steps, where each step is within the OVP threshold.
minimum: 0
maximum: 100
unevaluatedProperties: false
dependencies:
ovp-threshold-percent: [ min-slew-down-rate ]
required:
- compatible
- ctrl-supply
- ctrl-voltage-range
- regulator-min-microvolt
- regulator-max-microvolt
examples:
- |
vctrl-reg {
compatible = "vctrl-regulator";
regulator-name = "vctrl_reg";
ctrl-supply = <&ctrl_reg>;
ctrl-voltage-range = <200000 500000>;
min-slew-down-rate = <225>;
ovp-threshold-percent = <16>;
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1500000>;
};
...

View File

@ -1,49 +0,0 @@
Bindings for Voltage controlled regulators
==========================================
Required properties:
--------------------
- compatible : must be "vctrl-regulator".
- regulator-min-microvolt : smallest voltage consumers may set
- regulator-max-microvolt : largest voltage consumers may set
- ctrl-supply : The regulator supplying the control voltage.
- ctrl-voltage-range : an array of two integer values describing the range
(min/max) of the control voltage. The values specify
the control voltage needed to generate the corresponding
regulator-min/max-microvolt output voltage.
Optional properties:
--------------------
- ovp-threshold-percent : overvoltage protection (OVP) threshold of the
regulator in percent. Some regulators have an OVP
circuitry which shuts down the regulator when the
actual output voltage deviates beyond a certain
margin from the expected value for a given control
voltage. On larger voltage decreases this can occur
undesiredly since the output voltage does not adjust
immediately to changes in the control voltage. To
avoid this situation the vctrl driver breaks down
larger voltage decreases into multiple steps, where
each step is within the OVP threshold.
- min-slew-down-rate : Describes how slowly the regulator voltage will decay
down in the worst case (lightest expected load).
Specified in uV / us (like main regulator ramp rate).
This value is required when ovp-threshold-percent is
specified.
Example:
vctrl-reg {
compatible = "vctrl-regulator";
regulator-name = "vctrl_reg";
ctrl-supply = <&ctrl_reg>;
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1500000>;
ctrl-voltage-range = <200000 500000>;
min-slew-down-rate = <225>;
ovp-threshold-percent = <16>;
};

View File

@ -375,18 +375,18 @@ static int madera_ldo1_probe(struct platform_device *pdev)
static struct platform_driver arizona_ldo1_driver = {
.probe = arizona_ldo1_probe,
.remove_new = arizona_ldo1_remove,
.driver = {
.name = "arizona-ldo1",
.remove = arizona_ldo1_remove,
.driver = {
.name = "arizona-ldo1",
.probe_type = PROBE_FORCE_SYNCHRONOUS,
},
};
static struct platform_driver madera_ldo1_driver = {
.probe = madera_ldo1_probe,
.remove_new = arizona_ldo1_remove,
.driver = {
.name = "madera-ldo1",
.remove = arizona_ldo1_remove,
.driver = {
.name = "madera-ldo1",
.probe_type = PROBE_FORCE_SYNCHRONOUS,
},
};

View File

@ -356,7 +356,7 @@ static struct platform_driver bd9571mwv_regulator_driver = {
.pm = DEV_PM_OPS,
},
.probe = bd9571mwv_regulator_probe,
.remove_new = bd9571mwv_regulator_remove,
.remove = bd9571mwv_regulator_remove,
.id_table = bd9571mwv_regulator_id_table,
};
module_platform_driver(bd9571mwv_regulator_driver);

View File

@ -1959,8 +1959,8 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
regulator_supply_alias(&dev, &supply);
/* first do a dt based lookup */
if (dev && dev->of_node) {
r = of_regulator_dev_lookup(dev, supply);
if (dev_of_node(dev)) {
r = of_regulator_dev_lookup(dev, dev_of_node(dev), supply);
if (!IS_ERR(r))
return r;
if (PTR_ERR(r) == -EPROBE_DEFER)
@ -2642,45 +2642,6 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
return 0;
}
/**
* _regulator_delay_helper - a delay helper function
* @delay: time to delay in microseconds
*
* Delay for the requested amount of time as per the guidelines in:
*
* Documentation/timers/timers-howto.rst
*
* The assumption here is that these regulator operations will never used in
* atomic context and therefore sleeping functions can be used.
*/
static void _regulator_delay_helper(unsigned int delay)
{
unsigned int ms = delay / 1000;
unsigned int us = delay % 1000;
if (ms > 0) {
/*
* For small enough values, handle super-millisecond
* delays in the usleep_range() call below.
*/
if (ms < 20)
us += ms * 1000;
else
msleep(ms);
}
/*
* Give the scheduler some room to coalesce with any other
* wakeup sources. For delays shorter than 10 us, don't even
* bother setting up high-resolution timers and just busy-
* loop.
*/
if (us >= 10)
usleep_range(us, us + 100);
else
udelay(us);
}
/**
* _regulator_check_status_enabled - check if regulator status can be
* interpreted as "regulator is enabled"
@ -2733,7 +2694,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
s64 remaining = ktime_us_delta(end, ktime_get_boottime());
if (remaining > 0)
_regulator_delay_helper(remaining);
fsleep(remaining);
}
if (rdev->ena_pin) {
@ -2767,7 +2728,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
int time_remaining = delay;
while (time_remaining > 0) {
_regulator_delay_helper(rdev->desc->poll_enabled_time);
fsleep(rdev->desc->poll_enabled_time);
if (rdev->desc->ops->get_status) {
ret = _regulator_check_status_enabled(rdev);
@ -2786,7 +2747,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
return -ETIMEDOUT;
}
} else {
_regulator_delay_helper(delay);
fsleep(delay);
}
trace_regulator_enable_complete(rdev_get_name(rdev));
@ -3730,7 +3691,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
}
/* Insert any necessary delays */
_regulator_delay_helper(delay);
fsleep(delay);
if (best_val >= 0) {
unsigned long data = best_val;
@ -5681,32 +5642,43 @@ regulator_register(struct device *dev,
goto clean;
}
init_data = regulator_of_get_init_data(dev, regulator_desc, config,
&rdev->dev.of_node);
if (config->init_data) {
/*
* Providing of_match means the framework is expected to parse
* DT to get the init_data. This would conflict with provided
* init_data, if set. Warn if it happens.
*/
if (regulator_desc->of_match)
dev_warn(dev, "Using provided init data - OF match ignored\n");
/*
* Sometimes not all resources are probed already so we need to take
* that into account. This happens most the time if the ena_gpiod comes
* from a gpio extender or something else.
*/
if (PTR_ERR(init_data) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto clean;
}
/*
* We need to keep track of any GPIO descriptor coming from the
* device tree until we have handled it over to the core. If the
* config that was passed in to this function DOES NOT contain
* a descriptor, and the config after this call DOES contain
* a descriptor, we definitely got one from parsing the device
* tree.
*/
if (!cfg->ena_gpiod && config->ena_gpiod)
dangling_of_gpiod = true;
if (!init_data) {
init_data = config->init_data;
rdev->dev.of_node = of_node_get(config->of_node);
} else {
init_data = regulator_of_get_init_data(dev, regulator_desc,
config,
&rdev->dev.of_node);
/*
* Sometimes not all resources are probed already so we need to
* take that into account. This happens most the time if the
* ena_gpiod comes from a gpio extender or something else.
*/
if (PTR_ERR(init_data) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto clean;
}
/*
* We need to keep track of any GPIO descriptor coming from the
* device tree until we have handled it over to the core. If the
* config that was passed in to this function DOES NOT contain a
* descriptor, and the config after this call DOES contain a
* descriptor, we definitely got one from parsing the device
* tree.
*/
if (!cfg->ena_gpiod && config->ena_gpiod)
dangling_of_gpiod = true;
}
ww_mutex_init(&rdev->mutex, &regulator_ww_class);
@ -5747,6 +5719,12 @@ regulator_register(struct device *dev,
goto wash;
}
if (regulator_desc->init_cb) {
ret = regulator_desc->init_cb(rdev, config);
if (ret < 0)
goto wash;
}
if ((rdev->supply_name && !rdev->supply) &&
(rdev->constraints->always_on ||
rdev->constraints->boot_on)) {
@ -5758,13 +5736,6 @@ regulator_register(struct device *dev,
resolved_early = true;
}
/* perform any regulator specific init */
if (init_data && init_data->regulator_init) {
ret = init_data->regulator_init(rdev->reg_data);
if (ret < 0)
goto wash;
}
if (config->ena_gpiod) {
ret = regulator_ena_gpio_request(rdev, config);
if (ret != 0) {

View File

@ -480,7 +480,7 @@ static struct platform_driver db8500_regulator_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe = db8500_regulator_probe,
.remove_new = db8500_regulator_remove,
.remove = db8500_regulator_remove,
};
static int __init db8500_regulator_init(void)

View File

@ -749,3 +749,42 @@ void *devm_regulator_irq_helper(struct device *dev,
return ptr;
}
EXPORT_SYMBOL_GPL(devm_regulator_irq_helper);
#if IS_ENABLED(CONFIG_OF)
static struct regulator *_devm_of_regulator_get(struct device *dev, struct device_node *node,
const char *id, int get_type)
{
struct regulator **ptr, *regulator;
ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
regulator = _of_regulator_get(dev, node, id, get_type);
if (!IS_ERR(regulator)) {
*ptr = regulator;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return regulator;
}
/**
* devm_of_regulator_get_optional - Resource managed of_regulator_get_optional()
* @dev: device used for dev_printk() messages and resource lifetime management
* @node: device node for regulator "consumer"
* @id: supply name or regulator ID.
*
* Managed regulator_get_optional(). Regulators returned from this
* function are automatically regulator_put() on driver detach. See
* of_regulator_get_optional() for more information.
*/
struct regulator *devm_of_regulator_get_optional(struct device *dev, struct device_node *node,
const char *id)
{
return _devm_of_regulator_get(dev, node, id, OPTIONAL_GET);
}
EXPORT_SYMBOL_GPL(devm_of_regulator_get_optional);
#endif

View File

@ -65,14 +65,25 @@ static inline struct regulator_dev *dev_to_rdev(struct device *dev)
return container_of(dev, struct regulator_dev, dev);
}
enum regulator_get_type {
NORMAL_GET,
EXCLUSIVE_GET,
OPTIONAL_GET,
MAX_GET_TYPE
};
#ifdef CONFIG_OF
struct regulator_dev *of_regulator_dev_lookup(struct device *dev,
struct device_node *np,
const char *supply);
struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
const struct regulator_desc *desc,
struct regulator_config *config,
struct device_node **node);
struct regulator *_of_regulator_get(struct device *dev, struct device_node *node,
const char *id, enum regulator_get_type get_type);
struct regulator_dev *of_parse_coupled_regulator(struct regulator_dev *rdev,
int index);
@ -82,6 +93,7 @@ bool of_check_coupling_data(struct regulator_dev *rdev);
#else
static inline struct regulator_dev *of_regulator_dev_lookup(struct device *dev,
struct device_node *np,
const char *supply)
{
return ERR_PTR(-ENODEV);
@ -114,12 +126,6 @@ static inline bool of_check_coupling_data(struct regulator_dev *rdev)
}
#endif
enum regulator_get_type {
NORMAL_GET,
EXCLUSIVE_GET,
OPTIONAL_GET,
MAX_GET_TYPE
};
int _regulator_get_common_check(struct device *dev, const char *id,
enum regulator_get_type get_type);

View File

@ -138,8 +138,8 @@ static int isl6271a_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id isl6271a_id[] = {
{.name = "isl6271a", 0 },
{ },
{ .name = "isl6271a", },
{ }
};
MODULE_DEVICE_TABLE(i2c, isl6271a_id);

View File

@ -485,7 +485,7 @@ static int max597x_irq_handler(int irq, struct regulator_irq_data *rid,
}
static int max597x_adc_range(struct regmap *regmap, const int ch,
u32 *irng, u32 *mon_rng)
int *irng, int *mon_rng)
{
unsigned int reg;
int ret;
@ -552,7 +552,6 @@ static int max597x_setup_irq(struct device *dev,
static int max597x_regulator_probe(struct platform_device *pdev)
{
struct max5970_data *max597x;
struct regmap *regmap = dev_get_regmap(pdev->dev.parent, NULL);
struct max5970_regulator *data;
struct i2c_client *i2c = to_i2c_client(pdev->dev.parent);
@ -566,26 +565,18 @@ static int max597x_regulator_probe(struct platform_device *pdev)
if (!regmap)
return -EPROBE_DEFER;
max597x = devm_kzalloc(&i2c->dev, sizeof(struct max5970_data), GFP_KERNEL);
if (!max597x)
return -ENOMEM;
rdevs = devm_kcalloc(&i2c->dev, MAX5970_NUM_SWITCHES, sizeof(struct regulator_dev *),
GFP_KERNEL);
if (!rdevs)
return -ENOMEM;
i2c_set_clientdata(i2c, max597x);
if (of_device_is_compatible(i2c->dev.of_node, "maxim,max5978"))
max597x->num_switches = MAX5978_NUM_SWITCHES;
num_switches = MAX5978_NUM_SWITCHES;
else if (of_device_is_compatible(i2c->dev.of_node, "maxim,max5970"))
max597x->num_switches = MAX5970_NUM_SWITCHES;
num_switches = MAX5970_NUM_SWITCHES;
else
return -ENODEV;
num_switches = max597x->num_switches;
for (i = 0; i < num_switches; i++) {
data =
devm_kzalloc(&i2c->dev, sizeof(struct max5970_regulator),
@ -596,13 +587,10 @@ static int max597x_regulator_probe(struct platform_device *pdev)
data->num_switches = num_switches;
data->regmap = regmap;
ret = max597x_adc_range(regmap, i, &max597x->irng[i], &max597x->mon_rng[i]);
ret = max597x_adc_range(regmap, i, &data->irng, &data->mon_rng);
if (ret < 0)
return ret;
data->irng = max597x->irng[i];
data->mon_rng = max597x->mon_rng[i];
config.dev = &i2c->dev;
config.driver_data = (void *)data;
config.regmap = data->regmap;
@ -614,7 +602,6 @@ static int max597x_regulator_probe(struct platform_device *pdev)
return PTR_ERR(rdev);
}
rdevs[i] = rdev;
max597x->shunt_micro_ohms[i] = data->shunt_micro_ohms;
}
if (IS_REACHABLE(CONFIG_HWMON)) {

View File

@ -588,7 +588,8 @@ static struct device_node *of_get_child_regulator(struct device_node *parent,
/**
* of_get_regulator - get a regulator device node based on supply name
* @dev: Device pointer for the consumer (of regulator) device
* @dev: Device pointer for dev_printk() messages
* @node: Device node pointer for supply property lookup
* @supply: regulator supply name
*
* Extract the regulator device node corresponding to the supply name.
@ -596,15 +597,16 @@ static struct device_node *of_get_child_regulator(struct device_node *parent,
* Return: Pointer to the &struct device_node corresponding to the regulator
* if found, or %NULL if not found.
*/
static struct device_node *of_get_regulator(struct device *dev, const char *supply)
static struct device_node *of_get_regulator(struct device *dev, struct device_node *node,
const char *supply)
{
struct device_node *regnode = NULL;
char prop_name[64]; /* 64 is max size of property name */
dev_dbg(dev, "Looking up %s-supply from device tree\n", supply);
dev_dbg(dev, "Looking up %s-supply from device node %pOF\n", supply, node);
snprintf(prop_name, 64, "%s-supply", supply);
regnode = of_parse_phandle(dev->of_node, prop_name, 0);
regnode = of_parse_phandle(node, prop_name, 0);
if (regnode)
return regnode;
@ -628,6 +630,7 @@ static struct regulator_dev *of_find_regulator_by_node(struct device_node *np)
/**
* of_regulator_dev_lookup - lookup a regulator device with device tree only
* @dev: Device pointer for regulator supply lookup.
* @np: Device node pointer for regulator supply lookup.
* @supply: Supply name or regulator ID.
*
* Return: Pointer to the &struct regulator_dev on success, or ERR_PTR()
@ -642,13 +645,13 @@ static struct regulator_dev *of_find_regulator_by_node(struct device_node *np)
* * -%ENODEV if lookup fails permanently.
* * -%EPROBE_DEFER if lookup could succeed in the future.
*/
struct regulator_dev *of_regulator_dev_lookup(struct device *dev,
struct regulator_dev *of_regulator_dev_lookup(struct device *dev, struct device_node *np,
const char *supply)
{
struct regulator_dev *r;
struct device_node *node;
node = of_get_regulator(dev, supply);
node = of_get_regulator(dev, np, supply);
if (node) {
r = of_find_regulator_by_node(node);
of_node_put(node);
@ -665,6 +668,42 @@ struct regulator_dev *of_regulator_dev_lookup(struct device *dev,
return ERR_PTR(-ENODEV);
}
struct regulator *_of_regulator_get(struct device *dev, struct device_node *node,
const char *id, enum regulator_get_type get_type)
{
struct regulator_dev *r;
int ret;
ret = _regulator_get_common_check(dev, id, get_type);
if (ret)
return ERR_PTR(ret);
r = of_regulator_dev_lookup(dev, node, id);
return _regulator_get_common(r, dev, id, get_type);
}
/**
* of_regulator_get_optional - get optional regulator via device tree lookup
* @dev: device used for dev_printk() messages
* @node: device node for regulator "consumer"
* @id: Supply name
*
* Return: pointer to struct regulator corresponding to the regulator producer,
* or PTR_ERR() encoded error number.
*
* This is intended for use by consumers that want to get a regulator
* supply directly from a device node, and can and want to deal with
* absence of such supplies. This will _not_ consider supply aliases.
* See regulator_dev_lookup().
*/
struct regulator *of_regulator_get_optional(struct device *dev,
struct device_node *node,
const char *id)
{
return _of_regulator_get(dev, node, id, OPTIONAL_GET);
}
EXPORT_SYMBOL_GPL(of_regulator_get_optional);
/*
* Returns number of regulators coupled with rdev.
*/

View File

@ -11,7 +11,7 @@
#include <linux/regulator/of_regulator.h>
#include <linux/soc/qcom/smd-rpm.h>
struct qcom_smd_rpm *smd_vreg_rpm;
static struct qcom_smd_rpm *smd_vreg_rpm;
struct qcom_rpm_reg {
struct device *dev;

View File

@ -49,13 +49,10 @@ static int rzg2l_usb_vbus_regulator_probe(struct platform_device *pdev)
return dev_err_probe(dev, -ENODEV, "regulator node not found\n");
rdev = devm_regulator_register(dev, &rzg2l_usb_vbus_rdesc, &config);
if (IS_ERR(rdev)) {
of_node_put(config.of_node);
of_node_put(config.of_node);
if (IS_ERR(rdev))
return dev_err_probe(dev, PTR_ERR(rdev),
"not able to register vbus regulator\n");
}
of_node_put(config.of_node);
return 0;
}

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Regulator driver for Rockchip RK805/RK808/RK818
* Regulator driver for Rockchip RK80x and RK81x PMIC series
*
* Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
@ -23,7 +23,7 @@
#include <linux/regulator/of_regulator.h>
#include <linux/gpio/consumer.h>
/* Field Definitions */
/* Field definitions */
#define RK808_BUCK_VSEL_MASK 0x3f
#define RK808_BUCK4_VSEL_MASK 0xf
#define RK808_LDO_VSEL_MASK 0x1f
@ -1831,9 +1831,8 @@ static const struct regulator_desc rk818_reg[] = {
RK818_DCDC_EN_REG, BIT(7)),
};
static int rk808_regulator_dt_parse_pdata(struct device *dev,
struct regmap *map,
struct rk808_regulator_data *pdata)
static int rk808_regulator_dt_parse_pdata(struct device *dev, struct regmap *map,
struct rk808_regulator_data *pdata)
{
struct device_node *np;
int tmp, ret = 0, i;
@ -1844,23 +1843,21 @@ static int rk808_regulator_dt_parse_pdata(struct device *dev,
for (i = 0; i < ARRAY_SIZE(pdata->dvs_gpio); i++) {
pdata->dvs_gpio[i] =
devm_gpiod_get_index_optional(dev, "dvs", i,
GPIOD_OUT_LOW);
devm_gpiod_get_index_optional(dev, "dvs", i, GPIOD_OUT_LOW);
if (IS_ERR(pdata->dvs_gpio[i])) {
ret = PTR_ERR(pdata->dvs_gpio[i]);
dev_err(dev, "failed to get dvs%d gpio (%d)\n", i, ret);
ret = dev_err_probe(dev, PTR_ERR(pdata->dvs_gpio[i]),
"failed to get dvs%d gpio\n", i);
goto dt_parse_end;
}
if (!pdata->dvs_gpio[i]) {
dev_info(dev, "there is no dvs%d gpio\n", i);
dev_dbg(dev, "there is no dvs%d gpio\n", i);
continue;
}
tmp = i ? RK808_DVS2_POL : RK808_DVS1_POL;
ret = regmap_update_bits(map, RK808_IO_POL_REG, tmp,
gpiod_is_active_low(pdata->dvs_gpio[i]) ?
0 : tmp);
gpiod_is_active_low(pdata->dvs_gpio[i]) ? 0 : tmp);
}
dt_parse_end:
@ -1889,12 +1886,6 @@ static int rk808_regulator_probe(struct platform_device *pdev)
if (!pdata)
return -ENOMEM;
ret = rk808_regulator_dt_parse_pdata(&pdev->dev, regmap, pdata);
if (ret < 0)
return ret;
platform_set_drvdata(pdev, pdata);
switch (rk808->variant) {
case RK805_ID:
regulators = rk805_reg;
@ -1905,6 +1896,11 @@ static int rk808_regulator_probe(struct platform_device *pdev)
nregulators = ARRAY_SIZE(rk806_reg);
break;
case RK808_ID:
/* DVS0/1 GPIOs are supported on the RK808 only */
ret = rk808_regulator_dt_parse_pdata(&pdev->dev, regmap, pdata);
if (ret < 0)
return ret;
regulators = rk808_reg;
nregulators = RK808_NUM_REGULATORS;
break;
@ -1925,11 +1921,12 @@ static int rk808_regulator_probe(struct platform_device *pdev)
nregulators = RK818_NUM_REGULATORS;
break;
default:
dev_err(&pdev->dev, "unsupported RK8XX ID %lu\n",
rk808->variant);
return -EINVAL;
return dev_err_probe(&pdev->dev, -EINVAL,
"unsupported RK8xx ID %lu\n", rk808->variant);
}
platform_set_drvdata(pdev, pdata);
config.dev = &pdev->dev;
config.driver_data = pdata;
config.regmap = regmap;
@ -1956,7 +1953,7 @@ static struct platform_driver rk808_regulator_driver = {
module_platform_driver(rk808_regulator_driver);
MODULE_DESCRIPTION("regulator driver for the RK805/RK808/RK818 series PMICs");
MODULE_DESCRIPTION("Rockchip RK80x/RK81x PMIC series regulator driver");
MODULE_AUTHOR("Tony xie <tony.xie@rock-chips.com>");
MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");

View File

@ -280,7 +280,7 @@ MODULE_DEVICE_TABLE(of, stm32_vrefbuf_of_match);
static struct platform_driver stm32_vrefbuf_driver = {
.probe = stm32_vrefbuf_probe,
.remove_new = stm32_vrefbuf_remove,
.remove = stm32_vrefbuf_remove,
.driver = {
.name = "stm32-vrefbuf",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View File

@ -207,7 +207,7 @@ MODULE_DEVICE_TABLE(of, uniphier_regulator_match);
static struct platform_driver uniphier_regulator_driver = {
.probe = uniphier_regulator_probe,
.remove_new = uniphier_regulator_remove,
.remove = uniphier_regulator_remove,
.driver = {
.name = "uniphier-regulator",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View File

@ -210,7 +210,7 @@ MODULE_DEVICE_TABLE(of, regulator_userspace_consumer_of_match);
static struct platform_driver regulator_userspace_consumer_driver = {
.probe = regulator_userspace_consumer_probe,
.remove_new = regulator_userspace_consumer_remove,
.remove = regulator_userspace_consumer_remove,
.driver = {
.name = "reg-userspace-consumer",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View File

@ -357,7 +357,7 @@ static void regulator_virtual_remove(struct platform_device *pdev)
static struct platform_driver regulator_virtual_consumer_driver = {
.probe = regulator_virtual_probe,
.remove_new = regulator_virtual_remove,
.remove = regulator_virtual_remove,
.driver = {
.name = "reg-virt-consumer",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,

View File

@ -1304,9 +1304,9 @@ EXPORT_SYMBOL_GPL(wm8350_register_led);
static struct platform_driver wm8350_regulator_driver = {
.probe = wm8350_regulator_probe,
.remove_new = wm8350_regulator_remove,
.driver = {
.name = "wm8350-regulator",
.remove = wm8350_regulator_remove,
.driver = {
.name = "wm8350-regulator",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
};

View File

@ -16,18 +16,6 @@
#define MAX5978_NUM_SWITCHES 1
#define MAX5970_NUM_LEDS 4
struct max5970_data {
int num_switches;
u32 irng[MAX5970_NUM_SWITCHES];
u32 mon_rng[MAX5970_NUM_SWITCHES];
u32 shunt_micro_ohms[MAX5970_NUM_SWITCHES];
};
enum max5970_chip_type {
TYPE_MAX5978 = 1,
TYPE_MAX5970,
};
#define MAX5970_REG_CURRENT_L(ch) (0x01 + (ch) * 4)
#define MAX5970_REG_CURRENT_H(ch) (0x00 + (ch) * 4)
#define MAX5970_REG_VOLTAGE_L(ch) (0x03 + (ch) * 4)

View File

@ -168,6 +168,29 @@ 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);
#if IS_ENABLED(CONFIG_OF)
struct regulator *__must_check of_regulator_get_optional(struct device *dev,
struct device_node *node,
const char *id);
struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev,
struct device_node *node,
const char *id);
#else
static inline struct regulator *__must_check of_regulator_get_optional(struct device *dev,
struct device_node *node,
const char *id)
{
return ERR_PTR(-ENODEV);
}
static inline struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev,
struct device_node *node,
const char *id)
{
return ERR_PTR(-ENODEV);
}
#endif
int regulator_register_supply_alias(struct device *dev, const char *id,
struct device *alias_dev,
const char *alias_id);
@ -350,6 +373,20 @@ devm_regulator_get_optional(struct device *dev, const char *id)
return ERR_PTR(-ENODEV);
}
static inline struct regulator *__must_check of_regulator_get_optional(struct device *dev,
struct device_node *node,
const char *id)
{
return ERR_PTR(-ENODEV);
}
static inline struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev,
struct device_node *node,
const char *id)
{
return ERR_PTR(-ENODEV);
}
static inline void regulator_put(struct regulator *regulator)
{
}

View File

@ -269,6 +269,11 @@ enum regulator_type {
* config but it cannot store it for later usage.
* Callback should return 0 on success or negative ERRNO
* indicating failure.
* @init_cb: Optional callback called after the parsing of init_data.
* Allows the regulator to perform runtime init if necessary,
* such as synching the regulator and the parsed constraints.
* Callback should return 0 on success or negative ERRNO
* indicating failure.
* @id: Numerical identifier for the regulator.
* @ops: Regulator operations table.
* @irq: Interrupt number for the regulator.
@ -365,6 +370,8 @@ struct regulator_desc {
int (*of_parse_cb)(struct device_node *,
const struct regulator_desc *,
struct regulator_config *);
int (*init_cb)(struct regulator_dev *,
struct regulator_config *);
int id;
unsigned int continuous_voltage_range:1;
unsigned n_voltages;

View File

@ -273,8 +273,6 @@ struct regulator_consumer_supply {
* be usable.
* @num_consumer_supplies: Number of consumer device supplies.
* @consumer_supplies: Consumer device supply configuration.
*
* @regulator_init: Callback invoked when the regulator has been registered.
* @driver_data: Data passed to regulator_init.
*/
struct regulator_init_data {
@ -285,8 +283,7 @@ struct regulator_init_data {
int num_consumer_supplies;
struct regulator_consumer_supply *consumer_supplies;
/* optional regulator machine specific init */
int (*regulator_init)(void *driver_data);
/* optional regulator machine specific data */
void *driver_data; /* core does not touch this */
};