mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-11 23:03:55 +08:00
regulator: Update for v4.5
Aside from a fix for a spurious warning (which caused more problems than it fixed in the fixing really) this is all driver updates, including new drivers for Dialog PV88060/90 and TI LM363x and TPS65086 devices. The qcom_smd driver has had PM8916 and PMA8084 support added. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJWlUWiAAoJECTWi3JdVIfQtywH/0joibyUbL34arXcPNCUUhlo UnhTgT1kfOoS01ODt9gU49X4/8SRL9HdjcrIV8yTz4Ldb8by8Rd3ZrkO//9zs7BF 5PIqIzEw6FT/Ovsj8Tc35irccMSrwtTIGRrA8zrM/WtWQWcIUWFxMw+j/lewIvvH jHZNTTLL5XemObSTfvzhbS6PZ8RcvRVXLNJjZYYO5xAEHNg3i5Hxao5p3QKzVJ8m P5n4jSiTY/pVePcs9dzzQTGjlzkE11KX7DBxnmXOSPZsArSaRIC53DCmqu/JoG+o 3JJBkmRx7IJb0651hclFaUl8Wl56FSst+zigeAj82b301xpVR30iG3xiwYK/AT8= =NQ6n -----END PGP SIGNATURE----- Merge tag 'regulator-v4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator Pull regulator updates from Mark Brown: "Aside from a fix for a spurious warning (which caused more problems than it fixed in the fixing really) this is all driver updates, including new drivers for Dialog PV88060/90 and TI LM363x and TPS65086 devices. The qcom_smd driver has had PM8916 and PMA8084 support added" * tag 'regulator-v4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (36 commits) regulator: core: remove some dead code regulator: core: use dev_to_rdev regulator: lp872x: Get rid of duplicate reference to DVS GPIO regulator: lp872x: Add missing of_match in regulators descriptions regulator: axp20x: Fix GPIO LDO enable value for AXP22x regulator: lp8788: constify regulator_ops structures regulator: wm8*: constify regulator_ops structures regulator: da9*: constify regulator_ops structures regulator: mt6311: Use REGCACHE_RBTREE regulator: tps65917/palmas: Add bypass ops for LDOs with bypass capability regulator: qcom-smd: Add support for PMA8084 regulator: qcom-smd: Add PM8916 support soc: qcom: documentation: Update SMD/RPM Docs regulator: pv88090: logical vs bitwise AND typo regulator: pv88090: Fix irq leak regulator: pv88090: new regulator driver regulator: wm831x-ldo: Use platform_register/unregister_drivers() regulator: wm831x-dcdc: Use platform_register/unregister_drivers() regulator: lp8788-ldo: Use platform_register/unregister_drivers() regulator: core: Fix nested locking of supplies ...
This commit is contained in:
commit
4b43ea2a7c
@ -0,0 +1,34 @@
|
||||
TI LMU LM363x regulator device tree bindings
|
||||
|
||||
LM363x regulator driver supports LM3631 and LM3632.
|
||||
LM3631 has five regulators and LM3632 supports three regulators.
|
||||
|
||||
Required property:
|
||||
- compatible: "ti,lm363x-regulator"
|
||||
|
||||
Optional properties:
|
||||
LM3632 has external enable pins for two LDOs.
|
||||
- ti,lcm-en1-gpio: A GPIO specifier for Vpos control pin.
|
||||
- ti,lcm-en2-gpio: A GPIO specifier for Vneg control pin.
|
||||
|
||||
Child nodes:
|
||||
LM3631
|
||||
- vboost
|
||||
- vcont
|
||||
- voref
|
||||
- vpos
|
||||
- vneg
|
||||
|
||||
LM3632
|
||||
- vboost
|
||||
- vpos
|
||||
- vneg
|
||||
|
||||
Optional properties of a child node:
|
||||
Each sub-node should contain the constraints and initialization.
|
||||
Please refer to [1].
|
||||
|
||||
Examples: Please refer to ti-lmu dt-bindings [2].
|
||||
|
||||
[1] ../regulator/regulator.txt
|
||||
[2] ../mfd/ti-lmu.txt
|
124
Documentation/devicetree/bindings/regulator/pv88060.txt
Normal file
124
Documentation/devicetree/bindings/regulator/pv88060.txt
Normal file
@ -0,0 +1,124 @@
|
||||
* Powerventure Semiconductor PV88060 Voltage Regulator
|
||||
|
||||
Required properties:
|
||||
- compatible: "pvs,pv88060".
|
||||
- reg: I2C slave address, usually 0x49.
|
||||
- interrupts: the interrupt outputs of the controller
|
||||
- regulators: A node that houses a sub-node for each regulator within the
|
||||
device. Each sub-node is identified using the node's name, with valid
|
||||
values listed below. The content of each sub-node is defined by the
|
||||
standard binding for regulators; see regulator.txt.
|
||||
BUCK1, LDO1, LDO2, LDO3, LDO4, LDO5, LDO6, LDO7, SW1, SW2, SW3, SW4,
|
||||
SW5, and SW6.
|
||||
|
||||
Optional properties:
|
||||
- Any optional property defined in regulator.txt
|
||||
|
||||
Example
|
||||
|
||||
pmic: pv88060@49 {
|
||||
compatible = "pvs,pv88060";
|
||||
reg = <0x49>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <24 24>;
|
||||
|
||||
regulators {
|
||||
BUCK1 {
|
||||
regulator-name = "buck1";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <4387500>;
|
||||
regulator-min-microamp = <1496000>;
|
||||
regulator-max-microamp = <4189000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
LDO1 {
|
||||
regulator-name = "ldo1";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3350000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
LDO2 {
|
||||
regulator-name = "ldo2";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3350000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
LDO3 {
|
||||
regulator-name = "ldo3";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3350000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
LDO4 {
|
||||
regulator-name = "ldo4";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3350000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
LDO5 {
|
||||
regulator-name = "ldo5";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3350000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
LDO6 {
|
||||
regulator-name = "ldo6";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3350000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
LDO7 {
|
||||
regulator-name = "ldo7";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3350000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
SW1 {
|
||||
regulator-name = "sw1";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
};
|
||||
|
||||
SW2 {
|
||||
regulator-name = "sw2";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
SW3 {
|
||||
regulator-name = "sw3";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
SW4 {
|
||||
regulator-name = "sw4";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
SW5 {
|
||||
regulator-name = "sw5";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
SW6 {
|
||||
regulator-name = "sw6";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
};
|
||||
};
|
||||
};
|
65
Documentation/devicetree/bindings/regulator/pv88090.txt
Normal file
65
Documentation/devicetree/bindings/regulator/pv88090.txt
Normal file
@ -0,0 +1,65 @@
|
||||
* Powerventure Semiconductor PV88090 Voltage Regulator
|
||||
|
||||
Required properties:
|
||||
- compatible: "pvs,pv88090".
|
||||
- reg: I2C slave address, usually 0x48.
|
||||
- interrupts: the interrupt outputs of the controller
|
||||
- regulators: A node that houses a sub-node for each regulator within the
|
||||
device. Each sub-node is identified using the node's name, with valid
|
||||
values listed below. The content of each sub-node is defined by the
|
||||
standard binding for regulators; see regulator.txt.
|
||||
BUCK1, BUCK2, BUCK3, LDO1, and LDO2.
|
||||
|
||||
Optional properties:
|
||||
- Any optional property defined in regulator.txt
|
||||
|
||||
Example
|
||||
|
||||
pmic: pv88090@48 {
|
||||
compatible = "pvs,pv88090";
|
||||
reg = <0x48>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <24 24>;
|
||||
|
||||
regulators {
|
||||
BUCK1 {
|
||||
regulator-name = "buck1";
|
||||
regulator-min-microvolt = < 600000>;
|
||||
regulator-max-microvolt = <1393750>;
|
||||
regulator-min-microamp = < 220000>;
|
||||
regulator-max-microamp = <7040000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
BUCK2 {
|
||||
regulator-name = "buck2";
|
||||
regulator-min-microvolt = < 600000>;
|
||||
regulator-max-microvolt = <1393750>;
|
||||
regulator-min-microamp = <1496000>;
|
||||
regulator-max-microamp = <4189000>;
|
||||
};
|
||||
|
||||
BUCK3 {
|
||||
regulator-name = "buck3";
|
||||
regulator-min-microvolt = <600000>;
|
||||
regulator-max-microvolt = <1393750>;
|
||||
regulator-min-microamp = <1496000>;
|
||||
regulator-max-microamp = <4189000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
LDO1 {
|
||||
regulator-name = "ldo1";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <4350000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
LDO2 {
|
||||
regulator-name = "ldo2";
|
||||
regulator-min-microvolt = < 650000>;
|
||||
regulator-max-microvolt = <2225000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
};
|
||||
};
|
@ -1,27 +1,17 @@
|
||||
Qualcomm Resource Power Manager (RPM) over SMD
|
||||
QCOM SMD RPM REGULATOR
|
||||
|
||||
This driver is used to interface with the Resource Power Manager (RPM) found in
|
||||
various Qualcomm platforms. The RPM allows each component in the system to vote
|
||||
for state of the system resources, such as clocks, regulators and bus
|
||||
frequencies.
|
||||
The Qualcomm RPM over SMD regulator is modelled as a subdevice of the RPM.
|
||||
Because SMD is used as the communication transport mechanism, the RPM resides as
|
||||
a subnode of the SMD. As such, the SMD-RPM regulator requires that the SMD and
|
||||
RPM nodes be present.
|
||||
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: must be one of:
|
||||
"qcom,rpm-msm8974"
|
||||
Please refer to Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt for
|
||||
information pertaining to the SMD node.
|
||||
|
||||
- qcom,smd-channels:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Definition: Shared Memory channel used for communication with the RPM
|
||||
Please refer to Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.txt for
|
||||
information regarding the RPM node.
|
||||
|
||||
= SUBDEVICES
|
||||
|
||||
The RPM exposes resources to its subnodes. The below bindings specify the set
|
||||
of valid subnodes that can operate on these resources.
|
||||
|
||||
== Regulators
|
||||
== Regulator
|
||||
|
||||
Regulator nodes are identified by their compatible:
|
||||
|
||||
@ -30,7 +20,9 @@ Regulator nodes are identified by their compatible:
|
||||
Value type: <string>
|
||||
Definition: must be one of:
|
||||
"qcom,rpm-pm8841-regulators"
|
||||
"qcom,rpm-pm8916-regulators"
|
||||
"qcom,rpm-pm8941-regulators"
|
||||
"qcom,rpm-pma8084-regulators"
|
||||
|
||||
- vdd_s1-supply:
|
||||
- vdd_s2-supply:
|
||||
@ -45,6 +37,19 @@ Regulator nodes are identified by their compatible:
|
||||
Definition: reference to regulator supplying the input pin, as
|
||||
described in the data sheet
|
||||
|
||||
- vdd_s1-supply:
|
||||
- vdd_s2-supply:
|
||||
- vdd_s3-supply:
|
||||
- vdd_s4-supply:
|
||||
- vdd_l1_l2_l3-supply:
|
||||
- vdd_l4_l5_l6-supply:
|
||||
- vdd_l7-supply:
|
||||
- vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18-supply:
|
||||
Usage: optional (pm8916 only)
|
||||
Value type: <phandle>
|
||||
Definition: reference to regulator supplying the input pin, as
|
||||
described in the data sheet
|
||||
|
||||
- vdd_s1-supply:
|
||||
- vdd_s2-supply:
|
||||
- vdd_s3-supply:
|
||||
@ -63,6 +68,35 @@ Regulator nodes are identified by their compatible:
|
||||
Definition: reference to regulator supplying the input pin, as
|
||||
described in the data sheet
|
||||
|
||||
- vdd_s1-supply:
|
||||
- vdd_s2-supply:
|
||||
- vdd_s3-supply:
|
||||
- vdd_s4-supply:
|
||||
- vdd_s5-supply:
|
||||
- vdd_s6-supply:
|
||||
- vdd_s7-supply:
|
||||
- vdd_s8-supply:
|
||||
- vdd_s9-supply:
|
||||
- vdd_s10-supply:
|
||||
- vdd_s11-supply:
|
||||
- vdd_s12-supply:
|
||||
- vdd_l1_l11-supply:
|
||||
- vdd_l2_l3_l4_l27-supply:
|
||||
- vdd_l5_l7-supply:
|
||||
- vdd_l6_l12_l14_l15_l26-supply:
|
||||
- vdd_l8-supply:
|
||||
- vdd_l9_l10_l13_l20_l23_l24-supply:
|
||||
- vdd_l16_l25-supply:
|
||||
- vdd_l17-supply:
|
||||
- vdd_l18-supply:
|
||||
- vdd_l19-supply:
|
||||
- vdd_l21-supply:
|
||||
- vdd_l22-supply:
|
||||
Usage: optional (pma8084 only)
|
||||
Value type: <phandle>
|
||||
Definition: reference to regulator supplying the input pin, as
|
||||
described in the data sheet
|
||||
|
||||
The regulator node houses sub-nodes for each regulator within the device. Each
|
||||
sub-node is identified using the node's name, with valid values listed for each
|
||||
of the pmics below.
|
||||
@ -70,11 +104,20 @@ of the pmics below.
|
||||
pm8841:
|
||||
s1, s2, s3, s4, s5, s6, s7, s8
|
||||
|
||||
pm8916:
|
||||
s1, s2, s3, s4, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13,
|
||||
l14, l15, l16, l17, l18
|
||||
|
||||
pm8941:
|
||||
s1, s2, s3, s4, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13,
|
||||
l14, l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, lvs1, lvs2,
|
||||
lvs3, 5vs1, 5vs2
|
||||
|
||||
pma8084:
|
||||
s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, l1, l2, l3, l4, l5,
|
||||
l6, l7, l8, l9, l10, l11, l12, l13, l14, l15, l16, l17, l18, l19, l20,
|
||||
l21, l22, l23, l24, l25, l26, l27, lvs1, lvs2, lvs3, lvs4, 5vs1
|
||||
|
||||
The content of each sub-node is defined by the standard binding for regulators -
|
||||
see regulator.txt.
|
||||
|
||||
@ -114,4 +157,3 @@ see regulator.txt.
|
||||
};
|
||||
};
|
||||
};
|
||||
|
58
Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.txt
Normal file
58
Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.txt
Normal file
@ -0,0 +1,58 @@
|
||||
Qualcomm Resource Power Manager (RPM) over SMD
|
||||
|
||||
This driver is used to interface with the Resource Power Manager (RPM) found in
|
||||
various Qualcomm platforms. The RPM allows each component in the system to vote
|
||||
for state of the system resources, such as clocks, regulators and bus
|
||||
frequencies.
|
||||
|
||||
The SMD information for the RPM edge should be filled out. See qcom,smd.txt for
|
||||
the required edge properties. All SMD related properties will reside within the
|
||||
RPM node itself.
|
||||
|
||||
= SUBDEVICES
|
||||
|
||||
The RPM exposes resources to its subnodes. The rpm_requests node must be
|
||||
present and this subnode may contain children that designate regulator
|
||||
resources.
|
||||
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: must be one of:
|
||||
"qcom,rpm-apq8084"
|
||||
"qcom,rpm-msm8916"
|
||||
"qcom,rpm-msm8974"
|
||||
|
||||
- qcom,smd-channels:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: must be "rpm_requests"
|
||||
|
||||
Refer to Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.txt
|
||||
for information on the regulator subnodes that can exist under the rpm_requests.
|
||||
|
||||
Example:
|
||||
|
||||
soc {
|
||||
apcs: syscon@f9011000 {
|
||||
compatible = "syscon";
|
||||
reg = <0xf9011000 0x1000>;
|
||||
};
|
||||
};
|
||||
|
||||
smd {
|
||||
compatible = "qcom,smd";
|
||||
|
||||
rpm {
|
||||
interrupts = <0 168 1>;
|
||||
qcom,ipc = <&apcs 8 0>;
|
||||
qcom,smd-edge = <15>;
|
||||
|
||||
rpm_requests {
|
||||
compatible = "qcom,rpm-msm8974";
|
||||
qcom,smd-channels = "rpm_requests";
|
||||
|
||||
...
|
||||
};
|
||||
};
|
||||
};
|
@ -274,6 +274,15 @@ config REGULATOR_ISL6271A
|
||||
help
|
||||
This driver supports ISL6271A voltage regulator chip.
|
||||
|
||||
config REGULATOR_LM363X
|
||||
tristate "TI LM363X voltage regulators"
|
||||
depends on MFD_TI_LMU
|
||||
help
|
||||
This driver supports LM3631 and LM3632 voltage regulators for
|
||||
the LCD bias.
|
||||
One boost output voltage is configurable and always on.
|
||||
Other LDOs are used for the display module.
|
||||
|
||||
config REGULATOR_LP3971
|
||||
tristate "National Semiconductors LP3971 PMIC regulator driver"
|
||||
depends on I2C
|
||||
@ -446,6 +455,7 @@ config REGULATOR_MC13892
|
||||
config REGULATOR_MT6311
|
||||
tristate "MediaTek MT6311 PMIC"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
help
|
||||
Say y here to select this option to enable the power regulator of
|
||||
MediaTek MT6311 PMIC.
|
||||
@ -504,6 +514,22 @@ config REGULATOR_PFUZE100
|
||||
Say y here to support the regulators found on the Freescale
|
||||
PFUZE100/PFUZE200 PMIC.
|
||||
|
||||
config REGULATOR_PV88060
|
||||
tristate "Powerventure Semiconductor PV88060 regulator"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
help
|
||||
Say y here to support the voltage regulators and convertors
|
||||
PV88060
|
||||
|
||||
config REGULATOR_PV88090
|
||||
tristate "Powerventure Semiconductor PV88090 regulator"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
help
|
||||
Say y here to support the voltage regulators and convertors
|
||||
on PV88090
|
||||
|
||||
config REGULATOR_PWM
|
||||
tristate "PWM voltage regulator"
|
||||
depends on PWM
|
||||
@ -680,6 +706,13 @@ config REGULATOR_TPS6507X
|
||||
three step-down converters and two general-purpose LDO voltage regulators.
|
||||
It supports TI's software based Class-2 SmartReflex implementation.
|
||||
|
||||
config REGULATOR_TPS65086
|
||||
tristate "TI TPS65086 Power regulators"
|
||||
depends on MFD_TPS65086
|
||||
help
|
||||
This driver provides support for the voltage regulators on
|
||||
TI TPS65086 PMICs.
|
||||
|
||||
config REGULATOR_TPS65090
|
||||
tristate "TI TPS65090 Power regulator"
|
||||
depends on MFD_TPS65090
|
||||
|
@ -36,6 +36,7 @@ obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o
|
||||
obj-$(CONFIG_REGULATOR_LM363X) += lm363x-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
|
||||
obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o
|
||||
obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o
|
||||
@ -66,6 +67,8 @@ obj-$(CONFIG_REGULATOR_QCOM_SMD_RPM) += qcom_smd-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_QCOM_SPMI) += qcom_spmi-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PV88060) += pv88060-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PV88090) += pv88090-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PWM) += pwm-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PBIAS) += pbias-regulator.o
|
||||
@ -85,6 +88,7 @@ obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS65086) += tps65086-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS65090) += tps65090-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS65217) += tps65217-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS65218) += tps65218-regulator.o
|
||||
|
@ -27,8 +27,8 @@
|
||||
#define AXP20X_IO_ENABLED 0x03
|
||||
#define AXP20X_IO_DISABLED 0x07
|
||||
|
||||
#define AXP22X_IO_ENABLED 0x04
|
||||
#define AXP22X_IO_DISABLED 0x03
|
||||
#define AXP22X_IO_ENABLED 0x03
|
||||
#define AXP22X_IO_DISABLED 0x04
|
||||
|
||||
#define AXP20X_WORKMODE_DCDC2_MASK BIT(2)
|
||||
#define AXP20X_WORKMODE_DCDC3_MASK BIT(1)
|
||||
|
@ -132,24 +132,24 @@ static bool have_full_constraints(void)
|
||||
return has_full_constraints || of_have_populated_dt();
|
||||
}
|
||||
|
||||
static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev)
|
||||
{
|
||||
if (rdev && rdev->supply)
|
||||
return rdev->supply->rdev;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* regulator_lock_supply - lock a regulator and its supplies
|
||||
* @rdev: regulator source
|
||||
*/
|
||||
static void regulator_lock_supply(struct regulator_dev *rdev)
|
||||
{
|
||||
struct regulator *supply;
|
||||
int i = 0;
|
||||
int i;
|
||||
|
||||
while (1) {
|
||||
mutex_lock_nested(&rdev->mutex, i++);
|
||||
supply = rdev->supply;
|
||||
|
||||
if (!rdev->supply)
|
||||
return;
|
||||
|
||||
rdev = supply->rdev;
|
||||
}
|
||||
for (i = 0; rdev; rdev = rdev_get_supply(rdev), i++)
|
||||
mutex_lock_nested(&rdev->mutex, i);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2368,7 +2368,6 @@ static void regulator_disable_work(struct work_struct *work)
|
||||
int regulator_disable_deferred(struct regulator *regulator, int ms)
|
||||
{
|
||||
struct regulator_dev *rdev = regulator->rdev;
|
||||
int ret;
|
||||
|
||||
if (regulator->always_on)
|
||||
return 0;
|
||||
@ -2380,13 +2379,9 @@ int regulator_disable_deferred(struct regulator *regulator, int ms)
|
||||
rdev->deferred_disables++;
|
||||
mutex_unlock(&rdev->mutex);
|
||||
|
||||
ret = queue_delayed_work(system_power_efficient_wq,
|
||||
&rdev->disable_work,
|
||||
msecs_to_jiffies(ms));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else
|
||||
return 0;
|
||||
queue_delayed_work(system_power_efficient_wq, &rdev->disable_work,
|
||||
msecs_to_jiffies(ms));
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_disable_deferred);
|
||||
|
||||
@ -3451,8 +3446,10 @@ int regulator_bulk_get(struct device *dev, int num_consumers,
|
||||
consumers[i].consumer = NULL;
|
||||
|
||||
for (i = 0; i < num_consumers; i++) {
|
||||
consumers[i].consumer = regulator_get(dev,
|
||||
consumers[i].supply);
|
||||
consumers[i].consumer = _regulator_get(dev,
|
||||
consumers[i].supply,
|
||||
false,
|
||||
!consumers[i].optional);
|
||||
if (IS_ERR(consumers[i].consumer)) {
|
||||
ret = PTR_ERR(consumers[i].consumer);
|
||||
dev_err(dev, "Failed to get supply '%s': %d\n",
|
||||
@ -3708,7 +3705,7 @@ static umode_t regulator_attr_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int idx)
|
||||
{
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct regulator_dev *rdev = container_of(dev, struct regulator_dev, dev);
|
||||
struct regulator_dev *rdev = dev_to_rdev(dev);
|
||||
const struct regulator_ops *ops = rdev->desc->ops;
|
||||
umode_t mode = attr->mode;
|
||||
|
||||
|
@ -257,7 +257,7 @@ static const struct regulator_linear_range da9034_ldo12_ranges[] = {
|
||||
REGULATOR_LINEAR_RANGE(2700000, 8, 15, 50000),
|
||||
};
|
||||
|
||||
static struct regulator_ops da903x_regulator_ldo_ops = {
|
||||
static const struct regulator_ops da903x_regulator_ldo_ops = {
|
||||
.set_voltage_sel = da903x_set_voltage_sel,
|
||||
.get_voltage_sel = da903x_get_voltage_sel,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
@ -268,7 +268,7 @@ static struct regulator_ops da903x_regulator_ldo_ops = {
|
||||
};
|
||||
|
||||
/* NOTE: this is dedicated for the insane DA9030 LDO14 */
|
||||
static struct regulator_ops da9030_regulator_ldo14_ops = {
|
||||
static const struct regulator_ops da9030_regulator_ldo14_ops = {
|
||||
.set_voltage_sel = da903x_set_voltage_sel,
|
||||
.get_voltage_sel = da903x_get_voltage_sel,
|
||||
.list_voltage = da9030_list_ldo14_voltage,
|
||||
@ -279,7 +279,7 @@ static struct regulator_ops da9030_regulator_ldo14_ops = {
|
||||
};
|
||||
|
||||
/* NOTE: this is dedicated for the DA9030 LDO1 and LDO15 that have locks */
|
||||
static struct regulator_ops da9030_regulator_ldo1_15_ops = {
|
||||
static const struct regulator_ops da9030_regulator_ldo1_15_ops = {
|
||||
.set_voltage_sel = da9030_set_ldo1_15_voltage_sel,
|
||||
.get_voltage_sel = da903x_get_voltage_sel,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
@ -289,7 +289,7 @@ static struct regulator_ops da9030_regulator_ldo1_15_ops = {
|
||||
.is_enabled = da903x_is_enabled,
|
||||
};
|
||||
|
||||
static struct regulator_ops da9034_regulator_dvc_ops = {
|
||||
static const struct regulator_ops da9034_regulator_dvc_ops = {
|
||||
.set_voltage_sel = da9034_set_dvc_voltage_sel,
|
||||
.get_voltage_sel = da903x_get_voltage_sel,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
@ -300,7 +300,7 @@ static struct regulator_ops da9034_regulator_dvc_ops = {
|
||||
};
|
||||
|
||||
/* NOTE: this is dedicated for the insane LDO12 */
|
||||
static struct regulator_ops da9034_regulator_ldo12_ops = {
|
||||
static const struct regulator_ops da9034_regulator_ldo12_ops = {
|
||||
.set_voltage_sel = da903x_set_voltage_sel,
|
||||
.get_voltage_sel = da903x_get_voltage_sel,
|
||||
.list_voltage = regulator_list_voltage_linear_range,
|
||||
|
@ -265,7 +265,7 @@ static int da9052_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct regulator_ops da9052_dcdc_ops = {
|
||||
static const struct regulator_ops da9052_dcdc_ops = {
|
||||
.get_current_limit = da9052_dcdc_get_current_limit,
|
||||
.set_current_limit = da9052_dcdc_set_current_limit,
|
||||
|
||||
@ -279,7 +279,7 @@ static struct regulator_ops da9052_dcdc_ops = {
|
||||
.disable = regulator_disable_regmap,
|
||||
};
|
||||
|
||||
static struct regulator_ops da9052_ldo_ops = {
|
||||
static const struct regulator_ops da9052_ldo_ops = {
|
||||
.list_voltage = da9052_list_voltage,
|
||||
.map_voltage = da9052_map_voltage,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
|
@ -324,7 +324,7 @@ static int da9055_suspend_disable(struct regulator_dev *rdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct regulator_ops da9055_buck_ops = {
|
||||
static const struct regulator_ops da9055_buck_ops = {
|
||||
.get_mode = da9055_buck_get_mode,
|
||||
.set_mode = da9055_buck_set_mode,
|
||||
|
||||
@ -345,7 +345,7 @@ static struct regulator_ops da9055_buck_ops = {
|
||||
.set_suspend_mode = da9055_buck_set_mode,
|
||||
};
|
||||
|
||||
static struct regulator_ops da9055_ldo_ops = {
|
||||
static const struct regulator_ops da9055_ldo_ops = {
|
||||
.get_mode = da9055_ldo_get_mode,
|
||||
.set_mode = da9055_ldo_set_mode,
|
||||
|
||||
|
@ -371,7 +371,7 @@ static int da9062_ldo_set_suspend_mode(struct regulator_dev *rdev,
|
||||
return regmap_field_write(regl->suspend_sleep, val);
|
||||
}
|
||||
|
||||
static struct regulator_ops da9062_buck_ops = {
|
||||
static const struct regulator_ops da9062_buck_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
@ -389,7 +389,7 @@ static struct regulator_ops da9062_buck_ops = {
|
||||
.set_suspend_mode = da9062_buck_set_suspend_mode,
|
||||
};
|
||||
|
||||
static struct regulator_ops da9062_ldo_ops = {
|
||||
static const struct regulator_ops da9062_ldo_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
|
@ -427,7 +427,7 @@ static int da9063_ldo_set_suspend_mode(struct regulator_dev *rdev, unsigned mode
|
||||
return regmap_field_write(regl->suspend_sleep, val);
|
||||
}
|
||||
|
||||
static struct regulator_ops da9063_buck_ops = {
|
||||
static const struct regulator_ops da9063_buck_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
@ -445,7 +445,7 @@ static struct regulator_ops da9063_buck_ops = {
|
||||
.set_suspend_mode = da9063_buck_set_suspend_mode,
|
||||
};
|
||||
|
||||
static struct regulator_ops da9063_ldo_ops = {
|
||||
static const struct regulator_ops da9063_ldo_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
|
@ -46,7 +46,7 @@ static int da9210_set_current_limit(struct regulator_dev *rdev, int min_uA,
|
||||
int max_uA);
|
||||
static int da9210_get_current_limit(struct regulator_dev *rdev);
|
||||
|
||||
static struct regulator_ops da9210_buck_ops = {
|
||||
static const struct regulator_ops da9210_buck_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
|
@ -219,7 +219,7 @@ static int da9211_get_current_limit(struct regulator_dev *rdev)
|
||||
return current_limits[data];
|
||||
}
|
||||
|
||||
static struct regulator_ops da9211_buck_ops = {
|
||||
static const struct regulator_ops da9211_buck_ops = {
|
||||
.get_mode = da9211_buck_get_mode,
|
||||
.set_mode = da9211_buck_set_mode,
|
||||
.enable = regulator_enable_regmap,
|
||||
|
@ -164,8 +164,11 @@ int devm_regulator_bulk_get(struct device *dev, int num_consumers,
|
||||
consumers[i].consumer = NULL;
|
||||
|
||||
for (i = 0; i < num_consumers; i++) {
|
||||
consumers[i].consumer = devm_regulator_get(dev,
|
||||
consumers[i].supply);
|
||||
consumers[i].consumer = _devm_regulator_get(dev,
|
||||
consumers[i].supply,
|
||||
consumers[i].optional ?
|
||||
OPTIONAL_GET :
|
||||
NORMAL_GET);
|
||||
if (IS_ERR(consumers[i].consumer)) {
|
||||
ret = PTR_ERR(consumers[i].consumer);
|
||||
dev_err(dev, "Failed to get supply '%s': %d\n",
|
||||
|
291
drivers/regulator/lm363x-regulator.c
Normal file
291
drivers/regulator/lm363x-regulator.c
Normal file
@ -0,0 +1,291 @@
|
||||
/*
|
||||
* TI LM363X Regulator Driver
|
||||
*
|
||||
* Copyright 2015 Texas Instruments
|
||||
*
|
||||
* Author: Milo Kim <milo.kim@ti.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.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/ti-lmu.h>
|
||||
#include <linux/mfd/ti-lmu-register.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/* LM3631 */
|
||||
#define LM3631_BOOST_VSEL_MAX 0x25
|
||||
#define LM3631_LDO_VSEL_MAX 0x28
|
||||
#define LM3631_CONT_VSEL_MAX 0x03
|
||||
#define LM3631_VBOOST_MIN 4500000
|
||||
#define LM3631_VCONT_MIN 1800000
|
||||
#define LM3631_VLDO_MIN 4000000
|
||||
#define ENABLE_TIME_USEC 1000
|
||||
|
||||
/* LM3632 */
|
||||
#define LM3632_BOOST_VSEL_MAX 0x26
|
||||
#define LM3632_LDO_VSEL_MAX 0x29
|
||||
#define LM3632_VBOOST_MIN 4500000
|
||||
#define LM3632_VLDO_MIN 4000000
|
||||
|
||||
/* Common */
|
||||
#define LM363X_STEP_50mV 50000
|
||||
#define LM363X_STEP_500mV 500000
|
||||
|
||||
static const int ldo_cont_enable_time[] = {
|
||||
0, 2000, 5000, 10000, 20000, 50000, 100000, 200000,
|
||||
};
|
||||
|
||||
static int lm363x_regulator_enable_time(struct regulator_dev *rdev)
|
||||
{
|
||||
enum lm363x_regulator_id id = rdev_get_id(rdev);
|
||||
u8 val, addr, mask;
|
||||
|
||||
switch (id) {
|
||||
case LM3631_LDO_CONT:
|
||||
addr = LM3631_REG_ENTIME_VCONT;
|
||||
mask = LM3631_ENTIME_CONT_MASK;
|
||||
break;
|
||||
case LM3631_LDO_OREF:
|
||||
addr = LM3631_REG_ENTIME_VOREF;
|
||||
mask = LM3631_ENTIME_MASK;
|
||||
break;
|
||||
case LM3631_LDO_POS:
|
||||
addr = LM3631_REG_ENTIME_VPOS;
|
||||
mask = LM3631_ENTIME_MASK;
|
||||
break;
|
||||
case LM3631_LDO_NEG:
|
||||
addr = LM3631_REG_ENTIME_VNEG;
|
||||
mask = LM3631_ENTIME_MASK;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (regmap_read(rdev->regmap, addr, (unsigned int *)&val))
|
||||
return -EINVAL;
|
||||
|
||||
val = (val & mask) >> LM3631_ENTIME_SHIFT;
|
||||
|
||||
if (id == LM3631_LDO_CONT)
|
||||
return ldo_cont_enable_time[val];
|
||||
else
|
||||
return ENABLE_TIME_USEC * val;
|
||||
}
|
||||
|
||||
static struct regulator_ops lm363x_boost_voltage_table_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
};
|
||||
|
||||
static struct regulator_ops lm363x_regulator_voltage_table_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable_time = lm363x_regulator_enable_time,
|
||||
};
|
||||
|
||||
static const struct regulator_desc lm363x_regulator_desc[] = {
|
||||
/* LM3631 */
|
||||
{
|
||||
.name = "vboost",
|
||||
.of_match = "vboost",
|
||||
.id = LM3631_BOOST,
|
||||
.ops = &lm363x_boost_voltage_table_ops,
|
||||
.n_voltages = LM3631_BOOST_VSEL_MAX + 1,
|
||||
.min_uV = LM3631_VBOOST_MIN,
|
||||
.uV_step = LM363X_STEP_50mV,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LM3631_REG_VOUT_BOOST,
|
||||
.vsel_mask = LM3631_VOUT_MASK,
|
||||
},
|
||||
{
|
||||
.name = "ldo_cont",
|
||||
.of_match = "vcont",
|
||||
.id = LM3631_LDO_CONT,
|
||||
.ops = &lm363x_regulator_voltage_table_ops,
|
||||
.n_voltages = LM3631_CONT_VSEL_MAX + 1,
|
||||
.min_uV = LM3631_VCONT_MIN,
|
||||
.uV_step = LM363X_STEP_500mV,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LM3631_REG_VOUT_CONT,
|
||||
.vsel_mask = LM3631_VOUT_CONT_MASK,
|
||||
.enable_reg = LM3631_REG_LDO_CTRL2,
|
||||
.enable_mask = LM3631_EN_CONT_MASK,
|
||||
},
|
||||
{
|
||||
.name = "ldo_oref",
|
||||
.of_match = "voref",
|
||||
.id = LM3631_LDO_OREF,
|
||||
.ops = &lm363x_regulator_voltage_table_ops,
|
||||
.n_voltages = LM3631_LDO_VSEL_MAX + 1,
|
||||
.min_uV = LM3631_VLDO_MIN,
|
||||
.uV_step = LM363X_STEP_50mV,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LM3631_REG_VOUT_OREF,
|
||||
.vsel_mask = LM3631_VOUT_MASK,
|
||||
.enable_reg = LM3631_REG_LDO_CTRL1,
|
||||
.enable_mask = LM3631_EN_OREF_MASK,
|
||||
},
|
||||
{
|
||||
.name = "ldo_vpos",
|
||||
.of_match = "vpos",
|
||||
.id = LM3631_LDO_POS,
|
||||
.ops = &lm363x_regulator_voltage_table_ops,
|
||||
.n_voltages = LM3631_LDO_VSEL_MAX + 1,
|
||||
.min_uV = LM3631_VLDO_MIN,
|
||||
.uV_step = LM363X_STEP_50mV,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LM3631_REG_VOUT_POS,
|
||||
.vsel_mask = LM3631_VOUT_MASK,
|
||||
.enable_reg = LM3631_REG_LDO_CTRL1,
|
||||
.enable_mask = LM3631_EN_VPOS_MASK,
|
||||
},
|
||||
{
|
||||
.name = "ldo_vneg",
|
||||
.of_match = "vneg",
|
||||
.id = LM3631_LDO_NEG,
|
||||
.ops = &lm363x_regulator_voltage_table_ops,
|
||||
.n_voltages = LM3631_LDO_VSEL_MAX + 1,
|
||||
.min_uV = LM3631_VLDO_MIN,
|
||||
.uV_step = LM363X_STEP_50mV,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LM3631_REG_VOUT_NEG,
|
||||
.vsel_mask = LM3631_VOUT_MASK,
|
||||
.enable_reg = LM3631_REG_LDO_CTRL1,
|
||||
.enable_mask = LM3631_EN_VNEG_MASK,
|
||||
},
|
||||
/* LM3632 */
|
||||
{
|
||||
.name = "vboost",
|
||||
.of_match = "vboost",
|
||||
.id = LM3632_BOOST,
|
||||
.ops = &lm363x_boost_voltage_table_ops,
|
||||
.n_voltages = LM3632_BOOST_VSEL_MAX + 1,
|
||||
.min_uV = LM3632_VBOOST_MIN,
|
||||
.uV_step = LM363X_STEP_50mV,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LM3632_REG_VOUT_BOOST,
|
||||
.vsel_mask = LM3632_VOUT_MASK,
|
||||
},
|
||||
{
|
||||
.name = "ldo_vpos",
|
||||
.of_match = "vpos",
|
||||
.id = LM3632_LDO_POS,
|
||||
.ops = &lm363x_regulator_voltage_table_ops,
|
||||
.n_voltages = LM3632_LDO_VSEL_MAX + 1,
|
||||
.min_uV = LM3632_VLDO_MIN,
|
||||
.uV_step = LM363X_STEP_50mV,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LM3632_REG_VOUT_POS,
|
||||
.vsel_mask = LM3632_VOUT_MASK,
|
||||
.enable_reg = LM3632_REG_BIAS_CONFIG,
|
||||
.enable_mask = LM3632_EN_VPOS_MASK,
|
||||
},
|
||||
{
|
||||
.name = "ldo_vneg",
|
||||
.of_match = "vneg",
|
||||
.id = LM3632_LDO_NEG,
|
||||
.ops = &lm363x_regulator_voltage_table_ops,
|
||||
.n_voltages = LM3632_LDO_VSEL_MAX + 1,
|
||||
.min_uV = LM3632_VLDO_MIN,
|
||||
.uV_step = LM363X_STEP_50mV,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LM3632_REG_VOUT_NEG,
|
||||
.vsel_mask = LM3632_VOUT_MASK,
|
||||
.enable_reg = LM3632_REG_BIAS_CONFIG,
|
||||
.enable_mask = LM3632_EN_VNEG_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static int lm363x_regulator_of_get_enable_gpio(struct device_node *np, int id)
|
||||
{
|
||||
/*
|
||||
* Check LCM_EN1/2_GPIO is configured.
|
||||
* Those pins are used for enabling VPOS/VNEG LDOs.
|
||||
*/
|
||||
switch (id) {
|
||||
case LM3632_LDO_POS:
|
||||
return of_get_named_gpio(np, "ti,lcm-en1-gpio", 0);
|
||||
case LM3632_LDO_NEG:
|
||||
return of_get_named_gpio(np, "ti,lcm-en2-gpio", 0);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int lm363x_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ti_lmu *lmu = dev_get_drvdata(pdev->dev.parent);
|
||||
struct regmap *regmap = lmu->regmap;
|
||||
struct regulator_config cfg = { };
|
||||
struct regulator_dev *rdev;
|
||||
struct device *dev = &pdev->dev;
|
||||
int id = pdev->id;
|
||||
int ret, ena_gpio;
|
||||
|
||||
cfg.dev = dev;
|
||||
cfg.regmap = regmap;
|
||||
|
||||
/*
|
||||
* LM3632 LDOs can be controlled by external pin.
|
||||
* Register update is required if the pin is used.
|
||||
*/
|
||||
ena_gpio = lm363x_regulator_of_get_enable_gpio(dev->of_node, id);
|
||||
if (gpio_is_valid(ena_gpio)) {
|
||||
cfg.ena_gpio = ena_gpio;
|
||||
cfg.ena_gpio_flags = GPIOF_OUT_INIT_LOW;
|
||||
|
||||
ret = regmap_update_bits(regmap, LM3632_REG_BIAS_CONFIG,
|
||||
LM3632_EXT_EN_MASK,
|
||||
LM3632_EXT_EN_MASK);
|
||||
if (ret) {
|
||||
dev_err(dev, "External pin err: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
rdev = devm_regulator_register(dev, &lm363x_regulator_desc[id], &cfg);
|
||||
if (IS_ERR(rdev)) {
|
||||
ret = PTR_ERR(rdev);
|
||||
dev_err(dev, "[%d] regulator register err: %d\n", id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver lm363x_regulator_driver = {
|
||||
.probe = lm363x_regulator_probe,
|
||||
.driver = {
|
||||
.name = "lm363x-regulator",
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(lm363x_regulator_driver);
|
||||
|
||||
MODULE_DESCRIPTION("TI LM363X Regulator Driver");
|
||||
MODULE_AUTHOR("Milo Kim");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:lm363x-regulator");
|
@ -108,7 +108,6 @@ struct lp872x {
|
||||
struct lp872x_platform_data *pdata;
|
||||
int num_regulators;
|
||||
enum lp872x_dvs_state dvs_pin;
|
||||
int dvs_gpio;
|
||||
};
|
||||
|
||||
/* LP8720/LP8725 shared voltage table for LDOs */
|
||||
@ -520,6 +519,7 @@ static struct regulator_ops lp8725_buck_ops = {
|
||||
static struct regulator_desc lp8720_regulator_desc[] = {
|
||||
{
|
||||
.name = "ldo1",
|
||||
.of_match = of_match_ptr("ldo1"),
|
||||
.id = LP8720_ID_LDO1,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
@ -533,6 +533,7 @@ static struct regulator_desc lp8720_regulator_desc[] = {
|
||||
},
|
||||
{
|
||||
.name = "ldo2",
|
||||
.of_match = of_match_ptr("ldo2"),
|
||||
.id = LP8720_ID_LDO2,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
@ -546,6 +547,7 @@ static struct regulator_desc lp8720_regulator_desc[] = {
|
||||
},
|
||||
{
|
||||
.name = "ldo3",
|
||||
.of_match = of_match_ptr("ldo3"),
|
||||
.id = LP8720_ID_LDO3,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
@ -559,6 +561,7 @@ static struct regulator_desc lp8720_regulator_desc[] = {
|
||||
},
|
||||
{
|
||||
.name = "ldo4",
|
||||
.of_match = of_match_ptr("ldo4"),
|
||||
.id = LP8720_ID_LDO4,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8720_ldo4_vtbl),
|
||||
@ -572,6 +575,7 @@ static struct regulator_desc lp8720_regulator_desc[] = {
|
||||
},
|
||||
{
|
||||
.name = "ldo5",
|
||||
.of_match = of_match_ptr("ldo5"),
|
||||
.id = LP8720_ID_LDO5,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
@ -585,6 +589,7 @@ static struct regulator_desc lp8720_regulator_desc[] = {
|
||||
},
|
||||
{
|
||||
.name = "buck",
|
||||
.of_match = of_match_ptr("buck"),
|
||||
.id = LP8720_ID_BUCK,
|
||||
.ops = &lp8720_buck_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8720_buck_vtbl),
|
||||
@ -599,6 +604,7 @@ static struct regulator_desc lp8720_regulator_desc[] = {
|
||||
static struct regulator_desc lp8725_regulator_desc[] = {
|
||||
{
|
||||
.name = "ldo1",
|
||||
.of_match = of_match_ptr("ldo1"),
|
||||
.id = LP8725_ID_LDO1,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
@ -612,6 +618,7 @@ static struct regulator_desc lp8725_regulator_desc[] = {
|
||||
},
|
||||
{
|
||||
.name = "ldo2",
|
||||
.of_match = of_match_ptr("ldo2"),
|
||||
.id = LP8725_ID_LDO2,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
@ -625,6 +632,7 @@ static struct regulator_desc lp8725_regulator_desc[] = {
|
||||
},
|
||||
{
|
||||
.name = "ldo3",
|
||||
.of_match = of_match_ptr("ldo3"),
|
||||
.id = LP8725_ID_LDO3,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
@ -638,6 +646,7 @@ static struct regulator_desc lp8725_regulator_desc[] = {
|
||||
},
|
||||
{
|
||||
.name = "ldo4",
|
||||
.of_match = of_match_ptr("ldo4"),
|
||||
.id = LP8725_ID_LDO4,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
@ -651,6 +660,7 @@ static struct regulator_desc lp8725_regulator_desc[] = {
|
||||
},
|
||||
{
|
||||
.name = "ldo5",
|
||||
.of_match = of_match_ptr("ldo5"),
|
||||
.id = LP8725_ID_LDO5,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
@ -664,6 +674,7 @@ static struct regulator_desc lp8725_regulator_desc[] = {
|
||||
},
|
||||
{
|
||||
.name = "lilo1",
|
||||
.of_match = of_match_ptr("lilo1"),
|
||||
.id = LP8725_ID_LILO1,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8725_lilo_vtbl),
|
||||
@ -677,6 +688,7 @@ static struct regulator_desc lp8725_regulator_desc[] = {
|
||||
},
|
||||
{
|
||||
.name = "lilo2",
|
||||
.of_match = of_match_ptr("lilo2"),
|
||||
.id = LP8725_ID_LILO2,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8725_lilo_vtbl),
|
||||
@ -690,6 +702,7 @@ static struct regulator_desc lp8725_regulator_desc[] = {
|
||||
},
|
||||
{
|
||||
.name = "buck1",
|
||||
.of_match = of_match_ptr("buck1"),
|
||||
.id = LP8725_ID_BUCK1,
|
||||
.ops = &lp8725_buck_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8725_buck_vtbl),
|
||||
@ -701,6 +714,7 @@ static struct regulator_desc lp8725_regulator_desc[] = {
|
||||
},
|
||||
{
|
||||
.name = "buck2",
|
||||
.of_match = of_match_ptr("buck2"),
|
||||
.id = LP8725_ID_BUCK2,
|
||||
.ops = &lp8725_buck_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8725_buck_vtbl),
|
||||
@ -737,7 +751,6 @@ static int lp872x_init_dvs(struct lp872x *lp)
|
||||
}
|
||||
|
||||
lp->dvs_pin = pinstate;
|
||||
lp->dvs_gpio = gpio;
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -344,7 +344,7 @@ static unsigned int lp8788_buck_get_mode(struct regulator_dev *rdev)
|
||||
REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static struct regulator_ops lp8788_buck12_ops = {
|
||||
static const struct regulator_ops lp8788_buck12_ops = {
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.map_voltage = regulator_map_voltage_ascend,
|
||||
.set_voltage_sel = lp8788_buck12_set_voltage_sel,
|
||||
@ -357,7 +357,7 @@ static struct regulator_ops lp8788_buck12_ops = {
|
||||
.get_mode = lp8788_buck_get_mode,
|
||||
};
|
||||
|
||||
static struct regulator_ops lp8788_buck34_ops = {
|
||||
static const struct regulator_ops lp8788_buck34_ops = {
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.map_voltage = regulator_map_voltage_ascend,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
|
@ -170,7 +170,7 @@ static int lp8788_ldo_enable_time(struct regulator_dev *rdev)
|
||||
return ENABLE_TIME_USEC * val;
|
||||
}
|
||||
|
||||
static struct regulator_ops lp8788_ldo_voltage_table_ops = {
|
||||
static const struct regulator_ops lp8788_ldo_voltage_table_ops = {
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
@ -180,7 +180,7 @@ static struct regulator_ops lp8788_ldo_voltage_table_ops = {
|
||||
.enable_time = lp8788_ldo_enable_time,
|
||||
};
|
||||
|
||||
static struct regulator_ops lp8788_ldo_voltage_fixed_ops = {
|
||||
static const struct regulator_ops lp8788_ldo_voltage_fixed_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
@ -613,22 +613,20 @@ static struct platform_driver lp8788_aldo_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_driver * const drivers[] = {
|
||||
&lp8788_dldo_driver,
|
||||
&lp8788_aldo_driver,
|
||||
};
|
||||
|
||||
static int __init lp8788_ldo_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&lp8788_dldo_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return platform_driver_register(&lp8788_aldo_driver);
|
||||
return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
|
||||
}
|
||||
subsys_initcall(lp8788_ldo_init);
|
||||
|
||||
static void __exit lp8788_ldo_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&lp8788_aldo_driver);
|
||||
platform_driver_unregister(&lp8788_dldo_driver);
|
||||
platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
|
||||
}
|
||||
module_exit(lp8788_ldo_exit);
|
||||
|
||||
|
@ -30,6 +30,7 @@ static const struct regmap_config mt6311_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = MT6311_FQMTR_CON4,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
/* Default limits measured in millivolts and milliamps */
|
||||
|
@ -612,6 +612,18 @@ static struct regulator_ops palmas_ops_ldo = {
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
};
|
||||
|
||||
static struct regulator_ops palmas_ops_ldo9 = {
|
||||
.is_enabled = palmas_is_enabled_ldo,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.set_bypass = regulator_set_bypass_regmap,
|
||||
.get_bypass = regulator_get_bypass_regmap,
|
||||
};
|
||||
|
||||
static struct regulator_ops palmas_ops_ext_control_ldo = {
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
@ -639,6 +651,19 @@ static struct regulator_ops tps65917_ops_ldo = {
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
};
|
||||
|
||||
static struct regulator_ops tps65917_ops_ldo_1_2 = {
|
||||
.is_enabled = palmas_is_enabled_ldo,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.set_bypass = regulator_set_bypass_regmap,
|
||||
.get_bypass = regulator_get_bypass_regmap,
|
||||
};
|
||||
|
||||
static int palmas_regulator_config_external(struct palmas *palmas, int id,
|
||||
struct palmas_reg_init *reg_init)
|
||||
{
|
||||
@ -915,6 +940,13 @@ static int palmas_ldo_registration(struct palmas_pmic *pmic,
|
||||
if (pdata && pdata->ldo6_vibrator &&
|
||||
(id == PALMAS_REG_LDO6))
|
||||
desc->enable_time = 2000;
|
||||
|
||||
if (id == PALMAS_REG_LDO9) {
|
||||
desc->ops = &palmas_ops_ldo9;
|
||||
desc->bypass_reg = desc->enable_reg;
|
||||
desc->bypass_mask =
|
||||
PALMAS_LDO9_CTRL_LDO_BYPASS_EN;
|
||||
}
|
||||
} else {
|
||||
if (!ddata->has_regen3 && id == PALMAS_REG_REGEN3)
|
||||
continue;
|
||||
@ -1019,6 +1051,13 @@ static int tps65917_ldo_registration(struct palmas_pmic *pmic,
|
||||
* It is of the order of ~60mV/uS.
|
||||
*/
|
||||
desc->ramp_delay = 2500;
|
||||
if (id == TPS65917_REG_LDO1 ||
|
||||
id == TPS65917_REG_LDO2) {
|
||||
desc->ops = &tps65917_ops_ldo_1_2;
|
||||
desc->bypass_reg = desc->enable_reg;
|
||||
desc->bypass_mask =
|
||||
TPS65917_LDO1_CTRL_BYPASS_EN;
|
||||
}
|
||||
} else {
|
||||
desc->n_voltages = 1;
|
||||
if (reg_init && reg_init->roof_floor)
|
||||
|
437
drivers/regulator/pv88060-regulator.c
Normal file
437
drivers/regulator/pv88060-regulator.c
Normal file
@ -0,0 +1,437 @@
|
||||
/*
|
||||
* pv88060-regulator.c - Regulator device driver for PV88060
|
||||
* Copyright (C) 2015 Powerventure Semiconductor Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include "pv88060-regulator.h"
|
||||
|
||||
#define PV88060_MAX_REGULATORS 14
|
||||
|
||||
/* PV88060 REGULATOR IDs */
|
||||
enum {
|
||||
/* BUCKs */
|
||||
PV88060_ID_BUCK1,
|
||||
|
||||
/* LDOs */
|
||||
PV88060_ID_LDO1,
|
||||
PV88060_ID_LDO2,
|
||||
PV88060_ID_LDO3,
|
||||
PV88060_ID_LDO4,
|
||||
PV88060_ID_LDO5,
|
||||
PV88060_ID_LDO6,
|
||||
PV88060_ID_LDO7,
|
||||
|
||||
/* SWTs */
|
||||
PV88060_ID_SW1,
|
||||
PV88060_ID_SW2,
|
||||
PV88060_ID_SW3,
|
||||
PV88060_ID_SW4,
|
||||
PV88060_ID_SW5,
|
||||
PV88060_ID_SW6,
|
||||
};
|
||||
|
||||
struct pv88060_regulator {
|
||||
struct regulator_desc desc;
|
||||
/* Current limiting */
|
||||
unsigned n_current_limits;
|
||||
const int *current_limits;
|
||||
unsigned int limit_mask;
|
||||
unsigned int conf; /* buck configuration register */
|
||||
};
|
||||
|
||||
struct pv88060 {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct regulator_dev *rdev[PV88060_MAX_REGULATORS];
|
||||
};
|
||||
|
||||
static const struct regmap_config pv88060_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
/* Current limits array (in uA) for BUCK1
|
||||
* Entry indexes corresponds to register values.
|
||||
*/
|
||||
|
||||
static const int pv88060_buck1_limits[] = {
|
||||
1496000, 2393000, 3291000, 4189000
|
||||
};
|
||||
|
||||
static unsigned int pv88060_buck_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
struct pv88060_regulator *info = rdev_get_drvdata(rdev);
|
||||
unsigned int data;
|
||||
int ret, mode = 0;
|
||||
|
||||
ret = regmap_read(rdev->regmap, info->conf, &data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (data & PV88060_BUCK_MODE_MASK) {
|
||||
case PV88060_BUCK_MODE_SYNC:
|
||||
mode = REGULATOR_MODE_FAST;
|
||||
break;
|
||||
case PV88060_BUCK_MODE_AUTO:
|
||||
mode = REGULATOR_MODE_NORMAL;
|
||||
break;
|
||||
case PV88060_BUCK_MODE_SLEEP:
|
||||
mode = REGULATOR_MODE_STANDBY;
|
||||
break;
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static int pv88060_buck_set_mode(struct regulator_dev *rdev,
|
||||
unsigned int mode)
|
||||
{
|
||||
struct pv88060_regulator *info = rdev_get_drvdata(rdev);
|
||||
int val = 0;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_FAST:
|
||||
val = PV88060_BUCK_MODE_SYNC;
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
val = PV88060_BUCK_MODE_AUTO;
|
||||
break;
|
||||
case REGULATOR_MODE_STANDBY:
|
||||
val = PV88060_BUCK_MODE_SLEEP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return regmap_update_bits(rdev->regmap, info->conf,
|
||||
PV88060_BUCK_MODE_MASK, val);
|
||||
}
|
||||
|
||||
static int pv88060_set_current_limit(struct regulator_dev *rdev, int min,
|
||||
int max)
|
||||
{
|
||||
struct pv88060_regulator *info = rdev_get_drvdata(rdev);
|
||||
int i;
|
||||
|
||||
/* search for closest to maximum */
|
||||
for (i = info->n_current_limits; i >= 0; i--) {
|
||||
if (min <= info->current_limits[i]
|
||||
&& max >= info->current_limits[i]) {
|
||||
return regmap_update_bits(rdev->regmap,
|
||||
info->conf,
|
||||
info->limit_mask,
|
||||
i << PV88060_BUCK_ILIM_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int pv88060_get_current_limit(struct regulator_dev *rdev)
|
||||
{
|
||||
struct pv88060_regulator *info = rdev_get_drvdata(rdev);
|
||||
unsigned int data;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(rdev->regmap, info->conf, &data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
data = (data & info->limit_mask) >> PV88060_BUCK_ILIM_SHIFT;
|
||||
return info->current_limits[data];
|
||||
}
|
||||
|
||||
static struct regulator_ops pv88060_buck_ops = {
|
||||
.get_mode = pv88060_buck_get_mode,
|
||||
.set_mode = pv88060_buck_set_mode,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.set_current_limit = pv88060_set_current_limit,
|
||||
.get_current_limit = pv88060_get_current_limit,
|
||||
};
|
||||
|
||||
static struct regulator_ops pv88060_ldo_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
};
|
||||
|
||||
#define PV88060_BUCK(chip, regl_name, min, step, max, limits_array) \
|
||||
{\
|
||||
.desc = {\
|
||||
.id = chip##_ID_##regl_name,\
|
||||
.name = __stringify(chip##_##regl_name),\
|
||||
.of_match = of_match_ptr(#regl_name),\
|
||||
.regulators_node = of_match_ptr("regulators"),\
|
||||
.type = REGULATOR_VOLTAGE,\
|
||||
.owner = THIS_MODULE,\
|
||||
.ops = &pv88060_buck_ops,\
|
||||
.min_uV = min,\
|
||||
.uV_step = step,\
|
||||
.n_voltages = ((max) - (min))/(step) + 1,\
|
||||
.enable_reg = PV88060_REG_##regl_name##_CONF0,\
|
||||
.enable_mask = PV88060_BUCK_EN, \
|
||||
.vsel_reg = PV88060_REG_##regl_name##_CONF0,\
|
||||
.vsel_mask = PV88060_VBUCK_MASK,\
|
||||
},\
|
||||
.current_limits = limits_array,\
|
||||
.n_current_limits = ARRAY_SIZE(limits_array),\
|
||||
.limit_mask = PV88060_BUCK_ILIM_MASK, \
|
||||
.conf = PV88060_REG_##regl_name##_CONF1,\
|
||||
}
|
||||
|
||||
#define PV88060_LDO(chip, regl_name, min, step, max) \
|
||||
{\
|
||||
.desc = {\
|
||||
.id = chip##_ID_##regl_name,\
|
||||
.name = __stringify(chip##_##regl_name),\
|
||||
.of_match = of_match_ptr(#regl_name),\
|
||||
.regulators_node = of_match_ptr("regulators"),\
|
||||
.type = REGULATOR_VOLTAGE,\
|
||||
.owner = THIS_MODULE,\
|
||||
.ops = &pv88060_ldo_ops,\
|
||||
.min_uV = min, \
|
||||
.uV_step = step, \
|
||||
.n_voltages = (step) ? ((max - min) / step + 1) : 1, \
|
||||
.enable_reg = PV88060_REG_##regl_name##_CONF, \
|
||||
.enable_mask = PV88060_LDO_EN, \
|
||||
.vsel_reg = PV88060_REG_##regl_name##_CONF, \
|
||||
.vsel_mask = PV88060_VLDO_MASK, \
|
||||
},\
|
||||
}
|
||||
|
||||
#define PV88060_SW(chip, regl_name, max) \
|
||||
{\
|
||||
.desc = {\
|
||||
.id = chip##_ID_##regl_name,\
|
||||
.name = __stringify(chip##_##regl_name),\
|
||||
.of_match = of_match_ptr(#regl_name),\
|
||||
.regulators_node = of_match_ptr("regulators"),\
|
||||
.type = REGULATOR_VOLTAGE,\
|
||||
.owner = THIS_MODULE,\
|
||||
.ops = &pv88060_ldo_ops,\
|
||||
.min_uV = max,\
|
||||
.uV_step = 0,\
|
||||
.n_voltages = 1,\
|
||||
.enable_reg = PV88060_REG_##regl_name##_CONF,\
|
||||
.enable_mask = PV88060_SW_EN,\
|
||||
},\
|
||||
}
|
||||
|
||||
static const struct pv88060_regulator pv88060_regulator_info[] = {
|
||||
PV88060_BUCK(PV88060, BUCK1, 2800000, 12500, 4387500,
|
||||
pv88060_buck1_limits),
|
||||
PV88060_LDO(PV88060, LDO1, 1200000, 50000, 3350000),
|
||||
PV88060_LDO(PV88060, LDO2, 1200000, 50000, 3350000),
|
||||
PV88060_LDO(PV88060, LDO3, 1200000, 50000, 3350000),
|
||||
PV88060_LDO(PV88060, LDO4, 1200000, 50000, 3350000),
|
||||
PV88060_LDO(PV88060, LDO5, 1200000, 50000, 3350000),
|
||||
PV88060_LDO(PV88060, LDO6, 1200000, 50000, 3350000),
|
||||
PV88060_LDO(PV88060, LDO7, 1200000, 50000, 3350000),
|
||||
PV88060_SW(PV88060, SW1, 5000000),
|
||||
PV88060_SW(PV88060, SW2, 5000000),
|
||||
PV88060_SW(PV88060, SW3, 5000000),
|
||||
PV88060_SW(PV88060, SW4, 5000000),
|
||||
PV88060_SW(PV88060, SW5, 5000000),
|
||||
PV88060_SW(PV88060, SW6, 5000000),
|
||||
};
|
||||
|
||||
static irqreturn_t pv88060_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct pv88060 *chip = data;
|
||||
int i, reg_val, err, ret = IRQ_NONE;
|
||||
|
||||
err = regmap_read(chip->regmap, PV88060_REG_EVENT_A, ®_val);
|
||||
if (err < 0)
|
||||
goto error_i2c;
|
||||
|
||||
if (reg_val & PV88060_E_VDD_FLT) {
|
||||
for (i = 0; i < PV88060_MAX_REGULATORS; i++) {
|
||||
if (chip->rdev[i] != NULL) {
|
||||
regulator_notifier_call_chain(chip->rdev[i],
|
||||
REGULATOR_EVENT_UNDER_VOLTAGE,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
err = regmap_update_bits(chip->regmap, PV88060_REG_EVENT_A,
|
||||
PV88060_E_VDD_FLT, PV88060_E_VDD_FLT);
|
||||
if (err < 0)
|
||||
goto error_i2c;
|
||||
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (reg_val & PV88060_E_OVER_TEMP) {
|
||||
for (i = 0; i < PV88060_MAX_REGULATORS; i++) {
|
||||
if (chip->rdev[i] != NULL) {
|
||||
regulator_notifier_call_chain(chip->rdev[i],
|
||||
REGULATOR_EVENT_OVER_TEMP,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
err = regmap_update_bits(chip->regmap, PV88060_REG_EVENT_A,
|
||||
PV88060_E_OVER_TEMP, PV88060_E_OVER_TEMP);
|
||||
if (err < 0)
|
||||
goto error_i2c;
|
||||
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
error_i2c:
|
||||
dev_err(chip->dev, "I2C error : %d\n", err);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* I2C driver interface functions
|
||||
*/
|
||||
static int pv88060_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev);
|
||||
struct pv88060 *chip;
|
||||
struct regulator_config config = { };
|
||||
int error, i, ret = 0;
|
||||
|
||||
chip = devm_kzalloc(&i2c->dev, sizeof(struct pv88060), GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->dev = &i2c->dev;
|
||||
chip->regmap = devm_regmap_init_i2c(i2c, &pv88060_regmap_config);
|
||||
if (IS_ERR(chip->regmap)) {
|
||||
error = PTR_ERR(chip->regmap);
|
||||
dev_err(chip->dev, "Failed to allocate register map: %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(i2c, chip);
|
||||
|
||||
if (i2c->irq != 0) {
|
||||
ret = regmap_write(chip->regmap, PV88060_REG_MASK_A, 0xFF);
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev,
|
||||
"Failed to mask A reg: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_write(chip->regmap, PV88060_REG_MASK_B, 0xFF);
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev,
|
||||
"Failed to mask B reg: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_write(chip->regmap, PV88060_REG_MASK_C, 0xFF);
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev,
|
||||
"Failed to mask C reg: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
|
||||
pv88060_irq_handler,
|
||||
IRQF_TRIGGER_LOW|IRQF_ONESHOT,
|
||||
"pv88060", chip);
|
||||
if (ret != 0) {
|
||||
dev_err(chip->dev, "Failed to request IRQ: %d\n",
|
||||
i2c->irq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(chip->regmap, PV88060_REG_MASK_A,
|
||||
PV88060_M_VDD_FLT | PV88060_M_OVER_TEMP, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev,
|
||||
"Failed to update mask reg: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
} else {
|
||||
dev_warn(chip->dev, "No IRQ configured\n");
|
||||
}
|
||||
|
||||
config.dev = chip->dev;
|
||||
config.regmap = chip->regmap;
|
||||
|
||||
for (i = 0; i < PV88060_MAX_REGULATORS; i++) {
|
||||
if (init_data)
|
||||
config.init_data = &init_data[i];
|
||||
|
||||
config.driver_data = (void *)&pv88060_regulator_info[i];
|
||||
chip->rdev[i] = devm_regulator_register(chip->dev,
|
||||
&pv88060_regulator_info[i].desc, &config);
|
||||
if (IS_ERR(chip->rdev[i])) {
|
||||
dev_err(chip->dev,
|
||||
"Failed to register PV88060 regulator\n");
|
||||
return PTR_ERR(chip->rdev[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id pv88060_i2c_id[] = {
|
||||
{"pv88060", 0},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, pv88060_i2c_id);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id pv88060_dt_ids[] = {
|
||||
{ .compatible = "pvs,pv88060", .data = &pv88060_i2c_id[0] },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pv88060_dt_ids);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver pv88060_regulator_driver = {
|
||||
.driver = {
|
||||
.name = "pv88060",
|
||||
.of_match_table = of_match_ptr(pv88060_dt_ids),
|
||||
},
|
||||
.probe = pv88060_i2c_probe,
|
||||
.id_table = pv88060_i2c_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(pv88060_regulator_driver);
|
||||
|
||||
MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>");
|
||||
MODULE_DESCRIPTION("Regulator device driver for Powerventure PV88060");
|
||||
MODULE_LICENSE("GPL");
|
69
drivers/regulator/pv88060-regulator.h
Normal file
69
drivers/regulator/pv88060-regulator.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* pv88060-regulator.h - Regulator definitions for PV88060
|
||||
* Copyright (C) 2015 Powerventure Semiconductor Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __PV88060_REGISTERS_H__
|
||||
#define __PV88060_REGISTERS_H__
|
||||
|
||||
/* System Control and Event Registers */
|
||||
#define PV88060_REG_EVENT_A 0x04
|
||||
#define PV88060_REG_MASK_A 0x08
|
||||
#define PV88060_REG_MASK_B 0x09
|
||||
#define PV88060_REG_MASK_C 0x0A
|
||||
|
||||
/* Regulator Registers */
|
||||
#define PV88060_REG_BUCK1_CONF0 0x1B
|
||||
#define PV88060_REG_BUCK1_CONF1 0x1C
|
||||
#define PV88060_REG_LDO1_CONF 0x1D
|
||||
#define PV88060_REG_LDO2_CONF 0x1E
|
||||
#define PV88060_REG_LDO3_CONF 0x1F
|
||||
#define PV88060_REG_LDO4_CONF 0x20
|
||||
#define PV88060_REG_LDO5_CONF 0x21
|
||||
#define PV88060_REG_LDO6_CONF 0x22
|
||||
#define PV88060_REG_LDO7_CONF 0x23
|
||||
|
||||
#define PV88060_REG_SW1_CONF 0x3B
|
||||
#define PV88060_REG_SW2_CONF 0x3C
|
||||
#define PV88060_REG_SW3_CONF 0x3D
|
||||
#define PV88060_REG_SW4_CONF 0x3E
|
||||
#define PV88060_REG_SW5_CONF 0x3F
|
||||
#define PV88060_REG_SW6_CONF 0x40
|
||||
|
||||
/* PV88060_REG_EVENT_A (addr=0x04) */
|
||||
#define PV88060_E_VDD_FLT 0x01
|
||||
#define PV88060_E_OVER_TEMP 0x02
|
||||
|
||||
/* PV88060_REG_MASK_A (addr=0x08) */
|
||||
#define PV88060_M_VDD_FLT 0x01
|
||||
#define PV88060_M_OVER_TEMP 0x02
|
||||
|
||||
/* PV88060_REG_BUCK1_CONF0 (addr=0x1B) */
|
||||
#define PV88060_BUCK_EN 0x80
|
||||
#define PV88060_VBUCK_MASK 0x7F
|
||||
/* PV88060_REG_LDO1/2/3/4/5/6/7_CONT */
|
||||
#define PV88060_LDO_EN 0x40
|
||||
#define PV88060_VLDO_MASK 0x3F
|
||||
/* PV88060_REG_SW1/2/3/4/5_CONF */
|
||||
#define PV88060_SW_EN 0x80
|
||||
|
||||
/* PV88060_REG_BUCK1_CONF1 (addr=0x1C) */
|
||||
#define PV88060_BUCK_ILIM_SHIFT 2
|
||||
#define PV88060_BUCK_ILIM_MASK 0x0C
|
||||
#define PV88060_BUCK_MODE_SHIFT 0
|
||||
#define PV88060_BUCK_MODE_MASK 0x03
|
||||
#define PV88060_BUCK_MODE_SLEEP 0x00
|
||||
#define PV88060_BUCK_MODE_AUTO 0x01
|
||||
#define PV88060_BUCK_MODE_SYNC 0x02
|
||||
|
||||
#endif /* __PV88060_REGISTERS_H__ */
|
458
drivers/regulator/pv88090-regulator.c
Normal file
458
drivers/regulator/pv88090-regulator.c
Normal file
@ -0,0 +1,458 @@
|
||||
/*
|
||||
* pv88090-regulator.c - Regulator device driver for PV88090
|
||||
* Copyright (C) 2015 Powerventure Semiconductor Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include "pv88090-regulator.h"
|
||||
|
||||
#define PV88090_MAX_REGULATORS 5
|
||||
|
||||
/* PV88090 REGULATOR IDs */
|
||||
enum {
|
||||
/* BUCKs */
|
||||
PV88090_ID_BUCK1,
|
||||
PV88090_ID_BUCK2,
|
||||
PV88090_ID_BUCK3,
|
||||
|
||||
/* LDOs */
|
||||
PV88090_ID_LDO1,
|
||||
PV88090_ID_LDO2,
|
||||
};
|
||||
|
||||
struct pv88090_regulator {
|
||||
struct regulator_desc desc;
|
||||
/* Current limiting */
|
||||
unsigned n_current_limits;
|
||||
const int *current_limits;
|
||||
unsigned int limit_mask;
|
||||
unsigned int conf;
|
||||
unsigned int conf2;
|
||||
};
|
||||
|
||||
struct pv88090 {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct regulator_dev *rdev[PV88090_MAX_REGULATORS];
|
||||
};
|
||||
|
||||
struct pv88090_buck_voltage {
|
||||
int min_uV;
|
||||
int max_uV;
|
||||
int uV_step;
|
||||
};
|
||||
|
||||
static const struct regmap_config pv88090_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
/* Current limits array (in uA) for BUCK1, BUCK2, BUCK3.
|
||||
* Entry indexes corresponds to register values.
|
||||
*/
|
||||
|
||||
static const int pv88090_buck1_limits[] = {
|
||||
220000, 440000, 660000, 880000, 1100000, 1320000, 1540000, 1760000,
|
||||
1980000, 2200000, 2420000, 2640000, 2860000, 3080000, 3300000, 3520000,
|
||||
3740000, 3960000, 4180000, 4400000, 4620000, 4840000, 5060000, 5280000,
|
||||
5500000, 5720000, 5940000, 6160000, 6380000, 6600000, 6820000, 7040000
|
||||
};
|
||||
|
||||
static const int pv88090_buck23_limits[] = {
|
||||
1496000, 2393000, 3291000, 4189000
|
||||
};
|
||||
|
||||
static const struct pv88090_buck_voltage pv88090_buck_vol[3] = {
|
||||
{
|
||||
.min_uV = 600000,
|
||||
.max_uV = 1393750,
|
||||
.uV_step = 6250,
|
||||
},
|
||||
|
||||
{
|
||||
.min_uV = 1400000,
|
||||
.max_uV = 2193750,
|
||||
.uV_step = 6250,
|
||||
},
|
||||
{
|
||||
.min_uV = 1250000,
|
||||
.max_uV = 2837500,
|
||||
.uV_step = 12500,
|
||||
},
|
||||
};
|
||||
|
||||
static unsigned int pv88090_buck_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
struct pv88090_regulator *info = rdev_get_drvdata(rdev);
|
||||
unsigned int data;
|
||||
int ret, mode = 0;
|
||||
|
||||
ret = regmap_read(rdev->regmap, info->conf, &data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (data & PV88090_BUCK1_MODE_MASK) {
|
||||
case PV88090_BUCK_MODE_SYNC:
|
||||
mode = REGULATOR_MODE_FAST;
|
||||
break;
|
||||
case PV88090_BUCK_MODE_AUTO:
|
||||
mode = REGULATOR_MODE_NORMAL;
|
||||
break;
|
||||
case PV88090_BUCK_MODE_SLEEP:
|
||||
mode = REGULATOR_MODE_STANDBY;
|
||||
break;
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static int pv88090_buck_set_mode(struct regulator_dev *rdev,
|
||||
unsigned int mode)
|
||||
{
|
||||
struct pv88090_regulator *info = rdev_get_drvdata(rdev);
|
||||
int val = 0;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_FAST:
|
||||
val = PV88090_BUCK_MODE_SYNC;
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
val = PV88090_BUCK_MODE_AUTO;
|
||||
break;
|
||||
case REGULATOR_MODE_STANDBY:
|
||||
val = PV88090_BUCK_MODE_SLEEP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return regmap_update_bits(rdev->regmap, info->conf,
|
||||
PV88090_BUCK1_MODE_MASK, val);
|
||||
}
|
||||
|
||||
static int pv88090_set_current_limit(struct regulator_dev *rdev, int min,
|
||||
int max)
|
||||
{
|
||||
struct pv88090_regulator *info = rdev_get_drvdata(rdev);
|
||||
int i;
|
||||
|
||||
/* search for closest to maximum */
|
||||
for (i = info->n_current_limits; i >= 0; i--) {
|
||||
if (min <= info->current_limits[i]
|
||||
&& max >= info->current_limits[i]) {
|
||||
return regmap_update_bits(rdev->regmap,
|
||||
info->conf,
|
||||
info->limit_mask,
|
||||
i << PV88090_BUCK1_ILIM_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int pv88090_get_current_limit(struct regulator_dev *rdev)
|
||||
{
|
||||
struct pv88090_regulator *info = rdev_get_drvdata(rdev);
|
||||
unsigned int data;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(rdev->regmap, info->conf, &data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
data = (data & info->limit_mask) >> PV88090_BUCK1_ILIM_SHIFT;
|
||||
return info->current_limits[data];
|
||||
}
|
||||
|
||||
static struct regulator_ops pv88090_buck_ops = {
|
||||
.get_mode = pv88090_buck_get_mode,
|
||||
.set_mode = pv88090_buck_set_mode,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.set_current_limit = pv88090_set_current_limit,
|
||||
.get_current_limit = pv88090_get_current_limit,
|
||||
};
|
||||
|
||||
static struct regulator_ops pv88090_ldo_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
};
|
||||
|
||||
#define PV88090_BUCK(chip, regl_name, min, step, max, limits_array) \
|
||||
{\
|
||||
.desc = {\
|
||||
.id = chip##_ID_##regl_name,\
|
||||
.name = __stringify(chip##_##regl_name),\
|
||||
.of_match = of_match_ptr(#regl_name),\
|
||||
.regulators_node = of_match_ptr("regulators"),\
|
||||
.type = REGULATOR_VOLTAGE,\
|
||||
.owner = THIS_MODULE,\
|
||||
.ops = &pv88090_buck_ops,\
|
||||
.min_uV = min, \
|
||||
.uV_step = step, \
|
||||
.n_voltages = ((max) - (min))/(step) + 1, \
|
||||
.enable_reg = PV88090_REG_##regl_name##_CONF0, \
|
||||
.enable_mask = PV88090_##regl_name##_EN, \
|
||||
.vsel_reg = PV88090_REG_##regl_name##_CONF0, \
|
||||
.vsel_mask = PV88090_V##regl_name##_MASK, \
|
||||
},\
|
||||
.current_limits = limits_array, \
|
||||
.n_current_limits = ARRAY_SIZE(limits_array), \
|
||||
.limit_mask = PV88090_##regl_name##_ILIM_MASK, \
|
||||
.conf = PV88090_REG_##regl_name##_CONF1, \
|
||||
.conf2 = PV88090_REG_##regl_name##_CONF2, \
|
||||
}
|
||||
|
||||
#define PV88090_LDO(chip, regl_name, min, step, max) \
|
||||
{\
|
||||
.desc = {\
|
||||
.id = chip##_ID_##regl_name,\
|
||||
.name = __stringify(chip##_##regl_name),\
|
||||
.of_match = of_match_ptr(#regl_name),\
|
||||
.regulators_node = of_match_ptr("regulators"),\
|
||||
.type = REGULATOR_VOLTAGE,\
|
||||
.owner = THIS_MODULE,\
|
||||
.ops = &pv88090_ldo_ops,\
|
||||
.min_uV = min, \
|
||||
.uV_step = step, \
|
||||
.n_voltages = ((max) - (min))/(step) + 1, \
|
||||
.enable_reg = PV88090_REG_##regl_name##_CONT, \
|
||||
.enable_mask = PV88090_##regl_name##_EN, \
|
||||
.vsel_reg = PV88090_REG_##regl_name##_CONT, \
|
||||
.vsel_mask = PV88090_V##regl_name##_MASK, \
|
||||
},\
|
||||
}
|
||||
|
||||
static struct pv88090_regulator pv88090_regulator_info[] = {
|
||||
PV88090_BUCK(PV88090, BUCK1, 600000, 6250, 1393750,
|
||||
pv88090_buck1_limits),
|
||||
PV88090_BUCK(PV88090, BUCK2, 600000, 6250, 1393750,
|
||||
pv88090_buck23_limits),
|
||||
PV88090_BUCK(PV88090, BUCK3, 600000, 6250, 1393750,
|
||||
pv88090_buck23_limits),
|
||||
PV88090_LDO(PV88090, LDO1, 1200000, 50000, 4350000),
|
||||
PV88090_LDO(PV88090, LDO2, 650000, 25000, 2225000),
|
||||
};
|
||||
|
||||
static irqreturn_t pv88090_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct pv88090 *chip = data;
|
||||
int i, reg_val, err, ret = IRQ_NONE;
|
||||
|
||||
err = regmap_read(chip->regmap, PV88090_REG_EVENT_A, ®_val);
|
||||
if (err < 0)
|
||||
goto error_i2c;
|
||||
|
||||
if (reg_val & PV88090_E_VDD_FLT) {
|
||||
for (i = 0; i < PV88090_MAX_REGULATORS; i++) {
|
||||
if (chip->rdev[i] != NULL) {
|
||||
regulator_notifier_call_chain(chip->rdev[i],
|
||||
REGULATOR_EVENT_UNDER_VOLTAGE,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
err = regmap_update_bits(chip->regmap, PV88090_REG_EVENT_A,
|
||||
PV88090_E_VDD_FLT, PV88090_E_VDD_FLT);
|
||||
if (err < 0)
|
||||
goto error_i2c;
|
||||
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (reg_val & PV88090_E_OVER_TEMP) {
|
||||
for (i = 0; i < PV88090_MAX_REGULATORS; i++) {
|
||||
if (chip->rdev[i] != NULL) {
|
||||
regulator_notifier_call_chain(chip->rdev[i],
|
||||
REGULATOR_EVENT_OVER_TEMP,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
err = regmap_update_bits(chip->regmap, PV88090_REG_EVENT_A,
|
||||
PV88090_E_OVER_TEMP, PV88090_E_OVER_TEMP);
|
||||
if (err < 0)
|
||||
goto error_i2c;
|
||||
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
error_i2c:
|
||||
dev_err(chip->dev, "I2C error : %d\n", err);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* I2C driver interface functions
|
||||
*/
|
||||
static int pv88090_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev);
|
||||
struct pv88090 *chip;
|
||||
struct regulator_config config = { };
|
||||
int error, i, ret = 0;
|
||||
unsigned int conf2, range, index;
|
||||
|
||||
chip = devm_kzalloc(&i2c->dev, sizeof(struct pv88090), GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->dev = &i2c->dev;
|
||||
chip->regmap = devm_regmap_init_i2c(i2c, &pv88090_regmap_config);
|
||||
if (IS_ERR(chip->regmap)) {
|
||||
error = PTR_ERR(chip->regmap);
|
||||
dev_err(chip->dev, "Failed to allocate register map: %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(i2c, chip);
|
||||
|
||||
if (i2c->irq != 0) {
|
||||
ret = regmap_write(chip->regmap, PV88090_REG_MASK_A, 0xFF);
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev,
|
||||
"Failed to mask A reg: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_write(chip->regmap, PV88090_REG_MASK_B, 0xFF);
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev,
|
||||
"Failed to mask B reg: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
|
||||
pv88090_irq_handler,
|
||||
IRQF_TRIGGER_LOW|IRQF_ONESHOT,
|
||||
"pv88090", chip);
|
||||
if (ret != 0) {
|
||||
dev_err(chip->dev, "Failed to request IRQ: %d\n",
|
||||
i2c->irq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(chip->regmap, PV88090_REG_MASK_A,
|
||||
PV88090_M_VDD_FLT | PV88090_M_OVER_TEMP, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev,
|
||||
"Failed to update mask reg: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
} else {
|
||||
dev_warn(chip->dev, "No IRQ configured\n");
|
||||
}
|
||||
|
||||
config.dev = chip->dev;
|
||||
config.regmap = chip->regmap;
|
||||
|
||||
for (i = 0; i < PV88090_MAX_REGULATORS; i++) {
|
||||
if (init_data)
|
||||
config.init_data = &init_data[i];
|
||||
|
||||
if (i == PV88090_ID_BUCK2 || i == PV88090_ID_BUCK3) {
|
||||
ret = regmap_read(chip->regmap,
|
||||
pv88090_regulator_info[i].conf2, &conf2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
conf2 = (conf2 >> PV88090_BUCK_VDAC_RANGE_SHIFT) &
|
||||
PV88090_BUCK_VDAC_RANGE_MASK;
|
||||
|
||||
ret = regmap_read(chip->regmap,
|
||||
PV88090_REG_BUCK_FOLD_RANGE, &range);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
range = (range >>
|
||||
(PV88080_BUCK_VRANGE_GAIN_SHIFT + i - 1)) &
|
||||
PV88080_BUCK_VRANGE_GAIN_MASK;
|
||||
index = ((range << 1) | conf2);
|
||||
|
||||
pv88090_regulator_info[i].desc.min_uV
|
||||
= pv88090_buck_vol[index].min_uV;
|
||||
pv88090_regulator_info[i].desc.uV_step
|
||||
= pv88090_buck_vol[index].uV_step;
|
||||
pv88090_regulator_info[i].desc.n_voltages
|
||||
= ((pv88090_buck_vol[index].max_uV)
|
||||
- (pv88090_buck_vol[index].min_uV))
|
||||
/(pv88090_buck_vol[index].uV_step) + 1;
|
||||
}
|
||||
|
||||
config.driver_data = (void *)&pv88090_regulator_info[i];
|
||||
chip->rdev[i] = devm_regulator_register(chip->dev,
|
||||
&pv88090_regulator_info[i].desc, &config);
|
||||
if (IS_ERR(chip->rdev[i])) {
|
||||
dev_err(chip->dev,
|
||||
"Failed to register PV88090 regulator\n");
|
||||
return PTR_ERR(chip->rdev[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id pv88090_i2c_id[] = {
|
||||
{"pv88090", 0},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, pv88090_i2c_id);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id pv88090_dt_ids[] = {
|
||||
{ .compatible = "pvs,pv88090", .data = &pv88090_i2c_id[0] },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pv88090_dt_ids);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver pv88090_regulator_driver = {
|
||||
.driver = {
|
||||
.name = "pv88090",
|
||||
.of_match_table = of_match_ptr(pv88090_dt_ids),
|
||||
},
|
||||
.probe = pv88090_i2c_probe,
|
||||
.id_table = pv88090_i2c_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(pv88090_regulator_driver);
|
||||
|
||||
MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>");
|
||||
MODULE_DESCRIPTION("Regulator device driver for Powerventure PV88090");
|
||||
MODULE_LICENSE("GPL");
|
98
drivers/regulator/pv88090-regulator.h
Normal file
98
drivers/regulator/pv88090-regulator.h
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* pv88090-regulator.h - Regulator definitions for PV88090
|
||||
* Copyright (C) 2015 Powerventure Semiconductor Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __PV88090_REGISTERS_H__
|
||||
#define __PV88090_REGISTERS_H__
|
||||
|
||||
/* System Control and Event Registers */
|
||||
#define PV88090_REG_EVENT_A 0x03
|
||||
#define PV88090_REG_MASK_A 0x06
|
||||
#define PV88090_REG_MASK_B 0x07
|
||||
|
||||
/* Regulator Registers */
|
||||
#define PV88090_REG_BUCK1_CONF0 0x18
|
||||
#define PV88090_REG_BUCK1_CONF1 0x19
|
||||
#define PV88090_REG_BUCK1_CONF2 0x1a
|
||||
#define PV88090_REG_BUCK2_CONF0 0x1b
|
||||
#define PV88090_REG_BUCK2_CONF1 0x1c
|
||||
#define PV88090_REG_BUCK2_CONF2 0x58
|
||||
#define PV88090_REG_BUCK3_CONF0 0x1d
|
||||
#define PV88090_REG_BUCK3_CONF1 0x1e
|
||||
#define PV88090_REG_BUCK3_CONF2 0x5c
|
||||
|
||||
#define PV88090_REG_LDO1_CONT 0x1f
|
||||
#define PV88090_REG_LDO2_CONT 0x20
|
||||
#define PV88090_REG_LDO3_CONT 0x21
|
||||
#define PV88090_REG_BUCK_FOLD_RANGE 0x61
|
||||
|
||||
/* PV88090_REG_EVENT_A (addr=0x03) */
|
||||
#define PV88090_E_VDD_FLT 0x01
|
||||
#define PV88090_E_OVER_TEMP 0x02
|
||||
|
||||
/* PV88090_REG_MASK_A (addr=0x06) */
|
||||
#define PV88090_M_VDD_FLT 0x01
|
||||
#define PV88090_M_OVER_TEMP 0x02
|
||||
|
||||
/* PV88090_REG_BUCK1_CONF0 (addr=0x18) */
|
||||
#define PV88090_BUCK1_EN 0x80
|
||||
#define PV88090_VBUCK1_MASK 0x7F
|
||||
/* PV88090_REG_BUCK2_CONF0 (addr=0x1b) */
|
||||
#define PV88090_BUCK2_EN 0x80
|
||||
#define PV88090_VBUCK2_MASK 0x7F
|
||||
/* PV88090_REG_BUCK3_CONF0 (addr=0x1d) */
|
||||
#define PV88090_BUCK3_EN 0x80
|
||||
#define PV88090_VBUCK3_MASK 0x7F
|
||||
/* PV88090_REG_LDO1_CONT (addr=0x1f) */
|
||||
#define PV88090_LDO1_EN 0x40
|
||||
#define PV88090_VLDO1_MASK 0x3F
|
||||
/* PV88090_REG_LDO2_CONT (addr=0x20) */
|
||||
#define PV88090_LDO2_EN 0x40
|
||||
#define PV88090_VLDO2_MASK 0x3F
|
||||
|
||||
/* PV88090_REG_BUCK1_CONF1 (addr=0x19) */
|
||||
#define PV88090_BUCK1_ILIM_SHIFT 2
|
||||
#define PV88090_BUCK1_ILIM_MASK 0x7C
|
||||
#define PV88090_BUCK1_MODE_MASK 0x03
|
||||
|
||||
/* PV88090_REG_BUCK2_CONF1 (addr=0x1c) */
|
||||
#define PV88090_BUCK2_ILIM_SHIFT 2
|
||||
#define PV88090_BUCK2_ILIM_MASK 0x0C
|
||||
#define PV88090_BUCK2_MODE_MASK 0x03
|
||||
|
||||
/* PV88090_REG_BUCK3_CONF1 (addr=0x1e) */
|
||||
#define PV88090_BUCK3_ILIM_SHIFT 2
|
||||
#define PV88090_BUCK3_ILIM_MASK 0x0C
|
||||
#define PV88090_BUCK3_MODE_MASK 0x03
|
||||
|
||||
#define PV88090_BUCK_MODE_SLEEP 0x00
|
||||
#define PV88090_BUCK_MODE_AUTO 0x01
|
||||
#define PV88090_BUCK_MODE_SYNC 0x02
|
||||
|
||||
/* PV88090_REG_BUCK2_CONF2 (addr=0x58) */
|
||||
/* PV88090_REG_BUCK3_CONF2 (addr=0x5c) */
|
||||
#define PV88090_BUCK_VDAC_RANGE_SHIFT 7
|
||||
#define PV88090_BUCK_VDAC_RANGE_MASK 0x01
|
||||
|
||||
#define PV88090_BUCK_VDAC_RANGE_1 0x00
|
||||
#define PV88090_BUCK_VDAC_RANGE_2 0x01
|
||||
|
||||
/* PV88090_REG_BUCK_FOLD_RANGE (addr=0x61) */
|
||||
#define PV88080_BUCK_VRANGE_GAIN_SHIFT 3
|
||||
#define PV88080_BUCK_VRANGE_GAIN_MASK 0x01
|
||||
|
||||
#define PV88080_BUCK_VRANGE_GAIN_1 0x00
|
||||
#define PV88080_BUCK_VRANGE_GAIN_2 0x01
|
||||
|
||||
#endif /* __PV88090_REGISTERS_H__ */
|
@ -153,6 +153,49 @@ static const struct regulator_ops rpm_switch_ops = {
|
||||
.is_enabled = rpm_reg_is_enabled,
|
||||
};
|
||||
|
||||
static const struct regulator_desc pma8084_hfsmps = {
|
||||
.linear_ranges = (struct regulator_linear_range[]) {
|
||||
REGULATOR_LINEAR_RANGE(375000, 0, 95, 12500),
|
||||
REGULATOR_LINEAR_RANGE(1550000, 96, 158, 25000),
|
||||
},
|
||||
.n_linear_ranges = 2,
|
||||
.n_voltages = 159,
|
||||
.ops = &rpm_smps_ldo_ops,
|
||||
};
|
||||
|
||||
static const struct regulator_desc pma8084_ftsmps = {
|
||||
.linear_ranges = (struct regulator_linear_range[]) {
|
||||
REGULATOR_LINEAR_RANGE(350000, 0, 184, 5000),
|
||||
REGULATOR_LINEAR_RANGE(700000, 185, 339, 10000),
|
||||
},
|
||||
.n_linear_ranges = 2,
|
||||
.n_voltages = 340,
|
||||
.ops = &rpm_smps_ldo_ops,
|
||||
};
|
||||
|
||||
static const struct regulator_desc pma8084_pldo = {
|
||||
.linear_ranges = (struct regulator_linear_range[]) {
|
||||
REGULATOR_LINEAR_RANGE(750000, 0, 30, 25000),
|
||||
REGULATOR_LINEAR_RANGE(1500000, 31, 99, 50000),
|
||||
},
|
||||
.n_linear_ranges = 2,
|
||||
.n_voltages = 100,
|
||||
.ops = &rpm_smps_ldo_ops,
|
||||
};
|
||||
|
||||
static const struct regulator_desc pma8084_nldo = {
|
||||
.linear_ranges = (struct regulator_linear_range[]) {
|
||||
REGULATOR_LINEAR_RANGE(750000, 0, 63, 12500),
|
||||
},
|
||||
.n_linear_ranges = 1,
|
||||
.n_voltages = 64,
|
||||
.ops = &rpm_smps_ldo_ops,
|
||||
};
|
||||
|
||||
static const struct regulator_desc pma8084_switch = {
|
||||
.ops = &rpm_switch_ops,
|
||||
};
|
||||
|
||||
static const struct regulator_desc pm8x41_hfsmps = {
|
||||
.linear_ranges = (struct regulator_linear_range[]) {
|
||||
REGULATOR_LINEAR_RANGE( 375000, 0, 95, 12500),
|
||||
@ -211,6 +254,43 @@ static const struct regulator_desc pm8941_switch = {
|
||||
.ops = &rpm_switch_ops,
|
||||
};
|
||||
|
||||
static const struct regulator_desc pm8916_pldo = {
|
||||
.linear_ranges = (struct regulator_linear_range[]) {
|
||||
REGULATOR_LINEAR_RANGE(750000, 0, 208, 12500),
|
||||
},
|
||||
.n_linear_ranges = 1,
|
||||
.n_voltages = 209,
|
||||
.ops = &rpm_smps_ldo_ops,
|
||||
};
|
||||
|
||||
static const struct regulator_desc pm8916_nldo = {
|
||||
.linear_ranges = (struct regulator_linear_range[]) {
|
||||
REGULATOR_LINEAR_RANGE(375000, 0, 93, 12500),
|
||||
},
|
||||
.n_linear_ranges = 1,
|
||||
.n_voltages = 94,
|
||||
.ops = &rpm_smps_ldo_ops,
|
||||
};
|
||||
|
||||
static const struct regulator_desc pm8916_buck_lvo_smps = {
|
||||
.linear_ranges = (struct regulator_linear_range[]) {
|
||||
REGULATOR_LINEAR_RANGE(375000, 0, 95, 12500),
|
||||
REGULATOR_LINEAR_RANGE(750000, 96, 127, 25000),
|
||||
},
|
||||
.n_linear_ranges = 2,
|
||||
.n_voltages = 128,
|
||||
.ops = &rpm_smps_ldo_ops,
|
||||
};
|
||||
|
||||
static const struct regulator_desc pm8916_buck_hvo_smps = {
|
||||
.linear_ranges = (struct regulator_linear_range[]) {
|
||||
REGULATOR_LINEAR_RANGE(1550000, 0, 31, 25000),
|
||||
},
|
||||
.n_linear_ranges = 1,
|
||||
.n_voltages = 32,
|
||||
.ops = &rpm_smps_ldo_ops,
|
||||
};
|
||||
|
||||
struct rpm_regulator_data {
|
||||
const char *name;
|
||||
u32 type;
|
||||
@ -231,6 +311,32 @@ static const struct rpm_regulator_data rpm_pm8841_regulators[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct rpm_regulator_data rpm_pm8916_regulators[] = {
|
||||
{ "s1", QCOM_SMD_RPM_SMPA, 1, &pm8916_buck_lvo_smps, "vdd_s1" },
|
||||
{ "s2", QCOM_SMD_RPM_SMPA, 2, &pm8916_buck_lvo_smps, "vdd_s2" },
|
||||
{ "s3", QCOM_SMD_RPM_SMPA, 3, &pm8916_buck_lvo_smps, "vdd_s3" },
|
||||
{ "s4", QCOM_SMD_RPM_SMPA, 4, &pm8916_buck_hvo_smps, "vdd_s4" },
|
||||
{ "l1", QCOM_SMD_RPM_LDOA, 1, &pm8916_nldo, "vdd_l1_l2_l3" },
|
||||
{ "l2", QCOM_SMD_RPM_LDOA, 2, &pm8916_nldo, "vdd_l1_l2_l3" },
|
||||
{ "l3", QCOM_SMD_RPM_LDOA, 3, &pm8916_nldo, "vdd_l1_l2_l3" },
|
||||
{ "l4", QCOM_SMD_RPM_LDOA, 4, &pm8916_pldo, "vdd_l4_l5_l6" },
|
||||
{ "l5", QCOM_SMD_RPM_LDOA, 5, &pm8916_pldo, "vdd_l4_l5_l6" },
|
||||
{ "l6", QCOM_SMD_RPM_LDOA, 6, &pm8916_pldo, "vdd_l4_l5_l6" },
|
||||
{ "l7", QCOM_SMD_RPM_LDOA, 7, &pm8916_pldo, "vdd_l7" },
|
||||
{ "l8", QCOM_SMD_RPM_LDOA, 8, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18" },
|
||||
{ "l9", QCOM_SMD_RPM_LDOA, 9, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18" },
|
||||
{ "l10", QCOM_SMD_RPM_LDOA, 10, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
|
||||
{ "l11", QCOM_SMD_RPM_LDOA, 11, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
|
||||
{ "l12", QCOM_SMD_RPM_LDOA, 12, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
|
||||
{ "l13", QCOM_SMD_RPM_LDOA, 13, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
|
||||
{ "l14", QCOM_SMD_RPM_LDOA, 14, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
|
||||
{ "l15", QCOM_SMD_RPM_LDOA, 15, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
|
||||
{ "l16", QCOM_SMD_RPM_LDOA, 16, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
|
||||
{ "l17", QCOM_SMD_RPM_LDOA, 17, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
|
||||
{ "l18", QCOM_SMD_RPM_LDOA, 18, &pm8916_pldo, "vdd_l8_l9_l10_l11_l12_l13_l14_l15_l16_l17_l18"},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct rpm_regulator_data rpm_pm8941_regulators[] = {
|
||||
{ "s1", QCOM_SMD_RPM_SMPA, 1, &pm8x41_hfsmps, "vdd_s1" },
|
||||
{ "s2", QCOM_SMD_RPM_SMPA, 2, &pm8x41_hfsmps, "vdd_s2" },
|
||||
@ -272,9 +378,62 @@ static const struct rpm_regulator_data rpm_pm8941_regulators[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct rpm_regulator_data rpm_pma8084_regulators[] = {
|
||||
{ "s1", QCOM_SMD_RPM_SMPA, 1, &pma8084_ftsmps, "vdd_s1" },
|
||||
{ "s2", QCOM_SMD_RPM_SMPA, 2, &pma8084_ftsmps, "vdd_s2" },
|
||||
{ "s3", QCOM_SMD_RPM_SMPA, 3, &pma8084_hfsmps, "vdd_s3" },
|
||||
{ "s4", QCOM_SMD_RPM_SMPA, 4, &pma8084_hfsmps, "vdd_s4" },
|
||||
{ "s5", QCOM_SMD_RPM_SMPA, 5, &pma8084_hfsmps, "vdd_s5" },
|
||||
{ "s6", QCOM_SMD_RPM_SMPA, 6, &pma8084_ftsmps, "vdd_s6" },
|
||||
{ "s7", QCOM_SMD_RPM_SMPA, 7, &pma8084_ftsmps, "vdd_s7" },
|
||||
{ "s8", QCOM_SMD_RPM_SMPA, 8, &pma8084_ftsmps, "vdd_s8" },
|
||||
{ "s9", QCOM_SMD_RPM_SMPA, 9, &pma8084_ftsmps, "vdd_s9" },
|
||||
{ "s10", QCOM_SMD_RPM_SMPA, 10, &pma8084_ftsmps, "vdd_s10" },
|
||||
{ "s11", QCOM_SMD_RPM_SMPA, 11, &pma8084_ftsmps, "vdd_s11" },
|
||||
{ "s12", QCOM_SMD_RPM_SMPA, 12, &pma8084_ftsmps, "vdd_s12" },
|
||||
|
||||
{ "l1", QCOM_SMD_RPM_LDOA, 1, &pma8084_nldo, "vdd_l1_l11" },
|
||||
{ "l2", QCOM_SMD_RPM_LDOA, 2, &pma8084_nldo, "vdd_l2_l3_l4_l27" },
|
||||
{ "l3", QCOM_SMD_RPM_LDOA, 3, &pma8084_nldo, "vdd_l2_l3_l4_l27" },
|
||||
{ "l4", QCOM_SMD_RPM_LDOA, 4, &pma8084_nldo, "vdd_l2_l3_l4_l27" },
|
||||
{ "l5", QCOM_SMD_RPM_LDOA, 5, &pma8084_pldo, "vdd_l5_l7" },
|
||||
{ "l6", QCOM_SMD_RPM_LDOA, 6, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" },
|
||||
{ "l7", QCOM_SMD_RPM_LDOA, 7, &pma8084_pldo, "vdd_l5_l7" },
|
||||
{ "l8", QCOM_SMD_RPM_LDOA, 8, &pma8084_pldo, "vdd_l8" },
|
||||
{ "l9", QCOM_SMD_RPM_LDOA, 9, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
|
||||
{ "l10", QCOM_SMD_RPM_LDOA, 10, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
|
||||
{ "l11", QCOM_SMD_RPM_LDOA, 11, &pma8084_nldo, "vdd_l1_l11" },
|
||||
{ "l12", QCOM_SMD_RPM_LDOA, 12, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" },
|
||||
{ "l13", QCOM_SMD_RPM_LDOA, 13, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
|
||||
{ "l14", QCOM_SMD_RPM_LDOA, 14, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" },
|
||||
{ "l15", QCOM_SMD_RPM_LDOA, 15, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" },
|
||||
{ "l16", QCOM_SMD_RPM_LDOA, 16, &pma8084_pldo, "vdd_l16_l25" },
|
||||
{ "l17", QCOM_SMD_RPM_LDOA, 17, &pma8084_pldo, "vdd_l17" },
|
||||
{ "l18", QCOM_SMD_RPM_LDOA, 18, &pma8084_pldo, "vdd_l18" },
|
||||
{ "l19", QCOM_SMD_RPM_LDOA, 19, &pma8084_pldo, "vdd_l19" },
|
||||
{ "l20", QCOM_SMD_RPM_LDOA, 20, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
|
||||
{ "l21", QCOM_SMD_RPM_LDOA, 21, &pma8084_pldo, "vdd_l21" },
|
||||
{ "l22", QCOM_SMD_RPM_LDOA, 22, &pma8084_pldo, "vdd_l22" },
|
||||
{ "l23", QCOM_SMD_RPM_LDOA, 23, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
|
||||
{ "l24", QCOM_SMD_RPM_LDOA, 24, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" },
|
||||
{ "l25", QCOM_SMD_RPM_LDOA, 25, &pma8084_pldo, "vdd_l16_l25" },
|
||||
{ "l26", QCOM_SMD_RPM_LDOA, 26, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" },
|
||||
{ "l27", QCOM_SMD_RPM_LDOA, 27, &pma8084_nldo, "vdd_l2_l3_l4_l27" },
|
||||
|
||||
{ "lvs1", QCOM_SMD_RPM_VSA, 1, &pma8084_switch },
|
||||
{ "lvs2", QCOM_SMD_RPM_VSA, 2, &pma8084_switch },
|
||||
{ "lvs3", QCOM_SMD_RPM_VSA, 3, &pma8084_switch },
|
||||
{ "lvs4", QCOM_SMD_RPM_VSA, 4, &pma8084_switch },
|
||||
{ "5vs1", QCOM_SMD_RPM_VSA, 5, &pma8084_switch },
|
||||
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct of_device_id rpm_of_match[] = {
|
||||
{ .compatible = "qcom,rpm-pm8841-regulators", .data = &rpm_pm8841_regulators },
|
||||
{ .compatible = "qcom,rpm-pm8916-regulators", .data = &rpm_pm8916_regulators },
|
||||
{ .compatible = "qcom,rpm-pm8941-regulators", .data = &rpm_pm8941_regulators },
|
||||
{ .compatible = "qcom,rpm-pma8084-regulators", .data = &rpm_pma8084_regulators },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rpm_of_match);
|
||||
|
@ -27,90 +27,12 @@ static const unsigned int tps6105x_voltages[] = {
|
||||
5000000, /* There is an additional 5V */
|
||||
};
|
||||
|
||||
static int tps6105x_regulator_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct tps6105x *tps6105x = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
/* Activate voltage mode */
|
||||
ret = regmap_update_bits(tps6105x->regmap, TPS6105X_REG_0,
|
||||
TPS6105X_REG0_MODE_MASK,
|
||||
TPS6105X_REG0_MODE_VOLTAGE << TPS6105X_REG0_MODE_SHIFT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps6105x_regulator_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct tps6105x *tps6105x = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
/* Set into shutdown mode */
|
||||
ret = regmap_update_bits(tps6105x->regmap, TPS6105X_REG_0,
|
||||
TPS6105X_REG0_MODE_MASK,
|
||||
TPS6105X_REG0_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps6105x_regulator_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct tps6105x *tps6105x = rdev_get_drvdata(rdev);
|
||||
unsigned int regval;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(tps6105x->regmap, TPS6105X_REG_0, ®val);
|
||||
if (ret)
|
||||
return ret;
|
||||
regval &= TPS6105X_REG0_MODE_MASK;
|
||||
regval >>= TPS6105X_REG0_MODE_SHIFT;
|
||||
|
||||
if (regval == TPS6105X_REG0_MODE_VOLTAGE)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps6105x_regulator_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct tps6105x *tps6105x = rdev_get_drvdata(rdev);
|
||||
unsigned int regval;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(tps6105x->regmap, TPS6105X_REG_0, ®val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
regval &= TPS6105X_REG0_VOLTAGE_MASK;
|
||||
regval >>= TPS6105X_REG0_VOLTAGE_SHIFT;
|
||||
return (int) regval;
|
||||
}
|
||||
|
||||
static int tps6105x_regulator_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct tps6105x *tps6105x = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(tps6105x->regmap, TPS6105X_REG_0,
|
||||
TPS6105X_REG0_VOLTAGE_MASK,
|
||||
selector << TPS6105X_REG0_VOLTAGE_SHIFT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct regulator_ops tps6105x_regulator_ops = {
|
||||
.enable = tps6105x_regulator_enable,
|
||||
.disable = tps6105x_regulator_disable,
|
||||
.is_enabled = tps6105x_regulator_is_enabled,
|
||||
.get_voltage_sel = tps6105x_regulator_get_voltage_sel,
|
||||
.set_voltage_sel = tps6105x_regulator_set_voltage_sel,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
};
|
||||
|
||||
@ -122,6 +44,12 @@ static const struct regulator_desc tps6105x_regulator_desc = {
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = ARRAY_SIZE(tps6105x_voltages),
|
||||
.volt_table = tps6105x_voltages,
|
||||
.vsel_reg = TPS6105X_REG_0,
|
||||
.vsel_mask = TPS6105X_REG0_VOLTAGE_MASK,
|
||||
.enable_reg = TPS6105X_REG_0,
|
||||
.enable_mask = TPS6105X_REG0_MODE_MASK,
|
||||
.enable_val = TPS6105X_REG0_MODE_VOLTAGE <<
|
||||
TPS6105X_REG0_MODE_SHIFT,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -144,6 +72,7 @@ static int tps6105x_regulator_probe(struct platform_device *pdev)
|
||||
config.dev = &tps6105x->client->dev;
|
||||
config.init_data = pdata->regulator_data;
|
||||
config.driver_data = tps6105x;
|
||||
config.regmap = tps6105x->regmap;
|
||||
|
||||
/* Register regulator with framework */
|
||||
tps6105x->regulator = devm_regulator_register(&pdev->dev,
|
||||
|
251
drivers/regulator/tps65086-regulator.c
Normal file
251
drivers/regulator/tps65086-regulator.c
Normal file
@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
|
||||
*
|
||||
* Author: Andrew F. Davis <afd@ti.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 TPS65912 driver
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
|
||||
#include <linux/mfd/tps65086.h>
|
||||
|
||||
enum tps65086_regulators { BUCK1, BUCK2, BUCK3, BUCK4, BUCK5, BUCK6, LDOA1,
|
||||
LDOA2, LDOA3, SWA1, SWB1, SWB2, VTT };
|
||||
|
||||
#define TPS65086_REGULATOR(_name, _of, _id, _nv, _vr, _vm, _er, _em, _lr, _dr, _dm) \
|
||||
[_id] = { \
|
||||
.desc = { \
|
||||
.name = _name, \
|
||||
.of_match = of_match_ptr(_of), \
|
||||
.regulators_node = "regulators", \
|
||||
.of_parse_cb = tps65086_of_parse_cb, \
|
||||
.id = _id, \
|
||||
.ops = ®_ops, \
|
||||
.n_voltages = _nv, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.vsel_reg = _vr, \
|
||||
.vsel_mask = _vm, \
|
||||
.enable_reg = _er, \
|
||||
.enable_mask = _em, \
|
||||
.volt_table = NULL, \
|
||||
.linear_ranges = _lr, \
|
||||
.n_linear_ranges = ARRAY_SIZE(_lr), \
|
||||
}, \
|
||||
.decay_reg = _dr, \
|
||||
.decay_mask = _dm, \
|
||||
}
|
||||
|
||||
#define TPS65086_SWITCH(_name, _of, _id, _er, _em) \
|
||||
[_id] = { \
|
||||
.desc = { \
|
||||
.name = _name, \
|
||||
.of_match = of_match_ptr(_of), \
|
||||
.regulators_node = "regulators", \
|
||||
.of_parse_cb = tps65086_of_parse_cb, \
|
||||
.id = _id, \
|
||||
.ops = &switch_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.enable_reg = _er, \
|
||||
.enable_mask = _em, \
|
||||
}, \
|
||||
}
|
||||
|
||||
struct tps65086_regulator {
|
||||
struct regulator_desc desc;
|
||||
unsigned int decay_reg;
|
||||
unsigned int decay_mask;
|
||||
};
|
||||
|
||||
static const struct regulator_linear_range tps65086_buck126_10mv_ranges[] = {
|
||||
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
|
||||
REGULATOR_LINEAR_RANGE(410000, 0x1, 0x7F, 10000),
|
||||
};
|
||||
|
||||
static const struct regulator_linear_range tps65086_buck126_25mv_ranges[] = {
|
||||
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
|
||||
REGULATOR_LINEAR_RANGE(1000000, 0x1, 0x18, 0),
|
||||
REGULATOR_LINEAR_RANGE(1025000, 0x19, 0x7F, 25000),
|
||||
};
|
||||
|
||||
static const struct regulator_linear_range tps65086_buck345_ranges[] = {
|
||||
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
|
||||
REGULATOR_LINEAR_RANGE(425000, 0x1, 0x7F, 25000),
|
||||
};
|
||||
|
||||
static const struct regulator_linear_range tps65086_ldoa1_ranges[] = {
|
||||
REGULATOR_LINEAR_RANGE(1350000, 0x0, 0x0, 0),
|
||||
REGULATOR_LINEAR_RANGE(1500000, 0x1, 0x7, 100000),
|
||||
REGULATOR_LINEAR_RANGE(2300000, 0x8, 0xA, 100000),
|
||||
REGULATOR_LINEAR_RANGE(2700000, 0xB, 0xD, 150000),
|
||||
REGULATOR_LINEAR_RANGE(3300000, 0xE, 0xE, 0),
|
||||
};
|
||||
|
||||
static const struct regulator_linear_range tps65086_ldoa23_ranges[] = {
|
||||
REGULATOR_LINEAR_RANGE(700000, 0x0, 0xD, 50000),
|
||||
REGULATOR_LINEAR_RANGE(1400000, 0xE, 0xF, 100000),
|
||||
};
|
||||
|
||||
/* Operations permitted on regulators */
|
||||
static struct regulator_ops reg_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.map_voltage = regulator_map_voltage_linear_range,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear_range,
|
||||
};
|
||||
|
||||
/* Operations permitted on load switches */
|
||||
static struct regulator_ops switch_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
};
|
||||
|
||||
static int tps65086_of_parse_cb(struct device_node *dev,
|
||||
const struct regulator_desc *desc,
|
||||
struct regulator_config *config);
|
||||
|
||||
static struct tps65086_regulator regulators[] = {
|
||||
TPS65086_REGULATOR("BUCK1", "buck1", BUCK1, 0x80, TPS65086_BUCK1CTRL,
|
||||
BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(0),
|
||||
tps65086_buck126_10mv_ranges, TPS65086_BUCK1CTRL,
|
||||
BIT(0)),
|
||||
TPS65086_REGULATOR("BUCK2", "buck2", BUCK2, 0x80, TPS65086_BUCK2CTRL,
|
||||
BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(1),
|
||||
tps65086_buck126_10mv_ranges, TPS65086_BUCK2CTRL,
|
||||
BIT(0)),
|
||||
TPS65086_REGULATOR("BUCK3", "buck3", BUCK3, 0x80, TPS65086_BUCK3VID,
|
||||
BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(2),
|
||||
tps65086_buck345_ranges, TPS65086_BUCK3DECAY,
|
||||
BIT(0)),
|
||||
TPS65086_REGULATOR("BUCK4", "buck4", BUCK4, 0x80, TPS65086_BUCK4VID,
|
||||
BUCK_VID_MASK, TPS65086_BUCK4CTRL, BIT(0),
|
||||
tps65086_buck345_ranges, TPS65086_BUCK4VID,
|
||||
BIT(0)),
|
||||
TPS65086_REGULATOR("BUCK5", "buck5", BUCK5, 0x80, TPS65086_BUCK5VID,
|
||||
BUCK_VID_MASK, TPS65086_BUCK5CTRL, BIT(0),
|
||||
tps65086_buck345_ranges, TPS65086_BUCK5CTRL,
|
||||
BIT(0)),
|
||||
TPS65086_REGULATOR("BUCK6", "buck6", BUCK6, 0x80, TPS65086_BUCK6VID,
|
||||
BUCK_VID_MASK, TPS65086_BUCK6CTRL, BIT(0),
|
||||
tps65086_buck126_10mv_ranges, TPS65086_BUCK6CTRL,
|
||||
BIT(0)),
|
||||
TPS65086_REGULATOR("LDOA1", "ldoa1", LDOA1, 0xF, TPS65086_LDOA1CTRL,
|
||||
VDOA1_VID_MASK, TPS65086_LDOA1CTRL, BIT(0),
|
||||
tps65086_ldoa1_ranges, 0, 0),
|
||||
TPS65086_REGULATOR("LDOA2", "ldoa2", LDOA2, 0x10, TPS65086_LDOA2VID,
|
||||
VDOA23_VID_MASK, TPS65086_LDOA2CTRL, BIT(0),
|
||||
tps65086_ldoa23_ranges, 0, 0),
|
||||
TPS65086_REGULATOR("LDOA3", "ldoa3", LDOA3, 0x10, TPS65086_LDOA3VID,
|
||||
VDOA23_VID_MASK, TPS65086_LDOA3CTRL, BIT(0),
|
||||
tps65086_ldoa23_ranges, 0, 0),
|
||||
TPS65086_SWITCH("SWA1", "swa1", SWA1, TPS65086_SWVTT_EN, BIT(5)),
|
||||
TPS65086_SWITCH("SWB1", "swa2", SWB1, TPS65086_SWVTT_EN, BIT(6)),
|
||||
TPS65086_SWITCH("SWB2", "swa3", SWB2, TPS65086_SWVTT_EN, BIT(7)),
|
||||
TPS65086_SWITCH("VTT", "vtt", VTT, TPS65086_SWVTT_EN, BIT(4)),
|
||||
};
|
||||
|
||||
static inline bool has_25mv_mode(int id)
|
||||
{
|
||||
switch (id) {
|
||||
case BUCK1:
|
||||
case BUCK2:
|
||||
case BUCK6:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int tps65086_of_parse_cb(struct device_node *dev,
|
||||
const struct regulator_desc *desc,
|
||||
struct regulator_config *config)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Check for 25mV step mode */
|
||||
if (has_25mv_mode(desc->id) &&
|
||||
of_property_read_bool(config->of_node, "ti,regulator-step-size-25mv")) {
|
||||
regulators[desc->id].desc.linear_ranges =
|
||||
tps65086_buck126_25mv_ranges;
|
||||
regulators[desc->id].desc.n_linear_ranges =
|
||||
ARRAY_SIZE(tps65086_buck126_25mv_ranges);
|
||||
}
|
||||
|
||||
/* Check for decay mode */
|
||||
if (desc->id <= BUCK6 && of_property_read_bool(config->of_node, "ti,regulator-decay")) {
|
||||
ret = regmap_write_bits(config->regmap,
|
||||
regulators[desc->id].decay_reg,
|
||||
regulators[desc->id].decay_mask,
|
||||
regulators[desc->id].decay_mask);
|
||||
if (ret) {
|
||||
dev_err(config->dev, "Error setting decay\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps65086_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tps65086 *tps = dev_get_drvdata(pdev->dev.parent);
|
||||
struct regulator_config config = { };
|
||||
struct regulator_dev *rdev;
|
||||
int i;
|
||||
|
||||
platform_set_drvdata(pdev, tps);
|
||||
|
||||
config.dev = &pdev->dev;
|
||||
config.dev->of_node = tps->dev->of_node;
|
||||
config.driver_data = tps;
|
||||
config.regmap = tps->regmap;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(regulators); i++) {
|
||||
rdev = devm_regulator_register(&pdev->dev, ®ulators[i].desc,
|
||||
&config);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(tps->dev, "failed to register %s regulator\n",
|
||||
pdev->name);
|
||||
return PTR_ERR(rdev);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id tps65086_regulator_id_table[] = {
|
||||
{ "tps65086-regulator", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, tps65086_regulator_id_table);
|
||||
|
||||
static struct platform_driver tps65086_regulator_driver = {
|
||||
.driver = {
|
||||
.name = "tps65086-regulator",
|
||||
},
|
||||
.probe = tps65086_regulator_probe,
|
||||
.id_table = tps65086_regulator_id_table,
|
||||
};
|
||||
module_platform_driver(tps65086_regulator_driver);
|
||||
|
||||
MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");
|
||||
MODULE_DESCRIPTION("TPS65086 Regulator driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -27,19 +27,22 @@
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/mfd/tps65218.h>
|
||||
|
||||
enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4, DCDC5, DCDC6, LDO1 };
|
||||
enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4,
|
||||
DCDC5, DCDC6, LDO1, LS3 };
|
||||
|
||||
#define TPS65218_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _er, _em, \
|
||||
_lr, _nlr, _delay, _fuv) \
|
||||
#define TPS65218_REGULATOR(_name, _id, _type, _ops, _n, _vr, _vm, _er, _em, \
|
||||
_cr, _cm, _lr, _nlr, _delay, _fuv) \
|
||||
{ \
|
||||
.name = _name, \
|
||||
.id = _id, \
|
||||
.ops = &_ops, \
|
||||
.n_voltages = _n, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.type = _type, \
|
||||
.owner = THIS_MODULE, \
|
||||
.vsel_reg = _vr, \
|
||||
.vsel_mask = _vm, \
|
||||
.csel_reg = _cr, \
|
||||
.csel_mask = _cm, \
|
||||
.enable_reg = _er, \
|
||||
.enable_mask = _em, \
|
||||
.volt_table = NULL, \
|
||||
@ -80,6 +83,7 @@ static struct tps_info tps65218_pmic_regs[] = {
|
||||
TPS65218_INFO(DCDC5, "DCDC5", 1000000, 1000000),
|
||||
TPS65218_INFO(DCDC6, "DCDC6", 1800000, 1800000),
|
||||
TPS65218_INFO(LDO1, "LDO1", 900000, 3400000),
|
||||
TPS65218_INFO(LS3, "LS3", -1, -1),
|
||||
};
|
||||
|
||||
#define TPS65218_OF_MATCH(comp, label) \
|
||||
@ -96,6 +100,7 @@ static const struct of_device_id tps65218_of_match[] = {
|
||||
TPS65218_OF_MATCH("ti,tps65218-dcdc5", tps65218_pmic_regs[DCDC5]),
|
||||
TPS65218_OF_MATCH("ti,tps65218-dcdc6", tps65218_pmic_regs[DCDC6]),
|
||||
TPS65218_OF_MATCH("ti,tps65218-ldo1", tps65218_pmic_regs[LDO1]),
|
||||
TPS65218_OF_MATCH("ti,tps65218-ls3", tps65218_pmic_regs[LS3]),
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tps65218_of_match);
|
||||
@ -175,6 +180,68 @@ static struct regulator_ops tps65218_ldo1_dcdc34_ops = {
|
||||
.map_voltage = regulator_map_voltage_linear_range,
|
||||
};
|
||||
|
||||
static const int ls3_currents[] = { 100, 200, 500, 1000 };
|
||||
|
||||
static int tps65218_pmic_set_input_current_lim(struct regulator_dev *dev,
|
||||
int lim_uA)
|
||||
{
|
||||
unsigned int index = 0;
|
||||
unsigned int num_currents = ARRAY_SIZE(ls3_currents);
|
||||
struct tps65218 *tps = rdev_get_drvdata(dev);
|
||||
|
||||
while (index < num_currents && ls3_currents[index] != lim_uA)
|
||||
index++;
|
||||
|
||||
if (index == num_currents)
|
||||
return -EINVAL;
|
||||
|
||||
return tps65218_set_bits(tps, dev->desc->csel_reg, dev->desc->csel_mask,
|
||||
index << 2, TPS65218_PROTECT_L1);
|
||||
}
|
||||
|
||||
static int tps65218_pmic_set_current_limit(struct regulator_dev *dev,
|
||||
int min_uA, int max_uA)
|
||||
{
|
||||
int index = 0;
|
||||
unsigned int num_currents = ARRAY_SIZE(ls3_currents);
|
||||
struct tps65218 *tps = rdev_get_drvdata(dev);
|
||||
|
||||
while (index < num_currents && ls3_currents[index] < max_uA)
|
||||
index++;
|
||||
|
||||
index--;
|
||||
|
||||
if (index < 0 || ls3_currents[index] < min_uA)
|
||||
return -EINVAL;
|
||||
|
||||
return tps65218_set_bits(tps, dev->desc->csel_reg, dev->desc->csel_mask,
|
||||
index << 2, TPS65218_PROTECT_L1);
|
||||
}
|
||||
|
||||
static int tps65218_pmic_get_current_limit(struct regulator_dev *dev)
|
||||
{
|
||||
int retval;
|
||||
unsigned int index;
|
||||
struct tps65218 *tps = rdev_get_drvdata(dev);
|
||||
|
||||
retval = tps65218_reg_read(tps, dev->desc->csel_reg, &index);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
index = (index & dev->desc->csel_mask) >> 2;
|
||||
|
||||
return ls3_currents[index];
|
||||
}
|
||||
|
||||
static struct regulator_ops tps65218_ls3_ops = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = tps65218_pmic_enable,
|
||||
.disable = tps65218_pmic_disable,
|
||||
.set_input_current_limit = tps65218_pmic_set_input_current_lim,
|
||||
.set_current_limit = tps65218_pmic_set_current_limit,
|
||||
.get_current_limit = tps65218_pmic_get_current_limit,
|
||||
};
|
||||
|
||||
/* Operations permitted on DCDC5, DCDC6 */
|
||||
static struct regulator_ops tps65218_dcdc56_pmic_ops = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
@ -183,36 +250,46 @@ static struct regulator_ops tps65218_dcdc56_pmic_ops = {
|
||||
};
|
||||
|
||||
static const struct regulator_desc regulators[] = {
|
||||
TPS65218_REGULATOR("DCDC1", TPS65218_DCDC_1, tps65218_dcdc12_ops, 64,
|
||||
TPS65218_REG_CONTROL_DCDC1,
|
||||
TPS65218_CONTROL_DCDC1_MASK,
|
||||
TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC1_EN,
|
||||
dcdc1_dcdc2_ranges, 2, 4000, 0),
|
||||
TPS65218_REGULATOR("DCDC2", TPS65218_DCDC_2, tps65218_dcdc12_ops, 64,
|
||||
TPS65218_REG_CONTROL_DCDC2,
|
||||
TPS65218_CONTROL_DCDC2_MASK,
|
||||
TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC2_EN,
|
||||
dcdc1_dcdc2_ranges, 2, 4000, 0),
|
||||
TPS65218_REGULATOR("DCDC3", TPS65218_DCDC_3, tps65218_ldo1_dcdc34_ops,
|
||||
64, TPS65218_REG_CONTROL_DCDC3,
|
||||
TPS65218_REGULATOR("DCDC1", TPS65218_DCDC_1, REGULATOR_VOLTAGE,
|
||||
tps65218_dcdc12_ops, 64, TPS65218_REG_CONTROL_DCDC1,
|
||||
TPS65218_CONTROL_DCDC1_MASK, TPS65218_REG_ENABLE1,
|
||||
TPS65218_ENABLE1_DC1_EN, 0, 0, dcdc1_dcdc2_ranges,
|
||||
2, 4000, 0),
|
||||
TPS65218_REGULATOR("DCDC2", TPS65218_DCDC_2, REGULATOR_VOLTAGE,
|
||||
tps65218_dcdc12_ops, 64, TPS65218_REG_CONTROL_DCDC2,
|
||||
TPS65218_CONTROL_DCDC2_MASK, TPS65218_REG_ENABLE1,
|
||||
TPS65218_ENABLE1_DC2_EN, 0, 0, dcdc1_dcdc2_ranges,
|
||||
2, 4000, 0),
|
||||
TPS65218_REGULATOR("DCDC3", TPS65218_DCDC_3, REGULATOR_VOLTAGE,
|
||||
tps65218_ldo1_dcdc34_ops, 64,
|
||||
TPS65218_REG_CONTROL_DCDC3,
|
||||
TPS65218_CONTROL_DCDC3_MASK, TPS65218_REG_ENABLE1,
|
||||
TPS65218_ENABLE1_DC3_EN, ldo1_dcdc3_ranges, 2, 0, 0),
|
||||
TPS65218_REGULATOR("DCDC4", TPS65218_DCDC_4, tps65218_ldo1_dcdc34_ops,
|
||||
53, TPS65218_REG_CONTROL_DCDC4,
|
||||
TPS65218_CONTROL_DCDC4_MASK,
|
||||
TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC4_EN,
|
||||
dcdc4_ranges, 2, 0, 0),
|
||||
TPS65218_REGULATOR("DCDC5", TPS65218_DCDC_5, tps65218_dcdc56_pmic_ops,
|
||||
1, -1, -1, TPS65218_REG_ENABLE1,
|
||||
TPS65218_ENABLE1_DC5_EN, NULL, 0, 0, 1000000),
|
||||
TPS65218_REGULATOR("DCDC6", TPS65218_DCDC_6, tps65218_dcdc56_pmic_ops,
|
||||
1, -1, -1, TPS65218_REG_ENABLE1,
|
||||
TPS65218_ENABLE1_DC6_EN, NULL, 0, 0, 1800000),
|
||||
TPS65218_REGULATOR("LDO1", TPS65218_LDO_1, tps65218_ldo1_dcdc34_ops, 64,
|
||||
TPS65218_ENABLE1_DC3_EN, 0, 0, ldo1_dcdc3_ranges, 2,
|
||||
0, 0),
|
||||
TPS65218_REGULATOR("DCDC4", TPS65218_DCDC_4, REGULATOR_VOLTAGE,
|
||||
tps65218_ldo1_dcdc34_ops, 53,
|
||||
TPS65218_REG_CONTROL_DCDC4,
|
||||
TPS65218_CONTROL_DCDC4_MASK, TPS65218_REG_ENABLE1,
|
||||
TPS65218_ENABLE1_DC4_EN, 0, 0, dcdc4_ranges, 2,
|
||||
0, 0),
|
||||
TPS65218_REGULATOR("DCDC5", TPS65218_DCDC_5, REGULATOR_VOLTAGE,
|
||||
tps65218_dcdc56_pmic_ops, 1, -1, -1,
|
||||
TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC5_EN, 0, 0,
|
||||
NULL, 0, 0, 1000000),
|
||||
TPS65218_REGULATOR("DCDC6", TPS65218_DCDC_6, REGULATOR_VOLTAGE,
|
||||
tps65218_dcdc56_pmic_ops, 1, -1, -1,
|
||||
TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC6_EN, 0, 0,
|
||||
NULL, 0, 0, 1800000),
|
||||
TPS65218_REGULATOR("LDO1", TPS65218_LDO_1, REGULATOR_VOLTAGE,
|
||||
tps65218_ldo1_dcdc34_ops, 64,
|
||||
TPS65218_REG_CONTROL_LDO1,
|
||||
TPS65218_CONTROL_LDO1_MASK, TPS65218_REG_ENABLE2,
|
||||
TPS65218_ENABLE2_LDO1_EN, ldo1_dcdc3_ranges,
|
||||
TPS65218_ENABLE2_LDO1_EN, 0, 0, ldo1_dcdc3_ranges,
|
||||
2, 0, 0),
|
||||
TPS65218_REGULATOR("LS3", TPS65218_LS_3, REGULATOR_CURRENT,
|
||||
tps65218_ls3_ops, 0, 0, 0, TPS65218_REG_ENABLE2,
|
||||
TPS65218_ENABLE2_LS3_EN, TPS65218_REG_CONFIG2,
|
||||
TPS65218_CONFIG2_LS3ILIM_MASK, NULL, 0, 0, 0),
|
||||
};
|
||||
|
||||
static int tps65218_regulator_probe(struct platform_device *pdev)
|
||||
|
@ -365,7 +365,7 @@ static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev)
|
||||
return wm831x_dcdc_ilim[val];
|
||||
}
|
||||
|
||||
static struct regulator_ops wm831x_buckv_ops = {
|
||||
static const struct regulator_ops wm831x_buckv_ops = {
|
||||
.set_voltage_sel = wm831x_buckv_set_voltage_sel,
|
||||
.get_voltage_sel = wm831x_buckv_get_voltage_sel,
|
||||
.list_voltage = wm831x_buckv_list_voltage,
|
||||
@ -585,7 +585,7 @@ static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev, int uV)
|
||||
return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, sel);
|
||||
}
|
||||
|
||||
static struct regulator_ops wm831x_buckp_ops = {
|
||||
static const struct regulator_ops wm831x_buckp_ops = {
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
@ -725,7 +725,7 @@ static int wm831x_boostp_get_status(struct regulator_dev *rdev)
|
||||
return REGULATOR_STATUS_OFF;
|
||||
}
|
||||
|
||||
static struct regulator_ops wm831x_boostp_ops = {
|
||||
static const struct regulator_ops wm831x_boostp_ops = {
|
||||
.get_status = wm831x_boostp_get_status,
|
||||
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
@ -818,7 +818,7 @@ static struct platform_driver wm831x_boostp_driver = {
|
||||
|
||||
#define WM831X_EPE_BASE 6
|
||||
|
||||
static struct regulator_ops wm831x_epe_ops = {
|
||||
static const struct regulator_ops wm831x_epe_ops = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
@ -884,35 +884,22 @@ static struct platform_driver wm831x_epe_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_driver * const drivers[] = {
|
||||
&wm831x_buckv_driver,
|
||||
&wm831x_buckp_driver,
|
||||
&wm831x_boostp_driver,
|
||||
&wm831x_epe_driver,
|
||||
};
|
||||
|
||||
static int __init wm831x_dcdc_init(void)
|
||||
{
|
||||
int ret;
|
||||
ret = platform_driver_register(&wm831x_buckv_driver);
|
||||
if (ret != 0)
|
||||
pr_err("Failed to register WM831x BUCKV driver: %d\n", ret);
|
||||
|
||||
ret = platform_driver_register(&wm831x_buckp_driver);
|
||||
if (ret != 0)
|
||||
pr_err("Failed to register WM831x BUCKP driver: %d\n", ret);
|
||||
|
||||
ret = platform_driver_register(&wm831x_boostp_driver);
|
||||
if (ret != 0)
|
||||
pr_err("Failed to register WM831x BOOST driver: %d\n", ret);
|
||||
|
||||
ret = platform_driver_register(&wm831x_epe_driver);
|
||||
if (ret != 0)
|
||||
pr_err("Failed to register WM831x EPE driver: %d\n", ret);
|
||||
|
||||
return 0;
|
||||
return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
|
||||
}
|
||||
subsys_initcall(wm831x_dcdc_init);
|
||||
|
||||
static void __exit wm831x_dcdc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&wm831x_epe_driver);
|
||||
platform_driver_unregister(&wm831x_boostp_driver);
|
||||
platform_driver_unregister(&wm831x_buckp_driver);
|
||||
platform_driver_unregister(&wm831x_buckv_driver);
|
||||
platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
|
||||
}
|
||||
module_exit(wm831x_dcdc_exit);
|
||||
|
||||
|
@ -128,7 +128,7 @@ static int wm831x_isink_get_current(struct regulator_dev *rdev)
|
||||
return wm831x_isinkv_values[ret];
|
||||
}
|
||||
|
||||
static struct regulator_ops wm831x_isink_ops = {
|
||||
static const struct regulator_ops wm831x_isink_ops = {
|
||||
.is_enabled = wm831x_isink_is_enabled,
|
||||
.enable = wm831x_isink_enable,
|
||||
.disable = wm831x_isink_disable,
|
||||
|
@ -198,7 +198,7 @@ static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev,
|
||||
}
|
||||
|
||||
|
||||
static struct regulator_ops wm831x_gp_ldo_ops = {
|
||||
static const struct regulator_ops wm831x_gp_ldo_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear_range,
|
||||
.map_voltage = regulator_map_voltage_linear_range,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
@ -409,7 +409,7 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev)
|
||||
return regulator_mode_to_status(ret);
|
||||
}
|
||||
|
||||
static struct regulator_ops wm831x_aldo_ops = {
|
||||
static const struct regulator_ops wm831x_aldo_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear_range,
|
||||
.map_voltage = regulator_map_voltage_linear_range,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
@ -557,7 +557,7 @@ static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev)
|
||||
return REGULATOR_STATUS_OFF;
|
||||
}
|
||||
|
||||
static struct regulator_ops wm831x_alive_ldo_ops = {
|
||||
static const struct regulator_ops wm831x_alive_ldo_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
@ -653,32 +653,21 @@ static struct platform_driver wm831x_alive_ldo_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_driver * const drivers[] = {
|
||||
&wm831x_gp_ldo_driver,
|
||||
&wm831x_aldo_driver,
|
||||
&wm831x_alive_ldo_driver,
|
||||
};
|
||||
|
||||
static int __init wm831x_ldo_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&wm831x_gp_ldo_driver);
|
||||
if (ret != 0)
|
||||
pr_err("Failed to register WM831x GP LDO driver: %d\n", ret);
|
||||
|
||||
ret = platform_driver_register(&wm831x_aldo_driver);
|
||||
if (ret != 0)
|
||||
pr_err("Failed to register WM831x ALDO driver: %d\n", ret);
|
||||
|
||||
ret = platform_driver_register(&wm831x_alive_ldo_driver);
|
||||
if (ret != 0)
|
||||
pr_err("Failed to register WM831x alive LDO driver: %d\n",
|
||||
ret);
|
||||
|
||||
return 0;
|
||||
return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
|
||||
}
|
||||
subsys_initcall(wm831x_ldo_init);
|
||||
|
||||
static void __exit wm831x_ldo_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&wm831x_alive_ldo_driver);
|
||||
platform_driver_unregister(&wm831x_aldo_driver);
|
||||
platform_driver_unregister(&wm831x_gp_ldo_driver);
|
||||
platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
|
||||
}
|
||||
module_exit(wm831x_ldo_exit);
|
||||
|
||||
|
@ -941,7 +941,7 @@ static unsigned int wm8350_dcdc_get_optimum_mode(struct regulator_dev *rdev,
|
||||
return mode;
|
||||
}
|
||||
|
||||
static struct regulator_ops wm8350_dcdc_ops = {
|
||||
static const struct regulator_ops wm8350_dcdc_ops = {
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
@ -958,7 +958,7 @@ static struct regulator_ops wm8350_dcdc_ops = {
|
||||
.set_suspend_mode = wm8350_dcdc_set_suspend_mode,
|
||||
};
|
||||
|
||||
static struct regulator_ops wm8350_dcdc2_5_ops = {
|
||||
static const struct regulator_ops wm8350_dcdc2_5_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
@ -966,7 +966,7 @@ static struct regulator_ops wm8350_dcdc2_5_ops = {
|
||||
.set_suspend_disable = wm8350_dcdc25_set_suspend_disable,
|
||||
};
|
||||
|
||||
static struct regulator_ops wm8350_ldo_ops = {
|
||||
static const struct regulator_ops wm8350_ldo_ops = {
|
||||
.map_voltage = regulator_map_voltage_linear_range,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
@ -980,7 +980,7 @@ static struct regulator_ops wm8350_ldo_ops = {
|
||||
.set_suspend_disable = wm8350_ldo_set_suspend_disable,
|
||||
};
|
||||
|
||||
static struct regulator_ops wm8350_isink_ops = {
|
||||
static const struct regulator_ops wm8350_isink_ops = {
|
||||
.set_current_limit = wm8350_isink_set_current,
|
||||
.get_current_limit = wm8350_isink_get_current,
|
||||
.enable = wm8350_isink_enable,
|
||||
|
@ -24,7 +24,7 @@ static const struct regulator_linear_range wm8400_ldo_ranges[] = {
|
||||
REGULATOR_LINEAR_RANGE(1700000, 15, 31, 100000),
|
||||
};
|
||||
|
||||
static struct regulator_ops wm8400_ldo_ops = {
|
||||
static const struct regulator_ops wm8400_ldo_ops = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
@ -106,7 +106,7 @@ static unsigned int wm8400_dcdc_get_optimum_mode(struct regulator_dev *dev,
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static struct regulator_ops wm8400_dcdc_ops = {
|
||||
static const struct regulator_ops wm8400_dcdc_ops = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
|
@ -36,7 +36,7 @@ struct wm8994_ldo {
|
||||
#define WM8994_LDO1_MAX_SELECTOR 0x7
|
||||
#define WM8994_LDO2_MAX_SELECTOR 0x3
|
||||
|
||||
static struct regulator_ops wm8994_ldo1_ops = {
|
||||
static const struct regulator_ops wm8994_ldo1_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
@ -69,7 +69,7 @@ static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev,
|
||||
}
|
||||
}
|
||||
|
||||
static struct regulator_ops wm8994_ldo2_ops = {
|
||||
static const struct regulator_ops wm8994_ldo2_ops = {
|
||||
.list_voltage = wm8994_ldo2_list_voltage,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
|
@ -200,6 +200,8 @@ enum tps65218_regulator_id {
|
||||
TPS65218_DCDC_4,
|
||||
TPS65218_DCDC_5,
|
||||
TPS65218_DCDC_6,
|
||||
/* LS's */
|
||||
TPS65218_LS_3,
|
||||
/* LDOs */
|
||||
TPS65218_LDO_1,
|
||||
};
|
||||
@ -210,8 +212,11 @@ enum tps65218_regulator_id {
|
||||
#define TPS65218_NUM_DCDC 6
|
||||
/* Number of LDO voltage regulators available */
|
||||
#define TPS65218_NUM_LDO 1
|
||||
/* Number of total LS current regulators available */
|
||||
#define TPS65218_NUM_LS 1
|
||||
/* Number of total regulators available */
|
||||
#define TPS65218_NUM_REGULATOR (TPS65218_NUM_DCDC + TPS65218_NUM_LDO)
|
||||
#define TPS65218_NUM_REGULATOR (TPS65218_NUM_DCDC + TPS65218_NUM_LDO \
|
||||
+ TPS65218_NUM_LS)
|
||||
|
||||
/* Define the TPS65218 IRQ numbers */
|
||||
enum tps65218_irqs {
|
||||
|
@ -140,6 +140,8 @@ struct regulator;
|
||||
*
|
||||
* @supply: The name of the supply. Initialised by the user before
|
||||
* using the bulk regulator APIs.
|
||||
* @optional: The supply should be considered optional. Initialised by the user
|
||||
* before using the bulk regulator APIs.
|
||||
* @consumer: The regulator consumer for the supply. This will be managed
|
||||
* by the bulk API.
|
||||
*
|
||||
@ -149,6 +151,7 @@ struct regulator;
|
||||
*/
|
||||
struct regulator_bulk_data {
|
||||
const char *supply;
|
||||
bool optional;
|
||||
struct regulator *consumer;
|
||||
|
||||
/* private: Internal use */
|
||||
|
@ -302,6 +302,8 @@ struct regulator_desc {
|
||||
|
||||
unsigned int vsel_reg;
|
||||
unsigned int vsel_mask;
|
||||
unsigned int csel_reg;
|
||||
unsigned int csel_mask;
|
||||
unsigned int apply_reg;
|
||||
unsigned int apply_bit;
|
||||
unsigned int enable_reg;
|
||||
|
Loading…
Reference in New Issue
Block a user