Merge branch 'regulator-5.3' into regulator-next

This commit is contained in:
Mark Brown 2019-07-04 17:34:32 +01:00
commit 65244e5b1f
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
46 changed files with 2552 additions and 675 deletions

View File

@ -5,7 +5,8 @@ of analogue I/O.
This document lists regulator specific bindings, see the primary binding This document lists regulator specific bindings, see the primary binding
document: document:
../mfd/arizona.txt For Wolfson Microelectronic Arizona codecs: ../mfd/arizona.txt
For Cirrus Logic Madera codecs: ../mfd/madera.txt
Optional properties: Optional properties:
- wlf,ldoena : GPIO specifier for the GPIO controlling LDOENA - wlf,ldoena : GPIO specifier for the GPIO controlling LDOENA

View File

@ -12,10 +12,13 @@ maintainers:
description: description:
Any property defined as part of the core regulator binding, defined in Any property defined as part of the core regulator binding, defined in
regulator.txt, can also be used. However a fixed voltage regulator is regulator.yaml, can also be used. However a fixed voltage regulator is
expected to have the regulator-min-microvolt and regulator-max-microvolt expected to have the regulator-min-microvolt and regulator-max-microvolt
to be the same. to be the same.
allOf:
- $ref: "regulator.yaml#"
properties: properties:
compatible: compatible:
const: regulator-fixed const: regulator-fixed

View File

@ -1,57 +0,0 @@
GPIO controlled regulators
Required properties:
- compatible : Must be "regulator-gpio".
- regulator-name : Defined in regulator.txt as optional, but required
here.
- gpios : Array of one or more GPIO pins used to select the
regulator voltage/current listed in "states".
- states : Selection of available voltages/currents provided by
this regulator and matching GPIO configurations to
achieve them. If there are no states in the "states"
array, use a fixed regulator instead.
Optional properties:
- enable-gpios : GPIO used to enable/disable the regulator.
Warning, the GPIO phandle flags are ignored and the
GPIO polarity is controlled solely by the presence
of "enable-active-high" DT property. This is due to
compatibility with old DTs.
- enable-active-high : Polarity of "enable-gpio" GPIO is active HIGH.
Default is active LOW.
- gpios-states : On operating systems, that don't support reading back
gpio values in output mode (most notably linux), this
array provides the state of GPIO pins set when
requesting them from the gpio controller. Systems,
that are capable of preserving state when requesting
the lines, are free to ignore this property.
0: LOW, 1: HIGH. Default is LOW if nothing else
is specified.
- startup-delay-us : Startup time in microseconds.
- regulator-type : Specifies what is being regulated, must be either
"voltage" or "current", defaults to voltage.
Any property defined as part of the core regulator binding defined in
regulator.txt can also be used.
Example:
mmciv: gpio-regulator {
compatible = "regulator-gpio";
regulator-name = "mmci-gpio-supply";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <2600000>;
regulator-boot-on;
enable-gpios = <&gpio0 23 0x4>;
gpios = <&gpio0 24 0x4
&gpio0 25 0x4>;
states = <1800000 0x3
2200000 0x2
2600000 0x1
2900000 0x0>;
startup-delay-us = <100000>;
enable-active-high;
};

View File

@ -0,0 +1,118 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/gpio-regulator.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: GPIO controlled regulators
maintainers:
- Liam Girdwood <lgirdwood@gmail.com>
- Mark Brown <broonie@kernel.org>
description:
Any property defined as part of the core regulator binding, defined in
regulator.txt, can also be used.
allOf:
- $ref: "regulator.yaml#"
properties:
compatible:
const: regulator-gpio
regulator-name: true
enable-gpios:
description: GPIO to use to enable/disable the regulator.
Warning, the GPIO phandle flags are ignored and the GPIO polarity is
controlled solely by the presence of "enable-active-high" DT property.
This is due to compatibility with old DTs.
maxItems: 1
gpios:
description: Array of one or more GPIO pins used to select the regulator
voltage/current listed in "states".
minItems: 1
maxItems: 8 # Should be enough...
gpios-states:
description: |
On operating systems, that don't support reading back gpio values in
output mode (most notably linux), this array provides the state of GPIO
pins set when requesting them from the gpio controller. Systems, that are
capable of preserving state when requesting the lines, are free to ignore
this property.
0: LOW
1: HIGH
Default is LOW if nothing else is specified.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32-array
- maxItems: 8
items:
enum: [ 0, 1 ]
default: 0
states:
description: Selection of available voltages/currents provided by this
regulator and matching GPIO configurations to achieve them. If there are
no states in the "states" array, use a fixed regulator instead.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32-matrix
- maxItems: 8
items:
items:
- description: Voltage in microvolts
- description: GPIO group state value
startup-delay-us:
description: startup time in microseconds
enable-active-high:
description: Polarity of "enable-gpio" GPIO is active HIGH. Default is
active LOW.
type: boolean
gpio-open-drain:
description:
GPIO is open drain type. If this property is missing then default
assumption is false.
type: boolean
regulator-type:
description: Specifies what is being regulated.
allOf:
- $ref: /schemas/types.yaml#/definitions/string
- enum:
- voltage
- current
default: voltage
required:
- compatible
- regulator-name
- gpios
- states
examples:
- |
gpio-regulator {
compatible = "regulator-gpio";
regulator-name = "mmci-gpio-supply";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <2600000>;
regulator-boot-on;
enable-gpios = <&gpio0 23 0x4>;
gpios = <&gpio0 24 0x4
&gpio0 25 0x4>;
states = <1800000 0x3>,
<2200000 0x2>,
<2600000 0x1>,
<2900000 0x0>;
startup-delay-us = <100000>;
enable-active-high;
};
...

View File

@ -1,47 +0,0 @@
Maxim MAX8660 voltage regulator
Required properties:
- compatible: must be one of "maxim,max8660", "maxim,max8661"
- reg: I2C slave address, usually 0x34
- any required generic properties defined in regulator.txt
Example:
i2c_master {
max8660@34 {
compatible = "maxim,max8660";
reg = <0x34>;
regulators {
regulator@0 {
regulator-compatible= "V3(DCDC)";
regulator-min-microvolt = <725000>;
regulator-max-microvolt = <1800000>;
};
regulator@1 {
regulator-compatible= "V4(DCDC)";
regulator-min-microvolt = <725000>;
regulator-max-microvolt = <1800000>;
};
regulator@2 {
regulator-compatible= "V5(LDO)";
regulator-min-microvolt = <1700000>;
regulator-max-microvolt = <2000000>;
};
regulator@3 {
regulator-compatible= "V6(LDO)";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
};
regulator@4 {
regulator-compatible= "V7(LDO)";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
};
};
};
};

View File

@ -0,0 +1,77 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/max8660.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Maxim MAX8660 voltage regulator
maintainers:
- Daniel Mack <zonque@gmail.com>
properties:
$nodename:
pattern: "pmic@[0-9a-f]{1,2}"
compatible:
enum:
- maxim,max8660
- maxim,max8661
reg:
maxItems: 1
regulators:
type: object
patternProperties:
"regulator-.+":
$ref: "regulator.yaml#"
additionalProperties: false
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@34 {
compatible = "maxim,max8660";
reg = <0x34>;
regulators {
regulator-V3 {
regulator-compatible= "V3(DCDC)";
regulator-min-microvolt = <725000>;
regulator-max-microvolt = <1800000>;
};
regulator-V4 {
regulator-compatible= "V4(DCDC)";
regulator-min-microvolt = <725000>;
regulator-max-microvolt = <1800000>;
};
regulator-V5 {
regulator-compatible= "V5(LDO)";
regulator-min-microvolt = <1700000>;
regulator-max-microvolt = <2000000>;
};
regulator-V6 {
regulator-compatible= "V6(LDO)";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
};
regulator-V7 {
regulator-compatible= "V7(LDO)";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
};
};
};
};
...

View File

@ -4,11 +4,13 @@ Qualcomm SPMI Regulators
Usage: required Usage: required
Value type: <string> Value type: <string>
Definition: must be one of: Definition: must be one of:
"qcom,pm8005-regulators"
"qcom,pm8841-regulators" "qcom,pm8841-regulators"
"qcom,pm8916-regulators" "qcom,pm8916-regulators"
"qcom,pm8941-regulators" "qcom,pm8941-regulators"
"qcom,pm8994-regulators" "qcom,pm8994-regulators"
"qcom,pmi8994-regulators" "qcom,pmi8994-regulators"
"qcom,pms405-regulators"
- interrupts: - interrupts:
Usage: optional Usage: optional
@ -110,6 +112,23 @@ Qualcomm SPMI Regulators
Definition: Reference to regulator supplying the input pin, as Definition: Reference to regulator supplying the input pin, as
described in the data sheet. described in the data sheet.
- vdd_l1_l2-supply:
- vdd_l3_l8-supply:
- vdd_l4-supply:
- vdd_l5_l6-supply:
- vdd_l10_l11_l12_l13-supply:
- vdd_l7-supply:
- vdd_l9-supply:
- vdd_s1-supply:
- vdd_s2-supply:
- vdd_s3-supply:
- vdd_s4-supply:
- vdd_s5-supply
Usage: optional (pms405 only)
Value type: <phandle>
Definition: Reference to regulator supplying the input pin, as
described in the data sheet.
- qcom,saw-reg: - qcom,saw-reg:
Usage: optional Usage: optional
Value type: <phandle> Value type: <phandle>
@ -120,6 +139,9 @@ The regulator node houses sub-nodes for each regulator within the device. Each
sub-node is identified using the node's name, with valid values listed for each sub-node is identified using the node's name, with valid values listed for each
of the PMICs below. of the PMICs below.
pm8005:
s1, s2, s3, s4
pm8841: pm8841:
s1, s2, s3, s4, s5, s6, s7, s8 s1, s2, s3, s4, s5, s6, s7, s8

View File

@ -1,139 +1 @@
Voltage/Current Regulators This file has moved to regulator.yaml.
Optional properties:
- regulator-name: A string used as a descriptive name for regulator outputs
- regulator-min-microvolt: smallest voltage consumers may set
- regulator-max-microvolt: largest voltage consumers may set
- regulator-microvolt-offset: Offset applied to voltages to compensate for voltage drops
- regulator-min-microamp: smallest current consumers may set
- regulator-max-microamp: largest current consumers may set
- regulator-input-current-limit-microamp: maximum input current regulator allows
- regulator-always-on: boolean, regulator should never be disabled
- regulator-boot-on: bootloader/firmware enabled regulator
- regulator-allow-bypass: allow the regulator to go into bypass mode
- regulator-allow-set-load: allow the regulator performance level to be configured
- <name>-supply: phandle to the parent supply/regulator node
- regulator-ramp-delay: ramp delay for regulator(in uV/us)
For hardware which supports disabling ramp rate, it should be explicitly
initialised to zero (regulator-ramp-delay = <0>) for disabling ramp delay.
- regulator-enable-ramp-delay: The time taken, in microseconds, for the supply
rail to reach the target voltage, plus/minus whatever tolerance the board
design requires. This property describes the total system ramp time
required due to the combination of internal ramping of the regulator itself,
and board design issues such as trace capacitance and load on the supply.
- regulator-settling-time-us: Settling time, in microseconds, for voltage
change if regulator have the constant time for any level voltage change.
This is useful when regulator have exponential voltage change.
- regulator-settling-time-up-us: Settling time, in microseconds, for voltage
increase if the regulator needs a constant time to settle after voltage
increases of any level. This is useful for regulators with exponential
voltage changes.
- regulator-settling-time-down-us: Settling time, in microseconds, for voltage
decrease if the regulator needs a constant time to settle after voltage
decreases of any level. This is useful for regulators with exponential
voltage changes.
- regulator-soft-start: Enable soft start so that voltage ramps slowly
- regulator-state-standby sub-root node for Standby mode
: equivalent with standby Linux sleep state, which provides energy savings
with a relatively quick transition back time.
- regulator-state-mem sub-root node for Suspend-to-RAM mode
: suspend to memory, the device goes to sleep, but all data stored in memory,
only some external interrupt can wake the device.
- regulator-state-disk sub-root node for Suspend-to-DISK mode
: suspend to disk, this state operates similarly to Suspend-to-RAM,
but includes a final step of writing memory contents to disk.
- regulator-state-[mem/disk/standby] node has following common properties:
- regulator-on-in-suspend: regulator should be on in suspend state.
- regulator-off-in-suspend: regulator should be off in suspend state.
- regulator-suspend-min-microvolt: minimum voltage may be set in
suspend state.
- regulator-suspend-max-microvolt: maximum voltage may be set in
suspend state.
- regulator-suspend-microvolt: the default voltage which regulator
would be set in suspend. This property is now deprecated, instead
setting voltage for suspend mode via the API which regulator
driver provides is recommended.
- regulator-changeable-in-suspend: whether the default voltage and
the regulator on/off in suspend can be changed in runtime.
- regulator-mode: operating mode in the given suspend state.
The set of possible operating modes depends on the capabilities of
every hardware so the valid modes are documented on each regulator
device tree binding document.
- regulator-initial-mode: initial operating mode. The set of possible operating
modes depends on the capabilities of every hardware so each device binding
documentation explains which values the regulator supports.
- regulator-allowed-modes: list of operating modes that software is allowed to
configure for the regulator at run-time. Elements may be specified in any
order. The set of possible operating modes depends on the capabilities of
every hardware so each device binding document explains which values the
regulator supports.
- regulator-system-load: Load in uA present on regulator that is not captured by
any consumer request.
- regulator-pull-down: Enable pull down resistor when the regulator is disabled.
- regulator-over-current-protection: Enable over current protection.
- regulator-active-discharge: tristate, enable/disable active discharge of
regulators. The values are:
0: Disable active discharge.
1: Enable active discharge.
Absence of this property will leave configuration to default.
- regulator-coupled-with: Regulators with which the regulator
is coupled. The linkage is 2-way - all coupled regulators should be linked
with each other. A regulator should not be coupled with its supplier.
- regulator-coupled-max-spread: Array of maximum spread between voltages of
coupled regulators in microvolts, each value in the array relates to the
corresponding couple specified by the regulator-coupled-with property.
- regulator-max-step-microvolt: Maximum difference between current and target
voltages that can be changed safely in a single step.
Deprecated properties:
- regulator-compatible: If a regulator chip contains multiple
regulators, and if the chip's binding contains a child node that
describes each regulator, then this property indicates which regulator
this child node is intended to configure. If this property is missing,
the node's name will be used instead.
Example:
xyzreg: regulator@0 {
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <2500000>;
regulator-always-on;
vin-supply = <&vin>;
regulator-state-mem {
regulator-on-in-suspend;
};
};
Regulator Consumers:
Consumer nodes can reference one or more of its supplies/
regulators using the below bindings.
- <name>-supply: phandle to the regulator node
These are the same bindings that a regulator in the above
example used to reference its own supply, in which case
its just seen as a special case of a regulator being a
consumer itself.
Example of a consumer device node (mmc) referencing two
regulators (twl_reg1 and twl_reg2),
twl_reg1: regulator@0 {
...
...
...
};
twl_reg2: regulator@1 {
...
...
...
};
mmc: mmc@0 {
...
...
vmmc-supply = <&twl_reg1>;
vmmcaux-supply = <&twl_reg2>;
};

View File

@ -0,0 +1,200 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/regulator.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Voltage/Current Regulators
maintainers:
- Liam Girdwood <lgirdwood@gmail.com>
- Mark Brown <broonie@kernel.org>
properties:
regulator-name:
description: A string used as a descriptive name for regulator outputs
$ref: "/schemas/types.yaml#/definitions/string"
regulator-min-microvolt:
description: smallest voltage consumers may set
regulator-max-microvolt:
description: largest voltage consumers may set
regulator-microvolt-offset:
description: Offset applied to voltages to compensate for voltage drops
regulator-min-microamp:
description: smallest current consumers may set
regulator-max-microamp:
description: largest current consumers may set
regulator-input-current-limit-microamp:
description: maximum input current regulator allows
regulator-always-on:
description: boolean, regulator should never be disabled
type: boolean
regulator-boot-on:
description: bootloader/firmware enabled regulator
type: boolean
regulator-allow-bypass:
description: allow the regulator to go into bypass mode
type: boolean
regulator-allow-set-load:
description: allow the regulator performance level to be configured
type: boolean
regulator-ramp-delay:
description: ramp delay for regulator(in uV/us) For hardware which supports
disabling ramp rate, it should be explicitly initialised to zero (regulator-ramp-delay
= <0>) for disabling ramp delay.
$ref: "/schemas/types.yaml#/definitions/uint32"
regulator-enable-ramp-delay:
description: The time taken, in microseconds, for the supply rail to
reach the target voltage, plus/minus whatever tolerance the board
design requires. This property describes the total system ramp time
required due to the combination of internal ramping of the regulator
itself, and board design issues such as trace capacitance and load
on the supply.
$ref: "/schemas/types.yaml#/definitions/uint32"
regulator-settling-time-us:
description: Settling time, in microseconds, for voltage change if regulator
have the constant time for any level voltage change. This is useful
when regulator have exponential voltage change.
regulator-settling-time-up-us:
description: Settling time, in microseconds, for voltage increase if
the regulator needs a constant time to settle after voltage increases
of any level. This is useful for regulators with exponential voltage
changes.
regulator-settling-time-down-us:
description: Settling time, in microseconds, for voltage decrease if
the regulator needs a constant time to settle after voltage decreases
of any level. This is useful for regulators with exponential voltage
changes.
regulator-soft-start:
description: Enable soft start so that voltage ramps slowly
type: boolean
regulator-initial-mode:
description: initial operating mode. The set of possible operating modes
depends on the capabilities of every hardware so each device binding
documentation explains which values the regulator supports.
$ref: "/schemas/types.yaml#/definitions/uint32"
regulator-allowed-modes:
description: list of operating modes that software is allowed to configure
for the regulator at run-time. Elements may be specified in any order.
The set of possible operating modes depends on the capabilities of
every hardware so each device binding document explains which values
the regulator supports.
$ref: "/schemas/types.yaml#/definitions/uint32-array"
regulator-system-load:
description: Load in uA present on regulator that is not captured by
any consumer request.
$ref: "/schemas/types.yaml#/definitions/uint32"
regulator-pull-down:
description: Enable pull down resistor when the regulator is disabled.
type: boolean
regulator-over-current-protection:
description: Enable over current protection.
type: boolean
regulator-active-discharge:
description: |
tristate, enable/disable active discharge of regulators. The values are:
0: Disable active discharge.
1: Enable active discharge.
Absence of this property will leave configuration to default.
allOf:
- $ref: "/schemas/types.yaml#/definitions/uint32"
- enum: [ 0, 1 ]
regulator-coupled-with:
description: Regulators with which the regulator is coupled. The linkage
is 2-way - all coupled regulators should be linked with each other.
A regulator should not be coupled with its supplier.
$ref: "/schemas/types.yaml#/definitions/phandle-array"
regulator-coupled-max-spread:
description: Array of maximum spread between voltages of coupled regulators
in microvolts, each value in the array relates to the corresponding
couple specified by the regulator-coupled-with property.
$ref: "/schemas/types.yaml#/definitions/uint32"
regulator-max-step-microvolt:
description: Maximum difference between current and target voltages
that can be changed safely in a single step.
patternProperties:
".*-supply$":
description: Input supply phandle(s) for this node
regulator-state-(standby|mem|disk):
type: object
description:
sub-nodes for regulator state in Standby, Suspend-to-RAM, and
Suspend-to-DISK modes. Equivalent with standby, mem, and disk Linux
sleep states.
properties:
regulator-on-in-suspend:
description: regulator should be on in suspend state.
type: boolean
regulator-off-in-suspend:
description: regulator should be off in suspend state.
type: boolean
regulator-suspend-min-microvolt:
description: minimum voltage may be set in suspend state.
regulator-suspend-max-microvolt:
description: maximum voltage may be set in suspend state.
regulator-suspend-microvolt:
description: the default voltage which regulator would be set in
suspend. This property is now deprecated, instead setting voltage
for suspend mode via the API which regulator driver provides is
recommended.
regulator-changeable-in-suspend:
description: whether the default voltage and the regulator on/off
in suspend can be changed in runtime.
type: boolean
regulator-mode:
description: operating mode in the given suspend state. The set
of possible operating modes depends on the capabilities of every
hardware so the valid modes are documented on each regulator device
tree binding document.
$ref: "/schemas/types.yaml#/definitions/uint32"
additionalProperties: false
examples:
- |
xyzreg: regulator@0 {
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <2500000>;
regulator-always-on;
vin-supply = <&vin>;
regulator-state-mem {
regulator-on-in-suspend;
};
};
...

View File

@ -0,0 +1,88 @@
* Dialog Semiconductor SLG51000 Voltage Regulator
Required properties:
- compatible : Should be "dlg,slg51000" for SLG51000
- reg : Specifies the I2C slave address.
- xxx-supply: Input voltage supply regulator for ldo3 to ldo7.
These entries are required if regulators are enabled for a device.
An absence of these properties can cause the regulator registration to fail.
If some of input supply is powered through battery or always-on supply then
also it is required to have these parameters with proper node handle of always
on power supply.
vin3-supply: Input supply for ldo3
vin4-supply: Input supply for ldo4
vin5-supply: Input supply for ldo5
vin6-supply: Input supply for ldo6
vin7-supply: Input supply for ldo7
Optional properties:
- interrupt-parent : Specifies the reference to the interrupt controller.
- interrupts : IRQ line information.
- dlg,cs-gpios : Specify a valid GPIO for chip select
Sub-nodes:
- regulators : This node defines the settings for the regulators.
The content of the sub-node is defined by the standard binding
for regulators; see regulator.txt.
The SLG51000 regulators are bound using their names listed below:
ldo1
ldo2
ldo3
ldo4
ldo5
ldo6
ldo7
Optional properties for regulators:
- enable-gpios : Specify a valid GPIO for platform control of the regulator.
Example:
pmic: slg51000@75 {
compatible = "dlg,slg51000";
reg = <0x75>;
regulators {
ldo1 {
regulator-name = "ldo1";
regulator-min-microvolt = <2400000>;
regulator-max-microvolt = <3300000>;
};
ldo2 {
regulator-name = "ldo2";
regulator-min-microvolt = <2400000>;
regulator-max-microvolt = <3300000>;
};
ldo3 {
regulator-name = "ldo3";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3750000>;
};
ldo4 {
regulator-name = "ldo4";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3750000>;
};
ldo5 {
regulator-name = "ldo5";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1200000>;
};
ldo6 {
regulator-name = "ldo6";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1200000>;
};
ldo7 {
regulator-name = "ldo7";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3750000>;
};
};
};

View File

@ -0,0 +1,18 @@
STM32 BOOSTER - Booster for ADC analog input switches
Some STM32 devices embed a 3.3V booster supplied by Vdda, that can be used
to supply ADC analog input switches.
Required properties:
- compatible: Should be one of:
"st,stm32h7-booster"
"st,stm32mp1-booster"
- st,syscfg: Phandle to system configuration controller.
- vdda-supply: Phandle to the vdda input analog voltage.
Example:
booster: regulator-booster {
compatible = "st,stm32mp1-booster";
st,syscfg = <&syscfg>;
vdda-supply = <&vdda>;
};

View File

@ -4707,6 +4707,7 @@ F: Documentation/devicetree/bindings/mfd/da90*.txt
F: Documentation/devicetree/bindings/input/da90??-onkey.txt F: Documentation/devicetree/bindings/input/da90??-onkey.txt
F: Documentation/devicetree/bindings/thermal/da90??-thermal.txt F: Documentation/devicetree/bindings/thermal/da90??-thermal.txt
F: Documentation/devicetree/bindings/regulator/da92*.txt F: Documentation/devicetree/bindings/regulator/da92*.txt
F: Documentation/devicetree/bindings/regulator/slg51000.txt
F: Documentation/devicetree/bindings/watchdog/da90??-wdt.txt F: Documentation/devicetree/bindings/watchdog/da90??-wdt.txt
F: Documentation/devicetree/bindings/sound/da[79]*.txt F: Documentation/devicetree/bindings/sound/da[79]*.txt
F: drivers/gpio/gpio-da90??.c F: drivers/gpio/gpio-da90??.c
@ -4722,6 +4723,7 @@ F: drivers/power/supply/da9052-battery.c
F: drivers/power/supply/da91??-*.c F: drivers/power/supply/da91??-*.c
F: drivers/regulator/da903x.c F: drivers/regulator/da903x.c
F: drivers/regulator/da9???-regulator.[ch] F: drivers/regulator/da9???-regulator.[ch]
F: drivers/regulator/slg51000-regulator.[ch]
F: drivers/thermal/da90??-thermal.c F: drivers/thermal/da90??-thermal.c
F: drivers/rtc/rtc-da90??.c F: drivers/rtc/rtc-da90??.c
F: drivers/video/backlight/da90??_bl.c F: drivers/video/backlight/da90??_bl.c

View File

@ -15,6 +15,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
@ -398,7 +399,6 @@ static struct pca953x_platform_data crag6410_pca_data = {
/* VDDARM is controlled by DVS1 connected to GPK(0) */ /* VDDARM is controlled by DVS1 connected to GPK(0) */
static struct wm831x_buckv_pdata vddarm_pdata = { static struct wm831x_buckv_pdata vddarm_pdata = {
.dvs_control_src = 1, .dvs_control_src = 1,
.dvs_gpio = S3C64XX_GPK(0),
}; };
static struct regulator_consumer_supply vddarm_consumers[] = { static struct regulator_consumer_supply vddarm_consumers[] = {
@ -596,6 +596,24 @@ static struct wm831x_pdata crag_pmic_pdata = {
.touch = &touch_pdata, .touch = &touch_pdata,
}; };
/*
* VDDARM is eventually ending up as a regulator hanging on the MFD cell device
* "wm831x-buckv.1" spawn from drivers/mfd/wm831x-core.c.
*
* From the note on the platform data we can see that this is clearly DVS1
* and assigned as dcdc1 resource to the MFD core which sets .id of the cell
* spawning the DVS1 platform device to 1, then the cell platform device
* name is calculated from 10*instance + id resulting in the device name
* "wm831x-buckv.11"
*/
static struct gpiod_lookup_table crag_pmic_gpiod_table = {
.dev_id = "wm831x-buckv.11",
.table = {
GPIO_LOOKUP("GPIOK", 0, "dvs", GPIO_ACTIVE_HIGH),
{ },
},
};
static struct i2c_board_info i2c_devs0[] = { static struct i2c_board_info i2c_devs0[] = {
{ I2C_BOARD_INFO("24c08", 0x50), }, { I2C_BOARD_INFO("24c08", 0x50), },
{ I2C_BOARD_INFO("tca6408", 0x20), { I2C_BOARD_INFO("tca6408", 0x20),
@ -836,6 +854,7 @@ static void __init crag6410_machine_init(void)
s3c_fb_set_platdata(&crag6410_lcd_pdata); s3c_fb_set_platdata(&crag6410_lcd_pdata);
dwc2_hsotg_set_platdata(&crag6410_hsotg_pdata); dwc2_hsotg_set_platdata(&crag6410_hsotg_pdata);
gpiod_add_lookup_table(&crag_pmic_gpiod_table);
i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0)); i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1)); i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));

View File

@ -27,6 +27,23 @@
status = "okay"; status = "okay";
}; };
&pm8005_lsid1 {
pm8005-regulators {
compatible = "qcom,pm8005-regulators";
vdd_s1-supply = <&vph_pwr>;
pm8005_s1: s1 { /* VDD_GFX supply */
regulator-min-microvolt = <524000>;
regulator-max-microvolt = <1100000>;
regulator-enable-ramp-delay = <500>;
/* hack until we rig up the gpu consumer */
regulator-always-on;
};
};
};
&qusb2phy { &qusb2phy {
status = "okay"; status = "okay";

View File

@ -4244,8 +4244,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_index);
* *
* Returns: * Returns:
* On successful request the GPIO pin is configured in accordance with * On successful request the GPIO pin is configured in accordance with
* provided @dflags. If the node does not have the requested GPIO * provided @dflags.
* property, NULL is returned.
* *
* In case of error an ERR_PTR() is returned. * In case of error an ERR_PTR() is returned.
*/ */
@ -4267,9 +4266,6 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
index, &flags); index, &flags);
if (!desc || IS_ERR(desc)) { if (!desc || IS_ERR(desc)) {
/* If it is not there, just return NULL */
if (PTR_ERR(desc) == -ENOENT)
return NULL;
return desc; return desc;
} }

View File

@ -136,19 +136,20 @@ config REGULATOR_AB8500
signal AB8500 PMIC signal AB8500 PMIC
config REGULATOR_ARIZONA_LDO1 config REGULATOR_ARIZONA_LDO1
tristate "Wolfson Arizona class devices LDO1" tristate "Cirrus Madera and Wolfson Arizona class devices LDO1"
depends on MFD_ARIZONA depends on MFD_ARIZONA || MFD_MADERA
depends on SND_SOC depends on SND_SOC
help help
Support for the LDO1 regulators found on Wolfson Arizona class Support for the LDO1 regulators found on Cirrus Logic Madera codecs
devices. and Wolfson Microelectronic Arizona codecs.
config REGULATOR_ARIZONA_MICSUPP config REGULATOR_ARIZONA_MICSUPP
tristate "Wolfson Arizona class devices MICSUPP" tristate "Cirrus Madera and Wolfson Arizona class devices MICSUPP"
depends on MFD_ARIZONA depends on MFD_ARIZONA || MFD_MADERA
depends on SND_SOC depends on SND_SOC
help help
Support for the MICSUPP regulators found on Wolfson Arizona class Support for the MICSUPP regulators found on Cirrus Logic Madera codecs
and Wolfson Microelectronic Arizona codecs
devices. devices.
config REGULATOR_AS3711 config REGULATOR_AS3711
@ -258,7 +259,7 @@ config REGULATOR_DA9062
config REGULATOR_DA9063 config REGULATOR_DA9063
tristate "Dialog Semiconductor DA9063 regulators" tristate "Dialog Semiconductor DA9063 regulators"
depends on MFD_DA9063 depends on MFD_DA9063 && OF
help help
Say y here to support the BUCKs and LDOs regulators found on Say y here to support the BUCKs and LDOs regulators found on
DA9063 PMICs. DA9063 PMICs.
@ -829,6 +830,26 @@ config REGULATOR_SKY81452
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called sky81452-regulator. will be called sky81452-regulator.
config REGULATOR_SLG51000
tristate "Dialog Semiconductor SLG51000 regulators"
depends on I2C
select REGMAP_I2C
help
Say y here to support for the Dialog Semiconductor SLG51000.
The SLG51000 is seven compact and customizable low dropout
regulators.
config REGULATOR_STM32_BOOSTER
tristate "STMicroelectronics STM32 BOOSTER"
depends on ARCH_STM32 || COMPILE_TEST
help
This driver supports internal booster (3V3) embedded in some
STMicroelectronics STM32 chips. It can be used to supply ADC analog
input switches when vdda supply is below 2.7V.
This driver can also be built as a module. If so, the module
will be called stm32-booster.
config REGULATOR_STM32_VREFBUF config REGULATOR_STM32_VREFBUF
tristate "STMicroelectronics STM32 VREFBUF" tristate "STMicroelectronics STM32 VREFBUF"
depends on ARCH_STM32 || COMPILE_TEST depends on ARCH_STM32 || COMPILE_TEST

View File

@ -11,7 +11,7 @@ obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
obj-$(CONFIG_REGULATOR_88PG86X) += 88pg86x.o obj-$(CONFIG_REGULATOR_88PG86X) += 88pg86x.o
obj-$(CONFIG_REGULATOR_88PM800) += 88pm800.o obj-$(CONFIG_REGULATOR_88PM800) += 88pm800-regulator.o
obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
obj-$(CONFIG_REGULATOR_CPCAP) += cpcap-regulator.o obj-$(CONFIG_REGULATOR_CPCAP) += cpcap-regulator.o
obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
@ -104,6 +104,8 @@ obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
obj-$(CONFIG_REGULATOR_SC2731) += sc2731-regulator.o obj-$(CONFIG_REGULATOR_SC2731) += sc2731-regulator.o
obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o
obj-$(CONFIG_REGULATOR_SLG51000) += slg51000-regulator.o
obj-$(CONFIG_REGULATOR_STM32_BOOSTER) += stm32-booster.o
obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
obj-$(CONFIG_REGULATOR_STM32_PWR) += stm32-pwr.o obj-$(CONFIG_REGULATOR_STM32_PWR) += stm32-pwr.o
obj-$(CONFIG_REGULATOR_STPMIC1) += stpmic1_regulator.o obj-$(CONFIG_REGULATOR_STPMIC1) += stpmic1_regulator.o

View File

@ -25,6 +25,10 @@
#include <linux/mfd/arizona/pdata.h> #include <linux/mfd/arizona/pdata.h>
#include <linux/mfd/arizona/registers.h> #include <linux/mfd/arizona/registers.h>
#include <linux/mfd/madera/core.h>
#include <linux/mfd/madera/pdata.h>
#include <linux/mfd/madera/registers.h>
struct arizona_ldo1 { struct arizona_ldo1 {
struct regulator_dev *regulator; struct regulator_dev *regulator;
struct regmap *regmap; struct regmap *regmap;
@ -158,6 +162,31 @@ static const struct regulator_init_data arizona_ldo1_wm5110 = {
.num_consumer_supplies = 1, .num_consumer_supplies = 1,
}; };
static const struct regulator_desc madera_ldo1 = {
.name = "LDO1",
.supply_name = "LDOVDD",
.type = REGULATOR_VOLTAGE,
.ops = &arizona_ldo1_ops,
.vsel_reg = MADERA_LDO1_CONTROL_1,
.vsel_mask = MADERA_LDO1_VSEL_MASK,
.min_uV = 900000,
.uV_step = 25000,
.n_voltages = 13,
.enable_time = 3000,
.owner = THIS_MODULE,
};
static const struct regulator_init_data madera_ldo1_default = {
.constraints = {
.min_uV = 1200000,
.max_uV = 1200000,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = 1,
};
static int arizona_ldo1_of_get_pdata(struct arizona_ldo1_pdata *pdata, static int arizona_ldo1_of_get_pdata(struct arizona_ldo1_pdata *pdata,
struct regulator_config *config, struct regulator_config *config,
const struct regulator_desc *desc, const struct regulator_desc *desc,
@ -320,6 +349,32 @@ static int arizona_ldo1_remove(struct platform_device *pdev)
return 0; return 0;
} }
static int madera_ldo1_probe(struct platform_device *pdev)
{
struct madera *madera = dev_get_drvdata(pdev->dev.parent);
struct arizona_ldo1 *ldo1;
bool external_dcvdd;
int ret;
ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL);
if (!ldo1)
return -ENOMEM;
ldo1->regmap = madera->regmap;
ldo1->init_data = madera_ldo1_default;
ret = arizona_ldo1_common_init(pdev, ldo1, &madera_ldo1,
&madera->pdata.ldo1,
&external_dcvdd);
if (ret)
return ret;
madera->internal_dcvdd = !external_dcvdd;
return 0;
}
static struct platform_driver arizona_ldo1_driver = { static struct platform_driver arizona_ldo1_driver = {
.probe = arizona_ldo1_probe, .probe = arizona_ldo1_probe,
.remove = arizona_ldo1_remove, .remove = arizona_ldo1_remove,
@ -328,10 +383,36 @@ static struct platform_driver arizona_ldo1_driver = {
}, },
}; };
module_platform_driver(arizona_ldo1_driver); static struct platform_driver madera_ldo1_driver = {
.probe = madera_ldo1_probe,
.remove = arizona_ldo1_remove,
.driver = {
.name = "madera-ldo1",
},
};
static struct platform_driver * const madera_ldo1_drivers[] = {
&arizona_ldo1_driver,
&madera_ldo1_driver,
};
static int __init arizona_ldo1_init(void)
{
return platform_register_drivers(madera_ldo1_drivers,
ARRAY_SIZE(madera_ldo1_drivers));
}
module_init(arizona_ldo1_init);
static void __exit madera_ldo1_exit(void)
{
platform_unregister_drivers(madera_ldo1_drivers,
ARRAY_SIZE(madera_ldo1_drivers));
}
module_exit(madera_ldo1_exit);
/* Module information */ /* Module information */
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_DESCRIPTION("Arizona LDO1 driver"); MODULE_DESCRIPTION("Arizona LDO1 driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:arizona-ldo1"); MODULE_ALIAS("platform:arizona-ldo1");
MODULE_ALIAS("platform:madera-ldo1");

View File

@ -16,7 +16,6 @@
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h> #include <linux/regulator/of_regulator.h>
#include <linux/gpio.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <sound/soc.h> #include <sound/soc.h>
@ -25,6 +24,10 @@
#include <linux/mfd/arizona/pdata.h> #include <linux/mfd/arizona/pdata.h>
#include <linux/mfd/arizona/registers.h> #include <linux/mfd/arizona/registers.h>
#include <linux/mfd/madera/core.h>
#include <linux/mfd/madera/pdata.h>
#include <linux/mfd/madera/registers.h>
#include <linux/regulator/arizona-micsupp.h> #include <linux/regulator/arizona-micsupp.h>
struct arizona_micsupp { struct arizona_micsupp {
@ -200,6 +203,28 @@ static const struct regulator_init_data arizona_micsupp_ext_default = {
.num_consumer_supplies = 1, .num_consumer_supplies = 1,
}; };
static const struct regulator_desc madera_micsupp = {
.name = "MICVDD",
.supply_name = "CPVDD1",
.type = REGULATOR_VOLTAGE,
.n_voltages = 40,
.ops = &arizona_micsupp_ops,
.vsel_reg = MADERA_LDO2_CONTROL_1,
.vsel_mask = MADERA_LDO2_VSEL_MASK,
.enable_reg = MADERA_MIC_CHARGE_PUMP_1,
.enable_mask = MADERA_CPMIC_ENA,
.bypass_reg = MADERA_MIC_CHARGE_PUMP_1,
.bypass_mask = MADERA_CPMIC_BYPASS,
.linear_ranges = arizona_micsupp_ext_ranges,
.n_linear_ranges = ARRAY_SIZE(arizona_micsupp_ext_ranges),
.enable_time = 3000,
.owner = THIS_MODULE,
};
static int arizona_micsupp_of_get_pdata(struct arizona_micsupp_pdata *pdata, static int arizona_micsupp_of_get_pdata(struct arizona_micsupp_pdata *pdata,
struct regulator_config *config, struct regulator_config *config,
const struct regulator_desc *desc) const struct regulator_desc *desc)
@ -316,6 +341,24 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
&arizona->pdata.micvdd); &arizona->pdata.micvdd);
} }
static int madera_micsupp_probe(struct platform_device *pdev)
{
struct madera *madera = dev_get_drvdata(pdev->dev.parent);
struct arizona_micsupp *micsupp;
micsupp = devm_kzalloc(&pdev->dev, sizeof(*micsupp), GFP_KERNEL);
if (!micsupp)
return -ENOMEM;
micsupp->regmap = madera->regmap;
micsupp->dapm = &madera->dapm;
micsupp->dev = madera->dev;
micsupp->init_data = arizona_micsupp_ext_default;
return arizona_micsupp_common_init(pdev, micsupp, &madera_micsupp,
&madera->pdata.micvdd);
}
static struct platform_driver arizona_micsupp_driver = { static struct platform_driver arizona_micsupp_driver = {
.probe = arizona_micsupp_probe, .probe = arizona_micsupp_probe,
.driver = { .driver = {
@ -323,10 +366,35 @@ static struct platform_driver arizona_micsupp_driver = {
}, },
}; };
module_platform_driver(arizona_micsupp_driver); static struct platform_driver madera_micsupp_driver = {
.probe = madera_micsupp_probe,
.driver = {
.name = "madera-micsupp",
},
};
static struct platform_driver * const arizona_micsupp_drivers[] = {
&arizona_micsupp_driver,
&madera_micsupp_driver,
};
static int __init arizona_micsupp_init(void)
{
return platform_register_drivers(arizona_micsupp_drivers,
ARRAY_SIZE(arizona_micsupp_drivers));
}
module_init(arizona_micsupp_init);
static void __exit arizona_micsupp_exit(void)
{
platform_unregister_drivers(arizona_micsupp_drivers,
ARRAY_SIZE(arizona_micsupp_drivers));
}
module_exit(arizona_micsupp_exit);
/* Module information */ /* Module information */
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_DESCRIPTION("Arizona microphone supply driver"); MODULE_DESCRIPTION("Arizona microphone supply driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:arizona-micsupp"); MODULE_ALIAS("platform:arizona-micsupp");
MODULE_ALIAS("platform:madera-micsupp");

View File

@ -4,7 +4,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mfd/rohm-bd70528.h> #include <linux/mfd/rohm-bd70528.h>

View File

@ -4,7 +4,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mfd/rohm-bd718x7.h> #include <linux/mfd/rohm-bd718x7.h>

View File

@ -1,12 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
/* //
* core.c -- Voltage/Current Regulator framework. // core.c -- Voltage/Current Regulator framework.
* //
* Copyright 2007, 2008 Wolfson Microelectronics PLC. // Copyright 2007, 2008 Wolfson Microelectronics PLC.
* Copyright 2008 SlimLogic Ltd. // Copyright 2008 SlimLogic Ltd.
* //
* Author: Liam Girdwood <lrg@slimlogic.co.uk> // Author: Liam Girdwood <lrg@slimlogic.co.uk>
*/
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
@ -1645,9 +1644,9 @@ static int _regulator_get_enable_time(struct regulator_dev *rdev)
{ {
if (rdev->constraints && rdev->constraints->enable_time) if (rdev->constraints && rdev->constraints->enable_time)
return rdev->constraints->enable_time; return rdev->constraints->enable_time;
if (!rdev->desc->ops->enable_time) if (rdev->desc->ops->enable_time)
return rdev->desc->enable_time; return rdev->desc->ops->enable_time(rdev);
return rdev->desc->ops->enable_time(rdev); return rdev->desc->enable_time;
} }
static struct regulator_supply_alias *regulator_find_supply_alias( static struct regulator_supply_alias *regulator_find_supply_alias(
@ -3107,6 +3106,66 @@ static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev,
return ret; return ret;
} }
static int _regulator_set_voltage_sel_step(struct regulator_dev *rdev,
int uV, int new_selector)
{
const struct regulator_ops *ops = rdev->desc->ops;
int diff, old_sel, curr_sel, ret;
/* Stepping is only needed if the regulator is enabled. */
if (!_regulator_is_enabled(rdev))
goto final_set;
if (!ops->get_voltage_sel)
return -EINVAL;
old_sel = ops->get_voltage_sel(rdev);
if (old_sel < 0)
return old_sel;
diff = new_selector - old_sel;
if (diff == 0)
return 0; /* No change needed. */
if (diff > 0) {
/* Stepping up. */
for (curr_sel = old_sel + rdev->desc->vsel_step;
curr_sel < new_selector;
curr_sel += rdev->desc->vsel_step) {
/*
* Call the callback directly instead of using
* _regulator_call_set_voltage_sel() as we don't
* want to notify anyone yet. Same in the branch
* below.
*/
ret = ops->set_voltage_sel(rdev, curr_sel);
if (ret)
goto try_revert;
}
} else {
/* Stepping down. */
for (curr_sel = old_sel - rdev->desc->vsel_step;
curr_sel > new_selector;
curr_sel -= rdev->desc->vsel_step) {
ret = ops->set_voltage_sel(rdev, curr_sel);
if (ret)
goto try_revert;
}
}
final_set:
/* The final selector will trigger the notifiers. */
return _regulator_call_set_voltage_sel(rdev, uV, new_selector);
try_revert:
/*
* At least try to return to the previous voltage if setting a new
* one failed.
*/
(void)ops->set_voltage_sel(rdev, old_sel);
return ret;
}
static int _regulator_set_voltage_time(struct regulator_dev *rdev, static int _regulator_set_voltage_time(struct regulator_dev *rdev,
int old_uV, int new_uV) int old_uV, int new_uV)
{ {
@ -3180,6 +3239,9 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
selector = ret; selector = ret;
if (old_selector == selector) if (old_selector == selector)
ret = 0; ret = 0;
else if (rdev->desc->vsel_step)
ret = _regulator_set_voltage_sel_step(
rdev, best_val, selector);
else else
ret = _regulator_call_set_voltage_sel( ret = _regulator_call_set_voltage_sel(
rdev, best_val, selector); rdev, best_val, selector);

View File

@ -90,7 +90,7 @@
#define CPCAP_REG_OFF_MODE_SEC BIT(15) #define CPCAP_REG_OFF_MODE_SEC BIT(15)
/** /**
* SoC specific configuraion for CPCAP regulator. There are at least three * SoC specific configuration for CPCAP regulator. There are at least three
* different SoCs each with their own parameters: omap3, omap4 and tegra2. * different SoCs each with their own parameters: omap3, omap4 and tegra2.
* *
* The assign_reg and assign_mask seem to allow toggling between primary * The assign_reg and assign_mask seem to allow toggling between primary

View File

@ -493,12 +493,13 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
.desc.ops = &da9062_ldo_ops, .desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000, .desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000, .desc.uV_step = (50) * 1000,
.desc.n_voltages = ((3600) - (900))/(50) + 1, .desc.n_voltages = ((3600) - (900))/(50) + 1
+ DA9062AA_VLDO_A_MIN_SEL,
.desc.enable_reg = DA9062AA_LDO1_CONT, .desc.enable_reg = DA9062AA_LDO1_CONT,
.desc.enable_mask = DA9062AA_LDO1_EN_MASK, .desc.enable_mask = DA9062AA_LDO1_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO1_A, .desc.vsel_reg = DA9062AA_VLDO1_A,
.desc.vsel_mask = DA9062AA_VLDO1_A_MASK, .desc.vsel_mask = DA9062AA_VLDO1_A_MASK,
.desc.linear_min_sel = 0, .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
.sleep = REG_FIELD(DA9062AA_VLDO1_A, .sleep = REG_FIELD(DA9062AA_VLDO1_A,
__builtin_ffs((int)DA9062AA_LDO1_SL_A_MASK) - 1, __builtin_ffs((int)DA9062AA_LDO1_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 - sizeof(unsigned int) * 8 -
@ -525,12 +526,13 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
.desc.ops = &da9062_ldo_ops, .desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000, .desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000, .desc.uV_step = (50) * 1000,
.desc.n_voltages = ((3600) - (600))/(50) + 1, .desc.n_voltages = ((3600) - (900))/(50) + 1
+ DA9062AA_VLDO_A_MIN_SEL,
.desc.enable_reg = DA9062AA_LDO2_CONT, .desc.enable_reg = DA9062AA_LDO2_CONT,
.desc.enable_mask = DA9062AA_LDO2_EN_MASK, .desc.enable_mask = DA9062AA_LDO2_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO2_A, .desc.vsel_reg = DA9062AA_VLDO2_A,
.desc.vsel_mask = DA9062AA_VLDO2_A_MASK, .desc.vsel_mask = DA9062AA_VLDO2_A_MASK,
.desc.linear_min_sel = 0, .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
.sleep = REG_FIELD(DA9062AA_VLDO2_A, .sleep = REG_FIELD(DA9062AA_VLDO2_A,
__builtin_ffs((int)DA9062AA_LDO2_SL_A_MASK) - 1, __builtin_ffs((int)DA9062AA_LDO2_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 - sizeof(unsigned int) * 8 -
@ -557,12 +559,13 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
.desc.ops = &da9062_ldo_ops, .desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000, .desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000, .desc.uV_step = (50) * 1000,
.desc.n_voltages = ((3600) - (900))/(50) + 1, .desc.n_voltages = ((3600) - (900))/(50) + 1
+ DA9062AA_VLDO_A_MIN_SEL,
.desc.enable_reg = DA9062AA_LDO3_CONT, .desc.enable_reg = DA9062AA_LDO3_CONT,
.desc.enable_mask = DA9062AA_LDO3_EN_MASK, .desc.enable_mask = DA9062AA_LDO3_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO3_A, .desc.vsel_reg = DA9062AA_VLDO3_A,
.desc.vsel_mask = DA9062AA_VLDO3_A_MASK, .desc.vsel_mask = DA9062AA_VLDO3_A_MASK,
.desc.linear_min_sel = 0, .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
.sleep = REG_FIELD(DA9062AA_VLDO3_A, .sleep = REG_FIELD(DA9062AA_VLDO3_A,
__builtin_ffs((int)DA9062AA_LDO3_SL_A_MASK) - 1, __builtin_ffs((int)DA9062AA_LDO3_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 - sizeof(unsigned int) * 8 -
@ -589,12 +592,13 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
.desc.ops = &da9062_ldo_ops, .desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000, .desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000, .desc.uV_step = (50) * 1000,
.desc.n_voltages = ((3600) - (900))/(50) + 1, .desc.n_voltages = ((3600) - (900))/(50) + 1
+ DA9062AA_VLDO_A_MIN_SEL,
.desc.enable_reg = DA9062AA_LDO4_CONT, .desc.enable_reg = DA9062AA_LDO4_CONT,
.desc.enable_mask = DA9062AA_LDO4_EN_MASK, .desc.enable_mask = DA9062AA_LDO4_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO4_A, .desc.vsel_reg = DA9062AA_VLDO4_A,
.desc.vsel_mask = DA9062AA_VLDO4_A_MASK, .desc.vsel_mask = DA9062AA_VLDO4_A_MASK,
.desc.linear_min_sel = 0, .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
.sleep = REG_FIELD(DA9062AA_VLDO4_A, .sleep = REG_FIELD(DA9062AA_VLDO4_A,
__builtin_ffs((int)DA9062AA_LDO4_SL_A_MASK) - 1, __builtin_ffs((int)DA9062AA_LDO4_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 - sizeof(unsigned int) * 8 -
@ -769,12 +773,13 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
.desc.ops = &da9062_ldo_ops, .desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000, .desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000, .desc.uV_step = (50) * 1000,
.desc.n_voltages = ((3600) - (900))/(50) + 1, .desc.n_voltages = ((3600) - (900))/(50) + 1
+ DA9062AA_VLDO_A_MIN_SEL,
.desc.enable_reg = DA9062AA_LDO1_CONT, .desc.enable_reg = DA9062AA_LDO1_CONT,
.desc.enable_mask = DA9062AA_LDO1_EN_MASK, .desc.enable_mask = DA9062AA_LDO1_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO1_A, .desc.vsel_reg = DA9062AA_VLDO1_A,
.desc.vsel_mask = DA9062AA_VLDO1_A_MASK, .desc.vsel_mask = DA9062AA_VLDO1_A_MASK,
.desc.linear_min_sel = 0, .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
.sleep = REG_FIELD(DA9062AA_VLDO1_A, .sleep = REG_FIELD(DA9062AA_VLDO1_A,
__builtin_ffs((int)DA9062AA_LDO1_SL_A_MASK) - 1, __builtin_ffs((int)DA9062AA_LDO1_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 - sizeof(unsigned int) * 8 -
@ -801,12 +806,13 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
.desc.ops = &da9062_ldo_ops, .desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000, .desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000, .desc.uV_step = (50) * 1000,
.desc.n_voltages = ((3600) - (600))/(50) + 1, .desc.n_voltages = ((3600) - (900))/(50) + 1
+ DA9062AA_VLDO_A_MIN_SEL,
.desc.enable_reg = DA9062AA_LDO2_CONT, .desc.enable_reg = DA9062AA_LDO2_CONT,
.desc.enable_mask = DA9062AA_LDO2_EN_MASK, .desc.enable_mask = DA9062AA_LDO2_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO2_A, .desc.vsel_reg = DA9062AA_VLDO2_A,
.desc.vsel_mask = DA9062AA_VLDO2_A_MASK, .desc.vsel_mask = DA9062AA_VLDO2_A_MASK,
.desc.linear_min_sel = 0, .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
.sleep = REG_FIELD(DA9062AA_VLDO2_A, .sleep = REG_FIELD(DA9062AA_VLDO2_A,
__builtin_ffs((int)DA9062AA_LDO2_SL_A_MASK) - 1, __builtin_ffs((int)DA9062AA_LDO2_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 - sizeof(unsigned int) * 8 -
@ -833,12 +839,13 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
.desc.ops = &da9062_ldo_ops, .desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000, .desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000, .desc.uV_step = (50) * 1000,
.desc.n_voltages = ((3600) - (900))/(50) + 1, .desc.n_voltages = ((3600) - (900))/(50) + 1
+ DA9062AA_VLDO_A_MIN_SEL,
.desc.enable_reg = DA9062AA_LDO3_CONT, .desc.enable_reg = DA9062AA_LDO3_CONT,
.desc.enable_mask = DA9062AA_LDO3_EN_MASK, .desc.enable_mask = DA9062AA_LDO3_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO3_A, .desc.vsel_reg = DA9062AA_VLDO3_A,
.desc.vsel_mask = DA9062AA_VLDO3_A_MASK, .desc.vsel_mask = DA9062AA_VLDO3_A_MASK,
.desc.linear_min_sel = 0, .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
.sleep = REG_FIELD(DA9062AA_VLDO3_A, .sleep = REG_FIELD(DA9062AA_VLDO3_A,
__builtin_ffs((int)DA9062AA_LDO3_SL_A_MASK) - 1, __builtin_ffs((int)DA9062AA_LDO3_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 - sizeof(unsigned int) * 8 -
@ -865,12 +872,13 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
.desc.ops = &da9062_ldo_ops, .desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000, .desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000, .desc.uV_step = (50) * 1000,
.desc.n_voltages = ((3600) - (900))/(50) + 1, .desc.n_voltages = ((3600) - (900))/(50) + 1
+ DA9062AA_VLDO_A_MIN_SEL,
.desc.enable_reg = DA9062AA_LDO4_CONT, .desc.enable_reg = DA9062AA_LDO4_CONT,
.desc.enable_mask = DA9062AA_LDO4_EN_MASK, .desc.enable_mask = DA9062AA_LDO4_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO4_A, .desc.vsel_reg = DA9062AA_VLDO4_A,
.desc.vsel_mask = DA9062AA_VLDO4_A_MASK, .desc.vsel_mask = DA9062AA_VLDO4_A_MASK,
.desc.linear_min_sel = 0, .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
.sleep = REG_FIELD(DA9062AA_VLDO4_A, .sleep = REG_FIELD(DA9062AA_VLDO4_A,
__builtin_ffs((int)DA9062AA_LDO4_SL_A_MASK) - 1, __builtin_ffs((int)DA9062AA_LDO4_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 - sizeof(unsigned int) * 8 -

View File

@ -19,7 +19,6 @@
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h> #include <linux/regulator/of_regulator.h>
#include <linux/mfd/da9063/core.h> #include <linux/mfd/da9063/core.h>
#include <linux/mfd/da9063/pdata.h>
#include <linux/mfd/da9063/registers.h> #include <linux/mfd/da9063/registers.h>
@ -28,6 +27,49 @@
REG_FIELD(_reg, __builtin_ffs((int)_mask) - 1, \ REG_FIELD(_reg, __builtin_ffs((int)_mask) - 1, \
sizeof(unsigned int) * 8 - __builtin_clz((_mask)) - 1) sizeof(unsigned int) * 8 - __builtin_clz((_mask)) - 1)
/* DA9063 and DA9063L regulator IDs */
enum {
/* BUCKs */
DA9063_ID_BCORE1,
DA9063_ID_BCORE2,
DA9063_ID_BPRO,
DA9063_ID_BMEM,
DA9063_ID_BIO,
DA9063_ID_BPERI,
/* BCORE1 and BCORE2 in merged mode */
DA9063_ID_BCORES_MERGED,
/* BMEM and BIO in merged mode */
DA9063_ID_BMEM_BIO_MERGED,
/* When two BUCKs are merged, they cannot be reused separately */
/* LDOs on both DA9063 and DA9063L */
DA9063_ID_LDO3,
DA9063_ID_LDO7,
DA9063_ID_LDO8,
DA9063_ID_LDO9,
DA9063_ID_LDO11,
/* DA9063-only LDOs */
DA9063_ID_LDO1,
DA9063_ID_LDO2,
DA9063_ID_LDO4,
DA9063_ID_LDO5,
DA9063_ID_LDO6,
DA9063_ID_LDO10,
};
/* Old regulator platform data */
struct da9063_regulator_data {
int id;
struct regulator_init_data *initdata;
};
struct da9063_regulators_pdata {
unsigned n_regulators;
struct da9063_regulator_data *regulator_data;
};
/* Regulator capabilities and registers description */ /* Regulator capabilities and registers description */
struct da9063_regulator_info { struct da9063_regulator_info {
struct regulator_desc desc; struct regulator_desc desc;
@ -592,7 +634,6 @@ static const struct regulator_init_data *da9063_get_regulator_initdata(
return NULL; return NULL;
} }
#ifdef CONFIG_OF
static struct of_regulator_match da9063_matches[] = { static struct of_regulator_match da9063_matches[] = {
[DA9063_ID_BCORE1] = { .name = "bcore1" }, [DA9063_ID_BCORE1] = { .name = "bcore1" },
[DA9063_ID_BCORE2] = { .name = "bcore2" }, [DA9063_ID_BCORE2] = { .name = "bcore2" },
@ -670,20 +711,10 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
*da9063_reg_matches = da9063_matches; *da9063_reg_matches = da9063_matches;
return pdata; return pdata;
} }
#else
static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
struct platform_device *pdev,
struct of_regulator_match **da9063_reg_matches)
{
*da9063_reg_matches = NULL;
return ERR_PTR(-ENODEV);
}
#endif
static int da9063_regulator_probe(struct platform_device *pdev) static int da9063_regulator_probe(struct platform_device *pdev)
{ {
struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent); struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
struct da9063_pdata *da9063_pdata = dev_get_platdata(da9063->dev);
struct of_regulator_match *da9063_reg_matches = NULL; struct of_regulator_match *da9063_reg_matches = NULL;
struct da9063_regulators_pdata *regl_pdata; struct da9063_regulators_pdata *regl_pdata;
const struct da9063_dev_model *model; const struct da9063_dev_model *model;
@ -693,11 +724,7 @@ static int da9063_regulator_probe(struct platform_device *pdev)
bool bcores_merged, bmem_bio_merged; bool bcores_merged, bmem_bio_merged;
int id, irq, n, n_regulators, ret, val; int id, irq, n, n_regulators, ret, val;
regl_pdata = da9063_pdata ? da9063_pdata->regulators_pdata : NULL; regl_pdata = da9063_parse_regulators_dt(pdev, &da9063_reg_matches);
if (!regl_pdata)
regl_pdata = da9063_parse_regulators_dt(pdev,
&da9063_reg_matches);
if (IS_ERR(regl_pdata) || regl_pdata->n_regulators == 0) { if (IS_ERR(regl_pdata) || regl_pdata->n_regulators == 0) {
dev_err(&pdev->dev, dev_err(&pdev->dev,

View File

@ -289,6 +289,8 @@ static struct da9211_pdata *da9211_parse_regulators_dt(
0, 0,
GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE, GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
"da9211-enable"); "da9211-enable");
if (IS_ERR(pdata->gpiod_ren[n]))
pdata->gpiod_ren[n] = NULL;
n++; n++;
} }

View File

@ -1,10 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
/* //
* helpers.c -- Voltage/Current Regulator framework helper functions. // helpers.c -- Voltage/Current Regulator framework helper functions.
* //
* Copyright 2007, 2008 Wolfson Microelectronics PLC. // Copyright 2007, 2008 Wolfson Microelectronics PLC.
* Copyright 2008 SlimLogic Ltd. // Copyright 2008 SlimLogic Ltd.
*/
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/err.h> #include <linux/err.h>

View File

@ -467,7 +467,7 @@ static int max77620_regulator_is_enabled(struct regulator_dev *rdev)
{ {
struct max77620_regulator *pmic = rdev_get_drvdata(rdev); struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
int id = rdev_get_id(rdev); int id = rdev_get_id(rdev);
int ret = 1; int ret;
if (pmic->active_fps_src[id] != MAX77620_FPS_SRC_NONE) if (pmic->active_fps_src[id] != MAX77620_FPS_SRC_NONE)
return 1; return 1;
@ -758,6 +758,24 @@ static struct max77620_regulator_info max20024_regs_info[MAX77620_NUM_REGS] = {
RAIL_LDO(LDO8, ldo8, "in-ldo7-8", N, 800000, 3950000, 50000), RAIL_LDO(LDO8, ldo8, "in-ldo7-8", N, 800000, 3950000, 50000),
}; };
static struct max77620_regulator_info max77663_regs_info[MAX77620_NUM_REGS] = {
RAIL_SD(SD0, sd0, "in-sd0", SD0, 600000, 3387500, 12500, 0xFF, NONE),
RAIL_SD(SD1, sd1, "in-sd1", SD1, 800000, 1587500, 12500, 0xFF, NONE),
RAIL_SD(SD2, sd2, "in-sd2", SDX, 600000, 3787500, 12500, 0xFF, NONE),
RAIL_SD(SD3, sd3, "in-sd3", SDX, 600000, 3787500, 12500, 0xFF, NONE),
RAIL_SD(SD4, sd4, "in-sd4", SDX, 600000, 3787500, 12500, 0xFF, NONE),
RAIL_LDO(LDO0, ldo0, "in-ldo0-1", N, 800000, 2375000, 25000),
RAIL_LDO(LDO1, ldo1, "in-ldo0-1", N, 800000, 2375000, 25000),
RAIL_LDO(LDO2, ldo2, "in-ldo2", P, 800000, 3950000, 50000),
RAIL_LDO(LDO3, ldo3, "in-ldo3-5", P, 800000, 3950000, 50000),
RAIL_LDO(LDO4, ldo4, "in-ldo4-6", P, 800000, 1587500, 12500),
RAIL_LDO(LDO5, ldo5, "in-ldo3-5", P, 800000, 3950000, 50000),
RAIL_LDO(LDO6, ldo6, "in-ldo4-6", P, 800000, 3950000, 50000),
RAIL_LDO(LDO7, ldo7, "in-ldo7-8", N, 800000, 3950000, 50000),
RAIL_LDO(LDO8, ldo8, "in-ldo7-8", N, 800000, 3950000, 50000),
};
static int max77620_regulator_probe(struct platform_device *pdev) static int max77620_regulator_probe(struct platform_device *pdev)
{ {
struct max77620_chip *max77620_chip = dev_get_drvdata(pdev->dev.parent); struct max77620_chip *max77620_chip = dev_get_drvdata(pdev->dev.parent);
@ -782,9 +800,14 @@ static int max77620_regulator_probe(struct platform_device *pdev)
case MAX77620: case MAX77620:
rinfo = max77620_regs_info; rinfo = max77620_regs_info;
break; break;
default: case MAX20024:
rinfo = max20024_regs_info; rinfo = max20024_regs_info;
break; break;
case MAX77663:
rinfo = max77663_regs_info;
break;
default:
return -EINVAL;
} }
config.regmap = pmic->rmap; config.regmap = pmic->rmap;
@ -878,6 +901,7 @@ static const struct dev_pm_ops max77620_regulator_pm_ops = {
static const struct platform_device_id max77620_regulator_devtype[] = { static const struct platform_device_id max77620_regulator_devtype[] = {
{ .name = "max77620-pmic", }, { .name = "max77620-pmic", },
{ .name = "max20024-pmic", }, { .name = "max20024-pmic", },
{ .name = "max77663-pmic", },
{}, {},
}; };
MODULE_DEVICE_TABLE(platform, max77620_regulator_devtype); MODULE_DEVICE_TABLE(platform, max77620_regulator_devtype);

View File

@ -20,6 +20,8 @@
#define MAX77650_REGULATOR_V_LDO_MASK GENMASK(6, 0) #define MAX77650_REGULATOR_V_LDO_MASK GENMASK(6, 0)
#define MAX77650_REGULATOR_V_SBB_MASK GENMASK(5, 0) #define MAX77650_REGULATOR_V_SBB_MASK GENMASK(5, 0)
#define MAX77651_REGULATOR_V_SBB1_MASK GENMASK(5, 2)
#define MAX77651_REGULATOR_V_SBB1_RANGE_MASK GENMASK(1, 0)
#define MAX77650_REGULATOR_AD_MASK BIT(3) #define MAX77650_REGULATOR_AD_MASK BIT(3)
#define MAX77650_REGULATOR_AD_DISABLED 0x00 #define MAX77650_REGULATOR_AD_DISABLED 0x00
@ -41,43 +43,22 @@ struct max77650_regulator_desc {
unsigned int regB; unsigned int regB;
}; };
static const unsigned int max77651_sbb1_regulator_volt_table[] = { static struct max77650_regulator_desc max77651_SBB1_desc;
2400000, 3200000, 4000000, 4800000,
2450000, 3250000, 4050000, 4850000, static const unsigned int max77651_sbb1_volt_range_sel[] = {
2500000, 3300000, 4100000, 4900000, 0x0, 0x1, 0x2, 0x3
2550000, 3350000, 4150000, 4950000,
2600000, 3400000, 4200000, 5000000,
2650000, 3450000, 4250000, 5050000,
2700000, 3500000, 4300000, 5100000,
2750000, 3550000, 4350000, 5150000,
2800000, 3600000, 4400000, 5200000,
2850000, 3650000, 4450000, 5250000,
2900000, 3700000, 4500000, 0,
2950000, 3750000, 4550000, 0,
3000000, 3800000, 4600000, 0,
3050000, 3850000, 4650000, 0,
3100000, 3900000, 4700000, 0,
3150000, 3950000, 4750000, 0,
}; };
#define MAX77651_REGULATOR_SBB1_SEL_DEC(_val) \ static const struct regulator_linear_range max77651_sbb1_volt_ranges[] = {
(((_val & 0x3c) >> 2) | ((_val & 0x03) << 4)) /* range index 0 */
#define MAX77651_REGULATOR_SBB1_SEL_ENC(_val) \ REGULATOR_LINEAR_RANGE(2400000, 0x00, 0x0f, 50000),
(((_val & 0x30) >> 4) | ((_val & 0x0f) << 2)) /* range index 1 */
REGULATOR_LINEAR_RANGE(3200000, 0x00, 0x0f, 50000),
#define MAX77650_REGULATOR_SBB1_SEL_DECR(_val) \ /* range index 2 */
do { \ REGULATOR_LINEAR_RANGE(4000000, 0x00, 0x0f, 50000),
_val = MAX77651_REGULATOR_SBB1_SEL_DEC(_val); \ /* range index 3 */
_val--; \ REGULATOR_LINEAR_RANGE(4800000, 0x00, 0x09, 50000),
_val = MAX77651_REGULATOR_SBB1_SEL_ENC(_val); \ };
} while (0)
#define MAX77650_REGULATOR_SBB1_SEL_INCR(_val) \
do { \
_val = MAX77651_REGULATOR_SBB1_SEL_DEC(_val); \
_val++; \
_val = MAX77651_REGULATOR_SBB1_SEL_ENC(_val); \
} while (0)
static const unsigned int max77650_current_limit_table[] = { static const unsigned int max77650_current_limit_table[] = {
1000000, 866000, 707000, 500000, 1000000, 866000, 707000, 500000,
@ -127,96 +108,6 @@ static int max77650_regulator_disable(struct regulator_dev *rdev)
MAX77650_REGULATOR_DISABLED); MAX77650_REGULATOR_DISABLED);
} }
static int max77650_regulator_set_voltage_sel(struct regulator_dev *rdev,
unsigned int sel)
{
int rv = 0, curr, diff;
bool ascending;
/*
* If the regulator is disabled, we can program the desired
* voltage right away.
*/
if (!max77650_regulator_is_enabled(rdev))
return regulator_set_voltage_sel_regmap(rdev, sel);
/*
* Otherwise we need to manually ramp the output voltage up/down
* one step at a time.
*/
curr = regulator_get_voltage_sel_regmap(rdev);
if (curr < 0)
return curr;
diff = curr - sel;
if (diff == 0)
return 0; /* Already there. */
else if (diff > 0)
ascending = false;
else
ascending = true;
/*
* Make sure we'll get to the right voltage and break the loop even if
* the selector equals 0.
*/
for (ascending ? curr++ : curr--;; ascending ? curr++ : curr--) {
rv = regulator_set_voltage_sel_regmap(rdev, curr);
if (rv)
return rv;
if (curr == sel)
break;
}
return 0;
}
/*
* Special case: non-linear voltage table for max77651 SBB1 - software
* must ensure the voltage is ramped in 50mV increments.
*/
static int max77651_regulator_sbb1_set_voltage_sel(struct regulator_dev *rdev,
unsigned int sel)
{
int rv = 0, curr, vcurr, vdest, vdiff;
/*
* If the regulator is disabled, we can program the desired
* voltage right away.
*/
if (!max77650_regulator_is_enabled(rdev))
return regulator_set_voltage_sel_regmap(rdev, sel);
curr = regulator_get_voltage_sel_regmap(rdev);
if (curr < 0)
return curr;
if (curr == sel)
return 0; /* Already there. */
vcurr = max77651_sbb1_regulator_volt_table[curr];
vdest = max77651_sbb1_regulator_volt_table[sel];
vdiff = vcurr - vdest;
for (;;) {
if (vdiff > 0)
MAX77650_REGULATOR_SBB1_SEL_DECR(curr);
else
MAX77650_REGULATOR_SBB1_SEL_INCR(curr);
rv = regulator_set_voltage_sel_regmap(rdev, curr);
if (rv)
return rv;
if (curr == sel)
break;
};
return 0;
}
static const struct regulator_ops max77650_regulator_LDO_ops = { static const struct regulator_ops max77650_regulator_LDO_ops = {
.is_enabled = max77650_regulator_is_enabled, .is_enabled = max77650_regulator_is_enabled,
.enable = max77650_regulator_enable, .enable = max77650_regulator_enable,
@ -224,7 +115,7 @@ static const struct regulator_ops max77650_regulator_LDO_ops = {
.list_voltage = regulator_list_voltage_linear, .list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear, .map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = max77650_regulator_set_voltage_sel, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_active_discharge = regulator_set_active_discharge_regmap, .set_active_discharge = regulator_set_active_discharge_regmap,
}; };
@ -235,20 +126,20 @@ static const struct regulator_ops max77650_regulator_SBB_ops = {
.list_voltage = regulator_list_voltage_linear, .list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear, .map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = max77650_regulator_set_voltage_sel, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_current_limit = regulator_get_current_limit_regmap, .get_current_limit = regulator_get_current_limit_regmap,
.set_current_limit = regulator_set_current_limit_regmap, .set_current_limit = regulator_set_current_limit_regmap,
.set_active_discharge = regulator_set_active_discharge_regmap, .set_active_discharge = regulator_set_active_discharge_regmap,
}; };
/* Special case for max77651 SBB1 - non-linear voltage mapping. */ /* Special case for max77651 SBB1 - pickable linear-range voltage mapping. */
static const struct regulator_ops max77651_SBB1_regulator_ops = { static const struct regulator_ops max77651_SBB1_regulator_ops = {
.is_enabled = max77650_regulator_is_enabled, .is_enabled = max77650_regulator_is_enabled,
.enable = max77650_regulator_enable, .enable = max77650_regulator_enable,
.disable = max77650_regulator_disable, .disable = max77650_regulator_disable,
.list_voltage = regulator_list_voltage_table, .list_voltage = regulator_list_voltage_pickable_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
.set_voltage_sel = max77651_regulator_sbb1_set_voltage_sel, .set_voltage_sel = regulator_set_voltage_sel_pickable_regmap,
.get_current_limit = regulator_get_current_limit_regmap, .get_current_limit = regulator_get_current_limit_regmap,
.set_current_limit = regulator_set_current_limit_regmap, .set_current_limit = regulator_set_current_limit_regmap,
.set_active_discharge = regulator_set_active_discharge_regmap, .set_active_discharge = regulator_set_active_discharge_regmap,
@ -265,6 +156,7 @@ static struct max77650_regulator_desc max77650_LDO_desc = {
.min_uV = 1350000, .min_uV = 1350000,
.uV_step = 12500, .uV_step = 12500,
.n_voltages = 128, .n_voltages = 128,
.vsel_step = 1,
.vsel_mask = MAX77650_REGULATOR_V_LDO_MASK, .vsel_mask = MAX77650_REGULATOR_V_LDO_MASK,
.vsel_reg = MAX77650_REG_CNFG_LDO_A, .vsel_reg = MAX77650_REG_CNFG_LDO_A,
.active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
@ -290,6 +182,7 @@ static struct max77650_regulator_desc max77650_SBB0_desc = {
.min_uV = 800000, .min_uV = 800000,
.uV_step = 25000, .uV_step = 25000,
.n_voltages = 64, .n_voltages = 64,
.vsel_step = 1,
.vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
.vsel_reg = MAX77650_REG_CNFG_SBB0_A, .vsel_reg = MAX77650_REG_CNFG_SBB0_A,
.active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
@ -319,6 +212,7 @@ static struct max77650_regulator_desc max77650_SBB1_desc = {
.min_uV = 800000, .min_uV = 800000,
.uV_step = 12500, .uV_step = 12500,
.n_voltages = 64, .n_voltages = 64,
.vsel_step = 1,
.vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
.vsel_reg = MAX77650_REG_CNFG_SBB1_A, .vsel_reg = MAX77650_REG_CNFG_SBB1_A,
.active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
@ -345,9 +239,14 @@ static struct max77650_regulator_desc max77651_SBB1_desc = {
.supply_name = "in-sbb1", .supply_name = "in-sbb1",
.id = MAX77650_REGULATOR_ID_SBB1, .id = MAX77650_REGULATOR_ID_SBB1,
.ops = &max77651_SBB1_regulator_ops, .ops = &max77651_SBB1_regulator_ops,
.volt_table = max77651_sbb1_regulator_volt_table, .linear_range_selectors = max77651_sbb1_volt_range_sel,
.n_voltages = ARRAY_SIZE(max77651_sbb1_regulator_volt_table), .linear_ranges = max77651_sbb1_volt_ranges,
.vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, .n_linear_ranges = ARRAY_SIZE(max77651_sbb1_volt_ranges),
.n_voltages = 58,
.vsel_step = 1,
.vsel_range_mask = MAX77651_REGULATOR_V_SBB1_RANGE_MASK,
.vsel_range_reg = MAX77650_REG_CNFG_SBB1_A,
.vsel_mask = MAX77651_REGULATOR_V_SBB1_MASK,
.vsel_reg = MAX77650_REG_CNFG_SBB1_A, .vsel_reg = MAX77650_REG_CNFG_SBB1_A,
.active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
.active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
@ -376,6 +275,7 @@ static struct max77650_regulator_desc max77650_SBB2_desc = {
.min_uV = 800000, .min_uV = 800000,
.uV_step = 50000, .uV_step = 50000,
.n_voltages = 64, .n_voltages = 64,
.vsel_step = 1,
.vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
.vsel_reg = MAX77650_REG_CNFG_SBB2_A, .vsel_reg = MAX77650_REG_CNFG_SBB2_A,
.active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
@ -405,6 +305,7 @@ static struct max77650_regulator_desc max77651_SBB2_desc = {
.min_uV = 2400000, .min_uV = 2400000,
.uV_step = 50000, .uV_step = 50000,
.n_voltages = 64, .n_voltages = 64,
.vsel_step = 1,
.vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
.vsel_reg = MAX77650_REG_CNFG_SBB2_A, .vsel_reg = MAX77650_REG_CNFG_SBB2_A,
.active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
@ -496,3 +397,4 @@ module_platform_driver(max77650_regulator_driver);
MODULE_DESCRIPTION("MAXIM 77650/77651 regulator driver"); MODULE_DESCRIPTION("MAXIM 77650/77651 regulator driver");
MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>"); MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:max77650-regulator");

View File

@ -14,9 +14,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>

View File

@ -13,11 +13,9 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
#include <linux/regulator/max8952.h> #include <linux/regulator/max8952.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/regulator/of_regulator.h> #include <linux/regulator/of_regulator.h>
#include <linux/slab.h> #include <linux/slab.h>
@ -37,7 +35,8 @@ enum {
struct max8952_data { struct max8952_data {
struct i2c_client *client; struct i2c_client *client;
struct max8952_platform_data *pdata; struct max8952_platform_data *pdata;
struct gpio_desc *vid0_gpiod;
struct gpio_desc *vid1_gpiod;
bool vid0; bool vid0;
bool vid1; bool vid1;
}; };
@ -87,16 +86,15 @@ static int max8952_set_voltage_sel(struct regulator_dev *rdev,
{ {
struct max8952_data *max8952 = rdev_get_drvdata(rdev); struct max8952_data *max8952 = rdev_get_drvdata(rdev);
if (!gpio_is_valid(max8952->pdata->gpio_vid0) || if (!max8952->vid0_gpiod || !max8952->vid1_gpiod) {
!gpio_is_valid(max8952->pdata->gpio_vid1)) {
/* DVS not supported */ /* DVS not supported */
return -EPERM; return -EPERM;
} }
max8952->vid0 = selector & 0x1; max8952->vid0 = selector & 0x1;
max8952->vid1 = (selector >> 1) & 0x1; max8952->vid1 = (selector >> 1) & 0x1;
gpio_set_value(max8952->pdata->gpio_vid0, max8952->vid0); gpiod_set_value(max8952->vid0_gpiod, max8952->vid0);
gpio_set_value(max8952->pdata->gpio_vid1, max8952->vid1); gpiod_set_value(max8952->vid1_gpiod, max8952->vid1);
return 0; return 0;
} }
@ -134,9 +132,6 @@ static struct max8952_platform_data *max8952_parse_dt(struct device *dev)
if (!pd) if (!pd)
return NULL; return NULL;
pd->gpio_vid0 = of_get_named_gpio(np, "max8952,vid-gpios", 0);
pd->gpio_vid1 = of_get_named_gpio(np, "max8952,vid-gpios", 1);
if (of_property_read_u32(np, "max8952,default-mode", &pd->default_mode)) if (of_property_read_u32(np, "max8952,default-mode", &pd->default_mode))
dev_warn(dev, "Default mode not specified, assuming 0\n"); dev_warn(dev, "Default mode not specified, assuming 0\n");
@ -179,7 +174,7 @@ static struct max8952_platform_data *max8952_parse_dt(struct device *dev)
static int max8952_pmic_probe(struct i2c_client *client, static int max8952_pmic_probe(struct i2c_client *client,
const struct i2c_device_id *i2c_id) const struct i2c_device_id *i2c_id)
{ {
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = client->adapter;
struct max8952_platform_data *pdata = dev_get_platdata(&client->dev); struct max8952_platform_data *pdata = dev_get_platdata(&client->dev);
struct regulator_config config = { }; struct regulator_config config = { };
struct max8952_data *max8952; struct max8952_data *max8952;
@ -187,7 +182,7 @@ static int max8952_pmic_probe(struct i2c_client *client,
struct gpio_desc *gpiod; struct gpio_desc *gpiod;
enum gpiod_flags gflags; enum gpiod_flags gflags;
int ret = 0, err = 0; int ret = 0;
if (client->dev.of_node) if (client->dev.of_node)
pdata = max8952_parse_dt(&client->dev); pdata = max8952_parse_dt(&client->dev);
@ -240,32 +235,31 @@ static int max8952_pmic_probe(struct i2c_client *client,
max8952->vid0 = pdata->default_mode & 0x1; max8952->vid0 = pdata->default_mode & 0x1;
max8952->vid1 = (pdata->default_mode >> 1) & 0x1; max8952->vid1 = (pdata->default_mode >> 1) & 0x1;
if (gpio_is_valid(pdata->gpio_vid0) && /* Fetch vid0 and vid1 GPIOs if available */
gpio_is_valid(pdata->gpio_vid1)) { gflags = max8952->vid0 ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
unsigned long gpio_flags; max8952->vid0_gpiod = devm_gpiod_get_index_optional(&client->dev,
"max8952,vid",
0, gflags);
if (IS_ERR(max8952->vid0_gpiod))
return PTR_ERR(max8952->vid0_gpiod);
gflags = max8952->vid1 ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
max8952->vid1_gpiod = devm_gpiod_get_index_optional(&client->dev,
"max8952,vid",
1, gflags);
if (IS_ERR(max8952->vid1_gpiod))
return PTR_ERR(max8952->vid1_gpiod);
gpio_flags = max8952->vid0 ? /* If either VID GPIO is missing just disable this */
GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; if (!max8952->vid0_gpiod || !max8952->vid1_gpiod) {
if (devm_gpio_request_one(&client->dev, pdata->gpio_vid0,
gpio_flags, "MAX8952 VID0"))
err = 1;
gpio_flags = max8952->vid1 ?
GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
if (devm_gpio_request_one(&client->dev, pdata->gpio_vid1,
gpio_flags, "MAX8952 VID1"))
err = 2;
} else
err = 3;
if (err) {
dev_warn(&client->dev, "VID0/1 gpio invalid: " dev_warn(&client->dev, "VID0/1 gpio invalid: "
"DVS not available.\n"); "DVS not available.\n");
max8952->vid0 = 0; max8952->vid0 = 0;
max8952->vid1 = 0; max8952->vid1 = 0;
/* Mark invalid */ /* Make sure if we have any descriptors they get set to low */
pdata->gpio_vid0 = -1; if (max8952->vid0_gpiod)
pdata->gpio_vid1 = -1; gpiod_set_value(max8952->vid0_gpiod, 0);
if (max8952->vid1_gpiod)
gpiod_set_value(max8952->vid1_gpiod, 0);
/* Disable Pulldown of EN only */ /* Disable Pulldown of EN only */
max8952_write_reg(max8952, MAX8952_REG_CONTROL, 0x60); max8952_write_reg(max8952, MAX8952_REG_CONTROL, 0x60);

View File

@ -96,6 +96,8 @@ enum spmi_regulator_logical_type {
SPMI_REGULATOR_LOGICAL_TYPE_ULT_LO_SMPS, SPMI_REGULATOR_LOGICAL_TYPE_ULT_LO_SMPS,
SPMI_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS, SPMI_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS,
SPMI_REGULATOR_LOGICAL_TYPE_ULT_LDO, SPMI_REGULATOR_LOGICAL_TYPE_ULT_LDO,
SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS426,
SPMI_REGULATOR_LOGICAL_TYPE_HFS430,
}; };
enum spmi_regulator_type { enum spmi_regulator_type {
@ -142,11 +144,13 @@ enum spmi_regulator_subtype {
SPMI_REGULATOR_SUBTYPE_5V_BOOST = 0x01, SPMI_REGULATOR_SUBTYPE_5V_BOOST = 0x01,
SPMI_REGULATOR_SUBTYPE_FTS_CTL = 0x08, SPMI_REGULATOR_SUBTYPE_FTS_CTL = 0x08,
SPMI_REGULATOR_SUBTYPE_FTS2p5_CTL = 0x09, SPMI_REGULATOR_SUBTYPE_FTS2p5_CTL = 0x09,
SPMI_REGULATOR_SUBTYPE_FTS426_CTL = 0x0a,
SPMI_REGULATOR_SUBTYPE_BB_2A = 0x01, SPMI_REGULATOR_SUBTYPE_BB_2A = 0x01,
SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL1 = 0x0d, SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL1 = 0x0d,
SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL2 = 0x0e, SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL2 = 0x0e,
SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL3 = 0x0f, SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL3 = 0x0f,
SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL4 = 0x10, SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL4 = 0x10,
SPMI_REGULATOR_SUBTYPE_HFS430 = 0x0a,
}; };
enum spmi_common_regulator_registers { enum spmi_common_regulator_registers {
@ -162,6 +166,18 @@ enum spmi_common_regulator_registers {
SPMI_COMMON_REG_STEP_CTRL = 0x61, SPMI_COMMON_REG_STEP_CTRL = 0x61,
}; };
/*
* Second common register layout used by newer devices starting with ftsmps426
* Note that some of the registers from the first common layout remain
* unchanged and their definition is not duplicated.
*/
enum spmi_ftsmps426_regulator_registers {
SPMI_FTSMPS426_REG_VOLTAGE_LSB = 0x40,
SPMI_FTSMPS426_REG_VOLTAGE_MSB = 0x41,
SPMI_FTSMPS426_REG_VOLTAGE_ULS_LSB = 0x68,
SPMI_FTSMPS426_REG_VOLTAGE_ULS_MSB = 0x69,
};
enum spmi_vs_registers { enum spmi_vs_registers {
SPMI_VS_REG_OCP = 0x4a, SPMI_VS_REG_OCP = 0x4a,
SPMI_VS_REG_SOFT_START = 0x4c, SPMI_VS_REG_SOFT_START = 0x4c,
@ -221,6 +237,14 @@ enum spmi_common_control_register_index {
#define SPMI_COMMON_MODE_FOLLOW_HW_EN0_MASK 0x01 #define SPMI_COMMON_MODE_FOLLOW_HW_EN0_MASK 0x01
#define SPMI_COMMON_MODE_FOLLOW_ALL_MASK 0x1f #define SPMI_COMMON_MODE_FOLLOW_ALL_MASK 0x1f
#define SPMI_FTSMPS426_MODE_BYPASS_MASK 3
#define SPMI_FTSMPS426_MODE_RETENTION_MASK 4
#define SPMI_FTSMPS426_MODE_LPM_MASK 5
#define SPMI_FTSMPS426_MODE_AUTO_MASK 6
#define SPMI_FTSMPS426_MODE_HPM_MASK 7
#define SPMI_FTSMPS426_MODE_MASK 0x07
/* Common regulator pull down control register layout */ /* Common regulator pull down control register layout */
#define SPMI_COMMON_PULL_DOWN_ENABLE_MASK 0x80 #define SPMI_COMMON_PULL_DOWN_ENABLE_MASK 0x80
@ -266,6 +290,25 @@ enum spmi_common_control_register_index {
#define SPMI_FTSMPS_STEP_MARGIN_NUM 4 #define SPMI_FTSMPS_STEP_MARGIN_NUM 4
#define SPMI_FTSMPS_STEP_MARGIN_DEN 5 #define SPMI_FTSMPS_STEP_MARGIN_DEN 5
#define SPMI_FTSMPS426_STEP_CTRL_DELAY_MASK 0x03
#define SPMI_FTSMPS426_STEP_CTRL_DELAY_SHIFT 0
/* Clock rate in kHz of the FTSMPS426 regulator reference clock. */
#define SPMI_FTSMPS426_CLOCK_RATE 4800
#define SPMI_HFS430_CLOCK_RATE 1600
/* Minimum voltage stepper delay for each step. */
#define SPMI_FTSMPS426_STEP_DELAY 2
/*
* The ratio SPMI_FTSMPS426_STEP_MARGIN_NUM/SPMI_FTSMPS426_STEP_MARGIN_DEN is
* used to adjust the step rate in order to account for oscillator variance.
*/
#define SPMI_FTSMPS426_STEP_MARGIN_NUM 10
#define SPMI_FTSMPS426_STEP_MARGIN_DEN 11
/* VSET value to decide the range of ULT SMPS */ /* VSET value to decide the range of ULT SMPS */
#define ULT_SMPS_RANGE_SPLIT 0x60 #define ULT_SMPS_RANGE_SPLIT 0x60
@ -439,6 +482,10 @@ static struct spmi_voltage_range ftsmps2p5_ranges[] = {
SPMI_VOLTAGE_RANGE(1, 160000, 1360000, 2200000, 2200000, 10000), SPMI_VOLTAGE_RANGE(1, 160000, 1360000, 2200000, 2200000, 10000),
}; };
static struct spmi_voltage_range ftsmps426_ranges[] = {
SPMI_VOLTAGE_RANGE(0, 0, 320000, 1352000, 1352000, 4000),
};
static struct spmi_voltage_range boost_ranges[] = { static struct spmi_voltage_range boost_ranges[] = {
SPMI_VOLTAGE_RANGE(0, 4000000, 4000000, 5550000, 5550000, 50000), SPMI_VOLTAGE_RANGE(0, 4000000, 4000000, 5550000, 5550000, 50000),
}; };
@ -464,6 +511,10 @@ static struct spmi_voltage_range ult_pldo_ranges[] = {
SPMI_VOLTAGE_RANGE(0, 1750000, 1750000, 3337500, 3337500, 12500), SPMI_VOLTAGE_RANGE(0, 1750000, 1750000, 3337500, 3337500, 12500),
}; };
static struct spmi_voltage_range hfs430_ranges[] = {
SPMI_VOLTAGE_RANGE(0, 320000, 320000, 2040000, 2040000, 8000),
};
static DEFINE_SPMI_SET_POINTS(pldo); static DEFINE_SPMI_SET_POINTS(pldo);
static DEFINE_SPMI_SET_POINTS(nldo1); static DEFINE_SPMI_SET_POINTS(nldo1);
static DEFINE_SPMI_SET_POINTS(nldo2); static DEFINE_SPMI_SET_POINTS(nldo2);
@ -472,12 +523,14 @@ static DEFINE_SPMI_SET_POINTS(ln_ldo);
static DEFINE_SPMI_SET_POINTS(smps); static DEFINE_SPMI_SET_POINTS(smps);
static DEFINE_SPMI_SET_POINTS(ftsmps); static DEFINE_SPMI_SET_POINTS(ftsmps);
static DEFINE_SPMI_SET_POINTS(ftsmps2p5); static DEFINE_SPMI_SET_POINTS(ftsmps2p5);
static DEFINE_SPMI_SET_POINTS(ftsmps426);
static DEFINE_SPMI_SET_POINTS(boost); static DEFINE_SPMI_SET_POINTS(boost);
static DEFINE_SPMI_SET_POINTS(boost_byp); static DEFINE_SPMI_SET_POINTS(boost_byp);
static DEFINE_SPMI_SET_POINTS(ult_lo_smps); static DEFINE_SPMI_SET_POINTS(ult_lo_smps);
static DEFINE_SPMI_SET_POINTS(ult_ho_smps); static DEFINE_SPMI_SET_POINTS(ult_ho_smps);
static DEFINE_SPMI_SET_POINTS(ult_nldo); static DEFINE_SPMI_SET_POINTS(ult_nldo);
static DEFINE_SPMI_SET_POINTS(ult_pldo); static DEFINE_SPMI_SET_POINTS(ult_pldo);
static DEFINE_SPMI_SET_POINTS(hfs430);
static inline int spmi_vreg_read(struct spmi_regulator *vreg, u16 addr, u8 *buf, static inline int spmi_vreg_read(struct spmi_regulator *vreg, u16 addr, u8 *buf,
int len) int len)
@ -739,18 +792,31 @@ spmi_regulator_common_set_voltage(struct regulator_dev *rdev, unsigned selector)
return spmi_vreg_write(vreg, SPMI_COMMON_REG_VOLTAGE_RANGE, buf, 2); return spmi_vreg_write(vreg, SPMI_COMMON_REG_VOLTAGE_RANGE, buf, 2);
} }
static int spmi_regulator_common_list_voltage(struct regulator_dev *rdev,
unsigned selector);
static int spmi_regulator_ftsmps426_set_voltage(struct regulator_dev *rdev,
unsigned selector)
{
struct spmi_regulator *vreg = rdev_get_drvdata(rdev);
u8 buf[2];
int mV;
mV = spmi_regulator_common_list_voltage(rdev, selector) / 1000;
buf[0] = mV & 0xff;
buf[1] = mV >> 8;
return spmi_vreg_write(vreg, SPMI_FTSMPS426_REG_VOLTAGE_LSB, buf, 2);
}
static int spmi_regulator_set_voltage_time_sel(struct regulator_dev *rdev, static int spmi_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
unsigned int old_selector, unsigned int new_selector) unsigned int old_selector, unsigned int new_selector)
{ {
struct spmi_regulator *vreg = rdev_get_drvdata(rdev); struct spmi_regulator *vreg = rdev_get_drvdata(rdev);
const struct spmi_voltage_range *range;
int diff_uV; int diff_uV;
range = spmi_regulator_find_range(vreg); diff_uV = abs(spmi_regulator_common_list_voltage(rdev, new_selector) -
if (!range) spmi_regulator_common_list_voltage(rdev, old_selector));
return -EINVAL;
diff_uV = abs(new_selector - old_selector) * range->step_uV;
return DIV_ROUND_UP(diff_uV, vreg->slew_rate); return DIV_ROUND_UP(diff_uV, vreg->slew_rate);
} }
@ -770,6 +836,21 @@ static int spmi_regulator_common_get_voltage(struct regulator_dev *rdev)
return spmi_hw_selector_to_sw(vreg, voltage_sel, range); return spmi_hw_selector_to_sw(vreg, voltage_sel, range);
} }
static int spmi_regulator_ftsmps426_get_voltage(struct regulator_dev *rdev)
{
struct spmi_regulator *vreg = rdev_get_drvdata(rdev);
const struct spmi_voltage_range *range;
u8 buf[2];
int uV;
spmi_vreg_read(vreg, SPMI_FTSMPS426_REG_VOLTAGE_LSB, buf, 2);
uV = (((unsigned int)buf[1] << 8) | (unsigned int)buf[0]) * 1000;
range = vreg->set_points->range;
return (uV - range->set_point_min_uV) / range->step_uV;
}
static int spmi_regulator_single_map_voltage(struct regulator_dev *rdev, static int spmi_regulator_single_map_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV)
{ {
@ -903,13 +984,33 @@ static unsigned int spmi_regulator_common_get_mode(struct regulator_dev *rdev)
spmi_vreg_read(vreg, SPMI_COMMON_REG_MODE, &reg, 1); spmi_vreg_read(vreg, SPMI_COMMON_REG_MODE, &reg, 1);
if (reg & SPMI_COMMON_MODE_HPM_MASK) reg &= SPMI_COMMON_MODE_HPM_MASK | SPMI_COMMON_MODE_AUTO_MASK;
switch (reg) {
case SPMI_COMMON_MODE_HPM_MASK:
return REGULATOR_MODE_NORMAL; return REGULATOR_MODE_NORMAL;
case SPMI_COMMON_MODE_AUTO_MASK:
if (reg & SPMI_COMMON_MODE_AUTO_MASK)
return REGULATOR_MODE_FAST; return REGULATOR_MODE_FAST;
default:
return REGULATOR_MODE_IDLE;
}
}
return REGULATOR_MODE_IDLE; static unsigned int spmi_regulator_ftsmps426_get_mode(struct regulator_dev *rdev)
{
struct spmi_regulator *vreg = rdev_get_drvdata(rdev);
u8 reg;
spmi_vreg_read(vreg, SPMI_COMMON_REG_MODE, &reg, 1);
switch (reg) {
case SPMI_FTSMPS426_MODE_HPM_MASK:
return REGULATOR_MODE_NORMAL;
case SPMI_FTSMPS426_MODE_AUTO_MASK:
return REGULATOR_MODE_FAST;
default:
return REGULATOR_MODE_IDLE;
}
} }
static int static int
@ -917,12 +1018,43 @@ spmi_regulator_common_set_mode(struct regulator_dev *rdev, unsigned int mode)
{ {
struct spmi_regulator *vreg = rdev_get_drvdata(rdev); struct spmi_regulator *vreg = rdev_get_drvdata(rdev);
u8 mask = SPMI_COMMON_MODE_HPM_MASK | SPMI_COMMON_MODE_AUTO_MASK; u8 mask = SPMI_COMMON_MODE_HPM_MASK | SPMI_COMMON_MODE_AUTO_MASK;
u8 val = 0; u8 val;
if (mode == REGULATOR_MODE_NORMAL) switch (mode) {
case REGULATOR_MODE_NORMAL:
val = SPMI_COMMON_MODE_HPM_MASK; val = SPMI_COMMON_MODE_HPM_MASK;
else if (mode == REGULATOR_MODE_FAST) break;
case REGULATOR_MODE_FAST:
val = SPMI_COMMON_MODE_AUTO_MASK; val = SPMI_COMMON_MODE_AUTO_MASK;
break;
default:
val = 0;
break;
}
return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_MODE, val, mask);
}
static int
spmi_regulator_ftsmps426_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct spmi_regulator *vreg = rdev_get_drvdata(rdev);
u8 mask = SPMI_FTSMPS426_MODE_MASK;
u8 val;
switch (mode) {
case REGULATOR_MODE_NORMAL:
val = SPMI_FTSMPS426_MODE_HPM_MASK;
break;
case REGULATOR_MODE_FAST:
val = SPMI_FTSMPS426_MODE_AUTO_MASK;
break;
case REGULATOR_MODE_IDLE:
val = SPMI_FTSMPS426_MODE_LPM_MASK;
break;
default:
return -EINVAL;
}
return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_MODE, val, mask); return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_MODE, val, mask);
} }
@ -1256,12 +1388,41 @@ static struct regulator_ops spmi_ult_ldo_ops = {
.set_soft_start = spmi_regulator_common_set_soft_start, .set_soft_start = spmi_regulator_common_set_soft_start,
}; };
static struct regulator_ops spmi_ftsmps426_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.set_voltage_sel = spmi_regulator_ftsmps426_set_voltage,
.set_voltage_time_sel = spmi_regulator_set_voltage_time_sel,
.get_voltage_sel = spmi_regulator_ftsmps426_get_voltage,
.map_voltage = spmi_regulator_single_map_voltage,
.list_voltage = spmi_regulator_common_list_voltage,
.set_mode = spmi_regulator_ftsmps426_set_mode,
.get_mode = spmi_regulator_ftsmps426_get_mode,
.set_load = spmi_regulator_common_set_load,
.set_pull_down = spmi_regulator_common_set_pull_down,
};
static struct regulator_ops spmi_hfs430_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.set_voltage_sel = spmi_regulator_ftsmps426_set_voltage,
.set_voltage_time_sel = spmi_regulator_set_voltage_time_sel,
.get_voltage_sel = spmi_regulator_ftsmps426_get_voltage,
.map_voltage = spmi_regulator_single_map_voltage,
.list_voltage = spmi_regulator_common_list_voltage,
.set_mode = spmi_regulator_ftsmps426_set_mode,
.get_mode = spmi_regulator_ftsmps426_get_mode,
};
/* Maximum possible digital major revision value */ /* Maximum possible digital major revision value */
#define INF 0xFF #define INF 0xFF
static const struct spmi_regulator_mapping supported_regulators[] = { static const struct spmi_regulator_mapping supported_regulators[] = {
/* type subtype dig_min dig_max ltype ops setpoints hpm_min */ /* type subtype dig_min dig_max ltype ops setpoints hpm_min */
SPMI_VREG(BUCK, GP_CTL, 0, INF, SMPS, smps, smps, 100000), SPMI_VREG(BUCK, GP_CTL, 0, INF, SMPS, smps, smps, 100000),
SPMI_VREG(BUCK, HFS430, 0, INF, HFS430, hfs430, hfs430, 10000),
SPMI_VREG(LDO, N300, 0, INF, LDO, ldo, nldo1, 10000), SPMI_VREG(LDO, N300, 0, INF, LDO, ldo, nldo1, 10000),
SPMI_VREG(LDO, N600, 0, 0, LDO, ldo, nldo2, 10000), SPMI_VREG(LDO, N600, 0, 0, LDO, ldo, nldo2, 10000),
SPMI_VREG(LDO, N1200, 0, 0, LDO, ldo, nldo2, 10000), SPMI_VREG(LDO, N1200, 0, 0, LDO, ldo, nldo2, 10000),
@ -1291,6 +1452,7 @@ static const struct spmi_regulator_mapping supported_regulators[] = {
SPMI_VREG(BOOST, 5V_BOOST, 0, INF, BOOST, boost, boost, 0), SPMI_VREG(BOOST, 5V_BOOST, 0, INF, BOOST, boost, boost, 0),
SPMI_VREG(FTS, FTS_CTL, 0, INF, FTSMPS, ftsmps, ftsmps, 100000), SPMI_VREG(FTS, FTS_CTL, 0, INF, FTSMPS, ftsmps, ftsmps, 100000),
SPMI_VREG(FTS, FTS2p5_CTL, 0, INF, FTSMPS, ftsmps, ftsmps2p5, 100000), SPMI_VREG(FTS, FTS2p5_CTL, 0, INF, FTSMPS, ftsmps, ftsmps2p5, 100000),
SPMI_VREG(FTS, FTS426_CTL, 0, INF, FTSMPS426, ftsmps426, ftsmps426, 100000),
SPMI_VREG(BOOST_BYP, BB_2A, 0, INF, BOOST_BYP, boost, boost_byp, 0), SPMI_VREG(BOOST_BYP, BB_2A, 0, INF, BOOST_BYP, boost, boost_byp, 0),
SPMI_VREG(ULT_BUCK, ULT_HF_CTL1, 0, INF, ULT_LO_SMPS, ult_lo_smps, SPMI_VREG(ULT_BUCK, ULT_HF_CTL1, 0, INF, ULT_LO_SMPS, ult_lo_smps,
ult_lo_smps, 100000), ult_lo_smps, 100000),
@ -1428,6 +1590,35 @@ static int spmi_regulator_init_slew_rate(struct spmi_regulator *vreg)
return ret; return ret;
} }
static int spmi_regulator_init_slew_rate_ftsmps426(struct spmi_regulator *vreg,
int clock_rate)
{
int ret;
u8 reg = 0;
int delay, slew_rate;
const struct spmi_voltage_range *range = &vreg->set_points->range[0];
ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_STEP_CTRL, &reg, 1);
if (ret) {
dev_err(vreg->dev, "spmi read failed, ret=%d\n", ret);
return ret;
}
delay = reg & SPMI_FTSMPS426_STEP_CTRL_DELAY_MASK;
delay >>= SPMI_FTSMPS426_STEP_CTRL_DELAY_SHIFT;
/* slew_rate has units of uV/us */
slew_rate = clock_rate * range->step_uV;
slew_rate /= 1000 * (SPMI_FTSMPS426_STEP_DELAY << delay);
slew_rate *= SPMI_FTSMPS426_STEP_MARGIN_NUM;
slew_rate /= SPMI_FTSMPS426_STEP_MARGIN_DEN;
/* Ensure that the slew rate is greater than 0 */
vreg->slew_rate = max(slew_rate, 1);
return ret;
}
static int spmi_regulator_init_registers(struct spmi_regulator *vreg, static int spmi_regulator_init_registers(struct spmi_regulator *vreg,
const struct spmi_regulator_init_data *data) const struct spmi_regulator_init_data *data)
{ {
@ -1567,6 +1758,19 @@ static int spmi_regulator_of_parse(struct device_node *node,
ret = spmi_regulator_init_slew_rate(vreg); ret = spmi_regulator_init_slew_rate(vreg);
if (ret) if (ret)
return ret; return ret;
break;
case SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS426:
ret = spmi_regulator_init_slew_rate_ftsmps426(vreg,
SPMI_FTSMPS426_CLOCK_RATE);
if (ret)
return ret;
break;
case SPMI_REGULATOR_LOGICAL_TYPE_HFS430:
ret = spmi_regulator_init_slew_rate_ftsmps426(vreg,
SPMI_HFS430_CLOCK_RATE);
if (ret)
return ret;
break;
default: default:
break; break;
} }
@ -1723,12 +1927,27 @@ static const struct spmi_regulator_data pmi8994_regulators[] = {
{ } { }
}; };
static const struct spmi_regulator_data pm8005_regulators[] = {
{ "s1", 0x1400, "vdd_s1", },
{ "s2", 0x1700, "vdd_s2", },
{ "s3", 0x1a00, "vdd_s3", },
{ "s4", 0x1d00, "vdd_s4", },
{ }
};
static const struct spmi_regulator_data pms405_regulators[] = {
{ "s3", 0x1a00, "vdd_s3"},
{ }
};
static const struct of_device_id qcom_spmi_regulator_match[] = { static const struct of_device_id qcom_spmi_regulator_match[] = {
{ .compatible = "qcom,pm8005-regulators", .data = &pm8005_regulators },
{ .compatible = "qcom,pm8841-regulators", .data = &pm8841_regulators }, { .compatible = "qcom,pm8841-regulators", .data = &pm8841_regulators },
{ .compatible = "qcom,pm8916-regulators", .data = &pm8916_regulators }, { .compatible = "qcom,pm8916-regulators", .data = &pm8916_regulators },
{ .compatible = "qcom,pm8941-regulators", .data = &pm8941_regulators }, { .compatible = "qcom,pm8941-regulators", .data = &pm8941_regulators },
{ .compatible = "qcom,pm8994-regulators", .data = &pm8994_regulators }, { .compatible = "qcom,pm8994-regulators", .data = &pm8994_regulators },
{ .compatible = "qcom,pmi8994-regulators", .data = &pmi8994_regulators }, { .compatible = "qcom,pmi8994-regulators", .data = &pmi8994_regulators },
{ .compatible = "qcom,pms405-regulators", .data = &pms405_regulators },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, qcom_spmi_regulator_match); MODULE_DEVICE_TABLE(of, qcom_spmi_regulator_match);
@ -1736,6 +1955,7 @@ MODULE_DEVICE_TABLE(of, qcom_spmi_regulator_match);
static int qcom_spmi_regulator_probe(struct platform_device *pdev) static int qcom_spmi_regulator_probe(struct platform_device *pdev)
{ {
const struct spmi_regulator_data *reg; const struct spmi_regulator_data *reg;
const struct spmi_voltage_range *range;
const struct of_device_id *match; const struct of_device_id *match;
struct regulator_config config = { }; struct regulator_config config = { };
struct regulator_dev *rdev; struct regulator_dev *rdev;
@ -1825,6 +2045,12 @@ static int qcom_spmi_regulator_probe(struct platform_device *pdev)
} }
} }
if (vreg->set_points && vreg->set_points->count == 1) {
/* since there is only one range */
range = vreg->set_points->range;
vreg->desc.uV_step = range->step_uV;
}
config.dev = dev; config.dev = dev;
config.driver_data = vreg; config.driver_data = vreg;
config.regmap = regmap; config.regmap = regmap;

View File

@ -34,7 +34,7 @@ struct s2mps11_info {
enum sec_device_type dev_type; enum sec_device_type dev_type;
/* /*
* One bit for each S2MPS13/S2MPS14/S2MPU02 regulator whether * One bit for each S2MPS11/S2MPS13/S2MPS14/S2MPU02 regulator whether
* the suspend mode was enabled. * the suspend mode was enabled.
*/ */
DECLARE_BITMAP(suspend_state, S2MPS_REGULATOR_MAX); DECLARE_BITMAP(suspend_state, S2MPS_REGULATOR_MAX);
@ -70,10 +70,11 @@ static int s2mps11_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
unsigned int new_selector) unsigned int new_selector)
{ {
struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
int rdev_id = rdev_get_id(rdev);
unsigned int ramp_delay = 0; unsigned int ramp_delay = 0;
int old_volt, new_volt; int old_volt, new_volt;
switch (rdev_get_id(rdev)) { switch (rdev_id) {
case S2MPS11_BUCK2: case S2MPS11_BUCK2:
ramp_delay = s2mps11->ramp_delay2; ramp_delay = s2mps11->ramp_delay2;
break; break;
@ -111,9 +112,10 @@ static int s2mps11_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
unsigned int ramp_val, ramp_shift, ramp_reg = S2MPS11_REG_RAMP_BUCK; unsigned int ramp_val, ramp_shift, ramp_reg = S2MPS11_REG_RAMP_BUCK;
unsigned int ramp_enable = 1, enable_shift = 0; unsigned int ramp_enable = 1, enable_shift = 0;
int rdev_id = rdev_get_id(rdev);
int ret; int ret;
switch (rdev_get_id(rdev)) { switch (rdev_id) {
case S2MPS11_BUCK1: case S2MPS11_BUCK1:
if (ramp_delay > s2mps11->ramp_delay16) if (ramp_delay > s2mps11->ramp_delay16)
s2mps11->ramp_delay16 = ramp_delay; s2mps11->ramp_delay16 = ramp_delay;
@ -203,9 +205,8 @@ static int s2mps11_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
goto ramp_disable; goto ramp_disable;
/* Ramp delay can be enabled/disabled only for buck[2346] */ /* Ramp delay can be enabled/disabled only for buck[2346] */
if ((rdev_get_id(rdev) >= S2MPS11_BUCK2 && if ((rdev_id >= S2MPS11_BUCK2 && rdev_id <= S2MPS11_BUCK4) ||
rdev_get_id(rdev) <= S2MPS11_BUCK4) || rdev_id == S2MPS11_BUCK6) {
rdev_get_id(rdev) == S2MPS11_BUCK6) {
ret = regmap_update_bits(rdev->regmap, S2MPS11_REG_RAMP, ret = regmap_update_bits(rdev->regmap, S2MPS11_REG_RAMP,
1 << enable_shift, 1 << enable_shift); 1 << enable_shift, 1 << enable_shift);
if (ret) { if (ret) {
@ -224,27 +225,133 @@ ramp_disable:
1 << enable_shift, 0); 1 << enable_shift, 0);
} }
static int s2mps11_regulator_enable(struct regulator_dev *rdev)
{
struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
int rdev_id = rdev_get_id(rdev);
unsigned int val;
switch (s2mps11->dev_type) {
case S2MPS11X:
if (test_bit(rdev_id, s2mps11->suspend_state))
val = S2MPS14_ENABLE_SUSPEND;
else
val = rdev->desc->enable_mask;
break;
case S2MPS13X:
case S2MPS14X:
if (test_bit(rdev_id, s2mps11->suspend_state))
val = S2MPS14_ENABLE_SUSPEND;
else if (s2mps11->ext_control_gpiod[rdev_id])
val = S2MPS14_ENABLE_EXT_CONTROL;
else
val = rdev->desc->enable_mask;
break;
case S2MPU02:
if (test_bit(rdev_id, s2mps11->suspend_state))
val = S2MPU02_ENABLE_SUSPEND;
else
val = rdev->desc->enable_mask;
break;
default:
return -EINVAL;
}
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, val);
}
static int s2mps11_regulator_set_suspend_disable(struct regulator_dev *rdev)
{
int ret;
unsigned int val, state;
struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
int rdev_id = rdev_get_id(rdev);
/* Below LDO should be always on or does not support suspend mode. */
switch (s2mps11->dev_type) {
case S2MPS11X:
switch (rdev_id) {
case S2MPS11_LDO2:
case S2MPS11_LDO36:
case S2MPS11_LDO37:
case S2MPS11_LDO38:
return 0;
default:
state = S2MPS14_ENABLE_SUSPEND;
break;
}
break;
case S2MPS13X:
case S2MPS14X:
switch (rdev_id) {
case S2MPS14_LDO3:
return 0;
default:
state = S2MPS14_ENABLE_SUSPEND;
break;
}
break;
case S2MPU02:
switch (rdev_id) {
case S2MPU02_LDO13:
case S2MPU02_LDO14:
case S2MPU02_LDO15:
case S2MPU02_LDO17:
case S2MPU02_BUCK7:
state = S2MPU02_DISABLE_SUSPEND;
break;
default:
state = S2MPU02_ENABLE_SUSPEND;
break;
}
break;
default:
return -EINVAL;
}
ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
if (ret < 0)
return ret;
set_bit(rdev_id, s2mps11->suspend_state);
/*
* Don't enable suspend mode if regulator is already disabled because
* this would effectively for a short time turn on the regulator after
* resuming.
* However we still want to toggle the suspend_state bit for regulator
* in case if it got enabled before suspending the system.
*/
if (!(val & rdev->desc->enable_mask))
return 0;
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, state);
}
static const struct regulator_ops s2mps11_ldo_ops = { static const struct regulator_ops s2mps11_ldo_ops = {
.list_voltage = regulator_list_voltage_linear, .list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear, .map_voltage = regulator_map_voltage_linear,
.is_enabled = regulator_is_enabled_regmap, .is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap, .enable = s2mps11_regulator_enable,
.disable = regulator_disable_regmap, .disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel, .set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_suspend_disable = s2mps11_regulator_set_suspend_disable,
}; };
static const struct regulator_ops s2mps11_buck_ops = { static const struct regulator_ops s2mps11_buck_ops = {
.list_voltage = regulator_list_voltage_linear, .list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear, .map_voltage = regulator_map_voltage_linear,
.is_enabled = regulator_is_enabled_regmap, .is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap, .enable = s2mps11_regulator_enable,
.disable = regulator_disable_regmap, .disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = s2mps11_regulator_set_voltage_time_sel, .set_voltage_time_sel = s2mps11_regulator_set_voltage_time_sel,
.set_ramp_delay = s2mps11_set_ramp_delay, .set_ramp_delay = s2mps11_set_ramp_delay,
.set_suspend_disable = s2mps11_regulator_set_suspend_disable,
}; };
#define regulator_desc_s2mps11_ldo(num, step) { \ #define regulator_desc_s2mps11_ldo(num, step) { \
@ -507,101 +614,16 @@ static const struct regulator_desc s2mps13_regulators[] = {
regulator_desc_s2mps13_buck8_10(10, MIN_500_MV, STEP_6_25_MV, 0x10), regulator_desc_s2mps13_buck8_10(10, MIN_500_MV, STEP_6_25_MV, 0x10),
}; };
static int s2mps14_regulator_enable(struct regulator_dev *rdev)
{
struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
unsigned int val;
switch (s2mps11->dev_type) {
case S2MPS13X:
case S2MPS14X:
if (test_bit(rdev_get_id(rdev), s2mps11->suspend_state))
val = S2MPS14_ENABLE_SUSPEND;
else if (s2mps11->ext_control_gpiod[rdev_get_id(rdev)])
val = S2MPS14_ENABLE_EXT_CONTROL;
else
val = rdev->desc->enable_mask;
break;
case S2MPU02:
if (test_bit(rdev_get_id(rdev), s2mps11->suspend_state))
val = S2MPU02_ENABLE_SUSPEND;
else
val = rdev->desc->enable_mask;
break;
default:
return -EINVAL;
}
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, val);
}
static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev)
{
int ret;
unsigned int val, state;
struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
int rdev_id = rdev_get_id(rdev);
/* Below LDO should be always on or does not support suspend mode. */
switch (s2mps11->dev_type) {
case S2MPS13X:
case S2MPS14X:
switch (rdev_id) {
case S2MPS14_LDO3:
return 0;
default:
state = S2MPS14_ENABLE_SUSPEND;
break;
}
break;
case S2MPU02:
switch (rdev_id) {
case S2MPU02_LDO13:
case S2MPU02_LDO14:
case S2MPU02_LDO15:
case S2MPU02_LDO17:
case S2MPU02_BUCK7:
state = S2MPU02_DISABLE_SUSPEND;
break;
default:
state = S2MPU02_ENABLE_SUSPEND;
break;
}
break;
default:
return -EINVAL;
}
ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
if (ret < 0)
return ret;
set_bit(rdev_get_id(rdev), s2mps11->suspend_state);
/*
* Don't enable suspend mode if regulator is already disabled because
* this would effectively for a short time turn on the regulator after
* resuming.
* However we still want to toggle the suspend_state bit for regulator
* in case if it got enabled before suspending the system.
*/
if (!(val & rdev->desc->enable_mask))
return 0;
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, state);
}
static const struct regulator_ops s2mps14_reg_ops = { static const struct regulator_ops s2mps14_reg_ops = {
.list_voltage = regulator_list_voltage_linear, .list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear, .map_voltage = regulator_map_voltage_linear,
.is_enabled = regulator_is_enabled_regmap, .is_enabled = regulator_is_enabled_regmap,
.enable = s2mps14_regulator_enable, .enable = s2mps11_regulator_enable,
.disable = regulator_disable_regmap, .disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel, .set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_suspend_disable = s2mps14_regulator_set_suspend_disable, .set_suspend_disable = s2mps11_regulator_set_suspend_disable,
}; };
#define regulator_desc_s2mps14_ldo(num, min, step) { \ #define regulator_desc_s2mps14_ldo(num, min, step) { \
@ -828,7 +850,9 @@ static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev,
0, 0,
GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE, GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
"s2mps11-regulator"); "s2mps11-regulator");
if (IS_ERR(gpio[reg])) { if (PTR_ERR(gpio[reg]) == -ENOENT)
gpio[reg] = NULL;
else if (IS_ERR(gpio[reg])) {
dev_err(&pdev->dev, "Failed to get control GPIO for %d/%s\n", dev_err(&pdev->dev, "Failed to get control GPIO for %d/%s\n",
reg, rdata[reg].name); reg, rdata[reg].name);
gpio[reg] = NULL; gpio[reg] = NULL;
@ -864,8 +888,9 @@ static int s2mps11_pmic_dt_parse(struct platform_device *pdev,
static int s2mpu02_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) static int s2mpu02_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
{ {
unsigned int ramp_val, ramp_shift, ramp_reg; unsigned int ramp_val, ramp_shift, ramp_reg;
int rdev_id = rdev_get_id(rdev);
switch (rdev_get_id(rdev)) { switch (rdev_id) {
case S2MPU02_BUCK1: case S2MPU02_BUCK1:
ramp_shift = S2MPU02_BUCK1_RAMP_SHIFT; ramp_shift = S2MPU02_BUCK1_RAMP_SHIFT;
break; break;
@ -893,24 +918,24 @@ static const struct regulator_ops s2mpu02_ldo_ops = {
.list_voltage = regulator_list_voltage_linear, .list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear, .map_voltage = regulator_map_voltage_linear,
.is_enabled = regulator_is_enabled_regmap, .is_enabled = regulator_is_enabled_regmap,
.enable = s2mps14_regulator_enable, .enable = s2mps11_regulator_enable,
.disable = regulator_disable_regmap, .disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel, .set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_suspend_disable = s2mps14_regulator_set_suspend_disable, .set_suspend_disable = s2mps11_regulator_set_suspend_disable,
}; };
static const struct regulator_ops s2mpu02_buck_ops = { static const struct regulator_ops s2mpu02_buck_ops = {
.list_voltage = regulator_list_voltage_linear, .list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear, .map_voltage = regulator_map_voltage_linear,
.is_enabled = regulator_is_enabled_regmap, .is_enabled = regulator_is_enabled_regmap,
.enable = s2mps14_regulator_enable, .enable = s2mps11_regulator_enable,
.disable = regulator_disable_regmap, .disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel, .set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_suspend_disable = s2mps14_regulator_set_suspend_disable, .set_suspend_disable = s2mps11_regulator_set_suspend_disable,
.set_ramp_delay = s2mpu02_set_ramp_delay, .set_ramp_delay = s2mpu02_set_ramp_delay,
}; };

View File

@ -574,7 +574,9 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
0, 0,
GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE, GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
"s5m8767"); "s5m8767");
if (IS_ERR(rdata->ext_control_gpiod)) if (PTR_ERR(rdata->ext_control_gpiod) == -ENOENT)
rdata->ext_control_gpiod = NULL;
else if (IS_ERR(rdata->ext_control_gpiod))
return PTR_ERR(rdata->ext_control_gpiod); return PTR_ERR(rdata->ext_control_gpiod);
rdata->id = i; rdata->id = i;

View File

@ -0,0 +1,523 @@
// SPDX-License-Identifier: GPL-2.0+
//
// SLG51000 High PSRR, Multi-Output Regulators
// Copyright (C) 2019 Dialog Semiconductor
//
// Author: Eric Jeong <eric.jeong.opensource@diasemi.com>
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include "slg51000-regulator.h"
#define SLG51000_SCTL_EVT 7
#define SLG51000_MAX_EVT_REGISTER 8
#define SLG51000_LDOHP_LV_MIN 1200000
#define SLG51000_LDOHP_HV_MIN 2400000
enum slg51000_regulators {
SLG51000_REGULATOR_LDO1 = 0,
SLG51000_REGULATOR_LDO2,
SLG51000_REGULATOR_LDO3,
SLG51000_REGULATOR_LDO4,
SLG51000_REGULATOR_LDO5,
SLG51000_REGULATOR_LDO6,
SLG51000_REGULATOR_LDO7,
SLG51000_MAX_REGULATORS,
};
struct slg51000 {
struct device *dev;
struct regmap *regmap;
struct regulator_desc *rdesc[SLG51000_MAX_REGULATORS];
struct regulator_dev *rdev[SLG51000_MAX_REGULATORS];
struct gpio_desc *cs_gpiod;
int chip_irq;
};
struct slg51000_evt_sta {
unsigned int ereg;
unsigned int sreg;
};
static const struct slg51000_evt_sta es_reg[SLG51000_MAX_EVT_REGISTER] = {
{SLG51000_LDO1_EVENT, SLG51000_LDO1_STATUS},
{SLG51000_LDO2_EVENT, SLG51000_LDO2_STATUS},
{SLG51000_LDO3_EVENT, SLG51000_LDO3_STATUS},
{SLG51000_LDO4_EVENT, SLG51000_LDO4_STATUS},
{SLG51000_LDO5_EVENT, SLG51000_LDO5_STATUS},
{SLG51000_LDO6_EVENT, SLG51000_LDO6_STATUS},
{SLG51000_LDO7_EVENT, SLG51000_LDO7_STATUS},
{SLG51000_SYSCTL_EVENT, SLG51000_SYSCTL_STATUS},
};
static const struct regmap_range slg51000_writeable_ranges[] = {
regmap_reg_range(SLG51000_SYSCTL_MATRIX_CONF_A,
SLG51000_SYSCTL_MATRIX_CONF_A),
regmap_reg_range(SLG51000_LDO1_VSEL, SLG51000_LDO1_VSEL),
regmap_reg_range(SLG51000_LDO1_MINV, SLG51000_LDO1_MAXV),
regmap_reg_range(SLG51000_LDO1_IRQ_MASK, SLG51000_LDO1_IRQ_MASK),
regmap_reg_range(SLG51000_LDO2_VSEL, SLG51000_LDO2_VSEL),
regmap_reg_range(SLG51000_LDO2_MINV, SLG51000_LDO2_MAXV),
regmap_reg_range(SLG51000_LDO2_IRQ_MASK, SLG51000_LDO2_IRQ_MASK),
regmap_reg_range(SLG51000_LDO3_VSEL, SLG51000_LDO3_VSEL),
regmap_reg_range(SLG51000_LDO3_MINV, SLG51000_LDO3_MAXV),
regmap_reg_range(SLG51000_LDO3_IRQ_MASK, SLG51000_LDO3_IRQ_MASK),
regmap_reg_range(SLG51000_LDO4_VSEL, SLG51000_LDO4_VSEL),
regmap_reg_range(SLG51000_LDO4_MINV, SLG51000_LDO4_MAXV),
regmap_reg_range(SLG51000_LDO4_IRQ_MASK, SLG51000_LDO4_IRQ_MASK),
regmap_reg_range(SLG51000_LDO5_VSEL, SLG51000_LDO5_VSEL),
regmap_reg_range(SLG51000_LDO5_MINV, SLG51000_LDO5_MAXV),
regmap_reg_range(SLG51000_LDO5_IRQ_MASK, SLG51000_LDO5_IRQ_MASK),
regmap_reg_range(SLG51000_LDO6_VSEL, SLG51000_LDO6_VSEL),
regmap_reg_range(SLG51000_LDO6_MINV, SLG51000_LDO6_MAXV),
regmap_reg_range(SLG51000_LDO6_IRQ_MASK, SLG51000_LDO6_IRQ_MASK),
regmap_reg_range(SLG51000_LDO7_VSEL, SLG51000_LDO7_VSEL),
regmap_reg_range(SLG51000_LDO7_MINV, SLG51000_LDO7_MAXV),
regmap_reg_range(SLG51000_LDO7_IRQ_MASK, SLG51000_LDO7_IRQ_MASK),
regmap_reg_range(SLG51000_OTP_IRQ_MASK, SLG51000_OTP_IRQ_MASK),
};
static const struct regmap_range slg51000_readable_ranges[] = {
regmap_reg_range(SLG51000_SYSCTL_PATN_ID_B0,
SLG51000_SYSCTL_PATN_ID_B2),
regmap_reg_range(SLG51000_SYSCTL_SYS_CONF_A,
SLG51000_SYSCTL_SYS_CONF_A),
regmap_reg_range(SLG51000_SYSCTL_SYS_CONF_D,
SLG51000_SYSCTL_MATRIX_CONF_B),
regmap_reg_range(SLG51000_SYSCTL_REFGEN_CONF_C,
SLG51000_SYSCTL_UVLO_CONF_A),
regmap_reg_range(SLG51000_SYSCTL_FAULT_LOG1, SLG51000_SYSCTL_IRQ_MASK),
regmap_reg_range(SLG51000_IO_GPIO1_CONF, SLG51000_IO_GPIO_STATUS),
regmap_reg_range(SLG51000_LUTARRAY_LUT_VAL_0,
SLG51000_LUTARRAY_LUT_VAL_11),
regmap_reg_range(SLG51000_MUXARRAY_INPUT_SEL_0,
SLG51000_MUXARRAY_INPUT_SEL_63),
regmap_reg_range(SLG51000_PWRSEQ_RESOURCE_EN_0,
SLG51000_PWRSEQ_INPUT_SENSE_CONF_B),
regmap_reg_range(SLG51000_LDO1_VSEL, SLG51000_LDO1_VSEL),
regmap_reg_range(SLG51000_LDO1_MINV, SLG51000_LDO1_MAXV),
regmap_reg_range(SLG51000_LDO1_MISC1, SLG51000_LDO1_VSEL_ACTUAL),
regmap_reg_range(SLG51000_LDO1_EVENT, SLG51000_LDO1_IRQ_MASK),
regmap_reg_range(SLG51000_LDO2_VSEL, SLG51000_LDO2_VSEL),
regmap_reg_range(SLG51000_LDO2_MINV, SLG51000_LDO2_MAXV),
regmap_reg_range(SLG51000_LDO2_MISC1, SLG51000_LDO2_VSEL_ACTUAL),
regmap_reg_range(SLG51000_LDO2_EVENT, SLG51000_LDO2_IRQ_MASK),
regmap_reg_range(SLG51000_LDO3_VSEL, SLG51000_LDO3_VSEL),
regmap_reg_range(SLG51000_LDO3_MINV, SLG51000_LDO3_MAXV),
regmap_reg_range(SLG51000_LDO3_CONF1, SLG51000_LDO3_VSEL_ACTUAL),
regmap_reg_range(SLG51000_LDO3_EVENT, SLG51000_LDO3_IRQ_MASK),
regmap_reg_range(SLG51000_LDO4_VSEL, SLG51000_LDO4_VSEL),
regmap_reg_range(SLG51000_LDO4_MINV, SLG51000_LDO4_MAXV),
regmap_reg_range(SLG51000_LDO4_CONF1, SLG51000_LDO4_VSEL_ACTUAL),
regmap_reg_range(SLG51000_LDO4_EVENT, SLG51000_LDO4_IRQ_MASK),
regmap_reg_range(SLG51000_LDO5_VSEL, SLG51000_LDO5_VSEL),
regmap_reg_range(SLG51000_LDO5_MINV, SLG51000_LDO5_MAXV),
regmap_reg_range(SLG51000_LDO5_TRIM2, SLG51000_LDO5_TRIM2),
regmap_reg_range(SLG51000_LDO5_CONF1, SLG51000_LDO5_VSEL_ACTUAL),
regmap_reg_range(SLG51000_LDO5_EVENT, SLG51000_LDO5_IRQ_MASK),
regmap_reg_range(SLG51000_LDO6_VSEL, SLG51000_LDO6_VSEL),
regmap_reg_range(SLG51000_LDO6_MINV, SLG51000_LDO6_MAXV),
regmap_reg_range(SLG51000_LDO6_TRIM2, SLG51000_LDO6_TRIM2),
regmap_reg_range(SLG51000_LDO6_CONF1, SLG51000_LDO6_VSEL_ACTUAL),
regmap_reg_range(SLG51000_LDO6_EVENT, SLG51000_LDO6_IRQ_MASK),
regmap_reg_range(SLG51000_LDO7_VSEL, SLG51000_LDO7_VSEL),
regmap_reg_range(SLG51000_LDO7_MINV, SLG51000_LDO7_MAXV),
regmap_reg_range(SLG51000_LDO7_CONF1, SLG51000_LDO7_VSEL_ACTUAL),
regmap_reg_range(SLG51000_LDO7_EVENT, SLG51000_LDO7_IRQ_MASK),
regmap_reg_range(SLG51000_OTP_EVENT, SLG51000_OTP_EVENT),
regmap_reg_range(SLG51000_OTP_IRQ_MASK, SLG51000_OTP_IRQ_MASK),
regmap_reg_range(SLG51000_OTP_LOCK_OTP_PROG, SLG51000_OTP_LOCK_CTRL),
regmap_reg_range(SLG51000_LOCK_GLOBAL_LOCK_CTRL1,
SLG51000_LOCK_GLOBAL_LOCK_CTRL1),
};
static const struct regmap_range slg51000_volatile_ranges[] = {
regmap_reg_range(SLG51000_SYSCTL_FAULT_LOG1, SLG51000_SYSCTL_STATUS),
regmap_reg_range(SLG51000_IO_GPIO_STATUS, SLG51000_IO_GPIO_STATUS),
regmap_reg_range(SLG51000_LDO1_EVENT, SLG51000_LDO1_STATUS),
regmap_reg_range(SLG51000_LDO2_EVENT, SLG51000_LDO2_STATUS),
regmap_reg_range(SLG51000_LDO3_EVENT, SLG51000_LDO3_STATUS),
regmap_reg_range(SLG51000_LDO4_EVENT, SLG51000_LDO4_STATUS),
regmap_reg_range(SLG51000_LDO5_EVENT, SLG51000_LDO5_STATUS),
regmap_reg_range(SLG51000_LDO6_EVENT, SLG51000_LDO6_STATUS),
regmap_reg_range(SLG51000_LDO7_EVENT, SLG51000_LDO7_STATUS),
regmap_reg_range(SLG51000_OTP_EVENT, SLG51000_OTP_EVENT),
};
static const struct regmap_access_table slg51000_writeable_table = {
.yes_ranges = slg51000_writeable_ranges,
.n_yes_ranges = ARRAY_SIZE(slg51000_writeable_ranges),
};
static const struct regmap_access_table slg51000_readable_table = {
.yes_ranges = slg51000_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(slg51000_readable_ranges),
};
static const struct regmap_access_table slg51000_volatile_table = {
.yes_ranges = slg51000_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(slg51000_volatile_ranges),
};
static const struct regmap_config slg51000_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.max_register = 0x8000,
.wr_table = &slg51000_writeable_table,
.rd_table = &slg51000_readable_table,
.volatile_table = &slg51000_volatile_table,
};
static const struct regulator_ops slg51000_regl_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
};
static const struct regulator_ops slg51000_switch_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
};
static int slg51000_of_parse_cb(struct device_node *np,
const struct regulator_desc *desc,
struct regulator_config *config)
{
struct slg51000 *chip = config->driver_data;
struct gpio_desc *ena_gpiod;
enum gpiod_flags gflags = GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE;
ena_gpiod = devm_gpiod_get_from_of_node(chip->dev, np,
"enable-gpios", 0,
gflags, "gpio-en-ldo");
if (ena_gpiod) {
config->ena_gpiod = ena_gpiod;
devm_gpiod_unhinge(chip->dev, config->ena_gpiod);
}
return 0;
}
#define SLG51000_REGL_DESC(_id, _name, _s_name, _min, _step) \
[SLG51000_REGULATOR_##_id] = { \
.name = #_name, \
.supply_name = _s_name, \
.id = SLG51000_REGULATOR_##_id, \
.of_match = of_match_ptr(#_name), \
.of_parse_cb = slg51000_of_parse_cb, \
.ops = &slg51000_regl_ops, \
.regulators_node = of_match_ptr("regulators"), \
.n_voltages = 256, \
.min_uV = _min, \
.uV_step = _step, \
.linear_min_sel = 0, \
.vsel_mask = SLG51000_VSEL_MASK, \
.vsel_reg = SLG51000_##_id##_VSEL, \
.enable_reg = SLG51000_SYSCTL_MATRIX_CONF_A, \
.enable_mask = BIT(SLG51000_REGULATOR_##_id), \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}
static struct regulator_desc regls_desc[SLG51000_MAX_REGULATORS] = {
SLG51000_REGL_DESC(LDO1, ldo1, NULL, 2400000, 5000),
SLG51000_REGL_DESC(LDO2, ldo2, NULL, 2400000, 5000),
SLG51000_REGL_DESC(LDO3, ldo3, "vin3", 1200000, 10000),
SLG51000_REGL_DESC(LDO4, ldo4, "vin4", 1200000, 10000),
SLG51000_REGL_DESC(LDO5, ldo5, "vin5", 400000, 5000),
SLG51000_REGL_DESC(LDO6, ldo6, "vin6", 400000, 5000),
SLG51000_REGL_DESC(LDO7, ldo7, "vin7", 1200000, 10000),
};
static int slg51000_regulator_init(struct slg51000 *chip)
{
struct regulator_config config = { };
struct regulator_desc *rdesc;
unsigned int reg, val;
u8 vsel_range[2];
int id, ret = 0;
const unsigned int min_regs[SLG51000_MAX_REGULATORS] = {
SLG51000_LDO1_MINV, SLG51000_LDO2_MINV, SLG51000_LDO3_MINV,
SLG51000_LDO4_MINV, SLG51000_LDO5_MINV, SLG51000_LDO6_MINV,
SLG51000_LDO7_MINV,
};
for (id = 0; id < SLG51000_MAX_REGULATORS; id++) {
chip->rdesc[id] = &regls_desc[id];
rdesc = chip->rdesc[id];
config.regmap = chip->regmap;
config.dev = chip->dev;
config.driver_data = chip;
ret = regmap_bulk_read(chip->regmap, min_regs[id],
vsel_range, 2);
if (ret < 0) {
dev_err(chip->dev,
"Failed to read the MIN register\n");
return ret;
}
switch (id) {
case SLG51000_REGULATOR_LDO1:
case SLG51000_REGULATOR_LDO2:
if (id == SLG51000_REGULATOR_LDO1)
reg = SLG51000_LDO1_MISC1;
else
reg = SLG51000_LDO2_MISC1;
ret = regmap_read(chip->regmap, reg, &val);
if (ret < 0) {
dev_err(chip->dev,
"Failed to read voltage range of ldo%d\n",
id + 1);
return ret;
}
rdesc->linear_min_sel = vsel_range[0];
rdesc->n_voltages = vsel_range[1] + 1;
if (val & SLG51000_SEL_VRANGE_MASK)
rdesc->min_uV = SLG51000_LDOHP_HV_MIN
+ (vsel_range[0]
* rdesc->uV_step);
else
rdesc->min_uV = SLG51000_LDOHP_LV_MIN
+ (vsel_range[0]
* rdesc->uV_step);
break;
case SLG51000_REGULATOR_LDO5:
case SLG51000_REGULATOR_LDO6:
if (id == SLG51000_REGULATOR_LDO5)
reg = SLG51000_LDO5_TRIM2;
else
reg = SLG51000_LDO6_TRIM2;
ret = regmap_read(chip->regmap, reg, &val);
if (ret < 0) {
dev_err(chip->dev,
"Failed to read LDO mode register\n");
return ret;
}
if (val & SLG51000_SEL_BYP_MODE_MASK) {
rdesc->ops = &slg51000_switch_ops;
rdesc->n_voltages = 0;
rdesc->min_uV = 0;
rdesc->uV_step = 0;
rdesc->linear_min_sel = 0;
break;
}
/* Fall through - to the check below.*/
default:
rdesc->linear_min_sel = vsel_range[0];
rdesc->n_voltages = vsel_range[1] + 1;
rdesc->min_uV = rdesc->min_uV
+ (vsel_range[0] * rdesc->uV_step);
break;
}
chip->rdev[id] = devm_regulator_register(chip->dev, rdesc,
&config);
if (IS_ERR(chip->rdev[id])) {
ret = PTR_ERR(chip->rdev[id]);
dev_err(chip->dev,
"Failed to register regulator(%s):%d\n",
chip->rdesc[id]->name, ret);
return ret;
}
}
return 0;
}
static irqreturn_t slg51000_irq_handler(int irq, void *data)
{
struct slg51000 *chip = data;
struct regmap *regmap = chip->regmap;
enum { R0 = 0, R1, R2, REG_MAX };
u8 evt[SLG51000_MAX_EVT_REGISTER][REG_MAX];
int ret, i, handled = IRQ_NONE;
unsigned int evt_otp, mask_otp;
/* Read event[R0], status[R1] and mask[R2] register */
for (i = 0; i < SLG51000_MAX_EVT_REGISTER; i++) {
ret = regmap_bulk_read(regmap, es_reg[i].ereg, evt[i], REG_MAX);
if (ret < 0) {
dev_err(chip->dev,
"Failed to read event registers(%d)\n", ret);
return IRQ_NONE;
}
}
ret = regmap_read(regmap, SLG51000_OTP_EVENT, &evt_otp);
if (ret < 0) {
dev_err(chip->dev,
"Failed to read otp event registers(%d)\n", ret);
return IRQ_NONE;
}
ret = regmap_read(regmap, SLG51000_OTP_IRQ_MASK, &mask_otp);
if (ret < 0) {
dev_err(chip->dev,
"Failed to read otp mask register(%d)\n", ret);
return IRQ_NONE;
}
if ((evt_otp & SLG51000_EVT_CRC_MASK) &&
!(mask_otp & SLG51000_IRQ_CRC_MASK)) {
dev_info(chip->dev,
"OTP has been read or OTP crc is not zero\n");
handled = IRQ_HANDLED;
}
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,
"Over-current limit(ldo%d)\n", i + 1);
handled = IRQ_HANDLED;
}
}
if (!(evt[SLG51000_SCTL_EVT][R2] & SLG51000_IRQ_HIGH_TEMP_WARN_MASK) &&
(evt[SLG51000_SCTL_EVT][R0] & SLG51000_EVT_HIGH_TEMP_WARN_MASK)) {
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;
if (evt[SLG51000_SCTL_EVT][R1] &
SLG51000_STA_HIGH_TEMP_WARN_MASK)
dev_warn(chip->dev, "High temperature warning!\n");
}
return handled;
}
static void slg51000_clear_fault_log(struct slg51000 *chip)
{
unsigned int val = 0;
int ret = 0;
ret = regmap_read(chip->regmap, SLG51000_SYSCTL_FAULT_LOG1, &val);
if (ret < 0) {
dev_err(chip->dev, "Failed to read Fault log register\n");
return;
}
if (val & SLG51000_FLT_OVER_TEMP_MASK)
dev_dbg(chip->dev, "Fault log: FLT_OVER_TEMP\n");
if (val & SLG51000_FLT_POWER_SEQ_CRASH_REQ_MASK)
dev_dbg(chip->dev, "Fault log: FLT_POWER_SEQ_CRASH_REQ\n");
if (val & SLG51000_FLT_RST_MASK)
dev_dbg(chip->dev, "Fault log: FLT_RST\n");
if (val & SLG51000_FLT_POR_MASK)
dev_dbg(chip->dev, "Fault log: FLT_POR\n");
}
static int slg51000_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct slg51000 *chip;
struct gpio_desc *cs_gpiod = NULL;
int error, ret;
chip = devm_kzalloc(dev, sizeof(struct slg51000), GFP_KERNEL);
if (!chip)
return -ENOMEM;
cs_gpiod = devm_gpiod_get_from_of_node(dev, dev->of_node,
"dlg,cs-gpios", 0,
GPIOD_OUT_HIGH
| GPIOD_FLAGS_BIT_NONEXCLUSIVE,
"slg51000-cs");
if (cs_gpiod) {
dev_info(dev, "Found chip selector property\n");
chip->cs_gpiod = cs_gpiod;
}
i2c_set_clientdata(client, chip);
chip->chip_irq = client->irq;
chip->dev = dev;
chip->regmap = devm_regmap_init_i2c(client, &slg51000_regmap_config);
if (IS_ERR(chip->regmap)) {
error = PTR_ERR(chip->regmap);
dev_err(dev, "Failed to allocate register map: %d\n",
error);
return error;
}
ret = slg51000_regulator_init(chip);
if (ret < 0) {
dev_err(chip->dev, "Failed to init regulator(%d)\n", ret);
return ret;
}
slg51000_clear_fault_log(chip);
if (chip->chip_irq) {
ret = devm_request_threaded_irq(dev, chip->chip_irq, NULL,
slg51000_irq_handler,
(IRQF_TRIGGER_HIGH |
IRQF_ONESHOT),
"slg51000-irq", chip);
if (ret != 0) {
dev_err(dev, "Failed to request IRQ: %d\n",
chip->chip_irq);
return ret;
}
} else {
dev_info(dev, "No IRQ configured\n");
}
return ret;
}
static const struct i2c_device_id slg51000_i2c_id[] = {
{"slg51000", 0},
{},
};
MODULE_DEVICE_TABLE(i2c, slg51000_i2c_id);
static struct i2c_driver slg51000_regulator_driver = {
.driver = {
.name = "slg51000-regulator",
},
.probe = slg51000_i2c_probe,
.id_table = slg51000_i2c_id,
};
module_i2c_driver(slg51000_regulator_driver);
MODULE_AUTHOR("Eric Jeong <eric.jeong.opensource@diasemi.com>");
MODULE_DESCRIPTION("SLG51000 regulator driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,505 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* SLG51000 High PSRR, Multi-Output Regulators
* Copyright (C) 2019 Dialog Semiconductor
*
* Author: Eric Jeong <eric.jeong.opensource@diasemi.com>
*/
#ifndef __SLG51000_REGISTERS_H__
#define __SLG51000_REGISTERS_H__
/* Registers */
#define SLG51000_SYSCTL_PATN_ID_B0 0x1105
#define SLG51000_SYSCTL_PATN_ID_B1 0x1106
#define SLG51000_SYSCTL_PATN_ID_B2 0x1107
#define SLG51000_SYSCTL_SYS_CONF_A 0x1109
#define SLG51000_SYSCTL_SYS_CONF_D 0x110c
#define SLG51000_SYSCTL_MATRIX_CONF_A 0x110d
#define SLG51000_SYSCTL_MATRIX_CONF_B 0x110e
#define SLG51000_SYSCTL_REFGEN_CONF_C 0x1111
#define SLG51000_SYSCTL_UVLO_CONF_A 0x1112
#define SLG51000_SYSCTL_FAULT_LOG1 0x1115
#define SLG51000_SYSCTL_EVENT 0x1116
#define SLG51000_SYSCTL_STATUS 0x1117
#define SLG51000_SYSCTL_IRQ_MASK 0x1118
#define SLG51000_IO_GPIO1_CONF 0x1500
#define SLG51000_IO_GPIO2_CONF 0x1501
#define SLG51000_IO_GPIO3_CONF 0x1502
#define SLG51000_IO_GPIO4_CONF 0x1503
#define SLG51000_IO_GPIO5_CONF 0x1504
#define SLG51000_IO_GPIO6_CONF 0x1505
#define SLG51000_IO_GPIO_STATUS 0x1506
#define SLG51000_LUTARRAY_LUT_VAL_0 0x1600
#define SLG51000_LUTARRAY_LUT_VAL_1 0x1601
#define SLG51000_LUTARRAY_LUT_VAL_2 0x1602
#define SLG51000_LUTARRAY_LUT_VAL_3 0x1603
#define SLG51000_LUTARRAY_LUT_VAL_4 0x1604
#define SLG51000_LUTARRAY_LUT_VAL_5 0x1605
#define SLG51000_LUTARRAY_LUT_VAL_6 0x1606
#define SLG51000_LUTARRAY_LUT_VAL_7 0x1607
#define SLG51000_LUTARRAY_LUT_VAL_8 0x1608
#define SLG51000_LUTARRAY_LUT_VAL_9 0x1609
#define SLG51000_LUTARRAY_LUT_VAL_10 0x160a
#define SLG51000_LUTARRAY_LUT_VAL_11 0x160b
#define SLG51000_MUXARRAY_INPUT_SEL_0 0x1700
#define SLG51000_MUXARRAY_INPUT_SEL_1 0x1701
#define SLG51000_MUXARRAY_INPUT_SEL_2 0x1702
#define SLG51000_MUXARRAY_INPUT_SEL_3 0x1703
#define SLG51000_MUXARRAY_INPUT_SEL_4 0x1704
#define SLG51000_MUXARRAY_INPUT_SEL_5 0x1705
#define SLG51000_MUXARRAY_INPUT_SEL_6 0x1706
#define SLG51000_MUXARRAY_INPUT_SEL_7 0x1707
#define SLG51000_MUXARRAY_INPUT_SEL_8 0x1708
#define SLG51000_MUXARRAY_INPUT_SEL_9 0x1709
#define SLG51000_MUXARRAY_INPUT_SEL_10 0x170a
#define SLG51000_MUXARRAY_INPUT_SEL_11 0x170b
#define SLG51000_MUXARRAY_INPUT_SEL_12 0x170c
#define SLG51000_MUXARRAY_INPUT_SEL_13 0x170d
#define SLG51000_MUXARRAY_INPUT_SEL_14 0x170e
#define SLG51000_MUXARRAY_INPUT_SEL_15 0x170f
#define SLG51000_MUXARRAY_INPUT_SEL_16 0x1710
#define SLG51000_MUXARRAY_INPUT_SEL_17 0x1711
#define SLG51000_MUXARRAY_INPUT_SEL_18 0x1712
#define SLG51000_MUXARRAY_INPUT_SEL_19 0x1713
#define SLG51000_MUXARRAY_INPUT_SEL_20 0x1714
#define SLG51000_MUXARRAY_INPUT_SEL_21 0x1715
#define SLG51000_MUXARRAY_INPUT_SEL_22 0x1716
#define SLG51000_MUXARRAY_INPUT_SEL_23 0x1717
#define SLG51000_MUXARRAY_INPUT_SEL_24 0x1718
#define SLG51000_MUXARRAY_INPUT_SEL_25 0x1719
#define SLG51000_MUXARRAY_INPUT_SEL_26 0x171a
#define SLG51000_MUXARRAY_INPUT_SEL_27 0x171b
#define SLG51000_MUXARRAY_INPUT_SEL_28 0x171c
#define SLG51000_MUXARRAY_INPUT_SEL_29 0x171d
#define SLG51000_MUXARRAY_INPUT_SEL_30 0x171e
#define SLG51000_MUXARRAY_INPUT_SEL_31 0x171f
#define SLG51000_MUXARRAY_INPUT_SEL_32 0x1720
#define SLG51000_MUXARRAY_INPUT_SEL_33 0x1721
#define SLG51000_MUXARRAY_INPUT_SEL_34 0x1722
#define SLG51000_MUXARRAY_INPUT_SEL_35 0x1723
#define SLG51000_MUXARRAY_INPUT_SEL_36 0x1724
#define SLG51000_MUXARRAY_INPUT_SEL_37 0x1725
#define SLG51000_MUXARRAY_INPUT_SEL_38 0x1726
#define SLG51000_MUXARRAY_INPUT_SEL_39 0x1727
#define SLG51000_MUXARRAY_INPUT_SEL_40 0x1728
#define SLG51000_MUXARRAY_INPUT_SEL_41 0x1729
#define SLG51000_MUXARRAY_INPUT_SEL_42 0x172a
#define SLG51000_MUXARRAY_INPUT_SEL_43 0x172b
#define SLG51000_MUXARRAY_INPUT_SEL_44 0x172c
#define SLG51000_MUXARRAY_INPUT_SEL_45 0x172d
#define SLG51000_MUXARRAY_INPUT_SEL_46 0x172e
#define SLG51000_MUXARRAY_INPUT_SEL_47 0x172f
#define SLG51000_MUXARRAY_INPUT_SEL_48 0x1730
#define SLG51000_MUXARRAY_INPUT_SEL_49 0x1731
#define SLG51000_MUXARRAY_INPUT_SEL_50 0x1732
#define SLG51000_MUXARRAY_INPUT_SEL_51 0x1733
#define SLG51000_MUXARRAY_INPUT_SEL_52 0x1734
#define SLG51000_MUXARRAY_INPUT_SEL_53 0x1735
#define SLG51000_MUXARRAY_INPUT_SEL_54 0x1736
#define SLG51000_MUXARRAY_INPUT_SEL_55 0x1737
#define SLG51000_MUXARRAY_INPUT_SEL_56 0x1738
#define SLG51000_MUXARRAY_INPUT_SEL_57 0x1739
#define SLG51000_MUXARRAY_INPUT_SEL_58 0x173a
#define SLG51000_MUXARRAY_INPUT_SEL_59 0x173b
#define SLG51000_MUXARRAY_INPUT_SEL_60 0x173c
#define SLG51000_MUXARRAY_INPUT_SEL_61 0x173d
#define SLG51000_MUXARRAY_INPUT_SEL_62 0x173e
#define SLG51000_MUXARRAY_INPUT_SEL_63 0x173f
#define SLG51000_PWRSEQ_RESOURCE_EN_0 0x1900
#define SLG51000_PWRSEQ_RESOURCE_EN_1 0x1901
#define SLG51000_PWRSEQ_RESOURCE_EN_2 0x1902
#define SLG51000_PWRSEQ_RESOURCE_EN_3 0x1903
#define SLG51000_PWRSEQ_RESOURCE_EN_4 0x1904
#define SLG51000_PWRSEQ_RESOURCE_EN_5 0x1905
#define SLG51000_PWRSEQ_SLOT_TIME_MIN_UP0 0x1906
#define SLG51000_PWRSEQ_SLOT_TIME_MIN_DOWN0 0x1907
#define SLG51000_PWRSEQ_SLOT_TIME_MIN_UP1 0x1908
#define SLG51000_PWRSEQ_SLOT_TIME_MIN_DOWN1 0x1909
#define SLG51000_PWRSEQ_SLOT_TIME_MIN_UP2 0x190a
#define SLG51000_PWRSEQ_SLOT_TIME_MIN_DOWN2 0x190b
#define SLG51000_PWRSEQ_SLOT_TIME_MIN_UP3 0x190c
#define SLG51000_PWRSEQ_SLOT_TIME_MIN_DOWN3 0x190d
#define SLG51000_PWRSEQ_SLOT_TIME_MIN_UP4 0x190e
#define SLG51000_PWRSEQ_SLOT_TIME_MIN_DOWN4 0x190f
#define SLG51000_PWRSEQ_SLOT_TIME_MIN_UP5 0x1910
#define SLG51000_PWRSEQ_SLOT_TIME_MIN_DOWN5 0x1911
#define SLG51000_PWRSEQ_SLOT_TIME_MAX_CONF_A 0x1912
#define SLG51000_PWRSEQ_SLOT_TIME_MAX_CONF_B 0x1913
#define SLG51000_PWRSEQ_SLOT_TIME_MAX_CONF_C 0x1914
#define SLG51000_PWRSEQ_INPUT_SENSE_CONF_A 0x1915
#define SLG51000_PWRSEQ_INPUT_SENSE_CONF_B 0x1916
#define SLG51000_LDO1_VSEL 0x2000
#define SLG51000_LDO1_MINV 0x2060
#define SLG51000_LDO1_MAXV 0x2061
#define SLG51000_LDO1_MISC1 0x2064
#define SLG51000_LDO1_VSEL_ACTUAL 0x2065
#define SLG51000_LDO1_EVENT 0x20c0
#define SLG51000_LDO1_STATUS 0x20c1
#define SLG51000_LDO1_IRQ_MASK 0x20c2
#define SLG51000_LDO2_VSEL 0x2200
#define SLG51000_LDO2_MINV 0x2260
#define SLG51000_LDO2_MAXV 0x2261
#define SLG51000_LDO2_MISC1 0x2264
#define SLG51000_LDO2_VSEL_ACTUAL 0x2265
#define SLG51000_LDO2_EVENT 0x22c0
#define SLG51000_LDO2_STATUS 0x22c1
#define SLG51000_LDO2_IRQ_MASK 0x22c2
#define SLG51000_LDO3_VSEL 0x2300
#define SLG51000_LDO3_MINV 0x2360
#define SLG51000_LDO3_MAXV 0x2361
#define SLG51000_LDO3_CONF1 0x2364
#define SLG51000_LDO3_CONF2 0x2365
#define SLG51000_LDO3_VSEL_ACTUAL 0x2366
#define SLG51000_LDO3_EVENT 0x23c0
#define SLG51000_LDO3_STATUS 0x23c1
#define SLG51000_LDO3_IRQ_MASK 0x23c2
#define SLG51000_LDO4_VSEL 0x2500
#define SLG51000_LDO4_MINV 0x2560
#define SLG51000_LDO4_MAXV 0x2561
#define SLG51000_LDO4_CONF1 0x2564
#define SLG51000_LDO4_CONF2 0x2565
#define SLG51000_LDO4_VSEL_ACTUAL 0x2566
#define SLG51000_LDO4_EVENT 0x25c0
#define SLG51000_LDO4_STATUS 0x25c1
#define SLG51000_LDO4_IRQ_MASK 0x25c2
#define SLG51000_LDO5_VSEL 0x2700
#define SLG51000_LDO5_MINV 0x2760
#define SLG51000_LDO5_MAXV 0x2761
#define SLG51000_LDO5_TRIM2 0x2763
#define SLG51000_LDO5_CONF1 0x2765
#define SLG51000_LDO5_CONF2 0x2766
#define SLG51000_LDO5_VSEL_ACTUAL 0x2767
#define SLG51000_LDO5_EVENT 0x27c0
#define SLG51000_LDO5_STATUS 0x27c1
#define SLG51000_LDO5_IRQ_MASK 0x27c2
#define SLG51000_LDO6_VSEL 0x2900
#define SLG51000_LDO6_MINV 0x2960
#define SLG51000_LDO6_MAXV 0x2961
#define SLG51000_LDO6_TRIM2 0x2963
#define SLG51000_LDO6_CONF1 0x2965
#define SLG51000_LDO6_CONF2 0x2966
#define SLG51000_LDO6_VSEL_ACTUAL 0x2967
#define SLG51000_LDO6_EVENT 0x29c0
#define SLG51000_LDO6_STATUS 0x29c1
#define SLG51000_LDO6_IRQ_MASK 0x29c2
#define SLG51000_LDO7_VSEL 0x3100
#define SLG51000_LDO7_MINV 0x3160
#define SLG51000_LDO7_MAXV 0x3161
#define SLG51000_LDO7_CONF1 0x3164
#define SLG51000_LDO7_CONF2 0x3165
#define SLG51000_LDO7_VSEL_ACTUAL 0x3166
#define SLG51000_LDO7_EVENT 0x31c0
#define SLG51000_LDO7_STATUS 0x31c1
#define SLG51000_LDO7_IRQ_MASK 0x31c2
#define SLG51000_OTP_EVENT 0x782b
#define SLG51000_OTP_IRQ_MASK 0x782d
#define SLG51000_OTP_LOCK_OTP_PROG 0x78fe
#define SLG51000_OTP_LOCK_CTRL 0x78ff
#define SLG51000_LOCK_GLOBAL_LOCK_CTRL1 0x8000
/* Register Bit Fields */
/* SLG51000_SYSCTL_PATTERN_ID_BYTE0 = 0x1105 */
#define SLG51000_PATTERN_ID_BYTE0_SHIFT 0
#define SLG51000_PATTERN_ID_BYTE0_MASK (0xff << 0)
/* SLG51000_SYSCTL_PATTERN_ID_BYTE1 = 0x1106 */
#define SLG51000_PATTERN_ID_BYTE1_SHIFT 0
#define SLG51000_PATTERN_ID_BYTE1_MASK (0xff << 0)
/* SLG51000_SYSCTL_PATTERN_ID_BYTE2 = 0x1107 */
#define SLG51000_PATTERN_ID_BYTE2_SHIFT 0
#define SLG51000_PATTERN_ID_BYTE2_MASK (0xff << 0)
/* SLG51000_SYSCTL_SYS_CONF_A = 0x1109 */
#define SLG51000_I2C_ADDRESS_SHIFT 0
#define SLG51000_I2C_ADDRESS_MASK (0x7f << 0)
#define SLG51000_I2C_DISABLE_SHIFT 7
#define SLG51000_I2C_DISABLE_MASK (0x01 << 7)
/* SLG51000_SYSCTL_SYS_CONF_D = 0x110c */
#define SLG51000_CS_T_DEB_SHIFT 6
#define SLG51000_CS_T_DEB_MASK (0x03 << 6)
#define SLG51000_I2C_CLR_MODE_SHIFT 5
#define SLG51000_I2C_CLR_MODE_MASK (0x01 << 5)
/* SLG51000_SYSCTL_MATRIX_CTRL_CONF_A = 0x110d */
#define SLG51000_RESOURCE_CTRL_SHIFT 0
#define SLG51000_RESOURCE_CTRL_MASK (0xff << 0)
/* SLG51000_SYSCTL_MATRIX_CTRL_CONF_B = 0x110e */
#define SLG51000_MATRIX_EVENT_SENSE_SHIFT 0
#define SLG51000_MATRIX_EVENT_SENSE_MASK (0x07 << 0)
/* SLG51000_SYSCTL_REFGEN_CONF_C = 0x1111 */
#define SLG51000_REFGEN_SEL_TEMP_WARN_DEBOUNCE_SHIFT 2
#define SLG51000_REFGEN_SEL_TEMP_WARN_DEBOUNCE_MASK (0x03 << 2)
#define SLG51000_REFGEN_SEL_TEMP_WARN_THR_SHIFT 0
#define SLG51000_REFGEN_SEL_TEMP_WARN_THR_MASK (0x03 << 0)
/* SLG51000_SYSCTL_UVLO_CONF_A = 0x1112 */
#define SLG51000_VMON_UVLO_SEL_THR_SHIFT 0
#define SLG51000_VMON_UVLO_SEL_THR_MASK (0x1f << 0)
/* SLG51000_SYSCTL_FAULT_LOG1 = 0x1115 */
#define SLG51000_FLT_POR_SHIFT 5
#define SLG51000_FLT_POR_MASK (0x01 << 5)
#define SLG51000_FLT_RST_SHIFT 4
#define SLG51000_FLT_RST_MASK (0x01 << 4)
#define SLG51000_FLT_POWER_SEQ_CRASH_REQ_SHIFT 2
#define SLG51000_FLT_POWER_SEQ_CRASH_REQ_MASK (0x01 << 2)
#define SLG51000_FLT_OVER_TEMP_SHIFT 1
#define SLG51000_FLT_OVER_TEMP_MASK (0x01 << 1)
/* SLG51000_SYSCTL_EVENT = 0x1116 */
#define SLG51000_EVT_MATRIX_SHIFT 1
#define SLG51000_EVT_MATRIX_MASK (0x01 << 1)
#define SLG51000_EVT_HIGH_TEMP_WARN_SHIFT 0
#define SLG51000_EVT_HIGH_TEMP_WARN_MASK (0x01 << 0)
/* SLG51000_SYSCTL_STATUS = 0x1117 */
#define SLG51000_STA_MATRIX_SHIFT 1
#define SLG51000_STA_MATRIX_MASK (0x01 << 1)
#define SLG51000_STA_HIGH_TEMP_WARN_SHIFT 0
#define SLG51000_STA_HIGH_TEMP_WARN_MASK (0x01 << 0)
/* SLG51000_SYSCTL_IRQ_MASK = 0x1118 */
#define SLG51000_IRQ_MATRIX_SHIFT 1
#define SLG51000_IRQ_MATRIX_MASK (0x01 << 1)
#define SLG51000_IRQ_HIGH_TEMP_WARN_SHIFT 0
#define SLG51000_IRQ_HIGH_TEMP_WARN_MASK (0x01 << 0)
/* SLG51000_IO_GPIO1_CONF ~ SLG51000_IO_GPIO5_CONF =
* 0x1500, 0x1501, 0x1502, 0x1503, 0x1504
*/
#define SLG51000_GPIO_DIR_SHIFT 7
#define SLG51000_GPIO_DIR_MASK (0x01 << 7)
#define SLG51000_GPIO_SENS_SHIFT 5
#define SLG51000_GPIO_SENS_MASK (0x03 << 5)
#define SLG51000_GPIO_INVERT_SHIFT 4
#define SLG51000_GPIO_INVERT_MASK (0x01 << 4)
#define SLG51000_GPIO_BYP_SHIFT 3
#define SLG51000_GPIO_BYP_MASK (0x01 << 3)
#define SLG51000_GPIO_T_DEB_SHIFT 1
#define SLG51000_GPIO_T_DEB_MASK (0x03 << 1)
#define SLG51000_GPIO_LEVEL_SHIFT 0
#define SLG51000_GPIO_LEVEL_MASK (0x01 << 0)
/* SLG51000_IO_GPIO6_CONF = 0x1505 */
#define SLG51000_GPIO6_SENS_SHIFT 5
#define SLG51000_GPIO6_SENS_MASK (0x03 << 5)
#define SLG51000_GPIO6_INVERT_SHIFT 4
#define SLG51000_GPIO6_INVERT_MASK (0x01 << 4)
#define SLG51000_GPIO6_T_DEB_SHIFT 1
#define SLG51000_GPIO6_T_DEB_MASK (0x03 << 1)
#define SLG51000_GPIO6_LEVEL_SHIFT 0
#define SLG51000_GPIO6_LEVEL_MASK (0x01 << 0)
/* SLG51000_IO_GPIO_STATUS = 0x1506 */
#define SLG51000_GPIO6_STATUS_SHIFT 5
#define SLG51000_GPIO6_STATUS_MASK (0x01 << 5)
#define SLG51000_GPIO5_STATUS_SHIFT 4
#define SLG51000_GPIO5_STATUS_MASK (0x01 << 4)
#define SLG51000_GPIO4_STATUS_SHIFT 3
#define SLG51000_GPIO4_STATUS_MASK (0x01 << 3)
#define SLG51000_GPIO3_STATUS_SHIFT 2
#define SLG51000_GPIO3_STATUS_MASK (0x01 << 2)
#define SLG51000_GPIO2_STATUS_SHIFT 1
#define SLG51000_GPIO2_STATUS_MASK (0x01 << 1)
#define SLG51000_GPIO1_STATUS_SHIFT 0
#define SLG51000_GPIO1_STATUS_MASK (0x01 << 0)
/* SLG51000_LUTARRAY_LUT_VAL_0 ~ SLG51000_LUTARRAY_LUT_VAL_11
* 0x1600, 0x1601, 0x1602, 0x1603, 0x1604, 0x1605,
* 0x1606, 0x1607, 0x1608, 0x1609, 0x160a, 0x160b
*/
#define SLG51000_LUT_VAL_SHIFT 0
#define SLG51000_LUT_VAL_MASK (0xff << 0)
/* SLG51000_MUXARRAY_INPUT_SEL_0 ~ SLG51000_MUXARRAY_INPUT_SEL_63
* 0x1700, 0x1701, 0x1702, 0x1703, 0x1704, 0x1705,
* 0x1706, 0x1707, 0x1708, 0x1709, 0x170a, 0x170b,
* 0x170c, 0x170d, 0x170e, 0x170f, 0x1710, 0x1711,
* 0x1712, 0x1713, 0x1714, 0x1715, 0x1716, 0x1717,
* 0x1718, 0x1719, 0x171a, 0x171b, 0x171c, 0x171d,
* 0x171e, 0x171f, 0x1720, 0x1721, 0x1722, 0x1723,
* 0x1724, 0x1725, 0x1726, 0x1727, 0x1728, 0x1729,
* 0x173a, 0x173b, 0x173c, 0x173d, 0x173e, 0x173f,
*/
#define SLG51000_INPUT_SEL_SHIFT 0
#define SLG51000_INPUT_SEL_MASK (0x3f << 0)
/* SLG51000_PWRSEQ_RESOURCE_EN_0 ~ SLG51000_PWRSEQ_RESOURCE_EN_5
* 0x1900, 0x1901, 0x1902, 0x1903, 0x1904, 0x1905
*/
#define SLG51000_RESOURCE_EN_DOWN0_SHIFT 4
#define SLG51000_RESOURCE_EN_DOWN0_MASK (0x07 << 4)
#define SLG51000_RESOURCE_EN_UP0_SHIFT 0
#define SLG51000_RESOURCE_EN_UP0_MASK (0x07 << 0)
/* SLG51000_PWRSEQ_SLOT_TIME_MIN_UP0 ~ SLG51000_PWRSEQ_SLOT_TIME_MIN_UP5
* 0x1906, 0x1908, 0x190a, 0x190c, 0x190e, 0x1910
*/
#define SLG51000_SLOT_TIME_MIN_UP_SHIFT 0
#define SLG51000_SLOT_TIME_MIN_UP_MASK (0xff << 0)
/* SLG51000_PWRSEQ_SLOT_TIME_MIN_DOWN0 ~ SLG51000_PWRSEQ_SLOT_TIME_MIN_DOWN5
* 0x1907, 0x1909, 0x190b, 0x190d, 0x190f, 0x1911
*/
#define SLG51000_SLOT_TIME_MIN_DOWN_SHIFT 0
#define SLG51000_SLOT_TIME_MIN_DOWN_MASK (0xff << 0)
/* SLG51000_PWRSEQ_SLOT_TIME_MAX_CONF_A ~ SLG51000_PWRSEQ_SLOT_TIME_MAX_CONF_C
* 0x1912, 0x1913, 0x1914
*/
#define SLG51000_SLOT_TIME_MAX_DOWN1_SHIFT 6
#define SLG51000_SLOT_TIME_MAX_DOWN1_MASK (0x03 << 6)
#define SLG51000_SLOT_TIME_MAX_UP1_SHIFT 4
#define SLG51000_SLOT_TIME_MAX_UP1_MASK (0x03 << 4)
#define SLG51000_SLOT_TIME_MAX_DOWN0_SHIFT 2
#define SLG51000_SLOT_TIME_MAX_DOWN0_MASK (0x03 << 2)
#define SLG51000_SLOT_TIME_MAX_UP0_SHIFT 0
#define SLG51000_SLOT_TIME_MAX_UP0_MASK (0x03 << 0)
/* SLG51000_PWRSEQ_INPUT_SENSE_CONF_A = 0x1915 */
#define SLG51000_TRIG_UP_SENSE_SHIFT 6
#define SLG51000_TRIG_UP_SENSE_MASK (0x01 << 6)
#define SLG51000_UP_EN_SENSE5_SHIFT 5
#define SLG51000_UP_EN_SENSE5_MASK (0x01 << 5)
#define SLG51000_UP_EN_SENSE4_SHIFT 4
#define SLG51000_UP_EN_SENSE4_MASK (0x01 << 4)
#define SLG51000_UP_EN_SENSE3_SHIFT 3
#define SLG51000_UP_EN_SENSE3_MASK (0x01 << 3)
#define SLG51000_UP_EN_SENSE2_SHIFT 2
#define SLG51000_UP_EN_SENSE2_MASK (0x01 << 2)
#define SLG51000_UP_EN_SENSE1_SHIFT 1
#define SLG51000_UP_EN_SENSE1_MASK (0x01 << 1)
#define SLG51000_UP_EN_SENSE0_SHIFT 0
#define SLG51000_UP_EN_SENSE0_MASK (0x01 << 0)
/* SLG51000_PWRSEQ_INPUT_SENSE_CONF_B = 0x1916 */
#define SLG51000_CRASH_DETECT_SENSE_SHIFT 7
#define SLG51000_CRASH_DETECT_SENSE_MASK (0x01 << 7)
#define SLG51000_TRIG_DOWN_SENSE_SHIFT 6
#define SLG51000_TRIG_DOWN_SENSE_MASK (0x01 << 6)
#define SLG51000_DOWN_EN_SENSE5_SHIFT 5
#define SLG51000_DOWN_EN_SENSE5_MASK (0x01 << 5)
#define SLG51000_DOWN_EN_SENSE4_SHIFT 4
#define SLG51000_DOWN_EN_SENSE4_MASK (0x01 << 4)
#define SLG51000_DOWN_EN_SENSE3_SHIFT 3
#define SLG51000_DOWN_EN_SENSE3_MASK (0x01 << 3)
#define SLG51000_DOWN_EN_SENSE2_SHIFT 2
#define SLG51000_DOWN_EN_SENSE2_MASK (0x01 << 2)
#define SLG51000_DOWN_EN_SENSE1_SHIFT 1
#define SLG51000_DOWN_EN_SENSE1_MASK (0x01 << 1)
#define SLG51000_DOWN_EN_SENSE0_SHIFT 0
#define SLG51000_DOWN_EN_SENSE0_MASK (0x01 << 0)
/* SLG51000_LDO1_VSEL ~ SLG51000_LDO7_VSEL =
* 0x2000, 0x2200, 0x2300, 0x2500, 0x2700, 0x2900, 0x3100
*/
#define SLG51000_VSEL_SHIFT 0
#define SLG51000_VSEL_MASK (0xff << 0)
/* SLG51000_LDO1_MINV ~ SLG51000_LDO7_MINV =
* 0x2060, 0x2260, 0x2360, 0x2560, 0x2760, 0x2960, 0x3160
*/
#define SLG51000_MINV_SHIFT 0
#define SLG51000_MINV_MASK (0xff << 0)
/* SLG51000_LDO1_MAXV ~ SLG51000_LDO7_MAXV =
* 0x2061, 0x2261, 0x2361, 0x2561, 0x2761, 0x2961, 0x3161
*/
#define SLG51000_MAXV_SHIFT 0
#define SLG51000_MAXV_MASK (0xff << 0)
/* SLG51000_LDO1_MISC1 = 0x2064, SLG51000_LDO2_MISC1 = 0x2264 */
#define SLG51000_SEL_VRANGE_SHIFT 0
#define SLG51000_SEL_VRANGE_MASK (0x01 << 0)
/* SLG51000_LDO1_VSEL_ACTUAL ~ SLG51000_LDO7_VSEL_ACTUAL =
* 0x2065, 0x2265, 0x2366, 0x2566, 0x2767, 0x2967, 0x3166
*/
#define SLG51000_VSEL_ACTUAL_SHIFT 0
#define SLG51000_VSEL_ACTUAL_MASK (0xff << 0)
/* SLG51000_LDO1_EVENT ~ SLG51000_LDO7_EVENT =
* 0x20c0, 0x22c0, 0x23c0, 0x25c0, 0x27c0, 0x29c0, 0x31c0
*/
#define SLG51000_EVT_ILIM_FLAG_SHIFT 0
#define SLG51000_EVT_ILIM_FLAG_MASK (0x01 << 0)
#define SLG51000_EVT_VOUT_OK_FLAG_SHIFT 1
#define SLG51000_EVT_VOUT_OK_FLAG_MASK (0x01 << 1)
/* SLG51000_LDO1_STATUS ~ SLG51000_LDO7_STATUS =
* 0x20c1, 0x22c1, 0x23c1, 0x25c1, 0x27c1, 0x29c1, 0x31c1
*/
#define SLG51000_STA_ILIM_FLAG_SHIFT 0
#define SLG51000_STA_ILIM_FLAG_MASK (0x01 << 0)
#define SLG51000_STA_VOUT_OK_FLAG_SHIFT 1
#define SLG51000_STA_VOUT_OK_FLAG_MASK (0x01 << 1)
/* SLG51000_LDO1_IRQ_MASK ~ SLG51000_LDO7_IRQ_MASK =
* 0x20c2, 0x22c2, 0x23c2, 0x25c2, 0x27c2, 0x29c2, 0x31c2
*/
#define SLG51000_IRQ_ILIM_FLAG_SHIFT 0
#define SLG51000_IRQ_ILIM_FLAG_MASK (0x01 << 0)
/* SLG51000_LDO3_CONF1 ~ SLG51000_LDO7_CONF1 =
* 0x2364, 0x2564, 0x2765, 0x2965, 0x3164
*/
#define SLG51000_SEL_START_ILIM_SHIFT 0
#define SLG51000_SEL_START_ILIM_MASK (0x7f << 0)
/* SLG51000_LDO3_CONF2 ~ SLG51000_LDO7_CONF2 =
* 0x2365, 0x2565, 0x2766, 0x2966, 0x3165
*/
#define SLG51000_SEL_FUNC_ILIM_SHIFT 0
#define SLG51000_SEL_FUNC_ILIM_MASK (0x7f << 0)
/* SLG51000_LDO5_TRIM2 = 0x2763, SLG51000_LDO6_TRIM2 = 0x2963 */
#define SLG51000_SEL_BYP_SLEW_RATE_SHIFT 2
#define SLG51000_SEL_BYP_SLEW_RATE_MASK (0x03 << 2)
#define SLG51000_SEL_BYP_VGATE_SHIFT 1
#define SLG51000_SEL_BYP_VGATE_MASK (0x01 << 1)
#define SLG51000_SEL_BYP_MODE_SHIFT 0
#define SLG51000_SEL_BYP_MODE_MASK (0x01 << 0)
/* SLG51000_OTP_EVENT = 0x782b */
#define SLG51000_EVT_CRC_SHIFT 0
#define SLG51000_EVT_CRC_MASK (0x01 << 0)
/* SLG51000_OTP_IRQ_MASK = 0x782d */
#define SLG51000_IRQ_CRC_SHIFT 0
#define SLG51000_IRQ_CRC_MASK (0x01 << 0)
/* SLG51000_OTP_LOCK_OTP_PROG = 0x78fe */
#define SLG51000_LOCK_OTP_PROG_SHIFT 0
#define SLG51000_LOCK_OTP_PROG_MASK (0x01 << 0)
/* SLG51000_OTP_LOCK_CTRL = 0x78ff */
#define SLG51000_LOCK_DFT_SHIFT 1
#define SLG51000_LOCK_DFT_MASK (0x01 << 1)
#define SLG51000_LOCK_RWT_SHIFT 0
#define SLG51000_LOCK_RWT_MASK (0x01 << 0)
/* SLG51000_LOCK_GLOBAL_LOCK_CTRL1 = 0x8000 */
#define SLG51000_LDO7_LOCK_SHIFT 7
#define SLG51000_LDO7_LOCK_MASK (0x01 << 7)
#define SLG51000_LDO6_LOCK_SHIFT 6
#define SLG51000_LDO6_LOCK_MASK (0x01 << 6)
#define SLG51000_LDO5_LOCK_SHIFT 5
#define SLG51000_LDO5_LOCK_MASK (0x01 << 5)
#define SLG51000_LDO4_LOCK_SHIFT 4
#define SLG51000_LDO4_LOCK_MASK (0x01 << 4)
#define SLG51000_LDO3_LOCK_SHIFT 3
#define SLG51000_LDO3_LOCK_MASK (0x01 << 3)
#define SLG51000_LDO2_LOCK_SHIFT 2
#define SLG51000_LDO2_LOCK_MASK (0x01 << 2)
#define SLG51000_LDO1_LOCK_SHIFT 1
#define SLG51000_LDO1_LOCK_MASK (0x01 << 1)
#endif /* __SLG51000_REGISTERS_H__ */

View File

@ -0,0 +1,132 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) STMicroelectronics 2019
// Author(s): Fabrice Gasnier <fabrice.gasnier@st.com>.
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
/* STM32H7 SYSCFG register */
#define STM32H7_SYSCFG_PMCR 0x04
#define STM32H7_SYSCFG_BOOSTE_MASK BIT(8)
/* STM32MP1 SYSCFG has set and clear registers */
#define STM32MP1_SYSCFG_PMCSETR 0x04
#define STM32MP1_SYSCFG_PMCCLRR 0x44
#define STM32MP1_SYSCFG_EN_BOOSTER_MASK BIT(8)
static const struct regulator_ops stm32h7_booster_ops = {
.list_voltage = regulator_list_voltage_linear,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
};
static const struct regulator_desc stm32h7_booster_desc = {
.name = "booster",
.supply_name = "vdda",
.n_voltages = 1,
.type = REGULATOR_VOLTAGE,
.min_uV = 3300000,
.fixed_uV = 3300000,
.ramp_delay = 66000, /* up to 50us to stabilize */
.ops = &stm32h7_booster_ops,
.enable_reg = STM32H7_SYSCFG_PMCR,
.enable_mask = STM32H7_SYSCFG_BOOSTE_MASK,
.owner = THIS_MODULE,
};
static int stm32mp1_booster_enable(struct regulator_dev *rdev)
{
return regmap_write(rdev->regmap, STM32MP1_SYSCFG_PMCSETR,
STM32MP1_SYSCFG_EN_BOOSTER_MASK);
}
static int stm32mp1_booster_disable(struct regulator_dev *rdev)
{
return regmap_write(rdev->regmap, STM32MP1_SYSCFG_PMCCLRR,
STM32MP1_SYSCFG_EN_BOOSTER_MASK);
}
static const struct regulator_ops stm32mp1_booster_ops = {
.list_voltage = regulator_list_voltage_linear,
.enable = stm32mp1_booster_enable,
.disable = stm32mp1_booster_disable,
.is_enabled = regulator_is_enabled_regmap,
};
static const struct regulator_desc stm32mp1_booster_desc = {
.name = "booster",
.supply_name = "vdda",
.n_voltages = 1,
.type = REGULATOR_VOLTAGE,
.min_uV = 3300000,
.fixed_uV = 3300000,
.ramp_delay = 66000,
.ops = &stm32mp1_booster_ops,
.enable_reg = STM32MP1_SYSCFG_PMCSETR,
.enable_mask = STM32MP1_SYSCFG_EN_BOOSTER_MASK,
.owner = THIS_MODULE,
};
static int stm32_booster_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node;
struct regulator_config config = { };
const struct regulator_desc *desc;
struct regulator_dev *rdev;
struct regmap *regmap;
int ret;
regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
if (IS_ERR(regmap))
return PTR_ERR(regmap);
desc = (const struct regulator_desc *)
of_match_device(dev->driver->of_match_table, dev)->data;
config.regmap = regmap;
config.dev = dev;
config.of_node = np;
config.init_data = of_get_regulator_init_data(dev, np, desc);
rdev = devm_regulator_register(dev, desc, &config);
if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev);
dev_err(dev, "register failed with error %d\n", ret);
return ret;
}
return 0;
}
static const struct of_device_id stm32_booster_of_match[] = {
{
.compatible = "st,stm32h7-booster",
.data = (void *)&stm32h7_booster_desc
}, {
.compatible = "st,stm32mp1-booster",
.data = (void *)&stm32mp1_booster_desc
}, {
},
};
MODULE_DEVICE_TABLE(of, stm32_booster_of_match);
static struct platform_driver stm32_booster_driver = {
.probe = stm32_booster_probe,
.driver = {
.name = "stm32-booster",
.of_match_table = of_match_ptr(stm32_booster_of_match),
},
};
module_platform_driver(stm32_booster_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
MODULE_DESCRIPTION("STMicroelectronics STM32 booster regulator driver");
MODULE_ALIAS("platform:stm32-booster");

View File

@ -371,11 +371,12 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data(
"dcdc-ext-control-gpios", 0, "dcdc-ext-control-gpios", 0,
gflags, gflags,
"tps65090"); "tps65090");
if (IS_ERR(rpdata->gpiod)) if (PTR_ERR(rpdata->gpiod) == -ENOENT) {
return ERR_CAST(rpdata->gpiod);
if (!rpdata->gpiod)
dev_err(&pdev->dev, dev_err(&pdev->dev,
"could not find DCDC external control GPIO\n"); "could not find DCDC external control GPIO\n");
rpdata->gpiod = NULL;
} else if (IS_ERR(rpdata->gpiod))
return ERR_CAST(rpdata->gpiod);
} }
if (of_property_read_u32(tps65090_matches[idx].of_node, if (of_property_read_u32(tps65090_matches[idx].of_node,

View File

@ -15,7 +15,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mfd/wm831x/core.h> #include <linux/mfd/wm831x/core.h>
@ -50,7 +50,7 @@ struct wm831x_dcdc {
int base; int base;
struct wm831x *wm831x; struct wm831x *wm831x;
struct regulator_dev *regulator; struct regulator_dev *regulator;
int dvs_gpio; struct gpio_desc *dvs_gpiod;
int dvs_gpio_state; int dvs_gpio_state;
int on_vsel; int on_vsel;
int dvs_vsel; int dvs_vsel;
@ -217,7 +217,7 @@ static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state)
return 0; return 0;
dcdc->dvs_gpio_state = state; dcdc->dvs_gpio_state = state;
gpio_set_value(dcdc->dvs_gpio, state); gpiod_set_value(dcdc->dvs_gpiod, state);
/* Should wait for DVS state change to be asserted if we have /* Should wait for DVS state change to be asserted if we have
* a GPIO for it, for now assume the device is configured * a GPIO for it, for now assume the device is configured
@ -237,10 +237,10 @@ static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev,
int ret; int ret;
/* If this value is already set then do a GPIO update if we can */ /* If this value is already set then do a GPIO update if we can */
if (dcdc->dvs_gpio && dcdc->on_vsel == vsel) if (dcdc->dvs_gpiod && dcdc->on_vsel == vsel)
return wm831x_buckv_set_dvs(rdev, 0); return wm831x_buckv_set_dvs(rdev, 0);
if (dcdc->dvs_gpio && dcdc->dvs_vsel == vsel) if (dcdc->dvs_gpiod && dcdc->dvs_vsel == vsel)
return wm831x_buckv_set_dvs(rdev, 1); return wm831x_buckv_set_dvs(rdev, 1);
/* Always set the ON status to the minimum voltage */ /* Always set the ON status to the minimum voltage */
@ -249,7 +249,7 @@ static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev,
return ret; return ret;
dcdc->on_vsel = vsel; dcdc->on_vsel = vsel;
if (!dcdc->dvs_gpio) if (!dcdc->dvs_gpiod)
return ret; return ret;
/* Kick the voltage transition now */ /* Kick the voltage transition now */
@ -296,7 +296,7 @@ static int wm831x_buckv_get_voltage_sel(struct regulator_dev *rdev)
{ {
struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
if (dcdc->dvs_gpio && dcdc->dvs_gpio_state) if (dcdc->dvs_gpiod && dcdc->dvs_gpio_state)
return dcdc->dvs_vsel; return dcdc->dvs_vsel;
else else
return dcdc->on_vsel; return dcdc->on_vsel;
@ -337,7 +337,7 @@ static void wm831x_buckv_dvs_init(struct platform_device *pdev,
int ret; int ret;
u16 ctrl; u16 ctrl;
if (!pdata || !pdata->dvs_gpio) if (!pdata)
return; return;
/* gpiolib won't let us read the GPIO status so pick the higher /* gpiolib won't let us read the GPIO status so pick the higher
@ -345,17 +345,14 @@ static void wm831x_buckv_dvs_init(struct platform_device *pdev,
*/ */
dcdc->dvs_gpio_state = pdata->dvs_init_state; dcdc->dvs_gpio_state = pdata->dvs_init_state;
ret = devm_gpio_request_one(&pdev->dev, pdata->dvs_gpio, dcdc->dvs_gpiod = devm_gpiod_get(&pdev->dev, "dvs",
dcdc->dvs_gpio_state ? GPIOF_INIT_HIGH : 0, dcdc->dvs_gpio_state ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW);
"DCDC DVS"); if (IS_ERR(dcdc->dvs_gpiod)) {
if (ret < 0) { dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %ld\n",
dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n", dcdc->name, PTR_ERR(dcdc->dvs_gpiod));
dcdc->name, ret);
return; return;
} }
dcdc->dvs_gpio = pdata->dvs_gpio;
switch (pdata->dvs_control_src) { switch (pdata->dvs_control_src) {
case 1: case 1:
ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT; ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT;

View File

@ -797,6 +797,9 @@
#define DA9062AA_BUCK3_SL_A_SHIFT 7 #define DA9062AA_BUCK3_SL_A_SHIFT 7
#define DA9062AA_BUCK3_SL_A_MASK BIT(7) #define DA9062AA_BUCK3_SL_A_MASK BIT(7)
/* DA9062AA_VLDO[1-4]_A common */
#define DA9062AA_VLDO_A_MIN_SEL 2
/* DA9062AA_VLDO1_A = 0x0A9 */ /* DA9062AA_VLDO1_A = 0x0A9 */
#define DA9062AA_VLDO1_A_SHIFT 0 #define DA9062AA_VLDO1_A_SHIFT 0
#define DA9062AA_VLDO1_A_MASK 0x3f #define DA9062AA_VLDO1_A_MASK 0x3f

View File

@ -11,55 +11,6 @@
#ifndef __MFD_DA9063_PDATA_H__ #ifndef __MFD_DA9063_PDATA_H__
#define __MFD_DA9063_PDATA_H__ #define __MFD_DA9063_PDATA_H__
#include <linux/regulator/machine.h>
/*
* Regulator configuration
*/
/* DA9063 and DA9063L regulator IDs */
enum {
/* BUCKs */
DA9063_ID_BCORE1,
DA9063_ID_BCORE2,
DA9063_ID_BPRO,
DA9063_ID_BMEM,
DA9063_ID_BIO,
DA9063_ID_BPERI,
/* BCORE1 and BCORE2 in merged mode */
DA9063_ID_BCORES_MERGED,
/* BMEM and BIO in merged mode */
DA9063_ID_BMEM_BIO_MERGED,
/* When two BUCKs are merged, they cannot be reused separately */
/* LDOs on both DA9063 and DA9063L */
DA9063_ID_LDO3,
DA9063_ID_LDO7,
DA9063_ID_LDO8,
DA9063_ID_LDO9,
DA9063_ID_LDO11,
/* DA9063-only LDOs */
DA9063_ID_LDO1,
DA9063_ID_LDO2,
DA9063_ID_LDO4,
DA9063_ID_LDO5,
DA9063_ID_LDO6,
DA9063_ID_LDO10,
};
/* Regulators platform data */
struct da9063_regulator_data {
int id;
struct regulator_init_data *initdata;
};
struct da9063_regulators_pdata {
unsigned n_regulators;
struct da9063_regulator_data *regulator_data;
};
/* /*
* RGB LED configuration * RGB LED configuration
*/ */

View File

@ -190,4 +190,9 @@ enum s2mps11_regulators {
#define S2MPS11_BUCK6_RAMP_EN_SHIFT 0 #define S2MPS11_BUCK6_RAMP_EN_SHIFT 0
#define S2MPS11_PMIC_EN_SHIFT 6 #define S2MPS11_PMIC_EN_SHIFT 6
/*
* Bits for "enable suspend" (On/Off controlled by PWREN)
* are the same as in S2MPS14: S2MPS14_ENABLE_SUSPEND
*/
#endif /* __LINUX_MFD_S2MPS11_H */ #endif /* __LINUX_MFD_S2MPS11_H */

View File

@ -47,7 +47,6 @@ struct wm831x_battery_pdata {
* I2C or SPI buses. * I2C or SPI buses.
*/ */
struct wm831x_buckv_pdata { struct wm831x_buckv_pdata {
int dvs_gpio; /** CPU GPIO to use for DVS switching */
int dvs_control_src; /** Hardware DVS source to use (1 or 2) */ int dvs_control_src; /** Hardware DVS source to use (1 or 2) */
int dvs_init_state; /** DVS state to expect on startup */ int dvs_init_state; /** DVS state to expect on startup */
int dvs_state_gpio; /** CPU GPIO to use for monitoring status */ int dvs_state_gpio; /** CPU GPIO to use for monitoring status */

View File

@ -283,6 +283,11 @@ enum regulator_type {
* @vsel_range_mask: Mask for register bitfield used for range selector * @vsel_range_mask: Mask for register bitfield used for range selector
* @vsel_reg: Register for selector when using regulator_regmap_X_voltage_ * @vsel_reg: Register for selector when using regulator_regmap_X_voltage_
* @vsel_mask: Mask for register bitfield used for selector * @vsel_mask: Mask for register bitfield used for selector
* @vsel_step: Specify the resolution of selector stepping when setting
* voltage. If 0, then no stepping is done (requested selector is
* set directly), if >0 then the regulator API will ramp the
* voltage up/down gradually each time increasing/decreasing the
* selector by the specified step value.
* @csel_reg: Register for current limit selector using regmap set_current_limit * @csel_reg: Register for current limit selector using regmap set_current_limit
* @csel_mask: Mask for register bitfield used for current limit selector * @csel_mask: Mask for register bitfield used for current limit selector
* @apply_reg: Register for initiate voltage change on the output when * @apply_reg: Register for initiate voltage change on the output when
@ -357,6 +362,7 @@ struct regulator_desc {
unsigned int vsel_range_mask; unsigned int vsel_range_mask;
unsigned int vsel_reg; unsigned int vsel_reg;
unsigned int vsel_mask; unsigned int vsel_mask;
unsigned int vsel_step;
unsigned int csel_reg; unsigned int csel_reg;
unsigned int csel_mask; unsigned int csel_mask;
unsigned int apply_reg; unsigned int apply_reg;

View File

@ -105,9 +105,6 @@ enum {
#define MAX8952_NUM_DVS_MODE 4 #define MAX8952_NUM_DVS_MODE 4
struct max8952_platform_data { struct max8952_platform_data {
int gpio_vid0;
int gpio_vid1;
u32 default_mode; u32 default_mode;
u32 dvs_mode[MAX8952_NUM_DVS_MODE]; /* MAX8952_DVS_MODEx_XXXXmV */ u32 dvs_mode[MAX8952_NUM_DVS_MODE]; /* MAX8952_DVS_MODEx_XXXXmV */