diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-13 09:56:25 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-13 09:56:25 -0700 |
commit | 1724e02e024adf5a17da12fad6819e30d304da7d (patch) | |
tree | ba3067080cc97427b5263365702ac335602d184f | |
parent | 57218d7f2e87069f73c7a841b6ed6c1cc7acf616 (diff) | |
parent | c6e70a6fd5ceff381059e600156d78c1b94b7c60 (diff) | |
download | linux-1724e02e024adf5a17da12fad6819e30d304da7d.tar.bz2 |
Merge tag 'regulator-v5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator
Pull regulator updates from Mark Brown:
"This is a fairly small release for the regulator API, there's quite a
few new devices supported and some important improvements around
coupled regulators in the core but mostly just small fixes and
improvements otherwise.
Summary:
- Fixes and cleanups around the handling of coupled regulators.
- A special driver for some Raspberry Pi panels with some unusually
custom stuff around them.
- Support for Qualcomm PM660/PM660L, PM8950 and PM8953, Richtek
RT4801 and RTMV20, Rohm BD9576MUF and BD9573MUF"
* tag 'regulator-v5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (89 commits)
regulator: bd9576: Fix print
regulator: bd9576: fix regulator binfdings dt node names
dt-bindings: regulator: document pm8950 and pm8953 smd regulators
regulator: qcom_smd: add pm8953 regulators
regulator: Make constraint debug processing conditional on DEBUG
regulator: qcom: labibb: Constify static structs
regulator: dt-bindings: Document the PM660/PM660L PMICs entries
regulator: qcom_smd: Add PM660/PM660L regulator support
regulator: dt-bindings: Document the PM660/660L SPMI PMIC entries
regulator: qcom_spmi: Add PM660/PM660L regulators
regulator: qcom_spmi: Add support for new regulator types
regulator: core: Enlarge max OF property name length to 64 chars
regulator: tps65910: use regmap accessors
regulator: rtmv20: Add missing regcache cache only before marked as dirty
regulator: rtmv20: Update DT binding document and property name parsing
regulator: rtmv20: Add DT-binding document for Richtek RTMV20
regulator: rtmv20: Adds support for Richtek RTMV20 load switch regulator
regulator: resolve supply after creating regulator
regulator: print symbolic errors in kernel messages
regulator: print state at boot
...
77 files changed, 3498 insertions, 1033 deletions
diff --git a/Documentation/devicetree/bindings/regulator/mp886x.txt b/Documentation/devicetree/bindings/regulator/mp886x.txt deleted file mode 100644 index 551867829459..000000000000 --- a/Documentation/devicetree/bindings/regulator/mp886x.txt +++ /dev/null @@ -1,27 +0,0 @@ -Monolithic Power Systems MP8867/MP8869 voltage regulator - -Required properties: -- compatible: Must be one of the following. - "mps,mp8867" - "mps,mp8869" -- reg: I2C slave address. -- enable-gpios: enable gpios. -- mps,fb-voltage-divider: An array of two integers containing the resistor - values R1 and R2 of the feedback voltage divider in kilo ohms. - -Any property defined as part of the core regulator binding, defined in -./regulator.txt, can also be used. - -Example: - - vcpu: regulator@62 { - compatible = "mps,mp8869"; - regulator-name = "vcpu"; - regulator-min-microvolt = <700000>; - regulator-max-microvolt = <850000>; - regulator-always-on; - regulator-boot-on; - enable-gpios = <&porta 1 GPIO_ACTIVE_LOW>; - mps,fb-voltage-divider = <80 240>; - reg = <0x62>; - }; diff --git a/Documentation/devicetree/bindings/regulator/mps,mp886x.yaml b/Documentation/devicetree/bindings/regulator/mps,mp886x.yaml new file mode 100644 index 000000000000..ba175b30f468 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/mps,mp886x.yaml @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/mps,mp886x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Monolithic Power Systems MP8867/MP8869 voltage regulator + +maintainers: + - Jisheng Zhang <jszhang@kernel.org> + +allOf: + - $ref: regulator.yaml# + +properties: + compatible: + enum: + - mps,mp8867 + - mps,mp8869 + + reg: + maxItems: 1 + + enable-gpios: + description: GPIO to enable/disable the regulator. + maxItems: 1 + + mps,fb-voltage-divider: + description: An array of two integers containing the resistor + values R1 and R2 of the feedback voltage divider in kilo ohms. + $ref: "/schemas/types.yaml#/definitions/uint32-array" + maxItems: 2 + + mps,switch-frequency-hz: + description: The valid switch frequency in Hertz. + enum: [500000, 750000, 1000000, 1250000, 1500000] + +required: + - compatible + - reg + - enable-gpios + - mps,fb-voltage-divider + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + i2c { + #address-cells = <1>; + #size-cells = <0>; + regulator@62 { + compatible = "mps,mp8869"; + regulator-name = "vcpu"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1150000>; + enable-gpios = <&porta 1 GPIO_ACTIVE_LOW>; + mps,fb-voltage-divider = <80 240>; + reg = <0x62>; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/regulator/mt6360-regulator.yaml b/Documentation/devicetree/bindings/regulator/mt6360-regulator.yaml new file mode 100644 index 000000000000..a462d99a25cc --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/mt6360-regulator.yaml @@ -0,0 +1,113 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/mt6360-regulator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MT6360 Regulator from MediaTek Integrated + +maintainers: + - Gene Chen <gene_chen@richtek.com> + +description: | + list of regulators provided by this controller, must be named + after their hardware counterparts buck1/2 or ldo1/2/3/5/6/7 + +properties: + compatible: + const: mediatek,mt6360-regulator + + LDO_VIN1-supply: + description: Input supply phandle(s) for LDO1/2/3 + LDO_VIN2-supply: + description: Input supply phandle(s) for LDO5 + LDO_VIN3-supply: + description: Input supply phandle(s) for LDO6/7 + +patternProperties: + "^buck[12]$": + $ref: "regulator.yaml#" + + "^ldo[123567]$": + $ref: "regulator.yaml#" + +required: + - compatible + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/irq.h> + #include <dt-bindings/regulator/mediatek,mt6360-regulator.h> + regulator { + compatible = "mediatek,mt6360-regulator"; + LDO_VIN3-supply = <&BUCK2>; + buck1 { + regulator-compatible = "BUCK1"; + regulator-name = "mt6360,buck1"; + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <1300000>; + regulator-allowed-modes = <MT6360_OPMODE_NORMAL + MT6360_OPMODE_LP + MT6360_OPMODE_ULP>; + }; + BUCK2: buck2 { + regulator-compatible = "BUCK2"; + regulator-name = "mt6360,buck2"; + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <1300000>; + regulator-allowed-modes = <MT6360_OPMODE_NORMAL + MT6360_OPMODE_LP + MT6360_OPMODE_ULP>; + }; + ldo6 { + regulator-compatible = "LDO6"; + regulator-name = "mt6360,ldo6"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <2100000>; + regulator-allowed-modes = <MT6360_OPMODE_NORMAL + MT6360_OPMODE_LP>; + }; + ldo7 { + regulator-compatible = "LDO7"; + regulator-name = "mt6360,ldo7"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <2100000>; + regulator-allowed-modes = <MT6360_OPMODE_NORMAL + 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"; + regulator-name = "mt6360,ldo2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3600000>; + regulator-allowed-modes = <MT6360_OPMODE_NORMAL + MT6360_OPMODE_LP>; + }; + ldo3 { + regulator-compatible = "LDO3"; + regulator-name = "mt6360,ldo3"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3600000>; + regulator-allowed-modes = <MT6360_OPMODE_NORMAL + MT6360_OPMODE_LP>; + }; + ldo5 { + regulator-compatible = "LDO5"; + regulator-name = "mt6360,ldo5"; + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3600000>; + regulator-allowed-modes = <MT6360_OPMODE_NORMAL + MT6360_OPMODE_LP>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/regulator/pfuze100.txt b/Documentation/devicetree/bindings/regulator/pfuze100.txt deleted file mode 100644 index 4d3b12b92cb3..000000000000 --- a/Documentation/devicetree/bindings/regulator/pfuze100.txt +++ /dev/null @@ -1,394 +0,0 @@ -PFUZE100 family of regulators - -Required properties: -- compatible: "fsl,pfuze100", "fsl,pfuze200", "fsl,pfuze3000", "fsl,pfuze3001" -- reg: I2C slave address - -Optional properties: -- fsl,pfuze-support-disable-sw: Boolean, if present disable all unused switch - regulators to save power consumption. Attention, ensure that all important - regulators (e.g. DDR ref, DDR supply) has set the "regulator-always-on" - property. If not present, the switched regulators are always on and can't be - disabled. This binding is a workaround to keep backward compatibility with - old dtb's which rely on the fact that the switched regulators are always on - and don't mark them explicit as "regulator-always-on". -- fsl,pmic-stby-poweroff: if present, configure the PMIC to shutdown all - power rails when PMIC_STBY_REQ line is asserted during the power off sequence. - Use this option if the SoC should be powered off by external power - management IC (PMIC) on PMIC_STBY_REQ signal. - As opposite to PMIC_STBY_REQ boards can implement PMIC_ON_REQ signal. - -Required child node: -- regulators: This is the list of child nodes that specify the regulator - initialization data for defined regulators. Please refer to below doc - Documentation/devicetree/bindings/regulator/regulator.txt. - - The valid names for regulators are: - --PFUZE100 - sw1ab,sw1c,sw2,sw3a,sw3b,sw4,swbst,vsnvs,vrefddr,vgen1~vgen6 - --PFUZE200 - sw1ab,sw2,sw3a,sw3b,swbst,vsnvs,vrefddr,vgen1~vgen6,coin - --PFUZE3000 - sw1a,sw1b,sw2,sw3,swbst,vsnvs,vrefddr,vldo1,vldo2,vccsd,v33,vldo3,vldo4 - --PFUZE3001 - sw1,sw2,sw3,vsnvs,vldo1,vldo2,vccsd,v33,vldo3,vldo4 - -Each regulator is defined using the standard binding for regulators. - -Example 1: PFUZE100 - - pfuze100: pmic@8 { - compatible = "fsl,pfuze100"; - reg = <0x08>; - - regulators { - sw1a_reg: sw1ab { - regulator-min-microvolt = <300000>; - regulator-max-microvolt = <1875000>; - regulator-boot-on; - regulator-always-on; - regulator-ramp-delay = <6250>; - }; - - sw1c_reg: sw1c { - regulator-min-microvolt = <300000>; - regulator-max-microvolt = <1875000>; - regulator-boot-on; - regulator-always-on; - }; - - sw2_reg: sw2 { - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - }; - - sw3a_reg: sw3a { - regulator-min-microvolt = <400000>; - regulator-max-microvolt = <1975000>; - regulator-boot-on; - regulator-always-on; - }; - - sw3b_reg: sw3b { - regulator-min-microvolt = <400000>; - regulator-max-microvolt = <1975000>; - regulator-boot-on; - regulator-always-on; - }; - - sw4_reg: sw4 { - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <3300000>; - }; - - swbst_reg: swbst { - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5150000>; - }; - - snvs_reg: vsnvs { - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <3000000>; - regulator-boot-on; - regulator-always-on; - }; - - vref_reg: vrefddr { - regulator-boot-on; - regulator-always-on; - }; - - vgen1_reg: vgen1 { - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <1550000>; - }; - - vgen2_reg: vgen2 { - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <1550000>; - }; - - vgen3_reg: vgen3 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - vgen4_reg: vgen4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - vgen5_reg: vgen5 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - vgen6_reg: vgen6 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - }; - }; - - -Example 2: PFUZE200 - - pfuze200: pmic@8 { - compatible = "fsl,pfuze200"; - reg = <0x08>; - - regulators { - sw1a_reg: sw1ab { - regulator-min-microvolt = <300000>; - regulator-max-microvolt = <1875000>; - regulator-boot-on; - regulator-always-on; - regulator-ramp-delay = <6250>; - }; - - sw2_reg: sw2 { - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - }; - - sw3a_reg: sw3a { - regulator-min-microvolt = <400000>; - regulator-max-microvolt = <1975000>; - regulator-boot-on; - regulator-always-on; - }; - - sw3b_reg: sw3b { - regulator-min-microvolt = <400000>; - regulator-max-microvolt = <1975000>; - regulator-boot-on; - regulator-always-on; - }; - - swbst_reg: swbst { - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5150000>; - }; - - snvs_reg: vsnvs { - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <3000000>; - regulator-boot-on; - regulator-always-on; - }; - - vref_reg: vrefddr { - regulator-boot-on; - regulator-always-on; - }; - - vgen1_reg: vgen1 { - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <1550000>; - }; - - vgen2_reg: vgen2 { - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <1550000>; - }; - - vgen3_reg: vgen3 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - }; - - vgen4_reg: vgen4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - vgen5_reg: vgen5 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - vgen6_reg: vgen6 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - coin_reg: coin { - regulator-min-microvolt = <2500000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - }; - }; - -Example 3: PFUZE3000 - - pfuze3000: pmic@8 { - compatible = "fsl,pfuze3000"; - reg = <0x08>; - - regulators { - sw1a_reg: sw1a { - regulator-min-microvolt = <700000>; - regulator-max-microvolt = <1475000>; - regulator-boot-on; - regulator-always-on; - regulator-ramp-delay = <6250>; - }; - /* use sw1c_reg to align with pfuze100/pfuze200 */ - sw1c_reg: sw1b { - regulator-min-microvolt = <700000>; - regulator-max-microvolt = <1475000>; - regulator-boot-on; - regulator-always-on; - regulator-ramp-delay = <6250>; - }; - - sw2_reg: sw2 { - regulator-min-microvolt = <2500000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - }; - - sw3a_reg: sw3 { - regulator-min-microvolt = <900000>; - regulator-max-microvolt = <1650000>; - regulator-boot-on; - regulator-always-on; - }; - - swbst_reg: swbst { - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5150000>; - }; - - snvs_reg: vsnvs { - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <3000000>; - regulator-boot-on; - regulator-always-on; - }; - - vref_reg: vrefddr { - regulator-boot-on; - regulator-always-on; - }; - - vgen1_reg: vldo1 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - vgen2_reg: vldo2 { - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <1550000>; - }; - - vgen3_reg: vccsd { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - vgen4_reg: v33 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <3300000>; - }; - - vgen5_reg: vldo3 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - vgen6_reg: vldo4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - }; - }; - -Example 4: PFUZE 3001 - - pfuze3001: pmic@8 { - compatible = "fsl,pfuze3001"; - reg = <0x08>; - - regulators { - sw1_reg: sw1 { - regulator-min-microvolt = <700000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - }; - - sw2_reg: sw2 { - regulator-min-microvolt = <1500000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - }; - - sw3_reg: sw3 { - regulator-min-microvolt = <900000>; - regulator-max-microvolt = <1650000>; - regulator-boot-on; - regulator-always-on; - }; - - snvs_reg: vsnvs { - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <3000000>; - regulator-boot-on; - regulator-always-on; - }; - - vgen1_reg: vldo1 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - vgen2_reg: vldo2 { - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <1550000>; - regulator-always-on; - }; - - vgen3_reg: vccsd { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - vgen4_reg: v33 { - regulator-min-microvolt = <2850000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - vgen5_reg: vldo3 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - vgen6_reg: vldo4 { - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/regulator/pfuze100.yaml b/Documentation/devicetree/bindings/regulator/pfuze100.yaml new file mode 100644 index 000000000000..c6de49685db7 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/pfuze100.yaml @@ -0,0 +1,186 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/pfuze100.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: PFUZE100 family of regulators + +maintainers: + - Robin Gong <yibin.gong@nxp.com> + +description: | + The valid names for regulators are: + --PFUZE100 + sw1ab,sw1c,sw2,sw3a,sw3b,sw4,swbst,vsnvs,vrefddr,vgen1~vgen6 + --PFUZE200 + sw1ab,sw2,sw3a,sw3b,swbst,vsnvs,vrefddr,vgen1~vgen6,coin + --PFUZE3000 + sw1a,sw1b,sw2,sw3,swbst,vsnvs,vrefddr,vldo1,vldo2,vccsd,v33,vldo3,vldo4 + --PFUZE3001 + sw1,sw2,sw3,vsnvs,vldo1,vldo2,vccsd,v33,vldo3,vldo4 + + Each regulator is defined using the standard binding for regulators. + +properties: + $nodename: + pattern: "^pmic@[0-9]$" + + compatible: + enum: + - fsl,pfuze100 + - fsl,pfuze200 + - fsl,pfuze3000 + - fsl,pfuze3001 + + reg: + maxItems: 1 + + fsl,pfuze-support-disable-sw: + $ref: /schemas/types.yaml#/definitions/flag + description: | + Boolean, if present disable all unused switch regulators to save power + consumption. Attention, ensure that all important regulators + (e.g. DDR ref, DDR supply) has set the "regulator-always-on" property. + If not present, the switched regulators are always on and can't be + disabled. This binding is a workaround to keep backward compatibility + with old dtb's which rely on the fact that the switched regulators are + always on and don't mark them explicit as "regulator-always-on". + + fsl,pmic-stby-poweroff: + $ref: /schemas/types.yaml#/definitions/flag + description: | + if present, configure the PMIC to shutdown all + power rails when PMIC_STBY_REQ line is asserted during the power off sequence. + Use this option if the SoC should be powered off by external power management + IC (PMIC) on PMIC_STBY_REQ signal. + As opposite to PMIC_STBY_REQ boards can implement PMIC_ON_REQ signal. + + regulators: + type: object + description: | + list of regulators provided by this controller. + + patternProperties: + "^sw([1-4]|[1-4][a-c]|[1-4][a-c][a-c])$": + $ref: "regulator.yaml#" + type: object + + "^vgen[1-6]$": + $ref: "regulator.yaml#" + type: object + + "^(vsnvs|vref|vrefddr|swbst|coin)$": + $ref: "regulator.yaml#" + type: object + + additionalProperties: false + +required: + - compatible + - reg + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + pmic@8 { + compatible = "fsl,pfuze100"; + reg = <0x08>; + + regulators { + sw1a_reg: sw1ab { + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <1875000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <6250>; + }; + + sw1c_reg: sw1c { + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <1875000>; + regulator-boot-on; + regulator-always-on; + }; + + sw2_reg: sw2 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + sw3a_reg: sw3a { + regulator-min-microvolt = <400000>; + regulator-max-microvolt = <1975000>; + regulator-boot-on; + regulator-always-on; + }; + + sw3b_reg: sw3b { + regulator-min-microvolt = <400000>; + regulator-max-microvolt = <1975000>; + regulator-boot-on; + regulator-always-on; + }; + + sw4_reg: sw4 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + }; + + swbst_reg: swbst { + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5150000>; + }; + + snvs_reg: vsnvs { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <3000000>; + regulator-boot-on; + regulator-always-on; + }; + + vref_reg: vrefddr { + regulator-boot-on; + regulator-always-on; + }; + + vgen1_reg: vgen1 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1550000>; + }; + + vgen2_reg: vgen2 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1550000>; + }; + + vgen3_reg: vgen3 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + + vgen4_reg: vgen4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen5_reg: vgen5 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen6_reg: vgen6 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml index c0d7700afee7..a35c6cb9bf97 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml @@ -33,6 +33,10 @@ description: l12, l13, l14, l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, lvs1, lvs2, lvs3, 5vs1, 5vs2 + For pm8950 and pm8953, s1, s2, s3, s4, s5, s6, s7, l1, l2, l3, l4, l5, l6, + l7, l8, l9, l10, l11, l12, l13, l14, l15, l16, l17, l18, l19, l20, l21, l22, + l23 + For pm8994, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14, l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, l25, l26, l27, l28, l29, l30, l31, l32, lvs1, lvs2 @@ -41,6 +45,11 @@ description: l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14, l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, l25, l26, l27, l28, lvs1, lvs2 + For pm660, s1, s2, s3, s4, s5, s6, l1, l2, l3, l5, l6, l7, l8, l9, l10, l22, + l12, l13, l14, l15, l16, l17, l18, l19 + + For pm660l s1, s2, s3, s5, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, bob + For pma8084, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14, l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, l25, l26, l27, lvs1, lvs2, lvs3, lvs4, 5vs1 @@ -63,8 +72,11 @@ properties: - qcom,rpm-pm8916-regulators - qcom,rpm-pm8941-regulators - qcom,rpm-pm8950-regulators + - qcom,rpm-pm8953-regulators - qcom,rpm-pm8994-regulators - qcom,rpm-pm8998-regulators + - qcom,rpm-pm660-regulators + - qcom,rpm-pm660l-regulators - qcom,rpm-pma8084-regulators - qcom,rpm-pmi8994-regulators - qcom,rpm-pmi8998-regulators diff --git a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt index 8b005192f6e8..2b544059e029 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt @@ -12,6 +12,8 @@ Qualcomm SPMI Regulators "qcom,pm8950-regulators" "qcom,pm8994-regulators" "qcom,pmi8994-regulators" + "qcom,pm660-regulators" + "qcom,pm660l-regulators" "qcom,pms405-regulators" - interrupts: @@ -134,6 +136,35 @@ Qualcomm SPMI Regulators Definition: Reference to regulator supplying the input pin, as described in the data sheet. +- vdd_l1_l6_l7-supply: +- vdd_l2_l3-supply: +- vdd_l5-supply: +- vdd_l8_l9_l10_l11_l12_l13_l14-supply: +- vdd_l15_l16_l17_l18_l19-supply: +- vdd_s1-supply: +- vdd_s2-supply: +- vdd_s3-supply: +- vdd_s5-supply: +- vdd_s6-supply: + Usage: optional (pm660 only) + Value type: <phandle> + Definition: Reference to regulator supplying the input pin, as + described in the data sheet. + +- vdd_l1_l9_l10-supply: +- vdd_l2-supply: +- vdd_l3_l5_l7_l8-supply: +- vdd_l4_l6-supply: +- vdd_s1-supply: +- vdd_s2-supply: +- vdd_s3-supply: +- vdd_s4-supply: +- vdd_s5-supply: + Usage: optional (pm660l only) + Value type: <phandle> + Definition: Reference to regulator supplying the input pin, as + described in the data sheet. + - vdd_l1_l2-supply: - vdd_l3_l8-supply: - vdd_l4-supply: diff --git a/Documentation/devicetree/bindings/regulator/raspberrypi,7inch-touchscreen-panel-regulator.yaml b/Documentation/devicetree/bindings/regulator/raspberrypi,7inch-touchscreen-panel-regulator.yaml new file mode 100644 index 000000000000..0ae25d119b6f --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/raspberrypi,7inch-touchscreen-panel-regulator.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/raspberrypi,7inch-touchscreen-panel-regulator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: RaspberryPi 7" display ATTINY88-based regulator/backlight controller + +maintainers: + - Marek Vasut <marex@denx.de> + +description: | + The RaspberryPi 7" display has an ATTINY88-based regulator/backlight + controller on the PCB, which is used to turn the display unit on/off + and control the backlight. + +allOf: + - $ref: "regulator.yaml#" + +properties: + compatible: + const: raspberrypi,7inch-touchscreen-panel-regulator + + reg: + maxItems: 1 + +additionalProperties: false + +required: + - compatible + - reg + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + regulator@45 { + compatible = "raspberrypi,7inch-touchscreen-panel-regulator"; + reg = <0x45>; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/regulator/richtek,rt4801-regulator.yaml b/Documentation/devicetree/bindings/regulator/richtek,rt4801-regulator.yaml new file mode 100644 index 000000000000..235e593b3b2c --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/richtek,rt4801-regulator.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,rt4801-regulator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Richtek RT4801 Display Bias regulators + +maintainers: + - ChiYuan Huang <cy_huang@richtek.com> + +description: | + Regulator nodes should be named to DSVP and DSVN. The + definition for each of these nodes is defined using the standard + binding for regulators at + Documentation/devicetree/bindings/regulator/regulator.txt. + Datasheet is available at + https://www.richtek.com/assets/product_file/RT4801H/DS4801H-00.pdf + +#The valid names for RT4801 regulator nodes are: +#DSVP, DSVN + +properties: + compatible: + enum: + - richtek,rt4801 + + reg: + maxItems: 1 + + enable-gpios: + description: GPIOs to use to enable DSVP/DSVN regulator. + The first one is ENP to enable DSVP, and second one is ENM to enable DSVN. + Number of GPIO in the array list could be 1 or 2. + If only one gpio is specified, only one gpio used to control ENP/ENM. + Else both are spefied, DSVP/DSVN could be controlled individually. + Othersie, this property not specified. treat both as always-on regulator. + minItems: 1 + maxItems: 2 + +patternProperties: + "^DSV(P|N)$": + type: object + $ref: regulator.yaml# + description: + Properties for single display bias regulator. + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + rt4801@73 { + compatible = "richtek,rt4801"; + reg = <0x73>; + enable-gpios = <&gpio26 2 0>, <&gpio26 3 0>; + + dsvp: DSVP { + regulator-name = "rt4801,dsvp"; + regulator-min-microvolt = <4000000>; + regulator-max-microvolt = <6000000>; + regulator-boot-on; + }; + dsvn: DSVN { + regulator-name = "rt4801,dsvn"; + regulator-min-microvolt = <4000000>; + regulator-max-microvolt = <6000000>; + regulator-boot-on; + }; + + }; + }; diff --git a/Documentation/devicetree/bindings/regulator/richtek,rtmv20-regulator.yaml b/Documentation/devicetree/bindings/regulator/richtek,rtmv20-regulator.yaml new file mode 100644 index 000000000000..a8ccb5cb8d77 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/richtek,rtmv20-regulator.yaml @@ -0,0 +1,159 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/richtek,rtmv20-regulator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Richtek RTMV20 laser diode regulator + +maintainers: + - ChiYuan Huang <cy_huang@richtek.com> + +description: | + Richtek RTMV20 is a load switch current regulator that can supply up to 6A. + It is used to drive laser diode. There're two signals for chip controls + (Enable/Fail), Enable pin to turn chip on, and Fail pin as fault indication. + There're still four pins for camera control, two inputs (strobe and vsync), + the others for outputs (fsin1 and fsin2). Strobe input to start the current + supply, vsync input from IR camera, and fsin1/fsin2 output for the optional. + +properties: + compatible: + const: richtek,rtmv20 + + reg: + maxItems: 1 + + wakeup-source: true + + interrupts: + maxItems: 1 + + enable-gpios: + description: A connection of the 'enable' gpio line. + maxItems: 1 + + richtek,ld-pulse-delay-us: + description: | + load current pulse delay in microsecond after strobe pin pulse high. + minimum: 0 + maximum: 100000 + default: 0 + + richtek,ld-pulse-width-us: + description: | + Load current pulse width in microsecond after strobe pin pulse high. + minimum: 0 + maximum: 10000 + default: 1200 + + richtek,fsin1-delay-us: + description: | + Fsin1 pulse high delay in microsecond after vsync signal pulse high. + minimum: 0 + maximum: 100000 + default: 23000 + + richtek,fsin1-width-us: + description: | + Fsin1 pulse high width in microsecond after vsync signal pulse high. + minimum: 40 + maximum: 10000 + default: 160 + + richtek,fsin2-delay-us: + description: | + Fsin2 pulse high delay in microsecond after vsync signal pulse high. + minimum: 0 + maximum: 100000 + default: 23000 + + richtek,fsin2-width-us: + description: | + Fsin2 pulse high width in microsecond after vsync signal pulse high. + minimum: 40 + maximum: 10000 + default: 160 + + richtek,es-pulse-width-us: + description: Eye safety function pulse width limit in microsecond. + minimum: 0 + maximum: 10000 + default: 1200 + + richtek,es-ld-current-microamp: + description: Eye safety function load current limit in microamp. + minimum: 0 + maximum: 6000000 + default: 3000000 + + richtek,lbp-level-microvolt: + description: Low battery protection level in microvolt. + minimum: 2400000 + maximum: 3700000 + default: 2700000 + + richtek,lbp-enable: + description: Low battery protection function enable control. + type: boolean + + richtek,strobe-polarity-high: + description: Strobe pin active polarity control. + type: boolean + + richtek,vsync-polarity-high: + description: Vsync pin active polarity control. + type: boolean + + richtek,fsin-enable: + description: Fsin function enable control. + type: boolean + + richtek,fsin-output: + description: Fsin function output control. + type: boolean + + richtek,es-enable: + description: Eye safety function enable control. + type: boolean + + lsw: + description: load switch current regulator description. + type: object + $ref: "regulator.yaml#" + +required: + - compatible + - reg + - wakeup-source + - interrupts + - enable-gpios + - lsw + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/irq.h> + i2c { + #address-cells = <1>; + #size-cells = <0>; + + rtmv20@34 { + compatible = "richtek,rtmv20"; + reg = <0x34>; + wakeup-source; + interrupts-extended = <&gpio26 2 IRQ_TYPE_LEVEL_LOW>; + enable-gpios = <&gpio26 3 0>; + + richtek,strobe-polarity-high; + richtek,vsync-polarity-high; + + lsw { + regulator-name = "rtmv20,lsw"; + regulator-min-microamp = <0>; + regulator-max-microamp = <6000000>; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.yaml b/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.yaml index 19d9408d9c3b..f5e31196a646 100644 --- a/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.yaml @@ -93,6 +93,17 @@ patternProperties: # ---------------------------------------------------------------- # rest | not supported | not supported | not supported + # BD71837 power outputs can either be controlled by the PMIC internal + # hardware state machine or by software. If you need regulators to be + # turned ON/OFF for example based on PMIC_STBY_REQ line (which toggles + # PMIC HW state machine) - then you should set this property. + # Tradeoff is that then SW can't control the ON/OFF state for this + # regulator (other than invoking a PMIC state change). + rohm,no-regulator-enable-control: + description: | + Enable/Disable control of this regulator must be left to the + PMIC hardware state machine. + type: boolean required: - regulator-name diff --git a/Documentation/devicetree/bindings/regulator/rohm,bd71847-regulator.yaml b/Documentation/devicetree/bindings/regulator/rohm,bd71847-regulator.yaml index 07256a4b50b9..eeac32cd15d6 100644 --- a/Documentation/devicetree/bindings/regulator/rohm,bd71847-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/rohm,bd71847-regulator.yaml @@ -88,6 +88,17 @@ patternProperties: # ---------------------------------------------------------------- # rest | not supported | not supported | not supported + # BD718(47/50) power outputs can either be controlled by the PMIC internal + # hardware state machine or by software. If you need regulators to be + # turned ON/OFF for example based on PMIC_STBY_REQ line (which toggles + # PMIC HW state machine) - then you should set this property. + # Tradeoff is that then SW can't control the ON/OFF state for this + # regulator (other than invoking a PMIC state change). + rohm,no-regulator-enable-control: + description: | + Enable/Disable control of this regulator must be left to the + PMIC hardware state machine. + type: boolean required: - regulator-name diff --git a/Documentation/devicetree/bindings/regulator/rohm,bd9576-regulator.yaml b/Documentation/devicetree/bindings/regulator/rohm,bd9576-regulator.yaml new file mode 100644 index 000000000000..b6515a0cee62 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/rohm,bd9576-regulator.yaml @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/rohm,bd9576-regulator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ROHM BD9576 and BD9573 Power Management Integrated Circuit regulators + +maintainers: + - Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> + +description: | + This module is part of the ROHM BD9576 MFD device. For more details + see Documentation/devicetree/bindings/mfd/rohm,bd9576-pmic.yaml. + + The regulator controller is represented as a sub-node of the PMIC node + on the device tree. + + The valid names for BD9576 regulator nodes are + regulator-vd50, regulator-vd18, regulator-vdddr, regulator-vd10, + regulator-voutl1, regulator-vouts1 + +patternProperties: + "regulator-.+": + type: object + description: + Properties for single regulator. + $ref: "regulator.yaml#" + + required: + - regulator-name + + unevaluatedProperties: false +additionalProperties: false diff --git a/Documentation/devicetree/bindings/regulator/silergy,sy8824x.yaml b/Documentation/devicetree/bindings/regulator/silergy,sy8824x.yaml new file mode 100644 index 000000000000..82af4d656177 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/silergy,sy8824x.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/silergy,sy8824x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: silergy sy8824c,sy8824e,sy20276 and sy20278 PMIC + +maintainers: + - Jisheng Zhang <jszhang@kernel.org> + +allOf: + - $ref: regulator.yaml# + +properties: + compatible: + enum: + - silergy,sy8824c + - silergy,sy8824e + - silergy,sy20276 + - silergy,sy20278 + + reg: + maxItems: 1 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + regulator@60 { + compatible = "silergy,sy8824c"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1150000>; + reg = <0x60>; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/regulator/sy8824x.txt b/Documentation/devicetree/bindings/regulator/sy8824x.txt deleted file mode 100644 index c5e95850c427..000000000000 --- a/Documentation/devicetree/bindings/regulator/sy8824x.txt +++ /dev/null @@ -1,24 +0,0 @@ -SY8824C/SY8824E/SY20276 Voltage regulator - -Required properties: -- compatible: Must be one of the following. - "silergy,sy8824c" - "silergy,sy8824e" - "silergy,sy20276" - "silergy,sy20278" -- reg: I2C slave address - -Any property defined as part of the core regulator binding, defined in -./regulator.txt, can also be used. - -Example: - - vcore: regulator@00 { - compatible = "silergy,sy8824c"; - reg = <0x66>; - regulator-name = "vcore"; - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <1150000>; - regulator-boot-on; - regulator-always-on; - }; diff --git a/drivers/regulator/88pg86x.c b/drivers/regulator/88pg86x.c index 71cfa2c5de5e..e91d5885c5ef 100644 --- a/drivers/regulator/88pg86x.c +++ b/drivers/regulator/88pg86x.c @@ -84,7 +84,7 @@ static int pg86x_i2c_probe(struct i2c_client *i2c) return 0; } -static const struct of_device_id pg86x_dt_ids [] = { +static const struct of_device_id __maybe_unused pg86x_dt_ids[] = { { .compatible = "marvell,88pg867" }, { .compatible = "marvell,88pg868" }, { } diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index de17ef7e18f0..020a00d6696b 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -231,6 +231,16 @@ config REGULATOR_BD9571MWV This driver can also be built as a module. If so, the module will be called bd9571mwv-regulator. +config REGULATOR_BD957XMUF + tristate "ROHM BD9576MUF and BD9573MUF Regulators" + depends on MFD_ROHM_BD957XMUF + help + This driver supports voltage regulators on ROHM BD9576MUF and + BD9573MUF PMICs. + + This driver can also be built as a module. If so, the module + will be called bd9576-regulator. + config REGULATOR_CPCAP tristate "Motorola CPCAP regulator" depends on MFD_CPCAP @@ -500,7 +510,7 @@ config REGULATOR_MAX1586 config REGULATOR_MAX77620 tristate "Maxim 77620/MAX20024 voltage regulator" - depends on MFD_MAX77620 + depends on MFD_MAX77620 || COMPILE_TEST help This driver controls Maxim MAX77620 voltage output regulator via I2C bus. The provided regulator is suitable for Tegra @@ -509,7 +519,7 @@ config REGULATOR_MAX77620 config REGULATOR_MAX77650 tristate "Maxim MAX77650/77651 regulator support" - depends on MFD_MAX77650 + depends on MFD_MAX77650 || COMPILE_TEST help Regulator driver for MAX77650/77651 PMIC from Maxim Semiconductor. This device has a SIMO with three independent @@ -532,7 +542,7 @@ config REGULATOR_MAX8660 config REGULATOR_MAX8907 tristate "Maxim 8907 voltage regulator" - depends on MFD_MAX8907 + depends on MFD_MAX8907 || COMPILE_TEST help This driver controls a Maxim 8907 voltage output regulator via I2C bus. The provided regulator is suitable for Tegra @@ -582,7 +592,7 @@ config REGULATOR_MAX8998 config REGULATOR_MAX77686 tristate "Maxim 77686 regulator" - depends on MFD_MAX77686 + depends on MFD_MAX77686 || COMPILE_TEST help This driver controls a Maxim 77686 regulator via I2C bus. The provided regulator is suitable for @@ -590,7 +600,7 @@ config REGULATOR_MAX77686 config REGULATOR_MAX77693 tristate "Maxim 77693/77843 regulator" - depends on (MFD_MAX77693 || MFD_MAX77843) + depends on MFD_MAX77693 || MFD_MAX77843 || COMPILE_TEST help This driver controls a Maxim 77693/77843 regulators via I2C bus. The regulators include two LDOs, 'SAFEOUT1', 'SAFEOUT2' @@ -599,7 +609,7 @@ config REGULATOR_MAX77693 config REGULATOR_MAX77802 tristate "Maxim 77802 regulator" - depends on MFD_MAX77686 + depends on MFD_MAX77686 || COMPILE_TEST help This driver controls a Maxim 77802 regulator via I2C bus. The provided regulator is suitable for @@ -711,6 +721,15 @@ config REGULATOR_MT6358 This driver supports the control of different power rails of device through regulator interface. +config REGULATOR_MT6360 + tristate "MT6360 SubPMIC Regulator" + depends on MFD_MT6360 + help + Say Y here to enable MT6360 regulator support. + This is support MT6360 PMIC/LDO part include + 2-channel buck with Thermal Shutdown and Overload Protection + 6-channel High PSRR and Low Dropout LDO. + config REGULATOR_MT6380 tristate "MediaTek MT6380 PMIC" depends on MTK_PMIC_WRAP @@ -864,6 +883,16 @@ config REGULATOR_QCOM_USB_VBUS Say M here if you want to include support for enabling the VBUS output as a module. The module will be named "qcom_usb_vbus_regulator". +config REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY + tristate "Raspberry Pi 7-inch touchscreen panel ATTINY regulator" + depends on BACKLIGHT_CLASS_DEVICE + depends on I2C + select REGMAP_I2C + help + This driver supports ATTINY regulator on the Raspberry Pi 7-inch + touchscreen unit. The regulator is used to enable power to the + TC358762, display and to control backlight. + config REGULATOR_RC5T583 tristate "RICOH RC5T583 Power regulators" depends on MFD_RC5T583 @@ -894,6 +923,14 @@ config REGULATOR_RN5T618 config REGULATOR_ROHM tristate +config REGULATOR_RT4801 + tristate "Richtek RT4801 Regulators" + depends on I2C + select REGMAP_I2C + help + This adds support for voltage regulators in Richtek RT4801 Display Bias IC. + The device supports two regulators (DSVP/DSVN). + config REGULATOR_RT5033 tristate "Richtek RT5033 Regulators" depends on MFD_RT5033 @@ -902,16 +939,25 @@ config REGULATOR_RT5033 RT5033 PMIC. The device supports multiple regulators like current source, LDO and Buck. +config REGULATOR_RTMV20 + tristate "RTMV20 Laser Diode Regulator" + depends on I2C + select REGMAP_I2C + help + This driver adds support for the load switch current regulator on + the Richtek RTMV20. It can support the load current up to 6A and + integrate strobe/vsync/fsin signal to synchronize the IR camera. + config REGULATOR_S2MPA01 tristate "Samsung S2MPA01 voltage regulator" - depends on MFD_SEC_CORE + depends on MFD_SEC_CORE || COMPILE_TEST help This driver controls Samsung S2MPA01 voltage output regulator via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs. config REGULATOR_S2MPS11 tristate "Samsung S2MPS11/13/14/15/S2MPU02 voltage regulator" - depends on MFD_SEC_CORE + depends on MFD_SEC_CORE || COMPILE_TEST help This driver supports a Samsung S2MPS11/13/14/15/S2MPU02 voltage output regulator via I2C bus. The chip is comprised of high efficient @@ -920,7 +966,7 @@ config REGULATOR_S2MPS11 config REGULATOR_S5M8767 tristate "Samsung S5M8767A voltage regulator" - depends on MFD_SEC_CORE + depends on MFD_SEC_CORE || COMPILE_TEST help This driver supports a Samsung S5M8767A voltage output regulator via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index d8d3ecf526a8..6ebae516258e 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_REGULATOR_BD70528) += bd70528-regulator.o obj-$(CONFIG_REGULATOR_BD71828) += bd71828-regulator.o obj-$(CONFIG_REGULATOR_BD718XX) += bd718x7-regulator.o obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o +obj-$(CONFIG_REGULATOR_BD957XMUF) += bd9576-regulator.o obj-$(CONFIG_REGULATOR_DA903X) += da903x-regulator.o obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o @@ -88,6 +89,7 @@ obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o obj-$(CONFIG_REGULATOR_MT6358) += mt6358-regulator.o +obj-$(CONFIG_REGULATOR_MT6360) += mt6360-regulator.o obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o obj-$(CONFIG_REGULATOR_QCOM_LABIBB) += qcom-labibb-regulator.o @@ -107,11 +109,14 @@ obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o obj-$(CONFIG_REGULATOR_PBIAS) += pbias-regulator.o obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o +obj-$(CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY) += rpi-panel-attiny-regulator.o obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o obj-$(CONFIG_REGULATOR_RK808) += rk808-regulator.o obj-$(CONFIG_REGULATOR_RN5T618) += rn5t618-regulator.o obj-$(CONFIG_REGULATOR_ROHM) += rohm-regulator.o +obj-$(CONFIG_REGULATOR_RT4801) += rt4801-regulator.o obj-$(CONFIG_REGULATOR_RT5033) += rt5033-regulator.o +obj-$(CONFIG_REGULATOR_RTMV20) += rtmv20-regulator.o obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c index 7b311389f925..0774467994fb 100644 --- a/drivers/regulator/bd718x7-regulator.c +++ b/drivers/regulator/bd718x7-regulator.c @@ -16,6 +16,39 @@ #include <linux/slab.h> /* + * BD718(37/47/50) have two "enable control modes". ON/OFF can either be + * controlled by software - or by PMIC internal HW state machine. Whether + * regulator should be under SW or HW control can be defined from device-tree. + * Let's provide separate ops for regulators to use depending on the "enable + * control mode". + */ +#define BD718XX_HWOPNAME(swopname) swopname##_hwcontrol + +#define BD718XX_OPS(name, _list_voltage, _map_voltage, _set_voltage_sel, \ + _get_voltage_sel, _set_voltage_time_sel, _set_ramp_delay) \ +static const struct regulator_ops name = { \ + .enable = regulator_enable_regmap, \ + .disable = regulator_disable_regmap, \ + .is_enabled = regulator_is_enabled_regmap, \ + .list_voltage = (_list_voltage), \ + .map_voltage = (_map_voltage), \ + .set_voltage_sel = (_set_voltage_sel), \ + .get_voltage_sel = (_get_voltage_sel), \ + .set_voltage_time_sel = (_set_voltage_time_sel), \ + .set_ramp_delay = (_set_ramp_delay), \ +}; \ + \ +static const struct regulator_ops BD718XX_HWOPNAME(name) = { \ + .is_enabled = always_enabled_by_hwstate, \ + .list_voltage = (_list_voltage), \ + .map_voltage = (_map_voltage), \ + .set_voltage_sel = (_set_voltage_sel), \ + .get_voltage_sel = (_get_voltage_sel), \ + .set_voltage_time_sel = (_set_voltage_time_sel), \ + .set_ramp_delay = (_set_ramp_delay), \ +} \ + +/* * BUCK1/2/3/4 * BUCK1RAMPRATE[1:0] BUCK1 DVS ramp rate setting * 00: 10.00mV/usec 10mV 1uS @@ -55,6 +88,38 @@ static int bd718xx_buck1234_set_ramp_delay(struct regulator_dev *rdev, BUCK_RAMPRATE_MASK, ramp_value << 6); } +/* These functions are used when regulators are under HW state machine control. + * We assume PMIC is in RUN state because SW running and able to query the + * status. Most of the regulators have fixed ON or OFF state at RUN/IDLE so for + * them we just return a constant. BD71837 BUCK3 and BUCK4 are exceptions as + * they support configuring the ON/OFF state for RUN. + * + * Note for next hacker - these PMICs have a register where the HW state can be + * read. If assuming RUN appears to be false in your use-case - you can + * implement state reading (although that is not going to be atomic) before + * returning the enable state. + */ +static int always_enabled_by_hwstate(struct regulator_dev *rdev) +{ + return 1; +} + +static int never_enabled_by_hwstate(struct regulator_dev *rdev) +{ + return 0; +} + +static int bd71837_get_buck34_enable_hwctrl(struct regulator_dev *rdev) +{ + int ret; + unsigned int val; + + ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); + if (ret) + return ret; + + return !!(BD718XX_BUCK_RUN_ON & val); +} /* * On BD71837 (not on BD71847, BD71850, ...) * Bucks 1 to 4 support DVS. PWM mode is used when voltage is changed. @@ -71,7 +136,7 @@ static int bd718xx_buck1234_set_ramp_delay(struct regulator_dev *rdev, static int bd71837_set_voltage_sel_restricted(struct regulator_dev *rdev, unsigned int sel) { - if (regulator_is_enabled_regmap(rdev)) + if (rdev->desc->ops->is_enabled(rdev)) return -EBUSY; return regulator_set_voltage_sel_regmap(rdev, sel); @@ -113,7 +178,7 @@ static int voltage_change_prepare(struct regulator_dev *rdev, unsigned int sel, int ret; *mask = 0; - if (regulator_is_enabled_regmap(rdev)) { + if (rdev->desc->ops->is_enabled(rdev)) { int now, new; now = rdev->desc->ops->get_voltage_sel(rdev); @@ -195,133 +260,90 @@ static int bd718xx_set_voltage_sel_pickable_restricted( static int bd71837_set_voltage_sel_pickable_restricted( struct regulator_dev *rdev, unsigned int sel) { - if (regulator_is_enabled_regmap(rdev)) + if (rdev->desc->ops->is_enabled(rdev)) return -EBUSY; return regulator_set_voltage_sel_pickable_regmap(rdev, sel); } -static const struct regulator_ops bd718xx_pickable_range_ldo_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, +/* + * OPS common for BD71847 and BD71850 + */ +BD718XX_OPS(bd718xx_pickable_range_ldo_ops, + regulator_list_voltage_pickable_linear_range, NULL, + bd718xx_set_voltage_sel_pickable_restricted, + regulator_get_voltage_sel_pickable_regmap, NULL, NULL); + +/* BD71847 and BD71850 LDO 5 is by default OFF at RUN state */ +static const struct regulator_ops bd718xx_ldo5_ops_hwstate = { + .is_enabled = never_enabled_by_hwstate, .list_voltage = regulator_list_voltage_pickable_linear_range, .set_voltage_sel = bd718xx_set_voltage_sel_pickable_restricted, .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, - }; -static const struct regulator_ops bd71837_pickable_range_ldo_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .list_voltage = regulator_list_voltage_pickable_linear_range, - .set_voltage_sel = bd71837_set_voltage_sel_pickable_restricted, - .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, -}; - -static const struct regulator_ops bd718xx_pickable_range_buck_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .list_voltage = regulator_list_voltage_pickable_linear_range, - .set_voltage_sel = regulator_set_voltage_sel_pickable_regmap, - .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, -}; - -static const struct regulator_ops bd71837_pickable_range_buck_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .list_voltage = regulator_list_voltage_pickable_linear_range, - .set_voltage_sel = bd71837_set_voltage_sel_pickable_restricted, - .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, -}; - -static const struct regulator_ops bd71837_ldo_regulator_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .list_voltage = regulator_list_voltage_linear_range, - .set_voltage_sel = bd71837_set_voltage_sel_restricted, - .get_voltage_sel = regulator_get_voltage_sel_regmap, -}; - -static const struct regulator_ops bd718xx_ldo_regulator_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .list_voltage = regulator_list_voltage_linear_range, - .set_voltage_sel = bd718xx_set_voltage_sel_restricted, - .get_voltage_sel = regulator_get_voltage_sel_regmap, -}; - -static const struct regulator_ops bd71837_ldo_regulator_nolinear_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .list_voltage = regulator_list_voltage_table, - .set_voltage_sel = bd71837_set_voltage_sel_restricted, - .get_voltage_sel = regulator_get_voltage_sel_regmap, -}; - -static const struct regulator_ops bd718xx_ldo_regulator_nolinear_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .list_voltage = regulator_list_voltage_table, - .set_voltage_sel = bd718xx_set_voltage_sel_restricted, - .get_voltage_sel = regulator_get_voltage_sel_regmap, -}; +BD718XX_OPS(bd718xx_pickable_range_buck_ops, + regulator_list_voltage_pickable_linear_range, NULL, + regulator_set_voltage_sel_pickable_regmap, + regulator_get_voltage_sel_pickable_regmap, + regulator_set_voltage_time_sel, NULL); -static const struct regulator_ops bd718xx_buck_regulator_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .list_voltage = regulator_list_voltage_linear_range, - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, -}; +BD718XX_OPS(bd718xx_ldo_regulator_ops, regulator_list_voltage_linear_range, + NULL, bd718xx_set_voltage_sel_restricted, + regulator_get_voltage_sel_regmap, NULL, NULL); -static const struct regulator_ops bd71837_buck_regulator_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .list_voltage = regulator_list_voltage_linear_range, - .set_voltage_sel = bd71837_set_voltage_sel_restricted, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, -}; +BD718XX_OPS(bd718xx_ldo_regulator_nolinear_ops, regulator_list_voltage_table, + NULL, bd718xx_set_voltage_sel_restricted, + regulator_get_voltage_sel_regmap, NULL, NULL); -static const struct regulator_ops bd718xx_buck_regulator_nolinear_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .list_voltage = regulator_list_voltage_table, - .map_voltage = regulator_map_voltage_ascend, - .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, -}; +BD718XX_OPS(bd718xx_buck_regulator_ops, regulator_list_voltage_linear_range, + NULL, regulator_set_voltage_sel_regmap, + regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel, + NULL); -static const struct regulator_ops bd71837_buck_regulator_nolinear_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .list_voltage = regulator_list_voltage_table, - .map_voltage = regulator_map_voltage_ascend, - .set_voltage_sel = bd718xx_set_voltage_sel_restricted, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, -}; +BD718XX_OPS(bd718xx_buck_regulator_nolinear_ops, regulator_list_voltage_table, + regulator_map_voltage_ascend, regulator_set_voltage_sel_regmap, + regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel, + NULL); -static const struct regulator_ops bd718xx_dvs_buck_regulator_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, +/* + * OPS for BD71837 + */ +BD718XX_OPS(bd71837_pickable_range_ldo_ops, + regulator_list_voltage_pickable_linear_range, NULL, + bd71837_set_voltage_sel_pickable_restricted, + regulator_get_voltage_sel_pickable_regmap, NULL, NULL); + +BD718XX_OPS(bd71837_pickable_range_buck_ops, + regulator_list_voltage_pickable_linear_range, NULL, + bd71837_set_voltage_sel_pickable_restricted, + regulator_get_voltage_sel_pickable_regmap, + regulator_set_voltage_time_sel, NULL); + +BD718XX_OPS(bd71837_ldo_regulator_ops, regulator_list_voltage_linear_range, + NULL, bd71837_set_voltage_sel_restricted, + regulator_get_voltage_sel_regmap, NULL, NULL); + +BD718XX_OPS(bd71837_ldo_regulator_nolinear_ops, regulator_list_voltage_table, + NULL, bd71837_set_voltage_sel_restricted, + regulator_get_voltage_sel_regmap, NULL, NULL); + +BD718XX_OPS(bd71837_buck_regulator_ops, regulator_list_voltage_linear_range, + NULL, bd71837_set_voltage_sel_restricted, + regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel, + NULL); + +BD718XX_OPS(bd71837_buck_regulator_nolinear_ops, regulator_list_voltage_table, + regulator_map_voltage_ascend, bd718xx_set_voltage_sel_restricted, + regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel, + NULL); +/* + * BD71837 bucks 3 and 4 support defining their enable/disable state also + * when buck enable state is under HW state machine control. In that case the + * bit [2] in CTRL register is used to indicate if regulator should be ON. + */ +static const struct regulator_ops bd71837_buck34_ops_hwctrl = { + .is_enabled = bd71837_get_buck34_enable_hwctrl, .list_voltage = regulator_list_voltage_linear_range, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -330,6 +352,14 @@ static const struct regulator_ops bd718xx_dvs_buck_regulator_ops = { }; /* + * OPS for all of the ICs - BD718(37/47/50) + */ +BD718XX_OPS(bd718xx_dvs_buck_regulator_ops, regulator_list_voltage_linear_range, + NULL, regulator_set_voltage_sel_regmap, + regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel, + bd718xx_buck1234_set_ramp_delay); + +/* * BD71837 BUCK1/2/3/4 * BD71847 BUCK1/2 * 0.70 to 1.30V (10mV step) @@ -543,14 +573,37 @@ static int buck_set_hw_dvs_levels(struct device_node *np, return rohm_regulator_set_dvs_levels(&data->dvs, np, desc, cfg->regmap); } -static const struct bd718xx_regulator_data bd71847_regulators[] = { +static const struct regulator_ops *bd71847_swcontrol_ops[] = { + &bd718xx_dvs_buck_regulator_ops, &bd718xx_dvs_buck_regulator_ops, + &bd718xx_pickable_range_buck_ops, &bd718xx_pickable_range_buck_ops, + &bd718xx_buck_regulator_nolinear_ops, &bd718xx_buck_regulator_ops, + &bd718xx_pickable_range_ldo_ops, &bd718xx_ldo_regulator_nolinear_ops, + &bd718xx_ldo_regulator_ops, &bd718xx_ldo_regulator_ops, + &bd718xx_pickable_range_ldo_ops, &bd718xx_ldo_regulator_ops, +}; + +static const struct regulator_ops *bd71847_hwcontrol_ops[] = { + &BD718XX_HWOPNAME(bd718xx_dvs_buck_regulator_ops), + &BD718XX_HWOPNAME(bd718xx_dvs_buck_regulator_ops), + &BD718XX_HWOPNAME(bd718xx_pickable_range_buck_ops), + &BD718XX_HWOPNAME(bd718xx_pickable_range_buck_ops), + &BD718XX_HWOPNAME(bd718xx_buck_regulator_nolinear_ops), + &BD718XX_HWOPNAME(bd718xx_buck_regulator_ops), + &BD718XX_HWOPNAME(bd718xx_pickable_range_ldo_ops), + &BD718XX_HWOPNAME(bd718xx_ldo_regulator_nolinear_ops), + &BD718XX_HWOPNAME(bd718xx_ldo_regulator_ops), + &BD718XX_HWOPNAME(bd718xx_ldo_regulator_ops), + &bd718xx_ldo5_ops_hwstate, + &BD718XX_HWOPNAME(bd718xx_ldo_regulator_ops), +}; + +static struct bd718xx_regulator_data bd71847_regulators[] = { { .desc = { .name = "buck1", .of_match = of_match_ptr("BUCK1"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK1, - .ops = &bd718xx_dvs_buck_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM, .linear_ranges = bd718xx_dvs_buck_volts, @@ -585,7 +638,6 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .of_match = of_match_ptr("BUCK2"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK2, - .ops = &bd718xx_dvs_buck_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM, .linear_ranges = bd718xx_dvs_buck_volts, @@ -616,7 +668,6 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .of_match = of_match_ptr("BUCK3"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK3, - .ops = &bd718xx_pickable_range_buck_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD71847_BUCK3_VOLTAGE_NUM, .linear_ranges = bd71847_buck3_volts, @@ -643,7 +694,6 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .of_match = of_match_ptr("BUCK4"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK4, - .ops = &bd718xx_pickable_range_buck_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD71847_BUCK4_VOLTAGE_NUM, .linear_ranges = bd71847_buck4_volts, @@ -670,7 +720,6 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .of_match = of_match_ptr("BUCK5"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK5, - .ops = &bd718xx_buck_regulator_nolinear_ops, .type = REGULATOR_VOLTAGE, .volt_table = &bd718xx_3rd_nodvs_buck_volts[0], .n_voltages = ARRAY_SIZE(bd718xx_3rd_nodvs_buck_volts), @@ -692,7 +741,6 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .of_match = of_match_ptr("BUCK6"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK6, - .ops = &bd718xx_buck_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD718XX_4TH_NODVS_BUCK_VOLTAGE_NUM, .linear_ranges = bd718xx_4th_nodvs_buck_volts, @@ -716,7 +764,6 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .of_match = of_match_ptr("LDO1"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_LDO1, - .ops = &bd718xx_pickable_range_ldo_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD718XX_LDO1_VOLTAGE_NUM, .linear_ranges = bd718xx_ldo1_volts, @@ -742,7 +789,6 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .of_match = of_match_ptr("LDO2"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_LDO2, - .ops = &bd718xx_ldo_regulator_nolinear_ops, .type = REGULATOR_VOLTAGE, .volt_table = &ldo_2_volts[0], .vsel_reg = BD718XX_REG_LDO2_VOLT, @@ -764,7 +810,6 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .of_match = of_match_ptr("LDO3"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_LDO3, - .ops = &bd718xx_ldo_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD718XX_LDO3_VOLTAGE_NUM, .linear_ranges = bd718xx_ldo3_volts, @@ -787,7 +832,6 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .of_match = of_match_ptr("LDO4"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_LDO4, - .ops = &bd718xx_ldo_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD718XX_LDO4_VOLTAGE_NUM, .linear_ranges = bd718xx_ldo4_volts, @@ -810,7 +854,6 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .of_match = of_match_ptr("LDO5"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_LDO5, - .ops = &bd718xx_pickable_range_ldo_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD71847_LDO5_VOLTAGE_NUM, .linear_ranges = bd71847_ldo5_volts, @@ -836,7 +879,6 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .of_match = of_match_ptr("LDO6"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_LDO6, - .ops = &bd718xx_ldo_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD718XX_LDO6_VOLTAGE_NUM, .linear_ranges = bd718xx_ldo6_volts, @@ -857,14 +899,41 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { }, }; -static const struct bd718xx_regulator_data bd71837_regulators[] = { +static const struct regulator_ops *bd71837_swcontrol_ops[] = { + &bd718xx_dvs_buck_regulator_ops, &bd718xx_dvs_buck_regulator_ops, + &bd718xx_dvs_buck_regulator_ops, &bd718xx_dvs_buck_regulator_ops, + &bd71837_pickable_range_buck_ops, &bd71837_buck_regulator_ops, + &bd71837_buck_regulator_nolinear_ops, &bd71837_buck_regulator_ops, + &bd71837_pickable_range_ldo_ops, &bd71837_ldo_regulator_nolinear_ops, + &bd71837_ldo_regulator_ops, &bd71837_ldo_regulator_ops, + &bd71837_ldo_regulator_ops, &bd71837_ldo_regulator_ops, + &bd71837_ldo_regulator_ops, +}; + +static const struct regulator_ops *bd71837_hwcontrol_ops[] = { + &BD718XX_HWOPNAME(bd718xx_dvs_buck_regulator_ops), + &BD718XX_HWOPNAME(bd718xx_dvs_buck_regulator_ops), + &bd71837_buck34_ops_hwctrl, &bd71837_buck34_ops_hwctrl, + &BD718XX_HWOPNAME(bd71837_pickable_range_buck_ops), + &BD718XX_HWOPNAME(bd71837_buck_regulator_ops), + &BD718XX_HWOPNAME(bd71837_buck_regulator_nolinear_ops), + &BD718XX_HWOPNAME(bd71837_buck_regulator_ops), + &BD718XX_HWOPNAME(bd71837_pickable_range_ldo_ops), + &BD718XX_HWOPNAME(bd71837_ldo_regulator_nolinear_ops), + &BD718XX_HWOPNAME(bd71837_ldo_regulator_ops), + &BD718XX_HWOPNAME(bd71837_ldo_regulator_ops), + &BD718XX_HWOPNAME(bd71837_ldo_regulator_ops), + &BD718XX_HWOPNAME(bd71837_ldo_regulator_ops), + &BD718XX_HWOPNAME(bd71837_ldo_regulator_ops), +}; + +static struct bd718xx_regulator_data bd71837_regulators[] = { { .desc = { .name = "buck1", .of_match = of_match_ptr("BUCK1"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK1, - .ops = &bd718xx_dvs_buck_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM, .linear_ranges = bd718xx_dvs_buck_volts, @@ -898,7 +967,6 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .of_match = of_match_ptr("BUCK2"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK2, - .ops = &bd718xx_dvs_buck_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM, .linear_ranges = bd718xx_dvs_buck_volts, @@ -929,7 +997,6 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .of_match = of_match_ptr("BUCK3"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK3, - .ops = &bd718xx_dvs_buck_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM, .linear_ranges = bd718xx_dvs_buck_volts, @@ -958,7 +1025,6 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .of_match = of_match_ptr("BUCK4"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK4, - .ops = &bd718xx_dvs_buck_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM, .linear_ranges = bd718xx_dvs_buck_volts, @@ -987,7 +1053,6 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .of_match = of_match_ptr("BUCK5"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK5, - .ops = &bd71837_pickable_range_buck_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD71837_BUCK5_VOLTAGE_NUM, .linear_ranges = bd71837_buck5_volts, @@ -1014,7 +1079,6 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .of_match = of_match_ptr("BUCK6"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK6, - .ops = &bd71837_buck_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD71837_BUCK6_VOLTAGE_NUM, .linear_ranges = bd71837_buck6_volts, @@ -1038,7 +1102,6 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .of_match = of_match_ptr("BUCK7"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK7, - .ops = &bd71837_buck_regulator_nolinear_ops, .type = REGULATOR_VOLTAGE, .volt_table = &bd718xx_3rd_nodvs_buck_volts[0], .n_voltages = ARRAY_SIZE(bd718xx_3rd_nodvs_buck_volts), @@ -1060,7 +1123,6 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .of_match = of_match_ptr("BUCK8"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK8, - .ops = &bd71837_buck_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD718XX_4TH_NODVS_BUCK_VOLTAGE_NUM, .linear_ranges = bd718xx_4th_nodvs_buck_volts, @@ -1084,7 +1146,6 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .of_match = of_match_ptr("LDO1"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_LDO1, - .ops = &bd71837_pickable_range_ldo_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD718XX_LDO1_VOLTAGE_NUM, .linear_ranges = bd718xx_ldo1_volts, @@ -1110,7 +1171,6 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .of_match = of_match_ptr("LDO2"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_LDO2, - .ops = &bd71837_ldo_regulator_nolinear_ops, .type = REGULATOR_VOLTAGE, .volt_table = &ldo_2_volts[0], .vsel_reg = BD718XX_REG_LDO2_VOLT, @@ -1132,7 +1192,6 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .of_match = of_match_ptr("LDO3"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_LDO3, - .ops = &bd71837_ldo_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD718XX_LDO3_VOLTAGE_NUM, .linear_ranges = bd718xx_ldo3_volts, @@ -1155,7 +1214,6 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .of_match = of_match_ptr("LDO4"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_LDO4, - .ops = &bd71837_ldo_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD718XX_LDO4_VOLTAGE_NUM, .linear_ranges = bd718xx_ldo4_volts, @@ -1178,7 +1236,6 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .of_match = of_match_ptr("LDO5"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_LDO5, - .ops = &bd71837_ldo_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD71837_LDO5_VOLTAGE_NUM, .linear_ranges = bd71837_ldo5_volts, @@ -1205,7 +1262,6 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .of_match = of_match_ptr("LDO6"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_LDO6, - .ops = &bd71837_ldo_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD718XX_LDO6_VOLTAGE_NUM, .linear_ranges = bd718xx_ldo6_volts, @@ -1232,7 +1288,6 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .of_match = of_match_ptr("LDO7"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_LDO7, - .ops = &bd71837_ldo_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD71837_LDO7_VOLTAGE_NUM, .linear_ranges = bd71837_ldo7_volts, @@ -1251,15 +1306,57 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { }, }; +static void mark_hw_controlled(struct device *dev, struct device_node *np, + struct bd718xx_regulator_data *reg_data, + unsigned int num_reg_data, int *info) +{ + int i; + + for (i = 1; i <= num_reg_data; i++) { + if (!of_node_name_eq(np, reg_data[i-1].desc.of_match)) + continue; + + *info |= 1 << (i - 1); + dev_dbg(dev, "regulator %d runlevel controlled\n", i); + return; + } + dev_warn(dev, "Bad regulator node\n"); +} + +static int get_hw_controlled_regulators(struct device *dev, + struct bd718xx_regulator_data *reg_data, + unsigned int num_reg_data, int *info) +{ + struct device_node *np; + struct device_node *nproot = dev->of_node; + const char *prop = "rohm,no-regulator-enable-control"; + + *info = 0; + + nproot = of_get_child_by_name(nproot, "regulators"); + if (!nproot) { + dev_err(dev, "failed to find regulators node\n"); + return -ENODEV; + } + for_each_child_of_node(nproot, np) + if (of_property_read_bool(np, prop)) + mark_hw_controlled(dev, np, reg_data, num_reg_data, + info); + + of_node_put(nproot); + return 0; +} + static int bd718xx_probe(struct platform_device *pdev) { struct bd718xx *mfd; struct regulator_config config = { 0 }; - int i, j, err; + int i, j, err, omit_enable; bool use_snvs; - const struct bd718xx_regulator_data *reg_data; + struct bd718xx_regulator_data *reg_data; unsigned int num_reg_data; enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data; + const struct regulator_ops **swops, **hwops; mfd = dev_get_drvdata(pdev->dev.parent); if (!mfd) { @@ -1272,10 +1369,14 @@ static int bd718xx_probe(struct platform_device *pdev) case ROHM_CHIP_TYPE_BD71837: reg_data = bd71837_regulators; num_reg_data = ARRAY_SIZE(bd71837_regulators); + swops = &bd71837_swcontrol_ops[0]; + hwops = &bd71837_hwcontrol_ops[0]; break; case ROHM_CHIP_TYPE_BD71847: reg_data = bd71847_regulators; num_reg_data = ARRAY_SIZE(bd71847_regulators); + swops = &bd71847_swcontrol_ops[0]; + hwops = &bd71847_hwcontrol_ops[0]; break; default: dev_err(&pdev->dev, "Unsupported chip type\n"); @@ -1319,17 +1420,35 @@ static int bd718xx_probe(struct platform_device *pdev) } } + config.dev = pdev->dev.parent; + config.regmap = mfd->chip.regmap; + /* + * There are cases when we want to leave the enable-control for + * the HW state machine and use this driver only for voltage control. + * One special case is when we use PMIC_STBY_REQ line from SoC to PMIC + * in order to set the system to SUSPEND state. + * + * If regulator is taken under SW control the regulator state will not + * be affected by PMIC state machine - Eg. regulator is likely to stay + * on even in SUSPEND + */ + get_hw_controlled_regulators(pdev->dev.parent, reg_data, num_reg_data, + &omit_enable); + for (i = 0; i < num_reg_data; i++) { - const struct regulator_desc *desc; + struct regulator_desc *desc; struct regulator_dev *rdev; - const struct bd718xx_regulator_data *r; + struct bd718xx_regulator_data *r; + int no_enable_control = omit_enable & (1 << i); r = ®_data[i]; desc = &r->desc; - config.dev = pdev->dev.parent; - config.regmap = mfd->chip.regmap; + if (no_enable_control) + desc->ops = hwops[i]; + else + desc->ops = swops[i]; rdev = devm_regulator_register(&pdev->dev, desc, &config); if (IS_ERR(rdev)) { @@ -1356,8 +1475,9 @@ static int bd718xx_probe(struct platform_device *pdev) * enable SW control for crucial regulators if snvs state is * used */ - if (!use_snvs || !rdev->constraints->always_on || - !rdev->constraints->boot_on) { + if (!no_enable_control && (!use_snvs || + !rdev->constraints->always_on || + !rdev->constraints->boot_on)) { err = regmap_update_bits(mfd->chip.regmap, r->init.reg, r->init.mask, r->init.val); if (err) { diff --git a/drivers/regulator/bd9576-regulator.c b/drivers/regulator/bd9576-regulator.c new file mode 100644 index 000000000000..a8b5832a5a1b --- /dev/null +++ b/drivers/regulator/bd9576-regulator.c @@ -0,0 +1,337 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2020 ROHM Semiconductors +// ROHM BD9576MUF/BD9573MUF regulator driver + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/gpio/consumer.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/mfd/rohm-bd957x.h> +#include <linux/mfd/rohm-generic.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> +#include <linux/slab.h> + +#define BD957X_VOUTS1_VOLT 3300000 +#define BD957X_VOUTS4_BASE_VOLT 1030000 +#define BD957X_VOUTS34_NUM_VOLT 32 + +static int vout1_volt_table[] = {5000000, 4900000, 4800000, 4700000, 4600000, + 4500000, 4500000, 4500000, 5000000, 5100000, + 5200000, 5300000, 5400000, 5500000, 5500000, + 5500000}; + +static int vout2_volt_table[] = {1800000, 1780000, 1760000, 1740000, 1720000, + 1700000, 1680000, 1660000, 1800000, 1820000, + 1840000, 1860000, 1880000, 1900000, 1920000, + 1940000}; + +static int voutl1_volt_table[] = {2500000, 2540000, 2580000, 2620000, 2660000, + 2700000, 2740000, 2780000, 2500000, 2460000, + 2420000, 2380000, 2340000, 2300000, 2260000, + 2220000}; + +struct bd957x_regulator_data { + struct regulator_desc desc; + int base_voltage; +}; + +static int bd957x_vout34_list_voltage(struct regulator_dev *rdev, + unsigned int selector) +{ + const struct regulator_desc *desc = rdev->desc; + int multiplier = selector & desc->vsel_mask & 0x7f; + int tune; + + /* VOUT3 and 4 has 10mV step */ + tune = multiplier * 10000; + + if (!(selector & 0x80)) + return desc->fixed_uV - tune; + + return desc->fixed_uV + tune; +} + +static int bd957x_list_voltage(struct regulator_dev *rdev, + unsigned int selector) +{ + const struct regulator_desc *desc = rdev->desc; + int index = selector & desc->vsel_mask & 0x7f; + + if (!(selector & 0x80)) + index += desc->n_voltages/2; + + if (index >= desc->n_voltages) + return -EINVAL; + + return desc->volt_table[index]; +} + +static const struct regulator_ops bd957x_vout34_ops = { + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = bd957x_vout34_list_voltage, + .get_voltage_sel = regulator_get_voltage_sel_regmap, +}; + +static const struct regulator_ops bd957X_vouts1_regulator_ops = { + .is_enabled = regulator_is_enabled_regmap, +}; + +static const struct regulator_ops bd957x_ops = { + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = bd957x_list_voltage, + .get_voltage_sel = regulator_get_voltage_sel_regmap, +}; + +static struct bd957x_regulator_data bd9576_regulators[] = { + { + .desc = { + .name = "VD50", + .of_match = of_match_ptr("regulator-vd50"), + .regulators_node = of_match_ptr("regulators"), + .id = BD957X_VD50, + .type = REGULATOR_VOLTAGE, + .ops = &bd957x_ops, + .volt_table = &vout1_volt_table[0], + .n_voltages = ARRAY_SIZE(vout1_volt_table), + .vsel_reg = BD957X_REG_VOUT1_TUNE, + .vsel_mask = BD957X_MASK_VOUT1_TUNE, + .enable_reg = BD957X_REG_POW_TRIGGER1, + .enable_mask = BD957X_REGULATOR_EN_MASK, + .enable_val = BD957X_REGULATOR_DIS_VAL, + .enable_is_inverted = true, + .owner = THIS_MODULE, + }, + }, + { + .desc = { + .name = "VD18", + .of_match = of_match_ptr("regulator-vd18"), + .regulators_node = of_match_ptr("regulators"), + .id = BD957X_VD18, + .type = REGULATOR_VOLTAGE, + .ops = &bd957x_ops, + .volt_table = &vout2_volt_table[0], + .n_voltages = ARRAY_SIZE(vout2_volt_table), + .vsel_reg = BD957X_REG_VOUT2_TUNE, + .vsel_mask = BD957X_MASK_VOUT2_TUNE, + .enable_reg = BD957X_REG_POW_TRIGGER2, + .enable_mask = BD957X_REGULATOR_EN_MASK, + .enable_val = BD957X_REGULATOR_DIS_VAL, + .enable_is_inverted = true, + .owner = THIS_MODULE, + }, + }, + { + .desc = { + .name = "VDDDR", + .of_match = of_match_ptr("regulator-vdddr"), + .regulators_node = of_match_ptr("regulators"), + .id = BD957X_VDDDR, + .ops = &bd957x_vout34_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD957X_VOUTS34_NUM_VOLT, + .vsel_reg = BD957X_REG_VOUT3_TUNE, + .vsel_mask = BD957X_MASK_VOUT3_TUNE, + .enable_reg = BD957X_REG_POW_TRIGGER3, + .enable_mask = BD957X_REGULATOR_EN_MASK, + .enable_val = BD957X_REGULATOR_DIS_VAL, + .enable_is_inverted = true, + .owner = THIS_MODULE, + }, + }, + { + .desc = { + .name = "VD10", + .of_match = of_match_ptr("regulator-vd10"), + .regulators_node = of_match_ptr("regulators"), + .id = BD957X_VD10, + .ops = &bd957x_vout34_ops, + .type = REGULATOR_VOLTAGE, + .fixed_uV = BD957X_VOUTS4_BASE_VOLT, + .n_voltages = BD957X_VOUTS34_NUM_VOLT, + .vsel_reg = BD957X_REG_VOUT4_TUNE, + .vsel_mask = BD957X_MASK_VOUT4_TUNE, + .enable_reg = BD957X_REG_POW_TRIGGER4, + .enable_mask = BD957X_REGULATOR_EN_MASK, + .enable_val = BD957X_REGULATOR_DIS_VAL, + .enable_is_inverted = true, + .owner = THIS_MODULE, + }, + }, + { + .desc = { + .name = "VOUTL1", + .of_match = of_match_ptr("regulator-voutl1"), + .regulators_node = of_match_ptr("regulators"), + .id = BD957X_VOUTL1, + .ops = &bd957x_ops, + .type = REGULATOR_VOLTAGE, + .volt_table = &voutl1_volt_table[0], + .n_voltages = ARRAY_SIZE(voutl1_volt_table), + .vsel_reg = BD957X_REG_VOUTL1_TUNE, + .vsel_mask = BD957X_MASK_VOUTL1_TUNE, + .enable_reg = BD957X_REG_POW_TRIGGERL1, + .enable_mask = BD957X_REGULATOR_EN_MASK, + .enable_val = BD957X_REGULATOR_DIS_VAL, + .enable_is_inverted = true, + .owner = THIS_MODULE, + }, + }, + { + .desc = { + .name = "VOUTS1", + .of_match = of_match_ptr("regulator-vouts1"), + .regulators_node = of_match_ptr("regulators"), + .id = BD957X_VOUTS1, + .ops = &bd957X_vouts1_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 1, + .fixed_uV = BD957X_VOUTS1_VOLT, + .enable_reg = BD957X_REG_POW_TRIGGERS1, + .enable_mask = BD957X_REGULATOR_EN_MASK, + .enable_val = BD957X_REGULATOR_DIS_VAL, + .enable_is_inverted = true, + .owner = THIS_MODULE, + }, + }, +}; + +static int bd957x_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + struct regulator_config config = { 0 }; + int i, err; + bool vout_mode, ddr_sel; + const struct bd957x_regulator_data *reg_data = &bd9576_regulators[0]; + unsigned int num_reg_data = ARRAY_SIZE(bd9576_regulators); + enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data; + + regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!regmap) { + dev_err(&pdev->dev, "No regmap\n"); + return -EINVAL; + } + vout_mode = of_property_read_bool(pdev->dev.parent->of_node, + "rohm,vout1-en-low"); + if (vout_mode) { + struct gpio_desc *en; + + dev_dbg(&pdev->dev, "GPIO controlled mode\n"); + + /* VOUT1 enable state judged by VOUT1_EN pin */ + /* See if we have GPIO defined */ + en = devm_gpiod_get_from_of_node(&pdev->dev, + pdev->dev.parent->of_node, + "rohm,vout1-en-gpios", 0, + 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 + */ + 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); + } + } + + /* + * If more than one PMIC needs to be controlled by same processor then + * allocate the regulator data array here and use bd9576_regulators as + * template. At the moment I see no such use-case so I spare some + * bytes and use bd9576_regulators directly for non-constant configs + * like DDR voltage selection. + */ + ddr_sel = of_property_read_bool(pdev->dev.parent->of_node, + "rohm,ddr-sel-low"); + if (ddr_sel) + bd9576_regulators[2].desc.fixed_uV = 1350000; + else + bd9576_regulators[2].desc.fixed_uV = 1500000; + + switch (chip) { + case ROHM_CHIP_TYPE_BD9576: + dev_dbg(&pdev->dev, "Found BD9576MUF\n"); + break; + case ROHM_CHIP_TYPE_BD9573: + dev_dbg(&pdev->dev, "Found BD9573MUF\n"); + break; + default: + dev_err(&pdev->dev, "Unsupported chip type\n"); + err = -EINVAL; + goto err; + } + + config.dev = pdev->dev.parent; + config.regmap = regmap; + + for (i = 0; i < num_reg_data; i++) { + + const struct regulator_desc *desc; + struct regulator_dev *rdev; + const struct bd957x_regulator_data *r; + + r = ®_data[i]; + desc = &r->desc; + + 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; + } + /* + * Clear the VOUT1 GPIO setting - rest of the regulators do not + * support GPIO control + */ + config.ena_gpiod = NULL; + } + +err: + return err; +} + +static const struct platform_device_id bd957x_pmic_id[] = { + { "bd9573-pmic", ROHM_CHIP_TYPE_BD9573 }, + { "bd9576-pmic", ROHM_CHIP_TYPE_BD9576 }, + { }, +}; +MODULE_DEVICE_TABLE(platform, bd957x_pmic_id); + +static struct platform_driver bd957x_regulator = { + .driver = { + .name = "bd957x-pmic", + }, + .probe = bd957x_probe, + .id_table = bd957x_pmic_id, +}; + +module_platform_driver(bd957x_regulator); + +MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); +MODULE_DESCRIPTION("ROHM BD9576/BD9573 voltage regulator driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:bd957x-pmic"); diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 7ff507ec875a..a4ffd71696da 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -190,11 +190,10 @@ static inline int regulator_lock_nested(struct regulator_dev *rdev, * than the one, which initially locked the mutex, it will * wait on mutex. */ -void regulator_lock(struct regulator_dev *rdev) +static void regulator_lock(struct regulator_dev *rdev) { regulator_lock_nested(rdev, NULL); } -EXPORT_SYMBOL_GPL(regulator_lock); /** * regulator_unlock - unlock a single regulator @@ -203,7 +202,7 @@ EXPORT_SYMBOL_GPL(regulator_lock); * This function unlocks the mutex when the * reference counter reaches 0. */ -void regulator_unlock(struct regulator_dev *rdev) +static void regulator_unlock(struct regulator_dev *rdev) { mutex_lock(®ulator_nesting_mutex); @@ -216,7 +215,6 @@ void regulator_unlock(struct regulator_dev *rdev) mutex_unlock(®ulator_nesting_mutex); } -EXPORT_SYMBOL_GPL(regulator_unlock); static bool regulator_supply_is_couple(struct regulator_dev *rdev) { @@ -409,11 +407,11 @@ err_node_put: static struct device_node *of_get_regulator(struct device *dev, const char *supply) { struct device_node *regnode = NULL; - char prop_name[32]; /* 32 is max size of property name */ + char prop_name[64]; /* 64 is max size of property name */ dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); - snprintf(prop_name, 32, "%s-supply", supply); + snprintf(prop_name, 64, "%s-supply", supply); regnode = of_parse_phandle(dev->of_node, prop_name, 0); if (!regnode) { @@ -568,6 +566,30 @@ regulator_get_suspend_state(struct regulator_dev *rdev, suspend_state_t state) } } +static const struct regulator_state * +regulator_get_suspend_state_check(struct regulator_dev *rdev, suspend_state_t state) +{ + const struct regulator_state *rstate; + + rstate = regulator_get_suspend_state(rdev, state); + if (rstate == NULL) + return NULL; + + /* If we have no suspend mode configuration don't set anything; + * only warn if the driver implements set_suspend_voltage or + * set_suspend_mode callback. + */ + if (rstate->enabled != ENABLE_IN_SUSPEND && + rstate->enabled != DISABLE_IN_SUSPEND) { + if (rdev->desc->ops->set_suspend_voltage || + rdev->desc->ops->set_suspend_mode) + rdev_warn(rdev, "No configuration\n"); + return NULL; + } + + return rstate; +} + static ssize_t regulator_uV_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -945,7 +967,8 @@ static int drms_uA_update(struct regulator_dev *rdev) /* set the optimum mode for our new total regulator load */ err = rdev->desc->ops->set_load(rdev, current_uA); if (err < 0) - rdev_err(rdev, "failed to set load %d\n", current_uA); + rdev_err(rdev, "failed to set load %d: %pe\n", + current_uA, ERR_PTR(err)); } else { /* get output voltage */ output_uV = regulator_get_voltage_rdev(rdev); @@ -972,40 +995,24 @@ static int drms_uA_update(struct regulator_dev *rdev) /* check the new mode is allowed */ err = regulator_mode_constrain(rdev, &mode); if (err < 0) { - rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", - current_uA, input_uV, output_uV); + rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV: %pe\n", + current_uA, input_uV, output_uV, ERR_PTR(err)); return err; } err = rdev->desc->ops->set_mode(rdev, mode); if (err < 0) - rdev_err(rdev, "failed to set optimum mode %x\n", mode); + rdev_err(rdev, "failed to set optimum mode %x: %pe\n", + mode, ERR_PTR(err)); } return err; } -static int suspend_set_state(struct regulator_dev *rdev, - suspend_state_t state) +static int __suspend_set_state(struct regulator_dev *rdev, + const struct regulator_state *rstate) { int ret = 0; - struct regulator_state *rstate; - - rstate = regulator_get_suspend_state(rdev, state); - if (rstate == NULL) - return 0; - - /* If we have no suspend mode configuration don't set anything; - * only warn if the driver implements set_suspend_voltage or - * set_suspend_mode callback. - */ - if (rstate->enabled != ENABLE_IN_SUSPEND && - rstate->enabled != DISABLE_IN_SUSPEND) { - if (rdev->desc->ops->set_suspend_voltage || - rdev->desc->ops->set_suspend_mode) - rdev_warn(rdev, "No configuration\n"); - return 0; - } if (rstate->enabled == ENABLE_IN_SUSPEND && rdev->desc->ops->set_suspend_enable) @@ -1017,14 +1024,14 @@ static int suspend_set_state(struct regulator_dev *rdev, ret = 0; if (ret < 0) { - rdev_err(rdev, "failed to enabled/disable\n"); + rdev_err(rdev, "failed to enabled/disable: %pe\n", ERR_PTR(ret)); return ret; } if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); if (ret < 0) { - rdev_err(rdev, "failed to set voltage\n"); + rdev_err(rdev, "failed to set voltage: %pe\n", ERR_PTR(ret)); return ret; } } @@ -1032,7 +1039,7 @@ static int suspend_set_state(struct regulator_dev *rdev, if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); if (ret < 0) { - rdev_err(rdev, "failed to set mode\n"); + rdev_err(rdev, "failed to set mode: %pe\n", ERR_PTR(ret)); return ret; } } @@ -1040,7 +1047,20 @@ static int suspend_set_state(struct regulator_dev *rdev, return ret; } -static void print_constraints(struct regulator_dev *rdev) +static int suspend_set_initial_state(struct regulator_dev *rdev) +{ + const struct regulator_state *rstate; + + rstate = regulator_get_suspend_state_check(rdev, + rdev->constraints->initial_state); + if (!rstate) + return 0; + + return __suspend_set_state(rdev, rstate); +} + +#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) +static void print_constraints_debug(struct regulator_dev *rdev) { struct regulation_constraints *constraints = rdev->constraints; char buf[160] = ""; @@ -1097,12 +1117,27 @@ static void print_constraints(struct regulator_dev *rdev) if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) count += scnprintf(buf + count, len - count, "idle "); if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) - count += scnprintf(buf + count, len - count, "standby"); + count += scnprintf(buf + count, len - count, "standby "); if (!count) - scnprintf(buf, len, "no parameters"); + count = scnprintf(buf, len, "no parameters"); + else + --count; + + count += scnprintf(buf + count, len - count, ", %s", + _regulator_is_enabled(rdev) ? "enabled" : "disabled"); rdev_dbg(rdev, "%s\n", buf); +} +#else /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */ +static inline void print_constraints_debug(struct regulator_dev *rdev) {} +#endif /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */ + +static void print_constraints(struct regulator_dev *rdev) +{ + struct regulation_constraints *constraints = rdev->constraints; + + print_constraints_debug(rdev); if ((constraints->min_uV != constraints->max_uV) && !regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) @@ -1135,8 +1170,8 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, if (current_uV < 0) { rdev_err(rdev, - "failed to get the current voltage(%d)\n", - current_uV); + "failed to get the current voltage: %pe\n", + ERR_PTR(current_uV)); return current_uV; } @@ -1165,8 +1200,8 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, rdev, target_min, target_max); if (ret < 0) { rdev_err(rdev, - "failed to apply %d-%duV constraint(%d)\n", - target_min, target_max, ret); + "failed to apply %d-%duV constraint: %pe\n", + target_min, target_max, ERR_PTR(ret)); return ret; } } @@ -1315,16 +1350,16 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = ops->set_input_current_limit(rdev, rdev->constraints->ilim_uA); if (ret < 0) { - rdev_err(rdev, "failed to set input limit\n"); + rdev_err(rdev, "failed to set input limit: %pe\n", ERR_PTR(ret)); return ret; } } /* do we need to setup our suspend state */ if (rdev->constraints->initial_state) { - ret = suspend_set_state(rdev, rdev->constraints->initial_state); + ret = suspend_set_initial_state(rdev); if (ret < 0) { - rdev_err(rdev, "failed to set suspend state\n"); + rdev_err(rdev, "failed to set suspend state: %pe\n", ERR_PTR(ret)); return ret; } } @@ -1337,7 +1372,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = ops->set_mode(rdev, rdev->constraints->initial_mode); if (ret < 0) { - rdev_err(rdev, "failed to set initial mode: %d\n", ret); + rdev_err(rdev, "failed to set initial mode: %pe\n", ERR_PTR(ret)); return ret; } } else if (rdev->constraints->system_load) { @@ -1352,7 +1387,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, && ops->set_ramp_delay) { ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); if (ret < 0) { - rdev_err(rdev, "failed to set ramp_delay\n"); + rdev_err(rdev, "failed to set ramp_delay: %pe\n", ERR_PTR(ret)); return ret; } } @@ -1360,7 +1395,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, if (rdev->constraints->pull_down && ops->set_pull_down) { ret = ops->set_pull_down(rdev); if (ret < 0) { - rdev_err(rdev, "failed to set pull down\n"); + rdev_err(rdev, "failed to set pull down: %pe\n", ERR_PTR(ret)); return ret; } } @@ -1368,7 +1403,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, if (rdev->constraints->soft_start && ops->set_soft_start) { ret = ops->set_soft_start(rdev); if (ret < 0) { - rdev_err(rdev, "failed to set soft start\n"); + rdev_err(rdev, "failed to set soft start: %pe\n", ERR_PTR(ret)); return ret; } } @@ -1377,7 +1412,8 @@ static int set_machine_constraints(struct regulator_dev *rdev, && ops->set_over_current_protection) { ret = ops->set_over_current_protection(rdev); if (ret < 0) { - rdev_err(rdev, "failed to set over current protection\n"); + rdev_err(rdev, "failed to set over current protection: %pe\n", + ERR_PTR(ret)); return ret; } } @@ -1388,7 +1424,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = ops->set_active_discharge(rdev, ad_state); if (ret < 0) { - rdev_err(rdev, "failed to set active discharge\n"); + rdev_err(rdev, "failed to set active discharge: %pe\n", ERR_PTR(ret)); return ret; } } @@ -1408,7 +1444,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = _regulator_do_enable(rdev); if (ret < 0 && ret != -EINVAL) { - rdev_err(rdev, "failed to enable\n"); + rdev_err(rdev, "failed to enable: %pe\n", ERR_PTR(ret)); return ret; } @@ -1632,8 +1668,8 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj, supply_name); if (err) { - rdev_dbg(rdev, "could not add device link %s err %d\n", - dev->kobj.name, err); + rdev_dbg(rdev, "could not add device link %s: %pe\n", + dev->kobj.name, ERR_PTR(err)); /* non-fatal */ } } @@ -2421,7 +2457,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev) if (ret >= 0) { delay = ret; } else { - rdev_warn(rdev, "enable_time() failed: %d\n", ret); + rdev_warn(rdev, "enable_time() failed: %pe\n", ERR_PTR(ret)); delay = 0; } @@ -2610,7 +2646,7 @@ static int _regulator_enable(struct regulator *regulator) _notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE, NULL); } else if (ret < 0) { - rdev_err(rdev, "is_enabled() failed: %d\n", ret); + rdev_err(rdev, "is_enabled() failed: %pe\n", ERR_PTR(ret)); goto err_consumer_disable; } /* Fallthrough on positive return values - already enabled */ @@ -2712,7 +2748,7 @@ static int _regulator_disable(struct regulator *regulator) ret = _regulator_do_disable(rdev); if (ret < 0) { - rdev_err(rdev, "failed to disable\n"); + rdev_err(rdev, "failed to disable: %pe\n", ERR_PTR(ret)); _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_DISABLE, NULL); @@ -2779,7 +2815,7 @@ static int _regulator_force_disable(struct regulator_dev *rdev) ret = _regulator_do_disable(rdev); if (ret < 0) { - rdev_err(rdev, "failed to force disable\n"); + rdev_err(rdev, "failed to force disable: %pe\n", ERR_PTR(ret)); _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | REGULATOR_EVENT_ABORT_DISABLE, NULL); return ret; @@ -2858,7 +2894,8 @@ static void regulator_disable_work(struct work_struct *work) for (i = 0; i < count; i++) { ret = _regulator_disable(regulator); if (ret != 0) - rdev_err(rdev, "Deferred disable failed: %d\n", ret); + rdev_err(rdev, "Deferred disable failed: %pe\n", + ERR_PTR(ret)); } } WARN_ON(!total_count); @@ -3051,7 +3088,7 @@ int regulator_get_hardware_vsel_register(struct regulator *regulator, *vsel_reg = rdev->desc->vsel_reg; *vsel_mask = rdev->desc->vsel_mask; - return 0; + return 0; } EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register); @@ -3383,7 +3420,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, } if (delay < 0) { - rdev_warn(rdev, "failed to get delay: %d\n", delay); + rdev_warn(rdev, "failed to get delay: %pe\n", ERR_PTR(delay)); delay = 0; } @@ -3535,8 +3572,8 @@ int regulator_set_voltage_rdev(struct regulator_dev *rdev, int min_uV, ret = regulator_set_voltage_unlocked(rdev->supply, best_supply_uV, INT_MAX, state); if (ret) { - dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n", - ret); + dev_err(&rdev->dev, "Failed to increase supply voltage: %pe\n", + ERR_PTR(ret)); goto out; } } @@ -3553,8 +3590,8 @@ int regulator_set_voltage_rdev(struct regulator_dev *rdev, int min_uV, ret = regulator_set_voltage_unlocked(rdev->supply, best_supply_uV, INT_MAX, state); if (ret) - dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n", - ret); + dev_warn(&rdev->dev, "Failed to decrease supply voltage: %pe\n", + ERR_PTR(ret)); /* No need to fail here */ ret = 0; } @@ -4540,8 +4577,8 @@ int regulator_bulk_get(struct device *dev, int num_consumers, err: if (ret != -EPROBE_DEFER) - dev_err(dev, "Failed to get supply '%s': %d\n", - consumers[i].supply, ret); + dev_err(dev, "Failed to get supply '%s': %pe\n", + consumers[i].supply, ERR_PTR(ret)); else dev_dbg(dev, "Failed to get supply '%s', deferring\n", consumers[i].supply); @@ -4599,8 +4636,8 @@ int regulator_bulk_enable(int num_consumers, err: for (i = 0; i < num_consumers; i++) { if (consumers[i].ret < 0) - pr_err("Failed to enable %s: %d\n", consumers[i].supply, - consumers[i].ret); + pr_err("Failed to enable %s: %pe\n", consumers[i].supply, + ERR_PTR(consumers[i].ret)); else regulator_disable(consumers[i].consumer); } @@ -4636,12 +4673,12 @@ int regulator_bulk_disable(int num_consumers, return 0; err: - pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); + pr_err("Failed to disable %s: %pe\n", consumers[i].supply, ERR_PTR(ret)); for (++i; i < num_consumers; ++i) { r = regulator_enable(consumers[i].consumer); if (r != 0) - pr_err("Failed to re-enable %s: %d\n", - consumers[i].supply, r); + pr_err("Failed to re-enable %s: %pe\n", + consumers[i].supply, ERR_PTR(r)); } return ret; @@ -4709,14 +4746,11 @@ EXPORT_SYMBOL_GPL(regulator_bulk_free); * @data: callback-specific data. * * Called by regulator drivers to notify clients a regulator event has - * occurred. We also notify regulator clients downstream. - * Note lock must be held by caller. + * occurred. */ int regulator_notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data) { - lockdep_assert_held_once(&rdev->mutex.base); - _notifier_call_chain(rdev, event, data); return NOTIFY_DONE; @@ -5023,8 +5057,8 @@ static void regulator_remove_coupling(struct regulator_dev *rdev) if (coupler && coupler->detach_regulator) { err = coupler->detach_regulator(coupler, rdev); if (err) - rdev_err(rdev, "failed to detach from coupler: %d\n", - err); + rdev_err(rdev, "failed to detach from coupler: %pe\n", + ERR_PTR(err)); } kfree(rdev->coupling_desc.coupled_rdevs); @@ -5033,20 +5067,20 @@ static void regulator_remove_coupling(struct regulator_dev *rdev) static int regulator_init_coupling(struct regulator_dev *rdev) { + struct regulator_dev **coupled; int err, n_phandles; - size_t alloc_size; if (!IS_ENABLED(CONFIG_OF)) n_phandles = 0; else n_phandles = of_get_n_coupled(rdev); - alloc_size = sizeof(*rdev) * (n_phandles + 1); - - rdev->coupling_desc.coupled_rdevs = kzalloc(alloc_size, GFP_KERNEL); - if (!rdev->coupling_desc.coupled_rdevs) + coupled = kcalloc(n_phandles + 1, sizeof(*coupled), GFP_KERNEL); + if (!coupled) return -ENOMEM; + rdev->coupling_desc.coupled_rdevs = coupled; + /* * Every regulator should always have coupling descriptor filled with * at least pointer to itself. @@ -5068,7 +5102,7 @@ static int regulator_init_coupling(struct regulator_dev *rdev) if (IS_ERR(rdev->coupling_desc.coupler)) { err = PTR_ERR(rdev->coupling_desc.coupler); - rdev_err(rdev, "failed to get coupler: %d\n", err); + rdev_err(rdev, "failed to get coupler: %pe\n", ERR_PTR(err)); return err; } @@ -5231,8 +5265,8 @@ regulator_register(const struct regulator_desc *regulator_desc, if (config->ena_gpiod) { ret = regulator_ena_gpio_request(rdev, config); if (ret != 0) { - rdev_err(rdev, "Failed to request enable GPIO: %d\n", - ret); + rdev_err(rdev, "Failed to request enable GPIO: %pe\n", + ERR_PTR(ret)); goto clean; } /* The regulator core took over the GPIO descriptor */ @@ -5256,15 +5290,20 @@ regulator_register(const struct regulator_desc *regulator_desc, else if (regulator_desc->supply_name) rdev->supply_name = regulator_desc->supply_name; - /* - * Attempt to resolve the regulator supply, if specified, - * but don't return an error if we fail because we will try - * to resolve it again later as more regulators are added. - */ - if (regulator_resolve_supply(rdev)) - rdev_dbg(rdev, "unable to resolve supply\n"); - ret = set_machine_constraints(rdev, constraints); + if (ret == -EPROBE_DEFER) { + /* Regulator might be in bypass mode and so needs its supply + * to set the constraints */ + /* FIXME: this currently triggers a chicken-and-egg problem + * when creating -SUPPLY symlink in sysfs to a regulator + * that is just being created */ + ret = regulator_resolve_supply(rdev); + if (!ret) + ret = set_machine_constraints(rdev, constraints); + else + rdev_dbg(rdev, "unable to resolve supply early: %pe\n", + ERR_PTR(ret)); + } if (ret < 0) goto wash; @@ -5375,9 +5414,14 @@ static int regulator_suspend(struct device *dev) struct regulator_dev *rdev = dev_to_rdev(dev); suspend_state_t state = pm_suspend_target_state; int ret; + const struct regulator_state *rstate; + + rstate = regulator_get_suspend_state_check(rdev, state); + if (!rstate) + return 0; regulator_lock(rdev); - ret = suspend_set_state(rdev, state); + ret = __suspend_set_state(rdev, rstate); regulator_unlock(rdev); return ret; @@ -5394,11 +5438,14 @@ static int regulator_resume(struct device *dev) if (rstate == NULL) return 0; + /* Avoid grabbing the lock if we don't need to */ + if (!rdev->desc->ops->resume) + return 0; + regulator_lock(rdev); - if (rdev->desc->ops->resume && - (rstate->enabled == ENABLE_IN_SUSPEND || - rstate->enabled == DISABLE_IN_SUSPEND)) + if (rstate->enabled == ENABLE_IN_SUSPEND || + rstate->enabled == DISABLE_IN_SUSPEND) ret = rdev->desc->ops->resume(rdev); regulator_unlock(rdev); @@ -5809,7 +5856,7 @@ static int regulator_late_cleanup(struct device *dev, void *data) rdev_info(rdev, "disabling\n"); ret = _regulator_do_disable(rdev); if (ret != 0) - rdev_err(rdev, "couldn't disable: %d\n", ret); + rdev_err(rdev, "couldn't disable: %pe\n", ERR_PTR(ret)); } else { /* The intention is that in future we will * assume that full constraints are provided diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c index c025ccb1a30a..73ff5fc7d8d7 100644 --- a/drivers/regulator/da9055-regulator.c +++ b/drivers/regulator/da9055-regulator.c @@ -485,10 +485,8 @@ static irqreturn_t da9055_ldo5_6_oc_irq(int irq, void *data) { struct da9055_regulator *regulator = data; - regulator_lock(regulator->rdev); regulator_notifier_call_chain(regulator->rdev, REGULATOR_EVENT_OVER_CURRENT, NULL); - regulator_unlock(regulator->rdev); return IRQ_HANDLED; } diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c index d8112f56e94e..1a6324001027 100644 --- a/drivers/regulator/da9062-regulator.c +++ b/drivers/regulator/da9062-regulator.c @@ -907,10 +907,8 @@ static irqreturn_t da9062_ldo_lim_event(int irq, void *data) continue; if (BIT(regl->info->oc_event.lsb) & bits) { - regulator_lock(regl->rdev); regulator_notifier_call_chain(regl->rdev, REGULATOR_EVENT_OVER_CURRENT, NULL); - regulator_unlock(regl->rdev); handled = IRQ_HANDLED; } } diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index fe65b5acaf28..cf7d5341750e 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -574,10 +574,8 @@ static irqreturn_t da9063_ldo_lim_event(int irq, void *data) continue; if (BIT(regl->info->oc_event.lsb) & bits) { - regulator_lock(regl->rdev); regulator_notifier_call_chain(regl->rdev, REGULATOR_EVENT_OVER_CURRENT, NULL); - regulator_unlock(regl->rdev); } } diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c index 0cdeb6186529..7493af0b5c04 100644 --- a/drivers/regulator/da9210-regulator.c +++ b/drivers/regulator/da9210-regulator.c @@ -77,8 +77,6 @@ static irqreturn_t da9210_irq_handler(int irq, void *data) if (error < 0) goto error_i2c; - regulator_lock(chip->rdev); - if (val & DA9210_E_OVCURR) { regulator_notifier_call_chain(chip->rdev, REGULATOR_EVENT_OVER_CURRENT, @@ -103,8 +101,6 @@ static irqreturn_t da9210_irq_handler(int irq, void *data) handled |= DA9210_E_VMAX; } - regulator_unlock(chip->rdev); - if (handled) { /* Clear handled events */ error = regmap_write(chip->regmap, DA9210_REG_EVENT_B, handled); @@ -125,7 +121,7 @@ error_i2c: * I2C driver interface functions */ -static const struct of_device_id da9210_dt_ids[] = { +static const struct of_device_id __maybe_unused da9210_dt_ids[] = { { .compatible = "dlg,da9210", }, { } }; diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c index 297b3aa7c753..e01b32d1fa17 100644 --- a/drivers/regulator/da9211-regulator.c +++ b/drivers/regulator/da9211-regulator.c @@ -51,10 +51,24 @@ static const struct regmap_range_cfg da9211_regmap_range[] = { }, }; +static bool da9211_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case DA9211_REG_STATUS_A: + case DA9211_REG_STATUS_B: + case DA9211_REG_EVENT_A: + case DA9211_REG_EVENT_B: + return true; + } + return false; +} + static const struct regmap_config da9211_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = 5 * 128, + .volatile_reg = da9211_volatile_reg, + .cache_type = REGCACHE_RBTREE, .ranges = da9211_regmap_range, .num_ranges = ARRAY_SIZE(da9211_regmap_range), }; @@ -332,10 +346,8 @@ static irqreturn_t da9211_irq_handler(int irq, void *data) goto error_i2c; if (reg_val & DA9211_E_OV_CURR_A) { - regulator_lock(chip->rdev[0]); regulator_notifier_call_chain(chip->rdev[0], REGULATOR_EVENT_OVER_CURRENT, NULL); - regulator_unlock(chip->rdev[0]); err = regmap_write(chip->regmap, DA9211_REG_EVENT_B, DA9211_E_OV_CURR_A); @@ -346,10 +358,8 @@ static irqreturn_t da9211_irq_handler(int irq, void *data) } if (reg_val & DA9211_E_OV_CURR_B) { - regulator_lock(chip->rdev[1]); regulator_notifier_call_chain(chip->rdev[1], REGULATOR_EVENT_OVER_CURRENT, NULL); - regulator_unlock(chip->rdev[1]); err = regmap_write(chip->regmap, DA9211_REG_EVENT_B, DA9211_E_OV_CURR_B); diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c index c3ad6aa6b5d3..8b70bfe88019 100644 --- a/drivers/regulator/dbx500-prcmu.c +++ b/drivers/regulator/dbx500-prcmu.c @@ -67,8 +67,6 @@ static int power_state_active_get(void) static struct ux500_regulator_debug { struct dentry *dir; - struct dentry *status_file; - struct dentry *power_state_cnt_file; struct dbx500_regulator_info *regulator_array; int num_regulators; u8 *state_before_suspend; @@ -117,22 +115,14 @@ ux500_regulator_debug_init(struct platform_device *pdev, { /* create directory */ rdebug.dir = debugfs_create_dir("ux500-regulator", NULL); - if (!rdebug.dir) - goto exit_no_debugfs; /* create "status" file */ - rdebug.status_file = debugfs_create_file("status", - S_IRUGO, rdebug.dir, &pdev->dev, - &ux500_regulator_status_fops); - if (!rdebug.status_file) - goto exit_destroy_dir; + debugfs_create_file("status", S_IRUGO, rdebug.dir, &pdev->dev, + &ux500_regulator_status_fops); /* create "power-state-count" file */ - rdebug.power_state_cnt_file = debugfs_create_file("power-state-count", - S_IRUGO, rdebug.dir, &pdev->dev, - &ux500_regulator_power_state_cnt_fops); - if (!rdebug.power_state_cnt_file) - goto exit_destroy_status; + debugfs_create_file("power-state-count", S_IRUGO, rdebug.dir, + &pdev->dev, &ux500_regulator_power_state_cnt_fops); rdebug.regulator_array = regulator_info; rdebug.num_regulators = num_regulators; @@ -150,13 +140,7 @@ ux500_regulator_debug_init(struct platform_device *pdev, exit_free: kfree(rdebug.state_before_suspend); exit_destroy_power_state: - debugfs_remove(rdebug.power_state_cnt_file); -exit_destroy_status: - debugfs_remove(rdebug.status_file); -exit_destroy_dir: - debugfs_remove(rdebug.dir); -exit_no_debugfs: - dev_err(&pdev->dev, "failed to create debugfs entries.\n"); + debugfs_remove_recursive(rdebug.dir); return -ENOMEM; } diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c index 74de6983c61a..d8059f596391 100644 --- a/drivers/regulator/dummy.c +++ b/drivers/regulator/dummy.c @@ -21,13 +21,13 @@ struct regulator_dev *dummy_regulator_rdev; -static struct regulator_init_data dummy_initdata = { +static const struct regulator_init_data dummy_initdata = { .constraints = { .always_on = 1, }, }; -static struct regulator_ops dummy_ops; +static const struct regulator_ops dummy_ops; static const struct regulator_desc dummy_desc = { .name = "regulator-dummy", diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 00c83492f774..aa426183b6a1 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -436,7 +436,7 @@ static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev, return pdata; } -static const struct of_device_id fan53555_dt_ids[] = { +static const struct of_device_id __maybe_unused fan53555_dt_ids[] = { { .compatible = "fcs,fan53526", .data = (void *)FAN53526_VENDOR_FAIRCHILD, diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 142a70a89153..3de7709bdcd4 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -41,14 +41,6 @@ struct fixed_dev_type { bool has_enable_clock; }; -static const struct fixed_dev_type fixed_voltage_data = { - .has_enable_clock = false, -}; - -static const struct fixed_dev_type fixed_clkenable_data = { - .has_enable_clock = true, -}; - static int reg_clock_enable(struct regulator_dev *rdev) { struct fixed_voltage_data *priv = rdev_get_drvdata(rdev); @@ -131,10 +123,10 @@ of_get_fixed_voltage_config(struct device *dev, return config; } -static struct regulator_ops fixed_voltage_ops = { +static const struct regulator_ops fixed_voltage_ops = { }; -static struct regulator_ops fixed_voltage_clkenabled_ops = { +static const struct regulator_ops fixed_voltage_clkenabled_ops = { .enable = reg_clock_enable, .disable = reg_clock_disable, .is_enabled = reg_clock_is_enabled, @@ -260,6 +252,14 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) } #if defined(CONFIG_OF) +static const struct fixed_dev_type fixed_voltage_data = { + .has_enable_clock = false, +}; + +static const struct fixed_dev_type fixed_clkenable_data = { + .has_enable_clock = true, +}; + static const struct of_device_id fixed_of_match[] = { { .compatible = "regulator-fixed", diff --git a/drivers/regulator/lochnagar-regulator.c b/drivers/regulator/lochnagar-regulator.c index 5ea3e4141684..cb71fa5f43c3 100644 --- a/drivers/regulator/lochnagar-regulator.c +++ b/drivers/regulator/lochnagar-regulator.c @@ -98,6 +98,7 @@ static const struct regulator_ops lochnagar_vddcore_ops = { }; static const struct linear_range lochnagar_vddcore_ranges[] = { + REGULATOR_LINEAR_RANGE(600000, 0, 0x7, 0), REGULATOR_LINEAR_RANGE(600000, 0x8, 0x41, 12500), }; diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index 4291df077c39..13c535711265 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -49,53 +49,15 @@ struct lp8755_chip { struct regulator_dev *rdev[LP8755_BUCK_MAX]; }; -/** - *lp8755_read : read a single register value from lp8755. - *@pchip : device to read from - *@reg : register to read from - *@val : pointer to store read value - */ -static int lp8755_read(struct lp8755_chip *pchip, unsigned int reg, - unsigned int *val) -{ - return regmap_read(pchip->regmap, reg, val); -} - -/** - *lp8755_write : write a single register value to lp8755. - *@pchip : device to write to - *@reg : register to write to - *@val : value to be written - */ -static int lp8755_write(struct lp8755_chip *pchip, unsigned int reg, - unsigned int val) -{ - return regmap_write(pchip->regmap, reg, val); -} - -/** - *lp8755_update_bits : set the values of bit fields in lp8755 register. - *@pchip : device to read from - *@reg : register to update - *@mask : bitmask to be changed - *@val : value for bitmask - */ -static int lp8755_update_bits(struct lp8755_chip *pchip, unsigned int reg, - unsigned int mask, unsigned int val) -{ - return regmap_update_bits(pchip->regmap, reg, mask, val); -} - static int lp8755_buck_enable_time(struct regulator_dev *rdev) { int ret; unsigned int regval; enum lp8755_bucks id = rdev_get_id(rdev); - struct lp8755_chip *pchip = rdev_get_drvdata(rdev); - ret = lp8755_read(pchip, 0x12 + id, ®val); + ret = regmap_read(rdev->regmap, 0x12 + id, ®val); if (ret < 0) { - dev_err(pchip->dev, "i2c access error %s\n", __func__); + dev_err(&rdev->dev, "i2c access error %s\n", __func__); return ret; } return (regval & 0xff) * 100; @@ -115,17 +77,17 @@ static int lp8755_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) break; case REGULATOR_MODE_NORMAL: /* enable automatic pwm/pfm mode */ - ret = lp8755_update_bits(pchip, 0x08 + id, 0x20, 0x00); + ret = regmap_update_bits(rdev->regmap, 0x08 + id, 0x20, 0x00); if (ret < 0) goto err_i2c; break; case REGULATOR_MODE_IDLE: /* enable automatic pwm/pfm/lppfm mode */ - ret = lp8755_update_bits(pchip, 0x08 + id, 0x20, 0x20); + ret = regmap_update_bits(rdev->regmap, 0x08 + id, 0x20, 0x20); if (ret < 0) goto err_i2c; - ret = lp8755_update_bits(pchip, 0x10, 0x01, 0x01); + ret = regmap_update_bits(rdev->regmap, 0x10, 0x01, 0x01); if (ret < 0) goto err_i2c; break; @@ -135,12 +97,12 @@ static int lp8755_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) regbval = (0x01 << id); } - ret = lp8755_update_bits(pchip, 0x06, 0x01 << id, regbval); + ret = regmap_update_bits(rdev->regmap, 0x06, 0x01 << id, regbval); if (ret < 0) goto err_i2c; return ret; err_i2c: - dev_err(pchip->dev, "i2c access error %s\n", __func__); + dev_err(&rdev->dev, "i2c access error %s\n", __func__); return ret; } @@ -149,9 +111,8 @@ static unsigned int lp8755_buck_get_mode(struct regulator_dev *rdev) int ret; unsigned int regval; enum lp8755_bucks id = rdev_get_id(rdev); - struct lp8755_chip *pchip = rdev_get_drvdata(rdev); - ret = lp8755_read(pchip, 0x06, ®val); + ret = regmap_read(rdev->regmap, 0x06, ®val); if (ret < 0) goto err_i2c; @@ -159,7 +120,7 @@ static unsigned int lp8755_buck_get_mode(struct regulator_dev *rdev) if (regval & (0x01 << id)) return REGULATOR_MODE_FAST; - ret = lp8755_read(pchip, 0x08 + id, ®val); + ret = regmap_read(rdev->regmap, 0x08 + id, ®val); if (ret < 0) goto err_i2c; @@ -171,7 +132,7 @@ static unsigned int lp8755_buck_get_mode(struct regulator_dev *rdev) return REGULATOR_MODE_NORMAL; err_i2c: - dev_err(pchip->dev, "i2c access error %s\n", __func__); + dev_err(&rdev->dev, "i2c access error %s\n", __func__); return 0; } @@ -180,7 +141,6 @@ static int lp8755_buck_set_ramp(struct regulator_dev *rdev, int ramp) int ret; unsigned int regval = 0x00; enum lp8755_bucks id = rdev_get_id(rdev); - struct lp8755_chip *pchip = rdev_get_drvdata(rdev); /* uV/us */ switch (ramp) { @@ -209,17 +169,17 @@ static int lp8755_buck_set_ramp(struct regulator_dev *rdev, int ramp) regval = 0x00; break; default: - dev_err(pchip->dev, + dev_err(&rdev->dev, "Not supported ramp value %d %s\n", ramp, __func__); return -EINVAL; } - ret = lp8755_update_bits(pchip, 0x07 + id, 0x07, regval); + ret = regmap_update_bits(rdev->regmap, 0x07 + id, 0x07, regval); if (ret < 0) goto err_i2c; return ret; err_i2c: - dev_err(pchip->dev, "i2c access error %s\n", __func__); + dev_err(&rdev->dev, "i2c access error %s\n", __func__); return ret; } @@ -278,7 +238,7 @@ static int lp8755_init_data(struct lp8755_chip *pchip) struct lp8755_platform_data *pdata = pchip->pdata; /* read back muti-phase configuration */ - ret = lp8755_read(pchip, 0x3D, ®val); + ret = regmap_read(pchip->regmap, 0x3D, ®val); if (ret < 0) goto out_i2c_error; pchip->mphase = regval & 0x0F; @@ -356,11 +316,11 @@ static irqreturn_t lp8755_irq_handler(int irq, void *data) struct lp8755_chip *pchip = data; /* read flag0 register */ - ret = lp8755_read(pchip, 0x0D, &flag0); + ret = regmap_read(pchip->regmap, 0x0D, &flag0); if (ret < 0) goto err_i2c; /* clear flag register to pull up int. pin */ - ret = lp8755_write(pchip, 0x0D, 0x00); + ret = regmap_write(pchip->regmap, 0x0D, 0x00); if (ret < 0) goto err_i2c; @@ -369,19 +329,17 @@ static irqreturn_t lp8755_irq_handler(int irq, void *data) if ((flag0 & (0x4 << icnt)) && (pchip->irqmask & (0x04 << icnt)) && (pchip->rdev[icnt] != NULL)) { - regulator_lock(pchip->rdev[icnt]); regulator_notifier_call_chain(pchip->rdev[icnt], LP8755_EVENT_PWR_FAULT, NULL); - regulator_unlock(pchip->rdev[icnt]); } /* read flag1 register */ - ret = lp8755_read(pchip, 0x0E, &flag1); + ret = regmap_read(pchip->regmap, 0x0E, &flag1); if (ret < 0) goto err_i2c; /* clear flag register to pull up int. pin */ - ret = lp8755_write(pchip, 0x0E, 0x00); + ret = regmap_write(pchip->regmap, 0x0E, 0x00); if (ret < 0) goto err_i2c; @@ -389,22 +347,18 @@ static irqreturn_t lp8755_irq_handler(int irq, void *data) if ((flag1 & 0x01) && (pchip->irqmask & 0x01)) for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) if (pchip->rdev[icnt] != NULL) { - regulator_lock(pchip->rdev[icnt]); regulator_notifier_call_chain(pchip->rdev[icnt], LP8755_EVENT_OCP, NULL); - regulator_unlock(pchip->rdev[icnt]); } /* send OVP event to all regulator devices */ if ((flag1 & 0x02) && (pchip->irqmask & 0x02)) for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) if (pchip->rdev[icnt] != NULL) { - regulator_lock(pchip->rdev[icnt]); regulator_notifier_call_chain(pchip->rdev[icnt], LP8755_EVENT_OVP, NULL); - regulator_unlock(pchip->rdev[icnt]); } return IRQ_HANDLED; @@ -423,7 +377,7 @@ static int lp8755_int_config(struct lp8755_chip *pchip) return 0; } - ret = lp8755_read(pchip, 0x0F, ®val); + ret = regmap_read(pchip->regmap, 0x0F, ®val); if (ret < 0) { dev_err(pchip->dev, "i2c access error %s\n", __func__); return ret; @@ -502,7 +456,7 @@ static int lp8755_probe(struct i2c_client *client, err: /* output disable */ for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) - lp8755_write(pchip, icnt, 0x00); + regmap_write(pchip->regmap, icnt, 0x00); return ret; } @@ -513,7 +467,7 @@ static int lp8755_remove(struct i2c_client *client) struct lp8755_chip *pchip = i2c_get_clientdata(client); for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) - lp8755_write(pchip, icnt, 0x00); + regmap_write(pchip->regmap, icnt, 0x00); return 0; } diff --git a/drivers/regulator/ltc3589.c b/drivers/regulator/ltc3589.c index 9a037fdc5fc5..38f7ccb63b52 100644 --- a/drivers/regulator/ltc3589.c +++ b/drivers/regulator/ltc3589.c @@ -357,22 +357,16 @@ static irqreturn_t ltc3589_isr(int irq, void *dev_id) if (irqstat & LTC3589_IRQSTAT_THERMAL_WARN) { event = REGULATOR_EVENT_OVER_TEMP; - for (i = 0; i < LTC3589_NUM_REGULATORS; i++) { - regulator_lock(ltc3589->regulators[i]); + for (i = 0; i < LTC3589_NUM_REGULATORS; i++) regulator_notifier_call_chain(ltc3589->regulators[i], event, NULL); - regulator_unlock(ltc3589->regulators[i]); - } } if (irqstat & LTC3589_IRQSTAT_UNDERVOLT_WARN) { event = REGULATOR_EVENT_UNDER_VOLTAGE; - for (i = 0; i < LTC3589_NUM_REGULATORS; i++) { - regulator_lock(ltc3589->regulators[i]); + for (i = 0; i < LTC3589_NUM_REGULATORS; i++) regulator_notifier_call_chain(ltc3589->regulators[i], event, NULL); - regulator_unlock(ltc3589->regulators[i]); - } } /* Clear warning condition */ @@ -457,7 +451,7 @@ static const struct i2c_device_id ltc3589_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, ltc3589_i2c_id); -static const struct of_device_id ltc3589_of_match[] = { +static const struct of_device_id __maybe_unused ltc3589_of_match[] = { { .compatible = "lltc,ltc3589", .data = (void *)LTC3589, diff --git a/drivers/regulator/ltc3676.c b/drivers/regulator/ltc3676.c index 093b3e4a6303..eb3d6bed6d54 100644 --- a/drivers/regulator/ltc3676.c +++ b/drivers/regulator/ltc3676.c @@ -276,23 +276,17 @@ static irqreturn_t ltc3676_isr(int irq, void *dev_id) if (irqstat & LTC3676_IRQSTAT_THERMAL_WARN) { dev_warn(dev, "Over-temperature Warning\n"); event = REGULATOR_EVENT_OVER_TEMP; - for (i = 0; i < LTC3676_NUM_REGULATORS; i++) { - regulator_lock(ltc3676->regulators[i]); + for (i = 0; i < LTC3676_NUM_REGULATORS; i++) regulator_notifier_call_chain(ltc3676->regulators[i], event, NULL); - regulator_unlock(ltc3676->regulators[i]); - } } if (irqstat & LTC3676_IRQSTAT_UNDERVOLT_WARN) { dev_info(dev, "Undervoltage Warning\n"); event = REGULATOR_EVENT_UNDER_VOLTAGE; - for (i = 0; i < LTC3676_NUM_REGULATORS; i++) { - regulator_lock(ltc3676->regulators[i]); + for (i = 0; i < LTC3676_NUM_REGULATORS; i++) regulator_notifier_call_chain(ltc3676->regulators[i], event, NULL); - regulator_unlock(ltc3676->regulators[i]); - } } /* Clear warning condition */ @@ -368,7 +362,7 @@ static const struct i2c_device_id ltc3676_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, ltc3676_i2c_id); -static const struct of_device_id ltc3676_of_match[] = { +static const struct of_device_id __maybe_unused ltc3676_of_match[] = { { .compatible = "lltc,ltc3676" }, { }, }; diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index f8941025780b..d4958394e608 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -201,7 +201,7 @@ static int of_get_max1586_platform_data(struct device *dev, return 0; } -static const struct of_device_id max1586_of_match[] = { +static const struct of_device_id __maybe_unused max1586_of_match[] = { { .compatible = "maxim,max1586", }, {}, }; diff --git a/drivers/regulator/max77826-regulator.c b/drivers/regulator/max77826-regulator.c index 502ab6afc814..f9e2e884ff54 100644 --- a/drivers/regulator/max77826-regulator.c +++ b/drivers/regulator/max77826-regulator.c @@ -274,7 +274,7 @@ static int max77826_i2c_probe(struct i2c_client *client) return max77826_read_device_id(regmap, dev); } -static const struct of_device_id max77826_of_match[] = { +static const struct of_device_id __maybe_unused max77826_of_match[] = { { .compatible = "maxim,max77826" }, { /* sentinel */ } }; diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c index d3d475f717f4..a84fd74081de 100644 --- a/drivers/regulator/mp886x.c +++ b/drivers/regulator/mp886x.c @@ -18,18 +18,70 @@ #define MP886X_V_BOOT (1 << 7) #define MP886X_SYSCNTLREG1 0x01 #define MP886X_MODE (1 << 0) +#define MP886X_SLEW_SHIFT 3 +#define MP886X_SLEW_MASK (0x7 << MP886X_SLEW_SHIFT) #define MP886X_GO (1 << 6) #define MP886X_EN (1 << 7) +#define MP8869_SYSCNTLREG2 0x02 + +struct mp886x_cfg_info { + const struct regulator_ops *rops; + const int slew_rates[8]; + const int switch_freq[4]; + const u8 fs_reg; + const u8 fs_shift; +}; struct mp886x_device_info { struct device *dev; struct regulator_desc desc; struct regulator_init_data *regulator; struct gpio_desc *en_gpio; + const struct mp886x_cfg_info *ci; u32 r[2]; unsigned int sel; }; +static int mp886x_set_ramp(struct regulator_dev *rdev, int ramp) +{ + struct mp886x_device_info *di = rdev_get_drvdata(rdev); + const struct mp886x_cfg_info *ci = di->ci; + int reg = -1, i; + + for (i = 0; i < ARRAY_SIZE(ci->slew_rates); i++) { + if (ramp <= ci->slew_rates[i]) + reg = i; + else + break; + } + + if (reg < 0) { + dev_err(di->dev, "unsupported ramp value %d\n", ramp); + return -EINVAL; + } + + return regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1, + MP886X_SLEW_MASK, reg << MP886X_SLEW_SHIFT); +} + +static void mp886x_set_switch_freq(struct mp886x_device_info *di, + struct regmap *regmap, + u32 freq) +{ + const struct mp886x_cfg_info *ci = di->ci; + int i; + + for (i = 0; i < ARRAY_SIZE(ci->switch_freq); i++) { + if (freq == ci->switch_freq[i]) { + regmap_update_bits(regmap, ci->fs_reg, + 0x3 << ci->fs_shift, i << ci->fs_shift); + return; + } + } + + dev_err(di->dev, "invalid frequency %d\n", freq); +} + static int mp886x_set_mode(struct regulator_dev *rdev, unsigned int mode) { switch (mode) { @@ -117,6 +169,29 @@ static const struct regulator_ops mp8869_regulator_ops = { .is_enabled = regulator_is_enabled_regmap, .set_mode = mp886x_set_mode, .get_mode = mp886x_get_mode, + .set_ramp_delay = mp886x_set_ramp, +}; + +static const struct mp886x_cfg_info mp8869_ci = { + .rops = &mp8869_regulator_ops, + .slew_rates = { + 40000, + 30000, + 20000, + 10000, + 5000, + 2500, + 1250, + 625, + }, + .switch_freq = { + 500000, + 750000, + 1000000, + 1250000, + }, + .fs_reg = MP8869_SYSCNTLREG2, + .fs_shift = 4, }; static int mp8867_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel) @@ -173,6 +248,29 @@ static const struct regulator_ops mp8867_regulator_ops = { .is_enabled = regulator_is_enabled_regmap, .set_mode = mp886x_set_mode, .get_mode = mp886x_get_mode, + .set_ramp_delay = mp886x_set_ramp, +}; + +static const struct mp886x_cfg_info mp8867_ci = { + .rops = &mp8867_regulator_ops, + .slew_rates = { + 64000, + 32000, + 16000, + 8000, + 4000, + 2000, + 1000, + 500, + }, + .switch_freq = { + 500000, + 750000, + 1000000, + 1500000, + }, + .fs_reg = MP886X_SYSCNTLREG1, + .fs_shift = 1, }; static int mp886x_regulator_register(struct mp886x_device_info *di, @@ -183,7 +281,7 @@ static int mp886x_regulator_register(struct mp886x_device_info *di, rdesc->name = "mp886x-reg"; rdesc->supply_name = "vin"; - rdesc->ops = of_device_get_match_data(di->dev); + rdesc->ops = di->ci->rops; rdesc->type = REGULATOR_VOLTAGE; rdesc->n_voltages = 128; rdesc->enable_reg = MP886X_SYSCNTLREG1; @@ -213,6 +311,7 @@ static int mp886x_i2c_probe(struct i2c_client *client) struct mp886x_device_info *di; struct regulator_config config = { }; struct regmap *regmap; + u32 freq; int ret; di = devm_kzalloc(dev, sizeof(struct mp886x_device_info), GFP_KERNEL); @@ -234,6 +333,7 @@ static int mp886x_i2c_probe(struct i2c_client *client) if (IS_ERR(di->en_gpio)) return PTR_ERR(di->en_gpio); + di->ci = of_device_get_match_data(dev); di->dev = dev; regmap = devm_regmap_init_i2c(client, &mp886x_regmap_config); @@ -249,6 +349,9 @@ static int mp886x_i2c_probe(struct i2c_client *client) config.driver_data = di; config.of_node = np; + if (!of_property_read_u32(np, "mps,switch-frequency-hz", &freq)) + mp886x_set_switch_freq(di, regmap, freq); + ret = mp886x_regulator_register(di, &config); if (ret < 0) dev_err(dev, "Failed to register regulator!\n"); @@ -258,11 +361,11 @@ static int mp886x_i2c_probe(struct i2c_client *client) static const struct of_device_id mp886x_dt_ids[] = { { .compatible = "mps,mp8867", - .data = &mp8867_regulator_ops + .data = &mp8867_ci }, { .compatible = "mps,mp8869", - .data = &mp8869_regulator_ops + .data = &mp8869_ci }, { } }; diff --git a/drivers/regulator/mt6360-regulator.c b/drivers/regulator/mt6360-regulator.c new file mode 100644 index 000000000000..15308ee29c13 --- /dev/null +++ b/drivers/regulator/mt6360-regulator.c @@ -0,0 +1,459 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (C) 2020 MediaTek Inc. +// +// Author: Gene Chen <gene_chen@richtek.com> + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> + +#include <dt-bindings/regulator/mediatek,mt6360-regulator.h> + +enum { + MT6360_REGULATOR_BUCK1 = 0, + MT6360_REGULATOR_BUCK2, + MT6360_REGULATOR_LDO6, + MT6360_REGULATOR_LDO7, + MT6360_REGULATOR_LDO1, + MT6360_REGULATOR_LDO2, + MT6360_REGULATOR_LDO3, + MT6360_REGULATOR_LDO5, + MT6360_REGULATOR_MAX, +}; + +struct mt6360_irq_mapping { + const char *name; + irq_handler_t handler; +}; + +struct mt6360_regulator_desc { + const struct regulator_desc desc; + unsigned int mode_reg; + unsigned int mode_mask; + unsigned int state_reg; + unsigned int state_mask; + const struct mt6360_irq_mapping *irq_tables; + int irq_table_size; +}; + +struct mt6360_regulator_data { + struct device *dev; + struct regmap *regmap; +}; + +static irqreturn_t mt6360_pgb_event_handler(int irq, void *data) +{ + struct regulator_dev *rdev = data; + + regulator_notifier_call_chain(rdev, REGULATOR_EVENT_FAIL, NULL); + return IRQ_HANDLED; +} + +static irqreturn_t mt6360_oc_event_handler(int irq, void *data) +{ + struct regulator_dev *rdev = data; + + regulator_notifier_call_chain(rdev, REGULATOR_EVENT_OVER_CURRENT, NULL); + return IRQ_HANDLED; +} + +static irqreturn_t mt6360_ov_event_handler(int irq, void *data) +{ + struct regulator_dev *rdev = data; + + regulator_notifier_call_chain(rdev, REGULATOR_EVENT_REGULATION_OUT, NULL); + return IRQ_HANDLED; +} + +static irqreturn_t mt6360_uv_event_handler(int irq, void *data) +{ + struct regulator_dev *rdev = data; + + regulator_notifier_call_chain(rdev, REGULATOR_EVENT_UNDER_VOLTAGE, NULL); + return IRQ_HANDLED; +} + +static const struct mt6360_irq_mapping buck1_irq_tbls[] = { + { "buck1_pgb_evt", mt6360_pgb_event_handler }, + { "buck1_oc_evt", mt6360_oc_event_handler }, + { "buck1_ov_evt", mt6360_ov_event_handler }, + { "buck1_uv_evt", mt6360_uv_event_handler }, +}; + +static const struct mt6360_irq_mapping buck2_irq_tbls[] = { + { "buck2_pgb_evt", mt6360_pgb_event_handler }, + { "buck2_oc_evt", mt6360_oc_event_handler }, + { "buck2_ov_evt", mt6360_ov_event_handler }, + { "buck2_uv_evt", mt6360_uv_event_handler }, +}; + +static const struct mt6360_irq_mapping ldo6_irq_tbls[] = { + { "ldo6_pgb_evt", mt6360_pgb_event_handler }, + { "ldo6_oc_evt", mt6360_oc_event_handler }, +}; + +static const struct mt6360_irq_mapping ldo7_irq_tbls[] = { + { "ldo7_pgb_evt", mt6360_pgb_event_handler }, + { "ldo7_oc_evt", mt6360_oc_event_handler }, +}; + +static const struct mt6360_irq_mapping ldo1_irq_tbls[] = { + { "ldo1_pgb_evt", mt6360_pgb_event_handler }, + { "ldo1_oc_evt", mt6360_oc_event_handler }, +}; + +static const struct mt6360_irq_mapping ldo2_irq_tbls[] = { + { "ldo2_pgb_evt", mt6360_pgb_event_handler }, + { "ldo2_oc_evt", mt6360_oc_event_handler }, +}; + +static const struct mt6360_irq_mapping ldo3_irq_tbls[] = { + { "ldo3_pgb_evt", mt6360_pgb_event_handler }, + { "ldo3_oc_evt", mt6360_oc_event_handler }, +}; + +static const struct mt6360_irq_mapping ldo5_irq_tbls[] = { + { "ldo5_pgb_evt", mt6360_pgb_event_handler }, + { "ldo5_oc_evt", mt6360_oc_event_handler }, +}; + +static const struct linear_range buck_vout_ranges[] = { + REGULATOR_LINEAR_RANGE(300000, 0x00, 0xc7, 5000), + REGULATOR_LINEAR_RANGE(1300000, 0xc8, 0xff, 0), +}; + +static const struct linear_range ldo_vout_ranges1[] = { + REGULATOR_LINEAR_RANGE(500000, 0x00, 0x09, 10000), + REGULATOR_LINEAR_RANGE(600000, 0x0a, 0x10, 0), + REGULATOR_LINEAR_RANGE(610000, 0x11, 0x19, 10000), + REGULATOR_LINEAR_RANGE(700000, 0x1a, 0x20, 0), + REGULATOR_LINEAR_RANGE(710000, 0x21, 0x29, 10000), + REGULATOR_LINEAR_RANGE(800000, 0x2a, 0x30, 0), + REGULATOR_LINEAR_RANGE(810000, 0x31, 0x39, 10000), + REGULATOR_LINEAR_RANGE(900000, 0x3a, 0x40, 0), + REGULATOR_LINEAR_RANGE(910000, 0x41, 0x49, 10000), + REGULATOR_LINEAR_RANGE(1000000, 0x4a, 0x50, 0), + REGULATOR_LINEAR_RANGE(1010000, 0x51, 0x59, 10000), + REGULATOR_LINEAR_RANGE(1100000, 0x5a, 0x60, 0), + REGULATOR_LINEAR_RANGE(1110000, 0x61, 0x69, 10000), + REGULATOR_LINEAR_RANGE(1200000, 0x6a, 0x70, 0), + REGULATOR_LINEAR_RANGE(1210000, 0x71, 0x79, 10000), + REGULATOR_LINEAR_RANGE(1300000, 0x7a, 0x80, 0), + REGULATOR_LINEAR_RANGE(1310000, 0x81, 0x89, 10000), + REGULATOR_LINEAR_RANGE(1400000, 0x8a, 0x90, 0), + REGULATOR_LINEAR_RANGE(1410000, 0x91, 0x99, 10000), + REGULATOR_LINEAR_RANGE(1500000, 0x9a, 0xa0, 0), + REGULATOR_LINEAR_RANGE(1510000, 0xa1, 0xa9, 10000), + REGULATOR_LINEAR_RANGE(1600000, 0xaa, 0xb0, 0), + REGULATOR_LINEAR_RANGE(1610000, 0xb1, 0xb9, 10000), + REGULATOR_LINEAR_RANGE(1700000, 0xba, 0xc0, 0), + REGULATOR_LINEAR_RANGE(1710000, 0xc1, 0xc9, 10000), + REGULATOR_LINEAR_RANGE(1800000, 0xca, 0xd0, 0), + REGULATOR_LINEAR_RANGE(1810000, 0xd1, 0xd9, 10000), + REGULATOR_LINEAR_RANGE(1900000, 0xda, 0xe0, 0), + REGULATOR_LINEAR_RANGE(1910000, 0xe1, 0xe9, 10000), + REGULATOR_LINEAR_RANGE(2000000, 0xea, 0xf0, 0), + REGULATOR_LINEAR_RANGE(2010000, 0xf1, 0xf9, 10000), + REGULATOR_LINEAR_RANGE(2100000, 0xfa, 0xff, 0), +}; + +static const struct linear_range ldo_vout_ranges2[] = { + REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x09, 10000), + REGULATOR_LINEAR_RANGE(1300000, 0x0a, 0x10, 0), + REGULATOR_LINEAR_RANGE(1310000, 0x11, 0x19, 10000), + REGULATOR_LINEAR_RANGE(1400000, 0x1a, 0x1f, 0), + REGULATOR_LINEAR_RANGE(1500000, 0x20, 0x29, 10000), + REGULATOR_LINEAR_RANGE(1600000, 0x2a, 0x2f, 0), + REGULATOR_LINEAR_RANGE(1700000, 0x30, 0x39, 10000), + REGULATOR_LINEAR_RANGE(1800000, 0x3a, 0x40, 0), + REGULATOR_LINEAR_RANGE(1810000, 0x41, 0x49, 10000), + REGULATOR_LINEAR_RANGE(1900000, 0x4a, 0x4f, 0), + REGULATOR_LINEAR_RANGE(2000000, 0x50, 0x59, 10000), + REGULATOR_LINEAR_RANGE(2100000, 0x5a, 0x60, 0), + REGULATOR_LINEAR_RANGE(2110000, 0x61, 0x69, 10000), + REGULATOR_LINEAR_RANGE(2200000, 0x6a, 0x6f, 0), + REGULATOR_LINEAR_RANGE(2500000, 0x70, 0x79, 10000), + REGULATOR_LINEAR_RANGE(2600000, 0x7a, 0x7f, 0), + REGULATOR_LINEAR_RANGE(2700000, 0x80, 0x89, 10000), + REGULATOR_LINEAR_RANGE(2800000, 0x8a, 0x90, 0), + REGULATOR_LINEAR_RANGE(2810000, 0x91, 0x99, 10000), + REGULATOR_LINEAR_RANGE(2900000, 0x9a, 0xa0, 0), + REGULATOR_LINEAR_RANGE(2910000, 0xa1, 0xa9, 10000), + REGULATOR_LINEAR_RANGE(3000000, 0xaa, 0xb0, 0), + REGULATOR_LINEAR_RANGE(3010000, 0xb1, 0xb9, 10000), + REGULATOR_LINEAR_RANGE(3100000, 0xba, 0xc0, 0), + REGULATOR_LINEAR_RANGE(3110000, 0xc1, 0xc9, 10000), + REGULATOR_LINEAR_RANGE(3200000, 0xca, 0xcf, 0), + REGULATOR_LINEAR_RANGE(3300000, 0xd0, 0xd9, 10000), + REGULATOR_LINEAR_RANGE(3400000, 0xda, 0xe0, 0), + REGULATOR_LINEAR_RANGE(3410000, 0xe1, 0xe9, 10000), + REGULATOR_LINEAR_RANGE(3500000, 0xea, 0xf0, 0), + REGULATOR_LINEAR_RANGE(3510000, 0xf1, 0xf9, 10000), + REGULATOR_LINEAR_RANGE(3600000, 0xfa, 0xff, 0), +}; + +static const struct linear_range ldo_vout_ranges3[] = { + REGULATOR_LINEAR_RANGE(2700000, 0x00, 0x09, 10000), + REGULATOR_LINEAR_RANGE(2800000, 0x0a, 0x10, 0), + REGULATOR_LINEAR_RANGE(2810000, 0x11, 0x19, 10000), + REGULATOR_LINEAR_RANGE(2900000, 0x1a, 0x20, 0), + REGULATOR_LINEAR_RANGE(2910000, 0x21, 0x29, 10000), + REGULATOR_LINEAR_RANGE(3000000, 0x2a, 0x30, 0), + REGULATOR_LINEAR_RANGE(3010000, 0x31, 0x39, 10000), + REGULATOR_LINEAR_RANGE(3100000, 0x3a, 0x40, 0), + REGULATOR_LINEAR_RANGE(3110000, 0x41, 0x49, 10000), + REGULATOR_LINEAR_RANGE(3200000, 0x4a, 0x4f, 0), + REGULATOR_LINEAR_RANGE(3300000, 0x50, 0x59, 10000), + REGULATOR_LINEAR_RANGE(3400000, 0x5a, 0x60, 0), + REGULATOR_LINEAR_RANGE(3410000, 0x61, 0x69, 10000), + REGULATOR_LINEAR_RANGE(3500000, 0x6a, 0x70, 0), + REGULATOR_LINEAR_RANGE(3510000, 0x71, 0x79, 10000), + REGULATOR_LINEAR_RANGE(3600000, 0x7a, 0x7f, 0), +}; + +static int mt6360_regulator_set_mode(struct regulator_dev *rdev, + unsigned int mode) +{ + const struct mt6360_regulator_desc *rdesc = (struct mt6360_regulator_desc *)rdev->desc; + struct regmap *regmap = rdev_get_regmap(rdev); + int shift = ffs(rdesc->mode_mask) - 1; + unsigned int val; + int ret; + + switch (mode) { + case REGULATOR_MODE_NORMAL: + val = MT6360_OPMODE_NORMAL; + break; + case REGULATOR_MODE_STANDBY: + val = MT6360_OPMODE_ULP; + break; + case REGULATOR_MODE_IDLE: + val = MT6360_OPMODE_LP; + break; + default: + return -EINVAL; + } + + ret = regmap_update_bits(regmap, rdesc->mode_reg, rdesc->mode_mask, val << shift); + if (ret) { + dev_err(&rdev->dev, "%s: fail (%d)\n", __func__, ret); + return ret; + } + + return 0; +} + +static unsigned int mt6360_regulator_get_mode(struct regulator_dev *rdev) +{ + const struct mt6360_regulator_desc *rdesc = (struct mt6360_regulator_desc *)rdev->desc; + struct regmap *regmap = rdev_get_regmap(rdev); + int shift = ffs(rdesc->mode_mask) - 1; + unsigned int val; + int ret; + + ret = regmap_read(regmap, rdesc->mode_reg, &val); + if (ret) + return ret; + + val &= rdesc->mode_mask; + val >>= shift; + + switch (val) { + case MT6360_OPMODE_LP: + return REGULATOR_MODE_IDLE; + case MT6360_OPMODE_ULP: + return REGULATOR_MODE_STANDBY; + case MT6360_OPMODE_NORMAL: + return REGULATOR_MODE_NORMAL; + default: + return -EINVAL; + } +} + +static int mt6360_regulator_get_status(struct regulator_dev *rdev) +{ + const struct mt6360_regulator_desc *rdesc = (struct mt6360_regulator_desc *)rdev->desc; + struct regmap *regmap = rdev_get_regmap(rdev); + unsigned int val; + int ret; + + ret = regmap_read(regmap, rdesc->state_reg, &val); + if (ret) + return ret; + + if (val & rdesc->state_mask) + return REGULATOR_STATUS_ON; + + return REGULATOR_STATUS_OFF; +} + +static const struct regulator_ops mt6360_regulator_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_mode = mt6360_regulator_set_mode, + .get_mode = mt6360_regulator_get_mode, + .get_status = mt6360_regulator_get_status, +}; + +static unsigned int mt6360_regulator_of_map_mode(unsigned int hw_mode) +{ + switch (hw_mode) { + case MT6360_OPMODE_NORMAL: + return REGULATOR_MODE_NORMAL; + case MT6360_OPMODE_LP: + return REGULATOR_MODE_IDLE; + case MT6360_OPMODE_ULP: + return REGULATOR_MODE_STANDBY; + default: + return REGULATOR_MODE_INVALID; + } +} + +#define MT6360_REGULATOR_DESC(_name, _sname, ereg, emask, vreg, vmask, \ + mreg, mmask, streg, stmask, vranges, \ + vcnts, offon_delay, irq_tbls) \ +{ \ + .desc = { \ + .name = #_name, \ + .supply_name = #_sname, \ + .id = MT6360_REGULATOR_##_name, \ + .of_match = of_match_ptr(#_name), \ + .regulators_node = of_match_ptr("regulator"), \ + .of_map_mode = mt6360_regulator_of_map_mode, \ + .owner = THIS_MODULE, \ + .ops = &mt6360_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .vsel_reg = vreg, \ + .vsel_mask = vmask, \ + .enable_reg = ereg, \ + .enable_mask = emask, \ + .linear_ranges = vranges, \ + .n_linear_ranges = ARRAY_SIZE(vranges), \ + .n_voltages = vcnts, \ + .off_on_delay = offon_delay, \ + }, \ + .mode_reg = mreg, \ + .mode_mask = mmask, \ + .state_reg = streg, \ + .state_mask = stmask, \ + .irq_tables = irq_tbls, \ + .irq_table_size = ARRAY_SIZE(irq_tbls), \ +} + +static const struct mt6360_regulator_desc mt6360_regulator_descs[] = { + MT6360_REGULATOR_DESC(BUCK1, BUCK1_VIN, 0x117, 0x40, 0x110, 0xff, 0x117, 0x30, 0x117, 0x04, + buck_vout_ranges, 256, 0, buck1_irq_tbls), + MT6360_REGULATOR_DESC(BUCK2, BUCK2_VIN, 0x127, 0x40, 0x120, 0xff, 0x127, 0x30, 0x127, 0x04, + buck_vout_ranges, 256, 0, buck2_irq_tbls), + MT6360_REGULATOR_DESC(LDO6, LDO_VIN3, 0x137, 0x40, 0x13B, 0xff, 0x137, 0x30, 0x137, 0x04, + ldo_vout_ranges1, 256, 0, ldo6_irq_tbls), + MT6360_REGULATOR_DESC(LDO7, LDO_VIN3, 0x131, 0x40, 0x135, 0xff, 0x131, 0x30, 0x131, 0x04, + ldo_vout_ranges1, 256, 0, ldo7_irq_tbls), + MT6360_REGULATOR_DESC(LDO1, LDO_VIN1, 0x217, 0x40, 0x21B, 0xff, 0x217, 0x30, 0x217, 0x04, + ldo_vout_ranges2, 256, 0, ldo1_irq_tbls), + MT6360_REGULATOR_DESC(LDO2, LDO_VIN1, 0x211, 0x40, 0x215, 0xff, 0x211, 0x30, 0x211, 0x04, + ldo_vout_ranges2, 256, 0, ldo2_irq_tbls), + MT6360_REGULATOR_DESC(LDO3, LDO_VIN1, 0x205, 0x40, 0x209, 0xff, 0x205, 0x30, 0x205, 0x04, + ldo_vout_ranges2, 256, 100, ldo3_irq_tbls), + MT6360_REGULATOR_DESC(LDO5, LDO_VIN2, 0x20B, 0x40, 0x20F, 0x7f, 0x20B, 0x30, 0x20B, 0x04, + ldo_vout_ranges3, 128, 100, ldo5_irq_tbls), +}; + +static int mt6360_regulator_irq_register(struct platform_device *pdev, + struct regulator_dev *rdev, + const struct mt6360_irq_mapping *tbls, + int tbl_size) +{ + int i, irq, ret; + + for (i = 0; i < tbl_size; i++) { + const struct mt6360_irq_mapping *irq_desc = tbls + i; + + irq = platform_get_irq_byname(pdev, irq_desc->name); + if (irq < 0) { + dev_err(&pdev->dev, "Fail to get %s irq\n", irq_desc->name); + return irq; + } + + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, irq_desc->handler, 0, + irq_desc->name, rdev); + if (ret) { + dev_err(&pdev->dev, "Fail to request %s irq\n", irq_desc->name); + return ret; + } + } + + return 0; +} + +static int mt6360_regulator_probe(struct platform_device *pdev) +{ + struct mt6360_regulator_data *mrd; + struct regulator_config config = {}; + int i, ret; + + mrd = devm_kzalloc(&pdev->dev, sizeof(*mrd), GFP_KERNEL); + if (!mrd) + return -ENOMEM; + + mrd->dev = &pdev->dev; + + mrd->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!mrd->regmap) { + dev_err(&pdev->dev, "Failed to get parent regmap\n"); + return -ENODEV; + } + + config.dev = pdev->dev.parent; + config.driver_data = mrd; + config.regmap = mrd->regmap; + + for (i = 0; i < ARRAY_SIZE(mt6360_regulator_descs); i++) { + const struct mt6360_regulator_desc *rdesc = mt6360_regulator_descs + i; + struct regulator_dev *rdev; + + rdev = devm_regulator_register(&pdev->dev, &rdesc->desc, &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "Failed to register %d regulator\n", i); + return PTR_ERR(rdev); + } + + ret = mt6360_regulator_irq_register(pdev, rdev, rdesc->irq_tables, + rdesc->irq_table_size); + if (ret) { + dev_err(&pdev->dev, "Failed to register %d regulator irqs\n", i); + return ret; + } + } + + return 0; +} + +static const struct platform_device_id mt6360_regulator_id_table[] = { + { "mt6360-regulator", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(platform, mt6360_regulator_id_table); + +static struct platform_driver mt6360_regulator_driver = { + .driver = { + .name = "mt6360-regulator", + }, + .probe = mt6360_regulator_probe, + .id_table = mt6360_regulator_id_table, +}; +module_platform_driver(mt6360_regulator_driver); + +MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>"); +MODULE_DESCRIPTION("MT6360 Regulator Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c index eb5822bf53e0..cb29421d745a 100644 --- a/drivers/regulator/pca9450-regulator.c +++ b/drivers/regulator/pca9450-regulator.c @@ -90,7 +90,7 @@ static int pca9450_dvs_set_ramp_delay(struct regulator_dev *rdev, BUCK1_RAMP_MASK, ramp_value << 6); } -static struct regulator_ops pca9450_dvs_buck_regulator_ops = { +static const struct regulator_ops pca9450_dvs_buck_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -101,7 +101,7 @@ static struct regulator_ops pca9450_dvs_buck_regulator_ops = { .set_ramp_delay = pca9450_dvs_set_ramp_delay, }; -static struct regulator_ops pca9450_buck_regulator_ops = { +static const struct regulator_ops pca9450_buck_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -111,7 +111,7 @@ static struct regulator_ops pca9450_buck_regulator_ops = { .set_voltage_time_sel = regulator_set_voltage_time_sel, }; -static struct regulator_ops pca9450_ldo_regulator_ops = { +static const struct regulator_ops pca9450_ldo_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, diff --git a/drivers/regulator/pv88060-regulator.c b/drivers/regulator/pv88060-regulator.c index 787ced918372..48238846f45c 100644 --- a/drivers/regulator/pv88060-regulator.c +++ b/drivers/regulator/pv88060-regulator.c @@ -233,13 +233,10 @@ static irqreturn_t pv88060_irq_handler(int irq, void *data) if (reg_val & PV88060_E_VDD_FLT) { for (i = 0; i < PV88060_MAX_REGULATORS; i++) { - if (chip->rdev[i] != NULL) { - regulator_lock(chip->rdev[i]); + if (chip->rdev[i] != NULL) regulator_notifier_call_chain(chip->rdev[i], REGULATOR_EVENT_UNDER_VOLTAGE, NULL); - regulator_unlock(chip->rdev[i]); - } } err = regmap_write(chip->regmap, PV88060_REG_EVENT_A, @@ -252,13 +249,10 @@ static irqreturn_t pv88060_irq_handler(int irq, void *data) if (reg_val & PV88060_E_OVER_TEMP) { for (i = 0; i < PV88060_MAX_REGULATORS; i++) { - if (chip->rdev[i] != NULL) { - regulator_lock(chip->rdev[i]); + if (chip->rdev[i] != NULL) regulator_notifier_call_chain(chip->rdev[i], REGULATOR_EVENT_OVER_TEMP, NULL); - regulator_unlock(chip->rdev[i]); - } } err = regmap_write(chip->regmap, PV88060_REG_EVENT_A, diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c index a444f68af1a8..2a74cc05acfe 100644 --- a/drivers/regulator/pv88080-regulator.c +++ b/drivers/regulator/pv88080-regulator.c @@ -334,13 +334,10 @@ static irqreturn_t pv88080_irq_handler(int irq, void *data) if (reg_val & PV88080_E_VDD_FLT) { for (i = 0; i < PV88080_MAX_REGULATORS; i++) { - if (chip->rdev[i] != NULL) { - regulator_lock(chip->rdev[i]); + if (chip->rdev[i] != NULL) regulator_notifier_call_chain(chip->rdev[i], REGULATOR_EVENT_UNDER_VOLTAGE, NULL); - regulator_unlock(chip->rdev[i]); - } } err = regmap_write(chip->regmap, PV88080_REG_EVENT_A, @@ -353,13 +350,10 @@ static irqreturn_t pv88080_irq_handler(int irq, void *data) if (reg_val & PV88080_E_OVER_TEMP) { for (i = 0; i < PV88080_MAX_REGULATORS; i++) { - if (chip->rdev[i] != NULL) { - regulator_lock(chip->rdev[i]); + if (chip->rdev[i] != NULL) regulator_notifier_call_chain(chip->rdev[i], REGULATOR_EVENT_OVER_TEMP, NULL); - regulator_unlock(chip->rdev[i]); - } } err = regmap_write(chip->regmap, PV88080_REG_EVENT_A, diff --git a/drivers/regulator/pv88090-regulator.c b/drivers/regulator/pv88090-regulator.c index 784729ec2182..a80176bdf8ec 100644 --- a/drivers/regulator/pv88090-regulator.c +++ b/drivers/regulator/pv88090-regulator.c @@ -226,13 +226,10 @@ static irqreturn_t pv88090_irq_handler(int irq, void *data) if (reg_val & PV88090_E_VDD_FLT) { for (i = 0; i < PV88090_MAX_REGULATORS; i++) { - if (chip->rdev[i] != NULL) { - regulator_lock(chip->rdev[i]); + if (chip->rdev[i] != NULL) regulator_notifier_call_chain(chip->rdev[i], REGULATOR_EVENT_UNDER_VOLTAGE, NULL); - regulator_unlock(chip->rdev[i]); - } } err = regmap_write(chip->regmap, PV88090_REG_EVENT_A, @@ -245,13 +242,10 @@ static irqreturn_t pv88090_irq_handler(int irq, void *data) if (reg_val & PV88090_E_OVER_TEMP) { for (i = 0; i < PV88090_MAX_REGULATORS; i++) { - if (chip->rdev[i] != NULL) { - regulator_lock(chip->rdev[i]); + if (chip->rdev[i] != NULL) regulator_notifier_call_chain(chip->rdev[i], REGULATOR_EVENT_OVER_TEMP, NULL); - regulator_unlock(chip->rdev[i]); - } } err = regmap_write(chip->regmap, PV88090_REG_EVENT_A, diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c index 990bd50771d8..7629476d94ae 100644 --- a/drivers/regulator/pwm-regulator.c +++ b/drivers/regulator/pwm-regulator.c @@ -390,7 +390,7 @@ static int pwm_regulator_probe(struct platform_device *pdev) return 0; } -static const struct of_device_id pwm_of_match[] = { +static const struct of_device_id __maybe_unused pwm_of_match[] = { { .compatible = "pwm-regulator" }, { }, }; diff --git a/drivers/regulator/qcom-labibb-regulator.c b/drivers/regulator/qcom-labibb-regulator.c index 8c7dd1928380..8ccf572394a2 100644 --- a/drivers/regulator/qcom-labibb-regulator.c +++ b/drivers/regulator/qcom-labibb-regulator.c @@ -44,16 +44,16 @@ struct labibb_regulator_data { const char *name; u8 type; u16 base; - struct regulator_desc *desc; + const struct regulator_desc *desc; }; -static struct regulator_ops qcom_labibb_ops = { +static const struct regulator_ops qcom_labibb_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, }; -static struct regulator_desc pmi8998_lab_desc = { +static const struct regulator_desc pmi8998_lab_desc = { .enable_mask = LAB_ENABLE_CTL_MASK, .enable_reg = (PMI8998_LAB_REG_BASE + REG_LABIBB_ENABLE_CTL), .enable_val = LABIBB_CONTROL_ENABLE, @@ -65,7 +65,7 @@ static struct regulator_desc pmi8998_lab_desc = { .ops = &qcom_labibb_ops, }; -static struct regulator_desc pmi8998_ibb_desc = { +static const struct regulator_desc pmi8998_ibb_desc = { .enable_mask = IBB_ENABLE_CTL_MASK, .enable_reg = (PMI8998_IBB_REG_BASE + REG_LABIBB_ENABLE_CTL), .enable_val = LABIBB_CONTROL_ENABLE, diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index 08dcc614efa7..d488325499a9 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -967,7 +967,7 @@ static int rpmh_regulator_probe(struct platform_device *pdev) return 0; } -static const struct of_device_id rpmh_regulator_match_table[] = { +static const struct of_device_id __maybe_unused rpmh_regulator_match_table[] = { { .compatible = "qcom,pm8005-rpmh-regulators", .data = pm8005_vreg_data, diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c index a87b56bc29fa..bb944ee5fe3b 100644 --- a/drivers/regulator/qcom_smd-regulator.c +++ b/drivers/regulator/qcom_smd-regulator.c @@ -403,6 +403,24 @@ static const struct regulator_desc pm8950_pldo = { .ops = &rpm_smps_ldo_ops, }; +static const struct regulator_desc pm8953_lnldo = { + .linear_ranges = (struct linear_range[]) { + REGULATOR_LINEAR_RANGE(1380000, 8, 15, 120000), + REGULATOR_LINEAR_RANGE(690000, 0, 7, 60000), + }, + .n_linear_ranges = 2, + .n_voltages = 16, + .ops = &rpm_smps_ldo_ops, +}; + +static const struct regulator_desc pm8953_ult_nldo = { + .linear_ranges = (struct linear_range[]) { + REGULATOR_LINEAR_RANGE(375000, 0, 93, 12500), + }, + .n_linear_ranges = 1, + .n_voltages = 94, + .ops = &rpm_smps_ldo_ops, +}; static const struct regulator_desc pm8994_hfsmps = { .linear_ranges = (struct linear_range[]) { @@ -541,6 +559,69 @@ static const struct regulator_desc pmi8998_bob = { .ops = &rpm_bob_ops, }; +static const struct regulator_desc pm660_ftsmps = { + .linear_ranges = (struct linear_range[]) { + REGULATOR_LINEAR_RANGE(355000, 0, 199, 5000), + }, + .n_linear_ranges = 1, + .n_voltages = 200, + .ops = &rpm_smps_ldo_ops, +}; + +static const struct regulator_desc pm660_hfsmps = { + .linear_ranges = (struct linear_range[]) { + REGULATOR_LINEAR_RANGE(320000, 0, 216, 8000), + }, + .n_linear_ranges = 1, + .n_voltages = 217, + .ops = &rpm_smps_ldo_ops, +}; + +static const struct regulator_desc pm660_ht_nldo = { + .linear_ranges = (struct linear_range[]) { + REGULATOR_LINEAR_RANGE(312000, 0, 124, 8000), + }, + .n_linear_ranges = 1, + .n_voltages = 125, + .ops = &rpm_smps_ldo_ops, +}; + +static const struct regulator_desc pm660_ht_lvpldo = { + .linear_ranges = (struct linear_range[]) { + REGULATOR_LINEAR_RANGE(1504000, 0, 62, 8000), + }, + .n_linear_ranges = 1, + .n_voltages = 63, + .ops = &rpm_smps_ldo_ops, +}; + +static const struct regulator_desc pm660_nldo660 = { + .linear_ranges = (struct linear_range[]) { + REGULATOR_LINEAR_RANGE(320000, 0, 123, 8000), + }, + .n_linear_ranges = 1, + .n_voltages = 124, + .ops = &rpm_smps_ldo_ops, +}; + +static const struct regulator_desc pm660_pldo660 = { + .linear_ranges = (struct linear_range[]) { + REGULATOR_LINEAR_RANGE(1504000, 0, 255, 8000), + }, + .n_linear_ranges = 1, + .n_voltages = 256, + .ops = &rpm_smps_ldo_ops, +}; + +static const struct regulator_desc pm660l_bob = { + .linear_ranges = (struct linear_range[]) { + REGULATOR_LINEAR_RANGE(1800000, 0, 84, 32000), + }, + .n_linear_ranges = 1, + .n_voltages = 85, + .ops = &rpm_bob_ops, +}; + static const struct regulator_desc pms405_hfsmps3 = { .linear_ranges = (struct linear_range[]) { REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000), @@ -791,6 +872,41 @@ static const struct rpm_regulator_data rpm_pm8950_regulators[] = { {} }; +static const struct rpm_regulator_data rpm_pm8953_regulators[] = { + { "s1", QCOM_SMD_RPM_SMPA, 1, &pm8998_hfsmps, "vdd_s1" }, + { "s2", QCOM_SMD_RPM_SMPA, 2, &pm8998_hfsmps, "vdd_s2" }, + { "s3", QCOM_SMD_RPM_SMPA, 3, &pm8998_hfsmps, "vdd_s3" }, + { "s4", QCOM_SMD_RPM_SMPA, 4, &pm8998_hfsmps, "vdd_s4" }, + { "s5", QCOM_SMD_RPM_SMPA, 5, &pm8950_ftsmps2p5, "vdd_s5" }, + { "s6", QCOM_SMD_RPM_SMPA, 6, &pm8950_ftsmps2p5, "vdd_s6" }, + { "s7", QCOM_SMD_RPM_SMPA, 7, &pm8998_hfsmps, "vdd_s7" }, + + { "l1", QCOM_SMD_RPM_LDOA, 1, &pm8953_ult_nldo, "vdd_l1" }, + { "l2", QCOM_SMD_RPM_LDOA, 2, &pm8953_ult_nldo, "vdd_l2_l3" }, + { "l3", QCOM_SMD_RPM_LDOA, 3, &pm8953_ult_nldo, "vdd_l2_l3" }, + { "l4", QCOM_SMD_RPM_LDOA, 4, &pm8950_ult_pldo, "vdd_l4_l5_l6_l7_l16_l19" }, + { "l5", QCOM_SMD_RPM_LDOA, 5, &pm8950_ult_pldo, "vdd_l4_l5_l6_l7_l16_l19" }, + { "l6", QCOM_SMD_RPM_LDOA, 6, &pm8950_ult_pldo, "vdd_l4_l5_l6_l7_l16_l19" }, + { "l7", QCOM_SMD_RPM_LDOA, 7, &pm8950_ult_pldo, "vdd_l4_l5_l6_l7_l16_l19" }, + { "l8", QCOM_SMD_RPM_LDOA, 8, &pm8950_ult_pldo, "vdd_l8_l11_l12_l13_l14_l15" }, + { "l9", QCOM_SMD_RPM_LDOA, 9, &pm8950_ult_pldo, "vdd_l9_l10_l17_l18_l22" }, + { "l10", QCOM_SMD_RPM_LDOA, 10, &pm8950_ult_pldo, "vdd_l9_l10_l17_l18_l22" }, + { "l11", QCOM_SMD_RPM_LDOA, 11, &pm8950_ult_pldo, "vdd_l8_l11_l12_l13_l14_l15" }, + { "l12", QCOM_SMD_RPM_LDOA, 12, &pm8950_ult_pldo, "vdd_l8_l11_l12_l13_l14_l15" }, + { "l13", QCOM_SMD_RPM_LDOA, 13, &pm8950_ult_pldo, "vdd_l8_l11_l12_l13_l14_l15" }, + { "l14", QCOM_SMD_RPM_LDOA, 14, &pm8950_ult_pldo, "vdd_l8_l11_l12_l13_l14_l15" }, + { "l15", QCOM_SMD_RPM_LDOA, 15, &pm8950_ult_pldo, "vdd_l8_l11_l12_l13_l14_l15" }, + { "l16", QCOM_SMD_RPM_LDOA, 16, &pm8950_ult_pldo, "vdd_l4_l5_l6_l7_l16_l19" }, + { "l17", QCOM_SMD_RPM_LDOA, 17, &pm8950_ult_pldo, "vdd_l9_l10_l17_l18_l22" }, + { "l18", QCOM_SMD_RPM_LDOA, 18, &pm8950_ult_pldo, "vdd_l9_l10_l17_l18_l22" }, + { "l19", QCOM_SMD_RPM_LDOA, 19, &pm8953_ult_nldo, "vdd_l4_l5_l6_l7_l16_l19" }, + { "l20", QCOM_SMD_RPM_LDOA, 20, &pm8953_lnldo, "vdd_l20" }, + { "l21", QCOM_SMD_RPM_LDOA, 21, &pm8953_lnldo, "vdd_l21" }, + { "l22", QCOM_SMD_RPM_LDOA, 22, &pm8950_ult_pldo, "vdd_l9_l10_l17_l18_l22" }, + { "l23", QCOM_SMD_RPM_LDOA, 23, &pm8953_ult_nldo, "vdd_l23" }, + {} +}; + static const struct rpm_regulator_data rpm_pm8994_regulators[] = { { "s1", QCOM_SMD_RPM_SMPA, 1, &pm8994_ftsmps, "vdd_s1" }, { "s2", QCOM_SMD_RPM_SMPA, 2, &pm8994_ftsmps, "vdd_s2" }, @@ -902,6 +1018,54 @@ static const struct rpm_regulator_data rpm_pmi8998_regulators[] = { {} }; +static const struct rpm_regulator_data rpm_pm660_regulators[] = { + { "s1", QCOM_SMD_RPM_SMPA, 1, &pm660_ftsmps, "vdd_s1" }, + { "s2", QCOM_SMD_RPM_SMPA, 2, &pm660_ftsmps, "vdd_s2" }, + { "s3", QCOM_SMD_RPM_SMPA, 3, &pm660_ftsmps, "vdd_s3" }, + { "s4", QCOM_SMD_RPM_SMPA, 4, &pm660_hfsmps, "vdd_s4" }, + { "s5", QCOM_SMD_RPM_SMPA, 5, &pm660_hfsmps, "vdd_s5" }, + { "s6", QCOM_SMD_RPM_SMPA, 6, &pm660_hfsmps, "vdd_s6" }, + { "l1", QCOM_SMD_RPM_LDOA, 1, &pm660_nldo660, "vdd_l1_l6_l7" }, + { "l2", QCOM_SMD_RPM_LDOA, 2, &pm660_ht_nldo, "vdd_l2_l3" }, + { "l3", QCOM_SMD_RPM_LDOA, 3, &pm660_nldo660, "vdd_l2_l3" }, + /* l4 is unaccessible on PM660 */ + { "l5", QCOM_SMD_RPM_LDOA, 5, &pm660_ht_nldo, "vdd_l5" }, + { "l6", QCOM_SMD_RPM_LDOA, 6, &pm660_ht_nldo, "vdd_l1_l6_l7" }, + { "l7", QCOM_SMD_RPM_LDOA, 7, &pm660_ht_nldo, "vdd_l1_l6_l7" }, + { "l8", QCOM_SMD_RPM_LDOA, 8, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, + { "l9", QCOM_SMD_RPM_LDOA, 9, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, + { "l10", QCOM_SMD_RPM_LDOA, 10, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, + { "l11", QCOM_SMD_RPM_LDOA, 11, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, + { "l12", QCOM_SMD_RPM_LDOA, 12, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, + { "l13", QCOM_SMD_RPM_LDOA, 13, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, + { "l14", QCOM_SMD_RPM_LDOA, 14, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, + { "l15", QCOM_SMD_RPM_LDOA, 15, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" }, + { "l16", QCOM_SMD_RPM_LDOA, 16, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" }, + { "l17", QCOM_SMD_RPM_LDOA, 17, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" }, + { "l18", QCOM_SMD_RPM_LDOA, 18, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" }, + { "l19", QCOM_SMD_RPM_LDOA, 19, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" }, + { } +}; + +static const struct rpm_regulator_data rpm_pm660l_regulators[] = { + { "s1", QCOM_SMD_RPM_SMPB, 1, &pm660_ftsmps, "vdd_s1" }, + { "s2", QCOM_SMD_RPM_SMPB, 2, &pm660_ftsmps, "vdd_s2" }, + { "s3", QCOM_SMD_RPM_RWCX, 0, &pm660_ftsmps, "vdd_s3_s4" }, + { "s5", QCOM_SMD_RPM_RWMX, 0, &pm660_ftsmps, "vdd_s5" }, + { "l1", QCOM_SMD_RPM_LDOB, 1, &pm660_nldo660, "vdd_l1_l9_l10" }, + { "l2", QCOM_SMD_RPM_LDOB, 2, &pm660_pldo660, "vdd_l2" }, + { "l3", QCOM_SMD_RPM_LDOB, 3, &pm660_pldo660, "vdd_l3_l5_l7_l8" }, + { "l4", QCOM_SMD_RPM_LDOB, 4, &pm660_pldo660, "vdd_l4_l6" }, + { "l5", QCOM_SMD_RPM_LDOB, 5, &pm660_pldo660, "vdd_l3_l5_l7_l8" }, + { "l6", QCOM_SMD_RPM_LDOB, 6, &pm660_pldo660, "vdd_l4_l6" }, + { "l7", QCOM_SMD_RPM_LDOB, 7, &pm660_pldo660, "vdd_l3_l5_l7_l8" }, + { "l8", QCOM_SMD_RPM_LDOB, 8, &pm660_pldo660, "vdd_l3_l5_l7_l8" }, + { "l9", QCOM_SMD_RPM_RWLC, 0, &pm660_ht_nldo, "vdd_l1_l9_l10" }, + { "l10", QCOM_SMD_RPM_RWLM, 0, &pm660_ht_nldo, "vdd_l1_l9_l10" }, + { "bob", QCOM_SMD_RPM_BOBB, 1, &pm660l_bob, "vdd_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" }, @@ -930,8 +1094,11 @@ static const struct of_device_id rpm_of_match[] = { { .compatible = "qcom,rpm-pm8916-regulators", .data = &rpm_pm8916_regulators }, { .compatible = "qcom,rpm-pm8941-regulators", .data = &rpm_pm8941_regulators }, { .compatible = "qcom,rpm-pm8950-regulators", .data = &rpm_pm8950_regulators }, + { .compatible = "qcom,rpm-pm8953-regulators", .data = &rpm_pm8953_regulators }, { .compatible = "qcom,rpm-pm8994-regulators", .data = &rpm_pm8994_regulators }, { .compatible = "qcom,rpm-pm8998-regulators", .data = &rpm_pm8998_regulators }, + { .compatible = "qcom,rpm-pm660-regulators", .data = &rpm_pm660_regulators }, + { .compatible = "qcom,rpm-pm660l-regulators", .data = &rpm_pm660l_regulators }, { .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 }, diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index 5ee7c5305d95..e62e1d72d943 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -135,6 +135,18 @@ enum spmi_regulator_subtype { SPMI_REGULATOR_SUBTYPE_LV_P600 = 0x2b, SPMI_REGULATOR_SUBTYPE_LV_P1200 = 0x2c, SPMI_REGULATOR_SUBTYPE_LV_P450 = 0x2d, + SPMI_REGULATOR_SUBTYPE_HT_N300_ST = 0x30, + SPMI_REGULATOR_SUBTYPE_HT_N600_ST = 0x31, + SPMI_REGULATOR_SUBTYPE_HT_N1200_ST = 0x32, + SPMI_REGULATOR_SUBTYPE_HT_LVP150 = 0x3b, + SPMI_REGULATOR_SUBTYPE_HT_LVP300 = 0x3c, + SPMI_REGULATOR_SUBTYPE_L660_N300_ST = 0x42, + SPMI_REGULATOR_SUBTYPE_L660_N600_ST = 0x43, + SPMI_REGULATOR_SUBTYPE_L660_P50 = 0x46, + SPMI_REGULATOR_SUBTYPE_L660_P150 = 0x47, + SPMI_REGULATOR_SUBTYPE_L660_P600 = 0x49, + SPMI_REGULATOR_SUBTYPE_L660_LVP150 = 0x4d, + SPMI_REGULATOR_SUBTYPE_L660_LVP600 = 0x4f, SPMI_REGULATOR_SUBTYPE_LV100 = 0x01, SPMI_REGULATOR_SUBTYPE_LV300 = 0x02, SPMI_REGULATOR_SUBTYPE_MV300 = 0x08, @@ -511,6 +523,22 @@ static struct spmi_voltage_range ult_pldo_ranges[] = { SPMI_VOLTAGE_RANGE(0, 1750000, 1750000, 3337500, 3337500, 12500), }; +static struct spmi_voltage_range pldo660_ranges[] = { + SPMI_VOLTAGE_RANGE(0, 1504000, 1504000, 3544000, 3544000, 8000), +}; + +static struct spmi_voltage_range nldo660_ranges[] = { + SPMI_VOLTAGE_RANGE(0, 320000, 320000, 1304000, 1304000, 8000), +}; + +static struct spmi_voltage_range ht_lvpldo_ranges[] = { + SPMI_VOLTAGE_RANGE(0, 1504000, 1504000, 2000000, 2000000, 8000), +}; + +static struct spmi_voltage_range ht_nldo_ranges[] = { + SPMI_VOLTAGE_RANGE(0, 312000, 312000, 1304000, 1304000, 8000), +}; + static struct spmi_voltage_range hfs430_ranges[] = { SPMI_VOLTAGE_RANGE(0, 320000, 320000, 2040000, 2040000, 8000), }; @@ -530,6 +558,10 @@ static DEFINE_SPMI_SET_POINTS(ult_lo_smps); static DEFINE_SPMI_SET_POINTS(ult_ho_smps); static DEFINE_SPMI_SET_POINTS(ult_nldo); static DEFINE_SPMI_SET_POINTS(ult_pldo); +static DEFINE_SPMI_SET_POINTS(pldo660); +static DEFINE_SPMI_SET_POINTS(nldo660); +static DEFINE_SPMI_SET_POINTS(ht_lvpldo); +static DEFINE_SPMI_SET_POINTS(ht_nldo); static DEFINE_SPMI_SET_POINTS(hfs430); static inline int spmi_vreg_read(struct spmi_regulator *vreg, u16 addr, u8 *buf, @@ -1443,6 +1475,30 @@ static const struct spmi_regulator_mapping supported_regulators[] = { SPMI_VREG(LDO, LV_P300, 0, INF, LDO, ldo, pldo, 10000), SPMI_VREG(LDO, LV_P600, 0, INF, LDO, ldo, pldo, 10000), SPMI_VREG(LDO, LV_P1200, 0, INF, LDO, ldo, pldo, 10000), + SPMI_VREG(LDO, HT_N300_ST, 0, INF, FTSMPS426, ftsmps426, + ht_nldo, 30000), + SPMI_VREG(LDO, HT_N600_ST, 0, INF, FTSMPS426, ftsmps426, + ht_nldo, 30000), + SPMI_VREG(LDO, HT_N1200_ST, 0, INF, FTSMPS426, ftsmps426, + ht_nldo, 30000), + SPMI_VREG(LDO, HT_LVP150, 0, INF, FTSMPS426, ftsmps426, + ht_lvpldo, 10000), + SPMI_VREG(LDO, HT_LVP300, 0, INF, FTSMPS426, ftsmps426, + ht_lvpldo, 10000), + SPMI_VREG(LDO, L660_N300_ST, 0, INF, FTSMPS426, ftsmps426, + nldo660, 10000), + SPMI_VREG(LDO, L660_N600_ST, 0, INF, FTSMPS426, ftsmps426, + nldo660, 10000), + SPMI_VREG(LDO, L660_P50, 0, INF, FTSMPS426, ftsmps426, + pldo660, 10000), + SPMI_VREG(LDO, L660_P150, 0, INF, FTSMPS426, ftsmps426, + pldo660, 10000), + SPMI_VREG(LDO, L660_P600, 0, INF, FTSMPS426, ftsmps426, + pldo660, 10000), + SPMI_VREG(LDO, L660_LVP150, 0, INF, FTSMPS426, ftsmps426, + ht_lvpldo, 10000), + SPMI_VREG(LDO, L660_LVP600, 0, INF, FTSMPS426, ftsmps426, + ht_lvpldo, 10000), SPMI_VREG_VS(LV100, 0, INF), SPMI_VREG_VS(LV300, 0, INF), SPMI_VREG_VS(MV300, 0, INF), @@ -1633,45 +1689,43 @@ static int spmi_regulator_init_registers(struct spmi_regulator *vreg, return ret; /* Set up enable pin control. */ - if ((type == SPMI_REGULATOR_LOGICAL_TYPE_SMPS - || type == SPMI_REGULATOR_LOGICAL_TYPE_LDO - || type == SPMI_REGULATOR_LOGICAL_TYPE_VS) - && !(data->pin_ctrl_enable - & SPMI_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT)) { - ctrl_reg[SPMI_COMMON_IDX_ENABLE] &= - ~SPMI_COMMON_ENABLE_FOLLOW_ALL_MASK; - ctrl_reg[SPMI_COMMON_IDX_ENABLE] |= - data->pin_ctrl_enable & SPMI_COMMON_ENABLE_FOLLOW_ALL_MASK; + if (!(data->pin_ctrl_enable & SPMI_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT)) { + switch (type) { + case SPMI_REGULATOR_LOGICAL_TYPE_SMPS: + case SPMI_REGULATOR_LOGICAL_TYPE_LDO: + case SPMI_REGULATOR_LOGICAL_TYPE_VS: + ctrl_reg[SPMI_COMMON_IDX_ENABLE] &= + ~SPMI_COMMON_ENABLE_FOLLOW_ALL_MASK; + ctrl_reg[SPMI_COMMON_IDX_ENABLE] |= + data->pin_ctrl_enable & SPMI_COMMON_ENABLE_FOLLOW_ALL_MASK; + break; + default: + break; + } } /* Set up mode pin control. */ - if ((type == SPMI_REGULATOR_LOGICAL_TYPE_SMPS - || type == SPMI_REGULATOR_LOGICAL_TYPE_LDO) - && !(data->pin_ctrl_hpm - & SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT)) { - ctrl_reg[SPMI_COMMON_IDX_MODE] &= - ~SPMI_COMMON_MODE_FOLLOW_ALL_MASK; - ctrl_reg[SPMI_COMMON_IDX_MODE] |= - data->pin_ctrl_hpm & SPMI_COMMON_MODE_FOLLOW_ALL_MASK; - } - - if (type == SPMI_REGULATOR_LOGICAL_TYPE_VS - && !(data->pin_ctrl_hpm & SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT)) { - ctrl_reg[SPMI_COMMON_IDX_MODE] &= - ~SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK; - ctrl_reg[SPMI_COMMON_IDX_MODE] |= - data->pin_ctrl_hpm & SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK; - } - - if ((type == SPMI_REGULATOR_LOGICAL_TYPE_ULT_LO_SMPS - || type == SPMI_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS - || type == SPMI_REGULATOR_LOGICAL_TYPE_ULT_LDO) - && !(data->pin_ctrl_hpm - & SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT)) { - ctrl_reg[SPMI_COMMON_IDX_MODE] &= - ~SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK; - ctrl_reg[SPMI_COMMON_IDX_MODE] |= - data->pin_ctrl_hpm & SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK; + if (!(data->pin_ctrl_hpm & SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT)) { + switch (type) { + case SPMI_REGULATOR_LOGICAL_TYPE_SMPS: + case SPMI_REGULATOR_LOGICAL_TYPE_LDO: + ctrl_reg[SPMI_COMMON_IDX_MODE] &= + ~SPMI_COMMON_MODE_FOLLOW_ALL_MASK; + ctrl_reg[SPMI_COMMON_IDX_MODE] |= + data->pin_ctrl_hpm & SPMI_COMMON_MODE_FOLLOW_ALL_MASK; + break; + case SPMI_REGULATOR_LOGICAL_TYPE_VS: + case SPMI_REGULATOR_LOGICAL_TYPE_ULT_LO_SMPS: + case SPMI_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS: + case SPMI_REGULATOR_LOGICAL_TYPE_ULT_LDO: + ctrl_reg[SPMI_COMMON_IDX_MODE] &= + ~SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK; + ctrl_reg[SPMI_COMMON_IDX_MODE] |= + data->pin_ctrl_hpm & SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK; + break; + default: + break; + } } /* Write back any control register values that were modified. */ @@ -1960,6 +2014,55 @@ static const struct spmi_regulator_data pmi8994_regulators[] = { { } }; +static const struct spmi_regulator_data pm660_regulators[] = { + { "s1", 0x1400, "vdd_s1", }, + { "s2", 0x1700, "vdd_s2", }, + { "s3", 0x1a00, "vdd_s3", }, + { "s4", 0x1d00, "vdd_s3", }, + { "s5", 0x2000, "vdd_s5", }, + { "s6", 0x2300, "vdd_s6", }, + { "l1", 0x4000, "vdd_l1_l6_l7", }, + { "l2", 0x4100, "vdd_l2_l3", }, + { "l3", 0x4200, "vdd_l2_l3", }, + /* l4 is unaccessible on PM660 */ + { "l5", 0x4400, "vdd_l5", }, + { "l6", 0x4500, "vdd_l1_l6_l7", }, + { "l7", 0x4600, "vdd_l1_l6_l7", }, + { "l8", 0x4700, "vdd_l8_l9_l10_l11_l12_l13_l14", }, + { "l9", 0x4800, "vdd_l8_l9_l10_l11_l12_l13_l14", }, + { "l10", 0x4900, "vdd_l8_l9_l10_l11_l12_l13_l14", }, + { "l11", 0x4a00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, + { "l12", 0x4b00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, + { "l13", 0x4c00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, + { "l14", 0x4d00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, + { "l15", 0x4e00, "vdd_l15_l16_l17_l18_l19", }, + { "l16", 0x4f00, "vdd_l15_l16_l17_l18_l19", }, + { "l17", 0x5000, "vdd_l15_l16_l17_l18_l19", }, + { "l18", 0x5100, "vdd_l15_l16_l17_l18_l19", }, + { "l19", 0x5200, "vdd_l15_l16_l17_l18_l19", }, + { } +}; + +static const struct spmi_regulator_data pm660l_regulators[] = { + { "s1", 0x1400, "vdd_s1", }, + { "s2", 0x1700, "vdd_s2", }, + { "s3", 0x1a00, "vdd_s3", }, + { "s4", 0x1d00, "vdd_s4", }, + { "s5", 0x2000, "vdd_s5", }, + { "l1", 0x4000, "vdd_l1_l9_l10", }, + { "l2", 0x4100, "vdd_l2", }, + { "l3", 0x4200, "vdd_l3_l5_l7_l8", }, + { "l4", 0x4300, "vdd_l4_l6", }, + { "l5", 0x4400, "vdd_l3_l5_l7_l8", }, + { "l6", 0x4500, "vdd_l4_l6", }, + { "l7", 0x4600, "vdd_l3_l5_l7_l8", }, + { "l8", 0x4700, "vdd_l3_l5_l7_l8", }, + { "l9", 0x4800, "vdd_l1_l9_l10", }, + { "l10", 0x4900, "vdd_l1_l9_l10", }, + { } +}; + + static const struct spmi_regulator_data pm8004_regulators[] = { { "s2", 0x1700, "vdd_s2", }, { "s5", 0x2000, "vdd_s5", }, @@ -1988,6 +2091,8 @@ static const struct of_device_id qcom_spmi_regulator_match[] = { { .compatible = "qcom,pm8950-regulators", .data = &pm8950_regulators }, { .compatible = "qcom,pm8994-regulators", .data = &pm8994_regulators }, { .compatible = "qcom,pmi8994-regulators", .data = &pmi8994_regulators }, + { .compatible = "qcom,pm660-regulators", .data = &pm660_regulators }, + { .compatible = "qcom,pm660l-regulators", .data = &pm660l_regulators }, { .compatible = "qcom,pms405-regulators", .data = &pms405_regulators }, { } }; diff --git a/drivers/regulator/qcom_usb_vbus-regulator.c b/drivers/regulator/qcom_usb_vbus-regulator.c index 8ba947f3585f..457788b50572 100644 --- a/drivers/regulator/qcom_usb_vbus-regulator.c +++ b/drivers/regulator/qcom_usb_vbus-regulator.c @@ -63,6 +63,7 @@ static int qcom_usb_vbus_regulator_probe(struct platform_device *pdev) qcom_usb_vbus_rdesc.enable_mask = OTG_EN; config.dev = dev; config.init_data = init_data; + config.of_node = dev->of_node; config.regmap = regmap; rdev = devm_regulator_register(dev, &qcom_usb_vbus_rdesc, &config); diff --git a/drivers/regulator/rpi-panel-attiny-regulator.c b/drivers/regulator/rpi-panel-attiny-regulator.c new file mode 100644 index 000000000000..ee46bfbf5eee --- /dev/null +++ b/drivers/regulator/rpi-panel-attiny-regulator.c @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Marek Vasut <marex@denx.de> + * + * Based on rpi_touchscreen.c by Eric Anholt <eric@anholt.net> + */ + +#include <linux/backlight.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> +#include <linux/slab.h> + +/* I2C registers of the Atmel microcontroller. */ +#define REG_ID 0x80 +#define REG_PORTA 0x81 +#define REG_PORTA_HF BIT(2) +#define REG_PORTA_VF BIT(3) +#define REG_PORTB 0x82 +#define REG_POWERON 0x85 +#define REG_PWM 0x86 + +static const struct regmap_config attiny_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = REG_PWM, + .cache_type = REGCACHE_NONE, +}; + +static int attiny_lcd_power_enable(struct regulator_dev *rdev) +{ + unsigned int data; + + regmap_write(rdev->regmap, REG_POWERON, 1); + /* Wait for nPWRDWN to go low to indicate poweron is done. */ + regmap_read_poll_timeout(rdev->regmap, REG_PORTB, data, + data & BIT(0), 10, 1000000); + + /* Default to the same orientation as the closed source + * firmware used for the panel. Runtime rotation + * configuration will be supported using VC4's plane + * orientation bits. + */ + regmap_write(rdev->regmap, REG_PORTA, BIT(2)); + + return 0; +} + +static int attiny_lcd_power_disable(struct regulator_dev *rdev) +{ + regmap_write(rdev->regmap, REG_PWM, 0); + regmap_write(rdev->regmap, REG_POWERON, 0); + udelay(1); + return 0; +} + +static int attiny_lcd_power_is_enabled(struct regulator_dev *rdev) +{ + unsigned int data; + int ret; + + ret = regmap_read(rdev->regmap, REG_POWERON, &data); + if (ret < 0) + return ret; + + if (!(data & BIT(0))) + return 0; + + ret = regmap_read(rdev->regmap, REG_PORTB, &data); + if (ret < 0) + return ret; + + return data & BIT(0); +} + +static const struct regulator_init_data attiny_regulator_default = { + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, +}; + +static const struct regulator_ops attiny_regulator_ops = { + .enable = attiny_lcd_power_enable, + .disable = attiny_lcd_power_disable, + .is_enabled = attiny_lcd_power_is_enabled, +}; + +static const struct regulator_desc attiny_regulator = { + .name = "tc358762-power", + .ops = &attiny_regulator_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, +}; + +static int attiny_update_status(struct backlight_device *bl) +{ + struct regmap *regmap = bl_get_data(bl); + int brightness = bl->props.brightness; + + if (bl->props.power != FB_BLANK_UNBLANK || + bl->props.fb_blank != FB_BLANK_UNBLANK) + brightness = 0; + + return regmap_write(regmap, REG_PWM, brightness); +} + +static int attiny_get_brightness(struct backlight_device *bl) +{ + struct regmap *regmap = bl_get_data(bl); + int ret, brightness; + + ret = regmap_read(regmap, REG_PWM, &brightness); + if (ret) + return ret; + + return brightness; +} + +static const struct backlight_ops attiny_bl = { + .update_status = attiny_update_status, + .get_brightness = attiny_get_brightness, +}; + +/* + * I2C driver interface functions + */ +static int attiny_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct backlight_properties props = { }; + struct regulator_config config = { }; + struct backlight_device *bl; + struct regulator_dev *rdev; + struct regmap *regmap; + unsigned int data; + int ret; + + regmap = devm_regmap_init_i2c(i2c, &attiny_regmap_config); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + ret = regmap_read(regmap, REG_ID, &data); + if (ret < 0) { + dev_err(&i2c->dev, "Failed to read REG_ID reg: %d\n", ret); + return ret; + } + + switch (data) { + case 0xde: /* ver 1 */ + case 0xc3: /* ver 2 */ + break; + default: + dev_err(&i2c->dev, "Unknown Atmel firmware revision: 0x%02x\n", data); + return -ENODEV; + } + + regmap_write(regmap, REG_POWERON, 0); + mdelay(1); + + config.dev = &i2c->dev; + config.regmap = regmap; + config.of_node = i2c->dev.of_node; + config.init_data = &attiny_regulator_default; + + rdev = devm_regulator_register(&i2c->dev, &attiny_regulator, &config); + if (IS_ERR(rdev)) { + dev_err(&i2c->dev, "Failed to register ATTINY regulator\n"); + return PTR_ERR(rdev); + } + + props.type = BACKLIGHT_RAW; + props.max_brightness = 0xff; + bl = devm_backlight_device_register(&i2c->dev, + "7inch-touchscreen-panel-bl", + &i2c->dev, regmap, &attiny_bl, + &props); + if (IS_ERR(bl)) + return PTR_ERR(bl); + + bl->props.brightness = 0xff; + + return 0; +} + +static const struct of_device_id attiny_dt_ids[] = { + { .compatible = "raspberrypi,7inch-touchscreen-panel-regulator" }, + {}, +}; +MODULE_DEVICE_TABLE(of, attiny_dt_ids); + +static struct i2c_driver attiny_regulator_driver = { + .driver = { + .name = "rpi_touchscreen_attiny", + .of_match_table = of_match_ptr(attiny_dt_ids), + }, + .probe = attiny_i2c_probe, +}; + +module_i2c_driver(attiny_regulator_driver); + +MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); +MODULE_DESCRIPTION("Regulator device driver for Raspberry Pi 7-inch touchscreen"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/rt4801-regulator.c b/drivers/regulator/rt4801-regulator.c new file mode 100644 index 000000000000..2055a9cb13ba --- /dev/null +++ b/drivers/regulator/rt4801-regulator.c @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> + +#define RT4801_REG_VOP 0x00 +#define RT4801_REG_VON 0x01 +#define RT4801_REG_APPS 0x03 + +#define VOUT_MASK 0x1F + +#define MIN_UV 4000000 +#define STEP_UV 100000 +#define MAX_UV 6000000 +#define N_VOLTAGES ((MAX_UV - MIN_UV) / STEP_UV + 1) + +#define DSV_OUT_POS 0 +#define DSV_OUT_NEG 1 +#define DSV_OUT_MAX 2 + +#define DSVP_ENABLE BIT(0) +#define DSVN_ENABLE BIT(1) +#define DSVALL_ENABLE (DSVP_ENABLE | DSVN_ENABLE) + +struct rt4801_priv { + struct device *dev; + struct gpio_descs *enable_gpios; + unsigned int enable_flag; + unsigned int volt_sel[DSV_OUT_MAX]; +}; + +static int rt4801_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector) +{ + struct rt4801_priv *priv = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev), ret; + + if (priv->enable_flag & BIT(id)) { + ret = regulator_set_voltage_sel_regmap(rdev, selector); + if (ret) + return ret; + } + + priv->volt_sel[id] = selector; + return 0; +} + +static int rt4801_get_voltage_sel(struct regulator_dev *rdev) +{ + struct rt4801_priv *priv = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + + if (priv->enable_flag & BIT(id)) + return regulator_get_voltage_sel_regmap(rdev); + + return priv->volt_sel[id]; +} + +static int rt4801_enable(struct regulator_dev *rdev) +{ + struct rt4801_priv *priv = rdev_get_drvdata(rdev); + struct gpio_descs *gpios = priv->enable_gpios; + int id = rdev_get_id(rdev), ret; + + if (gpios->ndescs <= id) { + dev_warn(&rdev->dev, "no dedicated gpio can control\n"); + goto bypass_gpio; + } + + gpiod_set_value(gpios->desc[id], 1); + +bypass_gpio: + ret = regmap_write(rdev->regmap, rdev->desc->vsel_reg, priv->volt_sel[id]); + if (ret) + return ret; + + priv->enable_flag |= BIT(id); + return 0; +} + +static int rt4801_disable(struct regulator_dev *rdev) +{ + struct rt4801_priv *priv = rdev_get_drvdata(rdev); + struct gpio_descs *gpios = priv->enable_gpios; + int id = rdev_get_id(rdev); + + if (gpios->ndescs <= id) { + dev_warn(&rdev->dev, "no dedicated gpio can control\n"); + goto bypass_gpio; + } + + gpiod_set_value(gpios->desc[id], 0); + +bypass_gpio: + priv->enable_flag &= ~BIT(id); + return 0; +} + +static int rt4801_is_enabled(struct regulator_dev *rdev) +{ + struct rt4801_priv *priv = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + + return !!(priv->enable_flag & BIT(id)); +} + +static const struct regulator_ops rt4801_regulator_ops = { + .list_voltage = regulator_list_voltage_linear, + .set_voltage_sel = rt4801_set_voltage_sel, + .get_voltage_sel = rt4801_get_voltage_sel, + .enable = rt4801_enable, + .disable = rt4801_disable, + .is_enabled = rt4801_is_enabled, +}; + +static const struct regulator_desc rt4801_regulator_descs[] = { + { + .name = "DSVP", + .ops = &rt4801_regulator_ops, + .of_match = of_match_ptr("DSVP"), + .type = REGULATOR_VOLTAGE, + .id = DSV_OUT_POS, + .min_uV = MIN_UV, + .uV_step = STEP_UV, + .n_voltages = N_VOLTAGES, + .owner = THIS_MODULE, + .vsel_reg = RT4801_REG_VOP, + .vsel_mask = VOUT_MASK, + }, + { + .name = "DSVN", + .ops = &rt4801_regulator_ops, + .of_match = of_match_ptr("DSVN"), + .type = REGULATOR_VOLTAGE, + .id = DSV_OUT_NEG, + .min_uV = MIN_UV, + .uV_step = STEP_UV, + .n_voltages = N_VOLTAGES, + .owner = THIS_MODULE, + .vsel_reg = RT4801_REG_VON, + .vsel_mask = VOUT_MASK, + }, +}; + +static const struct regmap_config rt4801_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RT4801_REG_APPS, +}; + +static int rt4801_probe(struct i2c_client *i2c) +{ + struct rt4801_priv *priv; + struct regmap *regmap; + int i; + + priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = &i2c->dev; + /* bootloader will on, driver only reconfigure enable to all output high */ + priv->enable_flag = DSVALL_ENABLE; + + regmap = devm_regmap_init_i2c(i2c, &rt4801_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&i2c->dev, "Failed to init regmap\n"); + return PTR_ERR(regmap); + } + + priv->enable_gpios = devm_gpiod_get_array_optional(&i2c->dev, "enable", GPIOD_OUT_HIGH); + if (IS_ERR(priv->enable_gpios)) { + dev_err(&i2c->dev, "Failed to get gpios\n"); + return PTR_ERR(priv->enable_gpios); + } + + for (i = 0; i < DSV_OUT_MAX; i++) { + const struct regulator_desc *desc = rt4801_regulator_descs + i; + struct regulator_config config = { .dev = &i2c->dev, .driver_data = priv, + .regmap = regmap, }; + struct regulator_dev *rdev; + unsigned int val; + int ret; + + /* initialize volt_sel variable */ + ret = regmap_read(regmap, desc->vsel_reg, &val); + if (ret) + return ret; + + priv->volt_sel[i] = val & desc->vsel_mask; + + rdev = devm_regulator_register(&i2c->dev, desc, &config); + if (IS_ERR(rdev)) { + dev_err(&i2c->dev, "Failed to register [%d] regulator\n", i); + return PTR_ERR(rdev); + } + } + + return 0; +} + +static const struct of_device_id __maybe_unused rt4801_of_id[] = { + { .compatible = "richtek,rt4801", }, + { }, +}; +MODULE_DEVICE_TABLE(of, rt4801_of_id); + +static struct i2c_driver rt4801_driver = { + .driver = { + .name = "rt4801", + .of_match_table = of_match_ptr(rt4801_of_id), + }, + .probe_new = rt4801_probe, +}; +module_i2c_driver(rt4801_driver); + +MODULE_AUTHOR("ChiYuan Hwang <cy_huang@richtek.com>"); +MODULE_DESCRIPTION("Richtek RT4801 Display Bias Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/rtmv20-regulator.c b/drivers/regulator/rtmv20-regulator.c new file mode 100644 index 000000000000..852fb2596ffd --- /dev/null +++ b/drivers/regulator/rtmv20-regulator.c @@ -0,0 +1,397 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/property.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> + +#define RTMV20_REG_DEVINFO 0x00 +#define RTMV20_REG_PULSEDELAY 0x01 +#define RTMV20_REG_PULSEWIDTH 0x03 +#define RTMV20_REG_LDCTRL1 0x05 +#define RTMV20_REG_ESPULSEWIDTH 0x06 +#define RTMV20_REG_ESLDCTRL1 0x08 +#define RTMV20_REG_LBP 0x0A +#define RTMV20_REG_LDCTRL2 0x0B +#define RTMV20_REG_FSIN1CTRL1 0x0D +#define RTMV20_REG_FSIN1CTRL3 0x0F +#define RTMV20_REG_FSIN2CTRL1 0x10 +#define RTMV20_REG_FSIN2CTRL3 0x12 +#define RTMV20_REG_ENCTRL 0x13 +#define RTMV20_REG_STRBVSYNDLYL 0x29 +#define RTMV20_REG_LDIRQ 0x30 +#define RTMV20_REG_LDSTAT 0x40 +#define RTMV20_REG_LDMASK 0x50 + +#define RTMV20_VID_MASK GENMASK(7, 4) +#define RICHTEK_VID 0x80 +#define RTMV20_LDCURR_MASK GENMASK(7, 0) +#define RTMV20_DELAY_MASK GENMASK(9, 0) +#define RTMV20_WIDTH_MASK GENMASK(13, 0) +#define RTMV20_WIDTH2_MASK GENMASK(7, 0) +#define RTMV20_LBPLVL_MASK GENMASK(3, 0) +#define RTMV20_LBPEN_MASK BIT(7) +#define RTMV20_STROBEPOL_MASK BIT(1) +#define RTMV20_VSYNPOL_MASK BIT(1) +#define RTMV20_FSINEN_MASK BIT(7) +#define RTMV20_ESEN_MASK BIT(6) +#define RTMV20_FSINOUT_MASK BIT(2) +#define LDENABLE_MASK (BIT(3) | BIT(0)) + +#define OTPEVT_MASK BIT(4) +#define SHORTEVT_MASK BIT(3) +#define OPENEVT_MASK BIT(2) +#define LBPEVT_MASK BIT(1) +#define OCPEVT_MASK BIT(0) +#define FAILEVT_MASK (SHORTEVT_MASK | OPENEVT_MASK | LBPEVT_MASK) + +#define RTMV20_LSW_MINUA 0 +#define RTMV20_LSW_MAXUA 6000000 +#define RTMV20_LSW_STEPUA 30000 + +#define RTMV20_LSW_DEFAULTUA 3000000 + +#define RTMV20_I2CRDY_TIMEUS 200 +#define RTMV20_CSRDY_TIMEUS 2000 + +struct rtmv20_priv { + struct device *dev; + struct regmap *regmap; + struct gpio_desc *enable_gpio; + struct regulator_dev *rdev; +}; + +static int rtmv20_lsw_enable(struct regulator_dev *rdev) +{ + struct rtmv20_priv *priv = rdev_get_drvdata(rdev); + int ret; + + gpiod_set_value(priv->enable_gpio, 1); + + /* Wait for I2C can be accessed */ + usleep_range(RTMV20_I2CRDY_TIMEUS, RTMV20_I2CRDY_TIMEUS + 100); + + /* HW re-enable, disable cache only and sync regcache here */ + regcache_cache_only(priv->regmap, false); + ret = regcache_sync(priv->regmap); + if (ret) + return ret; + + return regulator_enable_regmap(rdev); +} + +static int rtmv20_lsw_disable(struct regulator_dev *rdev) +{ + struct rtmv20_priv *priv = rdev_get_drvdata(rdev); + int ret; + + ret = regulator_disable_regmap(rdev); + if (ret) + return ret; + + /* Mark the regcache as dirty and cache only before HW disabled */ + regcache_cache_only(priv->regmap, true); + regcache_mark_dirty(priv->regmap); + + gpiod_set_value(priv->enable_gpio, 0); + + return 0; +} + +static const struct regulator_ops rtmv20_regulator_ops = { + .set_current_limit = regulator_set_current_limit_regmap, + .get_current_limit = regulator_get_current_limit_regmap, + .enable = rtmv20_lsw_enable, + .disable = rtmv20_lsw_disable, + .is_enabled = regulator_is_enabled_regmap, +}; + +static const struct regulator_desc rtmv20_lsw_desc = { + .name = "rtmv20,lsw", + .of_match = of_match_ptr("lsw"), + .type = REGULATOR_CURRENT, + .owner = THIS_MODULE, + .ops = &rtmv20_regulator_ops, + .csel_reg = RTMV20_REG_LDCTRL1, + .csel_mask = RTMV20_LDCURR_MASK, + .enable_reg = RTMV20_REG_ENCTRL, + .enable_mask = LDENABLE_MASK, + .enable_time = RTMV20_CSRDY_TIMEUS, +}; + +static irqreturn_t rtmv20_irq_handler(int irq, void *data) +{ + struct rtmv20_priv *priv = data; + unsigned int val; + int ret; + + ret = regmap_read(priv->regmap, RTMV20_REG_LDIRQ, &val); + if (ret) { + dev_err(priv->dev, "Failed to get irq flags\n"); + return IRQ_NONE; + } + + if (val & OTPEVT_MASK) + regulator_notifier_call_chain(priv->rdev, REGULATOR_EVENT_OVER_TEMP, NULL); + + if (val & OCPEVT_MASK) + regulator_notifier_call_chain(priv->rdev, REGULATOR_EVENT_OVER_CURRENT, NULL); + + if (val & FAILEVT_MASK) + regulator_notifier_call_chain(priv->rdev, REGULATOR_EVENT_FAIL, NULL); + + return IRQ_HANDLED; +} + +static u32 clamp_to_selector(u32 val, u32 min, u32 max, u32 step) +{ + u32 retval = clamp_val(val, min, max); + + return (retval - min) / step; +} + +static int rtmv20_properties_init(struct rtmv20_priv *priv) +{ + const struct { + const char *name; + u32 def; + u32 min; + u32 max; + u32 step; + u32 addr; + u32 mask; + } props[] = { + { "richtek,ld-pulse-delay-us", 0, 0, 100000, 100, RTMV20_REG_PULSEDELAY, + RTMV20_DELAY_MASK }, + { "richtek,ld-pulse-width-us", 1200, 0, 10000, 1, RTMV20_REG_PULSEWIDTH, + RTMV20_WIDTH_MASK }, + { "richtek,fsin1-delay-us", 23000, 0, 100000, 100, RTMV20_REG_FSIN1CTRL1, + RTMV20_DELAY_MASK }, + { "richtek,fsin1-width-us", 160, 40, 10000, 40, RTMV20_REG_FSIN1CTRL3, + RTMV20_WIDTH2_MASK }, + { "richtek,fsin2-delay-us", 23000, 0, 100000, 100, RTMV20_REG_FSIN2CTRL1, + RTMV20_DELAY_MASK }, + { "richtek,fsin2-width-us", 160, 40, 10000, 40, RTMV20_REG_FSIN2CTRL3, + RTMV20_WIDTH2_MASK }, + { "richtek,es-pulse-width-us", 1200, 0, 10000, 1, RTMV20_REG_ESPULSEWIDTH, + RTMV20_WIDTH_MASK }, + { "richtek,es-ld-current-microamp", 3000000, 0, 6000000, 30000, + RTMV20_REG_ESLDCTRL1, RTMV20_LDCURR_MASK }, + { "richtek,lbp-level-microvolt", 2700000, 2400000, 3700000, 100000, RTMV20_REG_LBP, + RTMV20_LBPLVL_MASK }, + { "richtek,lbp-enable", 0, 0, 1, 1, RTMV20_REG_LBP, RTMV20_LBPEN_MASK }, + { "richtek,strobe-polarity-high", 1, 0, 1, 1, RTMV20_REG_LDCTRL2, + RTMV20_STROBEPOL_MASK }, + { "richtek,vsync-polarity-high", 1, 0, 1, 1, RTMV20_REG_LDCTRL2, + RTMV20_VSYNPOL_MASK }, + { "richtek,fsin-enable", 0, 0, 1, 1, RTMV20_REG_ENCTRL, RTMV20_FSINEN_MASK }, + { "richtek,fsin-output", 0, 0, 1, 1, RTMV20_REG_ENCTRL, RTMV20_FSINOUT_MASK }, + { "richtek,es-enable", 0, 0, 1, 1, RTMV20_REG_ENCTRL, RTMV20_ESEN_MASK }, + }; + int i, ret; + + for (i = 0; i < ARRAY_SIZE(props); i++) { + __be16 bval16; + u16 val16; + u32 temp; + int significant_bit = fls(props[i].mask); + int shift = ffs(props[i].mask) - 1; + + if (props[i].max > 1) { + ret = device_property_read_u32(priv->dev, props[i].name, &temp); + if (ret) + temp = props[i].def; + } else + temp = device_property_read_bool(priv->dev, props[i].name); + + temp = clamp_to_selector(temp, props[i].min, props[i].max, props[i].step); + + /* If significant bit is over 8, two byte access, others one */ + if (significant_bit > 8) { + ret = regmap_raw_read(priv->regmap, props[i].addr, &bval16, sizeof(bval16)); + if (ret) + return ret; + + val16 = be16_to_cpu(bval16); + val16 &= ~props[i].mask; + val16 |= (temp << shift); + bval16 = cpu_to_be16(val16); + + ret = regmap_raw_write(priv->regmap, props[i].addr, &bval16, + sizeof(bval16)); + } else { + ret = regmap_update_bits(priv->regmap, props[i].addr, props[i].mask, + temp << shift); + } + + if (ret) + return ret; + } + + return 0; +} + +static int rtmv20_check_chip_exist(struct rtmv20_priv *priv) +{ + unsigned int val; + int ret; + + ret = regmap_read(priv->regmap, RTMV20_REG_DEVINFO, &val); + if (ret) + return ret; + + if ((val & RTMV20_VID_MASK) != RICHTEK_VID) + return -ENODEV; + + return 0; +} + +static bool rtmv20_is_accessible_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RTMV20_REG_DEVINFO ... RTMV20_REG_STRBVSYNDLYL: + case RTMV20_REG_LDIRQ: + case RTMV20_REG_LDSTAT: + case RTMV20_REG_LDMASK: + return true; + } + return false; +} + +static bool rtmv20_is_volatile_reg(struct device *dev, unsigned int reg) +{ + if (reg == RTMV20_REG_LDIRQ || reg == RTMV20_REG_LDSTAT) + return true; + return false; +} + +static const struct regmap_config rtmv20_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .cache_type = REGCACHE_RBTREE, + .max_register = RTMV20_REG_LDMASK, + + .writeable_reg = rtmv20_is_accessible_reg, + .readable_reg = rtmv20_is_accessible_reg, + .volatile_reg = rtmv20_is_volatile_reg, +}; + +static int rtmv20_probe(struct i2c_client *i2c) +{ + struct rtmv20_priv *priv; + struct regulator_config config = {}; + int ret; + + priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = &i2c->dev; + + /* Before regmap register, configure HW enable to make I2C accessible */ + priv->enable_gpio = devm_gpiod_get(&i2c->dev, "enable", GPIOD_OUT_HIGH); + if (IS_ERR(priv->enable_gpio)) { + dev_err(&i2c->dev, "Failed to get enable gpio\n"); + return PTR_ERR(priv->enable_gpio); + } + + /* Wait for I2C can be accessed */ + usleep_range(RTMV20_I2CRDY_TIMEUS, RTMV20_I2CRDY_TIMEUS + 100); + + priv->regmap = devm_regmap_init_i2c(i2c, &rtmv20_regmap_config); + if (IS_ERR(priv->regmap)) { + dev_err(&i2c->dev, "Failed to allocate register map\n"); + return PTR_ERR(priv->regmap); + } + + ret = rtmv20_check_chip_exist(priv); + if (ret) { + dev_err(&i2c->dev, "Chip vendor info is not matched\n"); + return ret; + } + + ret = rtmv20_properties_init(priv); + if (ret) { + dev_err(&i2c->dev, "Failed to init properties\n"); + return ret; + } + + /* + * keep in shutdown mode to minimize the current consumption + * and also mark regcache as dirty + */ + regcache_cache_only(priv->regmap, true); + regcache_mark_dirty(priv->regmap); + gpiod_set_value(priv->enable_gpio, 0); + + config.dev = &i2c->dev; + config.regmap = priv->regmap; + config.driver_data = priv; + priv->rdev = devm_regulator_register(&i2c->dev, &rtmv20_lsw_desc, &config); + if (IS_ERR(priv->rdev)) { + dev_err(&i2c->dev, "Failed to register regulator\n"); + return PTR_ERR(priv->rdev); + } + + /* Unmask all events before IRQ registered */ + ret = regmap_write(priv->regmap, RTMV20_REG_LDMASK, 0); + if (ret) + return ret; + + return devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, rtmv20_irq_handler, + IRQF_ONESHOT, dev_name(&i2c->dev), priv); +} + +static int __maybe_unused rtmv20_suspend(struct device *dev) +{ + struct i2c_client *i2c = to_i2c_client(dev); + + /* + * When system suspend, disable irq to prevent interrupt trigger + * during I2C bus suspend + */ + disable_irq(i2c->irq); + if (device_may_wakeup(dev)) + enable_irq_wake(i2c->irq); + + return 0; +} + +static int __maybe_unused rtmv20_resume(struct device *dev) +{ + struct i2c_client *i2c = to_i2c_client(dev); + + /* Enable irq after I2C bus already resume */ + enable_irq(i2c->irq); + if (device_may_wakeup(dev)) + disable_irq_wake(i2c->irq); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(rtmv20_pm, rtmv20_suspend, rtmv20_resume); + +static const struct of_device_id __maybe_unused rtmv20_of_id[] = { + { .compatible = "richtek,rtmv20", }, + {} +}; +MODULE_DEVICE_TABLE(of, rtmv20_of_id); + +static struct i2c_driver rtmv20_driver = { + .driver = { + .name = "rtmv20", + .of_match_table = of_match_ptr(rtmv20_of_id), + .pm = &rtmv20_pm, + }, + .probe_new = rtmv20_probe, +}; +module_i2c_driver(rtmv20_driver); + +MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); +MODULE_DESCRIPTION("Richtek RTMV20 Regulator Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 4abd3ed31f60..3fa472127e9a 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -1000,18 +1000,7 @@ static struct platform_driver s5m8767_pmic_driver = { .probe = s5m8767_pmic_probe, .id_table = s5m8767_pmic_id, }; - -static int __init s5m8767_pmic_init(void) -{ - return platform_driver_register(&s5m8767_pmic_driver); -} -subsys_initcall(s5m8767_pmic_init); - -static void __exit s5m8767_pmic_exit(void) -{ - platform_driver_unregister(&s5m8767_pmic_driver); -} -module_exit(s5m8767_pmic_exit); +module_platform_driver(s5m8767_pmic_driver); /* Module information */ MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>"); diff --git a/drivers/regulator/slg51000-regulator.c b/drivers/regulator/slg51000-regulator.c index 87b020d0b958..75a941fb3c2b 100644 --- a/drivers/regulator/slg51000-regulator.c +++ b/drivers/regulator/slg51000-regulator.c @@ -386,10 +386,8 @@ static irqreturn_t slg51000_irq_handler(int irq, void *data) for (i = 0; i < SLG51000_MAX_REGULATORS; i++) { if (!(evt[i][R2] & SLG51000_IRQ_ILIM_FLAG_MASK) && (evt[i][R0] & SLG51000_EVT_ILIM_FLAG_MASK)) { - regulator_lock(chip->rdev[i]); regulator_notifier_call_chain(chip->rdev[i], REGULATOR_EVENT_OVER_CURRENT, NULL); - regulator_unlock(chip->rdev[i]); if (evt[i][R1] & SLG51000_STA_ILIM_FLAG_MASK) dev_warn(chip->dev, @@ -403,10 +401,8 @@ static irqreturn_t slg51000_irq_handler(int irq, void *data) for (i = 0; i < SLG51000_MAX_REGULATORS; i++) { if (!(evt[i][R1] & SLG51000_STA_ILIM_FLAG_MASK) && (evt[i][R1] & SLG51000_STA_VOUT_OK_FLAG_MASK)) { - regulator_lock(chip->rdev[i]); regulator_notifier_call_chain(chip->rdev[i], REGULATOR_EVENT_OVER_TEMP, NULL); - regulator_unlock(chip->rdev[i]); } } handled = IRQ_HANDLED; diff --git a/drivers/regulator/stm32-booster.c b/drivers/regulator/stm32-booster.c index 03f162ffd144..3136ea8a35d5 100644 --- a/drivers/regulator/stm32-booster.c +++ b/drivers/regulator/stm32-booster.c @@ -101,7 +101,7 @@ static int stm32_booster_probe(struct platform_device *pdev) return 0; } -static const struct of_device_id stm32_booster_of_match[] = { +static const struct of_device_id __maybe_unused stm32_booster_of_match[] = { { .compatible = "st,stm32h7-booster", .data = (void *)&stm32h7_booster_desc diff --git a/drivers/regulator/stm32-pwr.c b/drivers/regulator/stm32-pwr.c index e0e627b0106e..2a42acb7c24e 100644 --- a/drivers/regulator/stm32-pwr.c +++ b/drivers/regulator/stm32-pwr.c @@ -166,7 +166,7 @@ static int stm32_pwr_regulator_probe(struct platform_device *pdev) return ret; } -static const struct of_device_id stm32_pwr_of_match[] = { +static const struct of_device_id __maybe_unused stm32_pwr_of_match[] = { { .compatible = "st,stm32mp1,pwr-reg", }, {}, }; diff --git a/drivers/regulator/stm32-vrefbuf.c b/drivers/regulator/stm32-vrefbuf.c index 992bc18101ef..161622ea7259 100644 --- a/drivers/regulator/stm32-vrefbuf.c +++ b/drivers/regulator/stm32-vrefbuf.c @@ -284,7 +284,7 @@ static const struct dev_pm_ops stm32_vrefbuf_pm_ops = { NULL) }; -static const struct of_device_id stm32_vrefbuf_of_match[] = { +static const struct of_device_id __maybe_unused stm32_vrefbuf_of_match[] = { { .compatible = "st,stm32-vrefbuf", }, {}, }; diff --git a/drivers/regulator/stpmic1_regulator.c b/drivers/regulator/stpmic1_regulator.c index 73e0ab2baeaa..cf10fdb72e32 100644 --- a/drivers/regulator/stpmic1_regulator.c +++ b/drivers/regulator/stpmic1_regulator.c @@ -505,15 +505,11 @@ static irqreturn_t stpmic1_curlim_irq_handler(int irq, void *data) { struct regulator_dev *rdev = (struct regulator_dev *)data; - regulator_lock(rdev); - /* Send an overcurrent notification */ regulator_notifier_call_chain(rdev, REGULATOR_EVENT_OVER_CURRENT, NULL); - regulator_unlock(rdev); - return IRQ_HANDLED; } diff --git a/drivers/regulator/stw481x-vmmc.c b/drivers/regulator/stw481x-vmmc.c index 6dc2316daad3..127ab43add49 100644 --- a/drivers/regulator/stw481x-vmmc.c +++ b/drivers/regulator/stw481x-vmmc.c @@ -27,7 +27,7 @@ static const unsigned int stw481x_vmmc_voltages[] = { 3300000, }; -static struct regulator_ops stw481x_vmmc_ops = { +static const struct regulator_ops stw481x_vmmc_ops = { .list_voltage = regulator_list_voltage_table, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -36,7 +36,7 @@ static struct regulator_ops stw481x_vmmc_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, }; -static struct regulator_desc vmmc_regulator = { +static const struct regulator_desc vmmc_regulator = { .name = "VMMC", .id = 0, .ops = &stw481x_vmmc_ops, diff --git a/drivers/regulator/sy8106a-regulator.c b/drivers/regulator/sy8106a-regulator.c index 2222e739e62b..c119f85259a5 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 sy8106a_i2c_of_match[] = { +static const struct of_device_id __maybe_unused sy8106a_i2c_of_match[] = { { .compatible = "silergy,sy8106a" }, { }, }; diff --git a/drivers/regulator/sy8827n.c b/drivers/regulator/sy8827n.c index b207217f74d8..52e8c17afe24 100644 --- a/drivers/regulator/sy8827n.c +++ b/drivers/regulator/sy8827n.c @@ -156,6 +156,7 @@ 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", @@ -163,6 +164,7 @@ 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", }, diff --git a/drivers/regulator/ti-abb-regulator.c b/drivers/regulator/ti-abb-regulator.c index af9abcd9c166..3e60bff76194 100644 --- a/drivers/regulator/ti-abb-regulator.c +++ b/drivers/regulator/ti-abb-regulator.c @@ -619,7 +619,7 @@ check_abb: return 0; } -static struct regulator_ops ti_abb_reg_ops = { +static const struct regulator_ops ti_abb_reg_ops = { .list_voltage = regulator_list_voltage_table, .set_voltage_sel = ti_abb_set_voltage_sel, diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c index c139890c1514..a15e415e61d5 100644 --- a/drivers/regulator/tps51632-regulator.c +++ b/drivers/regulator/tps51632-regulator.c @@ -108,7 +108,7 @@ static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev, return ret; } -static struct regulator_ops tps51632_dcdc_ops = { +static const struct regulator_ops tps51632_dcdc_ops = { .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, .list_voltage = regulator_list_voltage_linear, diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c index f8939af0bd2c..a6469fe05635 100644 --- a/drivers/regulator/tps6105x-regulator.c +++ b/drivers/regulator/tps6105x-regulator.c @@ -26,7 +26,7 @@ static const unsigned int tps6105x_voltages[] = { 5000000, /* There is an additional 5V */ }; -static struct regulator_ops tps6105x_regulator_ops = { +static const struct regulator_ops tps6105x_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index f6a6d36a6533..315cd5daf480 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -233,7 +233,7 @@ static unsigned int tps62360_get_mode(struct regulator_dev *rdev) REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; } -static struct regulator_ops tps62360_dcdc_ops = { +static const struct regulator_ops tps62360_dcdc_ops = { .get_voltage_sel = tps62360_dcdc_get_voltage_sel, .set_voltage_sel = tps62360_dcdc_set_voltage_sel, .list_voltage = regulator_list_voltage_linear, diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 795d459ff3cf..f25806531c7e 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -316,7 +316,7 @@ static int tps_65023_probe(struct i2c_client *client, return 0; } -static const struct of_device_id tps65023_of_match[] = { +static const struct of_device_id __maybe_unused tps65023_of_match[] = { { .compatible = "ti,tps65020", .data = &tps65020_drv_data}, { .compatible = "ti,tps65021", .data = &tps65021_drv_data}, { .compatible = "ti,tps65023", .data = &tps65023_drv_data}, diff --git a/drivers/regulator/tps65086-regulator.c b/drivers/regulator/tps65086-regulator.c index 23528475a962..070c956216b0 100644 --- a/drivers/regulator/tps65086-regulator.c +++ b/drivers/regulator/tps65086-regulator.c @@ -101,7 +101,7 @@ static const struct linear_range tps65086_ldoa23_ranges[] = { }; /* Operations permitted on regulators */ -static struct regulator_ops reg_ops = { +static const struct regulator_ops reg_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -112,7 +112,7 @@ static struct regulator_ops reg_ops = { }; /* Operations permitted on load switches */ -static struct regulator_ops switch_ops = { +static const struct regulator_ops switch_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c index f0b660e9f15f..1d2e04f452d4 100644 --- a/drivers/regulator/tps65090-regulator.c +++ b/drivers/regulator/tps65090-regulator.c @@ -47,7 +47,7 @@ struct tps65090_regulator { int overcurrent_wait; }; -static struct regulator_ops tps65090_ext_control_ops = { +static const struct regulator_ops tps65090_ext_control_ops = { }; /** @@ -167,19 +167,19 @@ err: return ret; } -static struct regulator_ops tps65090_reg_control_ops = { +static const struct regulator_ops tps65090_reg_control_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, }; -static struct regulator_ops tps65090_fet_control_ops = { +static const struct regulator_ops tps65090_fet_control_ops = { .enable = tps65090_fet_enable, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, }; -static struct regulator_ops tps65090_ldo_ops = { +static const struct regulator_ops tps65090_ldo_ops = { }; #define tps65090_REG_DESC(_id, _sname, _en_reg, _en_bits, _nvolt, _volt, _ops) \ diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 09e994e1f9a9..18bf4b885b08 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -60,7 +60,7 @@ struct tps6586x_regulator { int enable_reg[2]; }; -static struct regulator_ops tps6586x_rw_regulator_ops = { +static const struct regulator_ops tps6586x_rw_regulator_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -71,7 +71,7 @@ static struct regulator_ops tps6586x_rw_regulator_ops = { .disable = regulator_disable_regmap, }; -static struct regulator_ops tps6586x_rw_linear_regulator_ops = { +static const struct regulator_ops tps6586x_rw_linear_regulator_ops = { .list_voltage = regulator_list_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, @@ -81,7 +81,7 @@ static struct regulator_ops tps6586x_rw_linear_regulator_ops = { .disable = regulator_disable_regmap, }; -static struct regulator_ops tps6586x_ro_regulator_ops = { +static const struct regulator_ops tps6586x_ro_regulator_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -91,7 +91,7 @@ static struct regulator_ops tps6586x_ro_regulator_ops = { .disable = regulator_disable_regmap, }; -static struct regulator_ops tps6586x_sys_regulator_ops = { +static const struct regulator_ops tps6586x_sys_regulator_ops = { }; static const unsigned int tps6586x_ldo0_voltages[] = { diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 4eb5b19d2344..1d5b0a1b86f7 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -390,8 +390,8 @@ static int tps65911_get_ctrl_register(int id) static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode) { struct tps65910_reg *pmic = rdev_get_drvdata(dev); - struct tps65910 *mfd = pmic->mfd; - int reg, value, id = rdev_get_id(dev); + struct regmap *regmap = rdev_get_regmap(dev); + int reg, id = rdev_get_id(dev); reg = pmic->get_ctrl_reg(id); if (reg < 0) @@ -399,14 +399,14 @@ static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode) switch (mode) { case REGULATOR_MODE_NORMAL: - return tps65910_reg_update_bits(pmic->mfd, reg, - LDO_ST_MODE_BIT | LDO_ST_ON_BIT, - LDO_ST_ON_BIT); + return regmap_update_bits(regmap, reg, + LDO_ST_MODE_BIT | LDO_ST_ON_BIT, + LDO_ST_ON_BIT); case REGULATOR_MODE_IDLE: - value = LDO_ST_ON_BIT | LDO_ST_MODE_BIT; - return tps65910_reg_set_bits(mfd, reg, value); + return regmap_set_bits(regmap, reg, + LDO_ST_ON_BIT | LDO_ST_MODE_BIT); case REGULATOR_MODE_STANDBY: - return tps65910_reg_clear_bits(mfd, reg, LDO_ST_ON_BIT); + return regmap_clear_bits(regmap, reg, LDO_ST_ON_BIT); } return -EINVAL; @@ -415,13 +415,14 @@ static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode) static unsigned int tps65910_get_mode(struct regulator_dev *dev) { struct tps65910_reg *pmic = rdev_get_drvdata(dev); + struct regmap *regmap = rdev_get_regmap(dev); int ret, reg, value, id = rdev_get_id(dev); reg = pmic->get_ctrl_reg(id); if (reg < 0) return reg; - ret = tps65910_reg_read(pmic->mfd, reg, &value); + ret = regmap_read(regmap, reg, &value); if (ret < 0) return ret; @@ -435,20 +436,20 @@ static unsigned int tps65910_get_mode(struct regulator_dev *dev) static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev) { - struct tps65910_reg *pmic = rdev_get_drvdata(dev); + struct regmap *regmap = rdev_get_regmap(dev); int ret, id = rdev_get_id(dev); int opvsel = 0, srvsel = 0, vselmax = 0, mult = 0, sr = 0; switch (id) { case TPS65910_REG_VDD1: - ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1_OP, &opvsel); + ret = regmap_read(regmap, TPS65910_VDD1_OP, &opvsel); if (ret < 0) return ret; - ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1, &mult); + ret = regmap_read(regmap, TPS65910_VDD1, &mult); if (ret < 0) return ret; mult = (mult & VDD1_VGAIN_SEL_MASK) >> VDD1_VGAIN_SEL_SHIFT; - ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1_SR, &srvsel); + ret = regmap_read(regmap, TPS65910_VDD1_SR, &srvsel); if (ret < 0) return ret; sr = opvsel & VDD1_OP_CMD_MASK; @@ -457,14 +458,14 @@ static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev) vselmax = 75; break; case TPS65910_REG_VDD2: - ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2_OP, &opvsel); + ret = regmap_read(regmap, TPS65910_VDD2_OP, &opvsel); if (ret < 0) return ret; - ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2, &mult); + ret = regmap_read(regmap, TPS65910_VDD2, &mult); if (ret < 0) return ret; mult = (mult & VDD2_VGAIN_SEL_MASK) >> VDD2_VGAIN_SEL_SHIFT; - ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2_SR, &srvsel); + ret = regmap_read(regmap, TPS65910_VDD2_SR, &srvsel); if (ret < 0) return ret; sr = opvsel & VDD2_OP_CMD_MASK; @@ -473,12 +474,10 @@ static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev) vselmax = 75; break; case TPS65911_REG_VDDCTRL: - ret = tps65910_reg_read(pmic->mfd, TPS65911_VDDCTRL_OP, - &opvsel); + ret = regmap_read(regmap, TPS65911_VDDCTRL_OP, &opvsel); if (ret < 0) return ret; - ret = tps65910_reg_read(pmic->mfd, TPS65911_VDDCTRL_SR, - &srvsel); + ret = regmap_read(regmap, TPS65911_VDDCTRL_SR, &srvsel); if (ret < 0) return ret; sr = opvsel & VDDCTRL_OP_CMD_MASK; @@ -514,13 +513,14 @@ static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev) static int tps65910_get_voltage_sel(struct regulator_dev *dev) { struct tps65910_reg *pmic = rdev_get_drvdata(dev); + struct regmap *regmap = rdev_get_regmap(dev); int ret, reg, value, id = rdev_get_id(dev); reg = pmic->get_ctrl_reg(id); if (reg < 0) return reg; - ret = tps65910_reg_read(pmic->mfd, reg, &value); + ret = regmap_read(regmap, reg, &value); if (ret < 0) return ret; @@ -556,12 +556,13 @@ static int tps65910_get_voltage_vdd3(struct regulator_dev *dev) static int tps65911_get_voltage_sel(struct regulator_dev *dev) { struct tps65910_reg *pmic = rdev_get_drvdata(dev); + struct regmap *regmap = rdev_get_regmap(dev); int ret, id = rdev_get_id(dev); unsigned int value, reg; reg = pmic->get_ctrl_reg(id); - ret = tps65910_reg_read(pmic->mfd, reg, &value); + ret = regmap_read(regmap, reg, &value); if (ret < 0) return ret; @@ -594,7 +595,7 @@ static int tps65911_get_voltage_sel(struct regulator_dev *dev) static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev, unsigned selector) { - struct tps65910_reg *pmic = rdev_get_drvdata(dev); + struct regmap *regmap = rdev_get_regmap(dev); int id = rdev_get_id(dev), vsel; int dcdc_mult = 0; @@ -605,10 +606,9 @@ static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev, dcdc_mult--; vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3; - tps65910_reg_update_bits(pmic->mfd, TPS65910_VDD1, - VDD1_VGAIN_SEL_MASK, - dcdc_mult << VDD1_VGAIN_SEL_SHIFT); - tps65910_reg_write(pmic->mfd, TPS65910_VDD1_OP, vsel); + regmap_update_bits(regmap, TPS65910_VDD1, VDD1_VGAIN_SEL_MASK, + dcdc_mult << VDD1_VGAIN_SEL_SHIFT); + regmap_write(regmap, TPS65910_VDD1_OP, vsel); break; case TPS65910_REG_VDD2: dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1; @@ -616,14 +616,14 @@ static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev, dcdc_mult--; vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3; - tps65910_reg_update_bits(pmic->mfd, TPS65910_VDD2, - VDD1_VGAIN_SEL_MASK, - dcdc_mult << VDD2_VGAIN_SEL_SHIFT); - tps65910_reg_write(pmic->mfd, TPS65910_VDD2_OP, vsel); + regmap_update_bits(regmap, TPS65910_VDD2, VDD1_VGAIN_SEL_MASK, + dcdc_mult << VDD2_VGAIN_SEL_SHIFT); + regmap_write(regmap, TPS65910_VDD2_OP, vsel); break; case TPS65911_REG_VDDCTRL: vsel = selector + 3; - tps65910_reg_write(pmic->mfd, TPS65911_VDDCTRL_OP, vsel); + regmap_write(regmap, TPS65911_VDDCTRL_OP, vsel); + break; } return 0; @@ -633,6 +633,7 @@ static int tps65910_set_voltage_sel(struct regulator_dev *dev, unsigned selector) { struct tps65910_reg *pmic = rdev_get_drvdata(dev); + struct regmap *regmap = rdev_get_regmap(dev); int reg, id = rdev_get_id(dev); reg = pmic->get_ctrl_reg(id); @@ -649,11 +650,11 @@ static int tps65910_set_voltage_sel(struct regulator_dev *dev, case TPS65910_REG_VAUX2: case TPS65910_REG_VAUX33: case TPS65910_REG_VMMC: - return tps65910_reg_update_bits(pmic->mfd, reg, LDO_SEL_MASK, - selector << LDO_SEL_SHIFT); + return regmap_update_bits(regmap, reg, LDO_SEL_MASK, + selector << LDO_SEL_SHIFT); case TPS65910_REG_VBB: - return tps65910_reg_update_bits(pmic->mfd, reg, BBCH_BBSEL_MASK, - selector << BBCH_BBSEL_SHIFT); + return regmap_update_bits(regmap, reg, BBCH_BBSEL_MASK, + selector << BBCH_BBSEL_SHIFT); } return -EINVAL; @@ -663,6 +664,7 @@ static int tps65911_set_voltage_sel(struct regulator_dev *dev, unsigned selector) { struct tps65910_reg *pmic = rdev_get_drvdata(dev); + struct regmap *regmap = rdev_get_regmap(dev); int reg, id = rdev_get_id(dev); reg = pmic->get_ctrl_reg(id); @@ -673,21 +675,21 @@ static int tps65911_set_voltage_sel(struct regulator_dev *dev, case TPS65911_REG_LDO1: case TPS65911_REG_LDO2: case TPS65911_REG_LDO4: - return tps65910_reg_update_bits(pmic->mfd, reg, LDO1_SEL_MASK, - selector << LDO_SEL_SHIFT); + return regmap_update_bits(regmap, reg, LDO1_SEL_MASK, + selector << LDO_SEL_SHIFT); case TPS65911_REG_LDO3: case TPS65911_REG_LDO5: case TPS65911_REG_LDO6: case TPS65911_REG_LDO7: case TPS65911_REG_LDO8: - return tps65910_reg_update_bits(pmic->mfd, reg, LDO3_SEL_MASK, - selector << LDO_SEL_SHIFT); + return regmap_update_bits(regmap, reg, LDO3_SEL_MASK, + selector << LDO_SEL_SHIFT); case TPS65910_REG_VIO: - return tps65910_reg_update_bits(pmic->mfd, reg, LDO_SEL_MASK, - selector << LDO_SEL_SHIFT); + return regmap_update_bits(regmap, reg, LDO_SEL_MASK, + selector << LDO_SEL_SHIFT); case TPS65910_REG_VBB: - return tps65910_reg_update_bits(pmic->mfd, reg, BBCH_BBSEL_MASK, - selector << BBCH_BBSEL_SHIFT); + return regmap_update_bits(regmap, reg, BBCH_BBSEL_MASK, + selector << BBCH_BBSEL_SHIFT); } return -EINVAL; @@ -757,7 +759,7 @@ static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector) } /* Regulator ops (except VRTC) */ -static struct regulator_ops tps65910_ops_dcdc = { +static const struct regulator_ops tps65910_ops_dcdc = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -770,7 +772,7 @@ static struct regulator_ops tps65910_ops_dcdc = { .map_voltage = regulator_map_voltage_ascend, }; -static struct regulator_ops tps65910_ops_vdd3 = { +static const struct regulator_ops tps65910_ops_vdd3 = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -781,7 +783,7 @@ static struct regulator_ops tps65910_ops_vdd3 = { .map_voltage = regulator_map_voltage_ascend, }; -static struct regulator_ops tps65910_ops_vbb = { +static const struct regulator_ops tps65910_ops_vbb = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -793,7 +795,7 @@ static struct regulator_ops tps65910_ops_vbb = { .map_voltage = regulator_map_voltage_iterate, }; -static struct regulator_ops tps65910_ops = { +static const struct regulator_ops tps65910_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -805,7 +807,7 @@ static struct regulator_ops tps65910_ops = { .map_voltage = regulator_map_voltage_ascend, }; -static struct regulator_ops tps65911_ops = { +static const struct regulator_ops tps65911_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -850,10 +852,10 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic, /* External EN1 control */ if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1) - ret = tps65910_reg_set_bits(mfd, + ret = regmap_set_bits(mfd->regmap, TPS65910_EN1_LDO_ASS + regoffs, bit_pos); else - ret = tps65910_reg_clear_bits(mfd, + ret = regmap_clear_bits(mfd->regmap, TPS65910_EN1_LDO_ASS + regoffs, bit_pos); if (ret < 0) { dev_err(mfd->dev, @@ -863,10 +865,10 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic, /* External EN2 control */ if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2) - ret = tps65910_reg_set_bits(mfd, + ret = regmap_set_bits(mfd->regmap, TPS65910_EN2_LDO_ASS + regoffs, bit_pos); else - ret = tps65910_reg_clear_bits(mfd, + ret = regmap_clear_bits(mfd->regmap, TPS65910_EN2_LDO_ASS + regoffs, bit_pos); if (ret < 0) { dev_err(mfd->dev, @@ -878,10 +880,10 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic, if ((tps65910_chip_id(mfd) == TPS65910) && (id >= TPS65910_REG_VDIG1)) { if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3) - ret = tps65910_reg_set_bits(mfd, + ret = regmap_set_bits(mfd->regmap, TPS65910_EN3_LDO_ASS + regoffs, bit_pos); else - ret = tps65910_reg_clear_bits(mfd, + ret = regmap_clear_bits(mfd->regmap, TPS65910_EN3_LDO_ASS + regoffs, bit_pos); if (ret < 0) { dev_err(mfd->dev, @@ -893,10 +895,10 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic, /* Return if no external control is selected */ if (!(ext_sleep_config & EXT_SLEEP_CONTROL)) { /* Clear all sleep controls */ - ret = tps65910_reg_clear_bits(mfd, + ret = regmap_clear_bits(mfd->regmap, TPS65910_SLEEP_KEEP_LDO_ON + regoffs, bit_pos); if (!ret) - ret = tps65910_reg_clear_bits(mfd, + ret = regmap_clear_bits(mfd->regmap, TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos); if (ret < 0) dev_err(mfd->dev, @@ -917,39 +919,38 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic, int sr_reg_add = pmic->get_ctrl_reg(id) + 2; int opvsel, srvsel; - ret = tps65910_reg_read(pmic->mfd, op_reg_add, &opvsel); + ret = regmap_read(mfd->regmap, op_reg_add, &opvsel); if (ret < 0) return ret; - ret = tps65910_reg_read(pmic->mfd, sr_reg_add, &srvsel); + ret = regmap_read(mfd->regmap, sr_reg_add, &srvsel); if (ret < 0) return ret; if (opvsel & VDD1_OP_CMD_MASK) { u8 reg_val = srvsel & VDD1_OP_SEL_MASK; - ret = tps65910_reg_write(pmic->mfd, op_reg_add, - reg_val); + ret = regmap_write(mfd->regmap, op_reg_add, reg_val); if (ret < 0) { dev_err(mfd->dev, "Error in configuring op register\n"); return ret; } } - ret = tps65910_reg_write(pmic->mfd, sr_reg_add, 0); + ret = regmap_write(mfd->regmap, sr_reg_add, 0); if (ret < 0) { dev_err(mfd->dev, "Error in setting sr register\n"); return ret; } } - ret = tps65910_reg_clear_bits(mfd, + ret = regmap_clear_bits(mfd->regmap, TPS65910_SLEEP_KEEP_LDO_ON + regoffs, bit_pos); if (!ret) { if (ext_sleep_config & TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP) - ret = tps65910_reg_set_bits(mfd, + ret = regmap_set_bits(mfd->regmap, TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos); else - ret = tps65910_reg_clear_bits(mfd, + ret = regmap_clear_bits(mfd->regmap, TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos); } if (ret < 0) @@ -1097,7 +1098,7 @@ static int tps65910_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pmic); /* Give control of all register to control port */ - err = tps65910_reg_set_bits(pmic->mfd, TPS65910_DEVCTRL, + err = regmap_set_bits(pmic->mfd->regmap, TPS65910_DEVCTRL, DEVCTRL_SR_CTL_I2C_SEL_MASK); if (err < 0) return err; @@ -1113,7 +1114,7 @@ static int tps65910_probe(struct platform_device *pdev) * voltage level can go higher than expected or crash * Workaround: use no synchronization of DCDC clocks */ - tps65910_reg_clear_bits(pmic->mfd, TPS65910_DCDCCTRL, + regmap_clear_bits(pmic->mfd->regmap, TPS65910_DCDCCTRL, DCDCCTRL_DCDCCKSYNC_MASK); break; case TPS65911: diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c index 63d6bbd4969b..b52d4f2874b7 100644 --- a/drivers/regulator/tps65912-regulator.c +++ b/drivers/regulator/tps65912-regulator.c @@ -57,7 +57,7 @@ static const struct linear_range tps65912_ldo_ranges[] = { }; /* Operations permitted on DCDCx */ -static struct regulator_ops tps65912_ops_dcdc = { +static const struct regulator_ops tps65912_ops_dcdc = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -67,7 +67,7 @@ static struct regulator_ops tps65912_ops_dcdc = { }; /* Operations permitted on LDOx */ -static struct regulator_ops tps65912_ops_ldo = { +static const struct regulator_ops tps65912_ops_ldo = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index ad2203d11a88..e43ed4d93f71 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -178,11 +178,9 @@ static irqreturn_t wm831x_dcdc_uv_irq(int irq, void *data) { struct wm831x_dcdc *dcdc = data; - regulator_lock(dcdc->regulator); regulator_notifier_call_chain(dcdc->regulator, REGULATOR_EVENT_UNDER_VOLTAGE, NULL); - regulator_unlock(dcdc->regulator); return IRQ_HANDLED; } @@ -191,11 +189,9 @@ static irqreturn_t wm831x_dcdc_oc_irq(int irq, void *data) { struct wm831x_dcdc *dcdc = data; - regulator_lock(dcdc->regulator); regulator_notifier_call_chain(dcdc->regulator, REGULATOR_EVENT_OVER_CURRENT, NULL); - regulator_unlock(dcdc->regulator); return IRQ_HANDLED; } diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c index ff3d2bf50410..eade3ae3e333 100644 --- a/drivers/regulator/wm831x-isink.c +++ b/drivers/regulator/wm831x-isink.c @@ -99,11 +99,9 @@ static irqreturn_t wm831x_isink_irq(int irq, void *data) { struct wm831x_isink *isink = data; - regulator_lock(isink->regulator); regulator_notifier_call_chain(isink->regulator, REGULATOR_EVENT_OVER_CURRENT, NULL); - regulator_unlock(isink->regulator); return IRQ_HANDLED; } diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 7b6cf4810cb7..e091b189ecc0 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -46,11 +46,9 @@ static irqreturn_t wm831x_ldo_uv_irq(int irq, void *data) { struct wm831x_ldo *ldo = data; - regulator_lock(ldo->regulator); regulator_notifier_call_chain(ldo->regulator, REGULATOR_EVENT_UNDER_VOLTAGE, NULL); - regulator_unlock(ldo->regulator); return IRQ_HANDLED; } diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 2e7bfdf7c87b..6579bfdb0c26 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -1089,7 +1089,6 @@ static irqreturn_t pmic_uv_handler(int irq, void *data) { struct regulator_dev *rdev = (struct regulator_dev *)data; - regulator_lock(rdev); if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2) regulator_notifier_call_chain(rdev, REGULATOR_EVENT_REGULATION_OUT, @@ -1098,7 +1097,6 @@ static irqreturn_t pmic_uv_handler(int irq, void *data) regulator_notifier_call_chain(rdev, REGULATOR_EVENT_UNDER_VOLTAGE, NULL); - regulator_unlock(rdev); return IRQ_HANDLED; } diff --git a/include/dt-bindings/regulator/mediatek,mt6360-regulator.h b/include/dt-bindings/regulator/mediatek,mt6360-regulator.h new file mode 100644 index 000000000000..21c75de700c0 --- /dev/null +++ b/include/dt-bindings/regulator/mediatek,mt6360-regulator.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __DT_BINDINGS_MEDIATEK_MT6360_REGULATOR_H__ +#define __DT_BINDINGS_MEDIATEK_MT6360_REGULATOR_H__ + +/* + * BUCK/LDO mode constants which may be used in devicetree properties + * (eg. regulator-allowed-modes). + * See the manufacturer's datasheet for more information on these modes. + */ + +#define MT6360_OPMODE_LP 2 +#define MT6360_OPMODE_ULP 3 +#define MT6360_OPMODE_NORMAL 0 + +#endif diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 8539f34ae42b..11cade73726c 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -533,9 +533,6 @@ int regulator_set_current_limit_regmap(struct regulator_dev *rdev, int regulator_get_current_limit_regmap(struct regulator_dev *rdev); void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data); -void regulator_lock(struct regulator_dev *rdev); -void regulator_unlock(struct regulator_dev *rdev); - /* * Helper functions intended to be used by regulator drivers prior registering * their regulators. diff --git a/include/linux/soc/qcom/smd-rpm.h b/include/linux/soc/qcom/smd-rpm.h index da304ce8c8f7..f2645ec52520 100644 --- a/include/linux/soc/qcom/smd-rpm.h +++ b/include/linux/soc/qcom/smd-rpm.h @@ -19,6 +19,10 @@ 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_RWCX 0x78637772 +#define QCOM_SMD_RPM_RWMX 0x786d7772 +#define QCOM_SMD_RPM_RWLC 0x636c7772 +#define QCOM_SMD_RPM_RWLM 0x6d6c7772 #define QCOM_SMD_RPM_MEM_CLK 0x326b6c63 #define QCOM_SMD_RPM_MISC_CLK 0x306b6c63 #define QCOM_SMD_RPM_NCPA 0x6170636E |