diff options
35 files changed, 1165 insertions, 664 deletions
diff --git a/Documentation/devicetree/bindings/regulator/mp886x.txt b/Documentation/devicetree/bindings/regulator/mp886x.txt index 551867829459..b05307bbb0d9 100644 --- a/Documentation/devicetree/bindings/regulator/mp886x.txt +++ b/Documentation/devicetree/bindings/regulator/mp886x.txt @@ -9,6 +9,10 @@ Required properties: - mps,fb-voltage-divider: An array of two integers containing the resistor values R1 and R2 of the feedback voltage divider in kilo ohms. +Optional properties: +- mps,switch-frequency-hz: The valid switch frequency in Hertz. Available values + are: 500000, 750000, 1000000, 1250000, 1500000 + Any property defined as part of the core regulator binding, defined in ./regulator.txt, can also be used. 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/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..fa075c6e67f9 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/richtek,rt4801-regulator.yaml @@ -0,0 +1,77 @@ +# 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 + +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/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..f719ed5a8c33 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -864,6 +864,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 +904,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 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index d8d3ecf526a8..9f478e5687b6 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -107,10 +107,12 @@ 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_S2MPA01) += s2mpa01.o obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 75ff7c563c5d..07edbd8ebb98 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -565,6 +565,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) { @@ -982,27 +1006,10 @@ static int drms_uA_update(struct regulator_dev *rdev) 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) @@ -1037,6 +1044,18 @@ static int suspend_set_state(struct regulator_dev *rdev, return ret; } +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); +} + static void print_constraints(struct regulator_dev *rdev) { struct regulation_constraints *constraints = rdev->constraints; @@ -1319,7 +1338,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, /* 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"); return ret; @@ -1461,7 +1480,7 @@ static int set_consumer_device_supply(struct regulator_dev *rdev, const char *consumer_dev_name, const char *supply) { - struct regulator_map *node; + struct regulator_map *node, *new_node; int has_dev; if (supply == NULL) @@ -1472,6 +1491,22 @@ static int set_consumer_device_supply(struct regulator_dev *rdev, else has_dev = 0; + new_node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); + if (new_node == NULL) + return -ENOMEM; + + new_node->regulator = rdev; + new_node->supply = supply; + + if (has_dev) { + new_node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); + if (new_node->dev_name == NULL) { + kfree(new_node); + return -ENOMEM; + } + } + + mutex_lock(®ulator_list_mutex); list_for_each_entry(node, ®ulator_map_list, list) { if (node->dev_name && consumer_dev_name) { if (strcmp(node->dev_name, consumer_dev_name) != 0) @@ -1489,26 +1524,19 @@ static int set_consumer_device_supply(struct regulator_dev *rdev, node->regulator->desc->name, supply, dev_name(&rdev->dev), rdev_get_name(rdev)); - return -EBUSY; + goto fail; } - node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); - if (node == NULL) - return -ENOMEM; - - node->regulator = rdev; - node->supply = supply; - - if (has_dev) { - node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); - if (node->dev_name == NULL) { - kfree(node); - return -ENOMEM; - } - } + list_add(&new_node->list, ®ulator_map_list); + mutex_unlock(®ulator_list_mutex); - list_add(&node->list, ®ulator_map_list); return 0; + +fail: + mutex_unlock(®ulator_list_mutex); + kfree(new_node->dev_name); + kfree(new_node); + return -EBUSY; } static void unset_regulator_supplies(struct regulator_dev *rdev) @@ -1580,44 +1608,53 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, const char *supply_name) { struct regulator *regulator; - char buf[REG_STR_SIZE]; - int err, size; + int err; + + if (dev) { + char buf[REG_STR_SIZE]; + int size; + + size = snprintf(buf, REG_STR_SIZE, "%s-%s", + dev->kobj.name, supply_name); + if (size >= REG_STR_SIZE) + return NULL; + + supply_name = kstrdup(buf, GFP_KERNEL); + if (supply_name == NULL) + return NULL; + } else { + supply_name = kstrdup_const(supply_name, GFP_KERNEL); + if (supply_name == NULL) + return NULL; + } regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); - if (regulator == NULL) + if (regulator == NULL) { + kfree(supply_name); return NULL; + } - regulator_lock(rdev); regulator->rdev = rdev; + regulator->supply_name = supply_name; + + regulator_lock(rdev); list_add(®ulator->list, &rdev->consumer_list); + regulator_unlock(rdev); if (dev) { regulator->dev = dev; /* Add a link to the device sysfs entry */ - size = snprintf(buf, REG_STR_SIZE, "%s-%s", - dev->kobj.name, supply_name); - if (size >= REG_STR_SIZE) - goto overflow_err; - - regulator->supply_name = kstrdup(buf, GFP_KERNEL); - if (regulator->supply_name == NULL) - goto overflow_err; - err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj, - buf); + supply_name); if (err) { rdev_dbg(rdev, "could not add device link %s err %d\n", dev->kobj.name, err); /* non-fatal */ } - } else { - regulator->supply_name = kstrdup_const(supply_name, GFP_KERNEL); - if (regulator->supply_name == NULL) - goto overflow_err; } - regulator->debugfs = debugfs_create_dir(regulator->supply_name, + regulator->debugfs = debugfs_create_dir(supply_name, rdev->debugfs); if (!regulator->debugfs) { rdev_dbg(rdev, "Failed to create debugfs directory\n"); @@ -1642,13 +1679,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, _regulator_is_enabled(rdev)) regulator->always_on = true; - regulator_unlock(rdev); return regulator; -overflow_err: - list_del(®ulator->list); - kfree(regulator); - regulator_unlock(rdev); - return NULL; } static int _regulator_get_enable_time(struct regulator_dev *rdev) @@ -2230,10 +2261,13 @@ EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias); static int regulator_ena_gpio_request(struct regulator_dev *rdev, const struct regulator_config *config) { - struct regulator_enable_gpio *pin; + struct regulator_enable_gpio *pin, *new_pin; struct gpio_desc *gpiod; gpiod = config->ena_gpiod; + new_pin = kzalloc(sizeof(*new_pin), GFP_KERNEL); + + mutex_lock(®ulator_list_mutex); list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { if (pin->gpiod == gpiod) { @@ -2242,9 +2276,13 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev, } } - pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL); - if (pin == NULL) + if (new_pin == NULL) { + mutex_unlock(®ulator_list_mutex); return -ENOMEM; + } + + pin = new_pin; + new_pin = NULL; pin->gpiod = gpiod; list_add(&pin->list, ®ulator_ena_gpio_list); @@ -2252,6 +2290,10 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev, update_ena_gpio_to_rdev: pin->request_count++; rdev->ena_pin = pin; + + mutex_unlock(®ulator_list_mutex); + kfree(new_pin); + return 0; } @@ -2264,19 +2306,19 @@ static void regulator_ena_gpio_free(struct regulator_dev *rdev) /* Free the GPIO only in case of no use */ list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { - if (pin->gpiod == rdev->ena_pin->gpiod) { - if (pin->request_count <= 1) { - pin->request_count = 0; - gpiod_put(pin->gpiod); - list_del(&pin->list); - kfree(pin); - rdev->ena_pin = NULL; - return; - } else { - pin->request_count--; - } - } + if (pin != rdev->ena_pin) + continue; + + if (--pin->request_count) + break; + + gpiod_put(pin->gpiod); + list_del(&pin->list); + kfree(pin); + break; } + + rdev->ena_pin = NULL; } /** @@ -5011,20 +5053,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. @@ -5040,7 +5082,10 @@ static int regulator_init_coupling(struct regulator_dev *rdev) if (!of_check_coupling_data(rdev)) return -EPERM; + mutex_lock(®ulator_list_mutex); rdev->coupling_desc.coupler = regulator_find_coupler(rdev); + mutex_unlock(®ulator_list_mutex); + if (IS_ERR(rdev->coupling_desc.coupler)) { err = PTR_ERR(rdev->coupling_desc.coupler); rdev_err(rdev, "failed to get coupler: %d\n", err); @@ -5141,6 +5186,7 @@ regulator_register(const struct regulator_desc *regulator_desc, ret = -ENOMEM; goto rinse; } + device_initialize(&rdev->dev); /* * Duplicate the config so the driver could override it after @@ -5148,9 +5194,8 @@ regulator_register(const struct regulator_desc *regulator_desc, */ config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL); if (config == NULL) { - kfree(rdev); ret = -ENOMEM; - goto rinse; + goto clean; } init_data = regulator_of_get_init_data(dev, regulator_desc, config, @@ -5162,10 +5207,8 @@ regulator_register(const struct regulator_desc *regulator_desc, * from a gpio extender or something else. */ if (PTR_ERR(init_data) == -EPROBE_DEFER) { - kfree(config); - kfree(rdev); ret = -EPROBE_DEFER; - goto rinse; + goto clean; } /* @@ -5206,9 +5249,7 @@ regulator_register(const struct regulator_desc *regulator_desc, } if (config->ena_gpiod) { - mutex_lock(®ulator_list_mutex); ret = regulator_ena_gpio_request(rdev, config); - mutex_unlock(®ulator_list_mutex); if (ret != 0) { rdev_err(rdev, "Failed to request enable GPIO: %d\n", ret); @@ -5220,7 +5261,6 @@ regulator_register(const struct regulator_desc *regulator_desc, } /* register with sysfs */ - device_initialize(&rdev->dev); rdev->dev.class = ®ulator_class; rdev->dev.parent = dev; dev_set_name(&rdev->dev, "regulator.%lu", @@ -5248,27 +5288,22 @@ regulator_register(const struct regulator_desc *regulator_desc, if (ret < 0) goto wash; - mutex_lock(®ulator_list_mutex); ret = regulator_init_coupling(rdev); - mutex_unlock(®ulator_list_mutex); if (ret < 0) goto wash; /* add consumers devices */ if (init_data) { - mutex_lock(®ulator_list_mutex); for (i = 0; i < init_data->num_consumer_supplies; i++) { ret = set_consumer_device_supply(rdev, init_data->consumer_supplies[i].dev_name, init_data->consumer_supplies[i].supply); if (ret < 0) { - mutex_unlock(®ulator_list_mutex); dev_err(dev, "Failed to set supply %s\n", init_data->consumer_supplies[i].supply); goto unset_supplies; } } - mutex_unlock(®ulator_list_mutex); } if (!rdev->desc->ops->get_voltage && @@ -5303,13 +5338,11 @@ wash: mutex_lock(®ulator_list_mutex); regulator_ena_gpio_free(rdev); mutex_unlock(®ulator_list_mutex); - put_device(&rdev->dev); - rdev = NULL; clean: if (dangling_of_gpiod) gpiod_put(config->ena_gpiod); - kfree(rdev); kfree(config); + put_device(&rdev->dev); rinse: if (dangling_cfg_gpiod) gpiod_put(cfg->ena_gpiod); @@ -5362,9 +5395,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; @@ -5381,11 +5419,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); diff --git a/drivers/regulator/cros-ec-regulator.c b/drivers/regulator/cros-ec-regulator.c index 3117bbd2826b..eb3fc1db4edc 100644 --- a/drivers/regulator/cros-ec-regulator.c +++ b/drivers/regulator/cros-ec-regulator.c @@ -170,6 +170,9 @@ static int cros_ec_regulator_init_info(struct device *dev, data->voltages_mV = devm_kmemdup(dev, resp.voltages_mv, sizeof(u16) * data->num_voltages, GFP_KERNEL); + if (!data->voltages_mV) + return -ENOMEM; + data->desc.n_voltages = data->num_voltages; /* Make sure the returned name is always a valid string */ diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c index 0cdeb6186529..2aea442b62fe 100644 --- a/drivers/regulator/da9210-regulator.c +++ b/drivers/regulator/da9210-regulator.c @@ -125,7 +125,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..cffcefd0538d 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), }; 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/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 d54830e48b8d..5a03fd86ad0a 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); @@ -182,7 +174,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) drvdata->enable_clock = devm_clk_get(dev, NULL); if (IS_ERR(drvdata->enable_clock)) { - dev_err(dev, "Cant get enable-clock from devicetree\n"); + dev_err(dev, "Can't get enable-clock from devicetree\n"); return -ENOENT; } } else { @@ -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/lp8755.c b/drivers/regulator/lp8755.c index 4291df077c39..8cc9963023f2 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; @@ -377,11 +337,11 @@ static irqreturn_t lp8755_irq_handler(int irq, void *data) } /* 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; @@ -423,7 +383,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 +462,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 +473,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..fa563aacf742 100644 --- a/drivers/regulator/ltc3589.c +++ b/drivers/regulator/ltc3589.c @@ -457,7 +457,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..557727b54f0e 100644 --- a/drivers/regulator/ltc3676.c +++ b/drivers/regulator/ltc3676.c @@ -368,7 +368,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/pwm-regulator.c b/drivers/regulator/pwm-regulator.c index 3234b118b53e..d250e60f1625 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-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_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index 5ee7c5305d95..05080483fe1b 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -1633,45 +1633,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. */ 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/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/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/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}, |
