diff options
| author | Mark Brown <broonie@kernel.org> | 2026-10-01 15:01:17 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-10-01 15:01:17 +0100 |
| commit | e40a96a4f9b58bd5f2d45ef44f5c13b48e54081a (patch) | |
| tree | 65a27b510ae4eab2754d5291f4c05f28d385fc1c | |
| parent | 3bd7fb35077f6f4e2000d0981ca0ca0055565509 (diff) | |
| parent | 6722016006986d96906dae1a2880875a9c414759 (diff) | |
| download | linux-next-e40a96a4f9b58bd5f2d45ef44f5c13b48e54081a.tar.gz linux-next-e40a96a4f9b58bd5f2d45ef44f5c13b48e54081a.zip | |
Merge branch 'for-next' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git
47 files changed, 1980 insertions, 488 deletions
diff --git a/Documentation/devicetree/bindings/regulator/maxim,max77620-regulator.yaml b/Documentation/devicetree/bindings/regulator/maxim,max77620-regulator.yaml index 7118c34961ba..0f2901cab8af 100644 --- a/Documentation/devicetree/bindings/regulator/maxim,max77620-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/maxim,max77620-regulator.yaml @@ -10,17 +10,17 @@ maintainers: - Svyatoslav Ryhel <clamor95@gmail.com> description: - Device has multiple DCDC(sd[0-3]) and LDOs(ldo[0-8]). The input supply - of these regulators are defined under parent device node. Details of - regulator properties are defined as child node under sub-node "regulators" - which is child node of device node. + Device has multiple DCDC (sd[0-3], plus sd4 on MAX20024) and LDOs + (ldo[0-8]). The input supply of these regulators are defined under parent + device node. Details of regulator properties are defined as child node under + sub-node "regulators" which is child node of device node. patternProperties: - "^in-(sd[0-3]|ldo(0-1|2|3-5|4-6|7-8))-supply$": + "^in-(sd[0-4]|ldo(0-1|2|3-5|4-6|7-8))-supply$": $ref: /schemas/types.yaml#/definitions/phandle description: Input supply for DCDC or LDO - "^(sd[0-3]|ldo[0-8])$": + "^(sd[0-4]|ldo[0-8])$": type: object $ref: /schemas/regulator/regulator.yaml# unevaluatedProperties: false diff --git a/Documentation/devicetree/bindings/regulator/maxim,max77826.yaml b/Documentation/devicetree/bindings/regulator/maxim,max77826.yaml index 6d6bbfbd26d4..3c02f98a38e9 100644 --- a/Documentation/devicetree/bindings/regulator/maxim,max77826.yaml +++ b/Documentation/devicetree/bindings/regulator/maxim,max77826.yaml @@ -62,6 +62,6 @@ examples: regulator-max-microvolt = <3587500>; }; }; - }; - }; + }; + }; ... diff --git a/Documentation/devicetree/bindings/regulator/maxim,max77838.yaml b/Documentation/devicetree/bindings/regulator/maxim,max77838.yaml index bed36af5493d..bbfc06fbf547 100644 --- a/Documentation/devicetree/bindings/regulator/maxim,max77838.yaml +++ b/Documentation/devicetree/bindings/regulator/maxim,max77838.yaml @@ -63,6 +63,6 @@ examples: regulator-max-microvolt = <1800000>; }; }; - }; - }; + }; + }; ... diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6380-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6380-regulator.yaml new file mode 100644 index 000000000000..0b3c604da727 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6380-regulator.yaml @@ -0,0 +1,117 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/mediatek,mt6380-regulator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT6380 Regulator + +maintainers: + - Sean Wang <sean.wang@mediatek.com> + +properties: + compatible: + const: mediatek,mt6380-regulator + +patternProperties: + '^buck-(vcore1?|vrf)$': + description: BUCK regulators + $ref: regulator.yaml# + unevaluatedProperties: false + + required: + - regulator-min-microvolt + - regulator-max-microvolt + - regulator-ramp-delay + + '^ldo-v([mat]|phy|ddr)$': + type: object + description: LDO regulators + $ref: regulator.yaml# + unevaluatedProperties: false + + required: + - regulator-min-microvolt + - regulator-max-microvolt + - regulator-ramp-delay + +required: + - compatible + +additionalProperties: false + +examples: + - | + regulators { + compatible = "mediatek,mt6380-regulator"; + + buck-vcore1 { + regulator-name = "vcore1"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1393750>; + regulator-ramp-delay = <6250>; + regulator-always-on; + regulator-boot-on; + }; + + buck-vcore { + regulator-name = "vcore"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1393750>; + regulator-ramp-delay = <6250>; + }; + + buck-vrf { + regulator-name = "vrf"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1575000>; + regulator-ramp-delay = <0>; + regulator-always-on; + regulator-boot-on; + }; + + ldo-vm { + regulator-name = "vm"; + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1400000>; + regulator-ramp-delay = <0>; + regulator-always-on; + regulator-boot-on; + }; + + ldo-va { + regulator-name = "va"; + regulator-min-microvolt = <2200000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <0>; + regulator-always-on; + regulator-boot-on; + }; + + ldo-vphy { + regulator-name = "vphy"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <0>; + regulator-always-on; + regulator-boot-on; + }; + + ldo-vddr { + regulator-name = "vddr"; + regulator-min-microvolt = <1240000>; + regulator-max-microvolt = <1840000>; + regulator-ramp-delay = <0>; + regulator-always-on; + regulator-boot-on; + }; + + ldo-vt { + regulator-name = "vt"; + regulator-min-microvolt = <2200000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <0>; + regulator-always-on; + regulator-boot-on; + }; + }; diff --git a/Documentation/devicetree/bindings/regulator/mps,mp5416.yaml b/Documentation/devicetree/bindings/regulator/mps,mp5416.yaml index f825ee9efd81..4b05e07f5537 100644 --- a/Documentation/devicetree/bindings/regulator/mps,mp5416.yaml +++ b/Documentation/devicetree/bindings/regulator/mps,mp5416.yaml @@ -53,26 +53,26 @@ examples: #size-cells = <0>; pmic@69 { - compatible = "mps,mp5416"; - reg = <0x69>; + compatible = "mps,mp5416"; + reg = <0x69>; - regulators { + regulators { - buck1 { - regulator-name = "buck1"; - regulator-min-microvolt = <600000>; - regulator-max-microvolt = <2187500>; - regulator-min-microamp = <3800000>; - regulator-max-microamp = <6800000>; - regulator-boot-on; - }; + buck1 { + regulator-name = "buck1"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <2187500>; + regulator-min-microamp = <3800000>; + regulator-max-microamp = <6800000>; + regulator-boot-on; + }; - ldo2 { - regulator-name = "ldo2"; - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <3975000>; + ldo2 { + regulator-name = "ldo2"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3975000>; + }; }; - }; - }; - }; + }; + }; ... diff --git a/Documentation/devicetree/bindings/regulator/mps,mp886x.yaml b/Documentation/devicetree/bindings/regulator/mps,mp886x.yaml index 374a4f6b1e23..68f64e86e476 100644 --- a/Documentation/devicetree/bindings/regulator/mps,mp886x.yaml +++ b/Documentation/devicetree/bindings/regulator/mps,mp886x.yaml @@ -4,17 +4,30 @@ $id: http://devicetree.org/schemas/regulator/mps,mp886x.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Monolithic Power Systems MP8867/MP8869 voltage regulator +title: Monolithic Power Systems MP8864/MP8867/MP8869 voltage regulator maintainers: - Jisheng Zhang <jszhang@kernel.org> allOf: - $ref: regulator.yaml# + - if: + properties: + compatible: + const: mps,mp8864 + then: + properties: + mps,switch-frequency-hz: + enum: [600000, 850000, 1100000, 1600000] + else: + properties: + mps,switch-frequency-hz: + enum: [500000, 750000, 1000000, 1250000, 1500000] properties: compatible: enum: + - mps,mp8864 - mps,mp8867 - mps,mp8869 @@ -33,7 +46,6 @@ properties: mps,switch-frequency-hz: description: The valid switch frequency in Hertz. - enum: [500000, 750000, 1000000, 1250000, 1500000] required: - compatible @@ -50,13 +62,13 @@ examples: #address-cells = <1>; #size-cells = <0>; regulator@62 { - compatible = "mps,mp8869"; - regulator-name = "vcpu"; - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <1150000>; - enable-gpios = <&porta 1 GPIO_ACTIVE_LOW>; - mps,fb-voltage-divider = <80 240>; - reg = <0x62>; + compatible = "mps,mp8869"; + regulator-name = "vcpu"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1150000>; + enable-gpios = <&porta 1 GPIO_ACTIVE_LOW>; + mps,fb-voltage-divider = <80 240>; + reg = <0x62>; }; }; diff --git a/Documentation/devicetree/bindings/regulator/mps,mpq4210.yaml b/Documentation/devicetree/bindings/regulator/mps,mpq4210.yaml new file mode 100644 index 000000000000..c1914aa1a9d6 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/mps,mpq4210.yaml @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/mps,mpq4210.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Monolithic Power Systems MPQ4210 buck-boost regulator + +maintainers: + - Tapio Reijonen <tapio.reijonen@vaisala.com> + +description: + The MPQ4210 is a synchronous four-switch buck-boost controller with an I2C + interface. The output voltage is programmed through an 11-bit feedback + reference DAC and scaled by an external feedback resistor divider. + + The controller ramps the feedback reference at 38, 50, 75 or 150 mV/ms. + The divider scales the ramp rate along with the voltage, so the output + ramp rates that regulator-ramp-delay can select are those values + multiplied by (R1 + R2) / R2. + +allOf: + - $ref: regulator.yaml# + +properties: + compatible: + const: mps,mpq4210 + + reg: + maxItems: 1 + + enable-gpios: + description: GPIO connected to the EN pin. If absent, EN is assumed to + be permanently asserted. + maxItems: 1 + + mps,fb-voltage-divider-ohms: + description: An array of two integers containing the resistor values R1 + and R2 of the output feedback voltage divider. + maxItems: 2 + +required: + - compatible + - reg + - mps,fb-voltage-divider-ohms + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + i2c { + #address-cells = <1>; + #size-cells = <0>; + + regulator@64 { + compatible = "mps,mpq4210"; + reg = <0x64>; + regulator-name = "vout"; + regulator-min-microvolt = <4000000>; + regulator-max-microvolt = <20000000>; + enable-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; + /* R1 = 82 kOhm, R2 = 9.1 kOhm */ + mps,fb-voltage-divider-ohms = <82000 9100>; + /* 50 mV/ms reference ramp x (82000 + 9100) / 9100 */ + regulator-ramp-delay = <500>; + }; + }; diff --git a/Documentation/devicetree/bindings/regulator/mps,mpq7920.yaml b/Documentation/devicetree/bindings/regulator/mps,mpq7920.yaml index 0d34af98403f..726aaeac054e 100644 --- a/Documentation/devicetree/bindings/regulator/mps,mpq7920.yaml +++ b/Documentation/devicetree/bindings/regulator/mps,mpq7920.yaml @@ -88,30 +88,30 @@ examples: #size-cells = <0>; pmic@69 { - compatible = "mps,mpq7920"; - reg = <0x69>; - - regulators { - mps,switch-freq = /bits/ 8 <1>; - - buck1 { - regulator-name = "buck1"; - regulator-min-microvolt = <400000>; - regulator-max-microvolt = <3587500>; - regulator-min-microamp = <460000>; - regulator-max-microamp = <7600000>; - regulator-boot-on; - mps,buck-ovp-disable; - mps,buck-phase-delay = /bits/ 8 <2>; - mps,buck-softstart = /bits/ 8 <1>; + compatible = "mps,mpq7920"; + reg = <0x69>; + + regulators { + mps,switch-freq = /bits/ 8 <1>; + + buck1 { + regulator-name = "buck1"; + regulator-min-microvolt = <400000>; + regulator-max-microvolt = <3587500>; + regulator-min-microamp = <460000>; + regulator-max-microamp = <7600000>; + regulator-boot-on; + mps,buck-ovp-disable; + mps,buck-phase-delay = /bits/ 8 <2>; + mps,buck-softstart = /bits/ 8 <1>; + }; + + ldo2 { + regulator-name = "ldo2"; + regulator-min-microvolt = <650000>; + regulator-max-microvolt = <3587500>; + }; }; - - ldo2 { - regulator-name = "ldo2"; - regulator-min-microvolt = <650000>; - regulator-max-microvolt = <3587500>; - }; - }; - }; - }; + }; + }; ... diff --git a/Documentation/devicetree/bindings/regulator/mt6380-regulator.txt b/Documentation/devicetree/bindings/regulator/mt6380-regulator.txt deleted file mode 100644 index 0058441f16d2..000000000000 --- a/Documentation/devicetree/bindings/regulator/mt6380-regulator.txt +++ /dev/null @@ -1,89 +0,0 @@ -MediaTek MT6380 Regulator - -All voltage regulators provided by the MT6380 PMIC are described as the -subnodes of the MT6380 regulators node. Each regulator is named according -to its regulator type, buck-<name> and ldo-<name>. The definition for each -of these nodes is defined using the standard binding for regulators at -Documentation/devicetree/bindings/regulator/regulator.txt. - -The valid names for regulators are: -BUCK: - buck-core1, buck-vcore, buck-vrf -LDO: - ldo-vm ,ldo-va , ldo-vphy, ldo-vddr, ldo-vt - -Example: - - regulators { - compatible = "mediatek,mt6380-regulator"; - - mt6380_vcpu_reg: buck-vcore1 { - regulator-name = "vcore1"; - regulator-min-microvolt = < 600000>; - regulator-max-microvolt = <1393750>; - regulator-ramp-delay = <6250>; - regulator-always-on; - regulator-boot-on; - }; - - mt6380_vcore_reg: buck-vcore { - regulator-name = "vcore"; - regulator-min-microvolt = <600000>; - regulator-max-microvolt = <1393750>; - regulator-ramp-delay = <6250>; - }; - - mt6380_vrf_reg: buck-vrf { - regulator-name = "vrf"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1575000>; - regulator-ramp-delay = <0>; - regulator-always-on; - regulator-boot-on; - }; - - mt6380_vm_reg: ldo-vm { - regulator-name = "vm"; - regulator-min-microvolt = <1050000>; - regulator-max-microvolt = <1400000>; - regulator-ramp-delay = <0>; - regulator-always-on; - regulator-boot-on; - }; - - mt6380_va_reg: ldo-va { - regulator-name = "va"; - regulator-min-microvolt = <2200000>; - regulator-max-microvolt = <3300000>; - regulator-ramp-delay = <0>; - regulator-always-on; - regulator-boot-on; - }; - - mt6380_vphy_reg: ldo-vphy { - regulator-name = "vphy"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-ramp-delay = <0>; - regulator-always-on; - regulator-boot-on; - }; - - mt6380_vddr_reg: ldo-vddr { - regulator-name = "vddr"; - regulator-min-microvolt = <1240000>; - regulator-max-microvolt = <1840000>; - regulator-ramp-delay = <0>; - regulator-always-on; - regulator-boot-on; - }; - - mt6380_vt_reg: ldo-vt { - regulator-name = "vt"; - regulator-min-microvolt = <2200000>; - regulator-max-microvolt = <3300000>; - regulator-ramp-delay = <0>; - regulator-always-on; - regulator-boot-on; - }; - }; diff --git a/Documentation/devicetree/bindings/regulator/nexperia,nex10000ub.yaml b/Documentation/devicetree/bindings/regulator/nexperia,nex10000ub.yaml new file mode 100644 index 000000000000..3c0db59b8c1f --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/nexperia,nex10000ub.yaml @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/nexperia,nex10000ub.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Nexperia NEX10000UB dual output LCD bias power supply + +maintainers: + - Neil Armstrong <neil.armstrong@linaro.org> + +description: + The NEX10000UB is designed to supply positive/negative supplies for display Panels. + +properties: + compatible: + enum: + - nexperia,nex10000ub + + reg: + maxItems: 1 + + vin-supply: true + +patternProperties: + "^(vpos|vneg)$": + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + + properties: + enable-gpios: + maxItems: 1 + + required: + - enable-gpios + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + regulator@3e { + compatible = "nexperia,nex10000ub"; + reg = <0x3e>; + vin-supply = <&supply>; + + vpos { + regulator-name = "outp"; + regulator-boot-on; + enable-gpios = <&gpio 23 GPIO_ACTIVE_HIGH>; + }; + + vneg { + regulator-name = "outn"; + regulator-boot-on; + enable-gpios = <&gpio 40 GPIO_ACTIVE_HIGH>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/regulator/nxp,pf0900.yaml b/Documentation/devicetree/bindings/regulator/nxp,pf0900.yaml index 8c8fc2cd4ced..38fe80749c3c 100644 --- a/Documentation/devicetree/bindings/regulator/nxp,pf0900.yaml +++ b/Documentation/devicetree/bindings/regulator/nxp,pf0900.yaml @@ -160,4 +160,4 @@ examples: }; }; }; - }; + }; diff --git a/Documentation/devicetree/bindings/regulator/onnn,fan53880.yaml b/Documentation/devicetree/bindings/regulator/onnn,fan53880.yaml index b5181719daa1..1618e8f1c4c4 100644 --- a/Documentation/devicetree/bindings/regulator/onnn,fan53880.yaml +++ b/Documentation/devicetree/bindings/regulator/onnn,fan53880.yaml @@ -82,6 +82,6 @@ examples: regulator-max-microvolt = <1200000>; }; }; - }; - }; + }; + }; ... diff --git a/Documentation/devicetree/bindings/regulator/pwm-regulator.yaml b/Documentation/devicetree/bindings/regulator/pwm-regulator.yaml index 80ecf938b749..a7f48d33bad5 100644 --- a/Documentation/devicetree/bindings/regulator/pwm-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/pwm-regulator.yaml @@ -116,7 +116,7 @@ examples: regulator-max-microvolt = <1114000>; regulator-name = "vdd_logic"; - /* Voltage Duty-Cycle */ + /* Voltage Duty-Cycle */ voltage-table = <1114000 0>, <1095000 10>, <1076000 20>, diff --git a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml index eed2ce7fa861..9115885e7985 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml @@ -191,6 +191,22 @@ allOf: properties: compatible: enum: + - qcom,pm6350-rpmh-regulators + then: + properties: + vdd-l2-l5-l7-supply: true + vdd-l3-l6-l8-l9-l10-supply: true + vdd-l12-l14-supply: true + vdd-l15-l19-l22-supply: true + vdd-l18-l20-l21-supply: true + patternProperties: + "^vdd-l([14]|1[1367])-supply$": true + "^vdd-s[1-6]-supply$": true + + - if: + properties: + compatible: + enum: - qcom,pm660-rpmh-regulators then: properties: diff --git a/Documentation/devicetree/bindings/regulator/richtek,rtmv20-regulator.yaml b/Documentation/devicetree/bindings/regulator/richtek,rtmv20-regulator.yaml index fec3d396ca50..1526cd071b61 100644 --- a/Documentation/devicetree/bindings/regulator/richtek,rtmv20-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/richtek,rtmv20-regulator.yaml @@ -151,9 +151,9 @@ examples: richtek,vsync-polarity-high; lsw { - regulator-name = "rtmv20,lsw"; - regulator-min-microamp = <0>; - regulator-max-microamp = <6000000>; + regulator-name = "rtmv20,lsw"; + regulator-min-microamp = <0>; + regulator-max-microamp = <6000000>; }; }; }; diff --git a/Documentation/devicetree/bindings/regulator/silergy,sy8824x.yaml b/Documentation/devicetree/bindings/regulator/silergy,sy8824x.yaml index 82af4d656177..0da920f84f89 100644 --- a/Documentation/devicetree/bindings/regulator/silergy,sy8824x.yaml +++ b/Documentation/devicetree/bindings/regulator/silergy,sy8824x.yaml @@ -35,10 +35,10 @@ examples: #address-cells = <1>; #size-cells = <0>; regulator@60 { - compatible = "silergy,sy8824c"; - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <1150000>; - reg = <0x60>; + compatible = "silergy,sy8824c"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1150000>; + reg = <0x60>; }; }; diff --git a/Documentation/devicetree/bindings/regulator/silergy,sy8827n.yaml b/Documentation/devicetree/bindings/regulator/silergy,sy8827n.yaml index b222adabc7b4..77da91c28c19 100644 --- a/Documentation/devicetree/bindings/regulator/silergy,sy8827n.yaml +++ b/Documentation/devicetree/bindings/regulator/silergy,sy8827n.yaml @@ -39,8 +39,8 @@ examples: #address-cells = <1>; #size-cells = <0>; regulator@60 { - compatible = "silergy,sy8827n"; - reg = <0x60>; + compatible = "silergy,sy8827n"; + reg = <0x60>; }; }; diff --git a/Documentation/devicetree/bindings/regulator/ti,tps65023.yaml b/Documentation/devicetree/bindings/regulator/ti,tps65023.yaml new file mode 100644 index 000000000000..928698595f52 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/ti,tps65023.yaml @@ -0,0 +1,90 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/ti,tps65023.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments TPS65023 Regulator + +maintainers: + - Eduard Bostina <egbostina@gmail.com> + +properties: + compatible: + enum: + - ti,tps65020 + - ti,tps65021 + - ti,tps65023 + + reg: + maxItems: 1 + + regulators: + type: object + description: > + List of child nodes that specify the regulator initialization data. + Must be named after their hardware counterparts: VDCDC[1-3] and LDO[1-2]. + + patternProperties: + "^(VDCDC[1-3]|LDO[1-2])$": + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + + additionalProperties: false + +required: + - compatible + - reg + - regulators + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + tps65023@48 { + compatible = "ti,tps65023"; + reg = <0x48>; + + regulators { + VDCDC1 { + regulator-name = "vdd_mpu"; + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + VDCDC2 { + regulator-name = "vdd_core"; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + VDCDC3 { + regulator-name = "vdd_io"; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + LDO1 { + regulator-name = "vdd_usb18"; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + LDO2 { + regulator-name = "vdd_usb33"; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/regulator/ti,tps6586x.yaml b/Documentation/devicetree/bindings/regulator/ti,tps6586x.yaml new file mode 100644 index 000000000000..1f7c7b35066f --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/ti,tps6586x.yaml @@ -0,0 +1,196 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/ti,tps6586x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: TI TPS6586x family of regulators + +maintainers: + - Thierry Reding <thierry.reding@avionic-design.de> + +properties: + compatible: + const: ti,tps6586x + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + "#gpio-cells": + const: 2 + + gpio-controller: true + + sys-supply: + description: The input supply for SYS. + + ti,system-power-controller: + type: boolean + description: + Whether or not this PMIC is controlling the system power. + + regulators: + type: object + additionalProperties: false + description: + list of regulators provided by this controller, LDO5 and LDO_RTC is + supplied by SYS regulator internally and driver take care of making + proper parent child relationship. + + properties: + sys: + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + + patternProperties: + "^ldo([0-9]|_rtc)$": + type: object + allOf: + - $ref: /schemas/regulator/regulator.yaml# + - $ref: /schemas/regulator/nvidia,tegra-regulators-coupling.yaml# + unevaluatedProperties: false + + "^sm[0-2]$": + type: object + allOf: + - $ref: /schemas/regulator/regulator.yaml# + - $ref: /schemas/regulator/nvidia,tegra-regulators-coupling.yaml# + unevaluatedProperties: false + +patternProperties: + "^vin-sm[0-2]-supply$": + description: The input supply for the corresponding SM (SM0, SM1, or SM2). + + "^vinldo(01|23|4|678|9)-supply$": + description: The input supply for the corresponding LDO or group of LDOs. + +required: + - compatible + - reg + - interrupts + - regulators + - "#gpio-cells" + - gpio-controller + - sys-supply + - vin-sm0-supply + - vin-sm1-supply + - vin-sm2-supply + - vinldo01-supply + - vinldo23-supply + - vinldo4-supply + - vinldo678-supply + - vinldo9-supply + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + pmic@34 { + compatible = "ti,tps6586x"; + reg = <0x34>; + interrupts = <0 88 0x4>; + + #gpio-cells = <2>; + gpio-controller; + + ti,system-power-controller; + + sys-supply = <&vdd_5v0_sys>; + vin-sm0-supply = <&sys_reg>; + vin-sm1-supply = <&sys_reg>; + vin-sm2-supply = <&sys_reg>; + vinldo01-supply = <&sm2_reg>; + vinldo23-supply = <&sm2_reg>; + vinldo4-supply = <&sm2_reg>; + vinldo678-supply = <&sm2_reg>; + vinldo9-supply = <&sm2_reg>; + + regulators { + sys { + regulator-name = "vdd_sys"; + regulator-boot-on; + regulator-always-on; + }; + + sm0 { + regulator-min-microvolt = < 725000>; + regulator-max-microvolt = <1500000>; + regulator-boot-on; + regulator-always-on; + }; + + sm1 { + regulator-min-microvolt = < 725000>; + regulator-max-microvolt = <1500000>; + regulator-boot-on; + regulator-always-on; + }; + + sm2 { + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <4550000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo0 { + regulator-name = "PCIE CLK"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + ldo1 { + regulator-min-microvolt = < 725000>; + regulator-max-microvolt = <1500000>; + }; + + ldo2 { + regulator-min-microvolt = < 725000>; + regulator-max-microvolt = <1500000>; + }; + + ldo3 { + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <3300000>; + }; + + ldo4 { + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <2475000>; + }; + + ldo5 { + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <3300000>; + }; + + ldo6 { + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <3300000>; + }; + + ldo7 { + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <3300000>; + }; + + ldo8 { + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <3300000>; + }; + + ldo9 { + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <3300000>; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/regulator/tps65023.txt b/Documentation/devicetree/bindings/regulator/tps65023.txt deleted file mode 100644 index a4714e4da370..000000000000 --- a/Documentation/devicetree/bindings/regulator/tps65023.txt +++ /dev/null @@ -1,60 +0,0 @@ -TPS65023 family of regulators - -Required properties: -- compatible: Must be one of the following. - "ti,tps65020", - "ti,tps65021", - "ti,tps65023", -- reg: I2C slave address -- regulators: list of regulators provided by this controller, must be named - after their hardware counterparts: VDCDC[1-3] and LDO[1-2] -- regulators: This is the list of child nodes that specify the regulator - initialization data for defined regulators. The definition for each of - these nodes is defined using the standard binding for regulators found at - Documentation/devicetree/bindings/regulator/regulator.txt. - -Each regulator is defined using the standard binding for regulators. - -Example: - - tps65023@48 { - compatible = "ti,tps65023"; - reg = <0x48>; - - regulators { - VDCDC1 { - regulator-name = "vdd_mpu"; - regulator-always-on; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - VDCDC2 { - regulator-name = "vdd_core"; - regulator-always-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - VDCDC3 { - regulator-name = "vdd_io"; - regulator-always-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - LDO1 { - regulator-name = "vdd_usb18"; - regulator-always-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - LDO2 { - regulator-name = "vdd_usb33"; - regulator-always-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/regulator/tps6586x.txt b/Documentation/devicetree/bindings/regulator/tps6586x.txt deleted file mode 100644 index 8b40cac24d93..000000000000 --- a/Documentation/devicetree/bindings/regulator/tps6586x.txt +++ /dev/null @@ -1,135 +0,0 @@ -TPS6586x family of regulators - -Required properties: -- compatible: "ti,tps6586x" -- reg: I2C slave address -- interrupts: the interrupt outputs of the controller -- #gpio-cells: number of cells to describe a GPIO -- gpio-controller: mark the device as a GPIO controller -- regulators: A node that houses a sub-node for each regulator within the - device. Each sub-node is identified using the node's name (or the deprecated - regulator-compatible property if present), with valid values listed below. - The content of each sub-node is defined by the standard binding for - regulators; see regulator.txt. - sys, sm[0-2], ldo[0-9] and ldo_rtc -- sys-supply: The input supply for SYS. -- vin-sm0-supply: The input supply for the SM0. -- vin-sm1-supply: The input supply for the SM1. -- vin-sm2-supply: The input supply for the SM2. -- vinldo01-supply: The input supply for the LDO1 and LDO2 -- vinldo23-supply: The input supply for the LDO2 and LDO3 -- vinldo4-supply: The input supply for the LDO4 -- vinldo678-supply: The input supply for the LDO6, LDO7 and LDO8 -- vinldo9-supply: The input supply for the LDO9 - -Optional properties: -- ti,system-power-controller: Telling whether or not this pmic is controlling - the system power. - -Each regulator is defined using the standard binding for regulators. - -Note: LDO5 and LDO_RTC is supplied by SYS regulator internally and driver - take care of making proper parent child relationship. - -Example: - - pmu: tps6586x@34 { - compatible = "ti,tps6586x"; - reg = <0x34>; - interrupts = <0 88 0x4>; - - #gpio-cells = <2>; - gpio-controller; - - ti,system-power-controller; - - sys-supply = <&some_reg>; - vin-sm0-supply = <&some_reg>; - vin-sm1-supply = <&some_reg>; - vin-sm2-supply = <&some_reg>; - vinldo01-supply = <...>; - vinldo23-supply = <...>; - vinldo4-supply = <...>; - vinldo678-supply = <...>; - vinldo9-supply = <...>; - - regulators { - sys_reg: sys { - regulator-name = "vdd_sys"; - regulator-boot-on; - regulator-always-on; - }; - - sm0_reg: sm0 { - regulator-min-microvolt = < 725000>; - regulator-max-microvolt = <1500000>; - regulator-boot-on; - regulator-always-on; - }; - - sm1_reg: sm1 { - regulator-min-microvolt = < 725000>; - regulator-max-microvolt = <1500000>; - regulator-boot-on; - regulator-always-on; - }; - - sm2_reg: sm2 { - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <4550000>; - regulator-boot-on; - regulator-always-on; - }; - - ldo0_reg: ldo0 { - regulator-name = "PCIE CLK"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - - ldo1_reg: ldo1 { - regulator-min-microvolt = < 725000>; - regulator-max-microvolt = <1500000>; - }; - - ldo2_reg: ldo2 { - regulator-min-microvolt = < 725000>; - regulator-max-microvolt = <1500000>; - }; - - ldo3_reg: ldo3 { - regulator-min-microvolt = <1250000>; - regulator-max-microvolt = <3300000>; - }; - - ldo4_reg: ldo4 { - regulator-min-microvolt = <1700000>; - regulator-max-microvolt = <2475000>; - }; - - ldo5_reg: ldo5 { - regulator-min-microvolt = <1250000>; - regulator-max-microvolt = <3300000>; - }; - - ldo6_reg: ldo6 { - regulator-min-microvolt = <1250000>; - regulator-max-microvolt = <3300000>; - }; - - ldo7_reg: ldo7 { - regulator-min-microvolt = <1250000>; - regulator-max-microvolt = <3300000>; - }; - - ldo8_reg: ldo8 { - regulator-min-microvolt = <1250000>; - regulator-max-microvolt = <3300000>; - }; - - ldo9_reg: ldo9 { - regulator-min-microvolt = <1250000>; - regulator-max-microvolt = <3300000>; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml b/Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml index e7c4a3984c60..79b755858bad 100644 --- a/Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml +++ b/Documentation/devicetree/bindings/soc/mediatek/mediatek,pwrap.yaml @@ -105,6 +105,9 @@ properties: pmic: type: object + regulators: + $ref: /schemas/regulator/mediatek,mt6380-regulator.yaml# + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 838def27c9cf..473019dd0126 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -1202,6 +1202,8 @@ patternProperties: description: New Vision Display (Shenzhen) Co., Ltd. "^nexbox,.*": description: Nexbox + "^nexperia,.*": + description: Nexperia B.V. "^nextthing,.*": description: Next Thing Co. "^ni,.*": diff --git a/MAINTAINERS b/MAINTAINERS index 83f444c96007..16b032b344d5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -18569,6 +18569,12 @@ F: scripts/module* F: tools/testing/selftests/kmod/ F: tools/testing/selftests/module/ +MONOLITHIC POWER SYSTEM MPQ4210 REGULATOR DRIVER +M: Tapio Reijonen <tapio.reijonen@vaisala.com> +S: Maintained +F: Documentation/devicetree/bindings/regulator/mps,mpq4210.yaml +F: drivers/regulator/mpq4210.c + MONOLITHIC POWER SYSTEM PMIC DRIVER M: Saravanan Sekar <sravanhome@gmail.com> S: Maintained diff --git a/drivers/regulator/88pm886-regulator.c b/drivers/regulator/88pm886-regulator.c index 7328cd1cf265..1961a7968982 100644 --- a/drivers/regulator/88pm886-regulator.c +++ b/drivers/regulator/88pm886-regulator.c @@ -337,6 +337,25 @@ static struct regulator_desc pm886_regulators[] = { }, }; +static const struct linear_range pm886_vbus_volt_ranges[] = { + REGULATOR_LINEAR_RANGE(3750000, 0, 7, 250000) +}; + +static struct regulator_desc pm886_vbus_regulator = { + .name = "vbus", + .regulators_node = "regulators", + .of_match = "vbus", + .ops = &pm886_buck_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 8, + .linear_ranges = pm886_vbus_volt_ranges, + .n_linear_ranges = ARRAY_SIZE(pm886_vbus_volt_ranges), + .vsel_reg = PM886_REG_BOOST_CONFIG1, + .vsel_mask = PM886_REG_BOOST_MASK, + .enable_reg = PM886_REG_BATTERY_CONFIG1, + .enable_mask = PM886_REG_VBUS_EN, +}; + static int pm886_regulator_probe(struct platform_device *pdev) { struct pm886_chip *chip = dev_get_drvdata(pdev->dev.parent); @@ -369,6 +388,13 @@ static int pm886_regulator_probe(struct platform_device *pdev) "Failed to register %s\n", rdesc->name); } + rcfg.regmap = chip->regmap_battery; + rdesc = &pm886_vbus_regulator; + rdev = devm_regulator_register(dev, rdesc, &rcfg); + if (IS_ERR(rdev)) + return dev_err_probe(dev, PTR_ERR(rdev), + "Failed to register %s\n", rdesc->name); + return 0; } diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 13928af8cad4..be6b72daa76f 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -864,12 +864,23 @@ config REGULATOR_MP8859 module. The module will be named "mp8859". config REGULATOR_MP886X - tristate "MPS MP8869 regulator driver" + tristate "MPS MP8864/MP8867/MP8869 regulator driver" depends on I2C && OF select REGMAP_I2C help This driver supports the MP8869 voltage regulator. +config REGULATOR_MPQ4210 + tristate "MPS MPQ4210 regulator driver" + depends on I2C && OF + select REGMAP_I2C + help + This driver supports the MPQ4210 synchronous buck-boost controller. + It supports get/set voltage, enable/disable and ramp rate selection + through the regulator interface. + Say M here if you want to include support for the regulator as a + module. The module will be named "mpq4210". + config REGULATOR_MPQ7920 tristate "Monolithic MPQ7920 PMIC" depends on I2C && OF @@ -1020,6 +1031,14 @@ config REGULATOR_MTK_DVFSRC of Mediatek. It allows for voting on regulator state between multiple users. +config REGULATOR_NEX10000UB + tristate "Nexperia NEX10000UB Dual Output Power regulators" + depends on I2C && GPIOLIB + select REGMAP_I2C + help + This driver supports the NEX10000UB single inductor - dual output + power supply specifically designed for display panels. + config REGULATOR_PALMAS tristate "TI Palmas PMIC Regulators" depends on MFD_PALMAS diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 5a764cec8df8..6aabcc54382a 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -104,6 +104,7 @@ obj-$(CONFIG_REGULATOR_MCP16502) += mcp16502.o obj-$(CONFIG_REGULATOR_MP5416) += mp5416.o obj-$(CONFIG_REGULATOR_MP8859) += mp8859.o obj-$(CONFIG_REGULATOR_MP886X) += mp886x.o +obj-$(CONFIG_REGULATOR_MPQ4210) += mpq4210.o obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o obj-$(CONFIG_REGULATOR_MT6315) += mt6315-regulator.o @@ -120,6 +121,7 @@ obj-$(CONFIG_REGULATOR_MT6370) += mt6370-regulator.o obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o obj-$(CONFIG_REGULATOR_MTK_DVFSRC) += mtk-dvfsrc-regulator.o +obj-$(CONFIG_REGULATOR_NEX10000UB) += nex10000ub-regulator.o obj-$(CONFIG_REGULATOR_QCOM_LABIBB) += qcom-labibb-regulator.o obj-$(CONFIG_REGULATOR_QCOM_PM8008) += qcom-pm8008-regulator.o obj-$(CONFIG_REGULATOR_QCOM_REFGEN) += qcom-refgen-regulator.o diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c index b9955aa4e0d1..c0657362a102 100644 --- a/drivers/regulator/ab8500-ext.c +++ b/drivers/regulator/ab8500-ext.c @@ -88,7 +88,7 @@ static struct regulator_init_data ab8500_ext_regulators[] = { * @update_reg: register to control on/off * @update_mask: mask to enable/disable and set mode of regulator * @update_val: bits holding the regulator current mode - * @update_val_hp: bits to set EN pin active (LPn pin deactive) + * @update_val_hp: bits to set EN pin active (LPn pin deactivate) * normally this means high power mode * @update_val_lp: bits to set EN pin active and LPn pin active * normally this means low power mode diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 3705c98b0713..3c1962ad85d4 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -9,15 +9,18 @@ * AB8500 peripheral regulators * * AB8500 supports the following regulators: - * VAUX1/2/3, VINTCORE, VTVOUT, VUSB, VAUDIO, VAMIC1/2, VDMIC, VANA + * VSMPS1/2/3, VARM, VAPE, VMOD, VAUX1/2/3, VINTCORE, VTVOUT, + * VUSB, VAUDIO, VAMIC1/2, VDMIC, VANA * * AB8505 supports the following regulators: - * VAUX1/2/3/4/5/6, VINTCORE, VADC, VUSB, VAUDIO, VAMIC1/2, VDMIC, VANA + * VSMPSA/B/C/M, VSAFE, VARM, VAUX1/2/3/4/5/6, VINTCORE, + * VADC, VUSB, VAUDIO, VAMIC1/2, VDMIC, VANA */ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/err.h> +#include <linux/mutex.h> #include <linux/platform_device.h> #include <linux/mfd/abx500.h> #include <linux/mfd/abx500/ab8500.h> @@ -39,6 +42,12 @@ enum ab8500_regulator_id { AB8500_LDO_ANAMIC2, AB8500_LDO_DMIC, AB8500_LDO_ANA, + AB8500_BUCK_SMPS1, + AB8500_BUCK_SMPS2, + AB8500_BUCK_SMPS3, + AB8500_BUCK_ARM, + AB8500_BUCK_APE, + AB8500_BUCK_MOD, AB8500_NUM_REGULATORS, }; @@ -57,6 +66,12 @@ enum ab8505_regulator_id { AB8505_LDO_ANAMIC2, AB8505_LDO_AUX8, AB8505_LDO_ANA, + AB8505_BUCK_SMPSA, + AB8505_BUCK_SMPSB, + AB8505_BUCK_SAFE, + AB8505_BUCK_ARM, + AB8505_BUCK_SMPSC, + AB8505_BUCK_SMPSM, AB8505_NUM_REGULATORS, }; @@ -162,6 +177,7 @@ struct ab8500_shared_mode { * @update_bank: bank to control on/off * @update_reg: register to control on/off * @update_mask: mask to enable/disable and set mode of regulator + * @enable_mask: optional mask for an enable bit separate from the mode bit * @update_val: bits holding the regulator current mode * @update_val_idle: bits to enable the regulator in idle (low power) mode * @update_val_normal: bits to enable the regulator in normal (high power) mode @@ -171,8 +187,17 @@ struct ab8500_shared_mode { * @mode_val_idle: mode setting for low power * @mode_val_normal: mode setting for normal power * @voltage_bank: bank to control regulator voltage - * @voltage_reg: register to control regulator voltage + * @voltage_reg: first register containing a selectable regulator voltage * @voltage_mask: mask to control regulator voltage + * @expand_register: additional register used to select an extra voltage + * @voltage_ctrl_bank: bank containing the voltage selector control + * @voltage_ctrl_reg: register containing the voltage selector control + * @voltage_ctrl_mask: mask selecting one of the first voltage registers + * @voltage_ext_ctrl_bank: bank containing the extended selector control + * @voltage_ext_ctrl_reg: register containing the extended selector control + * @voltage_ext_ctrl_mask: mask selecting one of the extended voltage registers + * @voltage_ext_reg: first extended voltage register + * @voltage_ext_regs: number of extended voltage registers */ struct ab8500_regulator_info { struct device *dev; @@ -182,6 +207,7 @@ struct ab8500_regulator_info { u8 update_bank; u8 update_reg; u8 update_mask; + u8 enable_mask; u8 update_val; u8 update_val_idle; u8 update_val_normal; @@ -193,6 +219,20 @@ struct ab8500_regulator_info { u8 voltage_bank; u8 voltage_reg; u8 voltage_mask; + struct { + u8 voltage_limit; + u8 voltage_bank; + u8 voltage_reg; + u8 voltage_mask; + } expand_register; + u8 voltage_ctrl_bank; + u8 voltage_ctrl_reg; + u8 voltage_ctrl_mask; + u8 voltage_ext_ctrl_bank; + u8 voltage_ext_ctrl_reg; + u8 voltage_ext_ctrl_mask; + u8 voltage_ext_reg; + u8 voltage_ext_regs; }; /* voltage tables for the vauxn/vintcore supplies */ @@ -226,6 +266,18 @@ static const unsigned int ldo_vaux3_voltages[] = { 2910000, }; +static const unsigned int ldo_vaux3_ab8505_voltages[] = { + 1200000, + 1500000, + 1800000, + 2100000, + 2500000, + 2750000, + 2790000, + 2910000, + 3050000, +}; + static const unsigned int ldo_vaux56_voltages[] = { 1800000, 1050000, @@ -237,14 +289,13 @@ static const unsigned int ldo_vaux56_voltages[] = { 2790000, }; -static const unsigned int ldo_vintcore_voltages[] = { - 1200000, - 1225000, - 1250000, - 1275000, - 1300000, - 1325000, - 1350000, +static const struct linear_range ldo_vintcore_ranges[] = { + REGULATOR_LINEAR_RANGE(1200000, 0, 6, 25000), +}; + +static const struct linear_range ldo_vintcore_ab8505_ranges[] = { + REGULATOR_LINEAR_RANGE(1200000, 0, 6, 25000), + REGULATOR_LINEAR_RANGE(1350000, 7, 7, 0), }; static const unsigned int fixed_1200000_voltage[] = { @@ -264,25 +315,54 @@ static const unsigned int fixed_2050000_voltage[] = { }; static const unsigned int ldo_vana_voltages[] = { + 1200000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, - 1200000, 1225000, }; -static const unsigned int ldo_vaudio_voltages[] = { - 2000000, - 2100000, - 2200000, - 2300000, - 2400000, - 2500000, - 2600000, - 2600000, /* Duplicated in Vaudio and IsoUicc Control register. */ +static const struct linear_range ldo_vaudio_ranges[] = { + REGULATOR_LINEAR_RANGE(2000000, 0, 6, 100000), + /* Duplicated in Vaudio and IsoUicc Control register. */ + REGULATOR_LINEAR_RANGE(2600000, 7, 7, 0), +}; + +/* + * AB8505 buck ranges except VARM are selected by OTP. The supported + * platforms use the AB8500-compatible profiles for VSMPSA/B and the low + * profiles for VSAFE, VSMPSC and VSMPSM. + */ +static const struct linear_range buck_low_voltages[] = { + REGULATOR_LINEAR_RANGE(700000, 0, 53, 12500), + REGULATOR_LINEAR_RANGE(1362500, 54, 63, 0), +}; + +/* VSMPS3 and VSAFE have a 7-bit selector, but the same low range. */ +static const struct linear_range buck_low_7bit_voltages[] = { + REGULATOR_LINEAR_RANGE(700000, 0, 53, 12500), + REGULATOR_LINEAR_RANGE(1362500, 54, 127, 0), +}; + +/* AB8505 VARM uses a separate 0.6 V to 1.39375 V selector range. */ +static const struct linear_range ab8505_buck_arm_voltages[] = { + REGULATOR_LINEAR_RANGE(600000, 0, 127, 6250), +}; + +/* VSMPS1 and the VSMPSA AB8500-compatible profile clamp to this range. */ +static const struct linear_range buck_smps1_voltages[] = { + REGULATOR_LINEAR_RANGE(1100000, 0, 32, 0), + REGULATOR_LINEAR_RANGE(1112500, 33, 48, 12500), + REGULATOR_LINEAR_RANGE(1300000, 49, 63, 0), +}; + +/* VSMPS2 and the VSMPSB AB8500-compatible profile clamp to this range. */ +static const struct linear_range buck_smps2_voltages[] = { + REGULATOR_LINEAR_RANGE(1800000, 0, 57, 0), + REGULATOR_LINEAR_RANGE(1812500, 58, 63, 12500), }; static DEFINE_MUTEX(shared_mode_mutex); @@ -343,7 +423,7 @@ static int ab8500_regulator_disable(struct regulator_dev *rdev) return ret; } -static int ab8500_regulator_is_enabled(struct regulator_dev *rdev) +static int ab8500_regulator_get_enable_value(struct regulator_dev *rdev) { int ret; struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); @@ -368,10 +448,65 @@ static int ab8500_regulator_is_enabled(struct regulator_dev *rdev) info->desc.name, info->update_bank, info->update_reg, info->update_mask, regval); - if (regval & info->update_mask) - return 1; + return regval & info->update_mask; +} + +static int ab8500_regulator_is_enabled(struct regulator_dev *rdev) +{ + struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); + u8 enable_mask; + int ret; + + ret = ab8500_regulator_get_enable_value(rdev); + if (ret < 0) + return ret; + + enable_mask = info->enable_mask ? info->enable_mask : info->update_mask; + + return !!(ret & enable_mask); +} + +static int ab8500_buck_enable(struct regulator_dev *rdev) +{ + int ret; + + /* Keep an OTP-selected hardware or low-power mode intact. */ + ret = ab8500_regulator_is_enabled(rdev); + if (ret) + return ret < 0 ? ret : 0; + + return ab8500_regulator_enable(rdev); +} + +static int ab8500_buck_init(struct regulator_dev *rdev, + struct regulator_config *config) +{ + struct ab8500_regulator_info *info = config->driver_data; + int ret; + + ret = ab8500_regulator_get_enable_value(rdev); + if (ret <= 0) + return ret; + + /* Report forced LP accurately; HP and hardware control are normal mode. */ + if (ret == info->update_val_idle) + info->update_val = info->update_val_idle; else - return 0; + info->update_val = info->update_val_normal; + + /* + * The SMPS enable state is selected by OTP. An enabled rail may + * supply discrete board components which are not represented as + * regulator consumers, so keep it out of the unused-regulator sweep. + */ + rdev->constraints->boot_on = true; + rdev->constraints->always_on = true; + rdev->constraints->valid_ops_mask &= ~REGULATOR_CHANGE_STATUS; + + dev_dbg(config->dev, "%s: preserving OTP-enabled state\n", + info->desc.name); + + return 0; } static unsigned int ab8500_regulator_get_optimum_mode( @@ -398,7 +533,7 @@ static unsigned int ab8500_regulator_get_optimum_mode( static int ab8500_regulator_set_mode(struct regulator_dev *rdev, unsigned int mode) { - int ret = 0; + int enabled, ret = 0; u8 bank, reg, mask, val; bool lp_mode_req = false; struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); @@ -408,6 +543,8 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, return -EINVAL; } + guard(mutex)(&shared_mode_mutex); + if (info->mode_mask) { bank = info->mode_bank; reg = info->mode_reg; @@ -418,9 +555,6 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, mask = info->update_mask; } - if (info->shared_mode) - mutex_lock(&shared_mode_mutex); - switch (mode) { case REGULATOR_MODE_NORMAL: if (info->shared_mode) @@ -439,7 +573,7 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, if (!shared_regulator->shared_mode->lp_mode_req) { /* Other regulator prevent LP mode */ info->shared_mode->lp_mode_req = true; - goto out_unlock; + return 0; } lp_mode_req = true; @@ -451,17 +585,24 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, val = info->update_val_idle; break; default: - ret = -EINVAL; - goto out_unlock; + return -EINVAL; + } + + if (info->mode_mask) { + enabled = 1; + } else { + enabled = ab8500_regulator_is_enabled(rdev); + if (enabled < 0) + return enabled; } - if (info->mode_mask || ab8500_regulator_is_enabled(rdev)) { + if (enabled) { ret = abx500_mask_and_set_register_interruptible(info->dev, bank, reg, mask, val); if (ret < 0) { dev_err(rdev_get_dev(rdev), "couldn't set regulator mode\n"); - goto out_unlock; + return ret; } dev_vdbg(rdev_get_dev(rdev), @@ -477,10 +618,6 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, if (info->shared_mode) info->shared_mode->lp_mode_req = lp_mode_req; -out_unlock: - if (info->shared_mode) - mutex_unlock(&shared_mode_mutex); - return ret; } @@ -530,11 +667,67 @@ static unsigned int ab8500_regulator_get_mode(struct regulator_dev *rdev) return ret; } +static int ab8500_regulator_get_voltage_reg(struct regulator_dev *rdev, + u8 *voltage_reg) +{ + struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); + u8 regval; + unsigned int selector; + int ret; + + if (info->voltage_ext_ctrl_mask) { + ret = abx500_get_register_interruptible(info->dev, + info->voltage_ext_ctrl_bank, + info->voltage_ext_ctrl_reg, ®val); + if (ret < 0) + return ret; + + selector = (regval & info->voltage_ext_ctrl_mask) >> + (ffs(info->voltage_ext_ctrl_mask) - 1); + if (selector) { + selector = min_t(unsigned int, selector, + info->voltage_ext_regs); + *voltage_reg = info->voltage_ext_reg + selector - 1; + return 0; + } + } + + if (!info->voltage_ctrl_mask) { + *voltage_reg = info->voltage_reg; + return 0; + } + + ret = abx500_get_register_interruptible(info->dev, + info->voltage_ctrl_bank, + info->voltage_ctrl_reg, ®val); + if (ret < 0) + return ret; + + /* The three hardware selector layouts all use consecutive registers. */ + switch (info->voltage_ctrl_mask) { + case 0x0c: + selector = min((unsigned int)((regval & 0x0c) >> 2), 2U); + break; + case 0x24: + selector = regval & BIT(5) ? 2 : !!(regval & BIT(2)); + break; + case 0x04: + selector = !!(regval & BIT(2)); + break; + default: + return -EINVAL; + } + + *voltage_reg = info->voltage_reg + selector; + + return 0; +} + static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev) { int ret, voltage_shift; struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); - u8 regval; + u8 regval, voltage_reg; if (info == NULL) { dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); @@ -543,8 +736,15 @@ static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev) voltage_shift = ffs(info->voltage_mask) - 1; + ret = ab8500_regulator_get_voltage_reg(rdev, &voltage_reg); + if (ret < 0) { + dev_err(rdev_get_dev(rdev), + "couldn't read voltage selector control\n"); + return ret; + } + ret = abx500_get_register_interruptible(info->dev, - info->voltage_bank, info->voltage_reg, ®val); + info->voltage_bank, voltage_reg, ®val); if (ret < 0) { dev_err(rdev_get_dev(rdev), "couldn't read voltage reg for regulator\n"); @@ -555,7 +755,7 @@ static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev) "%s-get_voltage (bank, reg, mask, shift, value): " "0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", info->desc.name, info->voltage_bank, - info->voltage_reg, info->voltage_mask, + voltage_reg, info->voltage_mask, voltage_shift, regval); return (regval & info->voltage_mask) >> voltage_shift; @@ -566,7 +766,7 @@ static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, { int ret, voltage_shift; struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); - u8 regval; + u8 regval, voltage_reg; if (info == NULL) { dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); @@ -575,10 +775,17 @@ static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, voltage_shift = ffs(info->voltage_mask) - 1; + ret = ab8500_regulator_get_voltage_reg(rdev, &voltage_reg); + if (ret < 0) { + dev_err(rdev_get_dev(rdev), + "couldn't read voltage selector control\n"); + return ret; + } + /* set the registers for the request */ regval = (u8)selector << voltage_shift; ret = abx500_mask_and_set_register_interruptible(info->dev, - info->voltage_bank, info->voltage_reg, + info->voltage_bank, voltage_reg, info->voltage_mask, regval); if (ret < 0) dev_err(rdev_get_dev(rdev), @@ -587,12 +794,70 @@ static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, dev_vdbg(rdev_get_dev(rdev), "%s-set_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x," " 0x%x\n", - info->desc.name, info->voltage_bank, info->voltage_reg, + info->desc.name, info->voltage_bank, voltage_reg, info->voltage_mask, regval); return ret; } +static int ab8500_regulator_get_voltage_sel_expand(struct regulator_dev *rdev) +{ + struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); + u8 regval; + int ret; + + if (!info) + return -EINVAL; + + ret = abx500_get_register_interruptible(info->dev, + info->expand_register.voltage_bank, + info->expand_register.voltage_reg, ®val); + if (ret < 0) { + dev_err(rdev_get_dev(rdev), + "couldn't read voltage expand reg for regulator\n"); + return ret; + } + + if (regval & info->expand_register.voltage_mask) + return info->expand_register.voltage_limit; + + return ab8500_regulator_get_voltage_sel(rdev); +} + +static int ab8500_regulator_set_voltage_sel_expand(struct regulator_dev *rdev, + unsigned int selector) +{ + struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); + u8 regval; + int ret; + + if (!info) + return -EINVAL; + + if (selector > info->expand_register.voltage_limit) + return -EINVAL; + + if (selector < info->expand_register.voltage_limit) { + ret = ab8500_regulator_set_voltage_sel(rdev, selector); + if (ret < 0) + return ret; + + regval = 0; + } else { + regval = info->expand_register.voltage_mask; + } + + ret = abx500_mask_and_set_register_interruptible(info->dev, + info->expand_register.voltage_bank, + info->expand_register.voltage_reg, + info->expand_register.voltage_mask, regval); + if (ret < 0) + dev_err(rdev_get_dev(rdev), + "couldn't set voltage expand reg for regulator\n"); + + return ret; +} + static const struct regulator_ops ab8500_regulator_volt_mode_ops = { .enable = ab8500_regulator_enable, .disable = ab8500_regulator_disable, @@ -605,13 +870,59 @@ static const struct regulator_ops ab8500_regulator_volt_mode_ops = { .list_voltage = regulator_list_voltage_table, }; -static const struct regulator_ops ab8500_regulator_volt_ops = { +static const struct regulator_ops ab8500_regulator_volt_mode_expand_ops = { + .enable = ab8500_regulator_enable, + .disable = ab8500_regulator_disable, + .is_enabled = ab8500_regulator_is_enabled, + .get_optimum_mode = ab8500_regulator_get_optimum_mode, + .set_mode = ab8500_regulator_set_mode, + .get_mode = ab8500_regulator_get_mode, + .get_voltage_sel = ab8500_regulator_get_voltage_sel_expand, + .set_voltage_sel = ab8500_regulator_set_voltage_sel_expand, + .list_voltage = regulator_list_voltage_table, +}; + +static const struct regulator_ops ab8500_regulator_linear_range_volt_mode_ops = { + .enable = ab8500_regulator_enable, + .disable = ab8500_regulator_disable, + .is_enabled = ab8500_regulator_is_enabled, + .get_optimum_mode = ab8500_regulator_get_optimum_mode, + .set_mode = ab8500_regulator_set_mode, + .get_mode = ab8500_regulator_get_mode, + .get_voltage_sel = ab8500_regulator_get_voltage_sel, + .set_voltage_sel = ab8500_regulator_set_voltage_sel, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, +}; + +static const struct regulator_ops ab8500_regulator_linear_range_volt_ops = { .enable = ab8500_regulator_enable, .disable = ab8500_regulator_disable, .is_enabled = ab8500_regulator_is_enabled, .get_voltage_sel = ab8500_regulator_get_voltage_sel, .set_voltage_sel = ab8500_regulator_set_voltage_sel, - .list_voltage = regulator_list_voltage_table, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, +}; + +static const struct regulator_ops ab8500_buck_ops = { + .enable = ab8500_buck_enable, + .disable = ab8500_regulator_disable, + .is_enabled = ab8500_regulator_is_enabled, + .get_optimum_mode = ab8500_regulator_get_optimum_mode, + .set_mode = ab8500_regulator_set_mode, + .get_mode = ab8500_regulator_get_mode, + .get_voltage_sel = ab8500_regulator_get_voltage_sel, + .set_voltage_sel = ab8500_regulator_set_voltage_sel, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, +}; + +static const struct regulator_ops ab8500_buck_voltage_ops = { + .get_voltage_sel = ab8500_regulator_get_voltage_sel, + .set_voltage_sel = ab8500_regulator_set_voltage_sel, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, }; static const struct regulator_ops ab8500_regulator_mode_ops = { @@ -721,18 +1032,20 @@ static struct ab8500_regulator_info [AB8500_LDO_INTCORE] = { .desc = { .name = "LDO-INTCORE", - .ops = &ab8500_regulator_volt_mode_ops, + .ops = &ab8500_regulator_linear_range_volt_mode_ops, .type = REGULATOR_VOLTAGE, .id = AB8500_LDO_INTCORE, .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), - .volt_table = ldo_vintcore_voltages, + .n_voltages = 7, + .linear_ranges = ldo_vintcore_ranges, + .n_linear_ranges = ARRAY_SIZE(ldo_vintcore_ranges), .enable_time = 750, }, .load_lp_uA = 5000, .update_bank = 0x03, .update_reg = 0x80, .update_mask = 0x44, + .enable_mask = 0x04, .update_val = 0x44, .update_val_idle = 0x44, .update_val_normal = 0x04, @@ -761,6 +1074,7 @@ static struct ab8500_regulator_info .update_bank = 0x03, .update_reg = 0x80, .update_mask = 0x82, + .enable_mask = 0x02, .update_val = 0x02, .update_val_idle = 0x82, .update_val_normal = 0x02, @@ -852,6 +1166,140 @@ static struct ab8500_regulator_info .update_val_idle = 0x0c, .update_val_normal = 0x04, }, + + /* Buck converters */ + [AB8500_BUCK_SMPS1] = { + .desc = { + .name = "BUCK-SMPS1", + .ops = &ab8500_buck_ops, + .init_cb = ab8500_buck_init, + .type = REGULATOR_VOLTAGE, + .id = AB8500_BUCK_SMPS1, + .owner = THIS_MODULE, + .n_voltages = 64, + .linear_ranges = buck_smps1_voltages, + .n_linear_ranges = ARRAY_SIZE(buck_smps1_voltages), + }, + .load_lp_uA = 20000, + .update_bank = 0x04, + .update_reg = 0x03, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + .voltage_bank = 0x04, + .voltage_reg = 0x13, + .voltage_mask = 0x3f, + .voltage_ctrl_bank = 0x04, + .voltage_ctrl_reg = 0x03, + .voltage_ctrl_mask = 0x0c, + }, + [AB8500_BUCK_SMPS2] = { + .desc = { + .name = "BUCK-SMPS2", + .ops = &ab8500_buck_ops, + .init_cb = ab8500_buck_init, + .type = REGULATOR_VOLTAGE, + .id = AB8500_BUCK_SMPS2, + .owner = THIS_MODULE, + .n_voltages = 64, + .linear_ranges = buck_smps2_voltages, + .n_linear_ranges = ARRAY_SIZE(buck_smps2_voltages), + }, + .load_lp_uA = 20000, + .update_bank = 0x04, + .update_reg = 0x04, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + .voltage_bank = 0x04, + .voltage_reg = 0x17, + .voltage_mask = 0x3f, + .voltage_ctrl_bank = 0x04, + .voltage_ctrl_reg = 0x04, + .voltage_ctrl_mask = 0x0c, + }, + [AB8500_BUCK_SMPS3] = { + .desc = { + .name = "BUCK-SMPS3", + .ops = &ab8500_buck_ops, + .init_cb = ab8500_buck_init, + .type = REGULATOR_VOLTAGE, + .id = AB8500_BUCK_SMPS3, + .owner = THIS_MODULE, + .n_voltages = 128, + .linear_ranges = buck_low_7bit_voltages, + .n_linear_ranges = ARRAY_SIZE(buck_low_7bit_voltages), + }, + .load_lp_uA = 50000, + .update_bank = 0x04, + .update_reg = 0x05, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + .voltage_bank = 0x04, + .voltage_reg = 0x1b, + .voltage_mask = 0x7f, + .voltage_ctrl_bank = 0x04, + .voltage_ctrl_reg = 0x05, + .voltage_ctrl_mask = 0x0c, + }, + [AB8500_BUCK_ARM] = { + .desc = { + .name = "BUCK-ARM", + .ops = &ab8500_buck_voltage_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_BUCK_ARM, + .owner = THIS_MODULE, + .n_voltages = 64, + .linear_ranges = buck_low_voltages, + .n_linear_ranges = ARRAY_SIZE(buck_low_voltages), + }, + .voltage_bank = 0x04, + .voltage_reg = 0x0b, + .voltage_mask = 0x3f, + .voltage_ctrl_bank = 0x04, + .voltage_ctrl_reg = 0x00, + .voltage_ctrl_mask = 0x0c, + }, + [AB8500_BUCK_APE] = { + .desc = { + .name = "BUCK-APE", + .ops = &ab8500_buck_voltage_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_BUCK_APE, + .owner = THIS_MODULE, + .n_voltages = 64, + .linear_ranges = buck_low_voltages, + .n_linear_ranges = ARRAY_SIZE(buck_low_voltages), + }, + .voltage_bank = 0x04, + .voltage_reg = 0x0e, + .voltage_mask = 0x3f, + .voltage_ctrl_bank = 0x04, + .voltage_ctrl_reg = 0x02, + .voltage_ctrl_mask = 0x24, + }, + [AB8500_BUCK_MOD] = { + .desc = { + .name = "BUCK-MOD", + .ops = &ab8500_buck_voltage_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_BUCK_MOD, + .owner = THIS_MODULE, + .n_voltages = 64, + .linear_ranges = buck_low_voltages, + .n_linear_ranges = ARRAY_SIZE(buck_low_voltages), + }, + .voltage_bank = 0x04, + .voltage_reg = 0x41, + .voltage_mask = 0x3f, + .voltage_ctrl_bank = 0x04, + .voltage_ctrl_reg = 0x40, + .voltage_ctrl_mask = 0x04, + }, }; /* AB8505 regulator information */ @@ -908,12 +1356,12 @@ static struct ab8500_regulator_info [AB8505_LDO_AUX3] = { .desc = { .name = "LDO-AUX3", - .ops = &ab8500_regulator_volt_mode_ops, + .ops = &ab8500_regulator_volt_mode_expand_ops, .type = REGULATOR_VOLTAGE, .id = AB8505_LDO_AUX3, .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages), - .volt_table = ldo_vaux3_voltages, + .n_voltages = ARRAY_SIZE(ldo_vaux3_ab8505_voltages), + .volt_table = ldo_vaux3_ab8505_voltages, }, .load_lp_uA = 5000, .update_bank = 0x04, @@ -925,6 +1373,12 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x21, .voltage_mask = 0x07, + .expand_register = { + .voltage_limit = 8, + .voltage_bank = 0x04, + .voltage_reg = 0x01, + .voltage_mask = 0x10, + }, }, [AB8505_LDO_AUX4] = { .desc = { @@ -964,6 +1418,7 @@ static struct ab8500_regulator_info .update_bank = 0x01, .update_reg = 0x55, .update_mask = 0x18, + .enable_mask = 0x10, .update_val = 0x10, .update_val_idle = 0x18, .update_val_normal = 0x10, @@ -986,6 +1441,7 @@ static struct ab8500_regulator_info .update_bank = 0x01, .update_reg = 0x56, .update_mask = 0x18, + .enable_mask = 0x10, .update_val = 0x10, .update_val_idle = 0x18, .update_val_normal = 0x10, @@ -996,17 +1452,19 @@ static struct ab8500_regulator_info [AB8505_LDO_INTCORE] = { .desc = { .name = "LDO-INTCORE", - .ops = &ab8500_regulator_volt_mode_ops, + .ops = &ab8500_regulator_linear_range_volt_mode_ops, .type = REGULATOR_VOLTAGE, .id = AB8505_LDO_INTCORE, .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), - .volt_table = ldo_vintcore_voltages, + .n_voltages = 8, + .linear_ranges = ldo_vintcore_ab8505_ranges, + .n_linear_ranges = ARRAY_SIZE(ldo_vintcore_ab8505_ranges), }, .load_lp_uA = 5000, .update_bank = 0x03, .update_reg = 0x80, .update_mask = 0x44, + .enable_mask = 0x04, .update_val = 0x04, .update_val_idle = 0x44, .update_val_normal = 0x04, @@ -1035,6 +1493,7 @@ static struct ab8500_regulator_info .update_bank = 0x03, .update_reg = 0x80, .update_mask = 0x82, + .enable_mask = 0x02, .update_val = 0x02, .update_val_idle = 0x82, .update_val_normal = 0x02, @@ -1042,12 +1501,13 @@ static struct ab8500_regulator_info [AB8505_LDO_AUDIO] = { .desc = { .name = "LDO-AUDIO", - .ops = &ab8500_regulator_volt_ops, + .ops = &ab8500_regulator_linear_range_volt_ops, .type = REGULATOR_VOLTAGE, .id = AB8505_LDO_AUDIO, .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_vaudio_voltages), - .volt_table = ldo_vaudio_voltages, + .n_voltages = 8, + .linear_ranges = ldo_vaudio_ranges, + .n_linear_ranges = ARRAY_SIZE(ldo_vaudio_ranges), }, .update_bank = 0x03, .update_reg = 0x83, @@ -1138,6 +1598,155 @@ static struct ab8500_regulator_info .voltage_reg = 0x29, .voltage_mask = 0x7, }, + + /* Buck converters */ + [AB8505_BUCK_SMPSA] = { + .desc = { + .name = "BUCK-SMPSA", + .ops = &ab8500_buck_ops, + .init_cb = ab8500_buck_init, + .type = REGULATOR_VOLTAGE, + .id = AB8505_BUCK_SMPSA, + .owner = THIS_MODULE, + .n_voltages = 64, + .linear_ranges = buck_smps1_voltages, + .n_linear_ranges = ARRAY_SIZE(buck_smps1_voltages), + }, + .load_lp_uA = 20000, + .update_bank = 0x04, + .update_reg = 0x03, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + .voltage_bank = 0x04, + .voltage_reg = 0x13, + .voltage_mask = 0x3f, + .voltage_ctrl_bank = 0x04, + .voltage_ctrl_reg = 0x03, + .voltage_ctrl_mask = 0x0c, + }, + [AB8505_BUCK_SMPSB] = { + .desc = { + .name = "BUCK-SMPSB", + .ops = &ab8500_buck_ops, + .init_cb = ab8500_buck_init, + .type = REGULATOR_VOLTAGE, + .id = AB8505_BUCK_SMPSB, + .owner = THIS_MODULE, + .n_voltages = 64, + .linear_ranges = buck_smps2_voltages, + .n_linear_ranges = ARRAY_SIZE(buck_smps2_voltages), + }, + .load_lp_uA = 20000, + .update_bank = 0x04, + .update_reg = 0x04, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + .voltage_bank = 0x04, + .voltage_reg = 0x17, + .voltage_mask = 0x3f, + .voltage_ctrl_bank = 0x04, + .voltage_ctrl_reg = 0x04, + .voltage_ctrl_mask = 0x0c, + }, + [AB8505_BUCK_SAFE] = { + .desc = { + .name = "BUCK-SAFE", + .ops = &ab8500_buck_ops, + .init_cb = ab8500_buck_init, + .type = REGULATOR_VOLTAGE, + .id = AB8505_BUCK_SAFE, + .owner = THIS_MODULE, + .n_voltages = 128, + .linear_ranges = buck_low_7bit_voltages, + .n_linear_ranges = ARRAY_SIZE(buck_low_7bit_voltages), + }, + .load_lp_uA = 50000, + .update_bank = 0x04, + .update_reg = 0x05, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + .voltage_bank = 0x04, + .voltage_reg = 0x1b, + .voltage_mask = 0x7f, + .voltage_ctrl_bank = 0x04, + .voltage_ctrl_reg = 0x05, + .voltage_ctrl_mask = 0x0c, + }, + [AB8505_BUCK_ARM] = { + .desc = { + .name = "BUCK-ARM", + .ops = &ab8500_buck_voltage_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8505_BUCK_ARM, + .owner = THIS_MODULE, + .n_voltages = 128, + .linear_ranges = ab8505_buck_arm_voltages, + .n_linear_ranges = ARRAY_SIZE(ab8505_buck_arm_voltages), + }, + .voltage_bank = 0x04, + .voltage_reg = 0x0b, + .voltage_mask = 0x7f, + .voltage_ctrl_bank = 0x04, + .voltage_ctrl_reg = 0x00, + .voltage_ctrl_mask = 0x0c, + .voltage_ext_ctrl_bank = 0x04, + .voltage_ext_ctrl_reg = 0x28, + .voltage_ext_ctrl_mask = 0x07, + .voltage_ext_reg = 0x24, + .voltage_ext_regs = 4, + }, + [AB8505_BUCK_SMPSC] = { + .desc = { + .name = "BUCK-SMPSC", + .ops = &ab8500_buck_voltage_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8505_BUCK_SMPSC, + .owner = THIS_MODULE, + .n_voltages = 64, + .linear_ranges = buck_low_voltages, + .n_linear_ranges = ARRAY_SIZE(buck_low_voltages), + }, + .voltage_bank = 0x04, + .voltage_reg = 0x0e, + .voltage_mask = 0x3f, + .voltage_ctrl_bank = 0x04, + .voltage_ctrl_reg = 0x02, + .voltage_ctrl_mask = 0x24, + .voltage_ext_ctrl_bank = 0x04, + .voltage_ext_ctrl_reg = 0x2a, + .voltage_ext_ctrl_mask = 0x03, + .voltage_ext_reg = 0x2b, + .voltage_ext_regs = 2, + }, + [AB8505_BUCK_SMPSM] = { + .desc = { + .name = "BUCK-SMPSM", + .ops = &ab8500_buck_voltage_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8505_BUCK_SMPSM, + .owner = THIS_MODULE, + .n_voltages = 64, + .linear_ranges = buck_low_voltages, + .n_linear_ranges = ARRAY_SIZE(buck_low_voltages), + }, + .voltage_bank = 0x04, + .voltage_reg = 0x41, + .voltage_mask = 0x3f, + .voltage_ctrl_bank = 0x04, + .voltage_ctrl_reg = 0x40, + .voltage_ctrl_mask = 0x04, + .voltage_ext_ctrl_bank = 0x04, + .voltage_ext_ctrl_reg = 0x47, + .voltage_ext_ctrl_mask = 0x03, + .voltage_ext_reg = 0x45, + .voltage_ext_regs = 2, + }, }; static struct ab8500_shared_mode ldo_anamic1_shared = { @@ -1613,6 +2222,12 @@ static struct of_regulator_match ab8500_regulator_match[] = { { .name = "ab8500_ldo_anamic2", .driver_data = (void *) AB8500_LDO_ANAMIC2, }, { .name = "ab8500_ldo_dmic", .driver_data = (void *) AB8500_LDO_DMIC, }, { .name = "ab8500_ldo_ana", .driver_data = (void *) AB8500_LDO_ANA, }, + { .name = "ab8500_buck_smps1", .driver_data = (void *)AB8500_BUCK_SMPS1, }, + { .name = "ab8500_buck_smps2", .driver_data = (void *)AB8500_BUCK_SMPS2, }, + { .name = "ab8500_buck_smps3", .driver_data = (void *)AB8500_BUCK_SMPS3, }, + { .name = "ab8500_buck_arm", .driver_data = (void *)AB8500_BUCK_ARM, }, + { .name = "ab8500_buck_ape", .driver_data = (void *)AB8500_BUCK_APE, }, + { .name = "ab8500_buck_mod", .driver_data = (void *)AB8500_BUCK_MOD, }, }; static struct of_regulator_match ab8505_regulator_match[] = { @@ -1629,6 +2244,12 @@ static struct of_regulator_match ab8505_regulator_match[] = { { .name = "ab8500_ldo_anamic2", .driver_data = (void *) AB8505_LDO_ANAMIC2, }, { .name = "ab8500_ldo_aux8", .driver_data = (void *) AB8505_LDO_AUX8, }, { .name = "ab8500_ldo_ana", .driver_data = (void *) AB8505_LDO_ANA, }, + { .name = "ab8505_buck_smpsa", .driver_data = (void *)AB8505_BUCK_SMPSA, }, + { .name = "ab8505_buck_smpsb", .driver_data = (void *)AB8505_BUCK_SMPSB, }, + { .name = "ab8505_buck_safe", .driver_data = (void *)AB8505_BUCK_SAFE, }, + { .name = "ab8505_buck_arm", .driver_data = (void *)AB8505_BUCK_ARM, }, + { .name = "ab8505_buck_smpsc", .driver_data = (void *)AB8505_BUCK_SMPSC, }, + { .name = "ab8505_buck_smpsm", .driver_data = (void *)AB8505_BUCK_SMPSM, }, }; static struct { @@ -1677,9 +2298,14 @@ static int ab8500_regulator_register(struct platform_device *pdev, config.driver_data = info; config.of_node = np; - /* fix for hardware before ab8500v2.0 */ - if (is_ab8500_1p1_or_earlier(ab8500)) { - if (info->desc.id == AB8500_LDO_AUX3) { + /* Handle the different VAUX3 implementations in early AB8500 cuts. */ + if (info->desc.id == AB8500_LDO_AUX3) { + if (is_ab8500_1p0_or_earlier(ab8500)) { + info->desc.ops = &ab8500_regulator_mode_ops; + info->desc.n_voltages = 1; + info->desc.volt_table = fixed_1200000_voltage; + info->voltage_mask = 0; + } else if (is_ab8500_1p1_or_earlier(ab8500)) { info->desc.n_voltages = ARRAY_SIZE(ldo_vauxn_voltages); info->desc.volt_table = ldo_vauxn_voltages; diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index da891415efc0..ec6ec071ffde 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -1652,7 +1652,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev) (regulators == axp803_regulators && i == AXP803_DC1SW) || (regulators == axp809_regulators && i == AXP809_DC1SW) || (regulators == axp15060_regulators && i == AXP15060_SW)) { - new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), + new_desc = devm_kzalloc(&pdev->dev, sizeof(*new_desc), GFP_KERNEL); if (!new_desc) return -ENOMEM; @@ -1665,7 +1665,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev) if ((regulators == axp22x_regulators && i == AXP22X_DC5LDO) || (regulators == axp809_regulators && i == AXP809_DC5LDO) || (regulators == axp15060_regulators && i == AXP15060_CPUSLDO)) { - new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), + new_desc = devm_kzalloc(&pdev->dev, sizeof(*new_desc), GFP_KERNEL); if (!new_desc) return -ENOMEM; @@ -1677,7 +1677,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev) if (regulators == axp15060_regulators && i == AXP15060_RTC_LDO) { - new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), + new_desc = devm_kzalloc(&pdev->dev, sizeof(*new_desc), GFP_KERNEL); if (!new_desc) return -ENOMEM; diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 6a4008f387b5..14422cfe80e2 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -462,6 +462,7 @@ int regulator_check_voltage(struct regulator_dev *rdev, return 0; } +EXPORT_SYMBOL_GPL(regulator_check_voltage); /* return 0 if the state is valid */ static int regulator_check_states(suspend_state_t state) @@ -502,6 +503,7 @@ int regulator_check_consumers(struct regulator_dev *rdev, return 0; } +EXPORT_SYMBOL_GPL(regulator_check_consumers); /* current constraint check */ static int regulator_check_current_limit(struct regulator_dev *rdev, @@ -2239,6 +2241,7 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) if (r == rdev) { dev_err(dev, "Supply for %s (%s) resolved to itself\n", rdev->desc->name, rdev->supply_name); + put_device(&rdev->dev); if (!have_full_constraints()) { ret = -EINVAL; goto out; @@ -3029,7 +3032,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev) */ trace_regulator_enable_delay(rdev_get_name(rdev)); - /* If poll_enabled_time is set, poll upto the delay calculated + /* If poll_enabled_time is set, poll up to the delay calculated * above, delaying poll_enabled_time uS to check if the regulator * actually got enabled. * If the regulator isn't enabled after our delay helper has expired, @@ -4468,6 +4471,7 @@ int regulator_do_balance_voltage(struct regulator_dev *rdev, out: return ret; } +EXPORT_SYMBOL_GPL(regulator_do_balance_voltage); static int regulator_balance_voltage(struct regulator_dev *rdev, suspend_state_t state) @@ -5797,6 +5801,7 @@ int regulator_coupler_register(struct regulator_coupler *coupler) return 0; } +EXPORT_SYMBOL_GPL(regulator_coupler_register); static struct regulator_coupler * regulator_find_coupler(struct regulator_dev *rdev) @@ -5861,6 +5866,7 @@ static void regulator_resolve_coupling(struct regulator_dev *rdev) if (c_rdev->coupling_desc.coupler != coupler) { rdev_err(rdev, "coupler mismatch with %s\n", rdev_get_name(c_rdev)); + put_device(&c_rdev->dev); return; } @@ -5907,6 +5913,8 @@ static void regulator_remove_coupling(struct regulator_dev *rdev) c_desc->coupled_rdevs[i] = NULL; c_desc->n_resolved--; + + put_device(&c_rdev->dev); } if (coupler && coupler->detach_regulator) { diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 417d282dd4ed..faa82f30eb1f 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -28,6 +28,7 @@ #include <linux/regulator/of_regulator.h> #include <linux/regulator/machine.h> #include <linux/clk.h> +#include <linux/string.h> struct fixed_voltage_data { struct regulator_desc desc; @@ -225,6 +226,9 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) enum gpiod_flags gflags; int ret; + if (!pdev->dev.of_node && strcmp(pdev->name, "reg-fixed-voltage")) + return -ENODEV; + drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data), GFP_KERNEL); if (!drvdata) diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c index e0b62bc02a1e..e483e9d7dcf2 100644 --- a/drivers/regulator/mp886x.c +++ b/drivers/regulator/mp886x.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // -// MP8867/MP8869 regulator driver +// MP8864/MP8867/MP8869 regulator driver // // Copyright (C) 2020 Synaptics Incorporated // @@ -229,6 +229,23 @@ static const struct regulator_ops mp8867_regulator_ops = { .set_ramp_delay = regulator_set_ramp_delay_regmap, }; +static const struct mp886x_cfg_info mp8864_ci = { + .rops = &mp8867_regulator_ops, + .slew_rates = { + 64000, + 32000, + 16000, + 8000, + 4000, + 2000, + 1000, + 500, + }, + .switch_freq = { 600000, 850000, 1100000, 1600000 }, + .fs_reg = MP886X_SYSCNTLREG1, + .fs_shift = 1, +}; + static const struct mp886x_cfg_info mp8867_ci = { .rops = &mp8867_regulator_ops, .slew_rates = { @@ -256,6 +273,7 @@ static int mp886x_regulator_register(struct mp886x_device_info *di, { struct regulator_desc *rdesc = &di->desc; struct regulator_dev *rdev; + int sel; rdesc->name = "mp886x-reg"; rdesc->supply_name = "vin"; @@ -267,7 +285,7 @@ static int mp886x_regulator_register(struct mp886x_device_info *di, rdesc->min_uV = 600000; rdesc->uV_step = 10000; rdesc->vsel_reg = MP886X_VSEL; - rdesc->vsel_mask = 0x3f; + rdesc->vsel_mask = 0x7f; rdesc->ramp_reg = MP886X_SYSCNTLREG1; rdesc->ramp_mask = MP886X_SLEW_MASK; rdesc->ramp_delay_table = di->ci->slew_rates; @@ -277,7 +295,12 @@ static int mp886x_regulator_register(struct mp886x_device_info *di, rdev = devm_regulator_register(di->dev, &di->desc, config); if (IS_ERR(rdev)) return PTR_ERR(rdev); - di->sel = rdesc->ops->get_voltage_sel(rdev); + + sel = rdesc->ops->get_voltage_sel(rdev); + if (sel < 0) + return sel; + di->sel = sel; + return 0; } @@ -311,6 +334,9 @@ static int mp886x_i2c_probe(struct i2c_client *client) if (ret) return ret; + if (di->r[1] == 0) + return -EINVAL; + di->en_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); if (IS_ERR(di->en_gpio)) return PTR_ERR(di->en_gpio); @@ -341,6 +367,7 @@ static int mp886x_i2c_probe(struct i2c_client *client) } static const struct of_device_id mp886x_dt_ids[] = { + { .compatible = "mps,mp8864", .data = &mp8864_ci }, { .compatible = "mps,mp8867", .data = &mp8867_ci }, { .compatible = "mps,mp8869", .data = &mp8869_ci }, { } @@ -348,6 +375,7 @@ static const struct of_device_id mp886x_dt_ids[] = { MODULE_DEVICE_TABLE(of, mp886x_dt_ids); static const struct i2c_device_id mp886x_id[] = { + { .name = "mp8864", .driver_data = (kernel_ulong_t)&mp8864_ci }, { .name = "mp8867", .driver_data = (kernel_ulong_t)&mp8867_ci }, { .name = "mp8869", .driver_data = (kernel_ulong_t)&mp8869_ci }, { } diff --git a/drivers/regulator/mpq4210.c b/drivers/regulator/mpq4210.c new file mode 100644 index 000000000000..293e7b209a98 --- /dev/null +++ b/drivers/regulator/mpq4210.c @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Monolithic Power Systems MPQ4210 buck-boost regulator + * + * Copyright (c) 2026 Vaisala Oyj + */ + +#include <linux/bitfield.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/math.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/of_regulator.h> + +#define MPQ4210_REF_LSB 0x00 +#define MPQ4210_REF_LSB_MASK GENMASK(2, 0) +#define MPQ4210_REF_LSB_BITS 3 +#define MPQ4210_REF_MSB 0x01 +#define MPQ4210_CONTROL1 0x02 +#define MPQ4210_CONTROL1_SR GENMASK(7, 6) +#define MPQ4210_CONTROL1_RESERVED BIT(2) +#define MPQ4210_CONTROL1_GO BIT(1) +#define MPQ4210_CONTROL1_ENPWR BIT(0) +#define MPQ4210_INT_MASK 0x06 + +/* + * The feedback reference is an 11 bit value with a 1mV step. The datasheet + * specifies no reference below 0.3V, so those selectors are not offered. + */ +#define MPQ4210_REF_MIN 0x12c +#define MPQ4210_REF_MAX 0x7ff +#define MPQ4210_REF_STEP_UV 1000 + +#define MPQ4210_ENPWR_DELAY_MS 200 + +/* Feedback reference slew rate per MPQ4210_CONTROL1_SR value, in uV/us. */ +static const unsigned int mpq4210_ref_slew_rate[] = { 38, 50, 75, 150 }; + +static const struct regmap_config mpq4210_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = MPQ4210_INT_MASK, +}; + +/* Scale a feedback reference value by the output voltage divider ratio. */ +static unsigned int mpq4210_scale(unsigned int val, u32 r1, u32 r2) +{ + u64 tmp = (u64)val * (r1 + r2); + + do_div(tmp, r2); + + return tmp; +} + +static int mpq4210_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel) +{ + int ret; + + ret = regmap_write(rdev->regmap, MPQ4210_REF_LSB, + sel & MPQ4210_REF_LSB_MASK); + if (ret) + return ret; + + ret = regmap_write(rdev->regmap, MPQ4210_REF_MSB, + sel >> MPQ4210_REF_LSB_BITS); + if (ret) + return ret; + + return regmap_set_bits(rdev->regmap, MPQ4210_CONTROL1, + MPQ4210_CONTROL1_GO); +} + +static int mpq4210_get_voltage_sel(struct regulator_dev *rdev) +{ + unsigned int lsb, msb; + int ret; + + ret = regmap_read(rdev->regmap, MPQ4210_REF_MSB, &msb); + if (ret) + return ret; + + ret = regmap_read(rdev->regmap, MPQ4210_REF_LSB, &lsb); + if (ret) + return ret; + + return (msb << MPQ4210_REF_LSB_BITS) | (lsb & MPQ4210_REF_LSB_MASK); +} + +static int mpq4210_enable(struct regulator_dev *rdev) +{ + int ret; + + ret = regmap_set_bits(rdev->regmap, MPQ4210_CONTROL1, + MPQ4210_CONTROL1_GO); + if (ret) + return ret; + + /* The reference has to settle before power switching may start. */ + msleep(MPQ4210_ENPWR_DELAY_MS); + + return regmap_set_bits(rdev->regmap, MPQ4210_CONTROL1, + MPQ4210_CONTROL1_ENPWR); +} + +static const struct regulator_ops mpq4210_regulator_ops = { + .set_voltage_sel = mpq4210_set_voltage_sel, + .get_voltage_sel = mpq4210_get_voltage_sel, + .list_voltage = regulator_list_voltage_linear, + .set_ramp_delay = regulator_set_ramp_delay_regmap, + .enable = mpq4210_enable, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + +static const struct regulator_desc mpq4210_regulator = { + .name = "mpq4210", + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .ops = &mpq4210_regulator_ops, + .n_voltages = MPQ4210_REF_MAX + 1, + .linear_min_sel = MPQ4210_REF_MIN, + .enable_reg = MPQ4210_CONTROL1, + .enable_mask = MPQ4210_CONTROL1_ENPWR, + .ramp_reg = MPQ4210_CONTROL1, + .ramp_mask = MPQ4210_CONTROL1_SR, + .n_ramp_values = ARRAY_SIZE(mpq4210_ref_slew_rate), +}; + +static int mpq4210_i2c_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct regulator_config config = { }; + struct regulator_desc *desc; + struct regulator_dev *rdev; + struct gpio_desc *enable; + struct regmap *regmap; + unsigned int *slew; + unsigned int i, val; + u32 r[2]; + int ret; + + ret = of_property_read_u32_array(dev->of_node, + "mps,fb-voltage-divider-ohms", + r, ARRAY_SIZE(r)); + if (ret) + return dev_err_probe(dev, ret, + "failed to read mps,fb-voltage-divider-ohms\n"); + + if (!r[1]) + return dev_err_probe(dev, -EINVAL, + "feedback divider R2 must not be zero\n"); + + /* The controller does not answer on the bus while EN is deasserted. */ + enable = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH); + if (IS_ERR(enable)) + return dev_err_probe(dev, PTR_ERR(enable), + "failed to get enable GPIO\n"); + + regmap = devm_regmap_init_i2c(client, &mpq4210_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "failed to init regmap\n"); + + desc = devm_kmemdup(dev, &mpq4210_regulator, sizeof(*desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + + desc->min_uV = mpq4210_scale(MPQ4210_REF_MIN * MPQ4210_REF_STEP_UV, + r[0], r[1]); + desc->uV_step = mpq4210_scale(MPQ4210_REF_STEP_UV, r[0], r[1]); + + slew = devm_kcalloc(dev, ARRAY_SIZE(mpq4210_ref_slew_rate), + sizeof(*slew), GFP_KERNEL); + if (!slew) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(mpq4210_ref_slew_rate); i++) + slew[i] = mpq4210_scale(mpq4210_ref_slew_rate[i], r[0], r[1]); + + desc->ramp_delay_table = slew; + + ret = regmap_read(regmap, MPQ4210_CONTROL1, &val); + if (ret) + return dev_err_probe(dev, ret, "failed to read control 1\n"); + + /* The core overrides this if the board sets regulator-ramp-delay. */ + desc->ramp_delay = slew[FIELD_GET(MPQ4210_CONTROL1_SR, val)]; + + /* + * Documented as reserved, but the datasheet requires it to be set + * before the controller starts up. + */ + ret = regmap_set_bits(regmap, MPQ4210_CONTROL1, + MPQ4210_CONTROL1_RESERVED); + if (ret) + return dev_err_probe(dev, ret, "failed to write control 1\n"); + + config.dev = dev; + config.regmap = regmap; + config.of_node = dev->of_node; + config.init_data = of_get_regulator_init_data(dev, dev->of_node, desc); + if (!config.init_data) + return -ENOMEM; + + rdev = devm_regulator_register(dev, desc, &config); + if (IS_ERR(rdev)) + return dev_err_probe(dev, PTR_ERR(rdev), + "failed to register regulator\n"); + + return 0; +} + +static const struct of_device_id mpq4210_of_match[] = { + { .compatible = "mps,mpq4210" }, + { } +}; +MODULE_DEVICE_TABLE(of, mpq4210_of_match); + +static const struct i2c_device_id mpq4210_i2c_id[] = { + { .name = "mpq4210" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mpq4210_i2c_id); + +static struct i2c_driver mpq4210_regulator_driver = { + .driver = { + .name = "mpq4210", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + .of_match_table = mpq4210_of_match, + }, + .probe = mpq4210_i2c_probe, + .id_table = mpq4210_i2c_id, +}; + +module_i2c_driver(mpq4210_regulator_driver); + +MODULE_DESCRIPTION("Monolithic Power Systems MPQ4210 voltage regulator driver"); +MODULE_AUTHOR("Tapio Reijonen <tapio.reijonen@vaisala.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/nex10000ub-regulator.c b/drivers/regulator/nex10000ub-regulator.c new file mode 100644 index 000000000000..f44b8b7906b9 --- /dev/null +++ b/drivers/regulator/nex10000ub-regulator.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Nexperia NEX10000UB Regulator driver + * + * Copyright (C) 2026 Linaro Limited. + */ + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> + +#define NEX10000UB_REG_VPOS 0x00 +#define NEX10000UB_REG_VNEG 0x01 +#define NEX10000UB_REG_ID 0x02 + +#define NEX10000UB_VOUT_MASK 0x1F +#define NEX10000UB_VOUT_N_VOLTAGE 0x15 +#define NEX10000UB_VOUT_VMIN 4000000 +#define NEX10000UB_VOUT_VMAX 6000000 +#define NEX10000UB_VOUT_STEP 100000 + +#define NEX10000UB_REGULATOR_ID_VPOS 0 +#define NEX10000UB_REGULATOR_ID_VNEG 1 +#define NEX10000UB_MAX_REGULATORS 2 + +static const struct regulator_ops nex10000ub_regulator_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, +}; + +static int nex10000ub_of_parse_cb(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *config) +{ + struct gpio_desc *ena_gpiod; + + ena_gpiod = fwnode_gpiod_get_index(of_fwnode_handle(np), "enable", 0, + GPIOD_OUT_LOW, desc->name); + if (IS_ERR(ena_gpiod)) + return PTR_ERR(ena_gpiod); + + config->ena_gpiod = ena_gpiod; + + return 0; +} + +#define NEX10000UB_REGULATOR_DESC(_id, _name) \ + [NEX10000UB_REGULATOR_ID_##_id] = { \ + .name = "nex10000ub-"#_name, \ + .supply_name = "vin", \ + .id = NEX10000UB_REGULATOR_ID_##_id, \ + .of_match = of_match_ptr(#_name), \ + .of_parse_cb = nex10000ub_of_parse_cb, \ + .ops = &nex10000ub_regulator_ops, \ + .n_voltages = NEX10000UB_VOUT_N_VOLTAGE, \ + .min_uV = NEX10000UB_VOUT_VMIN, \ + .uV_step = NEX10000UB_VOUT_STEP, \ + .enable_time = 2000, \ + .vsel_mask = NEX10000UB_VOUT_MASK, \ + .vsel_reg = NEX10000UB_REG_##_id, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + } + +static const struct regulator_desc nex10000_regs_desc[NEX10000UB_MAX_REGULATORS] = { + NEX10000UB_REGULATOR_DESC(VPOS, vpos), + NEX10000UB_REGULATOR_DESC(VNEG, vneg), +}; + +static const struct regmap_config nex10000ub_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = NEX10000UB_REG_ID, + .cache_type = REGCACHE_NONE, +}; + +static int nex10000ub_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct regmap *map; + int id; + int ret; + + map = devm_regmap_init_i2c(client, &nex10000ub_regmap_config); + if (IS_ERR(map)) { + ret = PTR_ERR(map); + dev_err(dev, "regmap init failed: %d\n", ret); + return ret; + } + + for (id = 0; id < NEX10000UB_MAX_REGULATORS; ++id) { + struct regulator_config config = { }; + struct regulator_dev *rdev; + + config.regmap = map; + config.dev = dev; + + rdev = devm_regulator_register(dev, &nex10000_regs_desc[id], + &config); + if (IS_ERR(rdev)) { + ret = PTR_ERR(rdev); + dev_err(dev, "regulator %s register failed: %d\n", + nex10000_regs_desc[id].name, ret); + return ret; + } + } + + return 0; +} + +static const struct i2c_device_id nex10000ub_id[] = { + { .name = "nex10000ub" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, nex10000ub_id); + +static const struct of_device_id __maybe_unused nex10000ub_of_match[] = { + { .compatible = "nexperia,nex10000ub" }, + {}, +}; +MODULE_DEVICE_TABLE(of, nex10000ub_of_match); + +static struct i2c_driver nex10000ub_i2c_driver = { + .driver = { + .name = "nex10000ub", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + .of_match_table = of_match_ptr(nex10000ub_of_match), + }, + .probe = nex10000ub_probe, + .id_table = nex10000ub_id, +}; + +module_i2c_driver(nex10000ub_i2c_driver); + +MODULE_DESCRIPTION("NEX10000UB regulator driver"); +MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c index c41db70fa052..613bce411f31 100644 --- a/drivers/regulator/pca9450-regulator.c +++ b/drivers/regulator/pca9450-regulator.c @@ -77,10 +77,56 @@ static const unsigned int pca9450_dvs_buck_ramp_table[] = { 25000, 12500, 6250, 3125 }; +static int pca9450_regulator_is_enabled(struct regulator_dev *rdev) +{ + unsigned int val; + int ret; + + ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); + if (ret) + return ret; + + /* All valid nonzero ENMODE values enable the regulator in RUN mode. */ + return !!(val & rdev->desc->enable_mask); +} + +static int pca9450_set_suspend_disable(struct regulator_dev *rdev, + unsigned int suspend_val) +{ + int ret; + + /* Do not enable a runtime-disabled regulator when returning to RUN. */ + ret = pca9450_regulator_is_enabled(rdev); + if (ret < 0) + return ret; + if (!ret) + return 0; + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, + suspend_val); +} + +/* + * ENMODE = 10b keeps the regulator enabled in RUN mode and disables it + * while PMIC_STBY_REQ is asserted. + */ +static int pca9450_buck_set_suspend_disable(struct regulator_dev *rdev) +{ + return pca9450_set_suspend_disable(rdev, + BUCK_ENMODE_ONREQ_STBYREQ); +} + +static int pca9450_ldo_set_suspend_disable(struct regulator_dev *rdev) +{ + return pca9450_set_suspend_disable(rdev, + LDO_ENMODE_ONREQ_STBYREQ); +} + static const struct regulator_ops pca9450_dvs_buck_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, + .is_enabled = pca9450_regulator_is_enabled, .list_voltage = regulator_list_voltage_linear_range, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -88,18 +134,20 @@ static const struct regulator_ops pca9450_dvs_buck_regulator_ops = { .set_ramp_delay = regulator_set_ramp_delay_regmap, .set_mode = pca9450_buck_set_mode, .get_mode = pca9450_buck_get_mode, + .set_suspend_disable = pca9450_buck_set_suspend_disable, }; static const struct regulator_ops pca9450_buck_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, + .is_enabled = pca9450_regulator_is_enabled, .list_voltage = regulator_list_voltage_linear_range, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_time_sel = regulator_set_voltage_time_sel, .set_mode = pca9450_buck_set_mode, .get_mode = pca9450_buck_get_mode, + .set_suspend_disable = pca9450_buck_set_suspend_disable, }; static const struct regulator_ops pca9450_ldo_regulator_ops = { @@ -111,6 +159,16 @@ static const struct regulator_ops pca9450_ldo_regulator_ops = { .get_voltage_sel = regulator_get_voltage_sel_regmap, }; +static const struct regulator_ops pca9450_ldo_suspend_regulator_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_suspend_disable = pca9450_ldo_set_suspend_disable, +}; + static unsigned int pca9450_ldo5_get_reg_voltage_sel(struct regulator_dev *rdev) { struct pca9450 *pca9450 = rdev_get_drvdata(rdev); @@ -164,6 +222,7 @@ static const struct regulator_ops pca9450_ldo5_regulator_ops = { .list_voltage = regulator_list_voltage_linear_range, .set_voltage_sel = pca9450_ldo5_set_voltage_sel_regmap, .get_voltage_sel = pca9450_ldo5_get_voltage_sel_regmap, + .set_suspend_disable = pca9450_ldo_set_suspend_disable, }; /* @@ -575,7 +634,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = { .of_match = of_match_ptr("LDO3"), .regulators_node = of_match_ptr("regulators"), .id = PCA9450_LDO3, - .ops = &pca9450_ldo_regulator_ops, + .ops = &pca9450_ldo_suspend_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = PCA9450_LDO3_VOLTAGE_NUM, .linear_ranges = pca9450_ldo34_volts, @@ -594,7 +653,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = { .of_match = of_match_ptr("LDO4"), .regulators_node = of_match_ptr("regulators"), .id = PCA9450_LDO4, - .ops = &pca9450_ldo_regulator_ops, + .ops = &pca9450_ldo_suspend_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = PCA9450_LDO4_VOLTAGE_NUM, .linear_ranges = pca9450_ldo34_volts, @@ -621,7 +680,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = { .vsel_reg = PCA9450_REG_LDO5CTRL_H, .vsel_mask = LDO5HOUT_MASK, .enable_reg = PCA9450_REG_LDO5CTRL_L, - .enable_mask = LDO5H_EN_MASK, + .enable_mask = LDO5L_EN_MASK, .owner = THIS_MODULE, }, }, @@ -820,7 +879,7 @@ static struct pca9450_regulator_desc pca9450bc_regulators[] = { .of_match = of_match_ptr("LDO3"), .regulators_node = of_match_ptr("regulators"), .id = PCA9450_LDO3, - .ops = &pca9450_ldo_regulator_ops, + .ops = &pca9450_ldo_suspend_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = PCA9450_LDO3_VOLTAGE_NUM, .linear_ranges = pca9450_ldo34_volts, @@ -839,7 +898,7 @@ static struct pca9450_regulator_desc pca9450bc_regulators[] = { .of_match = of_match_ptr("LDO4"), .regulators_node = of_match_ptr("regulators"), .id = PCA9450_LDO4, - .ops = &pca9450_ldo_regulator_ops, + .ops = &pca9450_ldo_suspend_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = PCA9450_LDO4_VOLTAGE_NUM, .linear_ranges = pca9450_ldo34_volts, @@ -866,7 +925,7 @@ static struct pca9450_regulator_desc pca9450bc_regulators[] = { .vsel_reg = PCA9450_REG_LDO5CTRL_H, .vsel_mask = LDO5HOUT_MASK, .enable_reg = PCA9450_REG_LDO5CTRL_L, - .enable_mask = LDO5H_EN_MASK, + .enable_mask = LDO5L_EN_MASK, .owner = THIS_MODULE, }, }, @@ -1040,7 +1099,7 @@ static struct pca9450_regulator_desc pca9451a_regulators[] = { .of_match = of_match_ptr("LDO3"), .regulators_node = of_match_ptr("regulators"), .id = PCA9450_LDO3, - .ops = &pca9450_ldo_regulator_ops, + .ops = &pca9450_ldo_suspend_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = PCA9450_LDO3_VOLTAGE_NUM, .linear_ranges = pca9450_ldo34_volts, @@ -1059,7 +1118,7 @@ static struct pca9450_regulator_desc pca9451a_regulators[] = { .of_match = of_match_ptr("LDO4"), .regulators_node = of_match_ptr("regulators"), .id = PCA9450_LDO4, - .ops = &pca9450_ldo_regulator_ops, + .ops = &pca9450_ldo_suspend_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = PCA9450_LDO4_VOLTAGE_NUM, .linear_ranges = pca9450_ldo34_volts, @@ -1086,7 +1145,7 @@ static struct pca9450_regulator_desc pca9451a_regulators[] = { .vsel_reg = PCA9450_REG_LDO5CTRL_H, .vsel_mask = LDO5HOUT_MASK, .enable_reg = PCA9450_REG_LDO5CTRL_L, - .enable_mask = LDO5H_EN_MASK, + .enable_mask = LDO5L_EN_MASK, .owner = THIS_MODULE, }, }, diff --git a/drivers/regulator/pf1550-regulator.c b/drivers/regulator/pf1550-regulator.c index ceee553a84b2..84f8b187a91b 100644 --- a/drivers/regulator/pf1550-regulator.c +++ b/drivers/regulator/pf1550-regulator.c @@ -49,17 +49,26 @@ static const int pf1550_ldo13_volts[] = { static int pf1550_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) { int id = rdev_get_id(rdev); - unsigned int ramp_bits = 0; + unsigned int ramp_bits; int ret; if (id > PF1550_VREFDDR) return -EACCES; - if (ramp_delay < 0 || ramp_delay > 6250) + switch (ramp_delay) { + case 0: + /* Ramp control is disabled, so use the fastest rate. */ + ramp_bits = 0; + break; + case 1 ... 3125: + ramp_bits = 1; + break; + case 3126 ... 6250: + ramp_bits = 0; + break; + default: return -EINVAL; - - ramp_delay = 6250 / ramp_delay; - ramp_bits = ramp_delay >> 1; + } ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg + 4, 0x10, ramp_bits << 4); diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c index b96afbf11ff3..1f2c405fd2bd 100644 --- a/drivers/regulator/pv88080-regulator.c +++ b/drivers/regulator/pv88080-regulator.c @@ -432,7 +432,7 @@ static int pv88080_i2c_probe(struct i2c_client *i2c) config.dev = chip->dev; config.regmap = chip->regmap; - /* Registeration for BUCK1, 2, 3 */ + /* Registration for BUCK1, 2, 3 */ for (i = 0; i < PV88080_MAX_REGULATORS-1; i++) { if (init_data) config.init_data = &init_data[i]; @@ -498,7 +498,7 @@ static int pv88080_i2c_probe(struct i2c_client *i2c) pv88080_regulator_info[PV88080_ID_HVBUCK].desc.vsel_mask = regmap_config->hvbuck_vsel_mask; - /* Registeration for HVBUCK */ + /* Registration for HVBUCK */ if (init_data) config.init_data = &init_data[PV88080_ID_HVBUCK]; diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index 25c14de3cd8b..4c90d206e63b 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -400,7 +400,7 @@ static unsigned int rpmh_regulator_vrm_get_mode(struct regulator_dev *rdev) * This function is used in the regulator_ops for VRM type RPMh regulator * devices. * - * Return: 0 on success, or a negative error number on failure + * Return: the regulator mode to use for the load */ static unsigned int rpmh_regulator_vrm_get_optimum_mode( struct regulator_dev *rdev, int input_uV, int output_uV, int load_uA) @@ -1589,31 +1589,34 @@ static const struct rpmh_vreg_init_data pm6150l_vreg_data[] = { }; static const struct rpmh_vreg_init_data pm6350_vreg_data[] = { - RPMH_VREG("smps1", SMPS, 1, &pmic5_ftsmps510, NULL), - RPMH_VREG("smps2", SMPS, 2, &pmic5_hfsmps510, NULL), - /* smps3 - smps5 not configured */ - RPMH_VREG("ldo1", LDO, 1, &pmic5_nldo, NULL), - RPMH_VREG("ldo2", LDO, 2, &pmic5_pldo, NULL), - RPMH_VREG("ldo3", LDO, 3, &pmic5_pldo, NULL), - RPMH_VREG("ldo4", LDO, 4, &pmic5_nldo, NULL), - RPMH_VREG("ldo5", LDO, 5, &pmic5_pldo, NULL), - RPMH_VREG("ldo6", LDO, 6, &pmic5_pldo, NULL), - RPMH_VREG("ldo7", LDO, 7, &pmic5_pldo, NULL), - RPMH_VREG("ldo8", LDO, 8, &pmic5_pldo, NULL), - RPMH_VREG("ldo9", LDO, 9, &pmic5_pldo, NULL), - RPMH_VREG("ldo10", LDO, 10, &pmic5_pldo, NULL), - RPMH_VREG("ldo11", LDO, 11, &pmic5_pldo, NULL), - RPMH_VREG("ldo12", LDO, 12, &pmic5_pldo, NULL), - RPMH_VREG("ldo13", LDO, 13, &pmic5_nldo, NULL), - RPMH_VREG("ldo14", LDO, 14, &pmic5_pldo, NULL), - RPMH_VREG("ldo15", LDO, 15, &pmic5_nldo, NULL), - RPMH_VREG("ldo16", LDO, 16, &pmic5_nldo, NULL), - /* ldo17 not configured */ - RPMH_VREG("ldo18", LDO, 18, &pmic5_nldo, NULL), - RPMH_VREG("ldo19", LDO, 19, &pmic5_nldo, NULL), - RPMH_VREG("ldo20", LDO, 20, &pmic5_nldo, NULL), - RPMH_VREG("ldo21", LDO, 21, &pmic5_nldo, NULL), - RPMH_VREG("ldo22", LDO, 22, &pmic5_nldo, NULL), + RPMH_VREG("smps1", SMPS, 1, &pmic5_ftsmps510, "vdd-s1"), + RPMH_VREG("smps2", SMPS, 2, &pmic5_hfsmps510, "vdd-s2"), + RPMH_VREG("smps3", SMPS, 3, &pmic5_ftsmps510, "vdd-s3"), + RPMH_VREG("smps4", SMPS, 4, &pmic5_ftsmps510, "vdd-s4"), + RPMH_VREG("smps5", SMPS, 5, &pmic5_ftsmps510, "vdd-s5"), + RPMH_VREG("smps6", SMPS, 6, &pmic5_hfsmps510, "vdd-s6"), + RPMH_VREG("ldo1", LDO, 1, &pmic5_nldo, "vdd-l1"), + RPMH_VREG("ldo2", LDO, 2, &pmic5_pldo, "vdd-l2-l5-l7"), + RPMH_VREG("ldo3", LDO, 3, &pmic5_pldo, "vdd-l3-l6-l8-l9-l10"), + RPMH_VREG("ldo4", LDO, 4, &pmic5_nldo, "vdd-l4"), + RPMH_VREG("ldo5", LDO, 5, &pmic5_pldo, "vdd-l2-l5-l7"), + RPMH_VREG("ldo6", LDO, 6, &pmic5_pldo, "vdd-l3-l6-l8-l9-l10"), + RPMH_VREG("ldo7", LDO, 7, &pmic5_pldo, "vdd-l2-l5-l7"), + RPMH_VREG("ldo8", LDO, 8, &pmic5_pldo, "vdd-l3-l6-l8-l9-l10"), + RPMH_VREG("ldo9", LDO, 9, &pmic5_pldo, "vdd-l3-l6-l8-l9-l10"), + RPMH_VREG("ldo10", LDO, 10, &pmic5_pldo, "vdd-l3-l6-l8-l9-l10"), + RPMH_VREG("ldo11", LDO, 11, &pmic5_pldo, "vdd-l11"), + RPMH_VREG("ldo12", LDO, 12, &pmic5_pldo, "vdd-l12-l14"), + RPMH_VREG("ldo13", LDO, 13, &pmic5_nldo, "vdd-l13"), + RPMH_VREG("ldo14", LDO, 14, &pmic5_pldo, "vdd-l12-l14"), + RPMH_VREG("ldo15", LDO, 15, &pmic5_nldo, "vdd-l15-l19-l22"), + RPMH_VREG("ldo16", LDO, 16, &pmic5_nldo, "vdd-l16"), + RPMH_VREG("ldo17", LDO, 17, &pmic5_nldo, "vdd-l17"), + RPMH_VREG("ldo18", LDO, 18, &pmic5_nldo, "vdd-l18-l20-l21"), + RPMH_VREG("ldo19", LDO, 19, &pmic5_nldo, "vdd-l15-l19-l22"), + RPMH_VREG("ldo20", LDO, 20, &pmic5_nldo, "vdd-l18-l20-l21"), + RPMH_VREG("ldo21", LDO, 21, &pmic5_nldo, "vdd-l18-l20-l21"), + RPMH_VREG("ldo22", LDO, 22, &pmic5_nldo, "vdd-l15-l19-l22"), }; static const struct rpmh_vreg_init_data pmcx0102_vreg_data[] = { diff --git a/drivers/regulator/rt6190-regulator.c b/drivers/regulator/rt6190-regulator.c index f2cd9540038d..21ced348a2cf 100644 --- a/drivers/regulator/rt6190-regulator.c +++ b/drivers/regulator/rt6190-regulator.c @@ -108,19 +108,27 @@ static int rt6190_out_enable(struct regulator_dev *rdev) ret = regmap_raw_read(regmap, RT6190_REG_OUTV, out_cfg, sizeof(out_cfg)); if (ret) - return ret; + goto err_pm_put; ret = regulator_enable_regmap(rdev); if (ret) - return ret; + goto err_pm_put; ret = regmap_raw_write(regmap, RT6190_REG_OUTV, out_cfg, sizeof(out_cfg)); if (ret) - return ret; + goto err_pm_put; + + ret = regmap_update_bits(regmap, RT6190_REG_SET5, RT6190_ENGCP_MASK, + RT6190_ENGCP_MASK); + if (ret) + goto err_pm_put; + + return 0; - return regmap_update_bits(regmap, RT6190_REG_SET5, RT6190_ENGCP_MASK, - RT6190_ENGCP_MASK); +err_pm_put: + pm_runtime_put(data->dev); + return ret; } static int rt6190_out_disable(struct regulator_dev *rdev) diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c index a09c6ae6a0ce..7f99f3e90bec 100644 --- a/drivers/regulator/tps6105x-regulator.c +++ b/drivers/regulator/tps6105x-regulator.c @@ -65,7 +65,7 @@ static int tps6105x_regulator_probe(struct platform_device *pdev) /* This instance is not set for regulator mode so bail out */ if (pdata->mode != TPS6105X_MODE_VOLTAGE) { dev_info(&pdev->dev, - "chip not in voltage mode mode, exit probe\n"); + "chip not in voltage mode, exit probe\n"); return 0; } diff --git a/drivers/regulator/tps65185.c b/drivers/regulator/tps65185.c index 6a3130177e7a..4865227e444a 100644 --- a/drivers/regulator/tps65185.c +++ b/drivers/regulator/tps65185.c @@ -392,8 +392,7 @@ static int tps65185_probe(struct i2c_client *client) IRQF_TRIGGER_RISING | IRQF_ONESHOT, "PGOOD", data); if (ret) - return dev_err_probe(&client->dev, ret, - "failed to request power good irq\n"); + return ret; if (client->irq) { ret = devm_request_threaded_irq(&client->dev, client->irq, @@ -401,8 +400,7 @@ static int tps65185_probe(struct i2c_client *client) IRQF_TRIGGER_LOW | IRQF_ONESHOT, "tps65185", data); if (ret) - return dev_err_probe(&client->dev, ret, - "failed to request irq\n"); + return ret; } ret = regmap_update_bits(data->regmap, TPS65185_REG_INT_EN2, BIT(0), BIT(0)); diff --git a/include/linux/mfd/88pm886.h b/include/linux/mfd/88pm886.h index 2c24dd3032ab..9e96d2cb92f5 100644 --- a/include/linux/mfd/88pm886.h +++ b/include/linux/mfd/88pm886.h @@ -2,6 +2,7 @@ #ifndef __MFD_88PM886_H #define __MFD_88PM886_H +#include <linux/bits.h> #include <linux/i2c.h> #include <linux/regmap.h> @@ -130,6 +131,12 @@ #define PM886_GPADC_INDEX_TO_BIAS_uA(i) (1 + (i) * 5) /* Battery block register definitions */ +#define PM886_REG_BATTERY_CONFIG1 0x28 +#define PM886_REG_VBUS_EN BIT(7) + +#define PM886_REG_BOOST_CONFIG1 0x6b +#define PM886_REG_BOOST_MASK GENMASK(2, 0) + #define PM886_REG_CLS_CONFIG1 0x71 struct pm886_chip { diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index cc6ce709ec86..55cc519103ed 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -362,7 +362,7 @@ enum regulator_type { * @off_on_delay: guard time (in uS), before re-enabling a regulator * * @poll_enabled_time: The polling interval (in uS) to use while checking that - * the regulator was actually enabled. Max upto enable_time. + * the regulator was actually enabled. Max up to enable_time. * * @of_map_mode: Maps a hardware mode defined in a DeviceTree to a standard mode */ diff --git a/include/linux/regulator/pca9450.h b/include/linux/regulator/pca9450.h index 0df8b3c48082..bf94df5fafe3 100644 --- a/include/linux/regulator/pca9450.h +++ b/include/linux/regulator/pca9450.h @@ -210,9 +210,11 @@ enum { #define LDO5L_EN_MASK 0xC0 #define LDO5LOUT_MASK 0x0F -#define LDO5H_EN_MASK 0xC0 #define LDO5HOUT_MASK 0x0F +/* LDO ENMODE value: ON in RUN, OFF while PMIC_STBY_REQ is asserted */ +#define LDO_ENMODE_ONREQ_STBYREQ 0x80 + /* PCA9450_REG_IRQ bits */ #define IRQ_PWRON 0x80 #define IRQ_WDOGB 0x40 diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 3a818f07a101..7cbcc3fb9e6d 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -28,7 +28,15 @@ static struct lock_class_key irq_desc_lock_class; static int __init irq_affinity_setup(char *str) { alloc_bootmem_cpumask_var(&irq_default_affinity); - cpulist_parse(str, irq_default_affinity); + if (cpulist_parse(str, irq_default_affinity) < 0) { + /* + * Clear the mask so that init_irq_default_affinity() + * defaults it later. + */ + cpumask_clear(irq_default_affinity); + pr_warn("irqaffinity: incorrect CPU range, using default\n"); + return 1; + } /* * Set at least the boot cpu. We don't want to end up with * bugreports caused by random commandline masks diff --git a/kernel/softirq.c b/kernel/softirq.c index 5d02c36c40e3..c3729c5b284b 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -645,8 +645,8 @@ restart: h->action(); trace_softirq_exit(vec_nr); if (unlikely(prev_count != preempt_count())) { - pr_err("huh, entered softirq %u %s %p with preempt_count %08x, exited with %08x?\n", - vec_nr, softirq_to_name[vec_nr], h->action, + pr_err("huh, entered softirq %u %s with preempt_count %08x, exited with %08x?\n", + vec_nr, softirq_to_name[vec_nr], prev_count, preempt_count()); preempt_count_set(prev_count); } |
