Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
b27d9668
Commit
b27d9668
authored
Dec 21, 2018
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'regulator-4.21' into regulator-next
parents
67a2ab93
cd07e370
Changes
58
Hide whitespace changes
Inline
Side-by-side
Showing
58 changed files
with
3129 additions
and
616 deletions
+3129
-616
Documentation/devicetree/bindings/mfd/axp20x.txt
Documentation/devicetree/bindings/mfd/axp20x.txt
+9
-0
Documentation/devicetree/bindings/regulator/act8945a-regulator.txt
...tion/devicetree/bindings/regulator/act8945a-regulator.txt
+34
-0
Documentation/devicetree/bindings/regulator/cirrus,lochnagar.txt
...tation/devicetree/bindings/regulator/cirrus,lochnagar.txt
+82
-0
Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt
...tion/devicetree/bindings/regulator/mcp16502-regulator.txt
+143
-0
Documentation/devicetree/bindings/regulator/regulator.txt
Documentation/devicetree/bindings/regulator/regulator.txt
+9
-3
Documentation/driver-model/devres.txt
Documentation/driver-model/devres.txt
+1
-0
MAINTAINERS
MAINTAINERS
+7
-0
arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts
arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts
+2
-0
arch/arm/mach-s3c64xx/mach-crag6410-module.c
arch/arm/mach-s3c64xx/mach-crag6410-module.c
+15
-2
drivers/gpio/gpiolib-devres.c
drivers/gpio/gpiolib-devres.c
+68
-12
drivers/gpio/gpiolib.c
drivers/gpio/gpiolib.c
+2
-0
drivers/gpio/gpiolib.h
drivers/gpio/gpiolib.h
+0
-6
drivers/mfd/axp20x.c
drivers/mfd/axp20x.c
+7
-6
drivers/mfd/wm8994-core.c
drivers/mfd/wm8994-core.c
+0
-9
drivers/regulator/88pm8607.c
drivers/regulator/88pm8607.c
+1
-1
drivers/regulator/Kconfig
drivers/regulator/Kconfig
+10
-0
drivers/regulator/Makefile
drivers/regulator/Makefile
+1
-0
drivers/regulator/act8945a-regulator.c
drivers/regulator/act8945a-regulator.c
+202
-3
drivers/regulator/arizona-ldo1.c
drivers/regulator/arizona-ldo1.c
+0
-3
drivers/regulator/as3711-regulator.c
drivers/regulator/as3711-regulator.c
+1
-4
drivers/regulator/axp20x-regulator.c
drivers/regulator/axp20x-regulator.c
+697
-179
drivers/regulator/bd718x7-regulator.c
drivers/regulator/bd718x7-regulator.c
+28
-4
drivers/regulator/bd9571mwv-regulator.c
drivers/regulator/bd9571mwv-regulator.c
+1
-9
drivers/regulator/core.c
drivers/regulator/core.c
+951
-220
drivers/regulator/da9052-regulator.c
drivers/regulator/da9052-regulator.c
+1
-1
drivers/regulator/da9210-regulator.c
drivers/regulator/da9210-regulator.c
+2
-2
drivers/regulator/da9211-regulator.c
drivers/regulator/da9211-regulator.c
+6
-0
drivers/regulator/dbx500-prcmu.c
drivers/regulator/dbx500-prcmu.c
+4
-31
drivers/regulator/fixed.c
drivers/regulator/fixed.c
+5
-1
drivers/regulator/internal.h
drivers/regulator/internal.h
+2
-0
drivers/regulator/lm363x-regulator.c
drivers/regulator/lm363x-regulator.c
+6
-2
drivers/regulator/lochnagar-regulator.c
drivers/regulator/lochnagar-regulator.c
+39
-11
drivers/regulator/lp8788-ldo.c
drivers/regulator/lp8788-ldo.c
+6
-2
drivers/regulator/max77686-regulator.c
drivers/regulator/max77686-regulator.c
+19
-10
drivers/regulator/max8952.c
drivers/regulator/max8952.c
+7
-3
drivers/regulator/max8973-regulator.c
drivers/regulator/max8973-regulator.c
+7
-1
drivers/regulator/max8997-regulator.c
drivers/regulator/max8997-regulator.c
+1
-1
drivers/regulator/mc13xxx-regulator-core.c
drivers/regulator/mc13xxx-regulator-core.c
+1
-1
drivers/regulator/mcp16502.c
drivers/regulator/mcp16502.c
+552
-0
drivers/regulator/of_regulator.c
drivers/regulator/of_regulator.c
+51
-30
drivers/regulator/palmas-regulator.c
drivers/regulator/palmas-regulator.c
+4
-1
drivers/regulator/pfuze100-regulator.c
drivers/regulator/pfuze100-regulator.c
+2
-0
drivers/regulator/qcom-rpmh-regulator.c
drivers/regulator/qcom-rpmh-regulator.c
+1
-1
drivers/regulator/s2mps11.c
drivers/regulator/s2mps11.c
+29
-25
drivers/regulator/s5m8767.c
drivers/regulator/s5m8767.c
+9
-2
drivers/regulator/stpmic1_regulator.c
drivers/regulator/stpmic1_regulator.c
+2
-2
drivers/regulator/tps65090-regulator.c
drivers/regulator/tps65090-regulator.c
+6
-0
drivers/regulator/tps65910-regulator.c
drivers/regulator/tps65910-regulator.c
+3
-1
drivers/regulator/wm8350-regulator.c
drivers/regulator/wm8350-regulator.c
+2
-2
drivers/regulator/wm8994-regulator.c
drivers/regulator/wm8994-regulator.c
+21
-12
drivers/spi/spi-qcom-qspi.c
drivers/spi/spi-qcom-qspi.c
+4
-4
include/dt-bindings/regulator/active-semi,8945a-regulator.h
include/dt-bindings/regulator/active-semi,8945a-regulator.h
+30
-0
include/linux/gpio/consumer.h
include/linux/gpio/consumer.h
+23
-0
include/linux/mfd/axp20x.h
include/linux/mfd/axp20x.h
+2
-2
include/linux/mfd/wm8994/pdata.h
include/linux/mfd/wm8994/pdata.h
+0
-3
include/linux/regulator/driver.h
include/linux/regulator/driver.h
+6
-3
include/linux/regulator/machine.h
include/linux/regulator/machine.h
+3
-0
include/linux/regulator/pfuze100.h
include/linux/regulator/pfuze100.h
+2
-1
No files found.
Documentation/devicetree/bindings/mfd/axp20x.txt
View file @
b27d9668
...
...
@@ -32,6 +32,15 @@ Required properties:
- interrupt-controller: The PMIC has its own internal IRQs
- #interrupt-cells: Should be set to 1
Supported common regulator properties, see ../regulator/regulator.txt for
more information:
- regulator-ramp-delay: sets the ramp up delay in uV/us
AXP20x/DCDC2: 1600, 800
AXP20x/LDO3: 1600, 800
- regulator-soft-start: enable the output at the lowest possible voltage and
only then set the desired voltage
AXP20x/LDO3: software-based implementation
Optional properties:
- x-powers,dcdc-freq: defines the work frequency of DC-DC in KHz
AXP152/20X: range: 750-1875, Default: 1.5 MHz
...
...
Documentation/devicetree/bindings/regulator/act8945a-regulator.txt
View file @
b27d9668
...
...
@@ -15,11 +15,17 @@ Optional input supply properties:
- inl67-supply: The input supply for REG_LDO3 and REG_LDO4
Any standard regulator properties can be used to configure the single regulator.
regulator-initial-mode, regulator-allowed-modes and regulator-mode could be
specified using mode values from dt-bindings/regulator/active-semi,8945a-regulator.h
file.
The valid names for regulators are:
REG_DCDC1, REG_DCDC2, REG_DCDC3, REG_LDO1, REG_LDO2, REG_LDO3, REG_LDO4.
Example:
#include <dt-bindings/regulator/active-semi,8945a-regulator.h>
pmic@5b {
compatible = "active-semi,act8945a";
reg = <0x5b>;
...
...
@@ -32,6 +38,18 @@ Example:
regulator-min-microvolt = <1350000>;
regulator-max-microvolt = <1350000>;
regulator-always-on;
regulator-allowed-modes = <ACT8945A_REGULATOR_MODE_FIXED>,
<ACT8945A_REGULATOR_MODE_LOWPOWER>;
regulator-initial-mode = <ACT8945A_REGULATOR_MODE_FIXED>;
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-min-microvolt=<1400000>;
regulator-suspend-max-microvolt=<1400000>;
regulator-changeable-in-suspend;
regulator-mode=<ACT8945A_REGULATOR_MODE_LOWPOWER>;
};
};
vdd_1v2_reg: REG_DCDC2 {
...
...
@@ -39,6 +57,14 @@ Example:
regulator-min-microvolt = <1100000>;
regulator-max-microvolt = <1300000>;
regulator-always-on;
regulator-allowed-modes = <ACT8945A_REGULATOR_MODE_FIXED>,
<ACT8945A_REGULATOR_MODE_LOWPOWER>;
regulator-initial-mode = <ACT8945A_REGULATOR_MODE_FIXED>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
vdd_3v3_reg: REG_DCDC3 {
...
...
@@ -53,6 +79,14 @@ Example:
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <2500000>;
regulator-always-on;
regulator-allowed-modes = <ACT8945A_REGULATOR_MODE_NORMAL>,
<ACT8945A_REGULATOR_MODE_LOWPOWER>;
regulator-initial-mode = <ACT8945A_REGULATOR_MODE_NORMAL>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
vdd_3v3_lp_reg: REG_LDO2 {
...
...
Documentation/devicetree/bindings/regulator/cirrus,lochnagar.txt
0 → 100644
View file @
b27d9668
Cirrus Logic Lochnagar Audio Development Board
Lochnagar is an evaluation and development board for Cirrus Logic
Smart CODEC and Amp devices. It allows the connection of most Cirrus
Logic devices on mini-cards, as well as allowing connection of
various application processor systems to provide a full evaluation
platform. Audio system topology, clocking and power can all be
controlled through the Lochnagar, allowing the device under test
to be used in a variety of possible use cases.
This binding document describes the binding for the regulator portion
of the driver.
Also see these documents for generic binding information:
[1] Regulator: ../regulator/regulator.txt
This binding must be part of the Lochnagar MFD binding:
[2] ../mfd/cirrus,lochnagar.txt
Optional sub-nodes:
- VDDCORE : Initialisation data for the VDDCORE regulator, which
supplies the CODECs digital core if it has no build regulator for that
purpose.
Required Properties:
- compatible : One of the following strings:
"cirrus,lochnagar2-vddcore"
- SYSVDD-supply: Primary power supply for the Lochnagar.
- MICVDD : Initialisation data for the MICVDD regulator, which
supplies the CODECs MICVDD.
Required Properties:
- compatible : One of the following strings:
"cirrus,lochnagar2-micvdd"
- SYSVDD-supply: Primary power supply for the Lochnagar.
- MIC1VDD, MIC2VDD : Initialisation data for the MICxVDD supplies.
Required Properties:
- compatible : One of the following strings:
"cirrus,lochnagar2-mic1vdd", "cirrus,lochnagar2-mic2vdd"
Optional Properties:
- cirrus,micbias-input : A property selecting which of the CODEC
minicard micbias outputs should be used, valid values are 1 - 4.
- MICBIAS1-supply, MICBIAS2-supply: Regulator supplies for the
MICxVDD outputs, supplying the digital microphones, normally
supplied from the attached CODEC.
- VDD1V8 : Recommended fixed regulator for the VDD1V8 regulator, which supplies the
CODECs analog and 1.8V digital supplies.
Required Properties:
- compatible : Should be set to "regulator-fixed"
- regulator-min-microvolt : Should be set to 1.8V
- regulator-max-microvolt : Should be set to 1.8V
- regulator-boot-on
- regulator-always-on
- vin-supply : Should be set to same supply as SYSVDD
Example:
lochnagar {
lochnagar-micvdd: MICVDD {
compatible = "cirrus,lochnagar2-micvdd";
SYSVDD-supply = <&wallvdd>;
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
lochnagar-vdd1v8: VDD1V8 {
compatible = "regulator-fixed";
regulator-name = "VDD1V8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-always-on;
vin-supply = <&wallvdd>;
};
};
Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt
0 → 100644
View file @
b27d9668
MCP16502 PMIC
Required properties:
- compatible: "microchip,mcp16502"
- reg: I2C slave address
- lpm-gpios: GPIO for LPM pin. Note that this GPIO *must* remain high during
suspend-to-ram, keeping the PMIC into HIBERNATE mode.
- regulators: A node that houses a sub-node for each regulator within
the device. Each sub-node is identified using the node's
name. The content of each sub-node is defined by the
standard binding for regulators; see regulator.txt.
Regualtors of MCP16502 PMIC:
1) VDD_IO - Buck (1.2 - 3.7 V)
2) VDD_DDR - Buck (0.6 - 1.85 V)
3) VDD_CORE - Buck (0.6 - 1.85 V)
4) VDD_OTHER - BUCK (0.6 - 1.85 V)
5) LDO1 - LDO (1.2 - 3.7 V)
6) LDO2 - LDO (1.2 - 3.7 V)
Regulator modes:
2 - FPWM: higher precision, higher consumption
4 - AutoPFM: lower precision, lower consumption
Each regulator is defined using the standard binding for regulators.
Example:
mcp16502@5b {
compatible = "microchip,mcp16502";
reg = <0x5b>;
status = "okay";
lpm-gpios = <&pioBU 7 GPIO_ACTIVE_HIGH>;
regulators {
VDD_IO {
regulator-name = "VDD_IO";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3700000>;
regulator-initial-mode = <2>;
regulator-allowed-modes = <2>, <4>;
regulator-always-on;
regulator-state-standby {
regulator-on-in-suspend;
regulator-mode = <4>;
};
regulator-state-mem {
regulator-off-in-suspend;
regulator-mode = <4>;
};
};
VDD_DDR {
regulator-name = "VDD_DDR";
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <1850000>;
regulator-initial-mode = <2>;
regulator-allowed-modes = <2>, <4>;
regulator-always-on;
regulator-state-standby {
regulator-on-in-suspend;
regulator-mode = <4>;
};
regulator-state-mem {
regulator-on-in-suspend;
regulator-mode = <4>;
};
};
VDD_CORE {
regulator-name = "VDD_CORE";
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <1850000>;
regulator-initial-mode = <2>;
regulator-allowed-modes = <2>, <4>;
regulator-always-on;
regulator-state-standby {
regulator-on-in-suspend;
regulator-mode = <4>;
};
regulator-state-mem {
regulator-off-in-suspend;
regulator-mode = <4>;
};
};
VDD_OTHER {
regulator-name = "VDD_OTHER";
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <1850000>;
regulator-initial-mode = <2>;
regulator-allowed-modes = <2>, <4>;
regulator-always-on;
regulator-state-standby {
regulator-on-in-suspend;
regulator-mode = <4>;
};
regulator-state-mem {
regulator-off-in-suspend;
regulator-mode = <4>;
};
};
LDO1 {
regulator-name = "LDO1";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3700000>;
regulator-always-on;
regulator-state-standby {
regulator-on-in-suspend;
};
regulator-state-mem {
regulator-off-in-suspend;
};
};
LDO2 {
regulator-name = "LDO2";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3700000>;
regulator-always-on;
regulator-state-standby {
regulator-on-in-suspend;
};
regulator-state-mem {
regulator-off-in-suspend;
};
};
};
};
Documentation/devicetree/bindings/regulator/regulator.txt
View file @
b27d9668
...
...
@@ -33,13 +33,16 @@ Optional properties:
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] node has following common properties:
- 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
...
...
@@ -76,8 +79,11 @@ Optional properties:
- 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: Max spread between voltages of coupled regulators
in microvolts.
- 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
...
...
Documentation/driver-model/devres.txt
View file @
b27d9668
...
...
@@ -254,6 +254,7 @@ GPIO
devm_gpiod_get_index_optional()
devm_gpiod_get_optional()
devm_gpiod_put()
devm_gpiod_unhinge()
devm_gpiochip_add_data()
devm_gpiochip_remove()
devm_gpio_request()
...
...
MAINTAINERS
View file @
b27d9668
...
...
@@ -9818,6 +9818,13 @@ M: Ludovic Desroches <ludovic.desroches@microchip.com>
S: Maintained
F: drivers/mmc/host/atmel-mci.c
MICROCHIP MCP16502 PMIC DRIVER
M: Andrei Stefanescu <andrei.stefanescu@microchip.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt
F: drivers/regulator/mcp16502.c
MICROCHIP MCP3911 ADC DRIVER
M: Marcus Folkesson <marcus.folkesson@gmail.com>
M: Kent Gustavsson <kent@minoris.se>
...
...
arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts
View file @
b27d9668
...
...
@@ -245,6 +245,8 @@ ®_ldo3 {
regulator
-
min
-
microvolt
=
<
2800000
>;
regulator
-
max
-
microvolt
=
<
2800000
>;
regulator
-
name
=
"vddio-csi0"
;
regulator
-
soft
-
start
;
regulator
-
ramp
-
delay
=
<
1600
>;
};
&
reg_ldo4
{
...
...
arch/arm/mach-s3c64xx/mach-crag6410-module.c
View file @
b27d9668
...
...
@@ -194,8 +194,8 @@ static struct wm8994_pdata wm8994_pdata = {
0x3
,
/* IRQ out, active high, CMOS */
},
.
ldo
=
{
{
.
enable
=
S3C64XX_GPN
(
6
),
.
init_data
=
&
wm8994_ldo1
,
},
{
.
enable
=
S3C64XX_GPN
(
4
),
.
init_data
=
&
wm8994_ldo2
,
},
{
.
init_data
=
&
wm8994_ldo1
,
},
{
.
init_data
=
&
wm8994_ldo2
,
},
},
};
...
...
@@ -203,6 +203,18 @@ static const struct i2c_board_info wm1277_devs[] = {
{
I2C_BOARD_INFO
(
"wm8958"
,
0x1a
),
/* WM8958 is the superset */
.
platform_data
=
&
wm8994_pdata
,
.
irq
=
GLENFARCLAS_PMIC_IRQ_BASE
+
WM831X_IRQ_GPIO_2
,
.
dev_name
=
"wm8958"
,
},
};
static
struct
gpiod_lookup_table
wm8994_gpiod_table
=
{
.
dev_id
=
"i2c-wm8958"
,
/* I2C device name */
.
table
=
{
GPIO_LOOKUP
(
"GPION"
,
6
,
"wlf,ldo1ena"
,
GPIO_ACTIVE_HIGH
),
GPIO_LOOKUP
(
"GPION"
,
4
,
"wlf,ldo2ena"
,
GPIO_ACTIVE_HIGH
),
{
},
},
};
...
...
@@ -381,6 +393,7 @@ static int wlf_gf_module_probe(struct i2c_client *i2c,
gpiod_add_lookup_table
(
&
wm5102_reva_gpiod_table
);
gpiod_add_lookup_table
(
&
wm5102_gpiod_table
);
gpiod_add_lookup_table
(
&
wm8994_gpiod_table
);
if
(
i
<
ARRAY_SIZE
(
gf_mods
))
{
dev_info
(
&
i2c
->
dev
,
"%s revision %d
\n
"
,
...
...
drivers/gpio/gpiolib-devres.c
View file @
b27d9668
...
...
@@ -98,15 +98,28 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
struct
gpio_desc
**
dr
;
struct
gpio_desc
*
desc
;
desc
=
gpiod_get_index
(
dev
,
con_id
,
idx
,
flags
);
if
(
IS_ERR
(
desc
))
return
desc
;
/*
* For non-exclusive GPIO descriptors, check if this descriptor is
* already under resource management by this device.
*/
if
(
flags
&
GPIOD_FLAGS_BIT_NONEXCLUSIVE
)
{
struct
devres
*
dres
;
dres
=
devres_find
(
dev
,
devm_gpiod_release
,
devm_gpiod_match
,
&
desc
);
if
(
dres
)
return
desc
;
}
dr
=
devres_alloc
(
devm_gpiod_release
,
sizeof
(
struct
gpio_desc
*
),
GFP_KERNEL
);
if
(
!
dr
)
if
(
!
dr
)
{
gpiod_put
(
desc
);
return
ERR_PTR
(
-
ENOMEM
);
desc
=
gpiod_get_index
(
dev
,
con_id
,
idx
,
flags
);
if
(
IS_ERR
(
desc
))
{
devres_free
(
dr
);
return
desc
;
}
*
dr
=
desc
;
...
...
@@ -140,15 +153,28 @@ struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
struct
gpio_desc
**
dr
;
struct
gpio_desc
*
desc
;
desc
=
gpiod_get_from_of_node
(
node
,
propname
,
index
,
dflags
,
label
);
if
(
IS_ERR
(
desc
))
return
desc
;
/*
* For non-exclusive GPIO descriptors, check if this descriptor is
* already under resource management by this device.
*/
if
(
dflags
&
GPIOD_FLAGS_BIT_NONEXCLUSIVE
)
{
struct
devres
*
dres
;
dres
=
devres_find
(
dev
,
devm_gpiod_release
,
devm_gpiod_match
,
&
desc
);
if
(
dres
)
return
desc
;
}
dr
=
devres_alloc
(
devm_gpiod_release
,
sizeof
(
struct
gpio_desc
*
),
GFP_KERNEL
);
if
(
!
dr
)
if
(
!
dr
)
{
gpiod_put
(
desc
);
return
ERR_PTR
(
-
ENOMEM
);
desc
=
gpiod_get_from_of_node
(
node
,
propname
,
index
,
dflags
,
label
);
if
(
IS_ERR
(
desc
))
{
devres_free
(
dr
);
return
desc
;
}
*
dr
=
desc
;
...
...
@@ -320,6 +346,36 @@ void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
}
EXPORT_SYMBOL
(
devm_gpiod_put
);
/**
* devm_gpiod_unhinge - Remove resource management from a gpio descriptor
* @dev: GPIO consumer
* @desc: GPIO descriptor to remove resource management from
*
* Remove resource management from a GPIO descriptor. This is needed when
* you want to hand over lifecycle management of a descriptor to another
* mechanism.
*/
void
devm_gpiod_unhinge
(
struct
device
*
dev
,
struct
gpio_desc
*
desc
)
{
int
ret
;
if
(
IS_ERR_OR_NULL
(
desc
))
return
;
ret
=
devres_destroy
(
dev
,
devm_gpiod_release
,
devm_gpiod_match
,
&
desc
);
/*
* If the GPIO descriptor is requested as nonexclusive, we
* may call this function several times on the same descriptor
* so it is OK if devres_destroy() returns -ENOENT.
*/
if
(
ret
==
-
ENOENT
)
return
;
/* Anything else we should warn about */
WARN_ON
(
ret
);
}
EXPORT_SYMBOL
(
devm_gpiod_unhinge
);
/**
* devm_gpiod_put_array - Resource-managed gpiod_put_array()
* @dev: GPIO consumer
...
...
drivers/gpio/gpiolib.c
View file @
b27d9668
...
...
@@ -4205,6 +4205,8 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
transitory
=
flags
&
OF_GPIO_TRANSITORY
;
ret
=
gpiod_request
(
desc
,
label
);
if
(
ret
==
-
EBUSY
&&
(
flags
&
GPIOD_FLAGS_BIT_NONEXCLUSIVE
))
return
desc
;
if
(
ret
)
return
ERR_PTR
(
ret
);
...
...
drivers/gpio/gpiolib.h
View file @
b27d9668
...
...
@@ -201,12 +201,6 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
struct
gpio_array
*
array_info
,
unsigned
long
*
value_bitmap
);
/* This is just passed between gpiolib and devres */
struct
gpio_desc
*
gpiod_get_from_of_node
(
struct
device_node
*
node
,
const
char
*
propname
,
int
index
,
enum
gpiod_flags
dflags
,
const
char
*
label
);
extern
struct
spinlock
gpio_lock
;
extern
struct
list_head
gpio_devices
;
...
...
drivers/mfd/axp20x.c
View file @
b27d9668
...
...
@@ -16,20 +16,21 @@
* published by the Free Software Foundation.
*/
#include <linux/err.h>
#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mfd/axp20x.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/mfd/axp20x.h>
#include <linux/mfd/core.h>
#include <linux/of_device.h>
#include <linux/acpi.h>
#define AXP20X_OFF
0x80
#define AXP20X_OFF
BIT(7)
#define AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE 0
#define AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE BIT(4)
...
...
drivers/mfd/wm8994-core.c
View file @
b27d9668
...
...
@@ -21,7 +21,6 @@
#include <linux/mfd/core.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
...
...
@@ -306,14 +305,6 @@ static int wm8994_set_pdata_from_of(struct wm8994 *wm8994)
pdata
->
csnaddr_pd
=
of_property_read_bool
(
np
,
"wlf,csnaddr-pd"
);
pdata
->
ldo
[
0
].
enable
=
of_get_named_gpio
(
np
,
"wlf,ldo1ena"
,
0
);
if
(
pdata
->
ldo
[
0
].
enable
<
0
)
pdata
->
ldo
[
0
].
enable
=
0
;
pdata
->
ldo
[
1
].
enable
=
of_get_named_gpio
(
np
,
"wlf,ldo2ena"
,
0
);
if
(
pdata
->
ldo
[
1
].
enable
<
0
)
pdata
->
ldo
[
1
].
enable
=
0
;
return
0
;
}
#else
...
...
drivers/regulator/88pm8607.c
View file @
b27d9668
...
...
@@ -328,7 +328,7 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev,
return
-
ENODEV
;
}
for_each_child_of_node
(
nproot
,
np
)
{
if
(
!
of_node_cmp
(
np
->
name
,
info
->
desc
.
name
))
{
if
(
of_node_name_eq
(
np
,
info
->
desc
.
name
))
{
config
->
init_data
=
of_get_regulator_init_data
(
&
pdev
->
dev
,
np
,
&
info
->
desc
);
...
...
drivers/regulator/Kconfig
View file @
b27d9668
...
...
@@ -567,6 +567,16 @@ config REGULATOR_MC13892
Say y here to support the regulators found on the Freescale MC13892
PMIC.
config REGULATOR_MCP16502
tristate "Microchip MCP16502 PMIC"
depends on I2C && OF
select REGMAP_I2C
help
Say y here to support the MCP16502 PMIC. This driver supports
basic operations (get/set voltage, get/set operating mode)
through the regulator interface. In addition it enables
suspend-to-ram/standby transition.
config REGULATOR_MT6311
tristate "MediaTek MT6311 PMIC"
depends on I2C
...
...
drivers/regulator/Makefile
View file @
b27d9668
...
...
@@ -74,6 +74,7 @@ obj-$(CONFIG_REGULATOR_MAX77802) += max77802-regulator.o
obj-$(CONFIG_REGULATOR_MC13783)
+=
mc13783-regulator.o
obj-$(CONFIG_REGULATOR_MC13892)
+=
mc13892-regulator.o
obj-$(CONFIG_REGULATOR_MC13XXX_CORE)
+=
mc13xxx-regulator-core.o
obj-$(CONFIG_REGULATOR_MCP16502)
+=
mcp16502.o
obj-$(CONFIG_REGULATOR_MT6311)
+=
mt6311-regulator.o
obj-$(CONFIG_REGULATOR_MT6323)
+=
mt6323-regulator.o
obj-$(CONFIG_REGULATOR_MT6380)
+=
mt6380-regulator.o
...
...
drivers/regulator/act8945a-regulator.c
View file @
b27d9668
...
...
@@ -15,31 +15,41 @@
#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/machine.h>
#include <dt-bindings/regulator/active-semi,8945a-regulator.h>
/**
* ACT8945A Global Register Map.
*/
#define ACT8945A_SYS_MODE 0x00
#define ACT8945A_SYS_CTRL 0x01
#define ACT8945A_SYS_UNLK_REGS 0x0b
#define ACT8945A_DCDC1_VSET1 0x20
#define ACT8945A_DCDC1_VSET2 0x21
#define ACT8945A_DCDC1_CTRL 0x22
#define ACT8945A_DCDC1_SUS 0x24
#define ACT8945A_DCDC2_VSET1 0x30
#define ACT8945A_DCDC2_VSET2 0x31
#define ACT8945A_DCDC2_CTRL 0x32
#define ACT8945A_DCDC2_SUS 0x34
#define ACT8945A_DCDC3_VSET1 0x40
#define ACT8945A_DCDC3_VSET2 0x41
#define ACT8945A_DCDC3_CTRL 0x42
#define ACT8945A_DCDC3_SUS 0x44
#define ACT8945A_LDO1_VSET 0x50
#define ACT8945A_LDO1_CTRL 0x51
#define ACT8945A_LDO1_SUS 0x52
#define ACT8945A_LDO2_VSET 0x54
#define ACT8945A_LDO2_CTRL 0x55
#define ACT8945A_LDO2_SUS 0x56
#define ACT8945A_LDO3_VSET 0x60
#define ACT8945A_LDO3_CTRL 0x61
#define ACT8945A_LDO3_SUS 0x62
#define ACT8945A_LDO4_VSET 0x64
#define ACT8945A_LDO4_CTRL 0x65
#define ACT8945A_LDO4_SUS 0x66
/**
* Field Definitions.
...
...
@@ -60,7 +70,12 @@ enum {
ACT8945A_ID_LDO2
,
ACT8945A_ID_LDO3
,
ACT8945A_ID_LDO4
,
ACT8945A_REG_NUM
,
ACT8945A_ID_MAX
,
};
struct
act8945a_pmic
{
struct
regmap
*
regmap
;
u32
op_mode
[
ACT8945A_ID_MAX
];
};
static
const
struct
regulator_linear_range
act8945a_voltage_ranges
[]
=
{
...
...
@@ -69,6 +84,143 @@ static const struct regulator_linear_range act8945a_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE
(
2400000
,
48
,
63
,
100000
),
};
static
int
act8945a_set_suspend_state
(
struct
regulator_dev
*
rdev
,
bool
enable
)
{
struct
regmap
*
regmap
=
rdev
->
regmap
;
int
id
=
rdev
->
desc
->
id
,
reg
,
val
;
switch
(
id
)
{
case
ACT8945A_ID_DCDC1
:
reg
=
ACT8945A_DCDC1_SUS
;
val
=
0xa8
;
break
;
case
ACT8945A_ID_DCDC2
:
reg
=
ACT8945A_DCDC2_SUS
;
val
=
0xa8
;
break
;
case
ACT8945A_ID_DCDC3
:
reg
=
ACT8945A_DCDC3_SUS
;
val
=
0xa8
;
break
;
case
ACT8945A_ID_LDO1
:
reg
=
ACT8945A_LDO1_SUS
;
val
=
0xe8
;
break
;
case
ACT8945A_ID_LDO2
:
reg
=
ACT8945A_LDO2_SUS
;
val
=
0xe8
;
break
;
case
ACT8945A_ID_LDO3
:
reg
=
ACT8945A_LDO3_SUS
;
val
=
0xe8
;
break
;
case
ACT8945A_ID_LDO4
:
reg
=
ACT8945A_LDO4_SUS
;
val
=
0xe8
;
break
;
default:
return
-
EINVAL
;
}
if
(
enable
)
val
|=
BIT
(
4
);
/*
* Ask the PMIC to enable/disable this output when entering hibernate
* mode.
*/
return
regmap_write
(
regmap
,
reg
,
val
);
}
static
int
act8945a_set_suspend_enable
(
struct
regulator_dev
*
rdev
)
{
return
act8945a_set_suspend_state
(
rdev
,
true
);
}
static
int
act8945a_set_suspend_disable
(
struct
regulator_dev
*
rdev
)
{
return
act8945a_set_suspend_state
(
rdev
,
false
);
}
static
unsigned
int
act8945a_of_map_mode
(
unsigned
int
mode
)
{
switch
(
mode
)
{
case
ACT8945A_REGULATOR_MODE_FIXED
:
case
ACT8945A_REGULATOR_MODE_NORMAL
:
return
REGULATOR_MODE_NORMAL
;
case
ACT8945A_REGULATOR_MODE_LOWPOWER
:
return
REGULATOR_MODE_STANDBY
;
default:
return
REGULATOR_MODE_INVALID
;
}
}
static
int
act8945a_set_mode
(
struct
regulator_dev
*
rdev
,
unsigned
int
mode
)
{
struct
act8945a_pmic
*
act8945a
=
rdev_get_drvdata
(
rdev
);
struct
regmap
*
regmap
=
rdev
->
regmap
;
int
id
=
rdev
->
desc
->
id
;
int
reg
,
ret
,
val
=
0
;
switch
(
id
)
{
case
ACT8945A_ID_DCDC1
:
reg
=
ACT8945A_DCDC1_CTRL
;
break
;
case
ACT8945A_ID_DCDC2
:
reg
=
ACT8945A_DCDC2_CTRL
;
break
;
case
ACT8945A_ID_DCDC3
:
reg
=
ACT8945A_DCDC3_CTRL
;
break
;
case
ACT8945A_ID_LDO1
:
reg
=
ACT8945A_LDO1_SUS
;
break
;
case
ACT8945A_ID_LDO2
:
reg
=
ACT8945A_LDO2_SUS
;
break
;
case
ACT8945A_ID_LDO3
:
reg
=
ACT8945A_LDO3_SUS
;
break
;
case
ACT8945A_ID_LDO4
:
reg
=
ACT8945A_LDO4_SUS
;
break
;
default:
return
-
EINVAL
;
}
switch
(
mode
)
{
case
REGULATOR_MODE_STANDBY
:
if
(
rdev
->
desc
->
id
>
ACT8945A_ID_DCDC3
)
val
=
BIT
(
5
);
break
;
case
REGULATOR_MODE_NORMAL
:
if
(
rdev
->
desc
->
id
<=
ACT8945A_ID_DCDC3
)
val
=
BIT
(
5
);
break
;
default:
return
-
EINVAL
;
}
ret
=
regmap_update_bits
(
regmap
,
reg
,
BIT
(
5
),
val
);
if
(
ret
)
return
ret
;
act8945a
->
op_mode
[
id
]
=
mode
;
return
0
;
}
static
unsigned
int
act8945a_get_mode
(
struct
regulator_dev
*
rdev
)
{
struct
act8945a_pmic
*
act8945a
=
rdev_get_drvdata
(
rdev
);
int
id
=
rdev
->
desc
->
id
;
if
(
id
<
ACT8945A_ID_DCDC1
||
id
>=
ACT8945A_ID_MAX
)
return
-
EINVAL
;
return
act8945a
->
op_mode
[
id
];
}
static
const
struct
regulator_ops
act8945a_ops
=
{
.
list_voltage
=
regulator_list_voltage_linear_range
,
.
map_voltage
=
regulator_map_voltage_linear_range
,
...
...
@@ -76,7 +228,11 @@ static const struct regulator_ops act8945a_ops = {
.
set_voltage_sel
=
regulator_set_voltage_sel_regmap
,
.
enable
=
regulator_enable_regmap
,
.
disable
=
regulator_disable_regmap
,
.
set_mode
=
act8945a_set_mode
,
.
get_mode
=
act8945a_get_mode
,
.
is_enabled
=
regulator_is_enabled_regmap
,
.
set_suspend_enable
=
act8945a_set_suspend_enable
,
.
set_suspend_disable
=
act8945a_set_suspend_disable
,
};
#define ACT89xx_REG(_name, _family, _id, _vsel_reg, _supply) \
...
...
@@ -84,6 +240,7 @@ static const struct regulator_ops act8945a_ops = {
.name = _name, \
.supply_name = _supply, \
.of_match = of_match_ptr("REG_"#_id), \
.of_map_mode = act8945a_of_map_mode, \
.regulators_node = of_match_ptr("regulators"), \
.id = _family##_ID_##_id, \
.type = REGULATOR_VOLTAGE, \
...
...
@@ -122,10 +279,22 @@ static int act8945a_pmic_probe(struct platform_device *pdev)
{
struct
regulator_config
config
=
{
};
const
struct
regulator_desc
*
regulators
;
struct
act8945a_pmic
*
act8945a
;
struct
regulator_dev
*
rdev
;
int
i
,
num_regulators
;
bool
voltage_select
;
act8945a
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
act8945a
),
GFP_KERNEL
);
if
(
!
act8945a
)
return
-
ENOMEM
;
act8945a
->
regmap
=
dev_get_regmap
(
pdev
->
dev
.
parent
,
NULL
);
if
(
!
act8945a
->
regmap
)
{
dev_err
(
&
pdev
->
dev
,
"could not retrieve regmap from parent device
\n
"
);
return
-
EINVAL
;
}
voltage_select
=
of_property_read_bool
(
pdev
->
dev
.
parent
->
of_node
,
"active-semi,vsel-high"
);
...
...
@@ -139,8 +308,10 @@ static int act8945a_pmic_probe(struct platform_device *pdev)
config
.
dev
=
&
pdev
->
dev
;
config
.
dev
->
of_node
=
pdev
->
dev
.
parent
->
of_node
;
config
.
driver_data
=
act8945a
;
for
(
i
=
0
;
i
<
num_regulators
;
i
++
)
{
rdev
=
devm_regulator_register
(
&
pdev
->
dev
,
&
regulators
[
i
],
&
config
);
rdev
=
devm_regulator_register
(
&
pdev
->
dev
,
&
regulators
[
i
],
&
config
);
if
(
IS_ERR
(
rdev
))
{
dev_err
(
&
pdev
->
dev
,
"failed to register %s regulator
\n
"
,
...
...
@@ -149,14 +320,42 @@ static int act8945a_pmic_probe(struct platform_device *pdev)
}
}
return
0
;
platform_set_drvdata
(
pdev
,
act8945a
);
/* Unlock expert registers. */
return
regmap_write
(
act8945a
->
regmap
,
ACT8945A_SYS_UNLK_REGS
,
0xef
);
}
static
int
__maybe_unused
act8945a_suspend
(
struct
device
*
pdev
)
{
struct
act8945a_pmic
*
act8945a
=
dev_get_drvdata
(
pdev
);
/*
* Ask the PMIC to enter the suspend mode on the next PWRHLD
* transition.
*/
return
regmap_write
(
act8945a
->
regmap
,
ACT8945A_SYS_CTRL
,
0x42
);
}
static
SIMPLE_DEV_PM_OPS
(
act8945a_pm
,
act8945a_suspend
,
NULL
);
static
void
act8945a_pmic_shutdown
(
struct
platform_device
*
pdev
)
{
struct
act8945a_pmic
*
act8945a
=
platform_get_drvdata
(
pdev
);
/*
* Ask the PMIC to shutdown everything on the next PWRHLD transition.
*/
regmap_write
(
act8945a
->
regmap
,
ACT8945A_SYS_CTRL
,
0x0
);
}
static
struct
platform_driver
act8945a_pmic_driver
=
{
.
driver
=
{
.
name
=
"act8945a-regulator"
,
.
pm
=
&
act8945a_pm
,
},
.
probe
=
act8945a_pmic_probe
,
.
shutdown
=
act8945a_pmic_shutdown
,
};
module_platform_driver
(
act8945a_pmic_driver
);
...
...
drivers/regulator/arizona-ldo1.c
View file @
b27d9668
...
...
@@ -283,9 +283,6 @@ static int arizona_ldo1_common_init(struct platform_device *pdev,
of_node_put
(
config
.
of_node
);
if
(
IS_ERR
(
ldo1
->
regulator
))
{
if
(
config
.
ena_gpiod
)
gpiod_put
(
config
.
ena_gpiod
);
ret
=
PTR_ERR
(
ldo1
->
regulator
);
dev_err
(
&
pdev
->
dev
,
"Failed to register LDO1 supply: %d
\n
"
,
ret
);
...
...
drivers/regulator/as3711-regulator.c
View file @
b27d9668
// SPDX-License-Identifier: GPL-2.0
/*
* AS3711 PMIC regulator driver, using DCDC Step Down and LDO supplies
*
* Copyright (C) 2012 Renesas Electronics Corporation
* Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the version 2 of the GNU General Public License as
* published by the Free Software Foundation
*/
#include <linux/err.h>
...
...
drivers/regulator/axp20x-regulator.c
View file @
b27d9668
...
...
@@ -13,31 +13,262 @@
* GNU General Public License for more details.
*/
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/mfd/axp20x.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/mfd/axp20x.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#define AXP20X_GPIO0_FUNC_MASK GENMASK(3, 0)
#define AXP20X_GPIO1_FUNC_MASK GENMASK(3, 0)
#define AXP20X_IO_ENABLED 0x03
#define AXP20X_IO_DISABLED 0x07
#define AXP20X_WORKMODE_DCDC2_MASK BIT_MASK(2)
#define AXP20X_WORKMODE_DCDC3_MASK BIT_MASK(1)
#define AXP20X_FREQ_DCDC_MASK GENMASK(3, 0)
#define AXP20X_VBUS_IPSOUT_MGMT_MASK BIT_MASK(2)
#define AXP20X_DCDC2_V_OUT_MASK GENMASK(5, 0)
#define AXP20X_DCDC3_V_OUT_MASK GENMASK(7, 0)
#define AXP20X_LDO24_V_OUT_MASK GENMASK(7, 4)
#define AXP20X_LDO3_V_OUT_MASK GENMASK(6, 0)
#define AXP20X_LDO5_V_OUT_MASK GENMASK(7, 4)
#define AXP20X_PWR_OUT_EXTEN_MASK BIT_MASK(0)
#define AXP20X_PWR_OUT_DCDC3_MASK BIT_MASK(1)
#define AXP20X_PWR_OUT_LDO2_MASK BIT_MASK(2)
#define AXP20X_PWR_OUT_LDO4_MASK BIT_MASK(3)
#define AXP20X_PWR_OUT_DCDC2_MASK BIT_MASK(4)
#define AXP20X_PWR_OUT_LDO3_MASK BIT_MASK(6)
#define AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_RATE_MASK BIT_MASK(0)
#define AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_RATE(x) \
((x) << 0)
#define AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE_MASK BIT_MASK(1)
#define AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE(x) \
((x) << 1)
#define AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN_MASK BIT_MASK(2)
#define AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN BIT(2)
#define AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN_MASK BIT_MASK(3)
#define AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN BIT(3)
#define AXP20X_LDO4_V_OUT_1250mV_START 0x0
#define AXP20X_LDO4_V_OUT_1250mV_STEPS 0
#define AXP20X_LDO4_V_OUT_1250mV_END \
(AXP20X_LDO4_V_OUT_1250mV_START + AXP20X_LDO4_V_OUT_1250mV_STEPS)
#define AXP20X_LDO4_V_OUT_1300mV_START 0x1
#define AXP20X_LDO4_V_OUT_1300mV_STEPS 7
#define AXP20X_LDO4_V_OUT_1300mV_END \
(AXP20X_LDO4_V_OUT_1300mV_START + AXP20X_LDO4_V_OUT_1300mV_STEPS)
#define AXP20X_LDO4_V_OUT_2500mV_START 0x9
#define AXP20X_LDO4_V_OUT_2500mV_STEPS 0
#define AXP20X_LDO4_V_OUT_2500mV_END \
(AXP20X_LDO4_V_OUT_2500mV_START + AXP20X_LDO4_V_OUT_2500mV_STEPS)
#define AXP20X_LDO4_V_OUT_2700mV_START 0xa
#define AXP20X_LDO4_V_OUT_2700mV_STEPS 1
#define AXP20X_LDO4_V_OUT_2700mV_END \
(AXP20X_LDO4_V_OUT_2700mV_START + AXP20X_LDO4_V_OUT_2700mV_STEPS)
#define AXP20X_LDO4_V_OUT_3000mV_START 0xc
#define AXP20X_LDO4_V_OUT_3000mV_STEPS 3
#define AXP20X_LDO4_V_OUT_3000mV_END \
(AXP20X_LDO4_V_OUT_3000mV_START + AXP20X_LDO4_V_OUT_3000mV_STEPS)
#define AXP20X_LDO4_V_OUT_NUM_VOLTAGES 16
#define AXP22X_IO_ENABLED 0x03
#define AXP22X_IO_DISABLED 0x04
#define AXP20X_WORKMODE_DCDC2_MASK BIT(2)
#define AXP20X_WORKMODE_DCDC3_MASK BIT(1)
#define AXP22X_WORKMODE_DCDCX_MASK(x) BIT(x)
#define AXP20X_FREQ_DCDC_MASK 0x0f
#define AXP22X_WORKMODE_DCDCX_MASK(x) BIT_MASK(x)
#define AXP22X_MISC_N_VBUSEN_FUNC BIT(4)
#define AXP22X_DCDC1_V_OUT_MASK GENMASK(4, 0)
#define AXP22X_DCDC2_V_OUT_MASK GENMASK(5, 0)
#define AXP22X_DCDC3_V_OUT_MASK GENMASK(5, 0)
#define AXP22X_DCDC4_V_OUT_MASK GENMASK(5, 0)
#define AXP22X_DCDC5_V_OUT_MASK GENMASK(4, 0)
#define AXP22X_DC5LDO_V_OUT_MASK GENMASK(2, 0)
#define AXP22X_ALDO1_V_OUT_MASK GENMASK(4, 0)
#define AXP22X_ALDO2_V_OUT_MASK GENMASK(4, 0)
#define AXP22X_ALDO3_V_OUT_MASK GENMASK(4, 0)
#define AXP22X_DLDO1_V_OUT_MASK GENMASK(4, 0)
#define AXP22X_DLDO2_V_OUT_MASK GENMASK(4, 0)
#define AXP22X_DLDO3_V_OUT_MASK GENMASK(4, 0)
#define AXP22X_DLDO4_V_OUT_MASK GENMASK(4, 0)
#define AXP22X_ELDO1_V_OUT_MASK GENMASK(4, 0)
#define AXP22X_ELDO2_V_OUT_MASK GENMASK(4, 0)
#define AXP22X_ELDO3_V_OUT_MASK GENMASK(4, 0)
#define AXP22X_LDO_IO0_V_OUT_MASK GENMASK(4, 0)
#define AXP22X_LDO_IO1_V_OUT_MASK GENMASK(4, 0)
#define AXP22X_PWR_OUT_DC5LDO_MASK BIT_MASK(0)
#define AXP22X_PWR_OUT_DCDC1_MASK BIT_MASK(1)
#define AXP22X_PWR_OUT_DCDC2_MASK BIT_MASK(2)
#define AXP22X_PWR_OUT_DCDC3_MASK BIT_MASK(3)
#define AXP22X_PWR_OUT_DCDC4_MASK BIT_MASK(4)
#define AXP22X_PWR_OUT_DCDC5_MASK BIT_MASK(5)
#define AXP22X_PWR_OUT_ALDO1_MASK BIT_MASK(6)
#define AXP22X_PWR_OUT_ALDO2_MASK BIT_MASK(7)
#define AXP22X_PWR_OUT_SW_MASK BIT_MASK(6)
#define AXP22X_PWR_OUT_DC1SW_MASK BIT_MASK(7)
#define AXP22X_PWR_OUT_ELDO1_MASK BIT_MASK(0)
#define AXP22X_PWR_OUT_ELDO2_MASK BIT_MASK(1)
#define AXP22X_PWR_OUT_ELDO3_MASK BIT_MASK(2)
#define AXP22X_PWR_OUT_DLDO1_MASK BIT_MASK(3)
#define AXP22X_PWR_OUT_DLDO2_MASK BIT_MASK(4)
#define AXP22X_PWR_OUT_DLDO3_MASK BIT_MASK(5)
#define AXP22X_PWR_OUT_DLDO4_MASK BIT_MASK(6)
#define AXP22X_PWR_OUT_ALDO3_MASK BIT_MASK(7)
#define AXP803_PWR_OUT_DCDC1_MASK BIT_MASK(0)
#define AXP803_PWR_OUT_DCDC2_MASK BIT_MASK(1)
#define AXP803_PWR_OUT_DCDC3_MASK BIT_MASK(2)
#define AXP803_PWR_OUT_DCDC4_MASK BIT_MASK(3)
#define AXP803_PWR_OUT_DCDC5_MASK BIT_MASK(4)
#define AXP803_PWR_OUT_DCDC6_MASK BIT_MASK(5)
#define AXP803_PWR_OUT_FLDO1_MASK BIT_MASK(2)
#define AXP803_PWR_OUT_FLDO2_MASK BIT_MASK(3)
#define AXP803_DCDC1_V_OUT_MASK GENMASK(4, 0)
#define AXP803_DCDC2_V_OUT_MASK GENMASK(6, 0)
#define AXP803_DCDC3_V_OUT_MASK GENMASK(6, 0)
#define AXP803_DCDC4_V_OUT_MASK GENMASK(6, 0)
#define AXP803_DCDC5_V_OUT_MASK GENMASK(6, 0)
#define AXP803_DCDC6_V_OUT_MASK GENMASK(6, 0)
#define AXP803_FLDO1_V_OUT_MASK GENMASK(3, 0)
#define AXP803_FLDO2_V_OUT_MASK GENMASK(3, 0)
#define AXP803_DCDC23_POLYPHASE_DUAL BIT(6)
#define AXP803_DCDC56_POLYPHASE_DUAL BIT(5)
#define AXP803_DCDC234_500mV_START 0x00
#define AXP803_DCDC234_500mV_STEPS 70
#define AXP803_DCDC234_500mV_END \
(AXP803_DCDC234_500mV_START + AXP803_DCDC234_500mV_STEPS)
#define AXP803_DCDC234_1220mV_START 0x47
#define AXP803_DCDC234_1220mV_STEPS 4
#define AXP803_DCDC234_1220mV_END \
(AXP803_DCDC234_1220mV_START + AXP803_DCDC234_1220mV_STEPS)
#define AXP803_DCDC234_NUM_VOLTAGES 76
#define AXP803_DCDC5_800mV_START 0x00
#define AXP803_DCDC5_800mV_STEPS 32
#define AXP803_DCDC5_800mV_END \
(AXP803_DCDC5_800mV_START + AXP803_DCDC5_800mV_STEPS)
#define AXP803_DCDC5_1140mV_START 0x21
#define AXP803_DCDC5_1140mV_STEPS 35
#define AXP803_DCDC5_1140mV_END \
(AXP803_DCDC5_1140mV_START + AXP803_DCDC5_1140mV_STEPS)
#define AXP803_DCDC5_NUM_VOLTAGES 68
#define AXP803_DCDC6_600mV_START 0x00
#define AXP803_DCDC6_600mV_STEPS 50
#define AXP803_DCDC6_600mV_END \
(AXP803_DCDC6_600mV_START + AXP803_DCDC6_600mV_STEPS)
#define AXP803_DCDC6_1120mV_START 0x33
#define AXP803_DCDC6_1120mV_STEPS 14
#define AXP803_DCDC6_1120mV_END \
(AXP803_DCDC6_1120mV_START + AXP803_DCDC6_1120mV_STEPS)
#define AXP803_DCDC6_NUM_VOLTAGES 72
#define AXP803_DLDO2_700mV_START 0x00
#define AXP803_DLDO2_700mV_STEPS 26
#define AXP803_DLDO2_700mV_END \
(AXP803_DLDO2_700mV_START + AXP803_DLDO2_700mV_STEPS)
#define AXP803_DLDO2_3400mV_START 0x1b
#define AXP803_DLDO2_3400mV_STEPS 4
#define AXP803_DLDO2_3400mV_END \
(AXP803_DLDO2_3400mV_START + AXP803_DLDO2_3400mV_STEPS)
#define AXP803_DLDO2_NUM_VOLTAGES 32
#define AXP806_DCDCA_V_CTRL_MASK GENMASK(6, 0)
#define AXP806_DCDCB_V_CTRL_MASK GENMASK(4, 0)
#define AXP806_DCDCC_V_CTRL_MASK GENMASK(6, 0)
#define AXP806_DCDCD_V_CTRL_MASK GENMASK(5, 0)
#define AXP806_DCDCE_V_CTRL_MASK GENMASK(4, 0)
#define AXP806_ALDO1_V_CTRL_MASK GENMASK(4, 0)
#define AXP806_ALDO2_V_CTRL_MASK GENMASK(4, 0)
#define AXP806_ALDO3_V_CTRL_MASK GENMASK(4, 0)
#define AXP806_BLDO1_V_CTRL_MASK GENMASK(3, 0)
#define AXP806_BLDO2_V_CTRL_MASK GENMASK(3, 0)
#define AXP806_BLDO3_V_CTRL_MASK GENMASK(3, 0)
#define AXP806_BLDO4_V_CTRL_MASK GENMASK(3, 0)
#define AXP806_CLDO1_V_CTRL_MASK GENMASK(4, 0)
#define AXP806_CLDO2_V_CTRL_MASK GENMASK(4, 0)
#define AXP806_CLDO3_V_CTRL_MASK GENMASK(4, 0)
#define AXP806_PWR_OUT_DCDCA_MASK BIT_MASK(0)
#define AXP806_PWR_OUT_DCDCB_MASK BIT_MASK(1)
#define AXP806_PWR_OUT_DCDCC_MASK BIT_MASK(2)
#define AXP806_PWR_OUT_DCDCD_MASK BIT_MASK(3)
#define AXP806_PWR_OUT_DCDCE_MASK BIT_MASK(4)
#define AXP806_PWR_OUT_ALDO1_MASK BIT_MASK(5)
#define AXP806_PWR_OUT_ALDO2_MASK BIT_MASK(6)
#define AXP806_PWR_OUT_ALDO3_MASK BIT_MASK(7)
#define AXP806_PWR_OUT_BLDO1_MASK BIT_MASK(0)
#define AXP806_PWR_OUT_BLDO2_MASK BIT_MASK(1)
#define AXP806_PWR_OUT_BLDO3_MASK BIT_MASK(2)
#define AXP806_PWR_OUT_BLDO4_MASK BIT_MASK(3)
#define AXP806_PWR_OUT_CLDO1_MASK BIT_MASK(4)
#define AXP806_PWR_OUT_CLDO2_MASK BIT_MASK(5)
#define AXP806_PWR_OUT_CLDO3_MASK BIT_MASK(6)
#define AXP806_PWR_OUT_SW_MASK BIT_MASK(7)
#define AXP806_DCDCAB_POLYPHASE_DUAL 0x40
#define AXP806_DCDCABC_POLYPHASE_TRI 0x80
#define AXP806_DCDCABC_POLYPHASE_MASK GENMASK(7, 6)
#define AXP806_DCDCDE_POLYPHASE_DUAL BIT(5)
#define AXP806_DCDCA_600mV_START 0x00
#define AXP806_DCDCA_600mV_STEPS 50
#define AXP806_DCDCA_600mV_END \
(AXP806_DCDCA_600mV_START + AXP806_DCDCA_600mV_STEPS)
#define AXP806_DCDCA_1120mV_START 0x33
#define AXP806_DCDCA_1120mV_STEPS 14
#define AXP806_DCDCA_1120mV_END \
(AXP806_DCDCA_1120mV_START + AXP806_DCDCA_1120mV_STEPS)
#define AXP806_DCDCA_NUM_VOLTAGES 72
#define AXP806_DCDCD_600mV_START 0x00
#define AXP806_DCDCD_600mV_STEPS 45
#define AXP806_DCDCD_600mV_END \
(AXP806_DCDCD_600mV_START + AXP806_DCDCD_600mV_STEPS)
#define AXP806_DCDCD_1600mV_START 0x2e
#define AXP806_DCDCD_1600mV_STEPS 17
#define AXP806_DCDCD_1600mV_END \
(AXP806_DCDCD_1600mV_START + AXP806_DCDCD_1600mV_STEPS)
#define AXP806_DCDCD_NUM_VOLTAGES 64
#define AXP809_DCDC4_600mV_START 0x00
#define AXP809_DCDC4_600mV_STEPS 47
#define AXP809_DCDC4_600mV_END \
(AXP809_DCDC4_600mV_START + AXP809_DCDC4_600mV_STEPS)
#define AXP809_DCDC4_1800mV_START 0x30
#define AXP809_DCDC4_1800mV_STEPS 8
#define AXP809_DCDC4_1800mV_END \
(AXP809_DCDC4_1800mV_START + AXP809_DCDC4_1800mV_STEPS)
#define AXP809_DCDC4_NUM_VOLTAGES 57
#define AXP813_DCDC7_V_OUT_MASK GENMASK(6, 0)
#define AXP813_PWR_OUT_DCDC7_MASK BIT_MASK(6)
#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask, _enable_val, _disable_val) \
[_family##_##_id] = { \
...
...
@@ -128,6 +359,133 @@
.ops = &axp20x_ops_range, \
}
static
const
int
axp209_dcdc2_ldo3_slew_rates
[]
=
{
1600
,
800
,
};
static
int
axp20x_set_ramp_delay
(
struct
regulator_dev
*
rdev
,
int
ramp
)
{
struct
axp20x_dev
*
axp20x
=
rdev_get_drvdata
(
rdev
);
const
struct
regulator_desc
*
desc
=
rdev
->
desc
;
u8
reg
,
mask
,
enable
,
cfg
=
0xff
;
const
int
*
slew_rates
;
int
rate_count
=
0
;
if
(
!
rdev
)
return
-
EINVAL
;
switch
(
axp20x
->
variant
)
{
case
AXP209_ID
:
if
(
desc
->
id
==
AXP20X_DCDC2
)
{
slew_rates
=
axp209_dcdc2_ldo3_slew_rates
;
rate_count
=
ARRAY_SIZE
(
axp209_dcdc2_ldo3_slew_rates
);
reg
=
AXP20X_DCDC2_LDO3_V_RAMP
;
mask
=
AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_RATE_MASK
|
AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN_MASK
;
enable
=
(
ramp
>
0
)
?
AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN
:
!
AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN
;
break
;
}
if
(
desc
->
id
==
AXP20X_LDO3
)
{
slew_rates
=
axp209_dcdc2_ldo3_slew_rates
;
rate_count
=
ARRAY_SIZE
(
axp209_dcdc2_ldo3_slew_rates
);
reg
=
AXP20X_DCDC2_LDO3_V_RAMP
;
mask
=
AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE_MASK
|
AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN_MASK
;
enable
=
(
ramp
>
0
)
?
AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN
:
!
AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN
;
break
;
}
if
(
rate_count
>
0
)
break
;
/* fall through */
default:
/* Not supported for this regulator */
return
-
ENOTSUPP
;
}
if
(
ramp
==
0
)
{
cfg
=
enable
;
}
else
{
int
i
;
for
(
i
=
0
;
i
<
rate_count
;
i
++
)
{
if
(
ramp
<=
slew_rates
[
i
])
cfg
=
AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE
(
i
);
else
break
;
}
if
(
cfg
==
0xff
)
{
dev_err
(
axp20x
->
dev
,
"unsupported ramp value %d"
,
ramp
);
return
-
EINVAL
;
}
cfg
|=
enable
;
}
return
regmap_update_bits
(
axp20x
->
regmap
,
reg
,
mask
,
cfg
);
}
static
int
axp20x_regulator_enable_regmap
(
struct
regulator_dev
*
rdev
)
{
struct
axp20x_dev
*
axp20x
=
rdev_get_drvdata
(
rdev
);
const
struct
regulator_desc
*
desc
=
rdev
->
desc
;
if
(
!
rdev
)
return
-
EINVAL
;
switch
(
axp20x
->
variant
)
{
case
AXP209_ID
:
if
((
desc
->
id
==
AXP20X_LDO3
)
&&
rdev
->
constraints
&&
rdev
->
constraints
->
soft_start
)
{
int
v_out
;
int
ret
;
/*
* On some boards, the LDO3 can be overloaded when
* turning on, causing the entire PMIC to shutdown
* without warning. Turning it on at the minimal voltage
* and then setting the voltage to the requested value
* works reliably.
*/
if
(
regulator_is_enabled_regmap
(
rdev
))
break
;
v_out
=
regulator_get_voltage_sel_regmap
(
rdev
);
if
(
v_out
<
0
)
return
v_out
;
if
(
v_out
==
0
)
break
;
ret
=
regulator_set_voltage_sel_regmap
(
rdev
,
0x00
);
/*
* A small pause is needed between
* setting the voltage and enabling the LDO to give the
* internal state machine time to process the request.
*/
usleep_range
(
1000
,
5000
);
ret
|=
regulator_enable_regmap
(
rdev
);
ret
|=
regulator_set_voltage_sel_regmap
(
rdev
,
v_out
);
return
ret
;
}
break
;
default:
/* No quirks */
break
;
}
return
regulator_enable_regmap
(
rdev
);
};
static
const
struct
regulator_ops
axp20x_ops_fixed
=
{
.
list_voltage
=
regulator_list_voltage_linear
,
};
...
...
@@ -145,9 +503,10 @@ static const struct regulator_ops axp20x_ops = {
.
set_voltage_sel
=
regulator_set_voltage_sel_regmap
,
.
get_voltage_sel
=
regulator_get_voltage_sel_regmap
,
.
list_voltage
=
regulator_list_voltage_linear
,
.
enable
=
regulator_enable_regmap
,
.
enable
=
axp20x_
regulator_enable_regmap
,
.
disable
=
regulator_disable_regmap
,
.
is_enabled
=
regulator_is_enabled_regmap
,
.
set_ramp_delay
=
axp20x_set_ramp_delay
,
};
static
const
struct
regulator_ops
axp20x_ops_sw
=
{
...
...
@@ -157,77 +516,116 @@ static const struct regulator_ops axp20x_ops_sw = {
};
static
const
struct
regulator_linear_range
axp20x_ldo4_ranges
[]
=
{
REGULATOR_LINEAR_RANGE
(
1250000
,
0x0
,
0x0
,
0
),
REGULATOR_LINEAR_RANGE
(
1300000
,
0x1
,
0x8
,
100000
),
REGULATOR_LINEAR_RANGE
(
2500000
,
0x9
,
0x9
,
0
),
REGULATOR_LINEAR_RANGE
(
2700000
,
0xa
,
0xb
,
100000
),
REGULATOR_LINEAR_RANGE
(
3000000
,
0xc
,
0xf
,
100000
),
REGULATOR_LINEAR_RANGE
(
1250000
,
AXP20X_LDO4_V_OUT_1250mV_START
,
AXP20X_LDO4_V_OUT_1250mV_END
,
0
),
REGULATOR_LINEAR_RANGE
(
1300000
,
AXP20X_LDO4_V_OUT_1300mV_START
,
AXP20X_LDO4_V_OUT_1300mV_END
,
100000
),
REGULATOR_LINEAR_RANGE
(
2500000
,
AXP20X_LDO4_V_OUT_2500mV_START
,
AXP20X_LDO4_V_OUT_2500mV_END
,
0
),
REGULATOR_LINEAR_RANGE
(
2700000
,
AXP20X_LDO4_V_OUT_2700mV_START
,
AXP20X_LDO4_V_OUT_2700mV_END
,
100000
),
REGULATOR_LINEAR_RANGE
(
3000000
,
AXP20X_LDO4_V_OUT_3000mV_START
,
AXP20X_LDO4_V_OUT_3000mV_END
,
100000
),
};
static
const
struct
regulator_desc
axp20x_regulators
[]
=
{
AXP_DESC
(
AXP20X
,
DCDC2
,
"dcdc2"
,
"vin2"
,
700
,
2275
,
25
,
AXP20X_DCDC2_V_OUT
,
0x3f
,
AXP20X_PWR_OUT_CTRL
,
0x10
),
AXP20X_DCDC2_V_OUT
,
AXP20X_DCDC2_V_OUT_MASK
,
AXP20X_PWR_OUT_CTRL
,
AXP20X_PWR_OUT_DCDC2_MASK
),
AXP_DESC
(
AXP20X
,
DCDC3
,
"dcdc3"
,
"vin3"
,
700
,
3500
,
25
,
AXP20X_DCDC3_V_OUT
,
0x7f
,
AXP20X_PWR_OUT_CTRL
,
0x02
),
AXP20X_DCDC3_V_OUT
,
AXP20X_DCDC3_V_OUT_MASK
,
AXP20X_PWR_OUT_CTRL
,
AXP20X_PWR_OUT_DCDC3_MASK
),
AXP_DESC_FIXED
(
AXP20X
,
LDO1
,
"ldo1"
,
"acin"
,
1300
),
AXP_DESC
(
AXP20X
,
LDO2
,
"ldo2"
,
"ldo24in"
,
1800
,
3300
,
100
,
AXP20X_LDO24_V_OUT
,
0xf0
,
AXP20X_PWR_OUT_CTRL
,
0x04
),
AXP20X_LDO24_V_OUT
,
AXP20X_LDO24_V_OUT_MASK
,
AXP20X_PWR_OUT_CTRL
,
AXP20X_PWR_OUT_LDO2_MASK
),
AXP_DESC
(
AXP20X
,
LDO3
,
"ldo3"
,
"ldo3in"
,
700
,
3500
,
25
,
AXP20X_LDO3_V_OUT
,
0x7f
,
AXP20X_PWR_OUT_CTRL
,
0x40
),
AXP_DESC_RANGES
(
AXP20X
,
LDO4
,
"ldo4"
,
"ldo24in"
,
axp20x_ldo4_ranges
,
16
,
AXP20X_LDO24_V_OUT
,
0x0f
,
AXP20X_PWR_OUT_CTRL
,
0x08
),
AXP20X_LDO3_V_OUT
,
AXP20X_LDO3_V_OUT_MASK
,
AXP20X_PWR_OUT_CTRL
,
AXP20X_PWR_OUT_LDO3_MASK
),
AXP_DESC_RANGES
(
AXP20X
,
LDO4
,
"ldo4"
,
"ldo24in"
,
axp20x_ldo4_ranges
,
AXP20X_LDO4_V_OUT_NUM_VOLTAGES
,
AXP20X_LDO24_V_OUT
,
AXP20X_LDO24_V_OUT_MASK
,
AXP20X_PWR_OUT_CTRL
,
AXP20X_PWR_OUT_LDO4_MASK
),
AXP_DESC_IO
(
AXP20X
,
LDO5
,
"ldo5"
,
"ldo5in"
,
1800
,
3300
,
100
,
AXP20X_LDO5_V_OUT
,
0xf0
,
AXP20X_GPIO0_CTRL
,
0x07
,
AXP20X_LDO5_V_OUT
,
AXP20X_LDO5_V_OUT_MASK
,
AXP20X_GPIO0_CTRL
,
AXP20X_GPIO0_FUNC_MASK
,
AXP20X_IO_ENABLED
,
AXP20X_IO_DISABLED
),
};
static
const
struct
regulator_desc
axp22x_regulators
[]
=
{
AXP_DESC
(
AXP22X
,
DCDC1
,
"dcdc1"
,
"vin1"
,
1600
,
3400
,
100
,
AXP22X_DCDC1_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
1
)),
AXP22X_DCDC1_V_OUT
,
AXP22X_DCDC1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP22X_PWR_OUT_DCDC1_MASK
),
AXP_DESC
(
AXP22X
,
DCDC2
,
"dcdc2"
,
"vin2"
,
600
,
1540
,
20
,
AXP22X_DCDC2_V_OUT
,
0x3f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
2
)),
AXP22X_DCDC2_V_OUT
,
AXP22X_DCDC2_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP22X_PWR_OUT_DCDC2_MASK
),
AXP_DESC
(
AXP22X
,
DCDC3
,
"dcdc3"
,
"vin3"
,
600
,
1860
,
20
,
AXP22X_DCDC3_V_OUT
,
0x3f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
3
)),
AXP22X_DCDC3_V_OUT
,
AXP22X_DCDC3_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP22X_PWR_OUT_DCDC3_MASK
),
AXP_DESC
(
AXP22X
,
DCDC4
,
"dcdc4"
,
"vin4"
,
600
,
1540
,
20
,
AXP22X_DCDC4_V_OUT
,
0x3f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
4
)),
AXP22X_DCDC4_V_OUT
,
AXP22X_DCDC4_V_OUT
,
AXP22X_PWR_OUT_CTRL1
,
AXP22X_PWR_OUT_DCDC4_MASK
),
AXP_DESC
(
AXP22X
,
DCDC5
,
"dcdc5"
,
"vin5"
,
1000
,
2550
,
50
,
AXP22X_DCDC5_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
5
)),
AXP22X_DCDC5_V_OUT
,
AXP22X_DCDC5_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP22X_PWR_OUT_DCDC5_MASK
),
/* secondary switchable output of DCDC1 */
AXP_DESC_SW
(
AXP22X
,
DC1SW
,
"dc1sw"
,
NULL
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
7
)
),
AXP_DESC_SW
(
AXP22X
,
DC1SW
,
"dc1sw"
,
NULL
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DC1SW_MASK
),
/* LDO regulator internally chained to DCDC5 */
AXP_DESC
(
AXP22X
,
DC5LDO
,
"dc5ldo"
,
NULL
,
700
,
1400
,
100
,
AXP22X_DC5LDO_V_OUT
,
0x7
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
0
)),
AXP22X_DC5LDO_V_OUT
,
AXP22X_DC5LDO_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP22X_PWR_OUT_DC5LDO_MASK
),
AXP_DESC
(
AXP22X
,
ALDO1
,
"aldo1"
,
"aldoin"
,
700
,
3300
,
100
,
AXP22X_ALDO1_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
6
)),
AXP22X_ALDO1_V_OUT
,
AXP22X_ALDO1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP22X_PWR_OUT_ALDO1_MASK
),
AXP_DESC
(
AXP22X
,
ALDO2
,
"aldo2"
,
"aldoin"
,
700
,
3300
,
100
,
AXP22X_ALDO2_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
7
)),
AXP22X_ALDO2_V_OUT
,
AXP22X_ALDO2_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP22X_PWR_OUT_ALDO2_MASK
),
AXP_DESC
(
AXP22X
,
ALDO3
,
"aldo3"
,
"aldoin"
,
700
,
3300
,
100
,
AXP22X_ALDO3_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL3
,
BIT
(
7
)),
AXP22X_ALDO3_V_OUT
,
AXP22X_ALDO3_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL3
,
AXP22X_PWR_OUT_ALDO3_MASK
),
AXP_DESC
(
AXP22X
,
DLDO1
,
"dldo1"
,
"dldoin"
,
700
,
3300
,
100
,
AXP22X_DLDO1_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
3
)),
AXP22X_DLDO1_V_OUT
,
AXP22X_DLDO1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DLDO1_MASK
),
AXP_DESC
(
AXP22X
,
DLDO2
,
"dldo2"
,
"dldoin"
,
700
,
3300
,
100
,
AXP22X_DLDO2_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
4
)),
AXP22X_DLDO2_V_OUT
,
AXP22X_PWR_OUT_DLDO2_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DLDO2_MASK
),
AXP_DESC
(
AXP22X
,
DLDO3
,
"dldo3"
,
"dldoin"
,
700
,
3300
,
100
,
AXP22X_DLDO3_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
5
)),
AXP22X_DLDO3_V_OUT
,
AXP22X_DLDO3_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DLDO3_MASK
),
AXP_DESC
(
AXP22X
,
DLDO4
,
"dldo4"
,
"dldoin"
,
700
,
3300
,
100
,
AXP22X_DLDO4_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
6
)),
AXP22X_DLDO4_V_OUT
,
AXP22X_DLDO4_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DLDO4_MASK
),
AXP_DESC
(
AXP22X
,
ELDO1
,
"eldo1"
,
"eldoin"
,
700
,
3300
,
100
,
AXP22X_ELDO1_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
0
)),
AXP22X_ELDO1_V_OUT
,
AXP22X_ELDO1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_ELDO1_MASK
),
AXP_DESC
(
AXP22X
,
ELDO2
,
"eldo2"
,
"eldoin"
,
700
,
3300
,
100
,
AXP22X_ELDO2_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
1
)),
AXP22X_ELDO2_V_OUT
,
AXP22X_ELDO2_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_ELDO1_MASK
),
AXP_DESC
(
AXP22X
,
ELDO3
,
"eldo3"
,
"eldoin"
,
700
,
3300
,
100
,
AXP22X_ELDO3_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
2
)),
AXP22X_ELDO3_V_OUT
,
AXP22X_ELDO3_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_ELDO3_MASK
),
/* Note the datasheet only guarantees reliable operation up to
* 3.3V, this needs to be enforced via dts provided constraints */
AXP_DESC_IO
(
AXP22X
,
LDO_IO0
,
"ldo_io0"
,
"ips"
,
700
,
3800
,
100
,
AXP22X_LDO_IO0_V_OUT
,
0x1f
,
AXP20X_GPIO0_CTRL
,
0x07
,
AXP22X_LDO_IO0_V_OUT
,
AXP22X_LDO_IO0_V_OUT_MASK
,
AXP20X_GPIO0_CTRL
,
AXP20X_GPIO0_FUNC_MASK
,
AXP22X_IO_ENABLED
,
AXP22X_IO_DISABLED
),
/* Note the datasheet only guarantees reliable operation up to
* 3.3V, this needs to be enforced via dts provided constraints */
AXP_DESC_IO
(
AXP22X
,
LDO_IO1
,
"ldo_io1"
,
"ips"
,
700
,
3800
,
100
,
AXP22X_LDO_IO1_V_OUT
,
0x1f
,
AXP20X_GPIO1_CTRL
,
0x07
,
AXP22X_LDO_IO1_V_OUT
,
AXP22X_LDO_IO1_V_OUT_MASK
,
AXP20X_GPIO1_CTRL
,
AXP20X_GPIO1_FUNC_MASK
,
AXP22X_IO_ENABLED
,
AXP22X_IO_DISABLED
),
AXP_DESC_FIXED
(
AXP22X
,
RTC_LDO
,
"rtc_ldo"
,
"ips"
,
3000
),
};
...
...
@@ -240,240 +638,354 @@ static const struct regulator_desc axp22x_drivevbus_regulator = {
.
type
=
REGULATOR_VOLTAGE
,
.
owner
=
THIS_MODULE
,
.
enable_reg
=
AXP20X_VBUS_IPSOUT_MGMT
,
.
enable_mask
=
BIT
(
2
)
,
.
enable_mask
=
AXP20X_VBUS_IPSOUT_MGMT_MASK
,
.
ops
=
&
axp20x_ops_sw
,
};
/* DCDC ranges shared with AXP813 */
static
const
struct
regulator_linear_range
axp803_dcdc234_ranges
[]
=
{
REGULATOR_LINEAR_RANGE
(
500000
,
0x0
,
0x46
,
10000
),
REGULATOR_LINEAR_RANGE
(
1220000
,
0x47
,
0x4b
,
20000
),
REGULATOR_LINEAR_RANGE
(
500000
,
AXP803_DCDC234_500mV_START
,
AXP803_DCDC234_500mV_END
,
10000
),
REGULATOR_LINEAR_RANGE
(
1220000
,
AXP803_DCDC234_1220mV_START
,
AXP803_DCDC234_1220mV_END
,
20000
),
};
static
const
struct
regulator_linear_range
axp803_dcdc5_ranges
[]
=
{
REGULATOR_LINEAR_RANGE
(
800000
,
0x0
,
0x20
,
10000
),
REGULATOR_LINEAR_RANGE
(
1140000
,
0x21
,
0x44
,
20000
),
REGULATOR_LINEAR_RANGE
(
800000
,
AXP803_DCDC5_800mV_START
,
AXP803_DCDC5_800mV_END
,
10000
),
REGULATOR_LINEAR_RANGE
(
1140000
,
AXP803_DCDC5_1140mV_START
,
AXP803_DCDC5_1140mV_END
,
20000
),
};
static
const
struct
regulator_linear_range
axp803_dcdc6_ranges
[]
=
{
REGULATOR_LINEAR_RANGE
(
600000
,
0x0
,
0x32
,
10000
),
REGULATOR_LINEAR_RANGE
(
1120000
,
0x33
,
0x47
,
20000
),
REGULATOR_LINEAR_RANGE
(
600000
,
AXP803_DCDC6_600mV_START
,
AXP803_DCDC6_600mV_END
,
10000
),
REGULATOR_LINEAR_RANGE
(
1120000
,
AXP803_DCDC6_1120mV_START
,
AXP803_DCDC6_1120mV_END
,
20000
),
};
/* AXP806's CLDO2 and AXP809's DLDO1 share
s
the same range */
/* AXP806's CLDO2 and AXP809's DLDO1 share the same range */
static
const
struct
regulator_linear_range
axp803_dldo2_ranges
[]
=
{
REGULATOR_LINEAR_RANGE
(
700000
,
0x0
,
0x1a
,
100000
),
REGULATOR_LINEAR_RANGE
(
3400000
,
0x1b
,
0x1f
,
200000
),
REGULATOR_LINEAR_RANGE
(
700000
,
AXP803_DLDO2_700mV_START
,
AXP803_DLDO2_700mV_END
,
100000
),
REGULATOR_LINEAR_RANGE
(
3400000
,
AXP803_DLDO2_3400mV_START
,
AXP803_DLDO2_3400mV_END
,
200000
),
};
static
const
struct
regulator_desc
axp803_regulators
[]
=
{
AXP_DESC
(
AXP803
,
DCDC1
,
"dcdc1"
,
"vin1"
,
1600
,
3400
,
100
,
AXP803_DCDC1_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
0
)),
AXP_DESC_RANGES
(
AXP803
,
DCDC2
,
"dcdc2"
,
"vin2"
,
axp803_dcdc234_ranges
,
76
,
AXP803_DCDC2_V_OUT
,
0x7f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
1
)),
AXP_DESC_RANGES
(
AXP803
,
DCDC3
,
"dcdc3"
,
"vin3"
,
axp803_dcdc234_ranges
,
76
,
AXP803_DCDC3_V_OUT
,
0x7f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
2
)),
AXP_DESC_RANGES
(
AXP803
,
DCDC4
,
"dcdc4"
,
"vin4"
,
axp803_dcdc234_ranges
,
76
,
AXP803_DCDC4_V_OUT
,
0x7f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
3
)),
AXP_DESC_RANGES
(
AXP803
,
DCDC5
,
"dcdc5"
,
"vin5"
,
axp803_dcdc5_ranges
,
68
,
AXP803_DCDC5_V_OUT
,
0x7f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
4
)),
AXP_DESC_RANGES
(
AXP803
,
DCDC6
,
"dcdc6"
,
"vin6"
,
axp803_dcdc6_ranges
,
72
,
AXP803_DCDC6_V_OUT
,
0x7f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
5
)),
AXP803_DCDC1_V_OUT
,
AXP803_DCDC1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP803_PWR_OUT_DCDC1_MASK
),
AXP_DESC_RANGES
(
AXP803
,
DCDC2
,
"dcdc2"
,
"vin2"
,
axp803_dcdc234_ranges
,
AXP803_DCDC234_NUM_VOLTAGES
,
AXP803_DCDC2_V_OUT
,
AXP803_DCDC2_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP803_PWR_OUT_DCDC2_MASK
),
AXP_DESC_RANGES
(
AXP803
,
DCDC3
,
"dcdc3"
,
"vin3"
,
axp803_dcdc234_ranges
,
AXP803_DCDC234_NUM_VOLTAGES
,
AXP803_DCDC3_V_OUT
,
AXP803_DCDC3_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP803_PWR_OUT_DCDC3_MASK
),
AXP_DESC_RANGES
(
AXP803
,
DCDC4
,
"dcdc4"
,
"vin4"
,
axp803_dcdc234_ranges
,
AXP803_DCDC234_NUM_VOLTAGES
,
AXP803_DCDC4_V_OUT
,
AXP803_DCDC4_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP803_PWR_OUT_DCDC4_MASK
),
AXP_DESC_RANGES
(
AXP803
,
DCDC5
,
"dcdc5"
,
"vin5"
,
axp803_dcdc5_ranges
,
AXP803_DCDC5_NUM_VOLTAGES
,
AXP803_DCDC5_V_OUT
,
AXP803_DCDC5_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP803_PWR_OUT_DCDC5_MASK
),
AXP_DESC_RANGES
(
AXP803
,
DCDC6
,
"dcdc6"
,
"vin6"
,
axp803_dcdc6_ranges
,
AXP803_DCDC6_NUM_VOLTAGES
,
AXP803_DCDC6_V_OUT
,
AXP803_DCDC6_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP803_PWR_OUT_DCDC6_MASK
),
/* secondary switchable output of DCDC1 */
AXP_DESC_SW
(
AXP803
,
DC1SW
,
"dc1sw"
,
NULL
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
7
)
),
AXP_DESC_SW
(
AXP803
,
DC1SW
,
"dc1sw"
,
NULL
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DC1SW_MASK
),
AXP_DESC
(
AXP803
,
ALDO1
,
"aldo1"
,
"aldoin"
,
700
,
3300
,
100
,
AXP22X_ALDO1_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL3
,
BIT
(
5
)),
AXP22X_ALDO1_V_OUT
,
AXP22X_ALDO1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL3
,
AXP806_PWR_OUT_ALDO1_MASK
),
AXP_DESC
(
AXP803
,
ALDO2
,
"aldo2"
,
"aldoin"
,
700
,
3300
,
100
,
AXP22X_ALDO2_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL3
,
BIT
(
6
)),
AXP22X_ALDO2_V_OUT
,
AXP22X_ALDO2_V_OUT
,
AXP22X_PWR_OUT_CTRL3
,
AXP806_PWR_OUT_ALDO2_MASK
),
AXP_DESC
(
AXP803
,
ALDO3
,
"aldo3"
,
"aldoin"
,
700
,
3300
,
100
,
AXP22X_ALDO3_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL3
,
BIT
(
7
)),
AXP22X_ALDO3_V_OUT
,
AXP22X_ALDO3_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL3
,
AXP806_PWR_OUT_ALDO3_MASK
),
AXP_DESC
(
AXP803
,
DLDO1
,
"dldo1"
,
"dldoin"
,
700
,
3300
,
100
,
AXP22X_DLDO1_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
3
)),
AXP_DESC_RANGES
(
AXP803
,
DLDO2
,
"dldo2"
,
"dldoin"
,
axp803_dldo2_ranges
,
32
,
AXP22X_DLDO2_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
4
)),
AXP22X_DLDO1_V_OUT
,
AXP22X_DLDO1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DLDO1_MASK
),
AXP_DESC_RANGES
(
AXP803
,
DLDO2
,
"dldo2"
,
"dldoin"
,
axp803_dldo2_ranges
,
AXP803_DLDO2_NUM_VOLTAGES
,
AXP22X_DLDO2_V_OUT
,
AXP22X_DLDO2_V_OUT
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DLDO2_MASK
),
AXP_DESC
(
AXP803
,
DLDO3
,
"dldo3"
,
"dldoin"
,
700
,
3300
,
100
,
AXP22X_DLDO3_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
5
)),
AXP22X_DLDO3_V_OUT
,
AXP22X_DLDO3_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DLDO3_MASK
),
AXP_DESC
(
AXP803
,
DLDO4
,
"dldo4"
,
"dldoin"
,
700
,
3300
,
100
,
AXP22X_DLDO4_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
6
)),
AXP22X_DLDO4_V_OUT
,
AXP22X_DLDO4_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DLDO4_MASK
),
AXP_DESC
(
AXP803
,
ELDO1
,
"eldo1"
,
"eldoin"
,
700
,
1900
,
50
,
AXP22X_ELDO1_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
0
)),
AXP22X_ELDO1_V_OUT
,
AXP22X_ELDO1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_ELDO1_MASK
),
AXP_DESC
(
AXP803
,
ELDO2
,
"eldo2"
,
"eldoin"
,
700
,
1900
,
50
,
AXP22X_ELDO2_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
1
)),
AXP22X_ELDO2_V_OUT
,
AXP22X_ELDO2_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_ELDO2_MASK
),
AXP_DESC
(
AXP803
,
ELDO3
,
"eldo3"
,
"eldoin"
,
700
,
1900
,
50
,
AXP22X_ELDO3_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
2
)),
AXP22X_ELDO3_V_OUT
,
AXP22X_ELDO3_V_OUT
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_ELDO3_MASK
),
AXP_DESC
(
AXP803
,
FLDO1
,
"fldo1"
,
"fldoin"
,
700
,
1450
,
50
,
AXP803_FLDO1_V_OUT
,
0x0f
,
AXP22X_PWR_OUT_CTRL3
,
BIT
(
2
)),
AXP803_FLDO1_V_OUT
,
AXP803_FLDO1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL3
,
AXP803_PWR_OUT_FLDO1_MASK
),
AXP_DESC
(
AXP803
,
FLDO2
,
"fldo2"
,
"fldoin"
,
700
,
1450
,
50
,
AXP803_FLDO2_V_OUT
,
0x0f
,
AXP22X_PWR_OUT_CTRL3
,
BIT
(
3
)),
AXP803_FLDO2_V_OUT
,
AXP803_FLDO2_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL3
,
AXP803_PWR_OUT_FLDO2_MASK
),
AXP_DESC_IO
(
AXP803
,
LDO_IO0
,
"ldo-io0"
,
"ips"
,
700
,
3300
,
100
,
AXP22X_LDO_IO0_V_OUT
,
0x1f
,
AXP20X_GPIO0_CTRL
,
0x07
,
AXP22X_LDO_IO0_V_OUT
,
AXP22X_LDO_IO0_V_OUT_MASK
,
AXP20X_GPIO0_CTRL
,
AXP20X_GPIO0_FUNC_MASK
,
AXP22X_IO_ENABLED
,
AXP22X_IO_DISABLED
),
AXP_DESC_IO
(
AXP803
,
LDO_IO1
,
"ldo-io1"
,
"ips"
,
700
,
3300
,
100
,
AXP22X_LDO_IO1_V_OUT
,
0x1f
,
AXP20X_GPIO1_CTRL
,
0x07
,
AXP22X_LDO_IO1_V_OUT
,
AXP22X_LDO_IO1_V_OUT_MASK
,
AXP20X_GPIO1_CTRL
,
AXP20X_GPIO1_FUNC_MASK
,
AXP22X_IO_ENABLED
,
AXP22X_IO_DISABLED
),
AXP_DESC_FIXED
(
AXP803
,
RTC_LDO
,
"rtc-ldo"
,
"ips"
,
3000
),
};
static
const
struct
regulator_linear_range
axp806_dcdca_ranges
[]
=
{
REGULATOR_LINEAR_RANGE
(
600000
,
0x0
,
0x32
,
10000
),
REGULATOR_LINEAR_RANGE
(
1120000
,
0x33
,
0x47
,
20000
),
REGULATOR_LINEAR_RANGE
(
600000
,
AXP806_DCDCA_600mV_START
,
AXP806_DCDCA_600mV_END
,
10000
),
REGULATOR_LINEAR_RANGE
(
1120000
,
AXP806_DCDCA_1120mV_START
,
AXP806_DCDCA_1120mV_END
,
20000
),
};
static
const
struct
regulator_linear_range
axp806_dcdcd_ranges
[]
=
{
REGULATOR_LINEAR_RANGE
(
600000
,
0x0
,
0x2d
,
20000
),
REGULATOR_LINEAR_RANGE
(
1600000
,
0x2e
,
0x3f
,
100000
),
REGULATOR_LINEAR_RANGE
(
600000
,
AXP806_DCDCD_600mV_START
,
AXP806_DCDCD_600mV_END
,
20000
),
REGULATOR_LINEAR_RANGE
(
1600000
,
AXP806_DCDCD_600mV_START
,
AXP806_DCDCD_600mV_END
,
100000
),
};
static
const
struct
regulator_desc
axp806_regulators
[]
=
{
AXP_DESC_RANGES
(
AXP806
,
DCDCA
,
"dcdca"
,
"vina"
,
axp806_dcdca_ranges
,
72
,
AXP806_DCDCA_V_CTRL
,
0x7f
,
AXP806_PWR_OUT_CTRL1
,
BIT
(
0
)),
AXP_DESC_RANGES
(
AXP806
,
DCDCA
,
"dcdca"
,
"vina"
,
axp806_dcdca_ranges
,
AXP806_DCDCA_NUM_VOLTAGES
,
AXP806_DCDCA_V_CTRL
,
AXP806_DCDCA_V_CTRL_MASK
,
AXP806_PWR_OUT_CTRL1
,
AXP806_PWR_OUT_DCDCA_MASK
),
AXP_DESC
(
AXP806
,
DCDCB
,
"dcdcb"
,
"vinb"
,
1000
,
2550
,
50
,
AXP806_DCDCB_V_CTRL
,
0x1f
,
AXP806_PWR_OUT_CTRL1
,
BIT
(
1
)),
AXP_DESC_RANGES
(
AXP806
,
DCDCC
,
"dcdcc"
,
"vinc"
,
axp806_dcdca_ranges
,
72
,
AXP806_DCDCC_V_CTRL
,
0x7f
,
AXP806_PWR_OUT_CTRL1
,
BIT
(
2
)),
AXP_DESC_RANGES
(
AXP806
,
DCDCD
,
"dcdcd"
,
"vind"
,
axp806_dcdcd_ranges
,
64
,
AXP806_DCDCD_V_CTRL
,
0x3f
,
AXP806_PWR_OUT_CTRL1
,
BIT
(
3
)),
AXP806_DCDCB_V_CTRL
,
AXP806_DCDCB_V_CTRL
,
AXP806_PWR_OUT_CTRL1
,
AXP806_PWR_OUT_DCDCB_MASK
),
AXP_DESC_RANGES
(
AXP806
,
DCDCC
,
"dcdcc"
,
"vinc"
,
axp806_dcdca_ranges
,
AXP806_DCDCA_NUM_VOLTAGES
,
AXP806_DCDCC_V_CTRL
,
AXP806_DCDCC_V_CTRL_MASK
,
AXP806_PWR_OUT_CTRL1
,
AXP806_PWR_OUT_DCDCC_MASK
),
AXP_DESC_RANGES
(
AXP806
,
DCDCD
,
"dcdcd"
,
"vind"
,
axp806_dcdcd_ranges
,
AXP806_DCDCD_NUM_VOLTAGES
,
AXP806_DCDCD_V_CTRL
,
AXP806_DCDCD_V_CTRL_MASK
,
AXP806_PWR_OUT_CTRL1
,
AXP806_PWR_OUT_DCDCD_MASK
),
AXP_DESC
(
AXP806
,
DCDCE
,
"dcdce"
,
"vine"
,
1100
,
3400
,
100
,
AXP806_DCDCE_V_CTRL
,
0x1f
,
AXP806_PWR_OUT_CTRL1
,
BIT
(
4
)),
AXP806_DCDCE_V_CTRL
,
AXP806_DCDCE_V_CTRL_MASK
,
AXP806_PWR_OUT_CTRL1
,
AXP806_PWR_OUT_DCDCE_MASK
),
AXP_DESC
(
AXP806
,
ALDO1
,
"aldo1"
,
"aldoin"
,
700
,
3300
,
100
,
AXP806_ALDO1_V_CTRL
,
0x1f
,
AXP806_PWR_OUT_CTRL1
,
BIT
(
5
)),
AXP806_ALDO1_V_CTRL
,
AXP806_ALDO1_V_CTRL_MASK
,
AXP806_PWR_OUT_CTRL1
,
AXP806_PWR_OUT_ALDO1_MASK
),
AXP_DESC
(
AXP806
,
ALDO2
,
"aldo2"
,
"aldoin"
,
700
,
3400
,
100
,
AXP806_ALDO2_V_CTRL
,
0x1f
,
AXP806_PWR_OUT_CTRL1
,
BIT
(
6
)),
AXP806_ALDO2_V_CTRL
,
AXP806_ALDO2_V_CTRL_MASK
,
AXP806_PWR_OUT_CTRL1
,
AXP806_PWR_OUT_ALDO2_MASK
),
AXP_DESC
(
AXP806
,
ALDO3
,
"aldo3"
,
"aldoin"
,
700
,
3300
,
100
,
AXP806_ALDO3_V_CTRL
,
0x1f
,
AXP806_PWR_OUT_CTRL1
,
BIT
(
7
)),
AXP806_ALDO3_V_CTRL
,
AXP806_ALDO3_V_CTRL_MASK
,
AXP806_PWR_OUT_CTRL1
,
AXP806_PWR_OUT_ALDO3_MASK
),
AXP_DESC
(
AXP806
,
BLDO1
,
"bldo1"
,
"bldoin"
,
700
,
1900
,
100
,
AXP806_BLDO1_V_CTRL
,
0x0f
,
AXP806_PWR_OUT_CTRL2
,
BIT
(
0
)),
AXP806_BLDO1_V_CTRL
,
AXP806_BLDO1_V_CTRL_MASK
,
AXP806_PWR_OUT_CTRL2
,
AXP806_PWR_OUT_BLDO1_MASK
),
AXP_DESC
(
AXP806
,
BLDO2
,
"bldo2"
,
"bldoin"
,
700
,
1900
,
100
,
AXP806_BLDO2_V_CTRL
,
0x0f
,
AXP806_PWR_OUT_CTRL2
,
BIT
(
1
)),
AXP806_BLDO2_V_CTRL
,
AXP806_BLDO2_V_CTRL
,
AXP806_PWR_OUT_CTRL2
,
AXP806_PWR_OUT_BLDO2_MASK
),
AXP_DESC
(
AXP806
,
BLDO3
,
"bldo3"
,
"bldoin"
,
700
,
1900
,
100
,
AXP806_BLDO3_V_CTRL
,
0x0f
,
AXP806_PWR_OUT_CTRL2
,
BIT
(
2
)),
AXP806_BLDO3_V_CTRL
,
AXP806_BLDO3_V_CTRL_MASK
,
AXP806_PWR_OUT_CTRL2
,
AXP806_PWR_OUT_BLDO3_MASK
),
AXP_DESC
(
AXP806
,
BLDO4
,
"bldo4"
,
"bldoin"
,
700
,
1900
,
100
,
AXP806_BLDO4_V_CTRL
,
0x0f
,
AXP806_PWR_OUT_CTRL2
,
BIT
(
3
)),
AXP806_BLDO4_V_CTRL
,
AXP806_BLDO4_V_CTRL_MASK
,
AXP806_PWR_OUT_CTRL2
,
AXP806_PWR_OUT_BLDO4_MASK
),
AXP_DESC
(
AXP806
,
CLDO1
,
"cldo1"
,
"cldoin"
,
700
,
3300
,
100
,
AXP806_CLDO1_V_CTRL
,
0x1f
,
AXP806_PWR_OUT_CTRL2
,
BIT
(
4
)),
AXP_DESC_RANGES
(
AXP806
,
CLDO2
,
"cldo2"
,
"cldoin"
,
axp803_dldo2_ranges
,
32
,
AXP806_CLDO2_V_CTRL
,
0x1f
,
AXP806_PWR_OUT_CTRL2
,
BIT
(
5
)),
AXP806_CLDO1_V_CTRL
,
AXP806_CLDO1_V_CTRL_MASK
,
AXP806_PWR_OUT_CTRL2
,
AXP806_PWR_OUT_CLDO1_MASK
),
AXP_DESC_RANGES
(
AXP806
,
CLDO2
,
"cldo2"
,
"cldoin"
,
axp803_dldo2_ranges
,
AXP803_DLDO2_NUM_VOLTAGES
,
AXP806_CLDO2_V_CTRL
,
AXP806_CLDO2_V_CTRL_MASK
,
AXP806_PWR_OUT_CTRL2
,
AXP806_PWR_OUT_CLDO2_MASK
),
AXP_DESC
(
AXP806
,
CLDO3
,
"cldo3"
,
"cldoin"
,
700
,
3300
,
100
,
AXP806_CLDO3_V_CTRL
,
0x1f
,
AXP806_PWR_OUT_CTRL2
,
BIT
(
6
)),
AXP_DESC_SW
(
AXP806
,
SW
,
"sw"
,
"swin"
,
AXP806_PWR_OUT_CTRL2
,
BIT
(
7
)),
AXP806_CLDO3_V_CTRL
,
AXP806_CLDO3_V_CTRL_MASK
,
AXP806_PWR_OUT_CTRL2
,
AXP806_PWR_OUT_CLDO3_MASK
),
AXP_DESC_SW
(
AXP806
,
SW
,
"sw"
,
"swin"
,
AXP806_PWR_OUT_CTRL2
,
AXP806_PWR_OUT_SW_MASK
),
};
static
const
struct
regulator_linear_range
axp809_dcdc4_ranges
[]
=
{
REGULATOR_LINEAR_RANGE
(
600000
,
0x0
,
0x2f
,
20000
),
REGULATOR_LINEAR_RANGE
(
1800000
,
0x30
,
0x38
,
100000
),
REGULATOR_LINEAR_RANGE
(
600000
,
AXP809_DCDC4_600mV_START
,
AXP809_DCDC4_600mV_END
,
20000
),
REGULATOR_LINEAR_RANGE
(
1800000
,
AXP809_DCDC4_1800mV_START
,
AXP809_DCDC4_1800mV_END
,
100000
),
};
static
const
struct
regulator_desc
axp809_regulators
[]
=
{
AXP_DESC
(
AXP809
,
DCDC1
,
"dcdc1"
,
"vin1"
,
1600
,
3400
,
100
,
AXP22X_DCDC1_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
1
)),
AXP22X_DCDC1_V_OUT
,
AXP22X_DCDC1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP22X_PWR_OUT_DCDC1_MASK
),
AXP_DESC
(
AXP809
,
DCDC2
,
"dcdc2"
,
"vin2"
,
600
,
1540
,
20
,
AXP22X_DCDC2_V_OUT
,
0x3f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
2
)),
AXP22X_DCDC2_V_OUT
,
AXP22X_DCDC2_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP22X_PWR_OUT_DCDC2_MASK
),
AXP_DESC
(
AXP809
,
DCDC3
,
"dcdc3"
,
"vin3"
,
600
,
1860
,
20
,
AXP22X_DCDC3_V_OUT
,
0x3f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
3
)),
AXP_DESC_RANGES
(
AXP809
,
DCDC4
,
"dcdc4"
,
"vin4"
,
axp809_dcdc4_ranges
,
57
,
AXP22X_DCDC4_V_OUT
,
0x3f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
4
)),
AXP22X_DCDC3_V_OUT
,
AXP22X_DCDC3_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP22X_PWR_OUT_DCDC3_MASK
),
AXP_DESC_RANGES
(
AXP809
,
DCDC4
,
"dcdc4"
,
"vin4"
,
axp809_dcdc4_ranges
,
AXP809_DCDC4_NUM_VOLTAGES
,
AXP22X_DCDC4_V_OUT
,
AXP22X_DCDC4_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP22X_PWR_OUT_DCDC4_MASK
),
AXP_DESC
(
AXP809
,
DCDC5
,
"dcdc5"
,
"vin5"
,
1000
,
2550
,
50
,
AXP22X_DCDC5_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
5
)),
AXP22X_DCDC5_V_OUT
,
AXP22X_DCDC5_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP22X_PWR_OUT_DCDC5_MASK
),
/* secondary switchable output of DCDC1 */
AXP_DESC_SW
(
AXP809
,
DC1SW
,
"dc1sw"
,
NULL
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
7
)
),
AXP_DESC_SW
(
AXP809
,
DC1SW
,
"dc1sw"
,
NULL
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DC1SW_MASK
),
/* LDO regulator internally chained to DCDC5 */
AXP_DESC
(
AXP809
,
DC5LDO
,
"dc5ldo"
,
NULL
,
700
,
1400
,
100
,
AXP22X_DC5LDO_V_OUT
,
0x7
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
0
)),
AXP22X_DC5LDO_V_OUT
,
AXP22X_DC5LDO_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP22X_PWR_OUT_DC5LDO_MASK
),
AXP_DESC
(
AXP809
,
ALDO1
,
"aldo1"
,
"aldoin"
,
700
,
3300
,
100
,
AXP22X_ALDO1_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
6
)),
AXP22X_ALDO1_V_OUT
,
AXP22X_ALDO1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP22X_PWR_OUT_ALDO1_MASK
),
AXP_DESC
(
AXP809
,
ALDO2
,
"aldo2"
,
"aldoin"
,
700
,
3300
,
100
,
AXP22X_ALDO2_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
7
)),
AXP22X_ALDO2_V_OUT
,
AXP22X_ALDO2_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP22X_PWR_OUT_ALDO2_MASK
),
AXP_DESC
(
AXP809
,
ALDO3
,
"aldo3"
,
"aldoin"
,
700
,
3300
,
100
,
AXP22X_ALDO3_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
5
)),
AXP_DESC_RANGES
(
AXP809
,
DLDO1
,
"dldo1"
,
"dldoin"
,
axp803_dldo2_ranges
,
32
,
AXP22X_DLDO1_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
3
)),
AXP22X_ALDO3_V_OUT
,
AXP22X_ALDO3_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_ALDO3_MASK
),
AXP_DESC_RANGES
(
AXP809
,
DLDO1
,
"dldo1"
,
"dldoin"
,
axp803_dldo2_ranges
,
AXP803_DLDO2_NUM_VOLTAGES
,
AXP22X_DLDO1_V_OUT
,
AXP22X_DLDO1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DLDO1_MASK
),
AXP_DESC
(
AXP809
,
DLDO2
,
"dldo2"
,
"dldoin"
,
700
,
3300
,
100
,
AXP22X_DLDO2_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
4
)),
AXP22X_DLDO2_V_OUT
,
AXP22X_DLDO2_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DLDO2_MASK
),
AXP_DESC
(
AXP809
,
ELDO1
,
"eldo1"
,
"eldoin"
,
700
,
3300
,
100
,
AXP22X_ELDO1_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
0
)),
AXP22X_ELDO1_V_OUT
,
AXP22X_ELDO1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_ELDO1_MASK
),
AXP_DESC
(
AXP809
,
ELDO2
,
"eldo2"
,
"eldoin"
,
700
,
3300
,
100
,
AXP22X_ELDO2_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
1
)),
AXP22X_ELDO2_V_OUT
,
AXP22X_ELDO2_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_ELDO2_MASK
),
AXP_DESC
(
AXP809
,
ELDO3
,
"eldo3"
,
"eldoin"
,
700
,
3300
,
100
,
AXP22X_ELDO3_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
2
)),
AXP22X_ELDO3_V_OUT
,
AXP22X_ELDO3_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_ELDO3_MASK
),
/*
* Note the datasheet only guarantees reliable operation up to
* 3.3V, this needs to be enforced via dts provided constraints
*/
AXP_DESC_IO
(
AXP809
,
LDO_IO0
,
"ldo_io0"
,
"ips"
,
700
,
3800
,
100
,
AXP22X_LDO_IO0_V_OUT
,
0x1f
,
AXP20X_GPIO0_CTRL
,
0x07
,
AXP22X_LDO_IO0_V_OUT
,
AXP22X_LDO_IO0_V_OUT_MASK
,
AXP20X_GPIO0_CTRL
,
AXP20X_GPIO0_FUNC_MASK
,
AXP22X_IO_ENABLED
,
AXP22X_IO_DISABLED
),
/*
* Note the datasheet only guarantees reliable operation up to
* 3.3V, this needs to be enforced via dts provided constraints
*/
AXP_DESC_IO
(
AXP809
,
LDO_IO1
,
"ldo_io1"
,
"ips"
,
700
,
3800
,
100
,
AXP22X_LDO_IO1_V_OUT
,
0x1f
,
AXP20X_GPIO1_CTRL
,
0x07
,
AXP22X_LDO_IO1_V_OUT
,
AXP22X_LDO_IO1_V_OUT_MASK
,
AXP20X_GPIO1_CTRL
,
AXP20X_GPIO1_FUNC_MASK
,
AXP22X_IO_ENABLED
,
AXP22X_IO_DISABLED
),
AXP_DESC_FIXED
(
AXP809
,
RTC_LDO
,
"rtc_ldo"
,
"ips"
,
1800
),
AXP_DESC_SW
(
AXP809
,
SW
,
"sw"
,
"swin"
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
6
)),
AXP_DESC_SW
(
AXP809
,
SW
,
"sw"
,
"swin"
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_SW_MASK
),
};
static
const
struct
regulator_desc
axp813_regulators
[]
=
{
AXP_DESC
(
AXP813
,
DCDC1
,
"dcdc1"
,
"vin1"
,
1600
,
3400
,
100
,
AXP803_DCDC1_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
0
)),
AXP_DESC_RANGES
(
AXP813
,
DCDC2
,
"dcdc2"
,
"vin2"
,
axp803_dcdc234_ranges
,
76
,
AXP803_DCDC2_V_OUT
,
0x7f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
1
)),
AXP_DESC_RANGES
(
AXP813
,
DCDC3
,
"dcdc3"
,
"vin3"
,
axp803_dcdc234_ranges
,
76
,
AXP803_DCDC3_V_OUT
,
0x7f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
2
)),
AXP_DESC_RANGES
(
AXP813
,
DCDC4
,
"dcdc4"
,
"vin4"
,
axp803_dcdc234_ranges
,
76
,
AXP803_DCDC4_V_OUT
,
0x7f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
3
)),
AXP_DESC_RANGES
(
AXP813
,
DCDC5
,
"dcdc5"
,
"vin5"
,
axp803_dcdc5_ranges
,
68
,
AXP803_DCDC5_V_OUT
,
0x7f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
4
)),
AXP_DESC_RANGES
(
AXP813
,
DCDC6
,
"dcdc6"
,
"vin6"
,
axp803_dcdc6_ranges
,
72
,
AXP803_DCDC6_V_OUT
,
0x7f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
5
)),
AXP_DESC_RANGES
(
AXP813
,
DCDC7
,
"dcdc7"
,
"vin7"
,
axp803_dcdc6_ranges
,
72
,
AXP813_DCDC7_V_OUT
,
0x7f
,
AXP22X_PWR_OUT_CTRL1
,
BIT
(
6
)),
AXP803_DCDC1_V_OUT
,
AXP803_DCDC1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP803_PWR_OUT_DCDC1_MASK
),
AXP_DESC_RANGES
(
AXP813
,
DCDC2
,
"dcdc2"
,
"vin2"
,
axp803_dcdc234_ranges
,
AXP803_DCDC234_NUM_VOLTAGES
,
AXP803_DCDC2_V_OUT
,
AXP803_DCDC2_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP803_PWR_OUT_DCDC2_MASK
),
AXP_DESC_RANGES
(
AXP813
,
DCDC3
,
"dcdc3"
,
"vin3"
,
axp803_dcdc234_ranges
,
AXP803_DCDC234_NUM_VOLTAGES
,
AXP803_DCDC3_V_OUT
,
AXP803_DCDC3_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP803_PWR_OUT_DCDC3_MASK
),
AXP_DESC_RANGES
(
AXP813
,
DCDC4
,
"dcdc4"
,
"vin4"
,
axp803_dcdc234_ranges
,
AXP803_DCDC234_NUM_VOLTAGES
,
AXP803_DCDC4_V_OUT
,
AXP803_DCDC4_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP803_PWR_OUT_DCDC4_MASK
),
AXP_DESC_RANGES
(
AXP813
,
DCDC5
,
"dcdc5"
,
"vin5"
,
axp803_dcdc5_ranges
,
AXP803_DCDC5_NUM_VOLTAGES
,
AXP803_DCDC5_V_OUT
,
AXP803_DCDC5_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP803_PWR_OUT_DCDC5_MASK
),
AXP_DESC_RANGES
(
AXP813
,
DCDC6
,
"dcdc6"
,
"vin6"
,
axp803_dcdc6_ranges
,
AXP803_DCDC6_NUM_VOLTAGES
,
AXP803_DCDC6_V_OUT
,
AXP803_DCDC6_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP803_PWR_OUT_DCDC6_MASK
),
AXP_DESC_RANGES
(
AXP813
,
DCDC7
,
"dcdc7"
,
"vin7"
,
axp803_dcdc6_ranges
,
AXP803_DCDC6_NUM_VOLTAGES
,
AXP813_DCDC7_V_OUT
,
AXP813_DCDC7_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL1
,
AXP813_PWR_OUT_DCDC7_MASK
),
AXP_DESC
(
AXP813
,
ALDO1
,
"aldo1"
,
"aldoin"
,
700
,
3300
,
100
,
AXP22X_ALDO1_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL3
,
BIT
(
5
)),
AXP22X_ALDO1_V_OUT
,
AXP22X_ALDO1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL3
,
AXP806_PWR_OUT_ALDO1_MASK
),
AXP_DESC
(
AXP813
,
ALDO2
,
"aldo2"
,
"aldoin"
,
700
,
3300
,
100
,
AXP22X_ALDO2_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL3
,
BIT
(
6
)),
AXP22X_ALDO2_V_OUT
,
AXP22X_ALDO2_V_OUT
,
AXP22X_PWR_OUT_CTRL3
,
AXP806_PWR_OUT_ALDO2_MASK
),
AXP_DESC
(
AXP813
,
ALDO3
,
"aldo3"
,
"aldoin"
,
700
,
3300
,
100
,
AXP22X_ALDO3_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL3
,
BIT
(
7
)),
AXP22X_ALDO3_V_OUT
,
AXP22X_ALDO3_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL3
,
AXP806_PWR_OUT_ALDO3_MASK
),
AXP_DESC
(
AXP813
,
DLDO1
,
"dldo1"
,
"dldoin"
,
700
,
3300
,
100
,
AXP22X_DLDO1_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
3
)),
AXP_DESC_RANGES
(
AXP813
,
DLDO2
,
"dldo2"
,
"dldoin"
,
axp803_dldo2_ranges
,
32
,
AXP22X_DLDO2_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
4
)),
AXP22X_DLDO1_V_OUT
,
AXP22X_DLDO1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DLDO1_MASK
),
AXP_DESC_RANGES
(
AXP813
,
DLDO2
,
"dldo2"
,
"dldoin"
,
axp803_dldo2_ranges
,
AXP803_DLDO2_NUM_VOLTAGES
,
AXP22X_DLDO2_V_OUT
,
AXP22X_DLDO2_V_OUT
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DLDO2_MASK
),
AXP_DESC
(
AXP813
,
DLDO3
,
"dldo3"
,
"dldoin"
,
700
,
3300
,
100
,
AXP22X_DLDO3_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
5
)),
AXP22X_DLDO3_V_OUT
,
AXP22X_DLDO3_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DLDO3_MASK
),
AXP_DESC
(
AXP813
,
DLDO4
,
"dldo4"
,
"dldoin"
,
700
,
3300
,
100
,
AXP22X_DLDO4_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
6
)),
AXP22X_DLDO4_V_OUT
,
AXP22X_DLDO4_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DLDO4_MASK
),
AXP_DESC
(
AXP813
,
ELDO1
,
"eldo1"
,
"eldoin"
,
700
,
1900
,
50
,
AXP22X_ELDO1_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
0
)),
AXP22X_ELDO1_V_OUT
,
AXP22X_ELDO1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_ELDO1_MASK
),
AXP_DESC
(
AXP813
,
ELDO2
,
"eldo2"
,
"eldoin"
,
700
,
1900
,
50
,
AXP22X_ELDO2_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
1
)),
AXP22X_ELDO2_V_OUT
,
AXP22X_ELDO2_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_ELDO2_MASK
),
AXP_DESC
(
AXP813
,
ELDO3
,
"eldo3"
,
"eldoin"
,
700
,
1900
,
50
,
AXP22X_ELDO3_V_OUT
,
0x1f
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
2
)),
AXP22X_ELDO3_V_OUT
,
AXP22X_ELDO3_V_OUT
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_ELDO3_MASK
),
/* to do / check ... */
AXP_DESC
(
AXP813
,
FLDO1
,
"fldo1"
,
"fldoin"
,
700
,
1450
,
50
,
AXP803_FLDO1_V_OUT
,
0x0f
,
AXP22X_PWR_OUT_CTRL3
,
BIT
(
2
)),
AXP803_FLDO1_V_OUT
,
AXP803_FLDO1_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL3
,
AXP803_PWR_OUT_FLDO1_MASK
),
AXP_DESC
(
AXP813
,
FLDO2
,
"fldo2"
,
"fldoin"
,
700
,
1450
,
50
,
AXP803_FLDO2_V_OUT
,
0x0f
,
AXP22X_PWR_OUT_CTRL3
,
BIT
(
3
)),
AXP803_FLDO2_V_OUT
,
AXP803_FLDO2_V_OUT_MASK
,
AXP22X_PWR_OUT_CTRL3
,
AXP803_PWR_OUT_FLDO2_MASK
),
/*
* TODO: FLDO3 = {DCDC5, FLDOIN} / 2
*
...
...
@@ -482,12 +994,15 @@ static const struct regulator_desc axp813_regulators[] = {
*/
AXP_DESC_FIXED
(
AXP813
,
RTC_LDO
,
"rtc-ldo"
,
"ips"
,
1800
),
AXP_DESC_IO
(
AXP813
,
LDO_IO0
,
"ldo-io0"
,
"ips"
,
700
,
3300
,
100
,
AXP22X_LDO_IO0_V_OUT
,
0x1f
,
AXP20X_GPIO0_CTRL
,
0x07
,
AXP22X_LDO_IO0_V_OUT
,
AXP22X_LDO_IO0_V_OUT_MASK
,
AXP20X_GPIO0_CTRL
,
AXP20X_GPIO0_FUNC_MASK
,
AXP22X_IO_ENABLED
,
AXP22X_IO_DISABLED
),
AXP_DESC_IO
(
AXP813
,
LDO_IO1
,
"ldo-io1"
,
"ips"
,
700
,
3300
,
100
,
AXP22X_LDO_IO1_V_OUT
,
0x1f
,
AXP20X_GPIO1_CTRL
,
0x07
,
AXP22X_LDO_IO1_V_OUT
,
AXP22X_LDO_IO1_V_OUT_MASK
,
AXP20X_GPIO1_CTRL
,
AXP20X_GPIO1_FUNC_MASK
,
AXP22X_IO_ENABLED
,
AXP22X_IO_DISABLED
),
AXP_DESC_SW
(
AXP813
,
SW
,
"sw"
,
"swin"
,
AXP22X_PWR_OUT_CTRL2
,
BIT
(
7
)),
AXP_DESC_SW
(
AXP813
,
SW
,
"sw"
,
"swin"
,
AXP22X_PWR_OUT_CTRL2
,
AXP22X_PWR_OUT_DC1SW_MASK
),
};
static
int
axp20x_set_dcdc_freq
(
struct
platform_device
*
pdev
,
u32
dcdcfreq
)
...
...
@@ -663,9 +1178,9 @@ static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id)
switch
(
id
)
{
case
AXP803_DCDC3
:
return
!!
(
reg
&
BIT
(
6
)
);
return
!!
(
reg
&
AXP803_DCDC23_POLYPHASE_DUAL
);
case
AXP803_DCDC6
:
return
!!
(
reg
&
BIT
(
5
)
);
return
!!
(
reg
&
AXP803_DCDC56_POLYPHASE_DUAL
);
}
break
;
...
...
@@ -674,12 +1189,15 @@ static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id)
switch
(
id
)
{
case
AXP806_DCDCB
:
return
(((
reg
&
GENMASK
(
7
,
6
))
==
BIT
(
6
))
||
((
reg
&
GENMASK
(
7
,
6
))
==
BIT
(
7
)));
return
(((
reg
&
AXP806_DCDCABC_POLYPHASE_MASK
)
==
AXP806_DCDCAB_POLYPHASE_DUAL
)
||
((
reg
&
AXP806_DCDCABC_POLYPHASE_MASK
)
==
AXP806_DCDCABC_POLYPHASE_TRI
));
case
AXP806_DCDCC
:
return
((
reg
&
GENMASK
(
7
,
6
))
==
BIT
(
7
));
return
((
reg
&
AXP806_DCDCABC_POLYPHASE_MASK
)
==
AXP806_DCDCABC_POLYPHASE_TRI
);
case
AXP806_DCDCE
:
return
!!
(
reg
&
BIT
(
5
)
);
return
!!
(
reg
&
AXP806_DCDCDE_POLYPHASE_DUAL
);
}
break
;
...
...
drivers/regulator/bd718x7-regulator.c
View file @
b27d9668
...
...
@@ -131,6 +131,7 @@ static struct regulator_ops bd718xx_buck_regulator_nolinear_ops = {
.
disable
=
regulator_disable_regmap
,
.
is_enabled
=
regulator_is_enabled_regmap
,
.
list_voltage
=
regulator_list_voltage_table
,
.
map_voltage
=
regulator_map_voltage_ascend
,
.
set_voltage_sel
=
bd718xx_set_voltage_sel_restricted
,
.
get_voltage_sel
=
regulator_get_voltage_sel_regmap
,
.
set_voltage_time_sel
=
regulator_set_voltage_time_sel
,
...
...
@@ -1008,7 +1009,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
};
struct
bd718xx_pmic_inits
{
const
struct
bd718xx_regulator_data
(
*
r_datas
)[]
;
const
struct
bd718xx_regulator_data
*
r_datas
;
unsigned
int
r_amount
;
};
...
...
@@ -1018,11 +1019,11 @@ static int bd718xx_probe(struct platform_device *pdev)
struct
regulator_config
config
=
{
0
};
struct
bd718xx_pmic_inits
pmic_regulators
[]
=
{
[
BD718XX_TYPE_BD71837
]
=
{
.
r_datas
=
&
bd71837_regulators
,
.
r_datas
=
bd71837_regulators
,
.
r_amount
=
ARRAY_SIZE
(
bd71837_regulators
),
},
[
BD718XX_TYPE_BD71847
]
=
{
.
r_datas
=
&
bd71847_regulators
,
.
r_datas
=
bd71847_regulators
,
.
r_amount
=
ARRAY_SIZE
(
bd71847_regulators
),
},
};
...
...
@@ -1054,13 +1055,36 @@ static int bd718xx_probe(struct platform_device *pdev)
BD718XX_REG_REGLOCK
);
}
/* At poweroff transition PMIC HW disables EN bit for regulators but
* leaves SEL bit untouched. So if state transition from POWEROFF
* is done to SNVS - then all power rails controlled by SW (having
* SEL bit set) stay disabled as EN is cleared. This may result boot
* failure if any crucial systems are powered by these rails.
*
* Change the next stage from poweroff to be READY instead of SNVS
* for all reset types because OTP loading at READY will clear SEL
* bit allowing HW defaults for power rails to be used
*/
err
=
regmap_update_bits
(
mfd
->
regmap
,
BD718XX_REG_TRANS_COND1
,
BD718XX_ON_REQ_POWEROFF_MASK
|
BD718XX_SWRESET_POWEROFF_MASK
|
BD718XX_WDOG_POWEROFF_MASK
|
BD718XX_KEY_L_POWEROFF_MASK
,
BD718XX_POWOFF_TO_RDY
);
if
(
err
)
{
dev_err
(
&
pdev
->
dev
,
"Failed to change reset target
\n
"
);
goto
err
;
}
else
{
dev_dbg
(
&
pdev
->
dev
,
"Changed all resets from SVNS to READY
\n
"
);
}
for
(
i
=
0
;
i
<
pmic_regulators
[
mfd
->
chip_type
].
r_amount
;
i
++
)
{
const
struct
regulator_desc
*
desc
;
struct
regulator_dev
*
rdev
;
const
struct
bd718xx_regulator_data
*
r
;
r
=
&
(
*
pmic_regulators
[
mfd
->
chip_type
].
r_datas
)
[
i
];
r
=
&
pmic_regulators
[
mfd
->
chip_type
].
r_datas
[
i
];
desc
=
&
r
->
desc
;
config
.
dev
=
pdev
->
dev
.
parent
;
...
...
drivers/regulator/bd9571mwv-regulator.c
View file @
b27d9668
// SPDX-License-Identifier: GPL-2.0
/*
* ROHM BD9571MWV-M regulator driver
*
* Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether expressed or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License version 2 for more details.
*
* Based on the TPS65086 driver
*
* NOTE: VD09 is missing
...
...
drivers/regulator/core.c
View file @
b27d9668
...
...
@@ -50,6 +50,8 @@
#define rdev_dbg(rdev, fmt, ...) \
pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
static
DEFINE_WW_CLASS
(
regulator_ww_class
);
static
DEFINE_MUTEX
(
regulator_nesting_mutex
);
static
DEFINE_MUTEX
(
regulator_list_mutex
);
static
LIST_HEAD
(
regulator_map_list
);
static
LIST_HEAD
(
regulator_ena_gpio_list
);
...
...
@@ -97,7 +99,7 @@ struct regulator_supply_alias {
};
static
int
_regulator_is_enabled
(
struct
regulator_dev
*
rdev
);
static
int
_regulator_disable
(
struct
regulator
_dev
*
rdev
);
static
int
_regulator_disable
(
struct
regulator
*
regulator
);
static
int
_regulator_get_voltage
(
struct
regulator_dev
*
rdev
);
static
int
_regulator_get_current_limit
(
struct
regulator_dev
*
rdev
);
static
unsigned
int
_regulator_get_mode
(
struct
regulator_dev
*
rdev
);
...
...
@@ -105,6 +107,11 @@ static int _notifier_call_chain(struct regulator_dev *rdev,
unsigned
long
event
,
void
*
data
);
static
int
_regulator_do_set_voltage
(
struct
regulator_dev
*
rdev
,
int
min_uV
,
int
max_uV
);
static
int
regulator_balance_voltage
(
struct
regulator_dev
*
rdev
,
suspend_state_t
state
);
static
int
regulator_set_voltage_rdev
(
struct
regulator_dev
*
rdev
,
int
min_uV
,
int
max_uV
,
suspend_state_t
state
);
static
struct
regulator
*
create_regulator
(
struct
regulator_dev
*
rdev
,
struct
device
*
dev
,
const
char
*
supply_name
);
...
...
@@ -149,7 +156,7 @@ static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev)
/**
* regulator_lock_nested - lock a single regulator
* @rdev: regulator source
* @
subclass: mutex subclass used for lockdep
* @
ww_ctx: w/w mutex acquire context
*
* This function can be called many times by one task on
* a single regulator and its mutex will be locked only
...
...
@@ -157,24 +164,52 @@ static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev)
* than the one, which initially locked the mutex, it will
* wait on mutex.
*/
static
void
regulator_lock_nested
(
struct
regulator_dev
*
rdev
,
unsigned
int
subclass
)
static
inline
int
regulator_lock_nested
(
struct
regulator_dev
*
rdev
,
struct
ww_acquire_ctx
*
ww_ctx
)
{
if
(
!
mutex_trylock
(
&
rdev
->
mutex
))
{
if
(
rdev
->
mutex_owner
==
current
)
{
bool
lock
=
false
;
int
ret
=
0
;
mutex_lock
(
&
regulator_nesting_mutex
);
if
(
ww_ctx
||
!
ww_mutex_trylock
(
&
rdev
->
mutex
))
{
if
(
rdev
->
mutex_owner
==
current
)
rdev
->
ref_cnt
++
;
return
;
else
lock
=
true
;
if
(
lock
)
{
mutex_unlock
(
&
regulator_nesting_mutex
);
ret
=
ww_mutex_lock
(
&
rdev
->
mutex
,
ww_ctx
);
mutex_lock
(
&
regulator_nesting_mutex
);
}
mutex_lock_nested
(
&
rdev
->
mutex
,
subclass
);
}
else
{
lock
=
true
;
}
if
(
lock
&&
ret
!=
-
EDEADLK
)
{
rdev
->
ref_cnt
++
;
rdev
->
mutex_owner
=
current
;
}
rdev
->
ref_cnt
=
1
;
rdev
->
mutex_owner
=
current
;
mutex_unlock
(
&
regulator_nesting_mutex
);
return
ret
;
}
static
inline
void
regulator_lock
(
struct
regulator_dev
*
rdev
)
/**
* regulator_lock - lock a single regulator
* @rdev: regulator source
*
* This function can be called many times by one task on
* a single regulator and its mutex will be locked only
* once. If a task, which is calling this function is other
* than the one, which initially locked the mutex, it will
* wait on mutex.
*/
void
regulator_lock
(
struct
regulator_dev
*
rdev
)
{
regulator_lock_nested
(
rdev
,
0
);
regulator_lock_nested
(
rdev
,
NULL
);
}
/**
...
...
@@ -184,47 +219,190 @@ static inline void regulator_lock(struct regulator_dev *rdev)
* This function unlocks the mutex when the
* reference counter reaches 0.
*/
static
void
regulator_unlock
(
struct
regulator_dev
*
rdev
)
void
regulator_unlock
(
struct
regulator_dev
*
rdev
)
{
mutex_lock
(
&
regulator_nesting_mutex
);
if
(
--
rdev
->
ref_cnt
==
0
)
{
rdev
->
mutex_owner
=
NULL
;
ww_mutex_unlock
(
&
rdev
->
mutex
);
}
WARN_ON_ONCE
(
rdev
->
ref_cnt
<
0
);
mutex_unlock
(
&
regulator_nesting_mutex
);
}
static
bool
regulator_supply_is_couple
(
struct
regulator_dev
*
rdev
)
{
if
(
rdev
->
ref_cnt
!=
0
)
{
rdev
->
ref_cnt
--
;
struct
regulator_dev
*
c_rdev
;
int
i
;
if
(
!
rdev
->
ref_cnt
)
{
rdev
->
mutex_owner
=
NULL
;
mutex_unlock
(
&
rdev
->
mutex
);
for
(
i
=
1
;
i
<
rdev
->
coupling_desc
.
n_coupled
;
i
++
)
{
c_rdev
=
rdev
->
coupling_desc
.
coupled_rdevs
[
i
];
if
(
rdev
->
supply
->
rdev
==
c_rdev
)
return
true
;
}
return
false
;
}
static
void
regulator_unlock_recursive
(
struct
regulator_dev
*
rdev
,
unsigned
int
n_coupled
)
{
struct
regulator_dev
*
c_rdev
;
int
i
;
for
(
i
=
n_coupled
;
i
>
0
;
i
--
)
{
c_rdev
=
rdev
->
coupling_desc
.
coupled_rdevs
[
i
-
1
];
if
(
!
c_rdev
)
continue
;
if
(
c_rdev
->
supply
&&
!
regulator_supply_is_couple
(
c_rdev
))
regulator_unlock_recursive
(
c_rdev
->
supply
->
rdev
,
c_rdev
->
coupling_desc
.
n_coupled
);
regulator_unlock
(
c_rdev
);
}
}
static
int
regulator_lock_recursive
(
struct
regulator_dev
*
rdev
,
struct
regulator_dev
**
new_contended_rdev
,
struct
regulator_dev
**
old_contended_rdev
,
struct
ww_acquire_ctx
*
ww_ctx
)
{
struct
regulator_dev
*
c_rdev
;
int
i
,
err
;
for
(
i
=
0
;
i
<
rdev
->
coupling_desc
.
n_coupled
;
i
++
)
{
c_rdev
=
rdev
->
coupling_desc
.
coupled_rdevs
[
i
];
if
(
!
c_rdev
)
continue
;
if
(
c_rdev
!=
*
old_contended_rdev
)
{
err
=
regulator_lock_nested
(
c_rdev
,
ww_ctx
);
if
(
err
)
{
if
(
err
==
-
EDEADLK
)
{
*
new_contended_rdev
=
c_rdev
;
goto
err_unlock
;
}
/* shouldn't happen */
WARN_ON_ONCE
(
err
!=
-
EALREADY
);
}
}
else
{
*
old_contended_rdev
=
NULL
;
}
if
(
c_rdev
->
supply
&&
!
regulator_supply_is_couple
(
c_rdev
))
{
err
=
regulator_lock_recursive
(
c_rdev
->
supply
->
rdev
,
new_contended_rdev
,
old_contended_rdev
,
ww_ctx
);
if
(
err
)
{
regulator_unlock
(
c_rdev
);
goto
err_unlock
;
}
}
}
return
0
;
err_unlock:
regulator_unlock_recursive
(
rdev
,
i
);
return
err
;
}
/**
* regulator_lock_supply - lock a regulator and its supplies
* @rdev: regulator source
* regulator_unlock_dependent - unlock regulator's suppliers and coupled
* regulators
* @rdev: regulator source
* @ww_ctx: w/w mutex acquire context
*
* Unlock all regulators related with rdev by coupling or suppling.
*/
static
void
regulator_lock_supply
(
struct
regulator_dev
*
rdev
)
static
void
regulator_unlock_dependent
(
struct
regulator_dev
*
rdev
,
struct
ww_acquire_ctx
*
ww_ctx
)
{
int
i
;
for
(
i
=
0
;
rdev
;
rdev
=
rdev_get_supply
(
rdev
),
i
++
)
regulator_lock_nested
(
rdev
,
i
);
regulator_unlock_recursive
(
rdev
,
rdev
->
coupling_desc
.
n_coupled
);
ww_acquire_fini
(
ww_ctx
);
}
/**
* regulator_unlock_supply - unlock a regulator and its supplies
* @rdev: regulator source
* regulator_lock_dependent - lock regulator's suppliers and coupled regulators
* @rdev: regulator source
* @ww_ctx: w/w mutex acquire context
*
* This function as a wrapper on regulator_lock_recursive(), which locks
* all regulators related with rdev by coupling or suppling.
*/
static
void
regulator_unlock_supply
(
struct
regulator_dev
*
rdev
)
static
void
regulator_lock_dependent
(
struct
regulator_dev
*
rdev
,
struct
ww_acquire_ctx
*
ww_ctx
)
{
struct
regulator
*
supply
;
struct
regulator_dev
*
new_contended_rdev
=
NULL
;
struct
regulator_dev
*
old_contended_rdev
=
NULL
;
int
err
;
mutex_lock
(
&
regulator_list_mutex
);
ww_acquire_init
(
ww_ctx
,
&
regulator_ww_class
);
do
{
if
(
new_contended_rdev
)
{
ww_mutex_lock_slow
(
&
new_contended_rdev
->
mutex
,
ww_ctx
);
old_contended_rdev
=
new_contended_rdev
;
old_contended_rdev
->
ref_cnt
++
;
}
err
=
regulator_lock_recursive
(
rdev
,
&
new_contended_rdev
,
&
old_contended_rdev
,
ww_ctx
);
if
(
old_contended_rdev
)
regulator_unlock
(
old_contended_rdev
);
}
while
(
err
==
-
EDEADLK
);
ww_acquire_done
(
ww_ctx
);
mutex_unlock
(
&
regulator_list_mutex
);
}
while
(
1
)
{
regulator_unlock
(
rdev
);
supply
=
rdev
->
supply
;
/**
* of_get_child_regulator - get a child regulator device node
* based on supply name
* @parent: Parent device node
* @prop_name: Combination regulator supply name and "-supply"
*
* Traverse all child nodes.
* Extract the child regulator device node corresponding to the supply name.
* returns the device node corresponding to the regulator if found, else
* returns NULL.
*/
static
struct
device_node
*
of_get_child_regulator
(
struct
device_node
*
parent
,
const
char
*
prop_name
)
{
struct
device_node
*
regnode
=
NULL
;
struct
device_node
*
child
=
NULL
;
if
(
!
rdev
->
supply
)
return
;
for_each_child_of_node
(
parent
,
child
)
{
regnode
=
of_parse_phandle
(
child
,
prop_name
,
0
)
;
rdev
=
supply
->
rdev
;
if
(
!
regnode
)
{
regnode
=
of_get_child_regulator
(
child
,
prop_name
);
if
(
regnode
)
return
regnode
;
}
else
{
return
regnode
;
}
}
return
NULL
;
}
/**
...
...
@@ -247,6 +425,10 @@ static struct device_node *of_get_regulator(struct device *dev, const char *supp
regnode
=
of_parse_phandle
(
dev
->
of_node
,
prop_name
,
0
);
if
(
!
regnode
)
{
regnode
=
of_get_child_regulator
(
dev
->
of_node
,
prop_name
);
if
(
regnode
)
return
regnode
;
dev_dbg
(
dev
,
"Looking up %s property in node %pOF failed
\n
"
,
prop_name
,
dev
->
of_node
);
return
NULL
;
...
...
@@ -582,8 +764,10 @@ static ssize_t regulator_total_uA_show(struct device *dev,
int
uA
=
0
;
regulator_lock
(
rdev
);
list_for_each_entry
(
regulator
,
&
rdev
->
consumer_list
,
list
)
uA
+=
regulator
->
uA_load
;
list_for_each_entry
(
regulator
,
&
rdev
->
consumer_list
,
list
)
{
if
(
regulator
->
enable_count
)
uA
+=
regulator
->
uA_load
;
}
regulator_unlock
(
rdev
);
return
sprintf
(
buf
,
"%d
\n
"
,
uA
);
}
...
...
@@ -738,7 +922,7 @@ static int drms_uA_update(struct regulator_dev *rdev)
int
current_uA
=
0
,
output_uV
,
input_uV
,
err
;
unsigned
int
mode
;
lockdep_assert_held_once
(
&
rdev
->
mutex
);
lockdep_assert_held_once
(
&
rdev
->
mutex
.
base
);
/*
* first check to see if we can set modes at all, otherwise just
...
...
@@ -756,8 +940,10 @@ static int drms_uA_update(struct regulator_dev *rdev)
return
-
EINVAL
;
/* calc total requested load */
list_for_each_entry
(
sibling
,
&
rdev
->
consumer_list
,
list
)
current_uA
+=
sibling
->
uA_load
;
list_for_each_entry
(
sibling
,
&
rdev
->
consumer_list
,
list
)
{
if
(
sibling
->
enable_count
)
current_uA
+=
sibling
->
uA_load
;
}
current_uA
+=
rdev
->
constraints
->
system_load
;
...
...
@@ -1156,6 +1342,12 @@ static int set_machine_constraints(struct regulator_dev *rdev,
rdev_err
(
rdev
,
"failed to set initial mode: %d
\n
"
,
ret
);
return
ret
;
}
}
else
if
(
rdev
->
constraints
->
system_load
)
{
/*
* We'll only apply the initial system load if an
* initial mode wasn't specified.
*/
drms_uA_update
(
rdev
);
}
if
((
rdev
->
constraints
->
ramp_delay
||
rdev
->
constraints
->
ramp_disable
)
...
...
@@ -1207,11 +1399,21 @@ static int set_machine_constraints(struct regulator_dev *rdev,
* and we have control then make sure it is enabled.
*/
if
(
rdev
->
constraints
->
always_on
||
rdev
->
constraints
->
boot_on
)
{
if
(
rdev
->
supply
)
{
ret
=
regulator_enable
(
rdev
->
supply
);
if
(
ret
<
0
)
{
_regulator_put
(
rdev
->
supply
);
rdev
->
supply
=
NULL
;
return
ret
;
}
}
ret
=
_regulator_do_enable
(
rdev
);
if
(
ret
<
0
&&
ret
!=
-
EINVAL
)
{
rdev_err
(
rdev
,
"failed to enable
\n
"
);
return
ret
;
}
rdev
->
use_count
++
;
}
print_constraints
(
rdev
);
...
...
@@ -1628,8 +1830,12 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
return
ret
;
}
/* Cascade always-on state to supply */
if
(
_regulator_is_enabled
(
rdev
))
{
/*
* In set_machine_constraints() we may have turned this regulator on
* but we couldn't propagate to the supply if it hadn't been resolved
* yet. Do it now.
*/
if
(
rdev
->
use_count
)
{
ret
=
regulator_enable
(
rdev
->
supply
);
if
(
ret
<
0
)
{
_regulator_put
(
rdev
->
supply
);
...
...
@@ -1713,6 +1919,16 @@ struct regulator *_regulator_get(struct device *dev, const char *id,
return
regulator
;
}
mutex_lock
(
&
regulator_list_mutex
);
ret
=
(
rdev
->
coupling_desc
.
n_resolved
!=
rdev
->
coupling_desc
.
n_coupled
);
mutex_unlock
(
&
regulator_list_mutex
);
if
(
ret
!=
0
)
{
regulator
=
ERR_PTR
(
-
EPROBE_DEFER
);
put_device
(
&
rdev
->
dev
);
return
regulator
;
}
ret
=
regulator_resolve_supply
(
rdev
);
if
(
ret
<
0
)
{
regulator
=
ERR_PTR
(
ret
);
...
...
@@ -1832,6 +2048,9 @@ static void _regulator_put(struct regulator *regulator)
lockdep_assert_held_once
(
&
regulator_list_mutex
);
/* Docs say you must disable before calling regulator_put() */
WARN_ON
(
regulator
->
enable_count
);
rdev
=
regulator
->
rdev
;
debugfs_remove_recursive
(
regulator
->
debugfs
);
...
...
@@ -2225,34 +2444,109 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
return
0
;
}
/**
* _regulator_handle_consumer_enable - handle that a consumer enabled
* @regulator: regulator source
*
* Some things on a regulator consumer (like the contribution towards total
* load on the regulator) only have an effect when the consumer wants the
* regulator enabled. Explained in example with two consumers of the same
* regulator:
* consumer A: set_load(100); => total load = 0
* consumer A: regulator_enable(); => total load = 100
* consumer B: set_load(1000); => total load = 100
* consumer B: regulator_enable(); => total load = 1100
* consumer A: regulator_disable(); => total_load = 1000
*
* This function (together with _regulator_handle_consumer_disable) is
* responsible for keeping track of the refcount for a given regulator consumer
* and applying / unapplying these things.
*
* Returns 0 upon no error; -error upon error.
*/
static
int
_regulator_handle_consumer_enable
(
struct
regulator
*
regulator
)
{
struct
regulator_dev
*
rdev
=
regulator
->
rdev
;
lockdep_assert_held_once
(
&
rdev
->
mutex
.
base
);
regulator
->
enable_count
++
;
if
(
regulator
->
uA_load
&&
regulator
->
enable_count
==
1
)
return
drms_uA_update
(
rdev
);
return
0
;
}
/**
* _regulator_handle_consumer_disable - handle that a consumer disabled
* @regulator: regulator source
*
* The opposite of _regulator_handle_consumer_enable().
*
* Returns 0 upon no error; -error upon error.
*/
static
int
_regulator_handle_consumer_disable
(
struct
regulator
*
regulator
)
{
struct
regulator_dev
*
rdev
=
regulator
->
rdev
;
lockdep_assert_held_once
(
&
rdev
->
mutex
.
base
);
if
(
!
regulator
->
enable_count
)
{
rdev_err
(
rdev
,
"Underflow of regulator enable count
\n
"
);
return
-
EINVAL
;
}
regulator
->
enable_count
--
;
if
(
regulator
->
uA_load
&&
regulator
->
enable_count
==
0
)
return
drms_uA_update
(
rdev
);
return
0
;
}
/* locks held by regulator_enable() */
static
int
_regulator_enable
(
struct
regulator
_dev
*
rdev
)
static
int
_regulator_enable
(
struct
regulator
*
regulator
)
{
struct
regulator_dev
*
rdev
=
regulator
->
rdev
;
int
ret
;
lockdep_assert_held_once
(
&
rdev
->
mutex
);
lockdep_assert_held_once
(
&
rdev
->
mutex
.
base
);
/* check voltage and requested load before enabling */
if
(
regulator_ops_is_valid
(
rdev
,
REGULATOR_CHANGE_DRMS
))
drms_uA_update
(
rdev
);
if
(
rdev
->
use_count
==
0
&&
rdev
->
supply
)
{
ret
=
_regulator_enable
(
rdev
->
supply
);
if
(
ret
<
0
)
return
ret
;
}
/* balance only if there are regulators coupled */
if
(
rdev
->
coupling_desc
.
n_coupled
>
1
)
{
ret
=
regulator_balance_voltage
(
rdev
,
PM_SUSPEND_ON
);
if
(
ret
<
0
)
goto
err_disable_supply
;
}
ret
=
_regulator_handle_consumer_enable
(
regulator
);
if
(
ret
<
0
)
goto
err_disable_supply
;
if
(
rdev
->
use_count
==
0
)
{
/* The regulator may on if it's not switchable or left on */
ret
=
_regulator_is_enabled
(
rdev
);
if
(
ret
==
-
EINVAL
||
ret
==
0
)
{
if
(
!
regulator_ops_is_valid
(
rdev
,
REGULATOR_CHANGE_STATUS
))
return
-
EPERM
;
REGULATOR_CHANGE_STATUS
))
{
ret
=
-
EPERM
;
goto
err_consumer_disable
;
}
ret
=
_regulator_do_enable
(
rdev
);
if
(
ret
<
0
)
return
ret
;
goto
err_consumer_disable
;
_notifier_call_chain
(
rdev
,
REGULATOR_EVENT_ENABLE
,
NULL
);
}
else
if
(
ret
<
0
)
{
rdev_err
(
rdev
,
"is_enabled() failed: %d
\n
"
,
ret
);
return
ret
;
goto
err_consumer_disable
;
}
/* Fallthrough on positive return values - already enabled */
}
...
...
@@ -2260,6 +2554,15 @@ static int _regulator_enable(struct regulator_dev *rdev)
rdev
->
use_count
++
;
return
0
;
err_consumer_disable:
_regulator_handle_consumer_disable
(
regulator
);
err_disable_supply:
if
(
rdev
->
use_count
==
0
&&
rdev
->
supply
)
_regulator_disable
(
rdev
->
supply
);
return
ret
;
}
/**
...
...
@@ -2276,23 +2579,12 @@ static int _regulator_enable(struct regulator_dev *rdev)
int
regulator_enable
(
struct
regulator
*
regulator
)
{
struct
regulator_dev
*
rdev
=
regulator
->
rdev
;
int
ret
=
0
;
if
(
regulator
->
always_on
)
return
0
;
if
(
rdev
->
supply
)
{
ret
=
regulator_enable
(
rdev
->
supply
);
if
(
ret
!=
0
)
return
ret
;
}
mutex_lock
(
&
rdev
->
mutex
);
ret
=
_regulator_enable
(
rdev
);
mutex_unlock
(
&
rdev
->
mutex
);
struct
ww_acquire_ctx
ww_ctx
;
int
ret
;
if
(
ret
!=
0
&&
rdev
->
supply
)
regulator_disable
(
rdev
->
supply
);
regulator_lock_dependent
(
rdev
,
&
ww_ctx
);
ret
=
_regulator_enable
(
regulator
);
regulator_unlock_dependent
(
rdev
,
&
ww_ctx
);
return
ret
;
}
...
...
@@ -2330,11 +2622,12 @@ static int _regulator_do_disable(struct regulator_dev *rdev)
}
/* locks held by regulator_disable() */
static
int
_regulator_disable
(
struct
regulator
_dev
*
rdev
)
static
int
_regulator_disable
(
struct
regulator
*
regulator
)
{
struct
regulator_dev
*
rdev
=
regulator
->
rdev
;
int
ret
=
0
;
lockdep_assert_held_once
(
&
rdev
->
mutex
);
lockdep_assert_held_once
(
&
rdev
->
mutex
.
base
);
if
(
WARN
(
rdev
->
use_count
<=
0
,
"unbalanced disables for %s
\n
"
,
rdev_get_name
(
rdev
)))
...
...
@@ -2366,12 +2659,18 @@ static int _regulator_disable(struct regulator_dev *rdev)
rdev
->
use_count
=
0
;
}
else
if
(
rdev
->
use_count
>
1
)
{
if
(
regulator_ops_is_valid
(
rdev
,
REGULATOR_CHANGE_DRMS
))
drms_uA_update
(
rdev
);
rdev
->
use_count
--
;
}
if
(
ret
==
0
)
ret
=
_regulator_handle_consumer_disable
(
regulator
);
if
(
ret
==
0
&&
rdev
->
coupling_desc
.
n_coupled
>
1
)
ret
=
regulator_balance_voltage
(
rdev
,
PM_SUSPEND_ON
);
if
(
ret
==
0
&&
rdev
->
use_count
==
0
&&
rdev
->
supply
)
ret
=
_regulator_disable
(
rdev
->
supply
);
return
ret
;
}
...
...
@@ -2390,17 +2689,12 @@ static int _regulator_disable(struct regulator_dev *rdev)
int
regulator_disable
(
struct
regulator
*
regulator
)
{
struct
regulator_dev
*
rdev
=
regulator
->
rdev
;
int
ret
=
0
;
if
(
regulator
->
always_on
)
return
0
;
mutex_lock
(
&
rdev
->
mutex
);
ret
=
_regulator_disable
(
rdev
);
mutex_unlock
(
&
rdev
->
mutex
);
struct
ww_acquire_ctx
ww_ctx
;
int
ret
;
if
(
ret
==
0
&&
rdev
->
supply
)
regulator_disable
(
rdev
->
supply
);
regulator_lock_dependent
(
rdev
,
&
ww_ctx
);
ret
=
_regulator_disable
(
regulator
);
regulator_unlock_dependent
(
rdev
,
&
ww_ctx
);
return
ret
;
}
...
...
@@ -2411,7 +2705,7 @@ static int _regulator_force_disable(struct regulator_dev *rdev)
{
int
ret
=
0
;
lockdep_assert_held_once
(
&
rdev
->
mutex
);
lockdep_assert_held_once
(
&
rdev
->
mutex
.
base
);
ret
=
_notifier_call_chain
(
rdev
,
REGULATOR_EVENT_FORCE_DISABLE
|
REGULATOR_EVENT_PRE_DISABLE
,
NULL
);
...
...
@@ -2444,16 +2738,25 @@ static int _regulator_force_disable(struct regulator_dev *rdev)
int
regulator_force_disable
(
struct
regulator
*
regulator
)
{
struct
regulator_dev
*
rdev
=
regulator
->
rdev
;
struct
ww_acquire_ctx
ww_ctx
;
int
ret
;
mutex_lock
(
&
rdev
->
mute
x
);
regulator
->
uA_load
=
0
;
regulator_lock_dependent
(
rdev
,
&
ww_ct
x
);
ret
=
_regulator_force_disable
(
regulator
->
rdev
);
mutex_unlock
(
&
rdev
->
mutex
);
if
(
rdev
->
supply
)
while
(
rdev
->
open_count
--
)
regulator_disable
(
rdev
->
supply
);
if
(
rdev
->
coupling_desc
.
n_coupled
>
1
)
regulator_balance_voltage
(
rdev
,
PM_SUSPEND_ON
);
if
(
regulator
->
uA_load
)
{
regulator
->
uA_load
=
0
;
ret
=
drms_uA_update
(
rdev
);
}
if
(
rdev
->
use_count
!=
0
&&
rdev
->
supply
)
_regulator_disable
(
rdev
->
supply
);
regulator_unlock_dependent
(
rdev
,
&
ww_ctx
);
return
ret
;
}
...
...
@@ -2463,14 +2766,12 @@ static void regulator_disable_work(struct work_struct *work)
{
struct
regulator_dev
*
rdev
=
container_of
(
work
,
struct
regulator_dev
,
disable_work
.
work
);
struct
ww_acquire_ctx
ww_ctx
;
int
count
,
i
,
ret
;
struct
regulator
*
regulator
;
int
total_count
=
0
;
regulator_lock
(
rdev
);
BUG_ON
(
!
rdev
->
deferred_disables
);
count
=
rdev
->
deferred_disables
;
rdev
->
deferred_disables
=
0
;
regulator_lock_dependent
(
rdev
,
&
ww_ctx
);
/*
* Workqueue functions queue the new work instance while the previous
...
...
@@ -2480,13 +2781,27 @@ static void regulator_disable_work(struct work_struct *work)
*/
cancel_delayed_work
(
&
rdev
->
disable_work
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
ret
=
_regulator_disable
(
rdev
);
if
(
ret
!=
0
)
rdev_err
(
rdev
,
"Deferred disable failed: %d
\n
"
,
ret
);
list_for_each_entry
(
regulator
,
&
rdev
->
consumer_list
,
list
)
{
count
=
regulator
->
deferred_disables
;
if
(
!
count
)
continue
;
total_count
+=
count
;
regulator
->
deferred_disables
=
0
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
ret
=
_regulator_disable
(
regulator
);
if
(
ret
!=
0
)
rdev_err
(
rdev
,
"Deferred disable failed: %d
\n
"
,
ret
);
}
}
WARN_ON
(
!
total_count
);
regulator_unlock
(
rdev
);
if
(
rdev
->
coupling_desc
.
n_coupled
>
1
)
regulator_balance_voltage
(
rdev
,
PM_SUSPEND_ON
);
regulator_unlock_dependent
(
rdev
,
&
ww_ctx
);
if
(
rdev
->
supply
)
{
for
(
i
=
0
;
i
<
count
;
i
++
)
{
...
...
@@ -2515,14 +2830,11 @@ int regulator_disable_deferred(struct regulator *regulator, int ms)
{
struct
regulator_dev
*
rdev
=
regulator
->
rdev
;
if
(
regulator
->
always_on
)
return
0
;
if
(
!
ms
)
return
regulator_disable
(
regulator
);
regulator_lock
(
rdev
);
r
dev
->
deferred_disables
++
;
r
egulator
->
deferred_disables
++
;
mod_delayed_work
(
system_power_efficient_wq
,
&
rdev
->
disable_work
,
msecs_to_jiffies
(
ms
));
regulator_unlock
(
rdev
);
...
...
@@ -2597,9 +2909,9 @@ int regulator_is_enabled(struct regulator *regulator)
if
(
regulator
->
always_on
)
return
1
;
mutex_lock
(
&
regulator
->
rdev
->
mutex
);
regulator_lock
(
regulator
->
rdev
);
ret
=
_regulator_is_enabled
(
regulator
->
rdev
);
mutex_unlock
(
&
regulator
->
rdev
->
mutex
);
regulator_unlock
(
regulator
->
rdev
);
return
ret
;
}
...
...
@@ -3013,8 +3325,6 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
int
ret
=
0
;
int
old_min_uV
,
old_max_uV
;
int
current_uV
;
int
best_supply_uV
=
0
;
int
supply_change_uV
=
0
;
/* If we're setting the same range as last time the change
* should be a noop (some cpufreq implementations use the same
...
...
@@ -3054,10 +3364,27 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
voltage
->
min_uV
=
min_uV
;
voltage
->
max_uV
=
max_uV
;
ret
=
regulator_check_consumers
(
rdev
,
&
min_uV
,
&
max_uV
,
state
);
/* for not coupled regulators this will just set the voltage */
ret
=
regulator_balance_voltage
(
rdev
,
state
);
if
(
ret
<
0
)
goto
out2
;
out:
return
0
;
out2:
voltage
->
min_uV
=
old_min_uV
;
voltage
->
max_uV
=
old_max_uV
;
return
ret
;
}
static
int
regulator_set_voltage_rdev
(
struct
regulator_dev
*
rdev
,
int
min_uV
,
int
max_uV
,
suspend_state_t
state
)
{
int
best_supply_uV
=
0
;
int
supply_change_uV
=
0
;
int
ret
;
if
(
rdev
->
supply
&&
regulator_ops_is_valid
(
rdev
->
supply
->
rdev
,
REGULATOR_CHANGE_VOLTAGE
)
&&
...
...
@@ -3069,13 +3396,13 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
selector
=
regulator_map_voltage
(
rdev
,
min_uV
,
max_uV
);
if
(
selector
<
0
)
{
ret
=
selector
;
goto
out
2
;
goto
out
;
}
best_supply_uV
=
_regulator_list_voltage
(
rdev
,
selector
,
0
);
if
(
best_supply_uV
<
0
)
{
ret
=
best_supply_uV
;
goto
out
2
;
goto
out
;
}
best_supply_uV
+=
rdev
->
desc
->
min_dropout_uV
;
...
...
@@ -3083,7 +3410,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
current_supply_uV
=
_regulator_get_voltage
(
rdev
->
supply
->
rdev
);
if
(
current_supply_uV
<
0
)
{
ret
=
current_supply_uV
;
goto
out
2
;
goto
out
;
}
supply_change_uV
=
best_supply_uV
-
current_supply_uV
;
...
...
@@ -3095,7 +3422,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
if
(
ret
)
{
dev_err
(
&
rdev
->
dev
,
"Failed to increase supply voltage: %d
\n
"
,
ret
);
goto
out
2
;
goto
out
;
}
}
...
...
@@ -3105,7 +3432,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
ret
=
_regulator_do_set_suspend_voltage
(
rdev
,
min_uV
,
max_uV
,
state
);
if
(
ret
<
0
)
goto
out
2
;
goto
out
;
if
(
supply_change_uV
<
0
)
{
ret
=
regulator_set_voltage_unlocked
(
rdev
->
supply
,
...
...
@@ -3119,10 +3446,273 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
out:
return
ret
;
out2:
voltage
->
min_uV
=
old_min_uV
;
voltage
->
max_uV
=
old_max_uV
;
}
static
int
regulator_limit_voltage_step
(
struct
regulator_dev
*
rdev
,
int
*
current_uV
,
int
*
min_uV
)
{
struct
regulation_constraints
*
constraints
=
rdev
->
constraints
;
/* Limit voltage change only if necessary */
if
(
!
constraints
->
max_uV_step
||
!
_regulator_is_enabled
(
rdev
))
return
1
;
if
(
*
current_uV
<
0
)
{
*
current_uV
=
_regulator_get_voltage
(
rdev
);
if
(
*
current_uV
<
0
)
return
*
current_uV
;
}
if
(
abs
(
*
current_uV
-
*
min_uV
)
<=
constraints
->
max_uV_step
)
return
1
;
/* Clamp target voltage within the given step */
if
(
*
current_uV
<
*
min_uV
)
*
min_uV
=
min
(
*
current_uV
+
constraints
->
max_uV_step
,
*
min_uV
);
else
*
min_uV
=
max
(
*
current_uV
-
constraints
->
max_uV_step
,
*
min_uV
);
return
0
;
}
static
int
regulator_get_optimal_voltage
(
struct
regulator_dev
*
rdev
,
int
*
current_uV
,
int
*
min_uV
,
int
*
max_uV
,
suspend_state_t
state
,
int
n_coupled
)
{
struct
coupling_desc
*
c_desc
=
&
rdev
->
coupling_desc
;
struct
regulator_dev
**
c_rdevs
=
c_desc
->
coupled_rdevs
;
struct
regulation_constraints
*
constraints
=
rdev
->
constraints
;
int
max_spread
=
constraints
->
max_spread
;
int
desired_min_uV
=
0
,
desired_max_uV
=
INT_MAX
;
int
max_current_uV
=
0
,
min_current_uV
=
INT_MAX
;
int
highest_min_uV
=
0
,
target_uV
,
possible_uV
;
int
i
,
ret
;
bool
done
;
*
current_uV
=
-
1
;
/*
* If there are no coupled regulators, simply set the voltage
* demanded by consumers.
*/
if
(
n_coupled
==
1
)
{
/*
* If consumers don't provide any demands, set voltage
* to min_uV
*/
desired_min_uV
=
constraints
->
min_uV
;
desired_max_uV
=
constraints
->
max_uV
;
ret
=
regulator_check_consumers
(
rdev
,
&
desired_min_uV
,
&
desired_max_uV
,
state
);
if
(
ret
<
0
)
return
ret
;
possible_uV
=
desired_min_uV
;
done
=
true
;
goto
finish
;
}
/* Find highest min desired voltage */
for
(
i
=
0
;
i
<
n_coupled
;
i
++
)
{
int
tmp_min
=
0
;
int
tmp_max
=
INT_MAX
;
lockdep_assert_held_once
(
&
c_rdevs
[
i
]
->
mutex
.
base
);
ret
=
regulator_check_consumers
(
c_rdevs
[
i
],
&
tmp_min
,
&
tmp_max
,
state
);
if
(
ret
<
0
)
return
ret
;
ret
=
regulator_check_voltage
(
c_rdevs
[
i
],
&
tmp_min
,
&
tmp_max
);
if
(
ret
<
0
)
return
ret
;
highest_min_uV
=
max
(
highest_min_uV
,
tmp_min
);
if
(
i
==
0
)
{
desired_min_uV
=
tmp_min
;
desired_max_uV
=
tmp_max
;
}
}
/*
* Let target_uV be equal to the desired one if possible.
* If not, set it to minimum voltage, allowed by other coupled
* regulators.
*/
target_uV
=
max
(
desired_min_uV
,
highest_min_uV
-
max_spread
);
/*
* Find min and max voltages, which currently aren't violating
* max_spread.
*/
for
(
i
=
1
;
i
<
n_coupled
;
i
++
)
{
int
tmp_act
;
if
(
!
_regulator_is_enabled
(
c_rdevs
[
i
]))
continue
;
tmp_act
=
_regulator_get_voltage
(
c_rdevs
[
i
]);
if
(
tmp_act
<
0
)
return
tmp_act
;
min_current_uV
=
min
(
tmp_act
,
min_current_uV
);
max_current_uV
=
max
(
tmp_act
,
max_current_uV
);
}
/* There aren't any other regulators enabled */
if
(
max_current_uV
==
0
)
{
possible_uV
=
target_uV
;
}
else
{
/*
* Correct target voltage, so as it currently isn't
* violating max_spread
*/
possible_uV
=
max
(
target_uV
,
max_current_uV
-
max_spread
);
possible_uV
=
min
(
possible_uV
,
min_current_uV
+
max_spread
);
}
if
(
possible_uV
>
desired_max_uV
)
return
-
EINVAL
;
done
=
(
possible_uV
==
target_uV
);
desired_min_uV
=
possible_uV
;
finish:
/* Apply max_uV_step constraint if necessary */
if
(
state
==
PM_SUSPEND_ON
)
{
ret
=
regulator_limit_voltage_step
(
rdev
,
current_uV
,
&
desired_min_uV
);
if
(
ret
<
0
)
return
ret
;
if
(
ret
==
0
)
done
=
false
;
}
/* Set current_uV if wasn't done earlier in the code and if necessary */
if
(
n_coupled
>
1
&&
*
current_uV
==
-
1
)
{
if
(
_regulator_is_enabled
(
rdev
))
{
ret
=
_regulator_get_voltage
(
rdev
);
if
(
ret
<
0
)
return
ret
;
*
current_uV
=
ret
;
}
else
{
*
current_uV
=
desired_min_uV
;
}
}
*
min_uV
=
desired_min_uV
;
*
max_uV
=
desired_max_uV
;
return
done
;
}
static
int
regulator_balance_voltage
(
struct
regulator_dev
*
rdev
,
suspend_state_t
state
)
{
struct
regulator_dev
**
c_rdevs
;
struct
regulator_dev
*
best_rdev
;
struct
coupling_desc
*
c_desc
=
&
rdev
->
coupling_desc
;
int
i
,
ret
,
n_coupled
,
best_min_uV
,
best_max_uV
,
best_c_rdev
;
bool
best_c_rdev_done
,
c_rdev_done
[
MAX_COUPLED
];
unsigned
int
delta
,
best_delta
;
c_rdevs
=
c_desc
->
coupled_rdevs
;
n_coupled
=
c_desc
->
n_coupled
;
/*
* If system is in a state other than PM_SUSPEND_ON, don't check
* other coupled regulators.
*/
if
(
state
!=
PM_SUSPEND_ON
)
n_coupled
=
1
;
if
(
c_desc
->
n_resolved
<
n_coupled
)
{
rdev_err
(
rdev
,
"Not all coupled regulators registered
\n
"
);
return
-
EPERM
;
}
for
(
i
=
0
;
i
<
n_coupled
;
i
++
)
c_rdev_done
[
i
]
=
false
;
/*
* Find the best possible voltage change on each loop. Leave the loop
* if there isn't any possible change.
*/
do
{
best_c_rdev_done
=
false
;
best_delta
=
0
;
best_min_uV
=
0
;
best_max_uV
=
0
;
best_c_rdev
=
0
;
best_rdev
=
NULL
;
/*
* Find highest difference between optimal voltage
* and current voltage.
*/
for
(
i
=
0
;
i
<
n_coupled
;
i
++
)
{
/*
* optimal_uV is the best voltage that can be set for
* i-th regulator at the moment without violating
* max_spread constraint in order to balance
* the coupled voltages.
*/
int
optimal_uV
=
0
,
optimal_max_uV
=
0
,
current_uV
=
0
;
if
(
c_rdev_done
[
i
])
continue
;
ret
=
regulator_get_optimal_voltage
(
c_rdevs
[
i
],
&
current_uV
,
&
optimal_uV
,
&
optimal_max_uV
,
state
,
n_coupled
);
if
(
ret
<
0
)
goto
out
;
delta
=
abs
(
optimal_uV
-
current_uV
);
if
(
delta
&&
best_delta
<=
delta
)
{
best_c_rdev_done
=
ret
;
best_delta
=
delta
;
best_rdev
=
c_rdevs
[
i
];
best_min_uV
=
optimal_uV
;
best_max_uV
=
optimal_max_uV
;
best_c_rdev
=
i
;
}
}
/* Nothing to change, return successfully */
if
(
!
best_rdev
)
{
ret
=
0
;
goto
out
;
}
ret
=
regulator_set_voltage_rdev
(
best_rdev
,
best_min_uV
,
best_max_uV
,
state
);
if
(
ret
<
0
)
goto
out
;
c_rdev_done
[
best_c_rdev
]
=
best_c_rdev_done
;
}
while
(
n_coupled
>
1
);
out:
return
ret
;
}
...
...
@@ -3146,14 +3736,15 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
*/
int
regulator_set_voltage
(
struct
regulator
*
regulator
,
int
min_uV
,
int
max_uV
)
{
int
ret
=
0
;
struct
ww_acquire_ctx
ww_ctx
;
int
ret
;
regulator_lock_
supply
(
regulator
->
rdev
);
regulator_lock_
dependent
(
regulator
->
rdev
,
&
ww_ctx
);
ret
=
regulator_set_voltage_unlocked
(
regulator
,
min_uV
,
max_uV
,
PM_SUSPEND_ON
);
regulator_unlock_
supply
(
regulator
->
rdev
);
regulator_unlock_
dependent
(
regulator
->
rdev
,
&
ww_ctx
);
return
ret
;
}
...
...
@@ -3225,18 +3816,19 @@ static int _regulator_set_suspend_voltage(struct regulator *regulator,
int
regulator_set_suspend_voltage
(
struct
regulator
*
regulator
,
int
min_uV
,
int
max_uV
,
suspend_state_t
state
)
{
int
ret
=
0
;
struct
ww_acquire_ctx
ww_ctx
;
int
ret
;
/* PM_SUSPEND_ON is handled by regulator_set_voltage() */
if
(
regulator_check_states
(
state
)
||
state
==
PM_SUSPEND_ON
)
return
-
EINVAL
;
regulator_lock_
supply
(
regulator
->
rdev
);
regulator_lock_
dependent
(
regulator
->
rdev
,
&
ww_ctx
);
ret
=
_regulator_set_suspend_voltage
(
regulator
,
min_uV
,
max_uV
,
state
);
regulator_unlock_
supply
(
regulator
->
rdev
);
regulator_unlock_
dependent
(
regulator
->
rdev
,
&
ww_ctx
);
return
ret
;
}
...
...
@@ -3426,13 +4018,12 @@ static int _regulator_get_voltage(struct regulator_dev *rdev)
*/
int
regulator_get_voltage
(
struct
regulator
*
regulator
)
{
struct
ww_acquire_ctx
ww_ctx
;
int
ret
;
regulator_lock_supply
(
regulator
->
rdev
);
regulator_lock_dependent
(
regulator
->
rdev
,
&
ww_ctx
);
ret
=
_regulator_get_voltage
(
regulator
->
rdev
);
regulator_unlock_supply
(
regulator
->
rdev
);
regulator_unlock_dependent
(
regulator
->
rdev
,
&
ww_ctx
);
return
ret
;
}
...
...
@@ -3650,16 +4241,30 @@ EXPORT_SYMBOL_GPL(regulator_get_error_flags);
* DRMS will sum the total requested load on the regulator and change
* to the most efficient operating mode if platform constraints allow.
*
* NOTE: when a regulator consumer requests to have a regulator
* disabled then any load that consumer requested no longer counts
* toward the total requested load. If the regulator is re-enabled
* then the previously requested load will start counting again.
*
* If a regulator is an always-on regulator then an individual consumer's
* load will still be removed if that consumer is fully disabled.
*
* On error a negative errno is returned.
*/
int
regulator_set_load
(
struct
regulator
*
regulator
,
int
uA_load
)
{
struct
regulator_dev
*
rdev
=
regulator
->
rdev
;
int
ret
;
int
old_uA_load
;
int
ret
=
0
;
regulator_lock
(
rdev
);
old_uA_load
=
regulator
->
uA_load
;
regulator
->
uA_load
=
uA_load
;
ret
=
drms_uA_update
(
rdev
);
if
(
regulator
->
enable_count
&&
old_uA_load
!=
uA_load
)
{
ret
=
drms_uA_update
(
rdev
);
if
(
ret
<
0
)
regulator
->
uA_load
=
old_uA_load
;
}
regulator_unlock
(
rdev
);
return
ret
;
...
...
@@ -3830,11 +4435,8 @@ int regulator_bulk_enable(int num_consumers,
int
ret
=
0
;
for
(
i
=
0
;
i
<
num_consumers
;
i
++
)
{
if
(
consumers
[
i
].
consumer
->
always_on
)
consumers
[
i
].
ret
=
0
;
else
async_schedule_domain
(
regulator_bulk_enable_async
,
&
consumers
[
i
],
&
async_domain
);
async_schedule_domain
(
regulator_bulk_enable_async
,
&
consumers
[
i
],
&
async_domain
);
}
async_synchronize_full_domain
(
&
async_domain
);
...
...
@@ -3968,7 +4570,7 @@ EXPORT_SYMBOL_GPL(regulator_bulk_free);
int
regulator_notifier_call_chain
(
struct
regulator_dev
*
rdev
,
unsigned
long
event
,
void
*
data
)
{
lockdep_assert_held_once
(
&
rdev
->
mutex
);
lockdep_assert_held_once
(
&
rdev
->
mutex
.
base
);
_notifier_call_chain
(
rdev
,
event
,
data
);
return
NOTIFY_DONE
;
...
...
@@ -4070,10 +4672,6 @@ static umode_t regulator_attr_is_visible(struct kobject *kobj,
if
(
attr
==
&
dev_attr_bypass
.
attr
)
return
ops
->
get_bypass
?
mode
:
0
;
/* some attributes are type-specific */
if
(
attr
==
&
dev_attr_requested_microamps
.
attr
)
return
rdev
->
desc
->
type
==
REGULATOR_CURRENT
?
mode
:
0
;
/* constraints need specific supporting methods */
if
(
attr
==
&
dev_attr_min_microvolts
.
attr
||
attr
==
&
dev_attr_max_microvolts
.
attr
)
...
...
@@ -4157,7 +4755,7 @@ static int regulator_register_resolve_supply(struct device *dev, void *data)
return
0
;
}
static
int
regulator_fill_coupling_array
(
struct
regulator_dev
*
rdev
)
static
void
regulator_resolve_coupling
(
struct
regulator_dev
*
rdev
)
{
struct
coupling_desc
*
c_desc
=
&
rdev
->
coupling_desc
;
int
n_coupled
=
c_desc
->
n_coupled
;
...
...
@@ -4171,33 +4769,58 @@ static int regulator_fill_coupling_array(struct regulator_dev *rdev)
c_rdev
=
of_parse_coupled_regulator
(
rdev
,
i
-
1
);
if
(
c_rdev
)
{
c_desc
->
coupled_rdevs
[
i
]
=
c_rdev
;
c_desc
->
n_resolved
++
;
}
}
if
(
!
c_rdev
)
continue
;
if
(
rdev
->
coupling_desc
.
n_resolved
<
n_coupled
)
return
-
1
;
else
return
0
;
regulator_lock
(
c_rdev
);
c_desc
->
coupled_rdevs
[
i
]
=
c_rdev
;
c_desc
->
n_resolved
++
;
regulator_unlock
(
c_rdev
);
regulator_resolve_coupling
(
c_rdev
);
}
}
static
int
regulator_register_fill_coupling_array
(
struct
device
*
dev
,
void
*
data
)
static
void
regulator_remove_coupling
(
struct
regulator_dev
*
rdev
)
{
struct
regulator_dev
*
rdev
=
dev_to_rdev
(
dev
);
struct
coupling_desc
*
__c_desc
,
*
c_desc
=
&
rdev
->
coupling_desc
;
struct
regulator_dev
*
__c_rdev
,
*
c_rdev
;
unsigned
int
__n_coupled
,
n_coupled
;
int
i
,
k
;
if
(
!
IS_ENABLED
(
CONFIG_OF
))
return
0
;
n_coupled
=
c_desc
->
n_coupled
;
if
(
regulator_fill_coupling_array
(
rdev
))
rdev_dbg
(
rdev
,
"unable to resolve coupling
\n
"
)
;
for
(
i
=
1
;
i
<
n_coupled
;
i
++
)
{
c_rdev
=
c_desc
->
coupled_rdevs
[
i
]
;
return
0
;
if
(
!
c_rdev
)
continue
;
regulator_lock
(
c_rdev
);
__c_desc
=
&
c_rdev
->
coupling_desc
;
__n_coupled
=
__c_desc
->
n_coupled
;
for
(
k
=
1
;
k
<
__n_coupled
;
k
++
)
{
__c_rdev
=
__c_desc
->
coupled_rdevs
[
k
];
if
(
__c_rdev
==
rdev
)
{
__c_desc
->
coupled_rdevs
[
k
]
=
NULL
;
__c_desc
->
n_resolved
--
;
break
;
}
}
regulator_unlock
(
c_rdev
);
c_desc
->
coupled_rdevs
[
i
]
=
NULL
;
c_desc
->
n_resolved
--
;
}
}
static
int
regulator_
resolve
_coupling
(
struct
regulator_dev
*
rdev
)
static
int
regulator_
init
_coupling
(
struct
regulator_dev
*
rdev
)
{
int
n_phandles
;
...
...
@@ -4237,13 +4860,6 @@ static int regulator_resolve_coupling(struct regulator_dev *rdev)
if
(
!
of_check_coupling_data
(
rdev
))
return
-
EPERM
;
/*
* After everything has been checked, try to fill rdevs array
* with pointers to regulators parsed from device tree. If some
* regulators are not registered yet, retry in late init call
*/
regulator_fill_coupling_array
(
rdev
);
return
0
;
}
...
...
@@ -4265,21 +4881,33 @@ regulator_register(const struct regulator_desc *regulator_desc,
struct
regulator_config
*
config
=
NULL
;
static
atomic_t
regulator_no
=
ATOMIC_INIT
(
-
1
);
struct
regulator_dev
*
rdev
;
bool
dangling_cfg_gpiod
=
false
;
bool
dangling_of_gpiod
=
false
;
struct
device
*
dev
;
int
ret
,
i
;
if
(
regulator_desc
==
NULL
||
cfg
==
NULL
)
if
(
cfg
==
NULL
)
return
ERR_PTR
(
-
EINVAL
);
if
(
cfg
->
ena_gpiod
)
dangling_cfg_gpiod
=
true
;
if
(
regulator_desc
==
NULL
)
{
ret
=
-
EINVAL
;
goto
rinse
;
}
dev
=
cfg
->
dev
;
WARN_ON
(
!
dev
);
if
(
regulator_desc
->
name
==
NULL
||
regulator_desc
->
ops
==
NULL
)
return
ERR_PTR
(
-
EINVAL
);
if
(
regulator_desc
->
name
==
NULL
||
regulator_desc
->
ops
==
NULL
)
{
ret
=
-
EINVAL
;
goto
rinse
;
}
if
(
regulator_desc
->
type
!=
REGULATOR_VOLTAGE
&&
regulator_desc
->
type
!=
REGULATOR_CURRENT
)
return
ERR_PTR
(
-
EINVAL
);
regulator_desc
->
type
!=
REGULATOR_CURRENT
)
{
ret
=
-
EINVAL
;
goto
rinse
;
}
/* Only one of each should be implemented */
WARN_ON
(
regulator_desc
->
ops
->
get_voltage
&&
...
...
@@ -4290,16 +4918,20 @@ regulator_register(const struct regulator_desc *regulator_desc,
/* If we're using selectors we must implement list_voltage. */
if
(
regulator_desc
->
ops
->
get_voltage_sel
&&
!
regulator_desc
->
ops
->
list_voltage
)
{
return
ERR_PTR
(
-
EINVAL
);
ret
=
-
EINVAL
;
goto
rinse
;
}
if
(
regulator_desc
->
ops
->
set_voltage_sel
&&
!
regulator_desc
->
ops
->
list_voltage
)
{
return
ERR_PTR
(
-
EINVAL
);
ret
=
-
EINVAL
;
goto
rinse
;
}
rdev
=
kzalloc
(
sizeof
(
struct
regulator_dev
),
GFP_KERNEL
);
if
(
rdev
==
NULL
)
return
ERR_PTR
(
-
ENOMEM
);
if
(
rdev
==
NULL
)
{
ret
=
-
ENOMEM
;
goto
rinse
;
}
/*
* Duplicate the config so the driver could override it after
...
...
@@ -4308,17 +4940,28 @@ regulator_register(const struct regulator_desc *regulator_desc,
config
=
kmemdup
(
cfg
,
sizeof
(
*
cfg
),
GFP_KERNEL
);
if
(
config
==
NULL
)
{
kfree
(
rdev
);
return
ERR_PTR
(
-
ENOMEM
);
ret
=
-
ENOMEM
;
goto
rinse
;
}
init_data
=
regulator_of_get_init_data
(
dev
,
regulator_desc
,
config
,
&
rdev
->
dev
.
of_node
);
/*
* We need to keep track of any GPIO descriptor coming from the
* device tree until we have handled it over to the core. If the
* config that was passed in to this function DOES NOT contain
* a descriptor, and the config after this call DOES contain
* a descriptor, we definately got one from parsing the device
* tree.
*/
if
(
!
cfg
->
ena_gpiod
&&
config
->
ena_gpiod
)
dangling_of_gpiod
=
true
;
if
(
!
init_data
)
{
init_data
=
config
->
init_data
;
rdev
->
dev
.
of_node
=
of_node_get
(
config
->
of_node
);
}
mutex_init
(
&
rdev
->
mutex
);
ww_mutex_init
(
&
rdev
->
mutex
,
&
regulator_ww_class
);
rdev
->
reg_data
=
config
->
driver_data
;
rdev
->
owner
=
regulator_desc
->
owner
;
rdev
->
desc
=
regulator_desc
;
...
...
@@ -4351,6 +4994,9 @@ regulator_register(const struct regulator_desc *regulator_desc,
config
->
ena_gpio
,
ret
);
goto
clean
;
}
/* The regulator core took over the GPIO descriptor */
dangling_cfg_gpiod
=
false
;
dangling_of_gpiod
=
false
;
}
/* register with sysfs */
...
...
@@ -4380,11 +5026,8 @@ regulator_register(const struct regulator_desc *regulator_desc,
if
(
ret
<
0
)
goto
wash
;
mutex_lock
(
&
regulator_list_mutex
);
ret
=
regulator_resolve_coupling
(
rdev
);
mutex_unlock
(
&
regulator_list_mutex
);
if
(
ret
!=
0
)
ret
=
regulator_init_coupling
(
rdev
);
if
(
ret
<
0
)
goto
wash
;
/* add consumers devices */
...
...
@@ -4418,6 +5061,11 @@ regulator_register(const struct regulator_desc *regulator_desc,
rdev_init_debugfs
(
rdev
);
/* try to resolve regulators coupling since a new one was registered */
mutex_lock
(
&
regulator_list_mutex
);
regulator_resolve_coupling
(
rdev
);
mutex_unlock
(
&
regulator_list_mutex
);
/* try to resolve regulators supply since a new one was registered */
class_for_each_device
(
&
regulator_class
,
NULL
,
NULL
,
regulator_register_resolve_supply
);
...
...
@@ -4434,8 +5082,13 @@ regulator_register(const struct regulator_desc *regulator_desc,
regulator_ena_gpio_free
(
rdev
);
mutex_unlock
(
&
regulator_list_mutex
);
clean:
if
(
dangling_of_gpiod
)
gpiod_put
(
config
->
ena_gpiod
);
kfree
(
rdev
);
kfree
(
config
);
rinse:
if
(
dangling_cfg_gpiod
)
gpiod_put
(
cfg
->
ena_gpiod
);
return
ERR_PTR
(
ret
);
}
EXPORT_SYMBOL_GPL
(
regulator_register
);
...
...
@@ -4456,15 +5109,19 @@ void regulator_unregister(struct regulator_dev *rdev)
regulator_disable
(
rdev
->
supply
);
regulator_put
(
rdev
->
supply
);
}
mutex_lock
(
&
regulator_list_mutex
);
debugfs_remove_recursive
(
rdev
->
debugfs
);
flush_work
(
&
rdev
->
disable_work
.
work
);
WARN_ON
(
rdev
->
open_count
);
regulator_remove_coupling
(
rdev
);
unset_regulator_supplies
(
rdev
);
list_del
(
&
rdev
->
list
);
regulator_ena_gpio_free
(
rdev
);
mutex_unlock
(
&
regulator_list_mutex
);
device_unregister
(
&
rdev
->
dev
);
mutex_unlock
(
&
regulator_list_mutex
);
}
EXPORT_SYMBOL_GPL
(
regulator_unregister
);
...
...
@@ -4621,23 +5278,8 @@ static int supply_map_show(struct seq_file *sf, void *data)
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
supply_map
);
static
int
supply_map_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
supply_map_show
,
inode
->
i_private
);
}
#endif
static
const
struct
file_operations
supply_map_fops
=
{
#ifdef CONFIG_DEBUG_FS
.
open
=
supply_map_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
#endif
};
#ifdef CONFIG_DEBUG_FS
struct
summary_data
{
struct
seq_file
*
s
;
struct
regulator_dev
*
parent
;
...
...
@@ -4672,8 +5314,6 @@ static void regulator_summary_show_subtree(struct seq_file *s,
if
(
!
rdev
)
return
;
regulator_lock_nested
(
rdev
,
level
);
opmode
=
_regulator_get_mode_unlocked
(
rdev
);
seq_printf
(
s
,
"%*s%-*s %3d %4d %6d %7s "
,
level
*
3
+
1
,
""
,
...
...
@@ -4712,8 +5352,11 @@ static void regulator_summary_show_subtree(struct seq_file *s,
switch
(
rdev
->
desc
->
type
)
{
case
REGULATOR_VOLTAGE
:
seq_printf
(
s
,
"%37dmA %5dmV %5dmV"
,
seq_printf
(
s
,
"%3d %33dmA%c%5dmV %5dmV"
,
consumer
->
enable_count
,
consumer
->
uA_load
/
1000
,
consumer
->
uA_load
&&
!
consumer
->
enable_count
?
'*'
:
' '
,
consumer
->
voltage
[
PM_SUSPEND_ON
].
min_uV
/
1000
,
consumer
->
voltage
[
PM_SUSPEND_ON
].
max_uV
/
1000
);
break
;
...
...
@@ -4730,8 +5373,105 @@ static void regulator_summary_show_subtree(struct seq_file *s,
class_for_each_device
(
&
regulator_class
,
NULL
,
&
summary_data
,
regulator_summary_show_children
);
}
struct
summary_lock_data
{
struct
ww_acquire_ctx
*
ww_ctx
;
struct
regulator_dev
**
new_contended_rdev
;
struct
regulator_dev
**
old_contended_rdev
;
};
static
int
regulator_summary_lock_one
(
struct
device
*
dev
,
void
*
data
)
{
struct
regulator_dev
*
rdev
=
dev_to_rdev
(
dev
);
struct
summary_lock_data
*
lock_data
=
data
;
int
ret
=
0
;
if
(
rdev
!=
*
lock_data
->
old_contended_rdev
)
{
ret
=
regulator_lock_nested
(
rdev
,
lock_data
->
ww_ctx
);
if
(
ret
==
-
EDEADLK
)
*
lock_data
->
new_contended_rdev
=
rdev
;
else
WARN_ON_ONCE
(
ret
);
}
else
{
*
lock_data
->
old_contended_rdev
=
NULL
;
}
return
ret
;
}
static
int
regulator_summary_unlock_one
(
struct
device
*
dev
,
void
*
data
)
{
struct
regulator_dev
*
rdev
=
dev_to_rdev
(
dev
);
struct
summary_lock_data
*
lock_data
=
data
;
if
(
lock_data
)
{
if
(
rdev
==
*
lock_data
->
new_contended_rdev
)
return
-
EDEADLK
;
}
regulator_unlock
(
rdev
);
return
0
;
}
static
int
regulator_summary_lock_all
(
struct
ww_acquire_ctx
*
ww_ctx
,
struct
regulator_dev
**
new_contended_rdev
,
struct
regulator_dev
**
old_contended_rdev
)
{
struct
summary_lock_data
lock_data
;
int
ret
;
lock_data
.
ww_ctx
=
ww_ctx
;
lock_data
.
new_contended_rdev
=
new_contended_rdev
;
lock_data
.
old_contended_rdev
=
old_contended_rdev
;
ret
=
class_for_each_device
(
&
regulator_class
,
NULL
,
&
lock_data
,
regulator_summary_lock_one
);
if
(
ret
)
class_for_each_device
(
&
regulator_class
,
NULL
,
&
lock_data
,
regulator_summary_unlock_one
);
return
ret
;
}
static
void
regulator_summary_lock
(
struct
ww_acquire_ctx
*
ww_ctx
)
{
struct
regulator_dev
*
new_contended_rdev
=
NULL
;
struct
regulator_dev
*
old_contended_rdev
=
NULL
;
int
err
;
mutex_lock
(
&
regulator_list_mutex
);
ww_acquire_init
(
ww_ctx
,
&
regulator_ww_class
);
do
{
if
(
new_contended_rdev
)
{
ww_mutex_lock_slow
(
&
new_contended_rdev
->
mutex
,
ww_ctx
);
old_contended_rdev
=
new_contended_rdev
;
old_contended_rdev
->
ref_cnt
++
;
}
err
=
regulator_summary_lock_all
(
ww_ctx
,
&
new_contended_rdev
,
&
old_contended_rdev
);
if
(
old_contended_rdev
)
regulator_unlock
(
old_contended_rdev
);
}
while
(
err
==
-
EDEADLK
);
ww_acquire_done
(
ww_ctx
);
}
static
void
regulator_summary_unlock
(
struct
ww_acquire_ctx
*
ww_ctx
)
{
class_for_each_device
(
&
regulator_class
,
NULL
,
NULL
,
regulator_summary_unlock_one
);
ww_acquire_fini
(
ww_ctx
);
mutex_unlock
(
&
regulator_list_mutex
);
}
static
int
regulator_summary_show_roots
(
struct
device
*
dev
,
void
*
data
)
...
...
@@ -4747,29 +5487,22 @@ static int regulator_summary_show_roots(struct device *dev, void *data)
static
int
regulator_summary_show
(
struct
seq_file
*
s
,
void
*
data
)
{
struct
ww_acquire_ctx
ww_ctx
;
seq_puts
(
s
,
" regulator use open bypass opmode voltage current min max
\n
"
);
seq_puts
(
s
,
"---------------------------------------------------------------------------------------
\n
"
);
regulator_summary_lock
(
&
ww_ctx
);
class_for_each_device
(
&
regulator_class
,
NULL
,
s
,
regulator_summary_show_roots
);
return
0
;
}
regulator_summary_unlock
(
&
ww_ctx
);
static
int
regulator_summary_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
regulator_summary_show
,
inode
->
i_private
);
return
0
;
}
#endif
static
const
struct
file_operations
regulator_summary_fops
=
{
#ifdef CONFIG_DEBUG_FS
.
open
=
regulator_summary_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
#endif
};
DEFINE_SHOW_ATTRIBUTE
(
regulator_summary
);
#endif
/* CONFIG_DEBUG_FS */
static
int
__init
regulator_init
(
void
)
{
...
...
@@ -4781,12 +5514,13 @@ static int __init regulator_init(void)
if
(
!
debugfs_root
)
pr_warn
(
"regulator: Failed to create debugfs directory
\n
"
);
#ifdef CONFIG_DEBUG_FS
debugfs_create_file
(
"supply_map"
,
0444
,
debugfs_root
,
NULL
,
&
supply_map_fops
);
debugfs_create_file
(
"regulator_summary"
,
0444
,
debugfs_root
,
NULL
,
&
regulator_summary_fops
);
#endif
regulator_dummy_init
();
return
ret
;
...
...
@@ -4873,9 +5607,6 @@ static int __init regulator_init_complete(void)
class_for_each_device
(
&
regulator_class
,
NULL
,
NULL
,
regulator_late_cleanup
);
class_for_each_device
(
&
regulator_class
,
NULL
,
NULL
,
regulator_register_fill_coupling_array
);
return
0
;
}
late_initcall_sync
(
regulator_init_complete
);
drivers/regulator/da9052-regulator.c
View file @
b27d9668
...
...
@@ -435,7 +435,7 @@ static int da9052_regulator_probe(struct platform_device *pdev)
return
-
ENODEV
;
for_each_child_of_node
(
nproot
,
np
)
{
if
(
!
of_node_cmp
(
np
->
name
,
if
(
of_node_name_eq
(
np
,
regulator
->
info
->
reg_desc
.
name
))
{
config
.
init_data
=
of_get_regulator_init_data
(
&
pdev
->
dev
,
np
,
...
...
drivers/regulator/da9210-regulator.c
View file @
b27d9668
...
...
@@ -131,7 +131,7 @@ static irqreturn_t da9210_irq_handler(int irq, void *data)
if
(
error
<
0
)
goto
error_i2c
;
mutex_lock
(
&
chip
->
rdev
->
mutex
);
regulator_lock
(
chip
->
rdev
);
if
(
val
&
DA9210_E_OVCURR
)
{
regulator_notifier_call_chain
(
chip
->
rdev
,
...
...
@@ -157,7 +157,7 @@ static irqreturn_t da9210_irq_handler(int irq, void *data)
handled
|=
DA9210_E_VMAX
;
}
mutex_unlock
(
&
chip
->
rdev
->
mutex
);
regulator_unlock
(
chip
->
rdev
);
if
(
handled
)
{
/* Clear handled events */
...
...
drivers/regulator/da9211-regulator.c
View file @
b27d9668
...
...
@@ -389,6 +389,12 @@ static int da9211_regulator_init(struct da9211 *chip)
else
config
.
ena_gpiod
=
NULL
;
/*
* Hand the GPIO descriptor management over to the regulator
* core, remove it from GPIO devres management.
*/
if
(
config
.
ena_gpiod
)
devm_gpiod_unhinge
(
chip
->
dev
,
config
.
ena_gpiod
);
chip
->
rdev
[
i
]
=
devm_regulator_register
(
chip
->
dev
,
&
da9211_regulators
[
i
],
&
config
);
if
(
IS_ERR
(
chip
->
rdev
[
i
]))
{
...
...
drivers/regulator/dbx500-prcmu.c
View file @
b27d9668
...
...
@@ -75,7 +75,7 @@ static struct ux500_regulator_debug {
u8
*
state_after_suspend
;
}
rdebug
;
static
int
ux500_regulator_power_state_cnt_
print
(
struct
seq_file
*
s
,
void
*
p
)
static
int
ux500_regulator_power_state_cnt_
show
(
struct
seq_file
*
s
,
void
*
p
)
{
/* print power state count */
seq_printf
(
s
,
"ux500-regulator power state count: %i
\n
"
,
...
...
@@ -83,23 +83,9 @@ static int ux500_regulator_power_state_cnt_print(struct seq_file *s, void *p)
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ux500_regulator_power_state_cnt
);
static
int
ux500_regulator_power_state_cnt_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
ux500_regulator_power_state_cnt_print
,
inode
->
i_private
);
}
static
const
struct
file_operations
ux500_regulator_power_state_cnt_fops
=
{
.
open
=
ux500_regulator_power_state_cnt_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
.
owner
=
THIS_MODULE
,
};
static
int
ux500_regulator_status_print
(
struct
seq_file
*
s
,
void
*
p
)
static
int
ux500_regulator_status_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
i
;
...
...
@@ -122,20 +108,7 @@ static int ux500_regulator_status_print(struct seq_file *s, void *p)
return
0
;
}
static
int
ux500_regulator_status_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
ux500_regulator_status_print
,
inode
->
i_private
);
}
static
const
struct
file_operations
ux500_regulator_status_fops
=
{
.
open
=
ux500_regulator_status_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
.
owner
=
THIS_MODULE
,
};
DEFINE_SHOW_ATTRIBUTE
(
ux500_regulator_status
);
int
__attribute__
((
weak
))
dbx500_regulator_testcase
(
struct
dbx500_regulator_info
*
regulator_info
,
...
...
drivers/regulator/fixed.c
View file @
b27d9668
...
...
@@ -183,7 +183,11 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
*/
gflags
|=
GPIOD_FLAGS_BIT_NONEXCLUSIVE
;
cfg
.
ena_gpiod
=
devm_gpiod_get_optional
(
&
pdev
->
dev
,
NULL
,
gflags
);
/*
* Do not use devm* here: the regulator core takes over the
* lifecycle management of the GPIO descriptor.
*/
cfg
.
ena_gpiod
=
gpiod_get_optional
(
&
pdev
->
dev
,
NULL
,
gflags
);
if
(
IS_ERR
(
cfg
.
ena_gpiod
))
return
PTR_ERR
(
cfg
.
ena_gpiod
);
...
...
drivers/regulator/internal.h
View file @
b27d9668
...
...
@@ -42,6 +42,8 @@ struct regulator {
unsigned
int
always_on
:
1
;
unsigned
int
bypass
:
1
;
int
uA_load
;
unsigned
int
enable_count
;
unsigned
int
deferred_disables
;
struct
regulator_voltage
voltage
[
REGULATOR_STATES_NUM
];
const
char
*
supply_name
;
struct
device_attribute
dev_attr
;
...
...
drivers/regulator/lm363x-regulator.c
View file @
b27d9668
...
...
@@ -224,13 +224,15 @@ static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev,
/*
* Check LCM_EN1/2_GPIO is configured.
* Those pins are used for enabling VPOS/VNEG LDOs.
* Do not use devm* here: the regulator core takes over the
* lifecycle management of the GPIO descriptor.
*/
switch
(
id
)
{
case
LM3632_LDO_POS
:
return
devm_
gpiod_get_index_optional
(
dev
,
"enable"
,
0
,
return
gpiod_get_index_optional
(
dev
,
"enable"
,
0
,
GPIOD_OUT_LOW
|
GPIOD_FLAGS_BIT_NONEXCLUSIVE
);
case
LM3632_LDO_NEG
:
return
devm_
gpiod_get_index_optional
(
dev
,
"enable"
,
1
,
return
gpiod_get_index_optional
(
dev
,
"enable"
,
1
,
GPIOD_OUT_LOW
|
GPIOD_FLAGS_BIT_NONEXCLUSIVE
);
default:
return
NULL
;
...
...
@@ -263,6 +265,8 @@ static int lm363x_regulator_probe(struct platform_device *pdev)
LM3632_EXT_EN_MASK
,
LM3632_EXT_EN_MASK
);
if
(
ret
)
{
if
(
gpiod
)
gpiod_put
(
gpiod
);
dev_err
(
dev
,
"External pin err: %d
\n
"
,
ret
);
return
ret
;
}
...
...
drivers/regulator/lochnagar-regulator.c
View file @
b27d9668
...
...
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
...
...
@@ -20,6 +21,8 @@
#include <linux/regulator/of_regulator.h>
#include <linux/mfd/lochnagar.h>
#include <linux/mfd/lochnagar1_regs.h>
#include <linux/mfd/lochnagar2_regs.h>
static
const
struct
regulator_ops
lochnagar_micvdd_ops
=
{
.
enable
=
regulator_enable_regmap
,
...
...
@@ -212,28 +215,52 @@ static const struct regulator_desc lochnagar_regulators[] = {
},
};
static
const
struct
of_device_id
lochnagar_of_match
[]
=
{
{
.
compatible
=
"cirrus,lochnagar2-micvdd"
,
.
data
=
&
lochnagar_regulators
[
LOCHNAGAR_MICVDD
],
},
{
.
compatible
=
"cirrus,lochnagar2-mic1vdd"
,
.
data
=
&
lochnagar_regulators
[
LOCHNAGAR_MIC1VDD
],
},
{
.
compatible
=
"cirrus,lochnagar2-mic2vdd"
,
.
data
=
&
lochnagar_regulators
[
LOCHNAGAR_MIC1VDD
],
},
{
.
compatible
=
"cirrus,lochnagar2-vddcore"
,
.
data
=
&
lochnagar_regulators
[
LOCHNAGAR_VDDCORE
],
},
{},
};
static
int
lochnagar_regulator_probe
(
struct
platform_device
*
pdev
)
{
struct
device
*
dev
=
&
pdev
->
dev
;
struct
lochnagar
*
lochnagar
=
dev_get_drvdata
(
dev
->
parent
);
struct
regulator_config
config
=
{
};
const
struct
of_device_id
*
of_id
;
const
struct
regulator_desc
*
desc
;
struct
regulator_dev
*
rdev
;
int
ret
,
i
;
int
ret
;
config
.
dev
=
lochnagar
->
dev
;
config
.
dev
=
dev
;
config
.
regmap
=
lochnagar
->
regmap
;
config
.
driver_data
=
lochnagar
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
lochnagar_regulators
);
i
++
)
{
const
struct
regulator_desc
*
desc
=
&
lochnagar_regulators
[
i
];
of_id
=
of_match_device
(
lochnagar_of_match
,
dev
);
if
(
!
of_id
)
return
-
EINVAL
;
rdev
=
devm_regulator_register
(
dev
,
desc
,
&
config
);
if
(
IS_ERR
(
rdev
))
{
ret
=
PTR_ERR
(
rdev
);
dev_err
(
dev
,
"Failed to register %s regulator: %d
\n
"
,
desc
->
name
,
ret
);
return
ret
;
}
desc
=
of_id
->
data
;
rdev
=
devm_regulator_register
(
dev
,
desc
,
&
config
);
if
(
IS_ERR
(
rdev
))
{
ret
=
PTR_ERR
(
rdev
);
dev_err
(
dev
,
"Failed to register %s regulator: %d
\n
"
,
desc
->
name
,
ret
);
return
ret
;
}
return
0
;
...
...
@@ -242,6 +269,7 @@ static int lochnagar_regulator_probe(struct platform_device *pdev)
static
struct
platform_driver
lochnagar_regulator_driver
=
{
.
driver
=
{
.
name
=
"lochnagar-regulator"
,
.
of_match_table
=
of_match_ptr
(
lochnagar_of_match
),
},
.
probe
=
lochnagar_regulator_probe
,
...
...
drivers/regulator/lp8788-ldo.c
View file @
b27d9668
...
...
@@ -501,8 +501,12 @@ static int lp8788_config_ldo_enable_mode(struct platform_device *pdev,
return
0
;
}
/* FIXME: check default mode for GPIO here: high or low? */
ldo
->
ena_gpiod
=
devm_gpiod_get_index_optional
(
&
pdev
->
dev
,
/*
* Do not use devm* here: the regulator core takes over the
* lifecycle management of the GPIO descriptor.
* FIXME: check default mode for GPIO here: high or low?
*/
ldo
->
ena_gpiod
=
gpiod_get_index_optional
(
&
pdev
->
dev
,
"enable"
,
enable_id
,
GPIOD_OUT_HIGH
|
...
...
drivers/regulator/max77686-regulator.c
View file @
b27d9668
...
...
@@ -11,8 +11,7 @@
#include <linux/kernel.h>
#include <linux/bug.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
...
...
@@ -76,6 +75,7 @@ enum max77686_ramp_rate {
};
struct
max77686_data
{
struct
device
*
dev
;
DECLARE_BITMAP
(
gpio_enabled
,
MAX77686_REGULATORS
);
/* Array indexed by regulator id */
...
...
@@ -250,26 +250,34 @@ static int max77686_of_parse_cb(struct device_node *np,
struct
regulator_config
*
config
)
{
struct
max77686_data
*
max77686
=
config
->
driver_data
;
int
ret
;
switch
(
desc
->
id
)
{
case
MAX77686_BUCK8
:
case
MAX77686_BUCK9
:
case
MAX77686_LDO20
...
MAX77686_LDO22
:
config
->
ena_gpio
=
of_get_named_gpio
(
np
,
"maxim,ena-gpios"
,
0
);
config
->
ena_gpio_flags
=
GPIOF_OUT_INIT_HIGH
;
config
->
ena_gpio_initialized
=
true
;
config
->
ena_gpiod
=
gpiod_get_from_of_node
(
np
,
"maxim,ena"
,
0
,
GPIOD_OUT_HIGH
|
GPIOD_FLAGS_BIT_NONEXCLUSIVE
,
"max77686-regulator"
);
if
(
IS_ERR
(
config
->
ena_gpiod
))
config
->
ena_gpiod
=
NULL
;
break
;
default:
return
0
;
}
if
(
gpio_is_valid
(
config
->
ena_gpio
)
)
{
if
(
config
->
ena_gpiod
)
{
set_bit
(
desc
->
id
,
max77686
->
gpio_enabled
);
return
regmap_update_bits
(
config
->
regmap
,
desc
->
enable_reg
,
desc
->
enable_mask
,
MAX77686_GPIO_CONTROL
);
ret
=
regmap_update_bits
(
config
->
regmap
,
desc
->
enable_reg
,
desc
->
enable_mask
,
MAX77686_GPIO_CONTROL
);
if
(
ret
)
{
gpiod_put
(
config
->
ena_gpiod
);
config
->
ena_gpiod
=
NULL
;
}
}
return
0
;
...
...
@@ -507,6 +515,7 @@ static int max77686_pmic_probe(struct platform_device *pdev)
if
(
!
max77686
)
return
-
ENOMEM
;
max77686
->
dev
=
&
pdev
->
dev
;
config
.
dev
=
iodev
->
dev
;
config
.
regmap
=
iodev
->
regmap
;
config
.
driver_data
=
max77686
;
...
...
drivers/regulator/max8952.c
View file @
b27d9668
...
...
@@ -231,9 +231,13 @@ static int max8952_pmic_probe(struct i2c_client *client,
else
gflags
=
GPIOD_OUT_LOW
;
gflags
|=
GPIOD_FLAGS_BIT_NONEXCLUSIVE
;
gpiod
=
devm_gpiod_get_optional
(
&
client
->
dev
,
"max8952,en"
,
gflags
);
/*
* Do not use devm* here: the regulator core takes over the
* lifecycle management of the GPIO descriptor.
*/
gpiod
=
gpiod_get_optional
(
&
client
->
dev
,
"max8952,en"
,
gflags
);
if
(
IS_ERR
(
gpiod
))
return
PTR_ERR
(
gpiod
);
if
(
gpiod
)
...
...
drivers/regulator/max8973-regulator.c
View file @
b27d9668
...
...
@@ -808,7 +808,13 @@ static int max8973_probe(struct i2c_client *client,
config
.
of_node
=
client
->
dev
.
of_node
;
config
.
regmap
=
max
->
regmap
;
/* Register the regulators */
/*
* Register the regulators
* Turn the GPIO descriptor over to the regulator core for
* lifecycle management if we pass an ena_gpiod.
*/
if
(
config
.
ena_gpiod
)
devm_gpiod_unhinge
(
&
client
->
dev
,
config
.
ena_gpiod
);
rdev
=
devm_regulator_register
(
&
client
->
dev
,
&
max
->
desc
,
&
config
);
if
(
IS_ERR
(
rdev
))
{
ret
=
PTR_ERR
(
rdev
);
...
...
drivers/regulator/max8997-regulator.c
View file @
b27d9668
...
...
@@ -925,7 +925,7 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
pdata
->
regulators
=
rdata
;
for_each_child_of_node
(
regulators_np
,
reg_np
)
{
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
regulators
);
i
++
)
if
(
!
of_node_cmp
(
reg_np
->
name
,
regulators
[
i
].
name
))
if
(
of_node_name_eq
(
reg_np
,
regulators
[
i
].
name
))
break
;
if
(
i
==
ARRAY_SIZE
(
regulators
))
{
...
...
drivers/regulator/mc13xxx-regulator-core.c
View file @
b27d9668
...
...
@@ -186,7 +186,7 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
for
(
i
=
0
;
i
<
num_regulators
;
i
++
)
{
if
(
!
regulators
[
i
].
desc
.
name
)
continue
;
if
(
!
of_node_cmp
(
child
->
name
,
if
(
of_node_name_eq
(
child
,
regulators
[
i
].
desc
.
name
))
{
p
->
id
=
i
;
p
->
init_data
=
of_get_regulator_init_data
(
...
...
drivers/regulator/mcp16502.c
0 → 100644
View file @
b27d9668
// SPDX-License-Identifier: GPL-2.0
//
// MCP16502 PMIC driver
//
// Copyright (C) 2018 Microchip Technology Inc. and its subsidiaries
//
// Author: Andrei Stefanescu <andrei.stefanescu@microchip.com>
//
// Inspired from tps65086-regulator.c
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/suspend.h>
#define VDD_LOW_SEL 0x0D
#define VDD_HIGH_SEL 0x3F
#define MCP16502_FLT BIT(7)
#define MCP16502_ENS BIT(0)
/*
* The PMIC has four sets of registers corresponding to four power modes:
* Performance, Active, Low-power, Hibernate.
*
* Registers:
* Each regulator has a register for each power mode. To access a register
* for a specific regulator and mode BASE_* and OFFSET_* need to be added.
*
* Operating modes:
* In order for the PMIC to transition to operating modes it has to be
* controlled via GPIO lines called LPM and HPM.
*
* The registers are fully configurable such that you can put all regulators in
* a low-power state while the PMIC is in Active mode. They are supposed to be
* configured at startup and then simply transition to/from a global low-power
* state by setting the GPIO lpm pin high/low.
*
* This driver keeps the PMIC in Active mode, Low-power state is set for the
* regulators by enabling/disabling operating mode (FPWM or Auto PFM).
*
* The PMIC's Low-power and Hibernate modes are used during standby/suspend.
* To enter standby/suspend the PMIC will go to Low-power mode. From there, it
* will transition to Hibernate when the PWRHLD line is set to low by the MPU.
*/
/*
* This function is useful for iterating over all regulators and accessing their
* registers in a generic way or accessing a regulator device by its id.
*/
#define MCP16502_BASE(i) (((i) + 1) << 4)
#define MCP16502_STAT_BASE(i) ((i) + 5)
#define MCP16502_OFFSET_MODE_A 0
#define MCP16502_OFFSET_MODE_LPM 1
#define MCP16502_OFFSET_MODE_HIB 2
#define MCP16502_OPMODE_ACTIVE REGULATOR_MODE_NORMAL
#define MCP16502_OPMODE_LPM REGULATOR_MODE_IDLE
#define MCP16502_OPMODE_HIB REGULATOR_MODE_STANDBY
#define MCP16502_MODE_AUTO_PFM 0
#define MCP16502_MODE_FPWM BIT(6)
#define MCP16502_VSEL 0x3F
#define MCP16502_EN BIT(7)
#define MCP16502_MODE BIT(6)
#define MCP16502_MIN_REG 0x0
#define MCP16502_MAX_REG 0x65
static
unsigned
int
mcp16502_of_map_mode
(
unsigned
int
mode
)
{
if
(
mode
==
REGULATOR_MODE_NORMAL
||
mode
==
REGULATOR_MODE_IDLE
)
return
mode
;
return
REGULATOR_MODE_INVALID
;
}
#define MCP16502_REGULATOR(_name, _id, _ranges, _ops) \
[_id] = { \
.name = _name, \
.regulators_node = of_match_ptr("regulators"), \
.id = _id, \
.ops = &(_ops), \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.n_voltages = MCP16502_VSEL + 1, \
.linear_ranges = _ranges, \
.n_linear_ranges = ARRAY_SIZE(_ranges), \
.of_match = of_match_ptr(_name), \
.of_map_mode = mcp16502_of_map_mode, \
.vsel_reg = (((_id) + 1) << 4), \
.vsel_mask = MCP16502_VSEL, \
.enable_reg = (((_id) + 1) << 4), \
.enable_mask = MCP16502_EN, \
}
enum
{
BUCK1
=
0
,
BUCK2
,
BUCK3
,
BUCK4
,
LDO1
,
LDO2
,
NUM_REGULATORS
};
/*
* struct mcp16502 - PMIC representation
* @rdev: the regulators belonging to this chip
* @rmap: regmap to be used for I2C communication
* @lpm: LPM GPIO descriptor
*/
struct
mcp16502
{
struct
regulator_dev
*
rdev
[
NUM_REGULATORS
];
struct
regmap
*
rmap
;
struct
gpio_desc
*
lpm
;
};
/*
* mcp16502_gpio_set_mode() - set the GPIO corresponding value
*
* Used to prepare transitioning into hibernate or resuming from it.
*/
static
void
mcp16502_gpio_set_mode
(
struct
mcp16502
*
mcp
,
int
mode
)
{
switch
(
mode
)
{
case
MCP16502_OPMODE_ACTIVE
:
gpiod_set_value
(
mcp
->
lpm
,
0
);
break
;
case
MCP16502_OPMODE_LPM
:
case
MCP16502_OPMODE_HIB
:
gpiod_set_value
(
mcp
->
lpm
,
1
);
break
;
default:
pr_err
(
"%s: %d invalid
\n
"
,
__func__
,
mode
);
}
}
/*
* mcp16502_get_reg() - get the PMIC's configuration register for opmode
*
* @rdev: the regulator whose register we are searching
* @opmode: the PMIC's operating mode ACTIVE, Low-power, Hibernate
*/
static
int
mcp16502_get_reg
(
struct
regulator_dev
*
rdev
,
int
opmode
)
{
int
reg
=
MCP16502_BASE
(
rdev_get_id
(
rdev
));
switch
(
opmode
)
{
case
MCP16502_OPMODE_ACTIVE
:
return
reg
+
MCP16502_OFFSET_MODE_A
;
case
MCP16502_OPMODE_LPM
:
return
reg
+
MCP16502_OFFSET_MODE_LPM
;
case
MCP16502_OPMODE_HIB
:
return
reg
+
MCP16502_OFFSET_MODE_HIB
;
default:
return
-
EINVAL
;
}
}
/*
* mcp16502_get_mode() - return the current operating mode of a regulator
*
* Note: all functions that are not part of entering/exiting standby/suspend
* use the Active mode registers.
*
* Note: this is different from the PMIC's operatig mode, it is the
* MODE bit from the regulator's register.
*/
static
unsigned
int
mcp16502_get_mode
(
struct
regulator_dev
*
rdev
)
{
unsigned
int
val
;
int
ret
,
reg
;
struct
mcp16502
*
mcp
=
rdev_get_drvdata
(
rdev
);
reg
=
mcp16502_get_reg
(
rdev
,
MCP16502_OPMODE_ACTIVE
);
if
(
reg
<
0
)
return
reg
;
ret
=
regmap_read
(
mcp
->
rmap
,
reg
,
&
val
);
if
(
ret
)
return
ret
;
switch
(
val
&
MCP16502_MODE
)
{
case
MCP16502_MODE_FPWM
:
return
REGULATOR_MODE_NORMAL
;
case
MCP16502_MODE_AUTO_PFM
:
return
REGULATOR_MODE_IDLE
;
default:
return
REGULATOR_MODE_INVALID
;
}
}
/*
* _mcp16502_set_mode() - helper for set_mode and set_suspend_mode
*
* @rdev: the regulator for which we are setting the mode
* @mode: the regulator's mode (the one from MODE bit)
* @opmode: the PMIC's operating mode: Active/Low-power/Hibernate
*/
static
int
_mcp16502_set_mode
(
struct
regulator_dev
*
rdev
,
unsigned
int
mode
,
unsigned
int
op_mode
)
{
int
val
;
int
reg
;
struct
mcp16502
*
mcp
=
rdev_get_drvdata
(
rdev
);
reg
=
mcp16502_get_reg
(
rdev
,
op_mode
);
if
(
reg
<
0
)
return
reg
;
switch
(
mode
)
{
case
REGULATOR_MODE_NORMAL
:
val
=
MCP16502_MODE_FPWM
;
break
;
case
REGULATOR_MODE_IDLE
:
val
=
MCP16502_MODE_AUTO_PFM
;
break
;
default:
return
-
EINVAL
;
}
reg
=
regmap_update_bits
(
mcp
->
rmap
,
reg
,
MCP16502_MODE
,
val
);
return
reg
;
}
/*
* mcp16502_set_mode() - regulator_ops set_mode
*/
static
int
mcp16502_set_mode
(
struct
regulator_dev
*
rdev
,
unsigned
int
mode
)
{
return
_mcp16502_set_mode
(
rdev
,
mode
,
MCP16502_OPMODE_ACTIVE
);
}
/*
* mcp16502_get_status() - regulator_ops get_status
*/
static
int
mcp16502_get_status
(
struct
regulator_dev
*
rdev
)
{
int
ret
;
unsigned
int
val
;
struct
mcp16502
*
mcp
=
rdev_get_drvdata
(
rdev
);
ret
=
regmap_read
(
mcp
->
rmap
,
MCP16502_STAT_BASE
(
rdev_get_id
(
rdev
)),
&
val
);
if
(
ret
)
return
ret
;
if
(
val
&
MCP16502_FLT
)
return
REGULATOR_STATUS_ERROR
;
else
if
(
val
&
MCP16502_ENS
)
return
REGULATOR_STATUS_ON
;
else
if
(
!
(
val
&
MCP16502_ENS
))
return
REGULATOR_STATUS_OFF
;
return
REGULATOR_STATUS_UNDEFINED
;
}
#ifdef CONFIG_SUSPEND
/*
* mcp16502_suspend_get_target_reg() - get the reg of the target suspend PMIC
* mode
*/
static
int
mcp16502_suspend_get_target_reg
(
struct
regulator_dev
*
rdev
)
{
switch
(
pm_suspend_target_state
)
{
case
PM_SUSPEND_STANDBY
:
return
mcp16502_get_reg
(
rdev
,
MCP16502_OPMODE_LPM
);
case
PM_SUSPEND_ON
:
case
PM_SUSPEND_MEM
:
return
mcp16502_get_reg
(
rdev
,
MCP16502_OPMODE_HIB
);
default:
dev_err
(
&
rdev
->
dev
,
"invalid suspend target: %d
\n
"
,
pm_suspend_target_state
);
}
return
-
EINVAL
;
}
/*
* mcp16502_set_suspend_voltage() - regulator_ops set_suspend_voltage
*/
static
int
mcp16502_set_suspend_voltage
(
struct
regulator_dev
*
rdev
,
int
uV
)
{
struct
mcp16502
*
mcp
=
rdev_get_drvdata
(
rdev
);
int
sel
=
regulator_map_voltage_linear_range
(
rdev
,
uV
,
uV
);
int
reg
=
mcp16502_suspend_get_target_reg
(
rdev
);
if
(
sel
<
0
)
return
sel
;
if
(
reg
<
0
)
return
reg
;
return
regmap_update_bits
(
mcp
->
rmap
,
reg
,
MCP16502_VSEL
,
sel
);
}
/*
* mcp16502_set_suspend_mode() - regulator_ops set_suspend_mode
*/
static
int
mcp16502_set_suspend_mode
(
struct
regulator_dev
*
rdev
,
unsigned
int
mode
)
{
switch
(
pm_suspend_target_state
)
{
case
PM_SUSPEND_STANDBY
:
return
_mcp16502_set_mode
(
rdev
,
mode
,
MCP16502_OPMODE_LPM
);
case
PM_SUSPEND_ON
:
case
PM_SUSPEND_MEM
:
return
_mcp16502_set_mode
(
rdev
,
mode
,
MCP16502_OPMODE_HIB
);
default:
dev_err
(
&
rdev
->
dev
,
"invalid suspend target: %d
\n
"
,
pm_suspend_target_state
);
}
return
-
EINVAL
;
}
/*
* mcp16502_set_suspend_enable() - regulator_ops set_suspend_enable
*/
static
int
mcp16502_set_suspend_enable
(
struct
regulator_dev
*
rdev
)
{
struct
mcp16502
*
mcp
=
rdev_get_drvdata
(
rdev
);
int
reg
=
mcp16502_suspend_get_target_reg
(
rdev
);
if
(
reg
<
0
)
return
reg
;
return
regmap_update_bits
(
mcp
->
rmap
,
reg
,
MCP16502_EN
,
MCP16502_EN
);
}
/*
* mcp16502_set_suspend_disable() - regulator_ops set_suspend_disable
*/
static
int
mcp16502_set_suspend_disable
(
struct
regulator_dev
*
rdev
)
{
struct
mcp16502
*
mcp
=
rdev_get_drvdata
(
rdev
);
int
reg
=
mcp16502_suspend_get_target_reg
(
rdev
);
if
(
reg
<
0
)
return
reg
;
return
regmap_update_bits
(
mcp
->
rmap
,
reg
,
MCP16502_EN
,
0
);
}
#endif
/* CONFIG_SUSPEND */
static
const
struct
regulator_ops
mcp16502_buck_ops
=
{
.
list_voltage
=
regulator_list_voltage_linear_range
,
.
map_voltage
=
regulator_map_voltage_linear_range
,
.
get_voltage_sel
=
regulator_get_voltage_sel_regmap
,
.
set_voltage_sel
=
regulator_set_voltage_sel_regmap
,
.
enable
=
regulator_enable_regmap
,
.
disable
=
regulator_disable_regmap
,
.
is_enabled
=
regulator_is_enabled_regmap
,
.
get_status
=
mcp16502_get_status
,
.
set_mode
=
mcp16502_set_mode
,
.
get_mode
=
mcp16502_get_mode
,
#ifdef CONFIG_SUSPEND
.
set_suspend_voltage
=
mcp16502_set_suspend_voltage
,
.
set_suspend_mode
=
mcp16502_set_suspend_mode
,
.
set_suspend_enable
=
mcp16502_set_suspend_enable
,
.
set_suspend_disable
=
mcp16502_set_suspend_disable
,
#endif
/* CONFIG_SUSPEND */
};
/*
* LDOs cannot change operating modes.
*/
static
const
struct
regulator_ops
mcp16502_ldo_ops
=
{
.
list_voltage
=
regulator_list_voltage_linear_range
,
.
map_voltage
=
regulator_map_voltage_linear_range
,
.
get_voltage_sel
=
regulator_get_voltage_sel_regmap
,
.
set_voltage_sel
=
regulator_set_voltage_sel_regmap
,
.
enable
=
regulator_enable_regmap
,
.
disable
=
regulator_disable_regmap
,
.
is_enabled
=
regulator_is_enabled_regmap
,
.
get_status
=
mcp16502_get_status
,
#ifdef CONFIG_SUSPEND
.
set_suspend_voltage
=
mcp16502_set_suspend_voltage
,
.
set_suspend_enable
=
mcp16502_set_suspend_enable
,
.
set_suspend_disable
=
mcp16502_set_suspend_disable
,
#endif
/* CONFIG_SUSPEND */
};
static
const
struct
of_device_id
mcp16502_ids
[]
=
{
{
.
compatible
=
"microchip,mcp16502"
,
},
{}
};
MODULE_DEVICE_TABLE
(
of
,
mcp16502_ids
);
static
const
struct
regulator_linear_range
b1l12_ranges
[]
=
{
REGULATOR_LINEAR_RANGE
(
1200000
,
VDD_LOW_SEL
,
VDD_HIGH_SEL
,
50000
),
};
static
const
struct
regulator_linear_range
b234_ranges
[]
=
{
REGULATOR_LINEAR_RANGE
(
600000
,
VDD_LOW_SEL
,
VDD_HIGH_SEL
,
25000
),
};
static
const
struct
regulator_desc
mcp16502_desc
[]
=
{
/* MCP16502_REGULATOR(_name, _id, ranges, regulator_ops) */
MCP16502_REGULATOR
(
"VDD_IO"
,
BUCK1
,
b1l12_ranges
,
mcp16502_buck_ops
),
MCP16502_REGULATOR
(
"VDD_DDR"
,
BUCK2
,
b234_ranges
,
mcp16502_buck_ops
),
MCP16502_REGULATOR
(
"VDD_CORE"
,
BUCK3
,
b234_ranges
,
mcp16502_buck_ops
),
MCP16502_REGULATOR
(
"VDD_OTHER"
,
BUCK4
,
b234_ranges
,
mcp16502_buck_ops
),
MCP16502_REGULATOR
(
"LDO1"
,
LDO1
,
b1l12_ranges
,
mcp16502_ldo_ops
),
MCP16502_REGULATOR
(
"LDO2"
,
LDO2
,
b1l12_ranges
,
mcp16502_ldo_ops
)
};
static
const
struct
regmap_range
mcp16502_ranges
[]
=
{
regmap_reg_range
(
MCP16502_MIN_REG
,
MCP16502_MAX_REG
)
};
static
const
struct
regmap_access_table
mcp16502_yes_reg_table
=
{
.
yes_ranges
=
mcp16502_ranges
,
.
n_yes_ranges
=
ARRAY_SIZE
(
mcp16502_ranges
),
};
static
const
struct
regmap_config
mcp16502_regmap_config
=
{
.
reg_bits
=
8
,
.
val_bits
=
8
,
.
max_register
=
MCP16502_MAX_REG
,
.
cache_type
=
REGCACHE_NONE
,
.
rd_table
=
&
mcp16502_yes_reg_table
,
.
wr_table
=
&
mcp16502_yes_reg_table
,
};
/*
* set_up_regulators() - initialize all regulators
*/
static
int
setup_regulators
(
struct
mcp16502
*
mcp
,
struct
device
*
dev
,
struct
regulator_config
config
)
{
int
i
;
for
(
i
=
0
;
i
<
NUM_REGULATORS
;
i
++
)
{
mcp
->
rdev
[
i
]
=
devm_regulator_register
(
dev
,
&
mcp16502_desc
[
i
],
&
config
);
if
(
IS_ERR
(
mcp
->
rdev
[
i
]))
{
dev_err
(
dev
,
"failed to register %s regulator %ld
\n
"
,
mcp16502_desc
[
i
].
name
,
PTR_ERR
(
mcp
->
rdev
[
i
]));
return
PTR_ERR
(
mcp
->
rdev
[
i
]);
}
}
return
0
;
}
static
int
mcp16502_probe
(
struct
i2c_client
*
client
,
const
struct
i2c_device_id
*
id
)
{
struct
regulator_config
config
=
{
};
struct
device
*
dev
;
struct
mcp16502
*
mcp
;
int
ret
=
0
;
dev
=
&
client
->
dev
;
config
.
dev
=
dev
;
mcp
=
devm_kzalloc
(
dev
,
sizeof
(
*
mcp
),
GFP_KERNEL
);
if
(
!
mcp
)
return
-
ENOMEM
;
mcp
->
rmap
=
devm_regmap_init_i2c
(
client
,
&
mcp16502_regmap_config
);
if
(
IS_ERR
(
mcp
->
rmap
))
{
ret
=
PTR_ERR
(
mcp
->
rmap
);
dev_err
(
dev
,
"regmap init failed: %d
\n
"
,
ret
);
return
ret
;
}
i2c_set_clientdata
(
client
,
mcp
);
config
.
regmap
=
mcp
->
rmap
;
config
.
driver_data
=
mcp
;
mcp
->
lpm
=
devm_gpiod_get
(
dev
,
"lpm"
,
GPIOD_OUT_LOW
);
if
(
IS_ERR
(
mcp
->
lpm
))
{
dev_err
(
dev
,
"failed to get lpm pin: %ld
\n
"
,
PTR_ERR
(
mcp
->
lpm
));
return
PTR_ERR
(
mcp
->
lpm
);
}
ret
=
setup_regulators
(
mcp
,
dev
,
config
);
if
(
ret
!=
0
)
return
ret
;
mcp16502_gpio_set_mode
(
mcp
,
MCP16502_OPMODE_ACTIVE
);
return
0
;
}
#ifdef CONFIG_PM_SLEEP
static
int
mcp16502_suspend_noirq
(
struct
device
*
dev
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
mcp16502
*
mcp
=
i2c_get_clientdata
(
client
);
mcp16502_gpio_set_mode
(
mcp
,
MCP16502_OPMODE_LPM
);
return
0
;
}
static
int
mcp16502_resume_noirq
(
struct
device
*
dev
)
{
struct
i2c_client
*
client
=
to_i2c_client
(
dev
);
struct
mcp16502
*
mcp
=
i2c_get_clientdata
(
client
);
mcp16502_gpio_set_mode
(
mcp
,
MCP16502_OPMODE_ACTIVE
);
return
0
;
}
#endif
#ifdef CONFIG_PM
static
const
struct
dev_pm_ops
mcp16502_pm_ops
=
{
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS
(
mcp16502_suspend_noirq
,
mcp16502_resume_noirq
)
};
#endif
static
const
struct
i2c_device_id
mcp16502_i2c_id
[]
=
{
{
"mcp16502"
,
0
},
{
}
};
MODULE_DEVICE_TABLE
(
i2c
,
mcp16502_i2c_id
);
static
struct
i2c_driver
mcp16502_drv
=
{
.
probe
=
mcp16502_probe
,
.
driver
=
{
.
name
=
"mcp16502-regulator"
,
.
of_match_table
=
of_match_ptr
(
mcp16502_ids
),
#ifdef CONFIG_PM
.
pm
=
&
mcp16502_pm_ops
,
#endif
},
.
id_table
=
mcp16502_i2c_id
,
};
module_i2c_driver
(
mcp16502_drv
);
MODULE_VERSION
(
"1.0"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_DESCRIPTION
(
"MCP16502 PMIC driver"
);
MODULE_AUTHOR
(
"Andrei Stefanescu andrei.stefanescu@microchip.com"
);
drivers/regulator/of_regulator.c
View file @
b27d9668
...
...
@@ -20,6 +20,7 @@
#include "internal.h"
static
const
char
*
const
regulator_states
[
PM_SUSPEND_MAX
+
1
]
=
{
[
PM_SUSPEND_STANDBY
]
=
"regulator-state-standby"
,
[
PM_SUSPEND_MEM
]
=
"regulator-state-mem"
,
[
PM_SUSPEND_MAX
]
=
"regulator-state-disk"
,
};
...
...
@@ -170,6 +171,10 @@ static void of_get_regulation_constraints(struct device_node *np,
&
pval
))
constraints
->
max_spread
=
pval
;
if
(
!
of_property_read_u32
(
np
,
"regulator-max-step-microvolt"
,
&
pval
))
constraints
->
max_uV_step
=
pval
;
constraints
->
over_current_protection
=
of_property_read_bool
(
np
,
"regulator-over-current-protection"
);
...
...
@@ -181,9 +186,11 @@ static void of_get_regulation_constraints(struct device_node *np,
case
PM_SUSPEND_MAX
:
suspend_state
=
&
constraints
->
state_disk
;
break
;
case
PM_SUSPEND_STANDBY
:
suspend_state
=
&
constraints
->
state_standby
;
break
;
case
PM_SUSPEND_ON
:
case
PM_SUSPEND_TO_IDLE
:
case
PM_SUSPEND_STANDBY
:
default:
continue
;
}
...
...
@@ -364,24 +371,25 @@ int of_regulator_match(struct device *dev, struct device_node *node,
}
EXPORT_SYMBOL_GPL
(
of_regulator_match
);
struct
regulator_init_data
*
regulator_of_get_init_data
(
struct
device
*
dev
,
const
struct
regulator_desc
*
desc
,
struct
regulator_config
*
config
,
struct
device_node
**
node
)
struct
device_node
*
regulator_of_get_init_node
(
struct
device
*
dev
,
const
struct
regulator_desc
*
desc
)
{
struct
device_node
*
search
,
*
child
;
struct
regulator_init_data
*
init_data
=
NULL
;
const
char
*
name
;
if
(
!
dev
->
of_node
||
!
desc
->
of_match
)
return
NULL
;
if
(
desc
->
regulators_node
)
if
(
desc
->
regulators_node
)
{
search
=
of_get_child_by_name
(
dev
->
of_node
,
desc
->
regulators_node
);
else
}
else
{
search
=
of_node_get
(
dev
->
of_node
);
if
(
!
strcmp
(
desc
->
of_match
,
search
->
name
))
return
search
;
}
if
(
!
search
)
{
dev_dbg
(
dev
,
"Failed to find regulator container node '%s'
\n
"
,
desc
->
regulators_node
);
...
...
@@ -393,35 +401,48 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
if
(
!
name
)
name
=
child
->
name
;
if
(
strcmp
(
desc
->
of_match
,
name
))
continue
;
if
(
!
strcmp
(
desc
->
of_match
,
name
))
return
of_node_get
(
child
);
}
init_data
=
of_get_regulator_init_data
(
dev
,
child
,
desc
);
if
(
!
init_data
)
{
dev_err
(
dev
,
"failed to parse DT for regulator %pOFn
\n
"
,
child
);
break
;
}
of_node_put
(
search
);
if
(
desc
->
of_parse_cb
)
{
if
(
desc
->
of_parse_cb
(
child
,
desc
,
config
))
{
dev_err
(
dev
,
"driver callback failed to parse DT for regulator %pOFn
\n
"
,
child
);
init_data
=
NULL
;
break
;
}
}
return
NULL
;
}
struct
regulator_init_data
*
regulator_of_get_init_data
(
struct
device
*
dev
,
const
struct
regulator_desc
*
desc
,
struct
regulator_config
*
config
,
struct
device_node
**
node
)
{
struct
device_node
*
child
;
struct
regulator_init_data
*
init_data
=
NULL
;
of_node_get
(
child
);
*
node
=
child
;
break
;
child
=
regulator_of_get_init_node
(
dev
,
desc
);
if
(
!
child
)
return
NULL
;
init_data
=
of_get_regulator_init_data
(
dev
,
child
,
desc
);
if
(
!
init_data
)
{
dev_err
(
dev
,
"failed to parse DT for regulator %pOFn
\n
"
,
child
);
goto
error
;
}
of_node_put
(
search
);
if
(
desc
->
of_parse_cb
&&
desc
->
of_parse_cb
(
child
,
desc
,
config
))
{
dev_err
(
dev
,
"driver callback failed to parse DT for regulator %pOFn
\n
"
,
child
);
goto
error
;
}
*
node
=
child
;
return
init_data
;
error:
of_node_put
(
child
);
return
NULL
;
}
static
int
of_node_match
(
struct
device
*
dev
,
const
void
*
data
)
...
...
drivers/regulator/palmas-regulator.c
View file @
b27d9668
...
...
@@ -443,13 +443,16 @@ static int palmas_ldo_write(struct palmas *palmas, unsigned int reg,
static
int
palmas_set_mode_smps
(
struct
regulator_dev
*
dev
,
unsigned
int
mode
)
{
int
id
=
rdev_get_id
(
dev
);
int
ret
;
struct
palmas_pmic
*
pmic
=
rdev_get_drvdata
(
dev
);
struct
palmas_pmic_driver_data
*
ddata
=
pmic
->
palmas
->
pmic_ddata
;
struct
palmas_regs_info
*
rinfo
=
&
ddata
->
palmas_regs_info
[
id
];
unsigned
int
reg
;
bool
rail_enable
=
true
;
palmas_smps_read
(
pmic
->
palmas
,
rinfo
->
ctrl_addr
,
&
reg
);
ret
=
palmas_smps_read
(
pmic
->
palmas
,
rinfo
->
ctrl_addr
,
&
reg
);
if
(
ret
)
return
ret
;
reg
&=
~
PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK
;
...
...
drivers/regulator/pfuze100-regulator.c
View file @
b27d9668
...
...
@@ -370,6 +370,7 @@ static struct pfuze_regulator pfuze100_regulators[] = {
PFUZE100_VGEN_REG
(
PFUZE100
,
VGEN4
,
PFUZE100_VGEN4VOL
,
1800000
,
3300000
,
100000
),
PFUZE100_VGEN_REG
(
PFUZE100
,
VGEN5
,
PFUZE100_VGEN5VOL
,
1800000
,
3300000
,
100000
),
PFUZE100_VGEN_REG
(
PFUZE100
,
VGEN6
,
PFUZE100_VGEN6VOL
,
1800000
,
3300000
,
100000
),
PFUZE100_COIN_REG
(
PFUZE100
,
COIN
,
PFUZE100_COINVOL
,
0x7
,
pfuze100_coin
),
};
static
struct
pfuze_regulator
pfuze200_regulators
[]
=
{
...
...
@@ -436,6 +437,7 @@ static struct of_regulator_match pfuze100_matches[] = {
{
.
name
=
"vgen4"
,
},
{
.
name
=
"vgen5"
,
},
{
.
name
=
"vgen6"
,
},
{
.
name
=
"coin"
,
},
};
/* PFUZE200 */
...
...
drivers/regulator/qcom-rpmh-regulator.c
View file @
b27d9668
...
...
@@ -410,7 +410,7 @@ static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev,
vreg
->
dev
=
dev
;
for
(
rpmh_data
=
pmic_rpmh_data
;
rpmh_data
->
name
;
rpmh_data
++
)
if
(
!
strcmp
(
rpmh_data
->
name
,
node
->
name
))
if
(
of_node_name_eq
(
node
,
rpmh_data
->
name
))
break
;
if
(
!
rpmh_data
->
name
)
{
...
...
drivers/regulator/s2mps11.c
View file @
b27d9668
...
...
@@ -5,7 +5,7 @@
#include <linux/bug.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/gpio
/consumer
.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/of.h>
...
...
@@ -14,7 +14,6 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/of_gpio.h>
#include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps13.h>
...
...
@@ -44,7 +43,7 @@ struct s2mps11_info {
* Array (size: number of regulators) with GPIO-s for external
* sleep control.
*/
int
*
ext_control_gpio
;
struct
gpio_desc
**
ext_control_gpiod
;
};
static
int
get_ramp_delay
(
int
ramp_delay
)
...
...
@@ -511,7 +510,7 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev)
case
S2MPS14X
:
if
(
test_bit
(
rdev_get_id
(
rdev
),
s2mps11
->
suspend_state
))
val
=
S2MPS14_ENABLE_SUSPEND
;
else
if
(
gpio_is_valid
(
s2mps11
->
ext_control_gpio
[
rdev_get_id
(
rdev
)])
)
else
if
(
s2mps11
->
ext_control_gpiod
[
rdev_get_id
(
rdev
)]
)
val
=
S2MPS14_ENABLE_EXT_CONTROL
;
else
val
=
rdev
->
desc
->
enable_mask
;
...
...
@@ -805,7 +804,7 @@ static int s2mps14_pmic_enable_ext_control(struct s2mps11_info *s2mps11,
static
void
s2mps14_pmic_dt_parse_ext_control_gpio
(
struct
platform_device
*
pdev
,
struct
of_regulator_match
*
rdata
,
struct
s2mps11_info
*
s2mps11
)
{
int
*
gpio
=
s2mps11
->
ext_control_gpio
;
struct
gpio_desc
**
gpio
=
s2mps11
->
ext_control_gpiod
;
unsigned
int
i
;
unsigned
int
valid_regulators
[
3
]
=
{
S2MPS14_LDO10
,
S2MPS14_LDO11
,
S2MPS14_LDO12
};
...
...
@@ -816,11 +815,20 @@ static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev,
if
(
!
rdata
[
reg
].
init_data
||
!
rdata
[
reg
].
of_node
)
continue
;
gpio
[
reg
]
=
of_get_named_gpio
(
rdata
[
reg
].
of_node
,
"samsung,ext-control-gpios"
,
0
);
if
(
gpio_is_valid
(
gpio
[
reg
]))
dev_dbg
(
&
pdev
->
dev
,
"Using GPIO %d for ext-control over %d/%s
\n
"
,
gpio
[
reg
],
reg
,
rdata
[
reg
].
name
);
gpio
[
reg
]
=
devm_gpiod_get_from_of_node
(
&
pdev
->
dev
,
rdata
[
reg
].
of_node
,
"samsung,ext-control-gpios"
,
0
,
GPIOD_OUT_HIGH
|
GPIOD_FLAGS_BIT_NONEXCLUSIVE
,
"s2mps11-regulator"
);
if
(
IS_ERR
(
gpio
[
reg
]))
{
dev_err
(
&
pdev
->
dev
,
"Failed to get control GPIO for %d/%s
\n
"
,
reg
,
rdata
[
reg
].
name
);
continue
;
}
if
(
gpio
[
reg
])
dev_dbg
(
&
pdev
->
dev
,
"Using GPIO for ext-control over %d/%s
\n
"
,
reg
,
rdata
[
reg
].
name
);
}
}
...
...
@@ -1126,17 +1134,10 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
return
-
EINVAL
;
}
s2mps11
->
ext_control_gpio
=
devm_kmalloc_array
(
&
pdev
->
dev
,
rdev_num
,
sizeof
(
*
s2mps11
->
ext_control_gpio
),
GFP_KERNEL
);
if
(
!
s2mps11
->
ext_control_gpio
)
s2mps11
->
ext_control_gpiod
=
devm_kcalloc
(
&
pdev
->
dev
,
rdev_num
,
sizeof
(
*
s2mps11
->
ext_control_gpiod
),
GFP_KERNEL
);
if
(
!
s2mps11
->
ext_control_gpiod
)
return
-
ENOMEM
;
/*
* 0 is a valid GPIO so initialize all GPIO-s to negative value
* to indicate that external control won't be used for this regulator.
*/
for
(
i
=
0
;
i
<
rdev_num
;
i
++
)
s2mps11
->
ext_control_gpio
[
i
]
=
-
EINVAL
;
if
(
!
iodev
->
dev
->
of_node
)
{
if
(
iodev
->
pdata
)
{
...
...
@@ -1166,8 +1167,6 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
config
.
dev
=
&
pdev
->
dev
;
config
.
regmap
=
iodev
->
regmap_pmic
;
config
.
driver_data
=
s2mps11
;
config
.
ena_gpio_flags
=
GPIOF_OUT_INIT_HIGH
;
config
.
ena_gpio_initialized
=
true
;
for
(
i
=
0
;
i
<
rdev_num
;
i
++
)
{
struct
regulator_dev
*
regulator
;
...
...
@@ -1178,8 +1177,13 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
config
.
init_data
=
rdata
[
i
].
init_data
;
config
.
of_node
=
rdata
[
i
].
of_node
;
}
config
.
ena_gpio
=
s2mps11
->
ext_control_gpio
[
i
];
config
.
ena_gpiod
=
s2mps11
->
ext_control_gpiod
[
i
];
/*
* Hand the GPIO descriptor management over to the regulator
* core, remove it from devres management.
*/
if
(
config
.
ena_gpiod
)
devm_gpiod_unhinge
(
&
pdev
->
dev
,
config
.
ena_gpiod
);
regulator
=
devm_regulator_register
(
&
pdev
->
dev
,
&
regulators
[
i
],
&
config
);
if
(
IS_ERR
(
regulator
))
{
...
...
@@ -1189,7 +1193,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
goto
out
;
}
if
(
gpio_is_valid
(
s2mps11
->
ext_control_gpio
[
i
])
)
{
if
(
s2mps11
->
ext_control_gpiod
[
i
]
)
{
ret
=
s2mps14_pmic_enable_ext_control
(
s2mps11
,
regulator
);
if
(
ret
<
0
)
{
...
...
drivers/regulator/s5m8767.c
View file @
b27d9668
...
...
@@ -561,7 +561,7 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
pdata
->
opmode
=
rmode
;
for_each_child_of_node
(
regulators_np
,
reg_np
)
{
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
regulators
);
i
++
)
if
(
!
of_node_cmp
(
reg_np
->
name
,
regulators
[
i
].
name
))
if
(
of_node_name_eq
(
reg_np
,
regulators
[
i
].
name
))
break
;
if
(
i
==
ARRAY_SIZE
(
regulators
))
{
...
...
@@ -956,10 +956,17 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
config
.
regmap
=
iodev
->
regmap_pmic
;
config
.
of_node
=
pdata
->
regulators
[
i
].
reg_node
;
config
.
ena_gpiod
=
NULL
;
if
(
pdata
->
regulators
[
i
].
ext_control_gpiod
)
if
(
pdata
->
regulators
[
i
].
ext_control_gpiod
)
{
/* Assigns config.ena_gpiod */
s5m8767_regulator_config_ext_control
(
s5m8767
,
&
pdata
->
regulators
[
i
],
&
config
);
/*
* Hand the GPIO descriptor management over to the
* regulator core, remove it from devres management.
*/
devm_gpiod_unhinge
(
s5m8767
->
dev
,
config
.
ena_gpiod
);
}
rdev
=
devm_regulator_register
(
&
pdev
->
dev
,
&
regulators
[
id
],
&
config
);
if
(
IS_ERR
(
rdev
))
{
...
...
drivers/regulator/stpmic1_regulator.c
View file @
b27d9668
...
...
@@ -489,14 +489,14 @@ static irqreturn_t stpmic1_curlim_irq_handler(int irq, void *data)
{
struct
regulator_dev
*
rdev
=
(
struct
regulator_dev
*
)
data
;
mutex_lock
(
&
rdev
->
mutex
);
regulator_lock
(
rdev
);
/* Send an overcurrent notification */
regulator_notifier_call_chain
(
rdev
,
REGULATOR_EVENT_OVER_CURRENT
,
NULL
);
mutex_unlock
(
&
rdev
->
mutex
);
regulator_unlock
(
rdev
);
return
IRQ_HANDLED
;
}
...
...
drivers/regulator/tps65090-regulator.c
View file @
b27d9668
...
...
@@ -480,6 +480,12 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
else
config
.
of_node
=
NULL
;
/*
* Hand the GPIO descriptor management over to the regulator
* core, remove it from devres management.
*/
if
(
config
.
ena_gpiod
)
devm_gpiod_unhinge
(
&
pdev
->
dev
,
config
.
ena_gpiod
);
rdev
=
devm_regulator_register
(
&
pdev
->
dev
,
ri
->
desc
,
&
config
);
if
(
IS_ERR
(
rdev
))
{
dev_err
(
&
pdev
->
dev
,
"failed to register regulator %s
\n
"
,
...
...
drivers/regulator/tps65910-regulator.c
View file @
b27d9668
...
...
@@ -1102,8 +1102,10 @@ static int tps65910_probe(struct platform_device *pdev)
platform_set_drvdata
(
pdev
,
pmic
);
/* Give control of all register to control port */
tps65910_reg_set_bits
(
pmic
->
mfd
,
TPS65910_DEVCTRL
,
err
=
tps65910_reg_set_bits
(
pmic
->
mfd
,
TPS65910_DEVCTRL
,
DEVCTRL_SR_CTL_I2C_SEL_MASK
);
if
(
err
<
0
)
return
err
;
switch
(
tps65910_chip_id
(
tps65910
))
{
case
TPS65910
:
...
...
drivers/regulator/wm8350-regulator.c
View file @
b27d9668
...
...
@@ -1153,7 +1153,7 @@ static irqreturn_t pmic_uv_handler(int irq, void *data)
{
struct
regulator_dev
*
rdev
=
(
struct
regulator_dev
*
)
data
;
mutex_lock
(
&
rdev
->
mutex
);
regulator_lock
(
rdev
);
if
(
irq
==
WM8350_IRQ_CS1
||
irq
==
WM8350_IRQ_CS2
)
regulator_notifier_call_chain
(
rdev
,
REGULATOR_EVENT_REGULATION_OUT
,
...
...
@@ -1162,7 +1162,7 @@ static irqreturn_t pmic_uv_handler(int irq, void *data)
regulator_notifier_call_chain
(
rdev
,
REGULATOR_EVENT_UNDER_VOLTAGE
,
NULL
);
mutex_unlock
(
&
rdev
->
mutex
);
regulator_unlock
(
rdev
);
return
IRQ_HANDLED
;
}
...
...
drivers/regulator/wm8994-regulator.c
View file @
b27d9668
...
...
@@ -19,7 +19,7 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/gpio.h>
#include <linux/gpio
/consumer
.h>
#include <linux/slab.h>
#include <linux/mfd/wm8994/core.h>
...
...
@@ -129,6 +129,7 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
int
id
=
pdev
->
id
%
ARRAY_SIZE
(
pdata
->
ldo
);
struct
regulator_config
config
=
{
};
struct
wm8994_ldo
*
ldo
;
struct
gpio_desc
*
gpiod
;
int
ret
;
dev_dbg
(
&
pdev
->
dev
,
"Probing LDO%d
\n
"
,
id
+
1
);
...
...
@@ -145,12 +146,18 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
config
.
driver_data
=
ldo
;
config
.
regmap
=
wm8994
->
regmap
;
config
.
init_data
=
&
ldo
->
init_data
;
if
(
pdata
)
{
config
.
ena_gpio
=
pdata
->
ldo
[
id
].
enable
;
}
else
if
(
wm8994
->
dev
->
of_node
)
{
config
.
ena_gpio
=
wm8994
->
pdata
.
ldo
[
id
].
enable
;
config
.
ena_gpio_initialized
=
true
;
}
/*
* Look up LDO enable GPIO from the parent device node, we don't
* use devm because the regulator core will free the GPIO
*/
gpiod
=
gpiod_get_optional
(
pdev
->
dev
.
parent
,
id
?
"wlf,ldo2ena"
:
"wlf,ldo1ena"
,
GPIOD_OUT_LOW
|
GPIOD_FLAGS_BIT_NONEXCLUSIVE
);
if
(
IS_ERR
(
gpiod
))
return
PTR_ERR
(
gpiod
);
config
.
ena_gpiod
=
gpiod
;
/* Use default constraints if none set up */
if
(
!
pdata
||
!
pdata
->
ldo
[
id
].
init_data
||
wm8994
->
dev
->
of_node
)
{
...
...
@@ -159,12 +166,17 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
ldo
->
init_data
=
wm8994_ldo_default
[
id
];
ldo
->
init_data
.
consumer_supplies
=
&
ldo
->
supply
;
if
(
!
config
.
ena_gpio
)
if
(
!
gpiod
)
ldo
->
init_data
.
constraints
.
valid_ops_mask
=
0
;
}
else
{
ldo
->
init_data
=
*
pdata
->
ldo
[
id
].
init_data
;
}
/*
* At this point the GPIO descriptor is handled over to the
* regulator core and we need not worry about it on the
* error path.
*/
ldo
->
regulator
=
devm_regulator_register
(
&
pdev
->
dev
,
&
wm8994_ldo_desc
[
id
],
&
config
);
...
...
@@ -172,15 +184,12 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
ret
=
PTR_ERR
(
ldo
->
regulator
);
dev_err
(
wm8994
->
dev
,
"Failed to register LDO%d: %d
\n
"
,
id
+
1
,
ret
);
goto
err
;
return
ret
;
}
platform_set_drvdata
(
pdev
,
ldo
);
return
0
;
err:
return
ret
;
}
static
struct
platform_driver
wm8994_ldo_driver
=
{
...
...
drivers/spi/spi-qcom-qspi.c
View file @
b27d9668
...
...
@@ -90,6 +90,9 @@
#define PIO_DATAOUT_1B 0x0020
#define PIO_DATAOUT_4B 0x0024
#define RD_FIFO_CFG 0x0028
#define CONTINUOUS_MODE BIT(0)
#define RD_FIFO_STATUS 0x002c
#define FIFO_EMPTY BIT(11)
#define WR_CNTS_MSK 0x7f0
...
...
@@ -99,9 +102,6 @@
#define RDY_16BYTE BIT(1)
#define FIFO_RDY BIT(0)
#define RD_FIFO_CFG 0x0028
#define CONTINUOUS_MODE BIT(0)
#define RD_FIFO_RESET 0x0030
#define RESET_FIFO BIT(0)
...
...
@@ -139,7 +139,7 @@ struct qcom_qspi {
struct
device
*
dev
;
struct
clk_bulk_data
clks
[
QSPI_NUM_CLKS
];
struct
qspi_xfer
xfer
;
/* Lock to protect
data accessed by IRQ
s */
/* Lock to protect
xfer and IRQ accessed register
s */
spinlock_t
lock
;
};
...
...
include/dt-bindings/regulator/active-semi,8945a-regulator.h
0 → 100644
View file @
b27d9668
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2018 Microchip Technology, Inc. All rights reserved.
*
* Device Tree binding constants for the ACT8945A PMIC regulators
*/
#ifndef _DT_BINDINGS_REGULATOR_ACT8945A_H
#define _DT_BINDINGS_REGULATOR_ACT8945A_H
/*
* These constants should be used to specify regulator modes in device tree for
* ACT8945A regulators as follows:
* ACT8945A_REGULATOR_MODE_FIXED: It is specific to DCDC regulators and it
* specifies the usage of fixed-frequency
* PWM.
*
* ACT8945A_REGULATOR_MODE_NORMAL: It is specific to LDO regulators and it
* specifies the usage of normal mode.
*
* ACT8945A_REGULATOR_MODE_LOWPOWER: For DCDC and LDO regulators; it specify
* the usage of proprietary power-saving
* mode.
*/
#define ACT8945A_REGULATOR_MODE_FIXED 1
#define ACT8945A_REGULATOR_MODE_NORMAL 2
#define ACT8945A_REGULATOR_MODE_LOWPOWER 3
#endif
include/linux/gpio/consumer.h
View file @
b27d9668
...
...
@@ -104,6 +104,7 @@ struct gpio_descs *__must_check
devm_gpiod_get_array_optional
(
struct
device
*
dev
,
const
char
*
con_id
,
enum
gpiod_flags
flags
);
void
devm_gpiod_put
(
struct
device
*
dev
,
struct
gpio_desc
*
desc
);
void
devm_gpiod_unhinge
(
struct
device
*
dev
,
struct
gpio_desc
*
desc
);
void
devm_gpiod_put_array
(
struct
device
*
dev
,
struct
gpio_descs
*
descs
);
int
gpiod_get_direction
(
struct
gpio_desc
*
desc
);
...
...
@@ -172,6 +173,10 @@ int desc_to_gpio(const struct gpio_desc *desc);
struct
device_node
;
struct
fwnode_handle
;
struct
gpio_desc
*
gpiod_get_from_of_node
(
struct
device_node
*
node
,
const
char
*
propname
,
int
index
,
enum
gpiod_flags
dflags
,
const
char
*
label
);
struct
gpio_desc
*
devm_gpiod_get_from_of_node
(
struct
device
*
dev
,
struct
device_node
*
node
,
const
char
*
propname
,
int
index
,
...
...
@@ -245,6 +250,15 @@ static inline void gpiod_put(struct gpio_desc *desc)
WARN_ON
(
1
);
}
static
inline
void
devm_gpiod_unhinge
(
struct
device
*
dev
,
struct
gpio_desc
*
desc
)
{
might_sleep
();
/* GPIO can never have been requested */
WARN_ON
(
1
);
}
static
inline
void
gpiod_put_array
(
struct
gpio_descs
*
descs
)
{
might_sleep
();
...
...
@@ -517,6 +531,15 @@ static inline int desc_to_gpio(const struct gpio_desc *desc)
struct
device_node
;
struct
fwnode_handle
;
static
inline
struct
gpio_desc
*
gpiod_get_from_of_node
(
struct
device_node
*
node
,
const
char
*
propname
,
int
index
,
enum
gpiod_flags
dflags
,
const
char
*
label
)
{
return
ERR_PTR
(
-
ENOSYS
);
}
static
inline
struct
gpio_desc
*
devm_gpiod_get_from_of_node
(
struct
device
*
dev
,
struct
device_node
*
node
,
...
...
include/linux/mfd/axp20x.h
View file @
b27d9668
...
...
@@ -35,7 +35,7 @@ enum axp20x_variants {
#define AXP152_ALDO_OP_MODE 0x13
#define AXP152_LDO0_CTRL 0x15
#define AXP152_DCDC2_V_OUT 0x23
#define AXP152_DCDC2_V_
SCAL
0x25
#define AXP152_DCDC2_V_
RAMP
0x25
#define AXP152_DCDC1_V_OUT 0x26
#define AXP152_DCDC3_V_OUT 0x27
#define AXP152_ALDO12_V_OUT 0x28
...
...
@@ -53,7 +53,7 @@ enum axp20x_variants {
#define AXP20X_USB_OTG_STATUS 0x02
#define AXP20X_PWR_OUT_CTRL 0x12
#define AXP20X_DCDC2_V_OUT 0x23
#define AXP20X_DCDC2_LDO3_V_
SCAL
0x25
#define AXP20X_DCDC2_LDO3_V_
RAMP
0x25
#define AXP20X_DCDC3_V_OUT 0x27
#define AXP20X_LDO24_V_OUT 0x28
#define AXP20X_LDO3_V_OUT 0x29
...
...
include/linux/mfd/wm8994/pdata.h
View file @
b27d9668
...
...
@@ -20,9 +20,6 @@
#define WM8994_NUM_AIF 3
struct
wm8994_ldo_pdata
{
/** GPIOs to enable regulator, 0 or less if not available */
int
enable
;
const
struct
regulator_init_data
*
init_data
;
};
...
...
include/linux/regulator/driver.h
View file @
b27d9668
...
...
@@ -15,11 +15,12 @@
#ifndef __LINUX_REGULATOR_DRIVER_H_
#define __LINUX_REGULATOR_DRIVER_H_
#define MAX_COUPLED
4
#define MAX_COUPLED
2
#include <linux/device.h>
#include <linux/notifier.h>
#include <linux/regulator/consumer.h>
#include <linux/ww_mutex.h>
struct
gpio_desc
;
struct
regmap
;
...
...
@@ -462,7 +463,7 @@ struct regulator_dev {
struct
coupling_desc
coupling_desc
;
struct
blocking_notifier_head
notifier
;
struct
mutex
mutex
;
/* consumer lock */
struct
ww_
mutex
mutex
;
/* consumer lock */
struct
task_struct
*
mutex_owner
;
int
ref_cnt
;
struct
module
*
owner
;
...
...
@@ -473,7 +474,6 @@ struct regulator_dev {
struct
regmap
*
regmap
;
struct
delayed_work
disable_work
;
int
deferred_disables
;
void
*
reg_data
;
/* regulator_dev data */
...
...
@@ -545,4 +545,7 @@ int regulator_set_active_discharge_regmap(struct regulator_dev *rdev,
bool
enable
);
void
*
regulator_get_init_drvdata
(
struct
regulator_init_data
*
reg_init_data
);
void
regulator_lock
(
struct
regulator_dev
*
rdev
);
void
regulator_unlock
(
struct
regulator_dev
*
rdev
);
#endif
include/linux/regulator/machine.h
View file @
b27d9668
...
...
@@ -158,6 +158,9 @@ struct regulation_constraints {
/* used for coupled regulators */
int
max_spread
;
/* used for changing voltage in steps */
int
max_uV_step
;
/* valid regulator operating modes for this machine */
unsigned
int
valid_modes_mask
;
...
...
include/linux/regulator/pfuze100.h
View file @
b27d9668
...
...
@@ -33,7 +33,8 @@
#define PFUZE100_VGEN4 12
#define PFUZE100_VGEN5 13
#define PFUZE100_VGEN6 14
#define PFUZE100_MAX_REGULATOR 15
#define PFUZE100_COIN 15
#define PFUZE100_MAX_REGULATOR 16
#define PFUZE200_SW1AB 0
#define PFUZE200_SW2 1
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment