regulator: Updates for v5.10

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.
 
  - 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.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAl+EU5IACgkQJNaLcl1U
 h9A2Qgf/WPEIdFBIgovcKD40T3Q74sA5FNYtpw1H9k0H0SKWwU1S2hnHq/FFZwfQ
 JGSBX8pLACIz74JT6JPV4Orf0snfSWNqyNwKoSJCAY83mRBCE0XmBApGPd6AT6me
 alb2E35FK0v+k7psRTl9Os36sULUt8Eq2/t16O0+51Dj/8M8mjeYpblaIolRviRN
 FMGWeiUJBVUH84cnoCxPogL3ORTxhkFd9vsSsZrmDR0ivlZ2Ng/1ZWmNvclfODwp
 wWkbjnkzGXfYFdr7QBAmjo+RRfXVY3/7s61Uvs6eCMxHCB5d2aJVYsol9z+R6MZY
 OY7vSOdjFmuqh/OlRvUHGqY2lbTKrw==
 =d5Wr
 -----END PGP SIGNATURE-----

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
  ...
This commit is contained in:
Linus Torvalds 2020-10-13 09:56:25 -07:00
commit 1724e02e02
77 changed files with 3493 additions and 1028 deletions

View file

@ -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>;
};

View file

@ -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>;
};
};
...

View file

@ -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>;
};
};
...

View file

@ -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;
};
};
};

View file

@ -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;
};
};
};
};

View file

@ -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

View file

@ -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:

View file

@ -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>;
};
};
...

View file

@ -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;
};
};
};

View file

@ -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>;
};
};
};
...

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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>;
};
};
...

View file

@ -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;
};

View file

@ -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" },
{ }

View file

@ -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

View file

@ -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

View file

@ -15,6 +15,39 @@
#include <linux/regulator/of_regulator.h>
#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
@ -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,
};
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_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,
};
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_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,
};
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 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,
};
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 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,
};
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 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,
};
/*
* 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);
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(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);
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(bd71837_ldo_regulator_ops, regulator_list_voltage_linear_range,
NULL, bd71837_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(bd71837_ldo_regulator_nolinear_ops, regulator_list_voltage_table,
NULL, bd71837_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(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);
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,
};
static const struct regulator_ops bd718xx_dvs_buck_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
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,
@ -329,6 +351,14 @@ static const struct regulator_ops bd718xx_dvs_buck_regulator_ops = {
.set_ramp_delay = bd718xx_buck1234_set_ramp_delay,
};
/*
* 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
@ -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 = &reg_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) {

View file

@ -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 = &reg_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");

View file

@ -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(&regulator_nesting_mutex);
@ -216,7 +215,6 @@ void regulator_unlock(struct regulator_dev *rdev)
mutex_unlock(&regulator_nesting_mutex);
}
EXPORT_SYMBOL_GPL(regulator_unlock);
static bool regulator_supply_is_couple(struct regulator_dev *rdev)
{
@ -409,11 +407,11 @@ static struct device_node *of_get_child_regulator(struct device_node *parent,
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

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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 @@ static irqreturn_t da9210_irq_handler(int irq, void *data)
* 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", },
{ }
};

View file

@ -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);

View file

@ -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;
}

View file

@ -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",

View file

@ -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,

View file

@ -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",

View file

@ -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),
};

View file

@ -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, &regval);
ret = regmap_read(rdev->regmap, 0x12 + id, &regval);
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, &regval);
ret = regmap_read(rdev->regmap, 0x06, &regval);
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, &regval);
ret = regmap_read(rdev->regmap, 0x08 + id, &regval);
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, &regval);
ret = regmap_read(pchip->regmap, 0x3D, &regval);
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, &regval);
ret = regmap_read(pchip->regmap, 0x0F, &regval);
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;
}

View file

@ -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,

View file

@ -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" },
{ },
};

View file

@ -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", },
{},
};

View file

@ -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 */ }
};

View file

@ -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
},
{ }
};

View file

@ -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");

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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" },
{ },
};

View file

@ -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,

View file

@ -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,

View file

@ -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 },

View file

@ -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 },
{ }
};

View file

@ -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);

View file

@ -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");

View file

@ -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");

View file

@ -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");

View file

@ -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>");

View file

@ -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;

View file

@ -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

View file

@ -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", },
{},
};

View file

@ -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", },
{},
};

View file

@ -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;
}

View file

@ -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,

View file

@ -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" },
{ },
};

View file

@ -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", },

View file

@ -619,7 +619,7 @@ static int ti_abb_init_table(struct device *dev, struct ti_abb *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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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},

View file

@ -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,

View file

@ -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 @@ static int tps65090_fet_enable(struct regulator_dev *rdev)
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) \

View file

@ -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[] = {

View file

@ -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:

View file

@ -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,

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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.

View file

@ -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