Commit 9b18d07b authored by Linus Torvalds's avatar Linus Torvalds

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

Pull regulator updates from Mark Brown:
 "This is mostly a drivers update including a couple of new drivers but
  we do have some fixes and improvements to the core as well.

   - Make sure we don't log spuriously about uncontrollable regulators.

   - Don't use delays when we should use sleeps for regulators with
     larger ramp times.

   - Support for MediaTek MT6358 and MT6366, Richtek RT5759 and Silicon
     Mitus SM5703"

* tag 'regulator-v5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (36 commits)
  regulator: scmi: Fix refcount leak in scmi_regulator_probe
  regulator: pfuze100: Fix refcount leak in pfuze_parse_regulators_dt
  regulator: qcom_smd: Fix up PM8950 regulator configuration
  regulator: core: Fix enable_count imbalance with EXCLUSIVE_GET
  regulator: core: Add error flags to sysfs attributes
  regulator: dt-bindings: qcom,rpmh: document vdd-l7-bob-supply on PMR735A
  regulator: dt-bindings: qcom,rpmh: document supplies per variant
  regulator: dt-bindings: qcom,rpmh: update maintainers
  regulator: mt6315: Enforce regulator-compatible, not name
  regulator: pca9450: Enable DVS control via PMIC_STBY_REQ
  regulator: pca9450: Make warm reset on WDOG_B assertion
  regulator: Add property for WDOG_B warm reset
  regulator: pca9450: Make I2C Level Translator configurable
  regulator: Add property for I2C level shifter
  regulator: sm5703: Correct reference to the common regulator schema
  regulator: sm5703-regulator: Add regulators support for SM5703 MFD
  dt-bindings: regulator: Add bindings for Silicon Mitus SM5703 regulators
  regulator: richtek,rt4801: parse GPIOs per regulator
  regulator: dt-bindings: richtek,rt4801: use existing ena_gpiod feature
  regulator: core: Sleep (not delay) in set_voltage()
  ...
parents 5d23bb5f a5b8e4a5
......@@ -370,3 +370,84 @@ Description:
'unknown' means software cannot determine the state, or
the reported state is invalid.
What: /sys/class/regulator/.../under_voltage
Date: April 2022
KernelVersion: 5.18
Contact: Zev Weiss <zev@bewilderbeest.net>
Description:
Some regulator directories will contain a field called
under_voltage. This indicates if the device reports an
under-voltage fault (1) or not (0).
What: /sys/class/regulator/.../over_current
Date: April 2022
KernelVersion: 5.18
Contact: Zev Weiss <zev@bewilderbeest.net>
Description:
Some regulator directories will contain a field called
over_current. This indicates if the device reports an
over-current fault (1) or not (0).
What: /sys/class/regulator/.../regulation_out
Date: April 2022
KernelVersion: 5.18
Contact: Zev Weiss <zev@bewilderbeest.net>
Description:
Some regulator directories will contain a field called
regulation_out. This indicates if the device reports an
out-of-regulation fault (1) or not (0).
What: /sys/class/regulator/.../fail
Date: April 2022
KernelVersion: 5.18
Contact: Zev Weiss <zev@bewilderbeest.net>
Description:
Some regulator directories will contain a field called
fail. This indicates if the device reports an output failure
(1) or not (0).
What: /sys/class/regulator/.../over_temp
Date: April 2022
KernelVersion: 5.18
Contact: Zev Weiss <zev@bewilderbeest.net>
Description:
Some regulator directories will contain a field called
over_temp. This indicates if the device reports an
over-temperature fault (1) or not (0).
What: /sys/class/regulator/.../under_voltage_warn
Date: April 2022
KernelVersion: 5.18
Contact: Zev Weiss <zev@bewilderbeest.net>
Description:
Some regulator directories will contain a field called
under_voltage_warn. This indicates if the device reports an
under-voltage warning (1) or not (0).
What: /sys/class/regulator/.../over_current_warn
Date: April 2022
KernelVersion: 5.18
Contact: Zev Weiss <zev@bewilderbeest.net>
Description:
Some regulator directories will contain a field called
over_current_warn. This indicates if the device reports an
over-current warning (1) or not (0).
What: /sys/class/regulator/.../over_voltage_warn
Date: April 2022
KernelVersion: 5.18
Contact: Zev Weiss <zev@bewilderbeest.net>
Description:
Some regulator directories will contain a field called
over_voltage_warn. This indicates if the device reports an
over-voltage warning (1) or not (0).
What: /sys/class/regulator/.../over_temp_warn
Date: April 2022
KernelVersion: 5.18
Contact: Zev Weiss <zev@bewilderbeest.net>
Description:
Some regulator directories will contain a field called
over_temp_warn. This indicates if the device reports an
over-temperature warning (1) or not (0).
......@@ -31,7 +31,7 @@ properties:
$ref: "regulator.yaml#"
properties:
regulator-name:
regulator-compatible:
pattern: "^vbuck[1-4]$"
additionalProperties: false
......
......@@ -8,14 +8,14 @@ Documentation/devicetree/bindings/regulator/regulator.txt.
The valid names for regulators are::
BUCK:
buck_vdram1, buck_vcore, buck_vpa, buck_vproc11, buck_vproc12, buck_vgpu,
buck_vs2, buck_vmodem, buck_vs1
buck_vdram1, buck_vcore, buck_vcore_sshub, buck_vpa, buck_vproc11,
buck_vproc12, buck_vgpu, buck_vs2, buck_vmodem, buck_vs1
LDO:
ldo_vdram2, ldo_vsim1, ldo_vibr, ldo_vrf12, ldo_vio18, ldo_vusb, ldo_vcamio,
ldo_vcamd, ldo_vcn18, ldo_vfe28, ldo_vsram_proc11, ldo_vcn28, ldo_vsram_others,
ldo_vsram_gpu, ldo_vxo22, ldo_vefuse, ldo_vaux18, ldo_vmch, ldo_vbif28,
ldo_vsram_proc12, ldo_vcama1, ldo_vemc, ldo_vio28, ldo_va12, ldo_vrf18,
ldo_vcn33_bt, ldo_vcn33_wifi, ldo_vcama2, ldo_vmc, ldo_vldo28, ldo_vaud28,
ldo_vsram_others_sshub, ldo_vsram_gpu, ldo_vxo22, ldo_vefuse, ldo_vaux18,
ldo_vmch, ldo_vbif28, ldo_vsram_proc12, ldo_vcama1, ldo_vemc, ldo_vio28, ldo_va12,
ldo_vrf18, ldo_vcn33_bt, ldo_vcn33_wifi, ldo_vcama2, ldo_vmc, ldo_vldo28, ldo_vaud28,
ldo_vsim2
Example:
......@@ -354,5 +354,17 @@ Example:
regulator-max-microvolt = <3100000>;
regulator-enable-ramp-delay = <540>;
};
mt6358_vcore_sshub_reg: buck_vcore_sshub {
regulator-name = "vcore_sshub";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1293750>;
};
mt6358_vsram_others_sshub_reg: ldo_vsram_others_sshub {
regulator-name = "vsram_others_sshub";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1293750>;
};
};
};
......@@ -92,6 +92,17 @@ properties:
LDO5CTRL_L or LDO5CTRL_H register. Use this if the SD_VSEL signal is
connected to a host GPIO.
nxp,i2c-lt-enable:
type: boolean
description:
Indicates that the I2C Level Translator is used.
nxp,wdog_b-warm-reset:
type: boolean
description:
When WDOG_B signal is asserted a warm reset will be done instead of cold
reset.
required:
- compatible
- reg
......
......@@ -7,7 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. RPMh Regulators
maintainers:
- David Collins <collinsd@codeaurora.org>
- Bjorn Andersson <bjorn.andersson@linaro.org>
- Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
description: |
rpmh-regulator devices support PMIC regulator management via the Voltage
......@@ -78,7 +79,7 @@ properties:
RPMh resource name suffix used for the regulators found
on this PMIC.
$ref: /schemas/types.yaml#/definitions/string
enum: [a, b, c, d, e, f]
enum: [a, b, c, d, e, f, h, k]
qcom,always-wait-for-ack:
description: |
......@@ -94,35 +95,264 @@ properties:
vdd-rgb-supply:
description: Input supply phandle of rgb.
vin-lvs-1-2-supply:
description: Input supply phandle of one or more regulators.
vdd-bob-supply:
description: BOB regulator parent supply phandle.
bob:
type: object
$ref: "regulator.yaml#"
description: BOB regulator node.
patternProperties:
"^vdd-s([0-9]+)-supply$":
description: Input supply phandle(s) of one or more regulators.
"^vdd-(l[0-9]+[-]){1,5}supply$":
description: Input supply phandle(s) of one or more regulators.
"^(smps|ldo|lvs)[0-9]+$":
type: object
$ref: "regulator.yaml#"
description: smps/ldo regulator nodes(s).
additionalProperties: false
required:
- compatible
- qcom,pmic-id
allOf:
- if:
properties:
compatible:
enum:
- qcom,pm6150-rpmh-regulators
then:
properties:
vdd-l2-l3-supply: true
vdd-l4-l7-l8-supply: true
vdd-l5-l16-l17-l18-l19-supply: true
vdd-l10-l14-l15-supply: true
vdd-l11-l12-l13-supply: true
patternProperties:
"^vdd-l[169]-supply$": true
"^vdd-s[1-5]-supply$": true
- if:
properties:
compatible:
enum:
- qcom,pm6150l-rpmh-regulators
then:
properties:
vdd-bob-supply:
description: BOB regulator parent supply phandle.
vdd-l1-l8-supply: true
vdd-l2-l3-supply: true
vdd-l4-l5-l6-supply: true
vdd-l7-l11-supply: true
vdd-l9-l10-supply: true
patternProperties:
"^vdd-s[1-8]-supply$": true
- if:
properties:
compatible:
enum:
- qcom,pm7325-rpmh-regulators
then:
properties:
vdd-l1-l4-l12-l15-supply: true
vdd-l2-l7-supply: true
vdd-l6-l9-l10-supply: true
vdd-l11-l17-l18-l19-supply: true
vdd-l13-supply: true
vdd-l14-l16-supply: true
patternProperties:
"^vdd-l[358]-supply$": true
"^vdd-s[1-8]-supply$": true
- if:
properties:
compatible:
enum:
- qcom,pm8005-rpmh-regulators
then:
patternProperties:
"^vdd-s[1-4]-supply$": true
- if:
properties:
compatible:
enum:
- qcom,pm8009-rpmh-regulators
- qcom,pm8009-1-rpmh-regulators
then:
properties:
vdd-l5-l6-supply: true
patternProperties:
"^vdd-l[1-47]-supply$": true
"^vdd-s[1-2]-supply$": true
- if:
properties:
compatible:
enum:
- qcom,pm8150-rpmh-regulators
- qcom,pmm8155au-rpmh-regulators
then:
properties:
vdd-l1-l8-l11-supply: true
vdd-l2-l10-supply: true
vdd-l3-l4-l5-l18-supply: true
vdd-l6-l9-supply: true
vdd-l7-l12-l14-l15-supply: true
vdd-l13-l16-l17-supply: true
patternProperties:
"^vdd-s([1-9]|10)-supply$": true
- if:
properties:
compatible:
enum:
- qcom,pm8150l-rpmh-regulators
then:
properties:
vdd-bob-supply:
description: BOB regulator parent supply phandle.
vdd-l1-l8-supply: true
vdd-l2-l3-supply: true
vdd-l4-l5-l6-supply: true
vdd-l7-l11-supply: true
vdd-l9-l10-supply: true
patternProperties:
"^vdd-s[1-8]-supply$": true
- if:
properties:
compatible:
enum:
- qcom,pm8350-rpmh-regulators
then:
properties:
vdd-l1-l4-supply: true
vdd-l2-l7-supply: true
vdd-l3-l5-supply: true
vdd-l6-l9-l10-supply: true
vdd-l8-supply: true
patternProperties:
"^vdd-s([1-9]|1[0-2])-supply$": true
- if:
properties:
compatible:
enum:
- qcom,pm8350c-rpmh-regulators
then:
properties:
vdd-bob-supply:
description: BOB regulator parent supply phandle.
vdd-l1-l12-supply: true
vdd-l2-l8-supply: true
vdd-l3-l4-l5-l7-l13-supply: true
vdd-l6-l9-l11-supply: true
vdd-l10-supply: true
patternProperties:
"^vdd-s([1-9]|10)-supply$": true
- if:
properties:
compatible:
enum:
- qcom,pm8450-rpmh-regulators
then:
patternProperties:
"^vdd-l[1-4]-supply$": true
"^vdd-s[1-6]-supply$": true
- if:
properties:
compatible:
enum:
- qcom,pm8998-rpmh-regulators
then:
properties:
vdd-l1-l27-supply: true
vdd-l2-l8-l17-supply: true
vdd-l3-l11-supply: true
vdd-l4-l5-supply: true
vdd-l6-supply: true
vdd-l7-l12-l14-l15-supply: true
vdd-l9-supply: true
vdd-l10-l23-l25-supply: true
vdd-l13-l19-l21-supply: true
vdd-l16-l28-supply: true
vdd-l18-l22-supply: true
vdd-l20-l24-supply: true
vdd-l26-supply: true
vin-lvs-1-2-supply: true
patternProperties:
"^vdd-s([1-9]|1[0-3])-supply$": true
- if:
properties:
compatible:
enum:
- qcom,pmg1110-rpmh-regulators
then:
properties:
vdd-s1-supply: true
- if:
properties:
compatible:
enum:
- qcom,pmi8998-rpmh-regulators
then:
properties:
vdd-bob-supply:
description: BOB regulator parent supply phandle.
- if:
properties:
compatible:
enum:
- qcom,pmr735a-rpmh-regulators
then:
properties:
vdd-l1-l2-supply: true
vdd-l3-supply: true
vdd-l4-supply: true
vdd-l5-l6-supply: true
vdd-l7-bob-supply: true
patternProperties:
"^vdd-s[1-3]-supply$": true
- if:
properties:
compatible:
enum:
- qcom,pmx55-rpmh-regulators
then:
properties:
vdd-l1-l2-supply: true
vdd-l3-l9-supply: true
vdd-l4-l12-supply: true
vdd-l5-l6-supply: true
vdd-l7-l8-supply: true
vdd-l10-l11-l13-supply: true
patternProperties:
"^vdd-l1[4-6]-supply$": true
"^vdd-s[1-7]-supply$": true
- if:
properties:
compatible:
enum:
- qcom,pmx65-rpmh-regulators
then:
properties:
vdd-l2-l18-supply: true
vdd-l5-l6-l16-supply: true
vdd-l8-l9-supply: true
vdd-l11-l13-supply: true
patternProperties:
"^vdd-l[1347]-supply$": true
"^vdd-l1[0245789]-supply$": true
"^vdd-l2[01]-supply$": true
"^vdd-s[1-8]-supply$": true
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
......
......@@ -17,9 +17,6 @@ description: |
Datasheet is available at
https://www.richtek.com/assets/product_file/RT4801H/DS4801H-00.pdf
#The valid names for RT4801 regulator nodes are:
#DSVP, DSVN
properties:
compatible:
enum:
......@@ -33,10 +30,13 @@ properties:
The first one is ENP to enable DSVP, and second one is ENM to enable DSVN.
Number of GPIO in the array list could be 1 or 2.
If only one gpio is specified, only one gpio used to control ENP/ENM.
Else both are spefied, DSVP/DSVN could be controlled individually.
Othersie, this property not specified. treat both as always-on regulator.
Else if both are specified, DSVP/DSVN could be controlled individually.
If this property not specified, treat both as always-on regulators.
Property is deprecated. Use enable-gpios in each regulator.
minItems: 1
maxItems: 2
deprecated: true
patternProperties:
"^DSV(P|N)$":
......@@ -45,6 +45,14 @@ patternProperties:
description:
Properties for single display bias regulator.
properties:
enable-gpios:
description:
GPIO to use to enable DSVP/DSVN regulator. One GPIO can be configured
for controlling both regulators. If this property not specified for
any regulator, treat both as always-on regulators.
maxItems: 1
required:
- compatible
- reg
......@@ -60,19 +68,20 @@ examples:
rt4801@73 {
compatible = "richtek,rt4801";
reg = <0x73>;
enable-gpios = <&gpio26 2 0>, <&gpio26 3 0>;
dsvp: DSVP {
regulator-name = "rt4801,dsvp";
regulator-min-microvolt = <4000000>;
regulator-max-microvolt = <6000000>;
regulator-boot-on;
enable-gpios = <&gpio26 2 0>;
};
dsvn: DSVN {
regulator-name = "rt4801,dsvn";
regulator-min-microvolt = <4000000>;
regulator-max-microvolt = <6000000>;
regulator-boot-on;
enable-gpios = <&gpio26 3 0>;
};
};
......
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/richtek,rt5759-regulator.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Richtek RT5759 High Performance DCDC Converter
maintainers:
- ChiYuan Huang <cy_huang@richtek.com>
description: |
The RT5759 is a high-performance, synchronous step-down DC-DC converter that
can deliver up to 9A output current from 3V to 6.5V input supply, The output
voltage can be programmable with I2C controlled 7-Bit VID.
Datasheet is available at
https://www.richtek.com/assets/product_file/RT5759/DS5759-00.pdf
properties:
compatible:
enum:
- richtek,rt5759
- richtek,rt5759a
reg:
maxItems: 1
regulator-allowed-modes:
description: |
buck allowed operating mode
0: auto mode (PSKIP: pulse skipping)
1: force pwm mode
items:
enum: [0, 1]
richtek,watchdog-enable:
description: enable the external watchdog reset pin listening
type: boolean
allOf:
- $ref: regulator.yaml#
- if:
properties:
compatible:
contains:
const: richtek,rt5759
then:
properties:
richtek,watchdog-enable: false
required:
- compatible
- reg
unevaluatedProperties: false
examples:
# example 1 for RT5759
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
regulator@62 {
compatible = "richtek,rt5759";
reg = <0x62>;
regulator-name = "rt5759-buck";
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <1500000>;
regulator-boot-on;
};
};
# example 2 for RT5759A
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
regulator@62 {
compatible = "richtek,rt5759a";
reg = <0x62>;
regulator-name = "rt5759a-buck";
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <1725000>;
regulator-boot-on;
richtek,watchdog-enable;
};
};
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/siliconmitus,sm5703-regulator.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Silicon Mitus SM5703 multi function device regulators
maintainers:
- Markuss Broks <markuss.broks@gmail.com>
description: |
SM5703 regulators node should be a sub node of the SM5703 MFD node. See SM5703 MFD
bindings at Documentation/devicetree/bindings/mfd/siliconmitus,sm5703.yaml
Regulator nodes should be named as USBLDO_<number>, BUCK, VBUS, LDO_<number>.
The definition for each of these nodes is defined using the standard
binding for regulators at Documentation/devicetree/bindings/regulator/regulator.txt.
properties:
buck:
type: object
$ref: regulator.yaml#
unevaluatedProperties: false
description:
Properties for the BUCK regulator.
vbus:
type: object
$ref: regulator.yaml#
unevaluatedProperties: false
description:
Properties for the VBUS regulator.
patternProperties:
"^ldo[1-3]$":
type: object
$ref: regulator.yaml#
unevaluatedProperties: false
description:
Properties for single LDO regulator.
"^usbldo[1-2]$":
type: object
$ref: regulator.yaml#
unevaluatedProperties: false
description:
Properties for a single USBLDO regulator.
additionalProperties: false
......@@ -14,9 +14,6 @@ description: |
maintainers:
- Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
allOf:
- $ref: "regulator.yaml#"
# USB3 Controller
properties:
......@@ -36,27 +33,51 @@ properties:
minItems: 1
maxItems: 2
clock-names:
oneOf:
- items: # for Pro4, Pro5
- const: gio
- const: link
- items: # for others
- const: link
clock-names: true
resets:
minItems: 1
maxItems: 2
reset-names:
oneOf:
- items: # for Pro4, Pro5
reset-names: true
allOf:
- $ref: "regulator.yaml#"
- if:
properties:
compatible:
contains:
enum:
- socionext,uniphier-pro4-usb3-regulator
- socionext,uniphier-pro5-usb3-regulator
then:
properties:
clocks:
minItems: 2
maxItems: 2
clock-names:
items:
- const: gio
- const: link
- items:
resets:
minItems: 2
maxItems: 2
reset-names:
items:
- const: gio
- const: link
else:
properties:
clocks:
maxItems: 1
clock-names:
const: link
resets:
maxItems: 1
reset-names:
const: link
additionalProperties: false
unevaluatedProperties: false
required:
- compatible
......
......@@ -1057,6 +1057,16 @@ config REGULATOR_RT5190A
buck converters, 1 LDO, mute AC OFF depop function, with the general
I2C control interface.
config REGULATOR_RT5759
tristate "Richtek RT5759 Regulator"
depends on I2C
select REGMAP_I2C
help
This adds support for voltage regulator in Richtek RT5759.
The RT5759 is a high-performance, synchronous step-down DC-DC
converter that can deliver up to 9A output current from 3V to 6.5V
input supply.
config REGULATOR_RT6160
tristate "Richtek RT6160 BuckBoost voltage regulator"
depends on I2C
......@@ -1157,6 +1167,13 @@ config REGULATOR_SLG51000
The SLG51000 is seven compact and customizable low dropout
regulators.
config REGULATOR_SM5703
tristate "Silicon Mitus SM5703 regulators"
depends on MFD_SM5703
help
This driver provides support for voltage regulators of SM5703
multi-function device.
config REGULATOR_STM32_BOOSTER
tristate "STMicroelectronics STM32 BOOSTER"
depends on ARCH_STM32 || COMPILE_TEST
......
......@@ -127,6 +127,7 @@ obj-$(CONFIG_REGULATOR_RT4801) += rt4801-regulator.o
obj-$(CONFIG_REGULATOR_RT4831) += rt4831-regulator.o
obj-$(CONFIG_REGULATOR_RT5033) += rt5033-regulator.o
obj-$(CONFIG_REGULATOR_RT5190A) += rt5190a-regulator.o
obj-$(CONFIG_REGULATOR_RT5759) += rt5759-regulator.o
obj-$(CONFIG_REGULATOR_RT6160) += rt6160-regulator.o
obj-$(CONFIG_REGULATOR_RT6245) += rt6245-regulator.o
obj-$(CONFIG_REGULATOR_RTMV20) += rtmv20-regulator.o
......@@ -138,6 +139,7 @@ obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
obj-$(CONFIG_REGULATOR_SC2731) += sc2731-regulator.o
obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o
obj-$(CONFIG_REGULATOR_SLG51000) += slg51000-regulator.o
obj-$(CONFIG_REGULATOR_SM5703) += sm5703-regulator.o
obj-$(CONFIG_REGULATOR_STM32_BOOSTER) += stm32-booster.o
obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
obj-$(CONFIG_REGULATOR_STM32_PWR) += stm32-pwr.o
......
......@@ -83,6 +83,7 @@ struct regulator_supply_alias {
static int _regulator_is_enabled(struct regulator_dev *rdev);
static int _regulator_disable(struct regulator *regulator);
static int _regulator_get_error_flags(struct regulator_dev *rdev, unsigned int *flags);
static int _regulator_get_current_limit(struct regulator_dev *rdev);
static unsigned int _regulator_get_mode(struct regulator_dev *rdev);
static int _notifier_call_chain(struct regulator_dev *rdev,
......@@ -911,6 +912,30 @@ static ssize_t bypass_show(struct device *dev,
}
static DEVICE_ATTR_RO(bypass);
#define REGULATOR_ERROR_ATTR(name, bit) \
static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \
char *buf) \
{ \
int ret; \
unsigned int flags; \
struct regulator_dev *rdev = dev_get_drvdata(dev); \
ret = _regulator_get_error_flags(rdev, &flags); \
if (ret) \
return ret; \
return sysfs_emit(buf, "%d\n", !!(flags & (bit))); \
} \
static DEVICE_ATTR_RO(name)
REGULATOR_ERROR_ATTR(under_voltage, REGULATOR_ERROR_UNDER_VOLTAGE);
REGULATOR_ERROR_ATTR(over_current, REGULATOR_ERROR_OVER_CURRENT);
REGULATOR_ERROR_ATTR(regulation_out, REGULATOR_ERROR_REGULATION_OUT);
REGULATOR_ERROR_ATTR(fail, REGULATOR_ERROR_FAIL);
REGULATOR_ERROR_ATTR(over_temp, REGULATOR_ERROR_OVER_TEMP);
REGULATOR_ERROR_ATTR(under_voltage_warn, REGULATOR_ERROR_UNDER_VOLTAGE_WARN);
REGULATOR_ERROR_ATTR(over_current_warn, REGULATOR_ERROR_OVER_CURRENT_WARN);
REGULATOR_ERROR_ATTR(over_voltage_warn, REGULATOR_ERROR_OVER_VOLTAGE_WARN);
REGULATOR_ERROR_ATTR(over_temp_warn, REGULATOR_ERROR_OVER_TEMP_WARN);
/* Calculate the new optimum regulator operating mode based on the new total
* consumer load. All locks held by caller
*/
......@@ -1522,6 +1547,24 @@ static int set_machine_constraints(struct regulator_dev *rdev)
}
}
/*
* If there is no mechanism for controlling the regulator then
* flag it as always_on so we don't end up duplicating checks
* for this so much. Note that we could control the state of
* a supply to control the output on a regulator that has no
* direct control.
*/
if (!rdev->ena_pin && !ops->enable) {
if (rdev->supply_name && !rdev->supply)
return -EPROBE_DEFER;
if (rdev->supply)
rdev->constraints->always_on =
rdev->supply->rdev->constraints->always_on;
else
rdev->constraints->always_on = true;
}
/* If the constraints say the regulator should be on at this point
* and we have control then make sure it is enabled.
*/
......@@ -2133,10 +2176,13 @@ struct regulator *_regulator_get(struct device *dev, const char *id,
rdev->exclusive = 1;
ret = _regulator_is_enabled(rdev);
if (ret > 0)
if (ret > 0) {
rdev->use_count = 1;
else
regulator->enable_count = 1;
} else {
rdev->use_count = 0;
regulator->enable_count = 0;
}
}
link = device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS);
......@@ -2511,17 +2557,17 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
}
/**
* _regulator_enable_delay - a delay helper function
* _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 regulators will never be enabled in
* The assumption here is that these regulator operations will never used in
* atomic context and therefore sleeping functions can be used.
*/
static void _regulator_enable_delay(unsigned int delay)
static void _regulator_delay_helper(unsigned int delay)
{
unsigned int ms = delay / 1000;
unsigned int us = delay % 1000;
......@@ -2603,7 +2649,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
s64 remaining = ktime_us_delta(end, ktime_get());
if (remaining > 0)
_regulator_enable_delay(remaining);
_regulator_delay_helper(remaining);
}
if (rdev->ena_pin) {
......@@ -2630,14 +2676,14 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
/* If poll_enabled_time is set, poll upto the delay calculated
* above, delaying poll_enabled_time uS to check if the regulator
* actually got enabled.
* If the regulator isn't enabled after enable_delay has
* expired, return -ETIMEDOUT.
* If the regulator isn't enabled after our delay helper has expired,
* return -ETIMEDOUT.
*/
if (rdev->desc->poll_enabled_time) {
unsigned int time_remaining = delay;
while (time_remaining > 0) {
_regulator_enable_delay(rdev->desc->poll_enabled_time);
_regulator_delay_helper(rdev->desc->poll_enabled_time);
if (rdev->desc->ops->get_status) {
ret = _regulator_check_status_enabled(rdev);
......@@ -2656,7 +2702,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
return -ETIMEDOUT;
}
} else {
_regulator_enable_delay(delay);
_regulator_delay_helper(delay);
}
trace_regulator_enable_complete(rdev_get_name(rdev));
......@@ -3548,12 +3594,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
}
/* Insert any necessary delays */
if (delay >= 1000) {
mdelay(delay / 1000);
udelay(delay % 1000);
} else if (delay) {
udelay(delay);
}
_regulator_delay_helper(delay);
if (best_val >= 0) {
unsigned long data = best_val;
......@@ -4971,6 +5012,15 @@ static struct attribute *regulator_dev_attrs[] = {
&dev_attr_max_microvolts.attr,
&dev_attr_min_microamps.attr,
&dev_attr_max_microamps.attr,
&dev_attr_under_voltage.attr,
&dev_attr_over_current.attr,
&dev_attr_regulation_out.attr,
&dev_attr_fail.attr,
&dev_attr_over_temp.attr,
&dev_attr_under_voltage_warn.attr,
&dev_attr_over_current_warn.attr,
&dev_attr_over_voltage_warn.attr,
&dev_attr_over_temp_warn.attr,
&dev_attr_suspend_standby_state.attr,
&dev_attr_suspend_mem_state.attr,
&dev_attr_suspend_disk_state.attr,
......@@ -5026,6 +5076,17 @@ static umode_t regulator_attr_is_visible(struct kobject *kobj,
if (attr == &dev_attr_bypass.attr)
return ops->get_bypass ? mode : 0;
if (attr == &dev_attr_under_voltage.attr ||
attr == &dev_attr_over_current.attr ||
attr == &dev_attr_regulation_out.attr ||
attr == &dev_attr_fail.attr ||
attr == &dev_attr_over_temp.attr ||
attr == &dev_attr_under_voltage_warn.attr ||
attr == &dev_attr_over_current_warn.attr ||
attr == &dev_attr_over_voltage_warn.attr ||
attr == &dev_attr_over_temp_warn.attr)
return ops->get_error_flags ? mode : 0;
/* constraints need specific supporting methods */
if (attr == &dev_attr_min_microvolts.attr ||
attr == &dev_attr_max_microvolts.attr)
......
......@@ -1030,6 +1030,8 @@ static int da9121_assign_chip_model(struct i2c_client *i2c,
chip->variant_id = DA9121_TYPE_DA9142;
regmap = &da9121_2ch_regmap_config;
break;
default:
return -EINVAL;
}
/* Set these up for of_regulator_match call which may want .of_map_modes */
......
......@@ -236,12 +236,9 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
drvdata->desc.supply_name = devm_kstrdup(&pdev->dev,
config->input_supply,
GFP_KERNEL);
if (!drvdata->desc.supply_name) {
dev_err(&pdev->dev,
"Failed to allocate input supply\n");
if (!drvdata->desc.supply_name)
return -ENOMEM;
}
}
if (config->microvolts)
drvdata->desc.n_voltages = 1;
......
......@@ -130,6 +130,102 @@ struct mt6358_regulator_info {
.qi = BIT(15), \
}
#define MT6366_BUCK(match, vreg, min, max, step, \
volt_ranges, vosel_mask, _da_vsel_reg, _da_vsel_mask, \
_modeset_reg, _modeset_shift) \
[MT6366_ID_##vreg] = { \
.desc = { \
.name = #vreg, \
.of_match = of_match_ptr(match), \
.ops = &mt6358_volt_range_ops, \
.type = REGULATOR_VOLTAGE, \
.id = MT6366_ID_##vreg, \
.owner = THIS_MODULE, \
.n_voltages = ((max) - (min)) / (step) + 1, \
.linear_ranges = volt_ranges, \
.n_linear_ranges = ARRAY_SIZE(volt_ranges), \
.vsel_reg = MT6358_BUCK_##vreg##_ELR0, \
.vsel_mask = vosel_mask, \
.enable_reg = MT6358_BUCK_##vreg##_CON0, \
.enable_mask = BIT(0), \
.of_map_mode = mt6358_map_mode, \
}, \
.status_reg = MT6358_BUCK_##vreg##_DBG1, \
.qi = BIT(0), \
.da_vsel_reg = _da_vsel_reg, \
.da_vsel_mask = _da_vsel_mask, \
.modeset_reg = _modeset_reg, \
.modeset_mask = BIT(_modeset_shift), \
}
#define MT6366_LDO(match, vreg, ldo_volt_table, \
ldo_index_table, enreg, enbit, vosel, \
vosel_mask) \
[MT6366_ID_##vreg] = { \
.desc = { \
.name = #vreg, \
.of_match = of_match_ptr(match), \
.ops = &mt6358_volt_table_ops, \
.type = REGULATOR_VOLTAGE, \
.id = MT6366_ID_##vreg, \
.owner = THIS_MODULE, \
.n_voltages = ARRAY_SIZE(ldo_volt_table), \
.volt_table = ldo_volt_table, \
.vsel_reg = vosel, \
.vsel_mask = vosel_mask, \
.enable_reg = enreg, \
.enable_mask = BIT(enbit), \
}, \
.status_reg = MT6358_LDO_##vreg##_CON1, \
.qi = BIT(15), \
.index_table = ldo_index_table, \
.n_table = ARRAY_SIZE(ldo_index_table), \
}
#define MT6366_LDO1(match, vreg, min, max, step, \
volt_ranges, _da_vsel_reg, _da_vsel_mask, \
vosel, vosel_mask) \
[MT6366_ID_##vreg] = { \
.desc = { \
.name = #vreg, \
.of_match = of_match_ptr(match), \
.ops = &mt6358_volt_range_ops, \
.type = REGULATOR_VOLTAGE, \
.id = MT6366_ID_##vreg, \
.owner = THIS_MODULE, \
.n_voltages = ((max) - (min)) / (step) + 1, \
.linear_ranges = volt_ranges, \
.n_linear_ranges = ARRAY_SIZE(volt_ranges), \
.vsel_reg = vosel, \
.vsel_mask = vosel_mask, \
.enable_reg = MT6358_LDO_##vreg##_CON0, \
.enable_mask = BIT(0), \
}, \
.da_vsel_reg = _da_vsel_reg, \
.da_vsel_mask = _da_vsel_mask, \
.status_reg = MT6358_LDO_##vreg##_DBG1, \
.qi = BIT(0), \
}
#define MT6366_REG_FIXED(match, vreg, \
enreg, enbit, volt) \
[MT6366_ID_##vreg] = { \
.desc = { \
.name = #vreg, \
.of_match = of_match_ptr(match), \
.ops = &mt6358_volt_fixed_ops, \
.type = REGULATOR_VOLTAGE, \
.id = MT6366_ID_##vreg, \
.owner = THIS_MODULE, \
.n_voltages = 1, \
.enable_reg = enreg, \
.enable_mask = BIT(enbit), \
.min_uV = volt, \
}, \
.status_reg = MT6358_LDO_##vreg##_CON1, \
.qi = BIT(15), \
}
static const struct linear_range buck_volt_range1[] = {
REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 6250),
};
......@@ -409,6 +505,9 @@ static struct mt6358_regulator_info mt6358_regulators[] = {
MT6358_BUCK("buck_vcore", VCORE, 500000, 1293750, 6250,
buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f,
MT6358_VCORE_VGPU_ANA_CON0, 1),
MT6358_BUCK("buck_vcore_sshub", VCORE_SSHUB, 500000, 1293750, 6250,
buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_SSHUB_ELR0, 0x7f,
MT6358_VCORE_VGPU_ANA_CON0, 1),
MT6358_BUCK("buck_vpa", VPA, 500000, 3650000, 50000,
buck_volt_range3, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f,
MT6358_VPA_ANA_CON0, 3),
......@@ -488,6 +587,10 @@ static struct mt6358_regulator_info mt6358_regulators[] = {
MT6358_LDO1("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250,
buck_volt_range1, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00,
MT6358_LDO_VSRAM_CON2, 0x7f),
MT6358_LDO1("ldo_vsram_others_sshub", VSRAM_OTHERS_SSHUB, 500000,
1293750, 6250, buck_volt_range1,
MT6358_LDO_VSRAM_OTHERS_SSHUB_CON1, 0x7f,
MT6358_LDO_VSRAM_OTHERS_SSHUB_CON1, 0x7f),
MT6358_LDO1("ldo_vsram_gpu", VSRAM_GPU, 500000, 1293750, 6250,
buck_volt_range1, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00,
MT6358_LDO_VSRAM_CON3, 0x7f),
......@@ -496,24 +599,124 @@ static struct mt6358_regulator_info mt6358_regulators[] = {
MT6358_LDO_VSRAM_CON1, 0x7f),
};
/* The array is indexed by id(MT6366_ID_XXX) */
static struct mt6358_regulator_info mt6366_regulators[] = {
MT6366_BUCK("buck_vdram1", VDRAM1, 500000, 2087500, 12500,
buck_volt_range2, 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f,
MT6358_VDRAM1_ANA_CON0, 8),
MT6366_BUCK("buck_vcore", VCORE, 500000, 1293750, 6250,
buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f,
MT6358_VCORE_VGPU_ANA_CON0, 1),
MT6366_BUCK("buck_vcore_sshub", VCORE_SSHUB, 500000, 1293750, 6250,
buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_SSHUB_ELR0, 0x7f,
MT6358_VCORE_VGPU_ANA_CON0, 1),
MT6366_BUCK("buck_vpa", VPA, 500000, 3650000, 50000,
buck_volt_range3, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f,
MT6358_VPA_ANA_CON0, 3),
MT6366_BUCK("buck_vproc11", VPROC11, 500000, 1293750, 6250,
buck_volt_range1, 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f,
MT6358_VPROC_ANA_CON0, 1),
MT6366_BUCK("buck_vproc12", VPROC12, 500000, 1293750, 6250,
buck_volt_range1, 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f,
MT6358_VPROC_ANA_CON0, 2),
MT6366_BUCK("buck_vgpu", VGPU, 500000, 1293750, 6250,
buck_volt_range1, 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f,
MT6358_VCORE_VGPU_ANA_CON0, 2),
MT6366_BUCK("buck_vs2", VS2, 500000, 2087500, 12500,
buck_volt_range2, 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f,
MT6358_VS2_ANA_CON0, 8),
MT6366_BUCK("buck_vmodem", VMODEM, 500000, 1293750, 6250,
buck_volt_range1, 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f,
MT6358_VMODEM_ANA_CON0, 8),
MT6366_BUCK("buck_vs1", VS1, 1000000, 2587500, 12500,
buck_volt_range4, 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f,
MT6358_VS1_ANA_CON0, 8),
MT6366_REG_FIXED("ldo_vrf12", VRF12,
MT6358_LDO_VRF12_CON0, 0, 1200000),
MT6366_REG_FIXED("ldo_vio18", VIO18,
MT6358_LDO_VIO18_CON0, 0, 1800000),
MT6366_REG_FIXED("ldo_vcn18", VCN18, MT6358_LDO_VCN18_CON0, 0, 1800000),
MT6366_REG_FIXED("ldo_vfe28", VFE28, MT6358_LDO_VFE28_CON0, 0, 2800000),
MT6366_REG_FIXED("ldo_vcn28", VCN28, MT6358_LDO_VCN28_CON0, 0, 2800000),
MT6366_REG_FIXED("ldo_vxo22", VXO22, MT6358_LDO_VXO22_CON0, 0, 2200000),
MT6366_REG_FIXED("ldo_vaux18", VAUX18,
MT6358_LDO_VAUX18_CON0, 0, 1800000),
MT6366_REG_FIXED("ldo_vbif28", VBIF28,
MT6358_LDO_VBIF28_CON0, 0, 2800000),
MT6366_REG_FIXED("ldo_vio28", VIO28, MT6358_LDO_VIO28_CON0, 0, 2800000),
MT6366_REG_FIXED("ldo_va12", VA12, MT6358_LDO_VA12_CON0, 0, 1200000),
MT6366_REG_FIXED("ldo_vrf18", VRF18, MT6358_LDO_VRF18_CON0, 0, 1800000),
MT6366_REG_FIXED("ldo_vaud28", VAUD28,
MT6358_LDO_VAUD28_CON0, 0, 2800000),
MT6366_LDO("ldo_vdram2", VDRAM2, vdram2_voltages, vdram2_idx,
MT6358_LDO_VDRAM2_CON0, 0, MT6358_LDO_VDRAM2_ELR0, 0x10),
MT6366_LDO("ldo_vsim1", VSIM1, vsim_voltages, vsim_idx,
MT6358_LDO_VSIM1_CON0, 0, MT6358_VSIM1_ANA_CON0, 0xf00),
MT6366_LDO("ldo_vibr", VIBR, vibr_voltages, vibr_idx,
MT6358_LDO_VIBR_CON0, 0, MT6358_VIBR_ANA_CON0, 0xf00),
MT6366_LDO("ldo_vusb", VUSB, vusb_voltages, vusb_idx,
MT6358_LDO_VUSB_CON0_0, 0, MT6358_VUSB_ANA_CON0, 0x700),
MT6366_LDO("ldo_vefuse", VEFUSE, vefuse_voltages, vefuse_idx,
MT6358_LDO_VEFUSE_CON0, 0, MT6358_VEFUSE_ANA_CON0, 0xf00),
MT6366_LDO("ldo_vmch", VMCH, vmch_vemc_voltages, vmch_vemc_idx,
MT6358_LDO_VMCH_CON0, 0, MT6358_VMCH_ANA_CON0, 0x700),
MT6366_LDO("ldo_vemc", VEMC, vmch_vemc_voltages, vmch_vemc_idx,
MT6358_LDO_VEMC_CON0, 0, MT6358_VEMC_ANA_CON0, 0x700),
MT6366_LDO("ldo_vcn33_bt", VCN33_BT, vcn33_bt_wifi_voltages,
vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_0,
0, MT6358_VCN33_ANA_CON0, 0x300),
MT6366_LDO("ldo_vcn33_wifi", VCN33_WIFI, vcn33_bt_wifi_voltages,
vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_1,
0, MT6358_VCN33_ANA_CON0, 0x300),
MT6366_LDO("ldo_vmc", VMC, vmc_voltages, vmc_idx,
MT6358_LDO_VMC_CON0, 0, MT6358_VMC_ANA_CON0, 0xf00),
MT6366_LDO("ldo_vsim2", VSIM2, vsim_voltages, vsim_idx,
MT6358_LDO_VSIM2_CON0, 0, MT6358_VSIM2_ANA_CON0, 0xf00),
MT6366_LDO1("ldo_vsram_proc11", VSRAM_PROC11, 500000, 1293750, 6250,
buck_volt_range1, MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f00,
MT6358_LDO_VSRAM_CON0, 0x7f),
MT6366_LDO1("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250,
buck_volt_range1, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00,
MT6358_LDO_VSRAM_CON2, 0x7f),
MT6366_LDO1("ldo_vsram_others_sshub", VSRAM_OTHERS_SSHUB, 500000,
1293750, 6250, buck_volt_range1,
MT6358_LDO_VSRAM_OTHERS_SSHUB_CON1, 0x7f,
MT6358_LDO_VSRAM_OTHERS_SSHUB_CON1, 0x7f),
MT6366_LDO1("ldo_vsram_gpu", VSRAM_GPU, 500000, 1293750, 6250,
buck_volt_range1, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00,
MT6358_LDO_VSRAM_CON3, 0x7f),
MT6366_LDO1("ldo_vsram_proc12", VSRAM_PROC12, 500000, 1293750, 6250,
buck_volt_range1, MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f00,
MT6358_LDO_VSRAM_CON1, 0x7f),
};
static int mt6358_regulator_probe(struct platform_device *pdev)
{
struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = {};
struct regulator_dev *rdev;
int i;
struct mt6358_regulator_info *mt6358_info;
int i, max_regulator;
if (mt6397->chip_id == MT6366_CHIP_ID) {
max_regulator = MT6366_MAX_REGULATOR;
mt6358_info = mt6366_regulators;
} else {
max_regulator = MT6358_MAX_REGULATOR;
mt6358_info = mt6358_regulators;
}
for (i = 0; i < MT6358_MAX_REGULATOR; i++) {
for (i = 0; i < max_regulator; i++) {
config.dev = &pdev->dev;
config.driver_data = &mt6358_regulators[i];
config.driver_data = &mt6358_info[i];
config.regmap = mt6397->regmap;
rdev = devm_regulator_register(&pdev->dev,
&mt6358_regulators[i].desc,
&mt6358_info[i].desc,
&config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register %s\n",
mt6358_regulators[i].desc.name);
mt6358_info[i].desc.name);
return PTR_ERR(rdev);
}
}
......
......@@ -174,6 +174,14 @@ static int buck_set_dvs(const struct regulator_desc *desc,
}
}
if (ret == 0) {
struct pca9450_regulator_desc *regulator = container_of(desc,
struct pca9450_regulator_desc, desc);
/* Enable DVS control through PMIC_STBY_REQ for this BUCK */
ret = regmap_update_bits(regmap, regulator->desc.enable_reg,
BUCK1_DVS_CTRL, BUCK1_DVS_CTRL);
}
return ret;
}
......@@ -702,6 +710,7 @@ static int pca9450_i2c_probe(struct i2c_client *i2c,
struct regulator_config config = { };
struct pca9450 *pca9450;
unsigned int device_id, i;
unsigned int reset_ctrl;
int ret;
if (!i2c->irq) {
......@@ -802,14 +811,30 @@ static int pca9450_i2c_probe(struct i2c_client *i2c,
return ret;
}
if (of_property_read_bool(i2c->dev.of_node, "nxp,wdog_b-warm-reset"))
reset_ctrl = WDOG_B_CFG_WARM;
else
reset_ctrl = WDOG_B_CFG_COLD_LDO12;
/* Set reset behavior on assertion of WDOG_B signal */
ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_RESET_CTRL,
WDOG_B_CFG_MASK, WDOG_B_CFG_COLD_LDO12);
WDOG_B_CFG_MASK, reset_ctrl);
if (ret) {
dev_err(&i2c->dev, "Failed to set WDOG_B reset behavior\n");
return ret;
}
if (of_property_read_bool(i2c->dev.of_node, "nxp,i2c-lt-enable")) {
/* Enable I2C Level Translator */
ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_CONFIG2,
I2C_LT_MASK, I2C_LT_ON_STANDBY_RUN);
if (ret) {
dev_err(&i2c->dev,
"Failed to enable I2C level translator\n");
return ret;
}
}
/*
* The driver uses the LDO5CTRL_H register to control the LDO5 regulator.
* This is only valid if the SD_VSEL input of the PMIC is high. Let's
......
......@@ -521,6 +521,7 @@ static int pfuze_parse_regulators_dt(struct pfuze_chip *chip)
parent = of_get_child_by_name(np, "regulators");
if (!parent) {
dev_err(dev, "regulators node not found\n");
of_node_put(np);
return -EINVAL;
}
......@@ -550,6 +551,7 @@ static int pfuze_parse_regulators_dt(struct pfuze_chip *chip)
}
of_node_put(parent);
of_node_put(np);
if (ret < 0) {
dev_err(dev, "Error parsing regulator init data: %d\n",
ret);
......
......@@ -944,32 +944,31 @@ static const struct rpm_regulator_data rpm_pm8950_regulators[] = {
{ "s2", QCOM_SMD_RPM_SMPA, 2, &pm8950_hfsmps, "vdd_s2" },
{ "s3", QCOM_SMD_RPM_SMPA, 3, &pm8950_hfsmps, "vdd_s3" },
{ "s4", QCOM_SMD_RPM_SMPA, 4, &pm8950_hfsmps, "vdd_s4" },
{ "s5", QCOM_SMD_RPM_SMPA, 5, &pm8950_ftsmps2p5, "vdd_s5" },
/* S5 is managed via SPMI. */
{ "s6", QCOM_SMD_RPM_SMPA, 6, &pm8950_hfsmps, "vdd_s6" },
{ "l1", QCOM_SMD_RPM_LDOA, 1, &pm8950_ult_nldo, "vdd_l1_l19" },
{ "l2", QCOM_SMD_RPM_LDOA, 2, &pm8950_ult_nldo, "vdd_l2_l23" },
{ "l3", QCOM_SMD_RPM_LDOA, 3, &pm8950_ult_nldo, "vdd_l3" },
{ "l4", QCOM_SMD_RPM_LDOA, 4, &pm8950_ult_pldo, "vdd_l4_l5_l6_l7_l16" },
{ "l5", QCOM_SMD_RPM_LDOA, 5, &pm8950_pldo_lv, "vdd_l4_l5_l6_l7_l16" },
{ "l6", QCOM_SMD_RPM_LDOA, 6, &pm8950_pldo_lv, "vdd_l4_l5_l6_l7_l16" },
{ "l7", QCOM_SMD_RPM_LDOA, 7, &pm8950_pldo_lv, "vdd_l4_l5_l6_l7_l16" },
/* L4 seems not to exist. */
{ "l5", QCOM_SMD_RPM_LDOA, 5, &pm8950_pldo_lv, "vdd_l5_l6_l7_l16" },
{ "l6", QCOM_SMD_RPM_LDOA, 6, &pm8950_pldo_lv, "vdd_l5_l6_l7_l16" },
{ "l7", QCOM_SMD_RPM_LDOA, 7, &pm8950_pldo_lv, "vdd_l5_l6_l7_l16" },
{ "l8", QCOM_SMD_RPM_LDOA, 8, &pm8950_ult_pldo, "vdd_l8_l11_l12_l17_l22" },
{ "l9", QCOM_SMD_RPM_LDOA, 9, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18" },
{ "l10", QCOM_SMD_RPM_LDOA, 10, &pm8950_ult_nldo, "vdd_l9_l10_l13_l14_l15_l18"},
{ "l11", QCOM_SMD_RPM_LDOA, 11, &pm8950_ult_pldo, "vdd_l8_l11_l12_l17_l22"},
{ "l12", QCOM_SMD_RPM_LDOA, 12, &pm8950_ult_pldo, "vdd_l8_l11_l12_l17_l22"},
{ "l13", QCOM_SMD_RPM_LDOA, 13, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18"},
{ "l14", QCOM_SMD_RPM_LDOA, 14, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18"},
{ "l15", QCOM_SMD_RPM_LDOA, 15, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18"},
{ "l16", QCOM_SMD_RPM_LDOA, 16, &pm8950_ult_pldo, "vdd_l4_l5_l6_l7_l16"},
{ "l17", QCOM_SMD_RPM_LDOA, 17, &pm8950_ult_pldo, "vdd_l8_l11_l12_l17_l22"},
{ "l18", QCOM_SMD_RPM_LDOA, 18, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18"},
{ "l19", QCOM_SMD_RPM_LDOA, 18, &pm8950_pldo, "vdd_l1_l19"},
{ "l20", QCOM_SMD_RPM_LDOA, 18, &pm8950_pldo, "vdd_l20"},
{ "l21", QCOM_SMD_RPM_LDOA, 18, &pm8950_pldo, "vdd_l21"},
{ "l22", QCOM_SMD_RPM_LDOA, 18, &pm8950_pldo, "vdd_l8_l11_l12_l17_l22"},
{ "l23", QCOM_SMD_RPM_LDOA, 18, &pm8950_pldo, "vdd_l2_l23"},
{ "l11", QCOM_SMD_RPM_LDOA, 11, &pm8950_ult_pldo, "vdd_l8_l11_l12_l17_l22" },
{ "l12", QCOM_SMD_RPM_LDOA, 12, &pm8950_ult_pldo, "vdd_l8_l11_l12_l17_l22" },
{ "l13", QCOM_SMD_RPM_LDOA, 13, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18" },
{ "l14", QCOM_SMD_RPM_LDOA, 14, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18" },
{ "l15", QCOM_SMD_RPM_LDOA, 15, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18" },
{ "l16", QCOM_SMD_RPM_LDOA, 16, &pm8950_ult_pldo, "vdd_l5_l6_l7_l16" },
{ "l17", QCOM_SMD_RPM_LDOA, 17, &pm8950_ult_pldo, "vdd_l8_l11_l12_l17_l22" },
/* L18 seems not to exist. */
{ "l19", QCOM_SMD_RPM_LDOA, 19, &pm8950_pldo, "vdd_l1_l19" },
/* L20 & L21 seem not to exist. */
{ "l22", QCOM_SMD_RPM_LDOA, 22, &pm8950_pldo, "vdd_l8_l11_l12_l17_l22" },
{ "l23", QCOM_SMD_RPM_LDOA, 23, &pm8950_pldo, "vdd_l2_l23" },
{}
};
......
......@@ -364,7 +364,6 @@ static int attiny_i2c_probe(struct i2c_client *i2c,
state->gc.parent = &i2c->dev;
state->gc.label = i2c->name;
state->gc.owner = THIS_MODULE;
state->gc.of_node = i2c->dev.of_node;
state->gc.base = -1;
state->gc.ngpio = NUM_GPIO;
......
......@@ -29,11 +29,33 @@
struct rt4801_priv {
struct device *dev;
struct gpio_descs *enable_gpios;
struct gpio_desc *enable_gpios[DSV_OUT_MAX];
unsigned int enable_flag;
unsigned int volt_sel[DSV_OUT_MAX];
};
static int rt4801_of_parse_cb(struct device_node *np,
const struct regulator_desc *desc,
struct regulator_config *config)
{
struct rt4801_priv *priv = config->driver_data;
int id = desc->id;
if (priv->enable_gpios[id]) {
dev_warn(priv->dev, "duplicated enable-gpios property\n");
return 0;
}
priv->enable_gpios[id] = devm_fwnode_gpiod_get_index(priv->dev,
of_fwnode_handle(np),
"enable", 0,
GPIOD_OUT_HIGH,
"rt4801");
if (IS_ERR(priv->enable_gpios[id]))
priv->enable_gpios[id] = NULL;
return 0;
}
static int rt4801_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector)
{
struct rt4801_priv *priv = rdev_get_drvdata(rdev);
......@@ -63,15 +85,14 @@ static int rt4801_get_voltage_sel(struct regulator_dev *rdev)
static int rt4801_enable(struct regulator_dev *rdev)
{
struct rt4801_priv *priv = rdev_get_drvdata(rdev);
struct gpio_descs *gpios = priv->enable_gpios;
int id = rdev_get_id(rdev), ret;
if (!gpios || gpios->ndescs <= id) {
if (!priv->enable_gpios[id]) {
dev_warn(&rdev->dev, "no dedicated gpio can control\n");
goto bypass_gpio;
}
gpiod_set_value(gpios->desc[id], 1);
gpiod_set_value(priv->enable_gpios[id], 1);
bypass_gpio:
ret = regmap_write(rdev->regmap, rdev->desc->vsel_reg, priv->volt_sel[id]);
......@@ -85,15 +106,14 @@ static int rt4801_enable(struct regulator_dev *rdev)
static int rt4801_disable(struct regulator_dev *rdev)
{
struct rt4801_priv *priv = rdev_get_drvdata(rdev);
struct gpio_descs *gpios = priv->enable_gpios;
int id = rdev_get_id(rdev);
if (!gpios || gpios->ndescs <= id) {
if (!priv->enable_gpios[id]) {
dev_warn(&rdev->dev, "no dedicated gpio can control\n");
goto bypass_gpio;
}
gpiod_set_value(gpios->desc[id], 0);
gpiod_set_value(priv->enable_gpios[id], 0);
bypass_gpio:
priv->enable_flag &= ~BIT(id);
......@@ -122,6 +142,7 @@ static const struct regulator_desc rt4801_regulator_descs[] = {
.name = "DSVP",
.ops = &rt4801_regulator_ops,
.of_match = of_match_ptr("DSVP"),
.of_parse_cb = rt4801_of_parse_cb,
.type = REGULATOR_VOLTAGE,
.id = DSV_OUT_POS,
.min_uV = MIN_UV,
......@@ -135,6 +156,7 @@ static const struct regulator_desc rt4801_regulator_descs[] = {
.name = "DSVN",
.ops = &rt4801_regulator_ops,
.of_match = of_match_ptr("DSVN"),
.of_parse_cb = rt4801_of_parse_cb,
.type = REGULATOR_VOLTAGE,
.id = DSV_OUT_NEG,
.min_uV = MIN_UV,
......@@ -172,10 +194,15 @@ static int rt4801_probe(struct i2c_client *i2c)
return PTR_ERR(regmap);
}
priv->enable_gpios = devm_gpiod_get_array_optional(&i2c->dev, "enable", GPIOD_OUT_HIGH);
if (IS_ERR(priv->enable_gpios)) {
for (i = 0; i < DSV_OUT_MAX; i++) {
priv->enable_gpios[i] = devm_gpiod_get_index_optional(&i2c->dev,
"enable",
i,
GPIOD_OUT_HIGH);
if (IS_ERR(priv->enable_gpios[i])) {
dev_err(&i2c->dev, "Failed to get gpios\n");
return PTR_ERR(priv->enable_gpios);
return PTR_ERR(priv->enable_gpios[i]);
}
}
for (i = 0; i < DSV_OUT_MAX; i++) {
......
// SPDX-License-Identifier: GPL-2.0+
#include <linux/bits.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
#define RT5759_REG_VENDORINFO 0x00
#define RT5759_REG_FREQ 0x01
#define RT5759_REG_VSEL 0x02
#define RT5759_REG_DCDCCTRL 0x03
#define RT5759_REG_STATUS 0x04
#define RT5759_REG_DCDCSET 0x05
#define RT5759A_REG_WDTEN 0x42
#define RT5759_TSTEP_MASK GENMASK(3, 2)
#define RT5759_VSEL_MASK GENMASK(6, 0)
#define RT5759_DISCHARGE_MASK BIT(3)
#define RT5759_FPWM_MASK BIT(2)
#define RT5759_ENABLE_MASK BIT(1)
#define RT5759_OT_MASK BIT(1)
#define RT5759_UV_MASK BIT(0)
#define RT5957_OCLVL_MASK GENMASK(7, 6)
#define RT5759_OCLVL_SHIFT 6
#define RT5957_OTLVL_MASK GENMASK(5, 4)
#define RT5759_OTLVL_SHIFT 4
#define RT5759A_WDTEN_MASK BIT(1)
#define RT5759_MANUFACTURER_ID 0x82
/* vsel range 0x00 ~ 0x5A */
#define RT5759_NUM_VOLTS 91
#define RT5759_MIN_UV 600000
#define RT5759_STEP_UV 10000
#define RT5759A_STEP_UV 12500
#define RT5759_MINSS_TIMEUS 1500
#define RT5759_PSKIP_MODE 0
#define RT5759_FPWM_MODE 1
enum {
CHIP_TYPE_RT5759 = 0,
CHIP_TYPE_RT5759A,
CHIP_TYPE_MAX
};
struct rt5759_priv {
struct device *dev;
struct regmap *regmap;
struct regulator_desc desc;
unsigned long chip_type;
};
static int rt5759_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct regmap *regmap = rdev_get_regmap(rdev);
unsigned int mode_val;
switch (mode) {
case REGULATOR_MODE_NORMAL:
mode_val = 0;
break;
case REGULATOR_MODE_FAST:
mode_val = RT5759_FPWM_MASK;
break;
default:
return -EINVAL;
}
return regmap_update_bits(regmap, RT5759_REG_STATUS, RT5759_FPWM_MASK,
mode_val);
}
static unsigned int rt5759_get_mode(struct regulator_dev *rdev)
{
struct regmap *regmap = rdev_get_regmap(rdev);
unsigned int regval;
int ret;
ret = regmap_read(regmap, RT5759_REG_DCDCCTRL, &regval);
if (ret)
return REGULATOR_MODE_INVALID;
if (regval & RT5759_FPWM_MASK)
return REGULATOR_MODE_FAST;
return REGULATOR_MODE_NORMAL;
}
static int rt5759_get_error_flags(struct regulator_dev *rdev,
unsigned int *flags)
{
struct regmap *regmap = rdev_get_regmap(rdev);
unsigned int status, events = 0;
int ret;
ret = regmap_read(regmap, RT5759_REG_STATUS, &status);
if (ret)
return ret;
if (status & RT5759_OT_MASK)
events |= REGULATOR_ERROR_OVER_TEMP;
if (status & RT5759_UV_MASK)
events |= REGULATOR_ERROR_UNDER_VOLTAGE;
*flags = events;
return 0;
}
static int rt5759_set_ocp(struct regulator_dev *rdev, int lim_uA, int severity,
bool enable)
{
struct regmap *regmap = rdev_get_regmap(rdev);
int ocp_lvl[] = { 9800000, 10800000, 11800000 };
unsigned int ocp_regval;
int i;
/* Only support over current protection parameter */
if (severity != REGULATOR_SEVERITY_PROT)
return 0;
if (enable) {
/* Default ocp level is 10.8A */
if (lim_uA == 0)
lim_uA = 10800000;
for (i = 0; i < ARRAY_SIZE(ocp_lvl); i++) {
if (lim_uA <= ocp_lvl[i])
break;
}
if (i == ARRAY_SIZE(ocp_lvl))
i = ARRAY_SIZE(ocp_lvl) - 1;
ocp_regval = i + 1;
} else
ocp_regval = 0;
return regmap_update_bits(regmap, RT5759_REG_DCDCSET, RT5957_OCLVL_MASK,
ocp_regval << RT5759_OCLVL_SHIFT);
}
static int rt5759_set_otp(struct regulator_dev *rdev, int lim, int severity,
bool enable)
{
struct regmap *regmap = rdev_get_regmap(rdev);
int otp_lvl[] = { 140, 150, 170 };
unsigned int otp_regval;
int i;
/* Only support over temperature protection parameter */
if (severity != REGULATOR_SEVERITY_PROT)
return 0;
if (enable) {
/* Default otp level is 150'c */
if (lim == 0)
lim = 150;
for (i = 0; i < ARRAY_SIZE(otp_lvl); i++) {
if (lim <= otp_lvl[i])
break;
}
if (i == ARRAY_SIZE(otp_lvl))
i = ARRAY_SIZE(otp_lvl) - 1;
otp_regval = i + 1;
} else
otp_regval = 0;
return regmap_update_bits(regmap, RT5759_REG_DCDCSET, RT5957_OTLVL_MASK,
otp_regval << RT5759_OTLVL_SHIFT);
}
static const struct regulator_ops rt5759_regulator_ops = {
.list_voltage = regulator_list_voltage_linear,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.set_active_discharge = regulator_set_active_discharge_regmap,
.set_mode = rt5759_set_mode,
.get_mode = rt5759_get_mode,
.set_ramp_delay = regulator_set_ramp_delay_regmap,
.get_error_flags = rt5759_get_error_flags,
.set_over_current_protection = rt5759_set_ocp,
.set_thermal_protection = rt5759_set_otp,
};
static unsigned int rt5759_of_map_mode(unsigned int mode)
{
switch (mode) {
case RT5759_FPWM_MODE:
return REGULATOR_MODE_FAST;
case RT5759_PSKIP_MODE:
return REGULATOR_MODE_NORMAL;
default:
return REGULATOR_MODE_INVALID;
}
}
static const unsigned int rt5759_ramp_table[] = { 20000, 15000, 10000, 5000 };
static int rt5759_regulator_register(struct rt5759_priv *priv)
{
struct device_node *np = priv->dev->of_node;
struct regulator_desc *reg_desc = &priv->desc;
struct regulator_config reg_cfg;
struct regulator_dev *rdev;
int ret;
reg_desc->name = "rt5759-buck";
reg_desc->type = REGULATOR_VOLTAGE;
reg_desc->owner = THIS_MODULE;
reg_desc->ops = &rt5759_regulator_ops;
reg_desc->n_voltages = RT5759_NUM_VOLTS;
reg_desc->min_uV = RT5759_MIN_UV;
reg_desc->uV_step = RT5759_STEP_UV;
reg_desc->vsel_reg = RT5759_REG_VSEL;
reg_desc->vsel_mask = RT5759_VSEL_MASK;
reg_desc->enable_reg = RT5759_REG_DCDCCTRL;
reg_desc->enable_mask = RT5759_ENABLE_MASK;
reg_desc->active_discharge_reg = RT5759_REG_DCDCCTRL;
reg_desc->active_discharge_mask = RT5759_DISCHARGE_MASK;
reg_desc->active_discharge_on = RT5759_DISCHARGE_MASK;
reg_desc->ramp_reg = RT5759_REG_FREQ;
reg_desc->ramp_mask = RT5759_TSTEP_MASK;
reg_desc->ramp_delay_table = rt5759_ramp_table;
reg_desc->n_ramp_values = ARRAY_SIZE(rt5759_ramp_table);
reg_desc->enable_time = RT5759_MINSS_TIMEUS;
reg_desc->of_map_mode = rt5759_of_map_mode;
/*
* RT5759 step uV = 10000
* RT5759A step uV = 12500
*/
if (priv->chip_type == CHIP_TYPE_RT5759A)
reg_desc->uV_step = RT5759A_STEP_UV;
reg_cfg.dev = priv->dev;
reg_cfg.of_node = np;
reg_cfg.init_data = of_get_regulator_init_data(priv->dev, np, reg_desc);
reg_cfg.regmap = priv->regmap;
rdev = devm_regulator_register(priv->dev, reg_desc, &reg_cfg);
if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev);
dev_err(priv->dev, "Failed to register regulator (%d)\n", ret);
return ret;
}
return 0;
}
static int rt5759_init_device_property(struct rt5759_priv *priv)
{
unsigned int val = 0;
/*
* Only RT5759A support external watchdog input
*/
if (priv->chip_type != CHIP_TYPE_RT5759A)
return 0;
if (device_property_read_bool(priv->dev, "richtek,watchdog-enable"))
val = RT5759A_WDTEN_MASK;
return regmap_update_bits(priv->regmap, RT5759A_REG_WDTEN,
RT5759A_WDTEN_MASK, val);
}
static int rt5759_manufacturer_check(struct rt5759_priv *priv)
{
unsigned int vendor;
int ret;
ret = regmap_read(priv->regmap, RT5759_REG_VENDORINFO, &vendor);
if (ret)
return ret;
if (vendor != RT5759_MANUFACTURER_ID) {
dev_err(priv->dev, "vendor info not correct (%d)\n", vendor);
return -EINVAL;
}
return 0;
}
static bool rt5759_is_accessible_reg(struct device *dev, unsigned int reg)
{
struct rt5759_priv *priv = dev_get_drvdata(dev);
if (reg <= RT5759_REG_DCDCSET)
return true;
if (priv->chip_type == CHIP_TYPE_RT5759A && reg == RT5759A_REG_WDTEN)
return true;
return false;
}
static const struct regmap_config rt5759_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = RT5759A_REG_WDTEN,
.readable_reg = rt5759_is_accessible_reg,
.writeable_reg = rt5759_is_accessible_reg,
};
static int rt5759_probe(struct i2c_client *i2c)
{
struct rt5759_priv *priv;
int ret;
priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->dev = &i2c->dev;
priv->chip_type = (unsigned long)of_device_get_match_data(&i2c->dev);
i2c_set_clientdata(i2c, priv);
priv->regmap = devm_regmap_init_i2c(i2c, &rt5759_regmap_config);
if (IS_ERR(priv->regmap)) {
ret = PTR_ERR(priv->regmap);
dev_err(&i2c->dev, "Failed to allocate regmap (%d)\n", ret);
return ret;
}
ret = rt5759_manufacturer_check(priv);
if (ret) {
dev_err(&i2c->dev, "Failed to check device (%d)\n", ret);
return ret;
}
ret = rt5759_init_device_property(priv);
if (ret) {
dev_err(&i2c->dev, "Failed to init device (%d)\n", ret);
return ret;
}
return rt5759_regulator_register(priv);
}
static const struct of_device_id __maybe_unused rt5759_device_table[] = {
{ .compatible = "richtek,rt5759", .data = (void *)CHIP_TYPE_RT5759 },
{ .compatible = "richtek,rt5759a", .data = (void *)CHIP_TYPE_RT5759A },
{}
};
MODULE_DEVICE_TABLE(of, rt5759_device_table);
static struct i2c_driver rt5759_driver = {
.driver = {
.name = "rt5759",
.of_match_table = of_match_ptr(rt5759_device_table),
},
.probe_new = rt5759_probe,
};
module_i2c_driver(rt5759_driver);
MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
MODULE_DESCRIPTION("Richtek RT5759 Regulator Driver");
MODULE_LICENSE("GPL v2");
......@@ -352,7 +352,7 @@ static int scmi_regulator_probe(struct scmi_device *sdev)
return ret;
}
}
of_node_put(np);
/*
* Register a regulator for each valid regulator-DT-entry that we
* can successfully reach via SCMI and has a valid associated voltage
......
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/mfd/sm5703.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
enum sm5703_regulators {
SM5703_BUCK,
SM5703_LDO1,
SM5703_LDO2,
SM5703_LDO3,
SM5703_USBLDO1,
SM5703_USBLDO2,
SM5703_VBUS,
SM5703_MAX_REGULATORS,
};
static const int sm5703_ldo_voltagemap[] = {
1500000, 1800000, 2600000, 2800000, 3000000, 3300000,
};
static const int sm5703_buck_voltagemap[] = {
1000000, 1000000, 1000000, 1000000,
1000000, 1000000, 1000000, 1000000,
1000000, 1000000, 1000000, 1100000,
1200000, 1300000, 1400000, 1500000,
1600000, 1700000, 1800000, 1900000,
2000000, 2100000, 2200000, 2300000,
2400000, 2500000, 2600000, 2700000,
2800000, 2900000, 3000000, 3000000,
};
#define SM5703USBLDO(_name, _id) \
[SM5703_USBLDO ## _id] = { \
.name = _name, \
.of_match = _name, \
.regulators_node = "regulators", \
.type = REGULATOR_VOLTAGE, \
.id = SM5703_USBLDO ## _id, \
.ops = &sm5703_regulator_ops_fixed, \
.fixed_uV = SM5703_USBLDO_MICROVOLT, \
.enable_reg = SM5703_REG_USBLDO12, \
.enable_mask = SM5703_REG_EN_USBLDO ##_id, \
.owner = THIS_MODULE, \
}
#define SM5703VBUS(_name) \
[SM5703_VBUS] = { \
.name = _name, \
.of_match = _name, \
.regulators_node = "regulators", \
.type = REGULATOR_VOLTAGE, \
.id = SM5703_VBUS, \
.ops = &sm5703_regulator_ops_fixed, \
.fixed_uV = SM5703_VBUS_MICROVOLT, \
.enable_reg = SM5703_REG_CNTL, \
.enable_mask = SM5703_OPERATION_MODE_MASK, \
.enable_val = SM5703_OPERATION_MODE_USB_OTG_MODE, \
.disable_val = SM5703_OPERATION_MODE_CHARGING_ON, \
.owner = THIS_MODULE, \
}
#define SM5703BUCK(_name) \
[SM5703_BUCK] = { \
.name = _name, \
.of_match = _name, \
.regulators_node = "regulators", \
.type = REGULATOR_VOLTAGE, \
.id = SM5703_BUCK, \
.ops = &sm5703_regulator_ops, \
.n_voltages = ARRAY_SIZE(sm5703_buck_voltagemap), \
.volt_table = sm5703_buck_voltagemap, \
.vsel_reg = SM5703_REG_BUCK, \
.vsel_mask = SM5703_BUCK_VOLT_MASK, \
.enable_reg = SM5703_REG_BUCK, \
.enable_mask = SM5703_REG_EN_BUCK, \
.owner = THIS_MODULE, \
}
#define SM5703LDO(_name, _id) \
[SM5703_LDO ## _id] = { \
.name = _name, \
.of_match = _name, \
.regulators_node = "regulators", \
.type = REGULATOR_VOLTAGE, \
.id = SM5703_LDO ## _id, \
.ops = &sm5703_regulator_ops, \
.n_voltages = ARRAY_SIZE(sm5703_ldo_voltagemap), \
.volt_table = sm5703_ldo_voltagemap, \
.vsel_reg = SM5703_REG_LDO ##_id, \
.vsel_mask = SM5703_LDO_VOLT_MASK, \
.enable_reg = SM5703_REG_LDO ##_id, \
.enable_mask = SM5703_LDO_EN, \
.owner = THIS_MODULE, \
}
static const struct regulator_ops sm5703_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.list_voltage = regulator_list_voltage_table,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
};
static const struct regulator_ops sm5703_regulator_ops_fixed = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
};
static struct regulator_desc sm5703_regulators_desc[SM5703_MAX_REGULATORS] = {
SM5703BUCK("buck"),
SM5703LDO("ldo1", 1),
SM5703LDO("ldo2", 2),
SM5703LDO("ldo3", 3),
SM5703USBLDO("usbldo1", 1),
SM5703USBLDO("usbldo2", 2),
SM5703VBUS("vbus"),
};
static int sm5703_regulator_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct regulator_config config = { NULL, };
struct regulator_dev *rdev;
struct sm5703_dev *sm5703 = dev_get_drvdata(pdev->dev.parent);
int i;
config.dev = dev->parent;
config.regmap = sm5703->regmap;
for (i = 0; i < SM5703_MAX_REGULATORS; i++) {
rdev = devm_regulator_register(dev,
&sm5703_regulators_desc[i],
&config);
if (IS_ERR(rdev))
return dev_err_probe(dev, PTR_ERR(rdev),
"Failed to register a regulator\n");
}
return 0;
}
static const struct platform_device_id sm5703_regulator_id[] = {
{ "sm5703-regulator", 0 },
{}
};
MODULE_DEVICE_TABLE(platform, sm5703_regulator_id);
static struct platform_driver sm5703_regulator_driver = {
.driver = {
.name = "sm5703-regulator",
},
.probe = sm5703_regulator_probe,
.id_table = sm5703_regulator_id,
};
module_platform_driver(sm5703_regulator_driver);
MODULE_DESCRIPTION("Silicon Mitus SM5703 LDO/Buck/USB regulator driver");
MODULE_AUTHOR("Markuss Broks <markuss.broks@gmail.com>");
MODULE_LICENSE("GPL");
......@@ -44,11 +44,9 @@ static int stm32_vrefbuf_enable(struct regulator_dev *rdev)
u32 val;
int ret;
ret = pm_runtime_get_sync(priv->dev);
if (ret < 0) {
pm_runtime_put_noidle(priv->dev);
ret = pm_runtime_resume_and_get(priv->dev);
if (ret < 0)
return ret;
}
val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
val = (val & ~STM32_HIZ) | STM32_ENVR;
......@@ -81,11 +79,9 @@ static int stm32_vrefbuf_disable(struct regulator_dev *rdev)
u32 val;
int ret;
ret = pm_runtime_get_sync(priv->dev);
if (ret < 0) {
pm_runtime_put_noidle(priv->dev);
ret = pm_runtime_resume_and_get(priv->dev);
if (ret < 0)
return ret;
}
val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
val &= ~STM32_ENVR;
......@@ -102,11 +98,9 @@ static int stm32_vrefbuf_is_enabled(struct regulator_dev *rdev)
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
int ret;
ret = pm_runtime_get_sync(priv->dev);
if (ret < 0) {
pm_runtime_put_noidle(priv->dev);
ret = pm_runtime_resume_and_get(priv->dev);
if (ret < 0)
return ret;
}
ret = readl_relaxed(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR;
......@@ -123,11 +117,9 @@ static int stm32_vrefbuf_set_voltage_sel(struct regulator_dev *rdev,
u32 val;
int ret;
ret = pm_runtime_get_sync(priv->dev);
if (ret < 0) {
pm_runtime_put_noidle(priv->dev);
ret = pm_runtime_resume_and_get(priv->dev);
if (ret < 0)
return ret;
}
val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
val = (val & ~STM32_VRS) | FIELD_PREP(STM32_VRS, sel);
......@@ -145,11 +137,9 @@ static int stm32_vrefbuf_get_voltage_sel(struct regulator_dev *rdev)
u32 val;
int ret;
ret = pm_runtime_get_sync(priv->dev);
if (ret < 0) {
pm_runtime_put_noidle(priv->dev);
ret = pm_runtime_resume_and_get(priv->dev);
if (ret < 0)
return ret;
}
val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
ret = FIELD_GET(STM32_VRS, val);
......
......@@ -48,9 +48,54 @@ enum {
MT6358_ID_VLDO28,
MT6358_ID_VAUD28,
MT6358_ID_VSIM2,
MT6358_ID_VCORE_SSHUB,
MT6358_ID_VSRAM_OTHERS_SSHUB,
MT6358_ID_RG_MAX,
};
enum {
MT6366_ID_VDRAM1 = 0,
MT6366_ID_VCORE,
MT6366_ID_VPA,
MT6366_ID_VPROC11,
MT6366_ID_VPROC12,
MT6366_ID_VGPU,
MT6366_ID_VS2,
MT6366_ID_VMODEM,
MT6366_ID_VS1,
MT6366_ID_VDRAM2,
MT6366_ID_VSIM1,
MT6366_ID_VIBR,
MT6366_ID_VRF12,
MT6366_ID_VIO18,
MT6366_ID_VUSB,
MT6366_ID_VCN18,
MT6366_ID_VFE28,
MT6366_ID_VSRAM_PROC11,
MT6366_ID_VCN28,
MT6366_ID_VSRAM_OTHERS,
MT6366_ID_VSRAM_GPU,
MT6366_ID_VXO22,
MT6366_ID_VEFUSE,
MT6366_ID_VAUX18,
MT6366_ID_VMCH,
MT6366_ID_VBIF28,
MT6366_ID_VSRAM_PROC12,
MT6366_ID_VEMC,
MT6366_ID_VIO28,
MT6366_ID_VA12,
MT6366_ID_VRF18,
MT6366_ID_VCN33_BT,
MT6366_ID_VCN33_WIFI,
MT6366_ID_VMC,
MT6366_ID_VAUD28,
MT6366_ID_VSIM2,
MT6366_ID_VCORE_SSHUB,
MT6366_ID_VSRAM_OTHERS_SSHUB,
MT6366_ID_RG_MAX,
};
#define MT6358_MAX_REGULATOR MT6358_ID_RG_MAX
#define MT6366_MAX_REGULATOR MT6366_ID_RG_MAX
#endif /* __LINUX_REGULATOR_MT6358_H */
......@@ -226,4 +226,11 @@ enum {
#define WDOG_B_CFG_COLD_LDO12 0x80
#define WDOG_B_CFG_COLD 0xC0
/* PCA9450_REG_CONFIG2 bits */
#define I2C_LT_MASK 0x03
#define I2C_LT_FORCE_DISABLE 0x00
#define I2C_LT_ON_STANDBY_RUN 0x01
#define I2C_LT_ON_RUN 0x02
#define I2C_LT_FORCE_ENABLE 0x03
#endif /* __LINUX_REG_PCA9450_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment