diff options
65 files changed, 1998 insertions, 288 deletions
diff --git a/Documentation/devicetree/bindings/mfd/max77650.yaml b/Documentation/devicetree/bindings/mfd/max77650.yaml index b0a0f0d3d9d4..4181174fcf58 100644 --- a/Documentation/devicetree/bindings/mfd/max77650.yaml +++ b/Documentation/devicetree/bindings/mfd/max77650.yaml @@ -100,14 +100,12 @@ examples: compatible = "maxim,max77650-regulator"; max77650_ldo: regulator-ldo { - regulator-compatible = "ldo"; regulator-name = "max77650-ldo"; regulator-min-microvolt = <1350000>; regulator-max-microvolt = <2937500>; }; max77650_sbb0: regulator-sbb0 { - regulator-compatible = "sbb0"; regulator-name = "max77650-sbb0"; regulator-min-microvolt = <800000>; regulator-max-microvolt = <1587500>; diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6360.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6360.yaml index 28eee02441ee..fb65abf30d57 100644 --- a/Documentation/devicetree/bindings/mfd/mediatek,mt6360.yaml +++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6360.yaml @@ -83,7 +83,6 @@ examples: richtek,vinovp-microvolt = <14500000>; otg_vbus_regulator: usb-otg-vbus-regulator { - regulator-compatible = "usb-otg-vbus"; regulator-name = "usb-otg-vbus"; regulator-min-microvolt = <4425000>; regulator-max-microvolt = <5825000>; @@ -145,7 +144,6 @@ examples: compatible = "mediatek,mt6360-regulator"; LDO_VIN3-supply = <&BUCK2>; buck1 { - regulator-compatible = "BUCK1"; regulator-name = "mt6360,buck1"; regulator-min-microvolt = <300000>; regulator-max-microvolt = <1300000>; @@ -154,7 +152,6 @@ examples: MT6360_OPMODE_ULP>; }; BUCK2: buck2 { - regulator-compatible = "BUCK2"; regulator-name = "mt6360,buck2"; regulator-min-microvolt = <300000>; regulator-max-microvolt = <1300000>; @@ -163,7 +160,6 @@ examples: MT6360_OPMODE_ULP>; }; ldo6 { - regulator-compatible = "LDO6"; regulator-name = "mt6360,ldo6"; regulator-min-microvolt = <500000>; regulator-max-microvolt = <2100000>; @@ -171,7 +167,6 @@ examples: MT6360_OPMODE_LP>; }; ldo7 { - regulator-compatible = "LDO7"; regulator-name = "mt6360,ldo7"; regulator-min-microvolt = <500000>; regulator-max-microvolt = <2100000>; @@ -179,7 +174,6 @@ examples: MT6360_OPMODE_LP>; }; ldo1 { - regulator-compatible = "LDO1"; regulator-name = "mt6360,ldo1"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3600000>; @@ -187,7 +181,6 @@ examples: MT6360_OPMODE_LP>; }; ldo2 { - regulator-compatible = "LDO2"; regulator-name = "mt6360,ldo2"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3600000>; @@ -195,7 +188,6 @@ examples: MT6360_OPMODE_LP>; }; ldo3 { - regulator-compatible = "LDO3"; regulator-name = "mt6360,ldo3"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3600000>; @@ -203,7 +195,6 @@ examples: MT6360_OPMODE_LP>; }; ldo5 { - regulator-compatible = "LDO5"; regulator-name = "mt6360,ldo5"; regulator-min-microvolt = <2700000>; regulator-max-microvolt = <3600000>; diff --git a/Documentation/devicetree/bindings/power/supply/mt6360_charger.yaml b/Documentation/devicetree/bindings/power/supply/mt6360_charger.yaml index b89b15a5bfa4..4c74cc78729e 100644 --- a/Documentation/devicetree/bindings/power/supply/mt6360_charger.yaml +++ b/Documentation/devicetree/bindings/power/supply/mt6360_charger.yaml @@ -26,6 +26,7 @@ properties: type: object description: OTG boost regulator. $ref: /schemas/regulator/regulator.yaml# + unevaluatedProperties: false required: - compatible @@ -39,7 +40,6 @@ examples: richtek,vinovp-microvolt = <14500000>; otg_vbus_regulator: usb-otg-vbus-regulator { - regulator-compatible = "usb-otg-vbus"; regulator-name = "usb-otg-vbus"; regulator-min-microvolt = <4425000>; regulator-max-microvolt = <5825000>; diff --git a/Documentation/devicetree/bindings/regulator/max77650-regulator.yaml b/Documentation/devicetree/bindings/regulator/max77650-regulator.yaml index ce0a4021ae7f..01b9775a92d1 100644 --- a/Documentation/devicetree/bindings/regulator/max77650-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/max77650-regulator.yaml @@ -26,6 +26,7 @@ properties: patternProperties: "^regulator-(ldo|sbb[0-2])$": $ref: "regulator.yaml#" + unevaluatedProperties: false required: - compatible diff --git a/Documentation/devicetree/bindings/regulator/max8660.yaml b/Documentation/devicetree/bindings/regulator/max8660.yaml index 9c038698f880..552176cc2315 100644 --- a/Documentation/devicetree/bindings/regulator/max8660.yaml +++ b/Documentation/devicetree/bindings/regulator/max8660.yaml @@ -26,6 +26,7 @@ properties: patternProperties: "regulator-.+": $ref: "regulator.yaml#" + unevaluatedProperties: false additionalProperties: false @@ -43,31 +44,26 @@ examples: regulators { regulator-V3 { - regulator-compatible= "V3(DCDC)"; regulator-min-microvolt = <725000>; regulator-max-microvolt = <1800000>; }; regulator-V4 { - regulator-compatible= "V4(DCDC)"; regulator-min-microvolt = <725000>; regulator-max-microvolt = <1800000>; }; regulator-V5 { - regulator-compatible= "V5(LDO)"; regulator-min-microvolt = <1700000>; regulator-max-microvolt = <2000000>; }; regulator-V6 { - regulator-compatible= "V6(LDO)"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; }; regulator-V7 { - regulator-compatible= "V7(LDO)"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; }; diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6357-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6357-regulator.yaml new file mode 100644 index 000000000000..6327bb2f6ee0 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6357-regulator.yaml @@ -0,0 +1,294 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/mediatek,mt6357-regulator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT6357 Regulators + +maintainers: + - Chen Zhong <chen.zhong@mediatek.com> + - Fabien Parent <fabien.parent@linaro.org> + - Alexandre Mergnat <amergnat@baylibre.com> + +description: | + The MT6357 PMIC provides 5 BUCK and 29 LDO. + Regulators and nodes are named according to the regulator type: + - buck-<name> + - ldo-<name>. + MT6357 regulators node should be sub node of the MT6397 MFD node. + +patternProperties: + "^buck-v(core|modem|pa|proc|s1)$": + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + description: + Properties for single BUCK regulator. + + required: + - regulator-name + - regulator-min-microvolt + - regulator-max-microvolt + + "^ldo-v(camio18|aud28|aux18|io18|io28|rf12|rf18|cn18|cn28|fe28)$": + type: object + $ref: fixed-regulator.yaml# + unevaluatedProperties: false + description: + Properties for single fixed LDO regulator. + + required: + - regulator-name + - regulator-min-microvolt + - regulator-max-microvolt + + "^ldo-v(efuse|ibr|ldo28|mch|cama|camd|cn33-bt|cn33-wifi)$": + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + description: + Properties for single LDO regulator. + + required: + - regulator-name + - regulator-min-microvolt + - regulator-max-microvolt + + "^ldo-v(xo22|emc|mc|sim1|sim2|sram-others|sram-proc|dram|usb33)$": + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + description: + Properties for single LDO regulator. + + required: + - regulator-name + - regulator-min-microvolt + - regulator-max-microvolt + +additionalProperties: false + +examples: + - | + pmic { + regulators { + mt6357_vproc_reg: buck-vproc { + regulator-name = "vproc"; + regulator-min-microvolt = <518750>; + regulator-max-microvolt = <1312500>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <220>; + regulator-always-on; + }; + mt6357_vcore_reg: buck-vcore { + regulator-name = "vcore"; + regulator-min-microvolt = <518750>; + regulator-max-microvolt = <1312500>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <220>; + regulator-always-on; + }; + mt6357_vmodem_reg: buck-vmodem { + regulator-name = "vmodem"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1193750>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <220>; + }; + mt6357_vs1_reg: buck-vs1 { + regulator-name = "vs1"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <2200000>; + regulator-ramp-delay = <12500>; + regulator-enable-ramp-delay = <220>; + regulator-always-on; + }; + mt6357_vpa_reg: buck-vpa { + regulator-name = "vpa"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3650000>; + regulator-ramp-delay = <50000>; + regulator-enable-ramp-delay = <220>; + }; + mt6357_vfe28_reg: ldo-vfe28 { + compatible = "regulator-fixed"; + regulator-name = "vfe28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vxo22_reg: ldo-vxo22 { + regulator-name = "vxo22"; + regulator-min-microvolt = <2200000>; + regulator-max-microvolt = <2400000>; + regulator-enable-ramp-delay = <110>; + }; + mt6357_vrf18_reg: ldo-vrf18 { + compatible = "regulator-fixed"; + regulator-name = "vrf18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <110>; + }; + mt6357_vrf12_reg: ldo-vrf12 { + compatible = "regulator-fixed"; + regulator-name = "vrf12"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-enable-ramp-delay = <110>; + }; + mt6357_vefuse_reg: ldo-vefuse { + regulator-name = "vefuse"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vcn33_bt_reg: ldo-vcn33-bt { + regulator-name = "vcn33-bt"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3500000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vcn33_wifi_reg: ldo-vcn33-wifi { + regulator-name = "vcn33-wifi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3500000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vcn28_reg: ldo-vcn28 { + compatible = "regulator-fixed"; + regulator-name = "vcn28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vcn18_reg: ldo-vcn18 { + compatible = "regulator-fixed"; + regulator-name = "vcn18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vcama_reg: ldo-vcama { + regulator-name = "vcama"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vcamd_reg: ldo-vcamd { + regulator-name = "vcamd"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vcamio_reg: ldo-vcamio18 { + compatible = "regulator-fixed"; + regulator-name = "vcamio"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vldo28_reg: ldo-vldo28 { + regulator-name = "vldo28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3000000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vsram_others_reg: ldo-vsram-others { + regulator-name = "vsram-others"; + regulator-min-microvolt = <518750>; + regulator-max-microvolt = <1312500>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <110>; + regulator-always-on; + }; + mt6357_vsram_proc_reg: ldo-vsram-proc { + regulator-name = "vsram-proc"; + regulator-min-microvolt = <518750>; + regulator-max-microvolt = <1312500>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <110>; + regulator-always-on; + }; + mt6357_vaux18_reg: ldo-vaux18 { + compatible = "regulator-fixed"; + regulator-name = "vaux18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vaud28_reg: ldo-vaud28 { + compatible = "regulator-fixed"; + regulator-name = "vaud28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vio28_reg: ldo-vio28 { + compatible = "regulator-fixed"; + regulator-name = "vio28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vio18_reg: ldo-vio18 { + compatible = "regulator-fixed"; + regulator-name = "vio18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <264>; + regulator-always-on; + }; + mt6357_vdram_reg: ldo-vdram { + regulator-name = "vdram"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1200000>; + regulator-enable-ramp-delay = <3300>; + }; + mt6357_vmc_reg: ldo-vmc { + regulator-name = "vmc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <44>; + }; + mt6357_vmch_reg: ldo-vmch { + regulator-name = "vmch"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <44>; + }; + mt6357_vemc_reg: ldo-vemc { + regulator-name = "vemc"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <44>; + regulator-always-on; + }; + mt6357_vsim1_reg: ldo-vsim1 { + regulator-name = "vsim1"; + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <3100000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vsim2_reg: ldo-vsim2 { + regulator-name = "vsim2"; + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <3100000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vibr_reg: ldo-vibr { + regulator-name = "vibr"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <44>; + }; + mt6357_vusb33_reg: ldo-vusb33 { + regulator-name = "vusb33"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3100000>; + regulator-enable-ramp-delay = <264>; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/regulator/mt6360-regulator.yaml b/Documentation/devicetree/bindings/regulator/mt6360-regulator.yaml index a462d99a25cc..8a0931dc2f30 100644 --- a/Documentation/devicetree/bindings/regulator/mt6360-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/mt6360-regulator.yaml @@ -27,9 +27,11 @@ properties: patternProperties: "^buck[12]$": $ref: "regulator.yaml#" + unevaluatedProperties: false "^ldo[123567]$": $ref: "regulator.yaml#" + unevaluatedProperties: false required: - compatible @@ -44,7 +46,6 @@ examples: compatible = "mediatek,mt6360-regulator"; LDO_VIN3-supply = <&BUCK2>; buck1 { - regulator-compatible = "BUCK1"; regulator-name = "mt6360,buck1"; regulator-min-microvolt = <300000>; regulator-max-microvolt = <1300000>; @@ -53,7 +54,6 @@ examples: MT6360_OPMODE_ULP>; }; BUCK2: buck2 { - regulator-compatible = "BUCK2"; regulator-name = "mt6360,buck2"; regulator-min-microvolt = <300000>; regulator-max-microvolt = <1300000>; @@ -62,7 +62,6 @@ examples: MT6360_OPMODE_ULP>; }; ldo6 { - regulator-compatible = "LDO6"; regulator-name = "mt6360,ldo6"; regulator-min-microvolt = <500000>; regulator-max-microvolt = <2100000>; @@ -70,7 +69,6 @@ examples: MT6360_OPMODE_LP>; }; ldo7 { - regulator-compatible = "LDO7"; regulator-name = "mt6360,ldo7"; regulator-min-microvolt = <500000>; regulator-max-microvolt = <2100000>; @@ -78,15 +76,13 @@ examples: MT6360_OPMODE_LP>; }; ldo1 { - regulator-compatible = "LDO1"; regulator-name = "mt6360,ldo1"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3600000>; regulator-allowed-modes = <MT6360_OPMODE_NORMAL MT6360_OPMODE_LP>; }; - ldo2 { - regulator-compatible = "LDO2"; + ldo2 { regulator-name = "mt6360,ldo2"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3600000>; @@ -94,7 +90,6 @@ examples: MT6360_OPMODE_LP>; }; ldo3 { - regulator-compatible = "LDO3"; regulator-name = "mt6360,ldo3"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3600000>; @@ -102,7 +97,6 @@ examples: MT6360_OPMODE_LP>; }; ldo5 { - regulator-compatible = "LDO5"; regulator-name = "mt6360,ldo5"; regulator-min-microvolt = <2700000>; regulator-max-microvolt = <3600000>; diff --git a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml index 90c3bda31c23..297a75069f60 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml @@ -47,6 +47,7 @@ description: | For PM8350, smps1 - smps12, ldo1 - ldo10 For PM8350C, smps1 - smps10, ldo1 - ldo13, bob For PM8450, smps1 - smps6, ldo1 - ldo4 + For PM8550, smps1 - smps6, ldo1 - ldo17, bob1 - bob2 For PM8998, smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2 For PMI8998, bob For PMR735A, smps1 - smps3, ldo1 - ldo7 @@ -70,6 +71,9 @@ properties: - qcom,pm8350-rpmh-regulators - qcom,pm8350c-rpmh-regulators - qcom,pm8450-rpmh-regulators + - qcom,pm8550-rpmh-regulators + - qcom,pm8550ve-rpmh-regulators + - qcom,pm8550vs-rpmh-regulators - qcom,pm8998-rpmh-regulators - qcom,pmg1110-rpmh-regulators - qcom,pmi8998-rpmh-regulators @@ -83,7 +87,7 @@ properties: RPMh resource name suffix used for the regulators found on this PMIC. $ref: /schemas/types.yaml#/definitions/string - enum: [a, b, c, d, e, f, h, k] + enum: [a, b, c, d, e, f, g, h, k] qcom,always-wait-for-ack: description: | @@ -107,7 +111,7 @@ properties: regulator-allow-set-load: ["regulator-allowed-modes"] patternProperties: - "^(smps|ldo|lvs)[0-9]+$": + "^(smps|ldo|lvs|bob)[0-9]+$": type: object $ref: "regulator.yaml#" description: smps/ldo regulator nodes(s). @@ -303,6 +307,24 @@ allOf: properties: compatible: enum: + - qcom,pm8550-rpmh-regulators + - qcom,pm8550ve-rpmh-regulators + - qcom,pm8550vs-rpmh-regulators + then: + properties: + vdd-l2-l13-l14-supply: true + vdd-l5-l16-supply: true + vdd-l6-l7-supply: true + vdd-l8-l9-supply: true + patternProperties: + "^vdd-l([1-4]|1[0-7])-supply$": true + "^vdd-s[1-6]-supply$": true + "^vdd-bob[1-2]-supply$": true + + - if: + properties: + compatible: + enum: - qcom,pm8998-rpmh-regulators then: properties: @@ -412,9 +434,8 @@ examples: regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>; - regulator-allowed-modes = - <RPMH_REGULATOR_MODE_LPM - RPMH_REGULATOR_MODE_HPM>; + regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM + RPMH_REGULATOR_MODE_HPM>; regulator-allow-set-load; }; @@ -431,9 +452,8 @@ examples: bob { regulator-min-microvolt = <3312000>; regulator-max-microvolt = <3600000>; - regulator-allowed-modes = - <RPMH_REGULATOR_MODE_AUTO - RPMH_REGULATOR_MODE_HPM>; + regulator-allowed-modes = <RPMH_REGULATOR_MODE_AUTO + RPMH_REGULATOR_MODE_HPM>; regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>; }; }; diff --git a/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml index 961eed51912c..8c45f53212b1 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml @@ -71,6 +71,8 @@ description: For pmi8998, bob + For pmr735a, s1, s2, s3, l1, l2, l3, l4, l5, l6, l7 + For pms405, s1, s2, s3, s4, s5, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13 @@ -98,6 +100,7 @@ properties: - qcom,rpm-pma8084-regulators - qcom,rpm-pmi8994-regulators - qcom,rpm-pmi8998-regulators + - qcom,rpm-pmr735a-regulators - qcom,rpm-pms405-regulators patternProperties: diff --git a/Documentation/devicetree/bindings/regulator/regulator-output.yaml b/Documentation/devicetree/bindings/regulator/regulator-output.yaml new file mode 100644 index 000000000000..078b37a1a71a --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/regulator-output.yaml @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- + +$id: http://devicetree.org/schemas/regulator/regulator-output.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Regulator output connector + +maintainers: + - Zev Weiss <zev@bewilderbeest.net> + +description: | + This describes a power output connector supplied by a regulator, + such as a power outlet on a power distribution unit (PDU). The + connector may be standalone or merely one channel or set of pins + within a ganged physical connector carrying multiple independent + power outputs. + +properties: + compatible: + const: regulator-output + + vout-supply: + description: + Phandle of the regulator supplying the output. + +required: + - compatible + - vout-supply + +additionalProperties: false + +examples: + - | + output { + compatible = "regulator-output"; + vout-supply = <&output_reg>; + }; diff --git a/Documentation/devicetree/bindings/regulator/richtek,rt6190.yaml b/Documentation/devicetree/bindings/regulator/richtek,rt6190.yaml new file mode 100644 index 000000000000..29f7d3d5d658 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/richtek,rt6190.yaml @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/richtek,rt6190.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Richtek RT6190 4-Switch BuckBoost controller + +maintainers: + - ChiYuan Huang <cy_huang@richtek.com> + +description: | + The RT6190 is 4-Switch BuckBoost controller designed for converting input + voltage to output voltage that can be equal to, higher or lower than input + voltage. It operates with wide input voltage range from 4.5V to 36V, and + the output voltage can be set from 3V to 36V by external FB pin. It's commonly + used for the application like as BuckBoost bus supply, docking station and USB + power delivery product. + + Datasheet is available at + https://www.richtek.com/assets/product_file/RT6190/DS6190-02.pdf + +allOf: + - $ref: regulator.yaml# + +properties: + compatible: + enum: + - richtek,rt6190 + + reg: + maxItems: 1 + + enable-gpios: + maxItems: 1 + + wakeup-source: true + + interrupts: + maxItems: 1 + + regulator-allowed-modes: + description: | + buck allowed operating mode + 0: PSM mode (light load Power Saving Mode) + 1: FCCM mode (Forced-CCM mode) + maxItems: 2 + items: + enum: [0, 1] + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/irq.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + regulator@2c { + compatible = "richtek,rt6190"; + reg = <0x2c>; + wakeup-source; + interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>; + enable-gpios = <&gpio26 1 GPIO_ACTIVE_HIGH>; + regulator-name = "richtek,rt6190-buckboost"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <32000000>; + regulator-min-microamp = <306000>; + regulator-max-microamp = <12114000>; + regulator-allowed-modes = <0 1>; + }; + }; diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst index cb95adf64f74..8abf9dda3241 100644 --- a/Documentation/driver-api/driver-model/devres.rst +++ b/Documentation/driver-api/driver-model/devres.rst @@ -417,6 +417,7 @@ PWM REGULATOR devm_regulator_bulk_register_supply_alias() devm_regulator_bulk_get() + devm_regulator_bulk_get_const() devm_regulator_bulk_get_enable() devm_regulator_bulk_put() devm_regulator_get() diff --git a/drivers/platform/x86/intel/int3472/clk_and_regulator.c b/drivers/platform/x86/intel/int3472/clk_and_regulator.c index 1cf958983e86..b2342b3d78c7 100644 --- a/drivers/platform/x86/intel/int3472/clk_and_regulator.c +++ b/drivers/platform/x86/intel/int3472/clk_and_regulator.c @@ -185,7 +185,8 @@ int skl_int3472_register_regulator(struct int3472_discrete_device *int3472, cfg.init_data = &init_data; cfg.ena_gpiod = int3472->regulator.gpio; - int3472->regulator.rdev = regulator_register(&int3472->regulator.rdesc, + int3472->regulator.rdev = regulator_register(int3472->dev, + &int3472->regulator.rdesc, &cfg); if (IS_ERR(int3472->regulator.rdev)) { ret = PTR_ERR(int3472->regulator.rdev); diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 070e4403c6c2..820c9a0788e5 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -377,7 +377,7 @@ config REGULATOR_FAN53555 config REGULATOR_FAN53880 tristate "Fairchild FAN53880 Regulator" - depends on I2C && (OF || COMPILE_TEST) + depends on I2C && OF select REGMAP_I2C help This driver supports Fairchild (ON Semiconductor) FAN53880 @@ -743,7 +743,7 @@ config REGULATOR_MP8859 config REGULATOR_MP886X tristate "MPS MP8869 regulator driver" - depends on I2C && (OF || COMPILE_TEST) + depends on I2C && OF select REGMAP_I2C help This driver supports the MP8869 voltage regulator. @@ -805,6 +805,15 @@ config REGULATOR_MT6332 This driver supports the control of different power rails of device through regulator interface +config REGULATOR_MT6357 + tristate "MediaTek MT6357 PMIC" + depends on MFD_MT6397 + help + Say y here to select this option to enable the power regulator of + MediaTek MT6357 PMIC. + This driver supports the control of different power rails of device + through regulator interface. + config REGULATOR_MT6358 tristate "MediaTek MT6358 PMIC" depends on MFD_MT6397 @@ -1124,6 +1133,17 @@ config REGULATOR_RT6160 The wide output range is from 2025mV to 5200mV and can be used on most common application scenario. +config REGULATOR_RT6190 + tristate "Richtek RT6190 4-Switch BuckBoost controller" + depends on I2C + select REGMAP_I2C + help + The RT6190 is a 4-Switch BuckBoost controller designed for converting + input voltage to output voltage that can be equal to, higher or lower + than input voltage. It operates with wide input voltage range from + 4.5V to 36V, and the output voltage can be set from 3V to 36V by + external FB pin. + config REGULATOR_RT6245 tristate "Richtek RT6245 voltage regulator" depends on I2C @@ -1288,21 +1308,21 @@ config REGULATOR_SY7636A config REGULATOR_SY8106A tristate "Silergy SY8106A regulator" - depends on I2C && (OF || COMPILE_TEST) + depends on I2C && OF select REGMAP_I2C help This driver supports SY8106A single output regulator. config REGULATOR_SY8824X tristate "Silergy SY8824C/SY8824E regulator" - depends on I2C && (OF || COMPILE_TEST) + depends on I2C && OF select REGMAP_I2C help This driver supports SY8824C single output regulator. config REGULATOR_SY8827N tristate "Silergy SY8827N regulator" - depends on I2C && (OF || COMPILE_TEST) + depends on I2C && OF select REGMAP_I2C help This driver supports SY8827N single output regulator. diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 5962307e1130..b9f5eb35bf5f 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -97,6 +97,7 @@ obj-$(CONFIG_REGULATOR_MT6315) += mt6315-regulator.o obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o obj-$(CONFIG_REGULATOR_MT6331) += mt6331-regulator.o obj-$(CONFIG_REGULATOR_MT6332) += mt6332-regulator.o +obj-$(CONFIG_REGULATOR_MT6357) += mt6357-regulator.o obj-$(CONFIG_REGULATOR_MT6358) += mt6358-regulator.o obj-$(CONFIG_REGULATOR_MT6359) += mt6359-regulator.o obj-$(CONFIG_REGULATOR_MT6360) += mt6360-regulator.o @@ -134,6 +135,7 @@ obj-$(CONFIG_REGULATOR_RT5120) += rt5120-regulator.o obj-$(CONFIG_REGULATOR_RT5190A) += rt5190a-regulator.o obj-$(CONFIG_REGULATOR_RT5759) += rt5759-regulator.o obj-$(CONFIG_REGULATOR_RT6160) += rt6160-regulator.o +obj-$(CONFIG_REGULATOR_RT6190) += rt6190-regulator.o obj-$(CONFIG_REGULATOR_RT6245) += rt6245-regulator.o obj-$(CONFIG_REGULATOR_RTMV20) += rtmv20-regulator.o obj-$(CONFIG_REGULATOR_RTQ2134) += rtq2134-regulator.o diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index 19b9742c9ecc..53f2c75cdeb4 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -651,9 +651,9 @@ static int act8600_charger_probe(struct device *dev, struct regmap *regmap) return PTR_ERR_OR_ZERO(charger); } -static int act8865_pmic_probe(struct i2c_client *client, - const struct i2c_device_id *i2c_id) +static int act8865_pmic_probe(struct i2c_client *client) { + const struct i2c_device_id *i2c_id = i2c_client_get_device_id(client); const struct regulator_desc *regulators; struct act8865_platform_data *pdata = NULL; struct device *dev = &client->dev; @@ -790,7 +790,7 @@ static struct i2c_driver act8865_pmic_driver = { .driver = { .name = "act8865", }, - .probe = act8865_pmic_probe, + .probe_new = act8865_pmic_probe, .id_table = act8865_ids, }; diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index 75f432f61e91..2ba8ac1773d1 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c @@ -212,9 +212,9 @@ static const struct i2c_device_id ad5398_id[] = { }; MODULE_DEVICE_TABLE(i2c, ad5398_id); -static int ad5398_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ad5398_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct regulator_init_data *init_data = dev_get_platdata(&client->dev); struct regulator_config config = { }; struct ad5398_chip_info *chip; @@ -254,7 +254,7 @@ static int ad5398_probe(struct i2c_client *client, } static struct i2c_driver ad5398_driver = { - .probe = ad5398_probe, + .probe_new = ad5398_probe, .driver = { .name = "ad5398", }, diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index f6cfd3f6f0dd..596ecd8041cd 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -34,7 +34,7 @@ struct arizona_micsupp { struct regulator_dev *regulator; struct regmap *regmap; struct snd_soc_dapm_context **dapm; - unsigned int enable_reg; + const struct regulator_desc *desc; struct device *dev; struct regulator_consumer_supply supply; @@ -49,10 +49,11 @@ static void arizona_micsupp_check_cp(struct work_struct *work) container_of(work, struct arizona_micsupp, check_cp_work); struct snd_soc_dapm_context *dapm = *micsupp->dapm; struct snd_soc_component *component; + const struct regulator_desc *desc = micsupp->desc; unsigned int val; int ret; - ret = regmap_read(micsupp->regmap, micsupp->enable_reg, &val); + ret = regmap_read(micsupp->regmap, desc->enable_reg, &val); if (ret != 0) { dev_err(micsupp->dev, "Failed to read CP state: %d\n", ret); @@ -62,8 +63,8 @@ static void arizona_micsupp_check_cp(struct work_struct *work) if (dapm) { component = snd_soc_dapm_to_component(dapm); - if ((val & (ARIZONA_CPMIC_ENA | ARIZONA_CPMIC_BYPASS)) == - ARIZONA_CPMIC_ENA) + if ((val & (desc->enable_mask | desc->bypass_mask)) == + desc->enable_mask) snd_soc_component_force_enable_pin(component, "MICSUPP"); else @@ -209,7 +210,6 @@ static const struct regulator_desc madera_micsupp = { .type = REGULATOR_VOLTAGE, .n_voltages = 40, .ops = &arizona_micsupp_ops, - .vsel_reg = MADERA_LDO2_CONTROL_1, .vsel_mask = MADERA_LDO2_VSEL_MASK, .enable_reg = MADERA_MIC_CHARGE_PUMP_1, @@ -262,9 +262,8 @@ static int arizona_micsupp_common_init(struct platform_device *pdev, INIT_WORK(&micsupp->check_cp_work, arizona_micsupp_check_cp); micsupp->init_data.consumer_supplies = &micsupp->supply; - micsupp->supply.supply = "MICVDD"; micsupp->supply.dev_name = dev_name(micsupp->dev); - micsupp->enable_reg = desc->enable_reg; + micsupp->desc = desc; config.dev = micsupp->dev; config.driver_data = micsupp; @@ -285,8 +284,7 @@ static int arizona_micsupp_common_init(struct platform_device *pdev, config.init_data = &micsupp->init_data; /* Default to regulated mode */ - regmap_update_bits(micsupp->regmap, micsupp->enable_reg, - ARIZONA_CPMIC_BYPASS, 0); + regmap_update_bits(micsupp->regmap, desc->enable_reg, desc->bypass_mask, 0); micsupp->regulator = devm_regulator_register(&pdev->dev, desc, @@ -320,6 +318,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev) micsupp->dapm = &arizona->dapm; micsupp->dev = arizona->dev; + micsupp->supply.supply = "MICVDD"; + /* * Since the chip usually supplies itself we provide some * default init_data for it. This will be overridden with @@ -355,6 +355,8 @@ static int madera_micsupp_probe(struct platform_device *pdev) micsupp->dev = madera->dev; micsupp->init_data = arizona_micsupp_ext_default; + micsupp->supply.supply = "MICVDD"; + return arizona_micsupp_common_init(pdev, micsupp, &madera_micsupp, &madera->pdata.micvdd); } diff --git a/drivers/regulator/bd71815-regulator.c b/drivers/regulator/bd71815-regulator.c index c2b8b8be7824..8b55046eded8 100644 --- a/drivers/regulator/bd71815-regulator.c +++ b/drivers/regulator/bd71815-regulator.c @@ -602,12 +602,10 @@ static int bd7181x_probe(struct platform_device *pdev) config.ena_gpiod = NULL; rdev = devm_regulator_register(&pdev->dev, desc, &config); - if (IS_ERR(rdev)) { - dev_err(&pdev->dev, - "failed to register %s regulator\n", - desc->name); - return PTR_ERR(rdev); - } + if (IS_ERR(rdev)) + return dev_err_probe(&pdev->dev, PTR_ERR(rdev), + "failed to register %s regulator\n", + desc->name); } return 0; } diff --git a/drivers/regulator/bd71828-regulator.c b/drivers/regulator/bd71828-regulator.c index a4f09a5a30ca..ad728f4f2241 100644 --- a/drivers/regulator/bd71828-regulator.c +++ b/drivers/regulator/bd71828-regulator.c @@ -750,23 +750,20 @@ static int bd71828_probe(struct platform_device *pdev) rd = &bd71828_rdata[i]; rdev = devm_regulator_register(&pdev->dev, &rd->desc, &config); - if (IS_ERR(rdev)) { - dev_err(&pdev->dev, - "failed to register %s regulator\n", - rd->desc.name); - return PTR_ERR(rdev); - } + if (IS_ERR(rdev)) + return dev_err_probe(&pdev->dev, PTR_ERR(rdev), + "failed to register %s regulator\n", + rd->desc.name); + for (j = 0; j < rd->reg_init_amnt; j++) { ret = regmap_update_bits(config.regmap, rd->reg_inits[j].reg, rd->reg_inits[j].mask, rd->reg_inits[j].val); - if (ret) { - dev_err(&pdev->dev, - "regulator %s init failed\n", - rd->desc.name); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, + "regulator %s init failed\n", + rd->desc.name); } } return 0; diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c index 00efb18a836c..894fab0d53d0 100644 --- a/drivers/regulator/bd718x7-regulator.c +++ b/drivers/regulator/bd718x7-regulator.c @@ -1576,8 +1576,6 @@ static int setup_feedback_loop(struct device *dev, struct device_node *np, if (!of_node_name_eq(np, desc->of_match)) continue; - pr_info("Looking at node '%s'\n", desc->of_match); - /* The feedback loop connection does not make sense for LDOs */ if (desc->id >= BD718XX_LDO1) return -EINVAL; @@ -1708,20 +1706,17 @@ static int bd718xx_probe(struct platform_device *pdev) break; default: dev_err(&pdev->dev, "Unsupported chip type\n"); - err = -EINVAL; - goto err; + return -EINVAL; } /* Register LOCK release */ err = regmap_update_bits(regmap, BD718XX_REG_REGLOCK, (REGLOCK_PWRSEQ | REGLOCK_VREG), 0); - if (err) { - dev_err(&pdev->dev, "Failed to unlock PMIC (%d)\n", err); - goto err; - } else { - dev_dbg(&pdev->dev, "Unlocked lock register 0x%x\n", - BD718XX_REG_REGLOCK); - } + if (err) + return dev_err_probe(&pdev->dev, err, "Failed to unlock PMIC\n"); + + dev_dbg(&pdev->dev, "Unlocked lock register 0x%x\n", + BD718XX_REG_REGLOCK); use_snvs = of_property_read_bool(pdev->dev.parent->of_node, "rohm,reset-snvs-powered"); @@ -1738,13 +1733,11 @@ static int bd718xx_probe(struct platform_device *pdev) BD718XX_WDOG_POWEROFF_MASK | BD718XX_KEY_L_POWEROFF_MASK, BD718XX_POWOFF_TO_RDY); - if (err) { - dev_err(&pdev->dev, "Failed to change reset target\n"); - goto err; - } else { - dev_dbg(&pdev->dev, - "Changed all resets from SVNS to READY\n"); - } + if (err) + return dev_err_probe(&pdev->dev, err, + "Failed to change reset target\n"); + + dev_dbg(&pdev->dev, "Changed all resets from SVNS to READY\n"); } config.dev = pdev->dev.parent; @@ -1780,13 +1773,10 @@ static int bd718xx_probe(struct platform_device *pdev) desc->ops = swops[i]; rdev = devm_regulator_register(&pdev->dev, desc, &config); - if (IS_ERR(rdev)) { - dev_err(&pdev->dev, - "failed to register %s regulator\n", - desc->name); - err = PTR_ERR(rdev); - goto err; - } + if (IS_ERR(rdev)) + return dev_err_probe(&pdev->dev, PTR_ERR(rdev), + "failed to register %s regulator\n", + desc->name); /* * Regulator register gets the regulator constraints and @@ -1809,28 +1799,23 @@ static int bd718xx_probe(struct platform_device *pdev) !rdev->constraints->boot_on)) { err = regmap_update_bits(regmap, r->init.reg, r->init.mask, r->init.val); - if (err) { - dev_err(&pdev->dev, + if (err) + return dev_err_probe(&pdev->dev, err, "Failed to take control for (%s)\n", desc->name); - goto err; - } } for (j = 0; j < r->additional_init_amnt; j++) { err = regmap_update_bits(regmap, r->additional_inits[j].reg, r->additional_inits[j].mask, r->additional_inits[j].val); - if (err) { - dev_err(&pdev->dev, + if (err) + return dev_err_probe(&pdev->dev, err, "Buck (%s) initialization failed\n", desc->name); - goto err; - } } } -err: return err; } diff --git a/drivers/regulator/bd9576-regulator.c b/drivers/regulator/bd9576-regulator.c index 393c8693b327..02c70768652b 100644 --- a/drivers/regulator/bd9576-regulator.c +++ b/drivers/regulator/bd9576-regulator.c @@ -953,30 +953,28 @@ static int bd957x_probe(struct platform_device *pdev) dev_fwnode(pdev->dev.parent), "rohm,vout1-en", GPIOD_OUT_LOW, "vout1-en"); - if (!IS_ERR(en)) { - /* VOUT1_OPS gpio ctrl */ - /* - * Regulator core prioritizes the ena_gpio over - * enable/disable/is_enabled callbacks so no need to - * clear them. We can still use same ops - */ + + /* VOUT1_OPS gpio ctrl */ + /* + * Regulator core prioritizes the ena_gpio over + * enable/disable/is_enabled callbacks so no need to clear them + * even if GPIO is used. So, we can still use same ops. + * + * In theory it is possible someone wants to set vout1-en LOW + * during OTP loading and set VOUT1 to be controlled by GPIO - + * but control the GPIO from some where else than this driver. + * For that to work we should unset the is_enabled callback + * here. + * + * I believe such case where rohm,vout1-en-low is set and + * vout1-en-gpios is not is likely to be a misconfiguration. + * So let's just err out for now. + */ + if (!IS_ERR(en)) config.ena_gpiod = en; - } else { - /* - * In theory it is possible someone wants to set - * vout1-en LOW during OTP loading and set VOUT1 to be - * controlled by GPIO - but control the GPIO from some - * where else than this driver. For that to work we - * should unset the is_enabled callback here. - * - * I believe such case where rohm,vout1-en-low is set - * and vout1-en-gpios is not is likely to be a - * misconfiguration. So let's just err out for now. - */ - dev_err(&pdev->dev, - "Failed to get VOUT1 control GPIO\n"); - return PTR_ERR(en); - } + else + return dev_err_probe(&pdev->dev, PTR_ERR(en), + "Failed to get VOUT1 control GPIO\n"); } /* @@ -1037,12 +1035,10 @@ static int bd957x_probe(struct platform_device *pdev) r->rdev = devm_regulator_register(&pdev->dev, desc, &config); - if (IS_ERR(r->rdev)) { - dev_err(&pdev->dev, - "failed to register %s regulator\n", - desc->name); - return PTR_ERR(r->rdev); - } + if (IS_ERR(r->rdev)) + return dev_err_probe(&pdev->dev, PTR_ERR(r->rdev), + "failed to register %s regulator\n", + desc->name); /* * Clear the VOUT1 GPIO setting - rest of the regulators do not * support GPIO control diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e8c00a884f1f..ace4ecc6d7c2 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1596,7 +1596,13 @@ static int set_machine_constraints(struct regulator_dev *rdev) if (rdev->supply_name && !rdev->supply) return -EPROBE_DEFER; - if (rdev->supply) { + /* If supplying regulator has already been enabled, + * it's not intended to have use_count increment + * when rdev is only boot-on. + */ + if (rdev->supply && + (rdev->constraints->always_on || + !regulator_is_enabled(rdev->supply))) { ret = regulator_enable(rdev->supply); if (ret < 0) { _regulator_put(rdev->supply); @@ -1640,6 +1646,7 @@ static int set_supply(struct regulator_dev *rdev, rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); if (rdev->supply == NULL) { + module_put(supply_rdev->owner); err = -ENOMEM; return err; } @@ -1813,7 +1820,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); if (regulator == NULL) { - kfree(supply_name); + kfree_const(supply_name); return NULL; } @@ -1943,6 +1950,7 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev, node = of_get_regulator(dev, supply); if (node) { r = of_find_regulator_by_node(node); + of_node_put(node); if (r) return r; @@ -4778,22 +4786,8 @@ static int _notifier_call_chain(struct regulator_dev *rdev, return blocking_notifier_call_chain(&rdev->notifier, event, data); } -/** - * regulator_bulk_get - get multiple regulator consumers - * - * @dev: Device to supply - * @num_consumers: Number of consumers to register - * @consumers: Configuration of consumers; clients are stored here. - * - * @return 0 on success, an errno on failure. - * - * This helper function allows drivers to get several regulator - * consumers in one operation. If any of the regulators cannot be - * acquired then any regulators that were allocated will be freed - * before returning to the caller. - */ -int regulator_bulk_get(struct device *dev, int num_consumers, - struct regulator_bulk_data *consumers) +int _regulator_bulk_get(struct device *dev, int num_consumers, + struct regulator_bulk_data *consumers, enum regulator_get_type get_type) { int i; int ret; @@ -4802,8 +4796,8 @@ int regulator_bulk_get(struct device *dev, int num_consumers, consumers[i].consumer = NULL; for (i = 0; i < num_consumers; i++) { - consumers[i].consumer = regulator_get(dev, - consumers[i].supply); + consumers[i].consumer = _regulator_get(dev, + consumers[i].supply, get_type); if (IS_ERR(consumers[i].consumer)) { ret = dev_err_probe(dev, PTR_ERR(consumers[i].consumer), "Failed to get supply '%s'", @@ -4830,6 +4824,26 @@ err: return ret; } + +/** + * regulator_bulk_get - get multiple regulator consumers + * + * @dev: Device to supply + * @num_consumers: Number of consumers to register + * @consumers: Configuration of consumers; clients are stored here. + * + * @return 0 on success, an errno on failure. + * + * This helper function allows drivers to get several regulator + * consumers in one operation. If any of the regulators cannot be + * acquired then any regulators that were allocated will be freed + * before returning to the caller. + */ +int regulator_bulk_get(struct device *dev, int num_consumers, + struct regulator_bulk_data *consumers) +{ + return _regulator_bulk_get(dev, num_consumers, consumers, NORMAL_GET); +} EXPORT_SYMBOL_GPL(regulator_bulk_get); static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) @@ -5396,6 +5410,7 @@ static struct regulator_coupler generic_regulator_coupler = { /** * regulator_register - register regulator + * @dev: the device that drive the regulator * @regulator_desc: regulator to register * @cfg: runtime configuration for regulator * @@ -5404,7 +5419,8 @@ static struct regulator_coupler generic_regulator_coupler = { * or an ERR_PTR() on error. */ struct regulator_dev * -regulator_register(const struct regulator_desc *regulator_desc, +regulator_register(struct device *dev, + const struct regulator_desc *regulator_desc, const struct regulator_config *cfg) { const struct regulator_init_data *init_data; @@ -5413,7 +5429,6 @@ regulator_register(const struct regulator_desc *regulator_desc, struct regulator_dev *rdev; bool dangling_cfg_gpiod = false; bool dangling_of_gpiod = false; - struct device *dev; int ret, i; bool resolved_early = false; @@ -5426,8 +5441,7 @@ regulator_register(const struct regulator_desc *regulator_desc, goto rinse; } - dev = cfg->dev; - WARN_ON(!dev); + WARN_ON(!dev || !cfg->dev); if (regulator_desc->name == NULL || regulator_desc->ops == NULL) { ret = -EINVAL; @@ -5641,6 +5655,7 @@ unset_supplies: regulator_remove_coupling(rdev); mutex_unlock(®ulator_list_mutex); wash: + regulator_put(rdev->supply); kfree(rdev->coupling_desc.coupled_rdevs); mutex_lock(®ulator_list_mutex); regulator_ena_gpio_free(rdev); diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c index e4c753b83088..d016e049d264 100644 --- a/drivers/regulator/da9121-regulator.c +++ b/drivers/regulator/da9121-regulator.c @@ -1128,8 +1128,7 @@ static inline int da9121_of_get_id(struct device *dev) return (uintptr_t)id->data; } -static int da9121_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int da9121_i2c_probe(struct i2c_client *i2c) { struct da9121 *chip; const int mask_all[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; @@ -1197,7 +1196,7 @@ static struct i2c_driver da9121_regulator_driver = { .name = "da9121", .of_match_table = of_match_ptr(da9121_dt_ids), }, - .probe = da9121_i2c_probe, + .probe_new = da9121_i2c_probe, .remove = da9121_i2c_remove, .id_table = da9121_i2c_id, }; diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c index 3265e75e97ab..90bb0d178885 100644 --- a/drivers/regulator/devres.c +++ b/drivers/regulator/devres.c @@ -186,23 +186,9 @@ static void devm_regulator_bulk_release(struct device *dev, void *res) regulator_bulk_free(devres->num_consumers, devres->consumers); } -/** - * devm_regulator_bulk_get - managed get multiple regulator consumers - * - * @dev: device to supply - * @num_consumers: number of consumers to register - * @consumers: configuration of consumers; clients are stored here. - * - * @return 0 on success, an errno on failure. - * - * This helper function allows drivers to get several regulator - * consumers in one operation with management, the regulators will - * automatically be freed when the device is unbound. If any of the - * regulators cannot be acquired then any regulators that were - * allocated will be freed before returning to the caller. - */ -int devm_regulator_bulk_get(struct device *dev, int num_consumers, - struct regulator_bulk_data *consumers) +static int _devm_regulator_bulk_get(struct device *dev, int num_consumers, + struct regulator_bulk_data *consumers, + enum regulator_get_type get_type) { struct regulator_bulk_devres *devres; int ret; @@ -212,7 +198,7 @@ int devm_regulator_bulk_get(struct device *dev, int num_consumers, if (!devres) return -ENOMEM; - ret = regulator_bulk_get(dev, num_consumers, consumers); + ret = _regulator_bulk_get(dev, num_consumers, consumers, get_type); if (!ret) { devres->consumers = consumers; devres->num_consumers = num_consumers; @@ -223,9 +209,53 @@ int devm_regulator_bulk_get(struct device *dev, int num_consumers, return ret; } + +/** + * devm_regulator_bulk_get - managed get multiple regulator consumers + * + * @dev: device to supply + * @num_consumers: number of consumers to register + * @consumers: configuration of consumers; clients are stored here. + * + * @return 0 on success, an errno on failure. + * + * This helper function allows drivers to get several regulator + * consumers in one operation with management, the regulators will + * automatically be freed when the device is unbound. If any of the + * regulators cannot be acquired then any regulators that were + * allocated will be freed before returning to the caller. + */ +int devm_regulator_bulk_get(struct device *dev, int num_consumers, + struct regulator_bulk_data *consumers) +{ + return _devm_regulator_bulk_get(dev, num_consumers, consumers, NORMAL_GET); +} EXPORT_SYMBOL_GPL(devm_regulator_bulk_get); /** + * devm_regulator_bulk_get_exclusive - managed exclusive get of multiple + * regulator consumers + * + * @dev: device to supply + * @num_consumers: number of consumers to register + * @consumers: configuration of consumers; clients are stored here. + * + * @return 0 on success, an errno on failure. + * + * This helper function allows drivers to exclusively get several + * regulator consumers in one operation with management, the regulators + * will automatically be freed when the device is unbound. If any of + * the regulators cannot be acquired then any regulators that were + * allocated will be freed before returning to the caller. + */ +int devm_regulator_bulk_get_exclusive(struct device *dev, int num_consumers, + struct regulator_bulk_data *consumers) +{ + return _devm_regulator_bulk_get(dev, num_consumers, consumers, EXCLUSIVE_GET); +} +EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_exclusive); + +/** * devm_regulator_bulk_get_const - devm_regulator_bulk_get() w/ const data * * @dev: device to supply @@ -385,7 +415,7 @@ struct regulator_dev *devm_regulator_register(struct device *dev, if (!ptr) return ERR_PTR(-ENOMEM); - rdev = regulator_register(regulator_desc, config); + rdev = regulator_register(dev, regulator_desc, config); if (!IS_ERR(rdev)) { *ptr = rdev; devres_add(dev, ptr); diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index dac1fb584fa3..529963a7e4f5 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -549,9 +549,9 @@ static const struct of_device_id __maybe_unused fan53555_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, fan53555_dt_ids); -static int fan53555_regulator_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int fan53555_regulator_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct device_node *np = client->dev.of_node; struct fan53555_device_info *di; struct fan53555_platform_data *pdata; @@ -665,7 +665,7 @@ static struct i2c_driver fan53555_regulator_driver = { .name = "fan53555-regulator", .of_match_table = of_match_ptr(fan53555_dt_ids), }, - .probe = fan53555_regulator_probe, + .probe_new = fan53555_regulator_probe, .id_table = fan53555_id, }; diff --git a/drivers/regulator/fan53880.c b/drivers/regulator/fan53880.c index 8f25930d2769..1d88d5381544 100644 --- a/drivers/regulator/fan53880.c +++ b/drivers/regulator/fan53880.c @@ -42,8 +42,8 @@ static const struct regulator_ops fan53880_ops = { #define FAN53880_LDO(_num, _supply, _default) \ [FAN53880_LDO ## _num] = { \ .name = "LDO"#_num, \ - .of_match = of_match_ptr("LDO"#_num), \ - .regulators_node = of_match_ptr("regulators"), \ + .of_match = "LDO"#_num, \ + .regulators_node = "regulators", \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ .linear_ranges = (struct linear_range[]) { \ @@ -68,8 +68,8 @@ static const struct regulator_desc fan53880_regulators[] = { FAN53880_LDO(4, "VIN4", 1800000), [FAN53880_BUCK] = { .name = "BUCK", - .of_match = of_match_ptr("BUCK"), - .regulators_node = of_match_ptr("regulators"), + .of_match = "BUCK", + .regulators_node = "regulators", .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .linear_ranges = (struct linear_range[]) { @@ -88,8 +88,8 @@ static const struct regulator_desc fan53880_regulators[] = { }, [FAN53880_BOOST] = { .name = "BOOST", - .of_match = of_match_ptr("BOOST"), - .regulators_node = of_match_ptr("regulators"), + .of_match = "BOOST", + .regulators_node = "regulators", .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .linear_ranges = (struct linear_range[]) { @@ -157,13 +157,11 @@ static int fan53880_i2c_probe(struct i2c_client *i2c) return 0; } -#ifdef CONFIG_OF static const struct of_device_id fan53880_dt_ids[] = { { .compatible = "onnn,fan53880", }, {} }; MODULE_DEVICE_TABLE(of, fan53880_dt_ids); -#endif static const struct i2c_device_id fan53880_i2c_id[] = { { "fan53880", }, @@ -174,7 +172,7 @@ MODULE_DEVICE_TABLE(i2c, fan53880_i2c_id); static struct i2c_driver fan53880_regulator_driver = { .driver = { .name = "fan53880", - .of_match_table = of_match_ptr(fan53880_dt_ids), + .of_match_table = fan53880_dt_ids, }, .probe_new = fan53880_i2c_probe, .id_table = fan53880_i2c_id, diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h index 1e9c71642143..fb4433068d29 100644 --- a/drivers/regulator/internal.h +++ b/drivers/regulator/internal.h @@ -122,4 +122,6 @@ enum regulator_get_type { struct regulator *_regulator_get(struct device *dev, const char *id, enum regulator_get_type get_type); +int _regulator_bulk_get(struct device *dev, int num_consumers, + struct regulator_bulk_data *consumers, enum regulator_get_type get_type); #endif diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index 591a64e1ca61..b23b052eab10 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -97,9 +97,9 @@ static const struct regulator_desc isl_rd[] = { }, }; -static int isl6271a_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int isl6271a_probe(struct i2c_client *i2c) { + const struct i2c_device_id *id = i2c_client_get_device_id(i2c); struct regulator_dev *rdev; struct regulator_config config = { }; struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev); @@ -148,7 +148,7 @@ static struct i2c_driver isl6271a_i2c_driver = { .driver = { .name = "isl6271a", }, - .probe = isl6271a_probe, + .probe_new = isl6271a_probe, .id_table = isl6271a_id, }; diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index 2d276bbeedf2..27b216bf18fc 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -495,8 +495,7 @@ static int setup_regulators(struct lp3972 *lp3972, return 0; } -static int lp3972_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int lp3972_i2c_probe(struct i2c_client *i2c) { struct lp3972 *lp3972; struct lp3972_platform_data *pdata = dev_get_platdata(&i2c->dev); @@ -547,7 +546,7 @@ static struct i2c_driver lp3972_i2c_driver = { .driver = { .name = "lp3972", }, - .probe = lp3972_i2c_probe, + .probe_new = lp3972_i2c_probe, .id_table = lp3972_i2c_id, }; diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 35d826fe9def..c576894c3d52 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -879,8 +879,9 @@ static struct lp872x_platform_data } #endif -static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id) +static int lp872x_probe(struct i2c_client *cl) { + const struct i2c_device_id *id = i2c_client_get_device_id(cl); struct lp872x *lp; struct lp872x_platform_data *pdata; int ret; @@ -946,7 +947,7 @@ static struct i2c_driver lp872x_driver = { .name = "lp872x", .of_match_table = of_match_ptr(lp872x_dt_ids), }, - .probe = lp872x_probe, + .probe_new = lp872x_probe, .id_table = lp872x_ids, }; diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index 31b43426d47c..467dfdcebc91 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -357,8 +357,7 @@ static const struct regmap_config lp8755_regmap = { .max_register = LP8755_REG_MAX, }; -static int lp8755_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int lp8755_probe(struct i2c_client *client) { int ret, icnt; struct lp8755_chip *pchip; @@ -442,7 +441,7 @@ static struct i2c_driver lp8755_i2c_driver = { .driver = { .name = LP8755_NAME, }, - .probe = lp8755_probe, + .probe_new = lp8755_probe, .remove = lp8755_remove, .id_table = lp8755_id, }; diff --git a/drivers/regulator/ltc3589.c b/drivers/regulator/ltc3589.c index 5e0b669c3a01..460d34c50fb0 100644 --- a/drivers/regulator/ltc3589.c +++ b/drivers/regulator/ltc3589.c @@ -378,9 +378,9 @@ static irqreturn_t ltc3589_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int ltc3589_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ltc3589_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct device *dev = &client->dev; struct regulator_desc *descs; struct ltc3589 *ltc3589; @@ -476,7 +476,7 @@ static struct i2c_driver ltc3589_driver = { .name = DRIVER_NAME, .of_match_table = of_match_ptr(ltc3589_of_match), }, - .probe = ltc3589_probe, + .probe_new = ltc3589_probe, .id_table = ltc3589_i2c_id, }; module_i2c_driver(ltc3589_driver); diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index d4958394e608..a00aa2e8ff3f 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -207,8 +207,7 @@ static const struct of_device_id __maybe_unused max1586_of_match[] = { }; MODULE_DEVICE_TABLE(of, max1586_of_match); -static int max1586_pmic_probe(struct i2c_client *client, - const struct i2c_device_id *i2c_id) +static int max1586_pmic_probe(struct i2c_client *client) { struct max1586_platform_data *pdata, pdata_of; struct regulator_config config = { }; @@ -290,7 +289,7 @@ static const struct i2c_device_id max1586_id[] = { MODULE_DEVICE_TABLE(i2c, max1586_id); static struct i2c_driver max1586_pmic_driver = { - .probe = max1586_pmic_probe, + .probe_new = max1586_pmic_probe, .driver = { .name = "max1586", .of_match_table = of_match_ptr(max1586_of_match), diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index e86d8bd25fdc..aed5443d88e1 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -145,8 +145,7 @@ static const struct regmap_config max8649_regmap_config = { .val_bits = 8, }; -static int max8649_regulator_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int max8649_regulator_probe(struct i2c_client *client) { struct max8649_platform_data *pdata = dev_get_platdata(&client->dev); struct max8649_regulator_info *info = NULL; @@ -247,7 +246,7 @@ static const struct i2c_device_id max8649_id[] = { MODULE_DEVICE_TABLE(i2c, max8649_id); static struct i2c_driver max8649_driver = { - .probe = max8649_regulator_probe, + .probe_new = max8649_regulator_probe, .driver = { .name = "max8649", }, diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 347043a5a9a7..711623be8eb5 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -367,9 +367,9 @@ static inline int max8660_pdata_from_dt(struct device *dev, } #endif -static int max8660_probe(struct i2c_client *client, - const struct i2c_device_id *i2c_id) +static int max8660_probe(struct i2c_client *client) { + const struct i2c_device_id *i2c_id = i2c_client_get_device_id(client); struct device *dev = &client->dev; struct max8660_platform_data pdata_of, *pdata = dev_get_platdata(dev); struct regulator_config config = { }; @@ -503,7 +503,7 @@ static const struct i2c_device_id max8660_id[] = { MODULE_DEVICE_TABLE(i2c, max8660_id); static struct i2c_driver max8660_driver = { - .probe = max8660_probe, + .probe_new = max8660_probe, .driver = { .name = "max8660", }, diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index ccd5da63cdf2..360a33ecc093 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -171,8 +171,7 @@ static struct max8952_platform_data *max8952_parse_dt(struct device *dev) } #endif -static int max8952_pmic_probe(struct i2c_client *client, - const struct i2c_device_id *i2c_id) +static int max8952_pmic_probe(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; struct max8952_platform_data *pdata = dev_get_platdata(&client->dev); @@ -314,7 +313,7 @@ static const struct i2c_device_id max8952_ids[] = { MODULE_DEVICE_TABLE(i2c, max8952_ids); static struct i2c_driver max8952_pmic_driver = { - .probe = max8952_pmic_probe, + .probe_new = max8952_pmic_probe, .driver = { .name = "max8952", .of_match_table = of_match_ptr(max8952_dt_match), diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c index 596cc36aaff6..7e00a45db26a 100644 --- a/drivers/regulator/max8973-regulator.c +++ b/drivers/regulator/max8973-regulator.c @@ -586,9 +586,9 @@ static const struct of_device_id of_max8973_match_tbl[] = { }; MODULE_DEVICE_TABLE(of, of_max8973_match_tbl); -static int max8973_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int max8973_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct max8973_regulator_platform_data *pdata; struct regulator_init_data *ridata; struct regulator_config config = { }; @@ -806,7 +806,7 @@ static struct i2c_driver max8973_i2c_driver = { .name = "max8973", .of_match_table = of_max8973_match_tbl, }, - .probe = max8973_probe, + .probe_new = max8973_probe, .id_table = max8973_id, }; diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c index 8ad4722eca4b..6a0c94c15027 100644 --- a/drivers/regulator/mp886x.c +++ b/drivers/regulator/mp886x.c @@ -362,7 +362,7 @@ MODULE_DEVICE_TABLE(i2c, mp886x_id); static struct i2c_driver mp886x_regulator_driver = { .driver = { .name = "mp886x-regulator", - .of_match_table = of_match_ptr(mp886x_dt_ids), + .of_match_table = mp886x_dt_ids, }, .probe_new = mp886x_i2c_probe, .id_table = mp886x_id, diff --git a/drivers/regulator/mt6357-regulator.c b/drivers/regulator/mt6357-regulator.c new file mode 100644 index 000000000000..b2352b96aed2 --- /dev/null +++ b/drivers/regulator/mt6357-regulator.c @@ -0,0 +1,453 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2022 MediaTek Inc. +// Copyright (c) 2022 BayLibre, SAS. +// Author: Chen Zhong <chen.zhong@mediatek.com> +// Author: Fabien Parent <fparent@baylibre.com> +// Author: Alexandre Mergnat <amergnat@baylibre.com> +// +// Based on mt6397-regulator.c +// + +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/mfd/mt6397/core.h> +#include <linux/mfd/mt6357/registers.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/mt6357-regulator.h> +#include <linux/regulator/of_regulator.h> + +/* + * MT6357 regulators' information + * + * @desc: standard fields of regulator description. + * @da_vsel_reg: Monitor register for query buck's voltage. + * @da_vsel_mask: Mask for query buck's voltage. + */ +struct mt6357_regulator_info { + struct regulator_desc desc; + u32 da_vsel_reg; + u32 da_vsel_mask; +}; + +#define MT6357_BUCK(match, vreg, min, max, step, \ + volt_ranges, vosel_reg, vosel_mask, _da_vsel_mask) \ +[MT6357_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .regulators_node = "regulators", \ + .ops = &mt6357_volt_range_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6357_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ((max) - (min)) / (step) + 1, \ + .linear_ranges = volt_ranges, \ + .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ + .vsel_reg = vosel_reg, \ + .vsel_mask = vosel_mask, \ + .enable_reg = MT6357_BUCK_##vreg##_CON0, \ + .enable_mask = BIT(0), \ + }, \ + .da_vsel_reg = MT6357_BUCK_##vreg##_DBG0, \ + .da_vsel_mask = vosel_mask, \ +} + +#define MT6357_LDO(match, vreg, ldo_volt_table, \ + enreg, vosel, vosel_mask) \ +[MT6357_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .regulators_node = "regulators", \ + .ops = &mt6357_volt_table_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6357_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(ldo_volt_table), \ + .volt_table = ldo_volt_table, \ + .vsel_reg = vosel, \ + .vsel_mask = vosel_mask, \ + .enable_reg = enreg, \ + .enable_mask = BIT(0), \ + }, \ +} + +#define MT6357_LDO1(match, vreg, min, max, step, volt_ranges, \ + enreg, vosel, vosel_mask) \ +[MT6357_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .regulators_node = "regulators", \ + .ops = &mt6357_volt_range_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6357_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ((max) - (min)) / (step) + 1, \ + .linear_ranges = volt_ranges, \ + .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ + .vsel_reg = vosel, \ + .vsel_mask = vosel_mask, \ + .enable_reg = enreg, \ + .enable_mask = BIT(0), \ + }, \ + .da_vsel_reg = MT6357_LDO_##vreg##_DBG0, \ + .da_vsel_mask = 0x7f00, \ +} + +#define MT6357_REG_FIXED(match, vreg, volt) \ +[MT6357_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .regulators_node = "regulators", \ + .ops = &mt6357_volt_fixed_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6357_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = 1, \ + .enable_reg = MT6357_LDO_##vreg##_CON0, \ + .enable_mask = BIT(0), \ + .min_uV = volt, \ + }, \ +} + +/** + * mt6357_get_buck_voltage_sel - get_voltage_sel for regmap users + * + * @rdev: regulator to operate on + * + * Regulators that use regmap for their register I/O can set the + * da_vsel_reg and da_vsel_mask fields in the info structure and + * then use this as their get_voltage_vsel operation. + */ +static int mt6357_get_buck_voltage_sel(struct regulator_dev *rdev) +{ + int ret, regval; + struct mt6357_regulator_info *info = rdev_get_drvdata(rdev); + + ret = regmap_read(rdev->regmap, info->da_vsel_reg, ®val); + if (ret != 0) { + dev_err(&rdev->dev, + "Failed to get mt6357 Buck %s vsel reg: %d\n", + info->desc.name, ret); + return ret; + } + + regval &= info->da_vsel_mask; + regval >>= ffs(info->da_vsel_mask) - 1; + + return regval; +} + +static const struct regulator_ops mt6357_volt_range_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = mt6357_get_buck_voltage_sel, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + +static const struct regulator_ops mt6357_volt_table_ops = { + .list_voltage = regulator_list_voltage_table, + .map_voltage = regulator_map_voltage_iterate, + .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, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + +static const struct regulator_ops mt6357_volt_fixed_ops = { + .list_voltage = regulator_list_voltage_linear, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + +static const int vxo22_voltages[] = { + 2200000, + 0, + 2400000, +}; + +static const int vefuse_voltages[] = { + 1200000, + 1300000, + 1500000, + 0, + 1800000, + 0, + 0, + 0, + 0, + 2800000, + 2900000, + 3000000, + 0, + 3300000, +}; + +static const int vcn33_voltages[] = { + 0, + 3300000, + 3400000, + 3500000, +}; + +static const int vcama_voltages[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2500000, + 0, + 0, + 2800000, +}; + +static const int vcamd_voltages[] = { + 0, + 0, + 0, + 0, + 1000000, + 1100000, + 1200000, + 1300000, + 0, + 1500000, + 0, + 0, + 1800000, +}; + +static const int vldo28_voltages[] = { + 0, + 2800000, + 0, + 3000000, +}; + +static const int vdram_voltages[] = { + 0, + 1100000, + 1200000, +}; + +static const int vsim_voltages[] = { + 0, + 0, + 0, + 1700000, + 1800000, + 0, + 0, + 0, + 2700000, + 0, + 0, + 3000000, + 3100000, +}; + +static const int vibr_voltages[] = { + 1200000, + 1300000, + 1500000, + 0, + 1800000, + 2000000, + 0, + 0, + 0, + 2800000, + 0, + 3000000, + 0, + 3300000, +}; + +static const int vmc_voltages[] = { + 0, + 0, + 0, + 0, + 1800000, + 0, + 0, + 0, + 0, + 0, + 2900000, + 3000000, + 0, + 3300000, +}; + +static const int vmch_voltages[] = { + 0, + 0, + 2900000, + 3000000, + 0, + 3300000, +}; + +static const int vemc_voltages[] = { + 0, + 0, + 2900000, + 3000000, + 0, + 3300000, +}; + +static const int vusb_voltages[] = { + 0, + 0, + 0, + 3000000, + 3100000, +}; + +static const struct linear_range buck_volt_range1[] = { + REGULATOR_LINEAR_RANGE(518750, 0, 0x7f, 6250), +}; + +static const struct linear_range buck_volt_range2[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 6250), +}; + +static const struct linear_range buck_volt_range3[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000), +}; + +static const struct linear_range buck_volt_range4[] = { + REGULATOR_LINEAR_RANGE(1200000, 0, 0x7f, 12500), +}; + +/* The array is indexed by id(MT6357_ID_XXX) */ +static struct mt6357_regulator_info mt6357_regulators[] = { + /* Bucks */ + MT6357_BUCK("buck-vcore", VCORE, 518750, 1312500, 6250, + buck_volt_range1, MT6357_BUCK_VCORE_ELR0, 0x7f, 0x7f), + MT6357_BUCK("buck-vproc", VPROC, 518750, 1312500, 6250, + buck_volt_range1, MT6357_BUCK_VPROC_ELR0, 0x7f, 0x7f), + MT6357_BUCK("buck-vmodem", VMODEM, 500000, 1293750, 6250, + buck_volt_range2, MT6357_BUCK_VMODEM_ELR0, 0x7f, 0x7f), + MT6357_BUCK("buck-vpa", VPA, 500000, 3650000, 50000, + buck_volt_range3, MT6357_BUCK_VPA_CON1, 0x3f, 0x3f), + MT6357_BUCK("buck-vs1", VS1, 1200000, 2787500, 12500, + buck_volt_range4, MT6357_BUCK_VS1_ELR0, 0x7f, 0x7f), + + /* LDOs */ + MT6357_LDO("ldo-vcama", VCAMA, vcama_voltages, + MT6357_LDO_VCAMA_CON0, MT6357_VCAMA_ANA_CON0, 0xf00), + MT6357_LDO("ldo-vcamd", VCAMD, vcamd_voltages, + MT6357_LDO_VCAMD_CON0, MT6357_VCAMD_ANA_CON0, 0xf00), + MT6357_LDO("ldo-vcn33-bt", VCN33_BT, vcn33_voltages, + MT6357_LDO_VCN33_CON0_0, MT6357_VCN33_ANA_CON0, 0x300), + MT6357_LDO("ldo-vcn33-wifi", VCN33_WIFI, vcn33_voltages, + MT6357_LDO_VCN33_CON0_1, MT6357_VCN33_ANA_CON0, 0x300), + MT6357_LDO("ldo-vdram", VDRAM, vdram_voltages, + MT6357_LDO_VDRAM_CON0, MT6357_VDRAM_ELR_2, 0x300), + MT6357_LDO("ldo-vefuse", VEFUSE, vefuse_voltages, + MT6357_LDO_VEFUSE_CON0, MT6357_VEFUSE_ANA_CON0, 0xf00), + MT6357_LDO("ldo-vemc", VEMC, vemc_voltages, + MT6357_LDO_VEMC_CON0, MT6357_VEMC_ANA_CON0, 0x700), + MT6357_LDO("ldo-vibr", VIBR, vibr_voltages, + MT6357_LDO_VIBR_CON0, MT6357_VIBR_ANA_CON0, 0xf00), + MT6357_LDO("ldo-vldo28", VLDO28, vldo28_voltages, + MT6357_LDO_VLDO28_CON0_0, MT6357_VLDO28_ANA_CON0, 0x300), + MT6357_LDO("ldo-vmc", VMC, vmc_voltages, + MT6357_LDO_VMC_CON0, MT6357_VMC_ANA_CON0, 0xf00), + MT6357_LDO("ldo-vmch", VMCH, vmch_voltages, + MT6357_LDO_VMCH_CON0, MT6357_VMCH_ANA_CON0, 0x700), + MT6357_LDO("ldo-vsim1", VSIM1, vsim_voltages, + MT6357_LDO_VSIM1_CON0, MT6357_VSIM1_ANA_CON0, 0xf00), + MT6357_LDO("ldo-vsim2", VSIM2, vsim_voltages, + MT6357_LDO_VSIM2_CON0, MT6357_VSIM2_ANA_CON0, 0xf00), + MT6357_LDO("ldo-vusb33", VUSB33, vusb_voltages, + MT6357_LDO_VUSB33_CON0_0, MT6357_VUSB33_ANA_CON0, 0x700), + MT6357_LDO("ldo-vxo22", VXO22, vxo22_voltages, + MT6357_LDO_VXO22_CON0, MT6357_VXO22_ANA_CON0, 0x300), + + MT6357_LDO1("ldo-vsram-proc", VSRAM_PROC, 518750, 1312500, 6250, + buck_volt_range1, MT6357_LDO_VSRAM_PROC_CON0, + MT6357_LDO_VSRAM_CON0, 0x7f00), + MT6357_LDO1("ldo-vsram-others", VSRAM_OTHERS, 518750, 1312500, 6250, + buck_volt_range1, MT6357_LDO_VSRAM_OTHERS_CON0, + MT6357_LDO_VSRAM_CON1, 0x7f00), + + MT6357_REG_FIXED("ldo-vaud28", VAUD28, 2800000), + MT6357_REG_FIXED("ldo-vaux18", VAUX18, 1800000), + MT6357_REG_FIXED("ldo-vcamio18", VCAMIO, 1800000), + MT6357_REG_FIXED("ldo-vcn18", VCN18, 1800000), + MT6357_REG_FIXED("ldo-vcn28", VCN28, 2800000), + MT6357_REG_FIXED("ldo-vfe28", VFE28, 2800000), + MT6357_REG_FIXED("ldo-vio18", VIO18, 1800000), + MT6357_REG_FIXED("ldo-vio28", VIO28, 2800000), + MT6357_REG_FIXED("ldo-vrf12", VRF12, 1200000), + MT6357_REG_FIXED("ldo-vrf18", VRF18, 1800000), +}; + +static int mt6357_regulator_probe(struct platform_device *pdev) +{ + struct mt6397_chip *mt6357 = dev_get_drvdata(pdev->dev.parent); + struct regulator_config config = {}; + struct regulator_dev *rdev; + int i; + + pdev->dev.of_node = pdev->dev.parent->of_node; + + for (i = 0; i < MT6357_MAX_REGULATOR; i++) { + config.dev = &pdev->dev; + config.driver_data = &mt6357_regulators[i]; + config.regmap = mt6357->regmap; + + rdev = devm_regulator_register(&pdev->dev, + &mt6357_regulators[i].desc, + &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "failed to register %s\n", + mt6357_regulators[i].desc.name); + return PTR_ERR(rdev); + } + } + + return 0; +} + +static const struct platform_device_id mt6357_platform_ids[] = { + { "mt6357-regulator" }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(platform, mt6357_platform_ids); + +static struct platform_driver mt6357_regulator_driver = { + .driver = { + .name = "mt6357-regulator", + }, + .probe = mt6357_regulator_probe, + .id_table = mt6357_platform_ids, +}; + +module_platform_driver(mt6357_regulator_driver); + +MODULE_AUTHOR("Chen Zhong <chen.zhong@mediatek.com>"); +MODULE_AUTHOR("Fabien Parent <fabien.parent@linaro.org>"); +MODULE_AUTHOR("Alexandre Mergnat <amergnat@baylibre.com>"); +MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6357 PMIC"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 0aff1c2886b5..1b65e5e4e40f 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -505,7 +505,7 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev, struct device_node *child; struct regulator_init_data *init_data = NULL; - child = regulator_of_get_init_node(dev, desc); + child = regulator_of_get_init_node(config->dev, desc); if (!child) return NULL; @@ -701,3 +701,95 @@ struct regulator_dev *of_parse_coupled_regulator(struct regulator_dev *rdev, return c_rdev; } + +/* + * Check if name is a supply name according to the '*-supply' pattern + * return 0 if false + * return length of supply name without the -supply + */ +static int is_supply_name(const char *name) +{ + int strs, i; + + strs = strlen(name); + /* string need to be at minimum len(x-supply) */ + if (strs < 8) + return 0; + for (i = strs - 6; i > 0; i--) { + /* find first '-' and check if right part is supply */ + if (name[i] != '-') + continue; + if (strcmp(name + i + 1, "supply") != 0) + return 0; + return i; + } + return 0; +} + +/* + * of_regulator_bulk_get_all - get multiple regulator consumers + * + * @dev: Device to supply + * @np: device node to search for consumers + * @consumers: Configuration of consumers; clients are stored here. + * + * @return number of regulators on success, an errno on failure. + * + * This helper function allows drivers to get several regulator + * consumers in one operation. If any of the regulators cannot be + * acquired then any regulators that were allocated will be freed + * before returning to the caller. + */ +int of_regulator_bulk_get_all(struct device *dev, struct device_node *np, + struct regulator_bulk_data **consumers) +{ + int num_consumers = 0; + struct regulator *tmp; + struct property *prop; + int i, n = 0, ret; + char name[64]; + + *consumers = NULL; + + /* + * first pass: get numbers of xxx-supply + * second pass: fill consumers + */ +restart: + for_each_property_of_node(np, prop) { + i = is_supply_name(prop->name); + if (i == 0) + continue; + if (!*consumers) { + num_consumers++; + continue; + } else { + memcpy(name, prop->name, i); + name[i] = '\0'; + tmp = regulator_get(dev, name); + if (IS_ERR(tmp)) { + ret = -EINVAL; + goto error; + } + (*consumers)[n].consumer = tmp; + n++; + continue; + } + } + if (*consumers) + return num_consumers; + if (num_consumers == 0) + return 0; + *consumers = kmalloc_array(num_consumers, + sizeof(struct regulator_bulk_data), + GFP_KERNEL); + if (!*consumers) + return -ENOMEM; + goto restart; + +error: + while (--n >= 0) + regulator_put(consumers[n]->consumer); + return ret; +} +EXPORT_SYMBOL_GPL(of_regulator_bulk_get_all); diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c index 14b7d3376516..c6351fac9f4d 100644 --- a/drivers/regulator/pca9450-regulator.c +++ b/drivers/regulator/pca9450-regulator.c @@ -701,8 +701,7 @@ static irqreturn_t pca9450_irq_handler(int irq, void *data) return IRQ_HANDLED; } -static int pca9450_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int pca9450_i2c_probe(struct i2c_client *i2c) { enum pca9450_chip_type type = (unsigned int)(uintptr_t) of_device_get_match_data(&i2c->dev); @@ -875,7 +874,7 @@ static struct i2c_driver pca9450_i2c_driver = { .name = "nxp-pca9450", .of_match_table = pca9450_of_match, }, - .probe = pca9450_i2c_probe, + .probe_new = pca9450_i2c_probe, }; module_i2c_driver(pca9450_i2c_driver); diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index d899d6e98fb8..9ab604289b5c 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -683,9 +683,9 @@ static const struct regmap_config pfuze_regmap_config = { .cache_type = REGCACHE_RBTREE, }; -static int pfuze100_regulator_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int pfuze100_regulator_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct pfuze_chip *pfuze_chip; struct regulator_config config = { }; int i, ret; @@ -847,7 +847,7 @@ static struct i2c_driver pfuze_driver = { .name = "pfuze100-regulator", .of_match_table = pfuze_dt_ids, }, - .probe = pfuze100_regulator_probe, + .probe_new = pfuze100_regulator_probe, }; module_i2c_driver(pfuze_driver); diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c index 2a74cc05acfe..15a67c05f519 100644 --- a/drivers/regulator/pv88080-regulator.c +++ b/drivers/regulator/pv88080-regulator.c @@ -374,9 +374,9 @@ error_i2c: /* * I2C driver interface functions */ -static int pv88080_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int pv88080_i2c_probe(struct i2c_client *i2c) { + const struct i2c_device_id *id = i2c_client_get_device_id(i2c); struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev); struct pv88080 *chip; const struct pv88080_compatible_regmap *regmap_config; @@ -559,7 +559,7 @@ static struct i2c_driver pv88080_regulator_driver = { .name = "pv88080", .of_match_table = of_match_ptr(pv88080_dt_ids), }, - .probe = pv88080_i2c_probe, + .probe_new = pv88080_i2c_probe, .id_table = pv88080_i2c_id, }; diff --git a/drivers/regulator/qcom-labibb-regulator.c b/drivers/regulator/qcom-labibb-regulator.c index 639b71eb41ff..bcf7140f3bc9 100644 --- a/drivers/regulator/qcom-labibb-regulator.c +++ b/drivers/regulator/qcom-labibb-regulator.c @@ -822,6 +822,7 @@ static int qcom_labibb_regulator_probe(struct platform_device *pdev) if (irq == 0) irq = -EINVAL; + of_node_put(reg_node); return dev_err_probe(vreg->dev, irq, "Short-circuit irq not found.\n"); } diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index 4158ff126a67..43b5b9377714 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -731,6 +731,24 @@ static const struct rpmh_vreg_hw_data pmic5_ftsmps520 = { .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, }; +static const struct rpmh_vreg_hw_data pmic5_ftsmps525_lv = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 267, 4000), + .n_voltages = 268, + .pmic_mode_map = pmic_mode_map_pmic5_smps, + .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, +}; + +static const struct rpmh_vreg_hw_data pmic5_ftsmps525_mv = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(600000, 0, 267, 8000), + .n_voltages = 268, + .pmic_mode_map = pmic_mode_map_pmic5_smps, + .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, +}; + static const struct rpmh_vreg_hw_data pmic5_hfsmps515 = { .regulator_type = VRM, .ops = &rpmh_regulator_vrm_ops, @@ -987,6 +1005,57 @@ static const struct rpmh_vreg_init_data pm8450_vreg_data[] = { {} }; +static const struct rpmh_vreg_init_data pm8550_vreg_data[] = { + RPMH_VREG("ldo1", "ldo%s1", &pmic5_pldo, "vdd-l1-l4-l10"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_pldo, "vdd-l2-l13-l14"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l1-l4-l10"), + RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l5-l16"), + RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo_lv, "vdd-l6-l7"), + RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo_lv, "vdd-l6-l7"), + RPMH_VREG("ldo8", "ldo%s8", &pmic5_pldo_lv, "vdd-l8-l9"), + RPMH_VREG("ldo9", "ldo%s9", &pmic5_pldo, "vdd-l8-l9"), + RPMH_VREG("ldo10", "ldo%s10", &pmic5_nldo, "vdd-l1-l4-l10"), + RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo, "vdd-l11"), + RPMH_VREG("ldo12", "ldo%s12", &pmic5_pldo, "vdd-l12"), + RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo, "vdd-l2-l13-l14"), + RPMH_VREG("ldo14", "ldo%s14", &pmic5_pldo, "vdd-l2-l13-l14"), + RPMH_VREG("ldo15", "ldo%s15", &pmic5_pldo, "vdd-l15"), + RPMH_VREG("ldo16", "ldo%s16", &pmic5_pldo, "vdd-l5-l16"), + RPMH_VREG("ldo17", "ldo%s17", &pmic5_pldo, "vdd-l17"), + RPMH_VREG("bob1", "bob%s1", &pmic5_bob, "vdd-bob1"), + RPMH_VREG("bob2", "bob%s2", &pmic5_bob, "vdd-bob2"), + {} +}; + +static const struct rpmh_vreg_init_data pm8550vs_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525_lv, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525_lv, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525_lv, "vdd-s3"), + RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525_lv, "vdd-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525_lv, "vdd-s5"), + RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525_mv, "vdd-s6"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"), + {} +}; + +static const struct rpmh_vreg_init_data pm8550ve_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525_lv, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525_lv, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525_lv, "vdd-s3"), + RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525_lv, "vdd-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525_lv, "vdd-s5"), + RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525_lv, "vdd-s6"), + RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps525_lv, "vdd-s7"), + RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps525_lv, "vdd-s8"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"), + {} +}; + static const struct rpmh_vreg_init_data pm8009_vreg_data[] = { RPMH_VREG("smps1", "smp%s1", &pmic5_hfsmps510, "vdd-s1"), RPMH_VREG("smps2", "smp%s2", &pmic5_hfsmps515, "vdd-s2"), @@ -1187,7 +1256,7 @@ static const struct rpmh_vreg_init_data pm7325_vreg_data[] = { static const struct rpmh_vreg_init_data pmr735a_vreg_data[] = { RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps520, "vdd-s1"), RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps520, "vdd-s2"), - RPMH_VREG("smps3", "smp%s3", &pmic5_hfsmps510, "vdd-s3"), + RPMH_VREG("smps3", "smp%s3", &pmic5_hfsmps515, "vdd-s3"), RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1-l2"), RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l1-l2"), RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"), @@ -1315,6 +1384,18 @@ static const struct of_device_id __maybe_unused rpmh_regulator_match_table[] = { .data = pm8450_vreg_data, }, { + .compatible = "qcom,pm8550-rpmh-regulators", + .data = pm8550_vreg_data, + }, + { + .compatible = "qcom,pm8550ve-rpmh-regulators", + .data = pm8550ve_vreg_data, + }, + { + .compatible = "qcom,pm8550vs-rpmh-regulators", + .data = pm8550vs_vreg_data, + }, + { .compatible = "qcom,pm8998-rpmh-regulators", .data = pm8998_vreg_data, }, diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c index f98168d58dce..9f2b58458841 100644 --- a/drivers/regulator/qcom_smd-regulator.c +++ b/drivers/regulator/qcom_smd-regulator.c @@ -677,6 +677,24 @@ static const struct regulator_desc pm6125_ftsmps = { .ops = &rpm_smps_ldo_ops, }; +static const struct regulator_desc pmic5_ftsmps520 = { + .linear_ranges = (struct linear_range[]) { + REGULATOR_LINEAR_RANGE(300000, 0, 263, 4000), + }, + .n_linear_ranges = 1, + .n_voltages = 264, + .ops = &rpm_smps_ldo_ops, +}; + +static const struct regulator_desc pmic5_hfsmps515 = { + .linear_ranges = (struct linear_range[]) { + REGULATOR_LINEAR_RANGE(320000, 0, 235, 16000), + }, + .n_linear_ranges = 1, + .n_voltages = 236, + .ops = &rpm_smps_ldo_ops, +}; + static const struct regulator_desc pms405_hfsmps3 = { .linear_ranges = (struct linear_range[]) { REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000), @@ -1265,6 +1283,20 @@ static const struct rpm_regulator_data rpm_pmi8998_regulators[] = { {} }; +static const struct rpm_regulator_data rpm_pmr735a_regulators[] = { + { "s1", QCOM_SMD_RPM_SMPE, 1, &pmic5_ftsmps520, "vdd_s1"}, + { "s2", QCOM_SMD_RPM_SMPE, 2, &pmic5_ftsmps520, "vdd_s2"}, + { "s3", QCOM_SMD_RPM_SMPE, 3, &pmic5_hfsmps515, "vdd_s3"}, + { "l1", QCOM_SMD_RPM_LDOE, 1, &pm660_nldo660, "vdd_l1_l2"}, + { "l2", QCOM_SMD_RPM_LDOE, 2, &pm660_nldo660, "vdd_l1_l2"}, + { "l3", QCOM_SMD_RPM_LDOE, 3, &pm660_nldo660, "vdd_l3"}, + { "l4", QCOM_SMD_RPM_LDOE, 4, &pm660_ht_lvpldo, "vdd_l4"}, + { "l5", QCOM_SMD_RPM_LDOE, 5, &pm660_nldo660, "vdd_l5_l6"}, + { "l6", QCOM_SMD_RPM_LDOE, 6, &pm660_nldo660, "vdd_l5_l6"}, + { "l7", QCOM_SMD_RPM_LDOE, 7, &pm660_pldo660, "vdd_l7_bob"}, + {} +}; + static const struct rpm_regulator_data rpm_pms405_regulators[] = { { "s1", QCOM_SMD_RPM_SMPA, 1, &pms405_hfsmps3, "vdd_s1" }, { "s2", QCOM_SMD_RPM_SMPA, 2, &pms405_hfsmps3, "vdd_s2" }, @@ -1305,6 +1337,7 @@ static const struct of_device_id rpm_of_match[] = { { .compatible = "qcom,rpm-pma8084-regulators", .data = &rpm_pma8084_regulators }, { .compatible = "qcom,rpm-pmi8994-regulators", .data = &rpm_pmi8994_regulators }, { .compatible = "qcom,rpm-pmi8998-regulators", .data = &rpm_pmi8998_regulators }, + { .compatible = "qcom,rpm-pmr735a-regulators", .data = &rpm_pmr735a_regulators }, { .compatible = "qcom,rpm-pms405-regulators", .data = &rpm_pms405_regulators }, {} }; diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 127dc2e2e690..fa9fc1aa1ae3 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -14,7 +14,6 @@ #include <linux/delay.h> #include <linux/gpio.h> -#include <linux/i2c.h> #include <linux/module.h> #include <linux/of_device.h> #include <linux/of_gpio.h> @@ -1286,19 +1285,23 @@ dt_parse_end: static int rk808_regulator_probe(struct platform_device *pdev) { struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); - struct i2c_client *client = rk808->i2c; struct regulator_config config = {}; struct regulator_dev *rk808_rdev; struct rk808_regulator_data *pdata; const struct regulator_desc *regulators; + struct regmap *regmap; int ret, i, nregulators; + regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!regmap) + return -ENODEV; + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; - ret = rk808_regulator_dt_parse_pdata(&pdev->dev, &client->dev, - rk808->regmap, pdata); + ret = rk808_regulator_dt_parse_pdata(&pdev->dev, pdev->dev.parent, + regmap, pdata); if (ret < 0) return ret; @@ -1326,24 +1329,23 @@ static int rk808_regulator_probe(struct platform_device *pdev) nregulators = RK818_NUM_REGULATORS; break; default: - dev_err(&client->dev, "unsupported RK8XX ID %lu\n", + dev_err(&pdev->dev, "unsupported RK8XX ID %lu\n", rk808->variant); return -EINVAL; } - config.dev = &client->dev; + config.dev = &pdev->dev; + config.dev->of_node = pdev->dev.parent->of_node; config.driver_data = pdata; - config.regmap = rk808->regmap; + config.regmap = regmap; /* Instantiate the regulators */ for (i = 0; i < nregulators; i++) { rk808_rdev = devm_regulator_register(&pdev->dev, ®ulators[i], &config); - if (IS_ERR(rk808_rdev)) { - dev_err(&client->dev, - "failed to register %d regulator\n", i); - return PTR_ERR(rk808_rdev); - } + if (IS_ERR(rk808_rdev)) + return dev_err_probe(&pdev->dev, PTR_ERR(rk808_rdev), + "failed to register %d regulator\n", i); } return 0; diff --git a/drivers/regulator/rpi-panel-attiny-regulator.c b/drivers/regulator/rpi-panel-attiny-regulator.c index 308f7972941b..34514976475e 100644 --- a/drivers/regulator/rpi-panel-attiny-regulator.c +++ b/drivers/regulator/rpi-panel-attiny-regulator.c @@ -282,8 +282,7 @@ static int attiny_i2c_read(struct i2c_client *client, u8 reg, unsigned int *buf) /* * I2C driver interface functions */ -static int attiny_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int attiny_i2c_probe(struct i2c_client *i2c) { struct backlight_properties props = { }; struct regulator_config config = { }; @@ -399,7 +398,7 @@ static struct i2c_driver attiny_regulator_driver = { .name = "rpi_touchscreen_attiny", .of_match_table = of_match_ptr(attiny_dt_ids), }, - .probe = attiny_i2c_probe, + .probe_new = attiny_i2c_probe, .remove = attiny_i2c_remove, }; diff --git a/drivers/regulator/rt6190-regulator.c b/drivers/regulator/rt6190-regulator.c new file mode 100644 index 000000000000..995e028abdd7 --- /dev/null +++ b/drivers/regulator/rt6190-regulator.c @@ -0,0 +1,495 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022 Richtek Technology Corp. + * + * Author: ChiYuan Huang <cy_huang@richtek.com> + * + */ + +#include <linux/bits.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/of_regulator.h> + +#define RT6190_REG_VID 0x00 +#define RT6190_REG_OUTV 0x01 +#define RT6190_REG_OUTC 0x03 +#define RT6190_REG_SET1 0x0D +#define RT6190_REG_SET2 0x0E +#define RT6190_REG_SET4 0x10 +#define RT6190_REG_RATIO 0x11 +#define RT6190_REG_OUT_VOLT_L 0x12 +#define RT6190_REG_TEMP_H 0x1B +#define RT6190_REG_STAT1 0x1C +#define RT6190_REG_ALERT1 0x1E +#define RT6190_REG_ALERT2 0x1F +#define RT6190_REG_MASK2 0x21 +#define RT6190_REG_OCPEN 0x28 +#define RT6190_REG_SET5 0x29 +#define RT6190_REG_VBUSC_ADC 0x32 +#define RT6190_REG_BUSC_VOLT_L 0x33 +#define RT6190_REG_BUSC_VOLT_H 0x34 +#define RT6190_REG_STAT3 0x37 +#define RT6190_REG_ALERT3 0x38 +#define RT6190_REG_MASK3 0x39 + +#define RT6190_ENPWM_MASK BIT(7) +#define RT6190_ENDCHG_MASK BIT(4) +#define RT6190_ALERT_OTPEVT BIT(6) +#define RT6190_ALERT_UVPEVT BIT(5) +#define RT6190_ALERT_OVPEVT BIT(4) +#define RT6190_ENGCP_MASK BIT(1) +#define RT6190_FCCM_MASK BIT(7) + +#define RICHTEK_VID 0x82 +#define RT6190_OUT_MIN_UV 3000000 +#define RT6190_OUT_MAX_UV 32000000 +#define RT6190_OUT_STEP_UV 20000 +#define RT6190_OUT_N_VOLT (RT6190_OUT_MAX_UV / RT6190_OUT_STEP_UV + 1) +#define RT6190_OUTV_MINSEL 150 +#define RT6190_OUT_MIN_UA 306000 +#define RT6190_OUT_MAX_UA 12114000 +#define RT6190_OUT_STEP_UA 24000 +#define RT6190_OUTC_MINSEL 19 +#define RT6190_EN_TIME_US 500 + +#define RT6190_PSM_MODE 0 +#define RT6190_FCCM_MODE 1 + +struct rt6190_data { + struct device *dev; + struct regmap *regmap; + struct gpio_desc *enable_gpio; + unsigned int cached_alert_evt; +}; + +static int rt6190_out_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) +{ + struct regmap *regmap = rdev_get_regmap(rdev); + __le16 le_sel = cpu_to_le16(selector); + + return regmap_raw_write(regmap, RT6190_REG_OUTV, &le_sel, + sizeof(le_sel)); +} + +static int rt6190_out_get_voltage_sel(struct regulator_dev *rdev) +{ + struct regmap *regmap = rdev_get_regmap(rdev); + __le16 le_sel; + int ret; + + ret = regmap_raw_read(regmap, RT6190_REG_OUTV, &le_sel, sizeof(le_sel)); + + return ret ?: le16_to_cpu(le_sel); +} + +static int rt6190_out_enable(struct regulator_dev *rdev) +{ + struct rt6190_data *data = rdev_get_drvdata(rdev); + struct regmap *regmap = rdev_get_regmap(rdev); + u8 out_cfg[4]; + int ret; + + pm_runtime_get_sync(data->dev); + + /* + * From off to on, vout config will restore to IC default. + * Read vout configs before enable, and restore them after enable + */ + ret = regmap_raw_read(regmap, RT6190_REG_OUTV, out_cfg, + sizeof(out_cfg)); + if (ret) + return ret; + + ret = regulator_enable_regmap(rdev); + if (ret) + return ret; + + ret = regmap_raw_write(regmap, RT6190_REG_OUTV, out_cfg, + sizeof(out_cfg)); + if (ret) + return ret; + + return regmap_update_bits(regmap, RT6190_REG_SET5, RT6190_ENGCP_MASK, + RT6190_ENGCP_MASK); +} + +static int rt6190_out_disable(struct regulator_dev *rdev) +{ + struct rt6190_data *data = rdev_get_drvdata(rdev); + struct regmap *regmap = rdev_get_regmap(rdev); + int ret; + + ret = regmap_update_bits(regmap, RT6190_REG_SET5, RT6190_ENGCP_MASK, 0); + if (ret) + return ret; + + ret = regulator_disable_regmap(rdev); + if (ret) + return ret; + + /* cleared cached alert event */ + data->cached_alert_evt = 0; + + pm_runtime_put(data->dev); + + return 0; +} + +static int rt6190_out_set_current_limit(struct regulator_dev *rdev, int min_uA, + int max_uA) +{ + struct regmap *regmap = rdev_get_regmap(rdev); + int csel, clim; + __le16 le_csel; + + if (min_uA < RT6190_OUT_MIN_UA || max_uA > RT6190_OUT_MAX_UA) + return -EINVAL; + + csel = DIV_ROUND_UP(min_uA - RT6190_OUT_MIN_UA, RT6190_OUT_STEP_UA); + + clim = RT6190_OUT_MIN_UA + RT6190_OUT_STEP_UA * csel; + if (clim > max_uA) + return -EINVAL; + + csel += RT6190_OUTC_MINSEL; + le_csel = cpu_to_le16(csel); + + return regmap_raw_write(regmap, RT6190_REG_OUTC, &le_csel, + sizeof(le_csel)); +} + +static int rt6190_out_get_current_limit(struct regulator_dev *rdev) +{ + struct regmap *regmap = rdev_get_regmap(rdev); + __le16 le_csel; + int csel, ret; + + ret = regmap_raw_read(regmap, RT6190_REG_OUTC, &le_csel, + sizeof(le_csel)); + if (ret) + return ret; + + csel = le16_to_cpu(le_csel); + csel -= RT6190_OUTC_MINSEL; + + return RT6190_OUT_MIN_UA + RT6190_OUT_STEP_UA * csel; +} + +static int rt6190_out_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + struct regmap *regmap = rdev_get_regmap(rdev); + unsigned int val; + + switch (mode) { + case REGULATOR_MODE_FAST: + val = RT6190_FCCM_MASK; + break; + case REGULATOR_MODE_NORMAL: + val = 0; + break; + default: + return -EINVAL; + } + + return regmap_update_bits(regmap, RT6190_REG_SET1, RT6190_FCCM_MASK, + val); +} + +static unsigned int rt6190_out_get_mode(struct regulator_dev *rdev) +{ + struct regmap *regmap = rdev_get_regmap(rdev); + unsigned int config; + int ret; + + ret = regmap_read(regmap, RT6190_REG_SET1, &config); + if (ret) + return REGULATOR_MODE_INVALID; + + if (config & RT6190_FCCM_MASK) + return REGULATOR_MODE_FAST; + + return REGULATOR_MODE_NORMAL; +} + +static int rt6190_out_get_error_flags(struct regulator_dev *rdev, + unsigned int *flags) +{ + struct rt6190_data *data = rdev_get_drvdata(rdev); + unsigned int state, rpt_flags = 0; + int ret; + + ret = regmap_read(data->regmap, RT6190_REG_STAT1, &state); + if (ret) + return ret; + + state |= data->cached_alert_evt; + + if (state & RT6190_ALERT_OTPEVT) + rpt_flags |= REGULATOR_ERROR_OVER_TEMP; + + if (state & RT6190_ALERT_UVPEVT) + rpt_flags |= REGULATOR_ERROR_UNDER_VOLTAGE; + + if (state & RT6190_ALERT_OVPEVT) + rpt_flags |= REGULATOR_ERROR_REGULATION_OUT; + + *flags = rpt_flags; + + return 0; +} + +static unsigned int rt6190_out_of_map_mode(unsigned int mode) +{ + switch (mode) { + case RT6190_PSM_MODE: + return REGULATOR_MODE_NORMAL; + case RT6190_FCCM_MODE: + return REGULATOR_MODE_FAST; + default: + return REGULATOR_MODE_INVALID; + } +} + +static const struct regulator_ops rt6190_regulator_ops = { + .list_voltage = regulator_list_voltage_linear, + .set_voltage_sel = rt6190_out_set_voltage_sel, + .get_voltage_sel = rt6190_out_get_voltage_sel, + .enable = rt6190_out_enable, + .disable = rt6190_out_disable, + .is_enabled = regulator_is_enabled_regmap, + .set_current_limit = rt6190_out_set_current_limit, + .get_current_limit = rt6190_out_get_current_limit, + .set_active_discharge = regulator_set_active_discharge_regmap, + .set_mode = rt6190_out_set_mode, + .get_mode = rt6190_out_get_mode, + .get_error_flags = rt6190_out_get_error_flags, +}; + +static const struct regulator_desc rt6190_regulator_desc = { + .name = "rt6190-regulator", + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .ops = &rt6190_regulator_ops, + .min_uV = RT6190_OUT_MIN_UV, + .uV_step = RT6190_OUT_STEP_UV, + .n_voltages = RT6190_OUT_N_VOLT, + .linear_min_sel = RT6190_OUTV_MINSEL, + .enable_reg = RT6190_REG_SET2, + .enable_mask = RT6190_ENPWM_MASK, + .active_discharge_reg = RT6190_REG_SET2, + .active_discharge_mask = RT6190_ENDCHG_MASK, + .active_discharge_on = RT6190_ENDCHG_MASK, + .of_map_mode = rt6190_out_of_map_mode, +}; + +static bool rt6190_is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT6190_REG_OUT_VOLT_L ... RT6190_REG_ALERT2: + case RT6190_REG_BUSC_VOLT_L ... RT6190_REG_BUSC_VOLT_H: + case RT6190_REG_STAT3 ... RT6190_REG_ALERT3: + return true; + default: + return false; + } +} + +static const struct regmap_config rt6190_regmap_config = { + .name = "rt6190", + .cache_type = REGCACHE_FLAT, + .reg_bits = 8, + .val_bits = 8, + .max_register = RT6190_REG_MASK3, + .num_reg_defaults_raw = RT6190_REG_MASK3 + 1, + .volatile_reg = rt6190_is_volatile_reg, +}; + +static irqreturn_t rt6190_irq_handler(int irq, void *devid) +{ + struct regulator_dev *rdev = devid; + struct rt6190_data *data = rdev_get_drvdata(rdev); + unsigned int alert; + int ret; + + ret = regmap_read(data->regmap, RT6190_REG_ALERT1, &alert); + if (ret) + return IRQ_NONE; + + /* Write clear alert events */ + ret = regmap_write(data->regmap, RT6190_REG_ALERT1, alert); + if (ret) + return IRQ_NONE; + + data->cached_alert_evt |= alert; + + if (alert & RT6190_ALERT_OTPEVT) + regulator_notifier_call_chain(rdev, REGULATOR_EVENT_OVER_TEMP, NULL); + + if (alert & RT6190_ALERT_UVPEVT) + regulator_notifier_call_chain(rdev, REGULATOR_EVENT_UNDER_VOLTAGE, NULL); + + if (alert & RT6190_ALERT_OVPEVT) + regulator_notifier_call_chain(rdev, REGULATOR_EVENT_REGULATION_OUT, NULL); + + return IRQ_HANDLED; +} + +static int rt6190_init_registers(struct regmap *regmap) +{ + int ret; + + /* Enable_ADC = 1 */ + ret = regmap_write(regmap, RT6190_REG_SET4, 0x82); + if (ret) + return ret; + + /* Config default VOUT ratio to be higher */ + ret = regmap_write(regmap, RT6190_REG_RATIO, 0x20); + + /* Mask unused alert */ + ret = regmap_write(regmap, RT6190_REG_MASK2, 0); + if (ret) + return ret; + + /* OCP config */ + ret = regmap_write(regmap, RT6190_REG_OCPEN, 0); + if (ret) + return ret; + + /* Enable VBUSC ADC */ + return regmap_write(regmap, RT6190_REG_VBUSC_ADC, 0x02); +} + +static int rt6190_probe(struct i2c_client *i2c) +{ + struct device *dev = &i2c->dev; + struct rt6190_data *data; + struct gpio_desc *enable_gpio; + struct regmap *regmap; + struct regulator_dev *rdev; + struct regulator_config cfg = {}; + unsigned int vid; + int ret; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH); + if (IS_ERR(enable_gpio)) + return dev_err_probe(dev, PTR_ERR(enable_gpio), "Failed to get 'enable' gpio\n"); + else if (enable_gpio) + usleep_range(RT6190_EN_TIME_US, RT6190_EN_TIME_US * 2); + + regmap = devm_regmap_init_i2c(i2c, &rt6190_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), "Failed to init regmap\n"); + + data->dev = dev; + data->enable_gpio = enable_gpio; + data->regmap = regmap; + i2c_set_clientdata(i2c, data); + + ret = regmap_read(regmap, RT6190_REG_VID, &vid); + if (ret) + return dev_err_probe(dev, ret, "Failed to read VID\n"); + + if (vid != RICHTEK_VID) + return dev_err_probe(dev, -ENODEV, "Incorrect VID 0x%02x\n", vid); + + ret = rt6190_init_registers(regmap); + if (ret) + return dev_err_probe(dev, ret, "Failed to init registers\n"); + + pm_runtime_set_active(dev); + ret = devm_pm_runtime_enable(dev); + if (ret) + return dev_err_probe(dev, ret, "Failed to set pm_runtime enable\n"); + + cfg.dev = dev; + cfg.of_node = dev->of_node; + cfg.driver_data = data; + cfg.init_data = of_get_regulator_init_data(dev, dev->of_node, + &rt6190_regulator_desc); + + rdev = devm_regulator_register(dev, &rt6190_regulator_desc, &cfg); + if (IS_ERR(rdev)) + return dev_err_probe(dev, PTR_ERR(rdev), "Failed to register regulator\n"); + + if (i2c->irq) { + ret = devm_request_threaded_irq(dev, i2c->irq, NULL, + rt6190_irq_handler, + IRQF_ONESHOT, dev_name(dev), + rdev); + if (ret) + return dev_err_probe(dev, ret, "Failed to register interrupt\n"); + } + + return 0; +} + +static int rt6190_runtime_suspend(struct device *dev) +{ + struct rt6190_data *data = dev_get_drvdata(dev); + struct regmap *regmap = data->regmap; + + if (!data->enable_gpio) + return 0; + + regcache_cache_only(regmap, true); + regcache_mark_dirty(regmap); + + gpiod_set_value(data->enable_gpio, 0); + + return 0; +} + +static int rt6190_runtime_resume(struct device *dev) +{ + struct rt6190_data *data = dev_get_drvdata(dev); + struct regmap *regmap = data->regmap; + + if (!data->enable_gpio) + return 0; + + gpiod_set_value(data->enable_gpio, 1); + usleep_range(RT6190_EN_TIME_US, RT6190_EN_TIME_US * 2); + + regcache_cache_only(regmap, false); + return regcache_sync(regmap); +} + +static const struct dev_pm_ops __maybe_unused rt6190_dev_pm = { + RUNTIME_PM_OPS(rt6190_runtime_suspend, rt6190_runtime_resume, NULL) +}; + +static const struct of_device_id rt6190_of_dev_table[] = { + { .compatible = "richtek,rt6190" }, + {} +}; +MODULE_DEVICE_TABLE(of, rt6190_of_dev_table); + +static struct i2c_driver rt6190_driver = { + .driver = { + .name = "rt6190", + .of_match_table = rt6190_of_dev_table, + .pm = pm_ptr(&rt6190_dev_pm), + }, + .probe_new = rt6190_probe, +}; +module_i2c_driver(rt6190_driver); + +MODULE_DESCRIPTION("Richtek RT6190 regulator driver"); +MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/stm32-vrefbuf.c b/drivers/regulator/stm32-vrefbuf.c index 30ea3bc8ca19..7a454b7b6eab 100644 --- a/drivers/regulator/stm32-vrefbuf.c +++ b/drivers/regulator/stm32-vrefbuf.c @@ -210,7 +210,7 @@ static int stm32_vrefbuf_probe(struct platform_device *pdev) pdev->dev.of_node, &stm32_vrefbuf_regu); - rdev = regulator_register(&stm32_vrefbuf_regu, &config); + rdev = regulator_register(&pdev->dev, &stm32_vrefbuf_regu, &config); if (IS_ERR(rdev)) { ret = PTR_ERR(rdev); dev_err(&pdev->dev, "register failed with error %d\n", ret); diff --git a/drivers/regulator/sy8106a-regulator.c b/drivers/regulator/sy8106a-regulator.c index c119f85259a5..b10bd99768a3 100644 --- a/drivers/regulator/sy8106a-regulator.c +++ b/drivers/regulator/sy8106a-regulator.c @@ -123,7 +123,7 @@ static int sy8106a_i2c_probe(struct i2c_client *i2c) return 0; } -static const struct of_device_id __maybe_unused sy8106a_i2c_of_match[] = { +static const struct of_device_id sy8106a_i2c_of_match[] = { { .compatible = "silergy,sy8106a" }, { }, }; @@ -138,7 +138,7 @@ MODULE_DEVICE_TABLE(i2c, sy8106a_i2c_id); static struct i2c_driver sy8106a_regulator_driver = { .driver = { .name = "sy8106a", - .of_match_table = of_match_ptr(sy8106a_i2c_of_match), + .of_match_table = sy8106a_i2c_of_match, }, .probe_new = sy8106a_i2c_probe, .id_table = sy8106a_i2c_id, diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c index 5e915cf307b3..2a81519bdf67 100644 --- a/drivers/regulator/sy8824x.c +++ b/drivers/regulator/sy8824x.c @@ -233,7 +233,7 @@ MODULE_DEVICE_TABLE(i2c, sy8824_id); static struct i2c_driver sy8824_regulator_driver = { .driver = { .name = "sy8824-regulator", - .of_match_table = of_match_ptr(sy8824_dt_ids), + .of_match_table = sy8824_dt_ids, }, .probe_new = sy8824_i2c_probe, .id_table = sy8824_id, diff --git a/drivers/regulator/sy8827n.c b/drivers/regulator/sy8827n.c index 7d5d9f879ce3..936a94b6df5b 100644 --- a/drivers/regulator/sy8827n.c +++ b/drivers/regulator/sy8827n.c @@ -170,7 +170,6 @@ static int sy8827n_i2c_probe(struct i2c_client *client) return ret; } -#ifdef CONFIG_OF static const struct of_device_id sy8827n_dt_ids[] = { { .compatible = "silergy,sy8827n", @@ -178,7 +177,6 @@ static const struct of_device_id sy8827n_dt_ids[] = { { } }; MODULE_DEVICE_TABLE(of, sy8827n_dt_ids); -#endif static const struct i2c_device_id sy8827n_id[] = { { "sy8827n", }, @@ -189,7 +187,7 @@ MODULE_DEVICE_TABLE(i2c, sy8827n_id); static struct i2c_driver sy8827n_regulator_driver = { .driver = { .name = "sy8827n-regulator", - .of_match_table = of_match_ptr(sy8827n_dt_ids), + .of_match_table = sy8827n_dt_ids, }, .probe_new = sy8827n_i2c_probe, .id_table = sy8827n_id, diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c index 85e3326b99eb..152c5ad6709c 100644 --- a/drivers/regulator/tps51632-regulator.c +++ b/drivers/regulator/tps51632-regulator.c @@ -247,8 +247,7 @@ static struct tps51632_regulator_platform_data * } #endif -static int tps51632_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int tps51632_probe(struct i2c_client *client) { struct tps51632_regulator_platform_data *pdata; struct regulator_dev *rdev; @@ -354,7 +353,7 @@ static struct i2c_driver tps51632_i2c_driver = { .name = "tps51632", .of_match_table = of_match_ptr(tps51632_of_match), }, - .probe = tps51632_probe, + .probe_new = tps51632_probe, .id_table = tps51632_id, }; diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index 7c697bdf344e..da1b2b1341ae 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -322,9 +322,9 @@ static const struct of_device_id tps62360_of_match[] = { MODULE_DEVICE_TABLE(of, tps62360_of_match); #endif -static int tps62360_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int tps62360_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct regulator_config config = { }; struct tps62360_regulator_platform_data *pdata; struct regulator_dev *rdev; @@ -497,7 +497,7 @@ static struct i2c_driver tps62360_i2c_driver = { .name = "tps62360", .of_match_table = of_match_ptr(tps62360_of_match), }, - .probe = tps62360_probe, + .probe_new = tps62360_probe, .shutdown = tps62360_shutdown, .id_table = tps62360_id, }; diff --git a/drivers/regulator/tps6286x-regulator.c b/drivers/regulator/tps6286x-regulator.c index e29deda30d75..207ac1d1d88d 100644 --- a/drivers/regulator/tps6286x-regulator.c +++ b/drivers/regulator/tps6286x-regulator.c @@ -111,8 +111,7 @@ static const struct of_device_id tps6286x_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, tps6286x_dt_ids); -static int tps6286x_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int tps6286x_i2c_probe(struct i2c_client *i2c) { struct device *dev = &i2c->dev; struct regulator_config config = {}; @@ -150,7 +149,7 @@ static struct i2c_driver tps6286x_regulator_driver = { .name = "tps6286x", .of_match_table = of_match_ptr(tps6286x_dt_ids), }, - .probe = tps6286x_i2c_probe, + .probe_new = tps6286x_i2c_probe, .id_table = tps6286x_i2c_id, }; diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index d24333344f93..680a57ff0837 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -257,9 +257,9 @@ static struct tps_driver_data tps65023_drv_data = { .core_regulator = TPS65023_DCDC_1, }; -static int tps_65023_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int tps_65023_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct regulator_init_data *init_data = dev_get_platdata(&client->dev); struct regulator_config config = { }; struct tps_pmic *tps; @@ -336,7 +336,7 @@ static struct i2c_driver tps_65023_i2c_driver = { .name = "tps65023", .of_match_table = of_match_ptr(tps65023_of_match), }, - .probe = tps_65023_probe, + .probe_new = tps_65023_probe, .id_table = tps_65023_id, }; diff --git a/drivers/regulator/userspace-consumer.c b/drivers/regulator/userspace-consumer.c index 8ca28664776e..402c8037cf39 100644 --- a/drivers/regulator/userspace-consumer.c +++ b/drivers/regulator/userspace-consumer.c @@ -14,6 +14,7 @@ #include <linux/err.h> #include <linux/mutex.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> #include <linux/regulator/userspace-consumer.h> @@ -24,6 +25,7 @@ struct userspace_consumer_data { struct mutex lock; bool enabled; + bool no_autoswitch; int num_supplies; struct regulator_bulk_data *supplies; @@ -96,19 +98,50 @@ static struct attribute *attributes[] = { NULL, }; +static umode_t attr_visible(struct kobject *kobj, struct attribute *attr, int idx) +{ + struct device *dev = kobj_to_dev(kobj); + struct userspace_consumer_data *data = dev_get_drvdata(dev); + + /* If a name hasn't been set, don't bother with the attribute */ + if (attr == &dev_attr_name.attr && !data->name) + return 0; + + return attr->mode; +} + static const struct attribute_group attr_group = { .attrs = attributes, + .is_visible = attr_visible, }; static int regulator_userspace_consumer_probe(struct platform_device *pdev) { + struct regulator_userspace_consumer_data tmpdata; struct regulator_userspace_consumer_data *pdata; struct userspace_consumer_data *drvdata; int ret; pdata = dev_get_platdata(&pdev->dev); - if (!pdata) + if (!pdata) { + if (!pdev->dev.of_node) + return -EINVAL; + + pdata = &tmpdata; + memset(pdata, 0, sizeof(*pdata)); + + pdata->no_autoswitch = true; + pdata->num_supplies = 1; + pdata->supplies = devm_kzalloc(&pdev->dev, sizeof(*pdata->supplies), GFP_KERNEL); + if (!pdata->supplies) + return -ENOMEM; + pdata->supplies[0].supply = "vout"; + } + + if (pdata->num_supplies < 1) { + dev_err(&pdev->dev, "At least one supply required\n"); return -EINVAL; + } drvdata = devm_kzalloc(&pdev->dev, sizeof(struct userspace_consumer_data), @@ -119,21 +152,24 @@ static int regulator_userspace_consumer_probe(struct platform_device *pdev) drvdata->name = pdata->name; drvdata->num_supplies = pdata->num_supplies; drvdata->supplies = pdata->supplies; + drvdata->no_autoswitch = pdata->no_autoswitch; mutex_init(&drvdata->lock); - ret = devm_regulator_bulk_get(&pdev->dev, drvdata->num_supplies, - drvdata->supplies); + ret = devm_regulator_bulk_get_exclusive(&pdev->dev, drvdata->num_supplies, + drvdata->supplies); if (ret) { dev_err(&pdev->dev, "Failed to get supplies: %d\n", ret); return ret; } + platform_set_drvdata(pdev, drvdata); + ret = sysfs_create_group(&pdev->dev.kobj, &attr_group); if (ret != 0) return ret; - if (pdata->init_on) { + if (pdata->init_on && !pdata->no_autoswitch) { ret = regulator_bulk_enable(drvdata->num_supplies, drvdata->supplies); if (ret) { @@ -143,8 +179,12 @@ static int regulator_userspace_consumer_probe(struct platform_device *pdev) } } - drvdata->enabled = pdata->init_on; - platform_set_drvdata(pdev, drvdata); + ret = regulator_is_enabled(pdata->supplies[0].consumer); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to get regulator status\n"); + goto err_enable; + } + drvdata->enabled = !!ret; return 0; @@ -160,17 +200,23 @@ static int regulator_userspace_consumer_remove(struct platform_device *pdev) sysfs_remove_group(&pdev->dev.kobj, &attr_group); - if (data->enabled) + if (data->enabled && !data->no_autoswitch) regulator_bulk_disable(data->num_supplies, data->supplies); return 0; } +static const struct of_device_id regulator_userspace_consumer_of_match[] = { + { .compatible = "regulator-output", }, + {}, +}; + static struct platform_driver regulator_userspace_consumer_driver = { .probe = regulator_userspace_consumer_probe, .remove = regulator_userspace_consumer_remove, .driver = { .name = "reg-userspace-consumer", + .of_match_table = regulator_userspace_consumer_of_match, }, }; diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index ee3b4a014611..39b666b40ea6 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -244,9 +244,13 @@ int regulator_disable_deferred(struct regulator *regulator, int ms); int __must_check regulator_bulk_get(struct device *dev, int num_consumers, struct regulator_bulk_data *consumers); +int __must_check of_regulator_bulk_get_all(struct device *dev, struct device_node *np, + struct regulator_bulk_data **consumers); int __must_check devm_regulator_bulk_get(struct device *dev, int num_consumers, struct regulator_bulk_data *consumers); void devm_regulator_bulk_put(struct regulator_bulk_data *consumers); +int __must_check devm_regulator_bulk_get_exclusive(struct device *dev, int num_consumers, + struct regulator_bulk_data *consumers); int __must_check devm_regulator_bulk_get_const( struct device *dev, int num_consumers, const struct regulator_bulk_data *in_consumers, @@ -479,6 +483,12 @@ static inline int devm_regulator_bulk_get(struct device *dev, int num_consumers, return 0; } +static inline int of_regulator_bulk_get_all(struct device *dev, struct device_node *np, + struct regulator_bulk_data **consumers) +{ + return 0; +} + static inline int regulator_bulk_enable(int num_consumers, struct regulator_bulk_data *consumers) { diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index f9a7461e72b8..d3b4a3d4514a 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -687,7 +687,8 @@ static inline int regulator_err2notif(int err) struct regulator_dev * -regulator_register(const struct regulator_desc *regulator_desc, +regulator_register(struct device *dev, + const struct regulator_desc *regulator_desc, const struct regulator_config *config); struct regulator_dev * devm_regulator_register(struct device *dev, diff --git a/include/linux/regulator/mt6357-regulator.h b/include/linux/regulator/mt6357-regulator.h new file mode 100644 index 000000000000..238b1ee77ea6 --- /dev/null +++ b/include/linux/regulator/mt6357-regulator.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2022 MediaTek Inc. + */ + +#ifndef __LINUX_REGULATOR_MT6357_H +#define __LINUX_REGULATOR_MT6357_H + +enum { + /* Bucks */ + MT6357_ID_VCORE, + MT6357_ID_VMODEM, + MT6357_ID_VPA, + MT6357_ID_VPROC, + MT6357_ID_VS1, + + /* LDOs */ + MT6357_ID_VAUX18, + MT6357_ID_VAUD28, + MT6357_ID_VCAMA, + MT6357_ID_VCAMD, + MT6357_ID_VCAMIO, + MT6357_ID_VCN18, + MT6357_ID_VCN28, + MT6357_ID_VCN33_BT, + MT6357_ID_VCN33_WIFI, + MT6357_ID_VDRAM, + MT6357_ID_VEFUSE, + MT6357_ID_VEMC, + MT6357_ID_VFE28, + MT6357_ID_VIBR, + MT6357_ID_VIO18, + MT6357_ID_VIO28, + MT6357_ID_VLDO28, + MT6357_ID_VMC, + MT6357_ID_VMCH, + MT6357_ID_VRF12, + MT6357_ID_VRF18, + MT6357_ID_VSIM1, + MT6357_ID_VSIM2, + MT6357_ID_VSRAM_OTHERS, + MT6357_ID_VSRAM_PROC, + MT6357_ID_VUSB33, + MT6357_ID_VXO22, + + MT6357_ID_RG_MAX, +}; + +#define MT6357_MAX_REGULATOR MT6357_ID_RG_MAX + +#endif /* __LINUX_REGULATOR_MT6357_H */ diff --git a/include/linux/regulator/userspace-consumer.h b/include/linux/regulator/userspace-consumer.h index b5dba0628951..2249ee697f8b 100644 --- a/include/linux/regulator/userspace-consumer.h +++ b/include/linux/regulator/userspace-consumer.h @@ -21,6 +21,7 @@ struct regulator_userspace_consumer_data { struct regulator_bulk_data *supplies; bool init_on; + bool no_autoswitch; }; #endif /* __REGULATOR_PLATFORM_CONSUMER_H_ */ diff --git a/include/linux/soc/qcom/smd-rpm.h b/include/linux/soc/qcom/smd-rpm.h index 3ab8c07f71c0..62de54992e49 100644 --- a/include/linux/soc/qcom/smd-rpm.h +++ b/include/linux/soc/qcom/smd-rpm.h @@ -19,6 +19,7 @@ struct qcom_smd_rpm; #define QCOM_SMD_RPM_CLK_BUF_A 0x616B6C63 #define QCOM_SMD_RPM_LDOA 0x616f646c #define QCOM_SMD_RPM_LDOB 0x626F646C +#define QCOM_SMD_RPM_LDOE 0x656f646c #define QCOM_SMD_RPM_RWCX 0x78637772 #define QCOM_SMD_RPM_RWMX 0x786d7772 #define QCOM_SMD_RPM_RWLC 0x636c7772 @@ -32,6 +33,7 @@ struct qcom_smd_rpm; #define QCOM_SMD_RPM_QUP_CLK 0x707571 #define QCOM_SMD_RPM_SMPA 0x61706d73 #define QCOM_SMD_RPM_SMPB 0x62706d73 +#define QCOM_SMD_RPM_SMPE 0x65706d73 #define QCOM_SMD_RPM_SPDM 0x63707362 #define QCOM_SMD_RPM_VSA 0x00617376 #define QCOM_SMD_RPM_MMAXI_CLK 0x69786d6d diff --git a/lib/test_linear_ranges.c b/lib/test_linear_ranges.c index 676e0b8abcdd..c18f9c0f1f25 100644 --- a/lib/test_linear_ranges.c +++ b/lib/test_linear_ranges.c @@ -107,17 +107,8 @@ static const unsigned int range2_vals[] = { RANGE2_MIN, RANGE2_MIN + #define SMALLEST_VAL RANGE1_MIN static struct linear_range testr[] = { - { - .min = RANGE1_MIN, - .min_sel = RANGE1_MIN_SEL, - .max_sel = RANGE1_MAX_SEL, - .step = RANGE1_STEP, - }, { - .min = RANGE2_MIN, - .min_sel = RANGE2_MIN_SEL, - .max_sel = RANGE2_MAX_SEL, - .step = RANGE2_STEP - }, + LINEAR_RANGE(RANGE1_MIN, RANGE1_MIN_SEL, RANGE1_MAX_SEL, RANGE1_STEP), + LINEAR_RANGE(RANGE2_MIN, RANGE2_MIN_SEL, RANGE2_MAX_SEL, RANGE2_STEP), }; static void range_test_get_value(struct kunit *test) |