Merge tag 'regulator-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator
Pull regulator updates from Mark Brown:
"Lots and lots of fixes from Axel and some others here, plus some
framework enhancements which continue the theme of factoring code out
of the drivers and into the core.
- Initial framework support for GPIO controlled enable signals,
saving a bunch of code in drivers.
- Move fixed regulator enable time and voltage mapping table
specifications to data.
- Used some of the recent framework enhancements to make voltage
change notifications more useful, passing the voltage in as an
argument to the notification.
- Fixed the pattern used for finding individual regulators on a
device to not rely on the node name, supporting the use of multiple
PMICs of the same type in the system.
- New drivers for Maxim MAX77686, TI LP872x and LP8788, Samsung
S2MPS11, and Wolfson Arizona microphone supplies and LDOs."
* tag 'regulator-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (176 commits)
regulator: add new lp8788 regulator driver
regulator: mc13xxx: Remove extern function declaration for mc13xxx_sw_regulator
regulator: tps65910: set input_supply on desc unconditionally
regulator: palmas: Fix calcuating selector in palmas_map_voltage_smps
regulator: lp872x: Simplify implementation of lp872x_find_regulator_init_data()
regulator: twl: Fix list_voltate for twl6030ldo_ops
regulator: twl: Convert twl6030ldo_ops to [get|set]_voltage_sel
regulator: twl: Fix the formula to calculate vsel and voltage for twl6030ldo
regulator: s5m8767: Properly handle gpio_request failure
regulator: max8997: Properly handle gpio_request failure
regulator: tps62360: use devm_* for gpio request
regulator: tps6586x: add support for input supply
regulator: tps65217: Add device tree support
regulator: aat2870: Remove unused min_uV and max_uV from struct aat2870_regulator
regulator: aat2870: Convert to regulator_list_voltage_table
regulator: da9052: initialize of_node param for regulator register
regulator: Add REGULATOR_STATUS_UNDEFINED.
regulator: Fix a typo in regulator_mode_to_status() core function.
regulator: s2mps11: Use sec_reg_write rather than sec_reg_update when mask is 0xff
regulator: s2mps11: Fix wrong setting for config.dev
...
This commit is contained in:
@@ -17,18 +17,46 @@ Required properties:
|
||||
device need to be present. The definition for each of these nodes is defined
|
||||
using the standard binding for regulators found at
|
||||
Documentation/devicetree/bindings/regulator/regulator.txt.
|
||||
The regulator is matched with the regulator-compatible.
|
||||
|
||||
The valid names for regulators are:
|
||||
The valid regulator-compatible values are:
|
||||
tps65910: vrtc, vio, vdd1, vdd2, vdd3, vdig1, vdig2, vpll, vdac, vaux1,
|
||||
vaux2, vaux33, vmmc
|
||||
tps65911: vrtc, vio, vdd1, vdd3, vddctrl, ldo1, ldo2, ldo3, ldo4, ldo5,
|
||||
ldo6, ldo7, ldo8
|
||||
|
||||
- xxx-supply: Input voltage supply regulator.
|
||||
These entries are require if regulators are enabled for a device. Missing of these
|
||||
properties can cause the regulator registration fails.
|
||||
If some of input supply is powered through battery or always-on supply then
|
||||
also it is require to have these parameters with proper node handle of always
|
||||
on power supply.
|
||||
tps65910:
|
||||
vcc1-supply: VDD1 input.
|
||||
vcc2-supply: VDD2 input.
|
||||
vcc3-supply: VAUX33 and VMMC input.
|
||||
vcc4-supply: VAUX1 and VAUX2 input.
|
||||
vcc5-supply: VPLL and VDAC input.
|
||||
vcc6-supply: VDIG1 and VDIG2 input.
|
||||
vcc7-supply: VRTC input.
|
||||
vccio-supply: VIO input.
|
||||
tps65911:
|
||||
vcc1-supply: VDD1 input.
|
||||
vcc2-supply: VDD2 input.
|
||||
vcc3-supply: LDO6, LDO7 and LDO8 input.
|
||||
vcc4-supply: LDO5 input.
|
||||
vcc5-supply: LDO3 and LDO4 input.
|
||||
vcc6-supply: LDO1 and LDO2 input.
|
||||
vcc7-supply: VRTC input.
|
||||
vccio-supply: VIO input.
|
||||
|
||||
Optional properties:
|
||||
- ti,vmbch-threshold: (tps65911) main battery charged threshold
|
||||
comparator. (see VMBCH_VSEL in TPS65910 datasheet)
|
||||
- ti,vmbch2-threshold: (tps65911) main battery discharged threshold
|
||||
comparator. (see VMBCH_VSEL in TPS65910 datasheet)
|
||||
- ti,en-ck32k-xtal: enable external 32-kHz crystal oscillator (see CK32K_CTRL
|
||||
in TPS6591X datasheet)
|
||||
- ti,en-gpio-sleep: enable sleep control for gpios
|
||||
There should be 9 entries here, one for each gpio.
|
||||
|
||||
@@ -56,74 +84,110 @@ Example:
|
||||
|
||||
ti,en-gpio-sleep = <0 0 1 0 0 0 0 0 0>;
|
||||
|
||||
vcc1-supply = <®_parent>;
|
||||
vcc2-supply = <&some_reg>;
|
||||
vcc3-supply = <...>;
|
||||
vcc4-supply = <...>;
|
||||
vcc5-supply = <...>;
|
||||
vcc6-supply = <...>;
|
||||
vcc7-supply = <...>;
|
||||
vccio-supply = <...>;
|
||||
|
||||
regulators {
|
||||
vdd1_reg: vdd1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
vdd1_reg: regulator@0 {
|
||||
regulator-compatible = "vdd1";
|
||||
reg = <0>;
|
||||
regulator-min-microvolt = < 600000>;
|
||||
regulator-max-microvolt = <1500000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
ti,regulator-ext-sleep-control = <0>;
|
||||
};
|
||||
vdd2_reg: vdd2 {
|
||||
vdd2_reg: regulator@1 {
|
||||
regulator-compatible = "vdd2";
|
||||
reg = <1>;
|
||||
regulator-min-microvolt = < 600000>;
|
||||
regulator-max-microvolt = <1500000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
ti,regulator-ext-sleep-control = <4>;
|
||||
};
|
||||
vddctrl_reg: vddctrl {
|
||||
vddctrl_reg: regulator@2 {
|
||||
regulator-compatible = "vddctrl";
|
||||
reg = <2>;
|
||||
regulator-min-microvolt = < 600000>;
|
||||
regulator-max-microvolt = <1400000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
ti,regulator-ext-sleep-control = <0>;
|
||||
};
|
||||
vio_reg: vio {
|
||||
vio_reg: regulator@3 {
|
||||
regulator-compatible = "vio";
|
||||
reg = <3>;
|
||||
regulator-min-microvolt = <1500000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
ti,regulator-ext-sleep-control = <1>;
|
||||
};
|
||||
ldo1_reg: ldo1 {
|
||||
ldo1_reg: regulator@4 {
|
||||
regulator-compatible = "ldo1";
|
||||
reg = <4>;
|
||||
regulator-min-microvolt = <1000000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
ti,regulator-ext-sleep-control = <0>;
|
||||
};
|
||||
ldo2_reg: ldo2 {
|
||||
ldo2_reg: regulator@5 {
|
||||
regulator-compatible = "ldo2";
|
||||
reg = <5>;
|
||||
regulator-min-microvolt = <1050000>;
|
||||
regulator-max-microvolt = <1050000>;
|
||||
ti,regulator-ext-sleep-control = <0>;
|
||||
};
|
||||
ldo3_reg: ldo3 {
|
||||
ldo3_reg: regulator@6 {
|
||||
regulator-compatible = "ldo3";
|
||||
reg = <6>;
|
||||
regulator-min-microvolt = <1000000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
ti,regulator-ext-sleep-control = <0>;
|
||||
};
|
||||
ldo4_reg: ldo4 {
|
||||
ldo4_reg: regulator@7 {
|
||||
regulator-compatible = "ldo4";
|
||||
reg = <7>;
|
||||
regulator-min-microvolt = <1000000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
ti,regulator-ext-sleep-control = <0>;
|
||||
};
|
||||
ldo5_reg: ldo5 {
|
||||
ldo5_reg: regulator@8 {
|
||||
regulator-compatible = "ldo5";
|
||||
reg = <8>;
|
||||
regulator-min-microvolt = <1000000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
ti,regulator-ext-sleep-control = <0>;
|
||||
};
|
||||
ldo6_reg: ldo6 {
|
||||
ldo6_reg: regulator@9 {
|
||||
regulator-compatible = "ldo6";
|
||||
reg = <9>;
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
ti,regulator-ext-sleep-control = <0>;
|
||||
};
|
||||
ldo7_reg: ldo7 {
|
||||
ldo7_reg: regulator@10 {
|
||||
regulator-compatible = "ldo7";
|
||||
reg = <10>;
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
ti,regulator-ext-sleep-control = <1>;
|
||||
};
|
||||
ldo8_reg: ldo8 {
|
||||
ldo8_reg: regulator@11 {
|
||||
regulator-compatible = "ldo8";
|
||||
reg = <11>;
|
||||
regulator-min-microvolt = <1000000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
|
||||
@@ -10,6 +10,7 @@ Optional properties:
|
||||
If this property is missing, the default assumed is Active low.
|
||||
- gpio-open-drain: GPIO is open drain type.
|
||||
If this property is missing then default assumption is false.
|
||||
-vin-supply: Input supply name.
|
||||
|
||||
Any property defined as part of the core regulator
|
||||
binding, defined in regulator.txt, can also be used.
|
||||
@@ -29,4 +30,5 @@ Example:
|
||||
enable-active-high;
|
||||
regulator-boot-on;
|
||||
gpio-open-drain;
|
||||
vin-supply = <&parent_reg>;
|
||||
};
|
||||
|
||||
@@ -10,6 +10,11 @@ Optional properties:
|
||||
- regulator-always-on: boolean, regulator should never be disabled
|
||||
- regulator-boot-on: bootloader/firmware enabled regulator
|
||||
- <name>-supply: phandle to the parent supply/regulator node
|
||||
- regulator-ramp-delay: ramp delay for regulator(in uV/uS)
|
||||
- regulator-compatible: If a regulator chip contains multiple
|
||||
regulators, and if the chip's binding contains a child node that
|
||||
describes each regulator, then this property indicates which regulator
|
||||
this child node is intended to configure.
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
TPS65217 family of regulators
|
||||
|
||||
Required properties:
|
||||
- compatible: "ti,tps65217"
|
||||
- reg: I2C slave address
|
||||
- regulators: list of regulators provided by this controller, must be named
|
||||
after their hardware counterparts: dcdc[1-3] and ldo[1-4]
|
||||
- regulators: This is the list of child nodes that specify the regulator
|
||||
initialization data for defined regulators. Not all regulators for the given
|
||||
device need to be present. The definition for each of these nodes is defined
|
||||
using the standard binding for regulators found at
|
||||
Documentation/devicetree/bindings/regulator/regulator.txt.
|
||||
|
||||
The valid names for regulators are:
|
||||
tps65217: dcdc1, dcdc2, dcdc3, ldo1, ldo2, ldo3 and ldo4
|
||||
|
||||
Each regulator is defined using the standard binding for regulators.
|
||||
|
||||
Example:
|
||||
|
||||
tps: tps@24 {
|
||||
compatible = "ti,tps65217";
|
||||
|
||||
regulators {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
dcdc1_reg: regulator@0 {
|
||||
reg = <0>;
|
||||
regulator-compatible = "dcdc1";
|
||||
regulator-min-microvolt = <900000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
dcdc2_reg: regulator@1 {
|
||||
reg = <1>;
|
||||
regulator-compatible = "dcdc2";
|
||||
regulator-min-microvolt = <900000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
dcdc3_reg: regulator@2 {
|
||||
reg = <2>;
|
||||
regulator-compatible = "dcdc3";
|
||||
regulator-min-microvolt = <900000>;
|
||||
regulator-max-microvolt = <1500000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
ldo1_reg: regulator@3 {
|
||||
reg = <3>;
|
||||
regulator-compatible = "ldo1";
|
||||
regulator-min-microvolt = <1000000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
ldo2_reg: regulator@4 {
|
||||
reg = <4>;
|
||||
regulator-compatible = "ldo2";
|
||||
regulator-min-microvolt = <900000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
ldo3_reg: regulator@5 {
|
||||
reg = <5>;
|
||||
regulator-compatible = "ldo3";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
ldo4_reg: regulator@6 {
|
||||
reg = <6>;
|
||||
regulator-compatible = "ldo4";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -6,8 +6,17 @@ Required properties:
|
||||
- interrupts: the interrupt outputs of the controller
|
||||
- #gpio-cells: number of cells to describe a GPIO
|
||||
- gpio-controller: mark the device as a GPIO controller
|
||||
- regulators: list of regulators provided by this controller, must be named
|
||||
after their hardware counterparts: sm[0-2], ldo[0-9] and ldo_rtc
|
||||
- regulators: list of regulators provided by this controller, must have
|
||||
property "regulator-compatible" to match their hardware counterparts:
|
||||
sm[0-2], ldo[0-9] and ldo_rtc
|
||||
- sm0-supply: The input supply for the SM0.
|
||||
- sm1-supply: The input supply for the SM1.
|
||||
- sm2-supply: The input supply for the SM2.
|
||||
- vinldo01-supply: The input supply for the LDO1 and LDO2
|
||||
- vinldo23-supply: The input supply for the LDO2 and LDO3
|
||||
- vinldo4-supply: The input supply for the LDO4
|
||||
- vinldo678-supply: The input supply for the LDO6, LDO7 and LDO8
|
||||
- vinldo9-supply: The input supply for the LDO9
|
||||
|
||||
Each regulator is defined using the standard binding for regulators.
|
||||
|
||||
@@ -21,75 +30,113 @@ Example:
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
|
||||
sm0-supply = <&some_reg>;
|
||||
sm1-supply = <&some_reg>;
|
||||
sm2-supply = <&some_reg>;
|
||||
vinldo01-supply = <...>;
|
||||
vinldo23-supply = <...>;
|
||||
vinldo4-supply = <...>;
|
||||
vinldo678-supply = <...>;
|
||||
vinldo9-supply = <...>;
|
||||
|
||||
regulators {
|
||||
sm0_reg: sm0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
sm0_reg: regulator@0 {
|
||||
reg = <0>;
|
||||
regulator-compatible = "sm0";
|
||||
regulator-min-microvolt = < 725000>;
|
||||
regulator-max-microvolt = <1500000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
sm1_reg: sm1 {
|
||||
sm1_reg: regulator@1 {
|
||||
reg = <1>;
|
||||
regulator-compatible = "sm1";
|
||||
regulator-min-microvolt = < 725000>;
|
||||
regulator-max-microvolt = <1500000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
sm2_reg: sm2 {
|
||||
sm2_reg: regulator@2 {
|
||||
reg = <2>;
|
||||
regulator-compatible = "sm2";
|
||||
regulator-min-microvolt = <3000000>;
|
||||
regulator-max-microvolt = <4550000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
ldo0_reg: ldo0 {
|
||||
ldo0_reg: regulator@3 {
|
||||
reg = <3>;
|
||||
regulator-compatible = "ldo0";
|
||||
regulator-name = "PCIE CLK";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
ldo1_reg: ldo1 {
|
||||
ldo1_reg: regulator@4 {
|
||||
reg = <4>;
|
||||
regulator-compatible = "ldo1";
|
||||
regulator-min-microvolt = < 725000>;
|
||||
regulator-max-microvolt = <1500000>;
|
||||
};
|
||||
|
||||
ldo2_reg: ldo2 {
|
||||
ldo2_reg: regulator@5 {
|
||||
reg = <5>;
|
||||
regulator-compatible = "ldo2";
|
||||
regulator-min-microvolt = < 725000>;
|
||||
regulator-max-microvolt = <1500000>;
|
||||
};
|
||||
|
||||
ldo3_reg: ldo3 {
|
||||
ldo3_reg: regulator@6 {
|
||||
reg = <6>;
|
||||
regulator-compatible = "ldo3";
|
||||
regulator-min-microvolt = <1250000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
ldo4_reg: ldo4 {
|
||||
ldo4_reg: regulator@7 {
|
||||
reg = <7>;
|
||||
regulator-compatible = "ldo4";
|
||||
regulator-min-microvolt = <1700000>;
|
||||
regulator-max-microvolt = <2475000>;
|
||||
};
|
||||
|
||||
ldo5_reg: ldo5 {
|
||||
ldo5_reg: regulator@8 {
|
||||
reg = <8>;
|
||||
regulator-compatible = "ldo5";
|
||||
regulator-min-microvolt = <1250000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
ldo6_reg: ldo6 {
|
||||
ldo6_reg: regulator@9 {
|
||||
reg = <9>;
|
||||
regulator-compatible = "ldo6";
|
||||
regulator-min-microvolt = <1250000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
ldo7_reg: ldo7 {
|
||||
ldo7_reg: regulator@10 {
|
||||
reg = <10>;
|
||||
regulator-compatible = "ldo7";
|
||||
regulator-min-microvolt = <1250000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
ldo8_reg: ldo8 {
|
||||
ldo8_reg: regulator@11 {
|
||||
reg = <11>;
|
||||
regulator-compatible = "ldo8";
|
||||
regulator-min-microvolt = <1250000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
ldo9_reg: ldo9 {
|
||||
ldo9_reg: regulator@12 {
|
||||
reg = <12>;
|
||||
regulator-compatible = "ldo9";
|
||||
regulator-min-microvolt = <1250000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
@@ -15,7 +15,6 @@ For twl6030 regulators/LDOs
|
||||
- "ti,twl6030-vusb" for VUSB LDO
|
||||
- "ti,twl6030-v1v8" for V1V8 LDO
|
||||
- "ti,twl6030-v2v1" for V2V1 LDO
|
||||
- "ti,twl6030-clk32kg" for CLK32KG RESOURCE
|
||||
- "ti,twl6030-vdd1" for VDD1 SMPS
|
||||
- "ti,twl6030-vdd2" for VDD2 SMPS
|
||||
- "ti,twl6030-vdd3" for VDD3 SMPS
|
||||
|
||||
@@ -206,62 +206,74 @@
|
||||
|
||||
// DB8500_REGULATOR_VAPE
|
||||
db8500_vape_reg: db8500_vape {
|
||||
regulator-compatible = "db8500_vape";
|
||||
regulator-name = "db8500-vape";
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
// DB8500_REGULATOR_VARM
|
||||
db8500_varm_reg: db8500_varm {
|
||||
regulator-compatible = "db8500_varm";
|
||||
regulator-name = "db8500-varm";
|
||||
};
|
||||
|
||||
// DB8500_REGULATOR_VMODEM
|
||||
db8500_vmodem_reg: db8500_vmodem {
|
||||
regulator-compatible = "db8500_vmodem";
|
||||
regulator-name = "db8500-vmodem";
|
||||
};
|
||||
|
||||
// DB8500_REGULATOR_VPLL
|
||||
db8500_vpll_reg: db8500_vpll {
|
||||
regulator-compatible = "db8500_vpll";
|
||||
regulator-name = "db8500-vpll";
|
||||
};
|
||||
|
||||
// DB8500_REGULATOR_VSMPS1
|
||||
db8500_vsmps1_reg: db8500_vsmps1 {
|
||||
regulator-compatible = "db8500_vsmps1";
|
||||
regulator-name = "db8500-vsmps1";
|
||||
};
|
||||
|
||||
// DB8500_REGULATOR_VSMPS2
|
||||
db8500_vsmps2_reg: db8500_vsmps2 {
|
||||
regulator-compatible = "db8500_vsmps2";
|
||||
regulator-name = "db8500-vsmps2";
|
||||
};
|
||||
|
||||
// DB8500_REGULATOR_VSMPS3
|
||||
db8500_vsmps3_reg: db8500_vsmps3 {
|
||||
regulator-compatible = "db8500_vsmps3";
|
||||
regulator-name = "db8500-vsmps3";
|
||||
};
|
||||
|
||||
// DB8500_REGULATOR_VRF1
|
||||
db8500_vrf1_reg: db8500_vrf1 {
|
||||
regulator-compatible = "db8500_vrf1";
|
||||
regulator-name = "db8500-vrf1";
|
||||
};
|
||||
|
||||
// DB8500_REGULATOR_SWITCH_SVAMMDSP
|
||||
db8500_sva_mmdsp_reg: db8500_sva_mmdsp {
|
||||
regulator-compatible = "db8500_sva_mmdsp";
|
||||
regulator-name = "db8500-sva-mmdsp";
|
||||
};
|
||||
|
||||
// DB8500_REGULATOR_SWITCH_SVAMMDSPRET
|
||||
db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret {
|
||||
regulator-compatible = "db8500_sva_mmdsp_ret";
|
||||
regulator-name = "db8500-sva-mmdsp-ret";
|
||||
};
|
||||
|
||||
// DB8500_REGULATOR_SWITCH_SVAPIPE
|
||||
db8500_sva_pipe_reg: db8500_sva_pipe {
|
||||
regulator-compatible = "db8500_sva_pipe";
|
||||
regulator-name = "db8500_sva_pipe";
|
||||
};
|
||||
|
||||
// DB8500_REGULATOR_SWITCH_SIAMMDSP
|
||||
db8500_sia_mmdsp_reg: db8500_sia_mmdsp {
|
||||
regulator-compatible = "db8500_sia_mmdsp";
|
||||
regulator-name = "db8500_sia_mmdsp";
|
||||
};
|
||||
|
||||
@@ -272,38 +284,45 @@
|
||||
|
||||
// DB8500_REGULATOR_SWITCH_SIAPIPE
|
||||
db8500_sia_pipe_reg: db8500_sia_pipe {
|
||||
regulator-compatible = "db8500_sia_pipe";
|
||||
regulator-name = "db8500-sia-pipe";
|
||||
};
|
||||
|
||||
// DB8500_REGULATOR_SWITCH_SGA
|
||||
db8500_sga_reg: db8500_sga {
|
||||
regulator-compatible = "db8500_sga";
|
||||
regulator-name = "db8500-sga";
|
||||
vin-supply = <&db8500_vape_reg>;
|
||||
};
|
||||
|
||||
// DB8500_REGULATOR_SWITCH_B2R2_MCDE
|
||||
db8500_b2r2_mcde_reg: db8500_b2r2_mcde {
|
||||
regulator-compatible = "db8500_b2r2_mcde";
|
||||
regulator-name = "db8500-b2r2-mcde";
|
||||
vin-supply = <&db8500_vape_reg>;
|
||||
};
|
||||
|
||||
// DB8500_REGULATOR_SWITCH_ESRAM12
|
||||
db8500_esram12_reg: db8500_esram12 {
|
||||
regulator-compatible = "db8500_esram12";
|
||||
regulator-name = "db8500-esram12";
|
||||
};
|
||||
|
||||
// DB8500_REGULATOR_SWITCH_ESRAM12RET
|
||||
db8500_esram12_ret_reg: db8500_esram12_ret {
|
||||
regulator-compatible = "db8500_esram12_ret";
|
||||
regulator-name = "db8500-esram12-ret";
|
||||
};
|
||||
|
||||
// DB8500_REGULATOR_SWITCH_ESRAM34
|
||||
db8500_esram34_reg: db8500_esram34 {
|
||||
regulator-compatible = "db8500_esram34";
|
||||
regulator-name = "db8500-esram34";
|
||||
};
|
||||
|
||||
// DB8500_REGULATOR_SWITCH_ESRAM34RET
|
||||
db8500_esram34_ret_reg: db8500_esram34_ret {
|
||||
regulator-compatible = "db8500_esram34_ret";
|
||||
regulator-name = "db8500-esram34-ret";
|
||||
};
|
||||
};
|
||||
@@ -318,6 +337,7 @@
|
||||
|
||||
// supplies to the display/camera
|
||||
ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
|
||||
regulator-compatible = "ab8500_ldo_aux1";
|
||||
regulator-name = "V-DISPLAY";
|
||||
regulator-min-microvolt = <2500000>;
|
||||
regulator-max-microvolt = <2900000>;
|
||||
@@ -328,6 +348,7 @@
|
||||
|
||||
// supplies to the on-board eMMC
|
||||
ab8500_ldo_aux2_reg: ab8500_ldo_aux2 {
|
||||
regulator-compatible = "ab8500_ldo_aux2";
|
||||
regulator-name = "V-eMMC1";
|
||||
regulator-min-microvolt = <1100000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
@@ -335,6 +356,7 @@
|
||||
|
||||
// supply for VAUX3; SDcard slots
|
||||
ab8500_ldo_aux3_reg: ab8500_ldo_aux3 {
|
||||
regulator-compatible = "ab8500_ldo_aux3";
|
||||
regulator-name = "V-MMC-SD";
|
||||
regulator-min-microvolt = <1100000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
@@ -342,41 +364,49 @@
|
||||
|
||||
// supply for v-intcore12; VINTCORE12 LDO
|
||||
ab8500_ldo_initcore_reg: ab8500_ldo_initcore {
|
||||
regulator-compatible = "ab8500_ldo_initcore";
|
||||
regulator-name = "V-INTCORE";
|
||||
};
|
||||
|
||||
// supply for tvout; gpadc; TVOUT LDO
|
||||
ab8500_ldo_tvout_reg: ab8500_ldo_tvout {
|
||||
regulator-compatible = "ab8500_ldo_tvout";
|
||||
regulator-name = "V-TVOUT";
|
||||
};
|
||||
|
||||
// supply for ab8500-usb; USB LDO
|
||||
ab8500_ldo_usb_reg: ab8500_ldo_usb {
|
||||
regulator-compatible = "ab8500_ldo_usb";
|
||||
regulator-name = "dummy";
|
||||
};
|
||||
|
||||
// supply for ab8500-vaudio; VAUDIO LDO
|
||||
ab8500_ldo_audio_reg: ab8500_ldo_audio {
|
||||
regulator-compatible = "ab8500_ldo_audio";
|
||||
regulator-name = "V-AUD";
|
||||
};
|
||||
|
||||
// supply for v-anamic1 VAMic1-LDO
|
||||
ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 {
|
||||
regulator-compatible = "ab8500_ldo_anamic1";
|
||||
regulator-name = "V-AMIC1";
|
||||
};
|
||||
|
||||
// supply for v-amic2; VAMIC2 LDO; reuse constants for AMIC1
|
||||
ab8500_ldo_amamic2_reg: ab8500_ldo_amamic2 {
|
||||
regulator-compatible = "ab8500_ldo_amamic2";
|
||||
regulator-name = "V-AMIC2";
|
||||
};
|
||||
|
||||
// supply for v-dmic; VDMIC LDO
|
||||
ab8500_ldo_dmic_reg: ab8500_ldo_dmic {
|
||||
regulator-compatible = "ab8500_ldo_dmic";
|
||||
regulator-name = "V-DMIC";
|
||||
};
|
||||
|
||||
// supply for U8500 CSI/DSI; VANA LDO
|
||||
ab8500_ldo_ana_reg: ab8500_ldo_ana {
|
||||
regulator-compatible = "ab8500_ldo_ana";
|
||||
regulator-name = "V-CSI/DSI";
|
||||
};
|
||||
};
|
||||
|
||||
+65
-2
@@ -24,6 +24,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/tps65217.h>
|
||||
@@ -132,6 +133,61 @@ int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tps65217_clear_bits);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct of_regulator_match reg_matches[] = {
|
||||
{ .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 },
|
||||
{ .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 },
|
||||
{ .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 },
|
||||
{ .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 },
|
||||
{ .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 },
|
||||
{ .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 },
|
||||
{ .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 },
|
||||
};
|
||||
|
||||
static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client)
|
||||
{
|
||||
struct device_node *node = client->dev.of_node;
|
||||
struct tps65217_board *pdata;
|
||||
struct device_node *regs;
|
||||
int count = ARRAY_SIZE(reg_matches);
|
||||
int ret, i;
|
||||
|
||||
regs = of_find_node_by_name(node, "regulators");
|
||||
if (!regs)
|
||||
return NULL;
|
||||
|
||||
ret = of_regulator_match(&client->dev, regs, reg_matches, count);
|
||||
of_node_put(regs);
|
||||
if ((ret < 0) || (ret > count))
|
||||
return NULL;
|
||||
|
||||
count = ret;
|
||||
pdata = devm_kzalloc(&client->dev, count * sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (!reg_matches[i].init_data || !reg_matches[i].of_node)
|
||||
continue;
|
||||
|
||||
pdata->tps65217_init_data[i] = reg_matches[i].init_data;
|
||||
pdata->of_node[i] = reg_matches[i].of_node;
|
||||
}
|
||||
|
||||
return pdata;
|
||||
}
|
||||
|
||||
static struct of_device_id tps65217_of_match[] = {
|
||||
{ .compatible = "ti,tps65217", },
|
||||
{ },
|
||||
};
|
||||
#else
|
||||
static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct regmap_config tps65217_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
@@ -141,10 +197,14 @@ static int __devinit tps65217_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *ids)
|
||||
{
|
||||
struct tps65217 *tps;
|
||||
struct regulator_init_data *reg_data;
|
||||
struct tps65217_board *pdata = client->dev.platform_data;
|
||||
int i, ret;
|
||||
unsigned int version;
|
||||
|
||||
if (!pdata && client->dev.of_node)
|
||||
pdata = tps65217_parse_dt(client);
|
||||
|
||||
tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
|
||||
if (!tps)
|
||||
return -ENOMEM;
|
||||
@@ -182,8 +242,9 @@ static int __devinit tps65217_probe(struct i2c_client *client,
|
||||
}
|
||||
|
||||
pdev->dev.parent = tps->dev;
|
||||
platform_device_add_data(pdev, &pdata->tps65217_init_data[i],
|
||||
sizeof(pdata->tps65217_init_data[i]));
|
||||
pdev->dev.of_node = pdata->of_node[i];
|
||||
reg_data = pdata->tps65217_init_data[i];
|
||||
platform_device_add_data(pdev, reg_data, sizeof(*reg_data));
|
||||
tps->regulator_pdev[i] = pdev;
|
||||
|
||||
platform_device_add(pdev);
|
||||
@@ -212,6 +273,8 @@ MODULE_DEVICE_TABLE(i2c, tps65217_id_table);
|
||||
static struct i2c_driver tps65217_driver = {
|
||||
.driver = {
|
||||
.name = "tps65217",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(tps65217_of_match),
|
||||
},
|
||||
.id_table = tps65217_id_table,
|
||||
.probe = tps65217_probe,
|
||||
|
||||
@@ -20,6 +20,7 @@ menuconfig REGULATOR
|
||||
|
||||
If unsure, say no.
|
||||
|
||||
|
||||
if REGULATOR
|
||||
|
||||
config REGULATOR_DEBUG
|
||||
@@ -88,6 +89,13 @@ config REGULATOR_AAT2870
|
||||
If you have a AnalogicTech AAT2870 say Y to enable the
|
||||
regulator driver.
|
||||
|
||||
config REGULATOR_ARIZONA
|
||||
tristate "Wolfson Arizona class devices"
|
||||
depends on MFD_ARIZONA
|
||||
help
|
||||
Support for the regulators found on Wolfson Arizona class
|
||||
devices.
|
||||
|
||||
config REGULATOR_DA903X
|
||||
tristate "Dialog Semiconductor DA9030/DA9034 regulators"
|
||||
depends on PMIC_DA903X
|
||||
@@ -195,6 +203,14 @@ config REGULATOR_MAX8998
|
||||
via I2C bus. The provided regulator is suitable for S3C6410
|
||||
and S5PC1XX chips to control VCC_CORE and VCC_USIM voltages.
|
||||
|
||||
config REGULATOR_MAX77686
|
||||
tristate "Maxim 77686 regulator"
|
||||
depends on MFD_MAX77686
|
||||
help
|
||||
This driver controls a Maxim 77686 regulator
|
||||
via I2C bus. The provided regulator is suitable for
|
||||
Exynos-4 chips to control VARM and VINT voltages.
|
||||
|
||||
config REGULATOR_PCAP
|
||||
tristate "Motorola PCAP2 regulator driver"
|
||||
depends on EZX_PCAP
|
||||
@@ -216,6 +232,19 @@ config REGULATOR_LP3972
|
||||
Say Y here to support the voltage regulators and convertors
|
||||
on National Semiconductors LP3972 PMIC
|
||||
|
||||
config REGULATOR_LP872X
|
||||
bool "TI/National Semiconductor LP8720/LP8725 voltage regulators"
|
||||
depends on I2C=y
|
||||
select REGMAP_I2C
|
||||
help
|
||||
This driver supports LP8720/LP8725 PMIC
|
||||
|
||||
config REGULATOR_LP8788
|
||||
bool "TI LP8788 Power Regulators"
|
||||
depends on MFD_LP8788
|
||||
help
|
||||
This driver supports LP8788 voltage regulator chip.
|
||||
|
||||
config REGULATOR_PCF50633
|
||||
tristate "NXP PCF50633 regulator driver"
|
||||
depends on MFD_PCF50633
|
||||
@@ -233,6 +262,14 @@ config REGULATOR_RC5T583
|
||||
through regulator interface. The device supports multiple DCDC/LDO
|
||||
outputs which can be controlled by i2c communication.
|
||||
|
||||
config REGULATOR_S2MPS11
|
||||
tristate "Samsung S2MPS11 voltage regulator"
|
||||
depends on MFD_SEC_CORE
|
||||
help
|
||||
This driver supports a Samsung S2MPS11 voltage output regulator
|
||||
via I2C bus. S2MPS11 is comprised of high efficient Buck converters
|
||||
including Dual-Phase Buck converter, Buck-Boost converter, various LDOs.
|
||||
|
||||
config REGULATOR_S5M8767
|
||||
tristate "Samsung S5M8767A voltage regulator"
|
||||
depends on MFD_S5M_CORE
|
||||
|
||||
@@ -15,6 +15,7 @@ obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
|
||||
obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
|
||||
obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
|
||||
obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
|
||||
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
|
||||
obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
|
||||
@@ -23,6 +24,9 @@ obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
|
||||
obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o
|
||||
obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o
|
||||
obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o
|
||||
obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o
|
||||
obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
|
||||
obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o
|
||||
obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
|
||||
@@ -30,6 +34,7 @@ obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o
|
||||
obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o
|
||||
obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
|
||||
obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o
|
||||
obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
|
||||
@@ -37,6 +42,7 @@ obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
|
||||
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
|
||||
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
|
||||
|
||||
@@ -33,11 +33,6 @@ struct aat2870_regulator {
|
||||
struct aat2870_data *aat2870;
|
||||
struct regulator_desc desc;
|
||||
|
||||
const int *voltages; /* uV */
|
||||
|
||||
int min_uV;
|
||||
int max_uV;
|
||||
|
||||
u8 enable_addr;
|
||||
u8 enable_shift;
|
||||
u8 enable_mask;
|
||||
@@ -47,14 +42,6 @@ struct aat2870_regulator {
|
||||
u8 voltage_mask;
|
||||
};
|
||||
|
||||
static int aat2870_ldo_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
|
||||
|
||||
return ri->voltages[selector];
|
||||
}
|
||||
|
||||
static int aat2870_ldo_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
@@ -111,7 +98,7 @@ static int aat2870_ldo_is_enabled(struct regulator_dev *rdev)
|
||||
}
|
||||
|
||||
static struct regulator_ops aat2870_ldo_ops = {
|
||||
.list_voltage = aat2870_ldo_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.set_voltage_sel = aat2870_ldo_set_voltage_sel,
|
||||
.get_voltage_sel = aat2870_ldo_get_voltage_sel,
|
||||
.enable = aat2870_ldo_enable,
|
||||
@@ -119,7 +106,7 @@ static struct regulator_ops aat2870_ldo_ops = {
|
||||
.is_enabled = aat2870_ldo_is_enabled,
|
||||
};
|
||||
|
||||
static const int aat2870_ldo_voltages[] = {
|
||||
static const unsigned int aat2870_ldo_voltages[] = {
|
||||
1200000, 1300000, 1500000, 1600000,
|
||||
1800000, 2000000, 2200000, 2500000,
|
||||
2600000, 2700000, 2800000, 2900000,
|
||||
@@ -132,13 +119,11 @@ static const int aat2870_ldo_voltages[] = {
|
||||
.name = #ids, \
|
||||
.id = AAT2870_ID_##ids, \
|
||||
.n_voltages = ARRAY_SIZE(aat2870_ldo_voltages), \
|
||||
.volt_table = aat2870_ldo_voltages, \
|
||||
.ops = &aat2870_ldo_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
}, \
|
||||
.voltages = aat2870_ldo_voltages, \
|
||||
.min_uV = 1200000, \
|
||||
.max_uV = 3300000, \
|
||||
}
|
||||
|
||||
static struct aat2870_regulator aat2870_regulators[] = {
|
||||
|
||||
+40
-79
@@ -43,20 +43,12 @@
|
||||
* @dev: handle to the device
|
||||
* @plfdata: AB3100 platform data passed in at probe time
|
||||
* @regreg: regulator register number in the AB3100
|
||||
* @fixed_voltage: a fixed voltage for this regulator, if this
|
||||
* 0 the voltages array is used instead.
|
||||
* @typ_voltages: an array of available typical voltages for
|
||||
* this regulator
|
||||
* @voltages_len: length of the array of available voltages
|
||||
*/
|
||||
struct ab3100_regulator {
|
||||
struct regulator_dev *rdev;
|
||||
struct device *dev;
|
||||
struct ab3100_platform_data *plfdata;
|
||||
u8 regreg;
|
||||
int fixed_voltage;
|
||||
int const *typ_voltages;
|
||||
u8 voltages_len;
|
||||
};
|
||||
|
||||
/* The order in which registers are initialized */
|
||||
@@ -80,7 +72,7 @@ static const u8 ab3100_reg_init_order[AB3100_NUM_REGULATORS+2] = {
|
||||
#define LDO_C_VOLTAGE 2650000
|
||||
#define LDO_D_VOLTAGE 2650000
|
||||
|
||||
static const int ldo_e_buck_typ_voltages[] = {
|
||||
static const unsigned int ldo_e_buck_typ_voltages[] = {
|
||||
1800000,
|
||||
1400000,
|
||||
1300000,
|
||||
@@ -90,7 +82,7 @@ static const int ldo_e_buck_typ_voltages[] = {
|
||||
900000,
|
||||
};
|
||||
|
||||
static const int ldo_f_typ_voltages[] = {
|
||||
static const unsigned int ldo_f_typ_voltages[] = {
|
||||
1800000,
|
||||
1400000,
|
||||
1300000,
|
||||
@@ -101,21 +93,21 @@ static const int ldo_f_typ_voltages[] = {
|
||||
2650000,
|
||||
};
|
||||
|
||||
static const int ldo_g_typ_voltages[] = {
|
||||
static const unsigned int ldo_g_typ_voltages[] = {
|
||||
2850000,
|
||||
2750000,
|
||||
1800000,
|
||||
1500000,
|
||||
};
|
||||
|
||||
static const int ldo_h_typ_voltages[] = {
|
||||
static const unsigned int ldo_h_typ_voltages[] = {
|
||||
2750000,
|
||||
1800000,
|
||||
1500000,
|
||||
1200000,
|
||||
};
|
||||
|
||||
static const int ldo_k_typ_voltages[] = {
|
||||
static const unsigned int ldo_k_typ_voltages[] = {
|
||||
2750000,
|
||||
1800000,
|
||||
};
|
||||
@@ -126,40 +118,27 @@ static struct ab3100_regulator
|
||||
ab3100_regulators[AB3100_NUM_REGULATORS] = {
|
||||
{
|
||||
.regreg = AB3100_LDO_A,
|
||||
.fixed_voltage = LDO_A_VOLTAGE,
|
||||
},
|
||||
{
|
||||
.regreg = AB3100_LDO_C,
|
||||
.fixed_voltage = LDO_C_VOLTAGE,
|
||||
},
|
||||
{
|
||||
.regreg = AB3100_LDO_D,
|
||||
.fixed_voltage = LDO_D_VOLTAGE,
|
||||
},
|
||||
{
|
||||
.regreg = AB3100_LDO_E,
|
||||
.typ_voltages = ldo_e_buck_typ_voltages,
|
||||
.voltages_len = ARRAY_SIZE(ldo_e_buck_typ_voltages),
|
||||
},
|
||||
{
|
||||
.regreg = AB3100_LDO_F,
|
||||
.typ_voltages = ldo_f_typ_voltages,
|
||||
.voltages_len = ARRAY_SIZE(ldo_f_typ_voltages),
|
||||
},
|
||||
{
|
||||
.regreg = AB3100_LDO_G,
|
||||
.typ_voltages = ldo_g_typ_voltages,
|
||||
.voltages_len = ARRAY_SIZE(ldo_g_typ_voltages),
|
||||
},
|
||||
{
|
||||
.regreg = AB3100_LDO_H,
|
||||
.typ_voltages = ldo_h_typ_voltages,
|
||||
.voltages_len = ARRAY_SIZE(ldo_h_typ_voltages),
|
||||
},
|
||||
{
|
||||
.regreg = AB3100_LDO_K,
|
||||
.typ_voltages = ldo_k_typ_voltages,
|
||||
.voltages_len = ARRAY_SIZE(ldo_k_typ_voltages),
|
||||
},
|
||||
{
|
||||
.regreg = AB3100_LDO_EXT,
|
||||
@@ -167,8 +146,6 @@ ab3100_regulators[AB3100_NUM_REGULATORS] = {
|
||||
},
|
||||
{
|
||||
.regreg = AB3100_BUCK,
|
||||
.typ_voltages = ldo_e_buck_typ_voltages,
|
||||
.voltages_len = ARRAY_SIZE(ldo_e_buck_typ_voltages),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -178,7 +155,7 @@ ab3100_regulators[AB3100_NUM_REGULATORS] = {
|
||||
*/
|
||||
static int ab3100_enable_regulator(struct regulator_dev *reg)
|
||||
{
|
||||
struct ab3100_regulator *abreg = reg->reg_data;
|
||||
struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
|
||||
int err;
|
||||
u8 regval;
|
||||
|
||||
@@ -209,7 +186,7 @@ static int ab3100_enable_regulator(struct regulator_dev *reg)
|
||||
|
||||
static int ab3100_disable_regulator(struct regulator_dev *reg)
|
||||
{
|
||||
struct ab3100_regulator *abreg = reg->reg_data;
|
||||
struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
|
||||
int err;
|
||||
u8 regval;
|
||||
|
||||
@@ -242,7 +219,7 @@ static int ab3100_disable_regulator(struct regulator_dev *reg)
|
||||
|
||||
static int ab3100_is_enabled_regulator(struct regulator_dev *reg)
|
||||
{
|
||||
struct ab3100_regulator *abreg = reg->reg_data;
|
||||
struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
|
||||
u8 regval;
|
||||
int err;
|
||||
|
||||
@@ -257,26 +234,12 @@ static int ab3100_is_enabled_regulator(struct regulator_dev *reg)
|
||||
return regval & AB3100_REG_ON_MASK;
|
||||
}
|
||||
|
||||
static int ab3100_list_voltage_regulator(struct regulator_dev *reg,
|
||||
unsigned selector)
|
||||
{
|
||||
struct ab3100_regulator *abreg = reg->reg_data;
|
||||
|
||||
if (selector >= abreg->voltages_len)
|
||||
return -EINVAL;
|
||||
return abreg->typ_voltages[selector];
|
||||
}
|
||||
|
||||
static int ab3100_get_voltage_regulator(struct regulator_dev *reg)
|
||||
{
|
||||
struct ab3100_regulator *abreg = reg->reg_data;
|
||||
struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
|
||||
u8 regval;
|
||||
int err;
|
||||
|
||||
/* Return the voltage for fixed regulators immediately */
|
||||
if (abreg->fixed_voltage)
|
||||
return abreg->fixed_voltage;
|
||||
|
||||
/*
|
||||
* For variable types, read out setting and index into
|
||||
* supplied voltage list.
|
||||
@@ -294,20 +257,20 @@ static int ab3100_get_voltage_regulator(struct regulator_dev *reg)
|
||||
regval &= 0xE0;
|
||||
regval >>= 5;
|
||||
|
||||
if (regval >= abreg->voltages_len) {
|
||||
if (regval >= reg->desc->n_voltages) {
|
||||
dev_err(®->dev,
|
||||
"regulator register %02x contains an illegal voltage setting\n",
|
||||
abreg->regreg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return abreg->typ_voltages[regval];
|
||||
return reg->desc->volt_table[regval];
|
||||
}
|
||||
|
||||
static int ab3100_set_voltage_regulator_sel(struct regulator_dev *reg,
|
||||
unsigned selector)
|
||||
{
|
||||
struct ab3100_regulator *abreg = reg->reg_data;
|
||||
struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
|
||||
u8 regval;
|
||||
int err;
|
||||
|
||||
@@ -336,7 +299,7 @@ static int ab3100_set_voltage_regulator_sel(struct regulator_dev *reg,
|
||||
static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg,
|
||||
int uV)
|
||||
{
|
||||
struct ab3100_regulator *abreg = reg->reg_data;
|
||||
struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
|
||||
u8 regval;
|
||||
int err;
|
||||
int bestindex;
|
||||
@@ -379,42 +342,22 @@ static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg,
|
||||
*/
|
||||
static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg)
|
||||
{
|
||||
struct ab3100_regulator *abreg = reg->reg_data;
|
||||
struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
|
||||
|
||||
return abreg->plfdata->external_voltage;
|
||||
}
|
||||
|
||||
static int ab3100_enable_time_regulator(struct regulator_dev *reg)
|
||||
static int ab3100_get_fixed_voltage_regulator(struct regulator_dev *reg)
|
||||
{
|
||||
struct ab3100_regulator *abreg = reg->reg_data;
|
||||
|
||||
/* Per-regulator power on delay from spec */
|
||||
switch (abreg->regreg) {
|
||||
case AB3100_LDO_A: /* Fallthrough */
|
||||
case AB3100_LDO_C: /* Fallthrough */
|
||||
case AB3100_LDO_D: /* Fallthrough */
|
||||
case AB3100_LDO_E: /* Fallthrough */
|
||||
case AB3100_LDO_H: /* Fallthrough */
|
||||
case AB3100_LDO_K:
|
||||
return 200;
|
||||
case AB3100_LDO_F:
|
||||
return 600;
|
||||
case AB3100_LDO_G:
|
||||
return 400;
|
||||
case AB3100_BUCK:
|
||||
return 1000;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
return reg->desc->min_uV;
|
||||
}
|
||||
|
||||
static struct regulator_ops regulator_ops_fixed = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.enable = ab3100_enable_regulator,
|
||||
.disable = ab3100_disable_regulator,
|
||||
.is_enabled = ab3100_is_enabled_regulator,
|
||||
.get_voltage = ab3100_get_voltage_regulator,
|
||||
.enable_time = ab3100_enable_time_regulator,
|
||||
.get_voltage = ab3100_get_fixed_voltage_regulator,
|
||||
};
|
||||
|
||||
static struct regulator_ops regulator_ops_variable = {
|
||||
@@ -423,8 +366,7 @@ static struct regulator_ops regulator_ops_variable = {
|
||||
.is_enabled = ab3100_is_enabled_regulator,
|
||||
.get_voltage = ab3100_get_voltage_regulator,
|
||||
.set_voltage_sel = ab3100_set_voltage_regulator_sel,
|
||||
.list_voltage = ab3100_list_voltage_regulator,
|
||||
.enable_time = ab3100_enable_time_regulator,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
};
|
||||
|
||||
static struct regulator_ops regulator_ops_variable_sleepable = {
|
||||
@@ -434,8 +376,7 @@ static struct regulator_ops regulator_ops_variable_sleepable = {
|
||||
.get_voltage = ab3100_get_voltage_regulator,
|
||||
.set_voltage_sel = ab3100_set_voltage_regulator_sel,
|
||||
.set_suspend_voltage = ab3100_set_suspend_voltage_regulator,
|
||||
.list_voltage = ab3100_list_voltage_regulator,
|
||||
.enable_time = ab3100_enable_time_regulator,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -457,62 +398,81 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
|
||||
.name = "LDO_A",
|
||||
.id = AB3100_LDO_A,
|
||||
.ops = ®ulator_ops_fixed,
|
||||
.n_voltages = 1,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.min_uV = LDO_A_VOLTAGE,
|
||||
.enable_time = 200,
|
||||
},
|
||||
{
|
||||
.name = "LDO_C",
|
||||
.id = AB3100_LDO_C,
|
||||
.ops = ®ulator_ops_fixed,
|
||||
.n_voltages = 1,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.min_uV = LDO_C_VOLTAGE,
|
||||
.enable_time = 200,
|
||||
},
|
||||
{
|
||||
.name = "LDO_D",
|
||||
.id = AB3100_LDO_D,
|
||||
.ops = ®ulator_ops_fixed,
|
||||
.n_voltages = 1,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.min_uV = LDO_D_VOLTAGE,
|
||||
.enable_time = 200,
|
||||
},
|
||||
{
|
||||
.name = "LDO_E",
|
||||
.id = AB3100_LDO_E,
|
||||
.ops = ®ulator_ops_variable_sleepable,
|
||||
.n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages),
|
||||
.volt_table = ldo_e_buck_typ_voltages,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_time = 200,
|
||||
},
|
||||
{
|
||||
.name = "LDO_F",
|
||||
.id = AB3100_LDO_F,
|
||||
.ops = ®ulator_ops_variable,
|
||||
.n_voltages = ARRAY_SIZE(ldo_f_typ_voltages),
|
||||
.volt_table = ldo_f_typ_voltages,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_time = 600,
|
||||
},
|
||||
{
|
||||
.name = "LDO_G",
|
||||
.id = AB3100_LDO_G,
|
||||
.ops = ®ulator_ops_variable,
|
||||
.n_voltages = ARRAY_SIZE(ldo_g_typ_voltages),
|
||||
.volt_table = ldo_g_typ_voltages,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_time = 400,
|
||||
},
|
||||
{
|
||||
.name = "LDO_H",
|
||||
.id = AB3100_LDO_H,
|
||||
.ops = ®ulator_ops_variable,
|
||||
.n_voltages = ARRAY_SIZE(ldo_h_typ_voltages),
|
||||
.volt_table = ldo_h_typ_voltages,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_time = 200,
|
||||
},
|
||||
{
|
||||
.name = "LDO_K",
|
||||
.id = AB3100_LDO_K,
|
||||
.ops = ®ulator_ops_variable,
|
||||
.n_voltages = ARRAY_SIZE(ldo_k_typ_voltages),
|
||||
.volt_table = ldo_k_typ_voltages,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_time = 200,
|
||||
},
|
||||
{
|
||||
.name = "LDO_EXT",
|
||||
@@ -528,6 +488,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
|
||||
.n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages),
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_time = 1000,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
+19
-77
@@ -30,9 +30,6 @@
|
||||
* @dev: device pointer
|
||||
* @desc: regulator description
|
||||
* @regulator_dev: regulator device
|
||||
* @max_uV: maximum voltage (for variable voltage supplies)
|
||||
* @min_uV: minimum voltage (for variable voltage supplies)
|
||||
* @fixed_uV: typical voltage (for fixed voltage supplies)
|
||||
* @update_bank: bank to control on/off
|
||||
* @update_reg: register to control on/off
|
||||
* @update_mask: mask to enable/disable regulator
|
||||
@@ -40,17 +37,12 @@
|
||||
* @voltage_bank: bank to control regulator voltage
|
||||
* @voltage_reg: register to control regulator voltage
|
||||
* @voltage_mask: mask to control regulator voltage
|
||||
* @voltages: supported voltage table
|
||||
* @voltages_len: number of supported voltages for the regulator
|
||||
* @delay: startup/set voltage delay in us
|
||||
*/
|
||||
struct ab8500_regulator_info {
|
||||
struct device *dev;
|
||||
struct regulator_desc desc;
|
||||
struct regulator_dev *regulator;
|
||||
int max_uV;
|
||||
int min_uV;
|
||||
int fixed_uV;
|
||||
u8 update_bank;
|
||||
u8 update_reg;
|
||||
u8 update_mask;
|
||||
@@ -58,13 +50,11 @@ struct ab8500_regulator_info {
|
||||
u8 voltage_bank;
|
||||
u8 voltage_reg;
|
||||
u8 voltage_mask;
|
||||
int const *voltages;
|
||||
int voltages_len;
|
||||
unsigned int delay;
|
||||
};
|
||||
|
||||
/* voltage tables for the vauxn/vintcore supplies */
|
||||
static const int ldo_vauxn_voltages[] = {
|
||||
static const unsigned int ldo_vauxn_voltages[] = {
|
||||
1100000,
|
||||
1200000,
|
||||
1300000,
|
||||
@@ -83,7 +73,7 @@ static const int ldo_vauxn_voltages[] = {
|
||||
3300000,
|
||||
};
|
||||
|
||||
static const int ldo_vaux3_voltages[] = {
|
||||
static const unsigned int ldo_vaux3_voltages[] = {
|
||||
1200000,
|
||||
1500000,
|
||||
1800000,
|
||||
@@ -94,7 +84,7 @@ static const int ldo_vaux3_voltages[] = {
|
||||
2910000,
|
||||
};
|
||||
|
||||
static const int ldo_vintcore_voltages[] = {
|
||||
static const unsigned int ldo_vintcore_voltages[] = {
|
||||
1200000,
|
||||
1225000,
|
||||
1250000,
|
||||
@@ -185,25 +175,6 @@ static int ab8500_regulator_is_enabled(struct regulator_dev *rdev)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector)
|
||||
{
|
||||
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
if (info == NULL) {
|
||||
dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* return the uV for the fixed regulators */
|
||||
if (info->fixed_uV)
|
||||
return info->fixed_uV;
|
||||
|
||||
if (selector >= info->voltages_len)
|
||||
return -EINVAL;
|
||||
|
||||
return info->voltages[selector];
|
||||
}
|
||||
|
||||
static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
int ret, val;
|
||||
@@ -279,14 +250,7 @@ static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
|
||||
unsigned int new_sel)
|
||||
{
|
||||
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
/* If the regulator isn't on, it won't take time here */
|
||||
ret = ab8500_regulator_is_enabled(rdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (!ret)
|
||||
return 0;
|
||||
return info->delay;
|
||||
}
|
||||
|
||||
@@ -296,21 +260,14 @@ static struct regulator_ops ab8500_regulator_ops = {
|
||||
.is_enabled = ab8500_regulator_is_enabled,
|
||||
.get_voltage_sel = ab8500_regulator_get_voltage_sel,
|
||||
.set_voltage_sel = ab8500_regulator_set_voltage_sel,
|
||||
.list_voltage = ab8500_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.enable_time = ab8500_regulator_enable_time,
|
||||
.set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
|
||||
};
|
||||
|
||||
static int ab8500_fixed_get_voltage(struct regulator_dev *rdev)
|
||||
{
|
||||
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
if (info == NULL) {
|
||||
dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return info->fixed_uV;
|
||||
return rdev->desc->min_uV;
|
||||
}
|
||||
|
||||
static struct regulator_ops ab8500_regulator_fixed_ops = {
|
||||
@@ -318,9 +275,8 @@ static struct regulator_ops ab8500_regulator_fixed_ops = {
|
||||
.disable = ab8500_regulator_disable,
|
||||
.is_enabled = ab8500_regulator_is_enabled,
|
||||
.get_voltage = ab8500_fixed_get_voltage,
|
||||
.list_voltage = ab8500_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.enable_time = ab8500_regulator_enable_time,
|
||||
.set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
|
||||
};
|
||||
|
||||
static struct ab8500_regulator_info
|
||||
@@ -329,7 +285,7 @@ static struct ab8500_regulator_info
|
||||
* Variable Voltage Regulators
|
||||
* name, min mV, max mV,
|
||||
* update bank, reg, mask, enable val
|
||||
* volt bank, reg, mask, table, table length
|
||||
* volt bank, reg, mask
|
||||
*/
|
||||
[AB8500_LDO_AUX1] = {
|
||||
.desc = {
|
||||
@@ -339,9 +295,8 @@ static struct ab8500_regulator_info
|
||||
.id = AB8500_LDO_AUX1,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = ARRAY_SIZE(ldo_vauxn_voltages),
|
||||
.volt_table = ldo_vauxn_voltages,
|
||||
},
|
||||
.min_uV = 1100000,
|
||||
.max_uV = 3300000,
|
||||
.update_bank = 0x04,
|
||||
.update_reg = 0x09,
|
||||
.update_mask = 0x03,
|
||||
@@ -349,8 +304,6 @@ static struct ab8500_regulator_info
|
||||
.voltage_bank = 0x04,
|
||||
.voltage_reg = 0x1f,
|
||||
.voltage_mask = 0x0f,
|
||||
.voltages = ldo_vauxn_voltages,
|
||||
.voltages_len = ARRAY_SIZE(ldo_vauxn_voltages),
|
||||
},
|
||||
[AB8500_LDO_AUX2] = {
|
||||
.desc = {
|
||||
@@ -360,9 +313,8 @@ static struct ab8500_regulator_info
|
||||
.id = AB8500_LDO_AUX2,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = ARRAY_SIZE(ldo_vauxn_voltages),
|
||||
.volt_table = ldo_vauxn_voltages,
|
||||
},
|
||||
.min_uV = 1100000,
|
||||
.max_uV = 3300000,
|
||||
.update_bank = 0x04,
|
||||
.update_reg = 0x09,
|
||||
.update_mask = 0x0c,
|
||||
@@ -370,8 +322,6 @@ static struct ab8500_regulator_info
|
||||
.voltage_bank = 0x04,
|
||||
.voltage_reg = 0x20,
|
||||
.voltage_mask = 0x0f,
|
||||
.voltages = ldo_vauxn_voltages,
|
||||
.voltages_len = ARRAY_SIZE(ldo_vauxn_voltages),
|
||||
},
|
||||
[AB8500_LDO_AUX3] = {
|
||||
.desc = {
|
||||
@@ -381,9 +331,8 @@ static struct ab8500_regulator_info
|
||||
.id = AB8500_LDO_AUX3,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = ARRAY_SIZE(ldo_vaux3_voltages),
|
||||
.volt_table = ldo_vaux3_voltages,
|
||||
},
|
||||
.min_uV = 1100000,
|
||||
.max_uV = 3300000,
|
||||
.update_bank = 0x04,
|
||||
.update_reg = 0x0a,
|
||||
.update_mask = 0x03,
|
||||
@@ -391,8 +340,6 @@ static struct ab8500_regulator_info
|
||||
.voltage_bank = 0x04,
|
||||
.voltage_reg = 0x21,
|
||||
.voltage_mask = 0x07,
|
||||
.voltages = ldo_vaux3_voltages,
|
||||
.voltages_len = ARRAY_SIZE(ldo_vaux3_voltages),
|
||||
},
|
||||
[AB8500_LDO_INTCORE] = {
|
||||
.desc = {
|
||||
@@ -402,9 +349,8 @@ static struct ab8500_regulator_info
|
||||
.id = AB8500_LDO_INTCORE,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = ARRAY_SIZE(ldo_vintcore_voltages),
|
||||
.volt_table = ldo_vintcore_voltages,
|
||||
},
|
||||
.min_uV = 1100000,
|
||||
.max_uV = 3300000,
|
||||
.update_bank = 0x03,
|
||||
.update_reg = 0x80,
|
||||
.update_mask = 0x44,
|
||||
@@ -412,8 +358,6 @@ static struct ab8500_regulator_info
|
||||
.voltage_bank = 0x03,
|
||||
.voltage_reg = 0x80,
|
||||
.voltage_mask = 0x38,
|
||||
.voltages = ldo_vintcore_voltages,
|
||||
.voltages_len = ARRAY_SIZE(ldo_vintcore_voltages),
|
||||
},
|
||||
|
||||
/*
|
||||
@@ -429,9 +373,9 @@ static struct ab8500_regulator_info
|
||||
.id = AB8500_LDO_TVOUT,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = 1,
|
||||
.min_uV = 2000000,
|
||||
},
|
||||
.delay = 10000,
|
||||
.fixed_uV = 2000000,
|
||||
.update_bank = 0x03,
|
||||
.update_reg = 0x80,
|
||||
.update_mask = 0x82,
|
||||
@@ -445,8 +389,8 @@ static struct ab8500_regulator_info
|
||||
.id = AB8500_LDO_USB,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = 1,
|
||||
.min_uV = 3300000,
|
||||
},
|
||||
.fixed_uV = 3300000,
|
||||
.update_bank = 0x03,
|
||||
.update_reg = 0x82,
|
||||
.update_mask = 0x03,
|
||||
@@ -460,8 +404,8 @@ static struct ab8500_regulator_info
|
||||
.id = AB8500_LDO_AUDIO,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = 1,
|
||||
.min_uV = 2000000,
|
||||
},
|
||||
.fixed_uV = 2000000,
|
||||
.update_bank = 0x03,
|
||||
.update_reg = 0x83,
|
||||
.update_mask = 0x02,
|
||||
@@ -475,8 +419,8 @@ static struct ab8500_regulator_info
|
||||
.id = AB8500_LDO_ANAMIC1,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = 1,
|
||||
.min_uV = 2050000,
|
||||
},
|
||||
.fixed_uV = 2050000,
|
||||
.update_bank = 0x03,
|
||||
.update_reg = 0x83,
|
||||
.update_mask = 0x08,
|
||||
@@ -490,8 +434,8 @@ static struct ab8500_regulator_info
|
||||
.id = AB8500_LDO_ANAMIC2,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = 1,
|
||||
.min_uV = 2050000,
|
||||
},
|
||||
.fixed_uV = 2050000,
|
||||
.update_bank = 0x03,
|
||||
.update_reg = 0x83,
|
||||
.update_mask = 0x10,
|
||||
@@ -505,8 +449,8 @@ static struct ab8500_regulator_info
|
||||
.id = AB8500_LDO_DMIC,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = 1,
|
||||
.min_uV = 1800000,
|
||||
},
|
||||
.fixed_uV = 1800000,
|
||||
.update_bank = 0x03,
|
||||
.update_reg = 0x83,
|
||||
.update_mask = 0x04,
|
||||
@@ -520,8 +464,8 @@ static struct ab8500_regulator_info
|
||||
.id = AB8500_LDO_ANA,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = 1,
|
||||
.min_uV = 1200000,
|
||||
},
|
||||
.fixed_uV = 1200000,
|
||||
.update_bank = 0x04,
|
||||
.update_reg = 0x06,
|
||||
.update_mask = 0x0c,
|
||||
@@ -769,9 +713,7 @@ static __devinit int ab8500_regulator_register(struct platform_device *pdev,
|
||||
if (info->desc.id == AB8500_LDO_AUX3) {
|
||||
info->desc.n_voltages =
|
||||
ARRAY_SIZE(ldo_vauxn_voltages);
|
||||
info->voltages = ldo_vauxn_voltages;
|
||||
info->voltages_len =
|
||||
ARRAY_SIZE(ldo_vauxn_voltages);
|
||||
info->desc.volt_table = ldo_vauxn_voltages;
|
||||
info->voltage_mask = 0xf;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,9 +89,12 @@ static int ad5398_set_current_limit(struct regulator_dev *rdev, int min_uA, int
|
||||
unsigned short data;
|
||||
int ret;
|
||||
|
||||
if (min_uA > chip->max_uA || min_uA < chip->min_uA)
|
||||
return -EINVAL;
|
||||
if (max_uA > chip->max_uA || max_uA < chip->min_uA)
|
||||
if (min_uA < chip->min_uA)
|
||||
min_uA = chip->min_uA;
|
||||
if (max_uA > chip->max_uA)
|
||||
max_uA = chip->max_uA;
|
||||
|
||||
if (min_uA > chip->max_uA || max_uA < chip->min_uA)
|
||||
return -EINVAL;
|
||||
|
||||
selector = DIV_ROUND_UP((min_uA - chip->min_uA) * chip->current_level,
|
||||
|
||||
@@ -43,33 +43,15 @@ struct anatop_regulator {
|
||||
struct regulator_init_data *initdata;
|
||||
};
|
||||
|
||||
static int anatop_set_voltage(struct regulator_dev *reg, int min_uV,
|
||||
int max_uV, unsigned *selector)
|
||||
static int anatop_set_voltage_sel(struct regulator_dev *reg, unsigned selector)
|
||||
{
|
||||
struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
|
||||
u32 val, sel, mask;
|
||||
int uv;
|
||||
|
||||
uv = min_uV;
|
||||
dev_dbg(®->dev, "%s: uv %d, min %d, max %d\n", __func__,
|
||||
uv, anatop_reg->min_voltage,
|
||||
anatop_reg->max_voltage);
|
||||
|
||||
if (uv < anatop_reg->min_voltage) {
|
||||
if (max_uV > anatop_reg->min_voltage)
|
||||
uv = anatop_reg->min_voltage;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
u32 val, mask;
|
||||
|
||||
if (!anatop_reg->control_reg)
|
||||
return -ENOTSUPP;
|
||||
|
||||
sel = DIV_ROUND_UP(uv - anatop_reg->min_voltage, 25000);
|
||||
if (sel * 25000 + anatop_reg->min_voltage > anatop_reg->max_voltage)
|
||||
return -EINVAL;
|
||||
val = anatop_reg->min_bit_val + sel;
|
||||
*selector = sel;
|
||||
val = anatop_reg->min_bit_val + selector;
|
||||
dev_dbg(®->dev, "%s: calculated val %d\n", __func__, val);
|
||||
mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
|
||||
anatop_reg->vol_bit_shift;
|
||||
@@ -94,21 +76,11 @@ static int anatop_get_voltage_sel(struct regulator_dev *reg)
|
||||
return val - anatop_reg->min_bit_val;
|
||||
}
|
||||
|
||||
static int anatop_list_voltage(struct regulator_dev *reg, unsigned selector)
|
||||
{
|
||||
struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
|
||||
int uv;
|
||||
|
||||
uv = anatop_reg->min_voltage + selector * 25000;
|
||||
dev_dbg(®->dev, "vddio = %d, selector = %u\n", uv, selector);
|
||||
|
||||
return uv;
|
||||
}
|
||||
|
||||
static struct regulator_ops anatop_rops = {
|
||||
.set_voltage = anatop_set_voltage,
|
||||
.set_voltage_sel = anatop_set_voltage_sel,
|
||||
.get_voltage_sel = anatop_get_voltage_sel,
|
||||
.list_voltage = anatop_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
};
|
||||
|
||||
static int __devinit anatop_regulator_probe(struct platform_device *pdev)
|
||||
@@ -176,6 +148,8 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev)
|
||||
|
||||
rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage)
|
||||
/ 25000 + 1;
|
||||
rdesc->min_uV = sreg->min_voltage;
|
||||
rdesc->uV_step = 25000;
|
||||
|
||||
config.dev = &pdev->dev;
|
||||
config.init_data = initdata;
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* arizona-ldo1.c -- LDO1 supply for Arizona devices
|
||||
*
|
||||
* Copyright 2012 Wolfson Microelectronics PLC.
|
||||
*
|
||||
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/mfd/arizona/core.h>
|
||||
#include <linux/mfd/arizona/pdata.h>
|
||||
#include <linux/mfd/arizona/registers.h>
|
||||
|
||||
struct arizona_ldo1 {
|
||||
struct regulator_dev *regulator;
|
||||
struct arizona *arizona;
|
||||
|
||||
struct regulator_consumer_supply supply;
|
||||
struct regulator_init_data init_data;
|
||||
};
|
||||
|
||||
static struct regulator_ops arizona_ldo1_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
};
|
||||
|
||||
static const struct regulator_desc arizona_ldo1 = {
|
||||
.name = "LDO1",
|
||||
.supply_name = "LDOVDD",
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.ops = &arizona_ldo1_ops,
|
||||
|
||||
.vsel_reg = ARIZONA_LDO1_CONTROL_1,
|
||||
.vsel_mask = ARIZONA_LDO1_VSEL_MASK,
|
||||
.min_uV = 900000,
|
||||
.uV_step = 50000,
|
||||
.n_voltages = 7,
|
||||
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static const struct regulator_init_data arizona_ldo1_default = {
|
||||
.constraints = {
|
||||
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
|
||||
},
|
||||
.num_consumer_supplies = 1,
|
||||
};
|
||||
|
||||
static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
|
||||
struct regulator_config config = { };
|
||||
struct arizona_ldo1 *ldo1;
|
||||
int ret;
|
||||
|
||||
ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL);
|
||||
if (ldo1 == NULL) {
|
||||
dev_err(&pdev->dev, "Unable to allocate private data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ldo1->arizona = arizona;
|
||||
|
||||
/*
|
||||
* Since the chip usually supplies itself we provide some
|
||||
* default init_data for it. This will be overridden with
|
||||
* platform data if provided.
|
||||
*/
|
||||
ldo1->init_data = arizona_ldo1_default;
|
||||
ldo1->init_data.consumer_supplies = &ldo1->supply;
|
||||
ldo1->supply.supply = "DCVDD";
|
||||
ldo1->supply.dev_name = dev_name(arizona->dev);
|
||||
|
||||
config.dev = arizona->dev;
|
||||
config.driver_data = ldo1;
|
||||
config.regmap = arizona->regmap;
|
||||
config.ena_gpio = arizona->pdata.ldoena;
|
||||
|
||||
if (arizona->pdata.ldo1)
|
||||
config.init_data = arizona->pdata.ldo1;
|
||||
else
|
||||
config.init_data = &ldo1->init_data;
|
||||
|
||||
ldo1->regulator = regulator_register(&arizona_ldo1, &config);
|
||||
if (IS_ERR(ldo1->regulator)) {
|
||||
ret = PTR_ERR(ldo1->regulator);
|
||||
dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, ldo1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __devexit int arizona_ldo1_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev);
|
||||
|
||||
regulator_unregister(ldo1->regulator);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver arizona_ldo1_driver = {
|
||||
.probe = arizona_ldo1_probe,
|
||||
.remove = __devexit_p(arizona_ldo1_remove),
|
||||
.driver = {
|
||||
.name = "arizona-ldo1",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(arizona_ldo1_driver);
|
||||
|
||||
/* Module information */
|
||||
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
|
||||
MODULE_DESCRIPTION("Arizona LDO1 driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:arizona-ldo1");
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* arizona-micsupp.c -- Microphone supply for Arizona devices
|
||||
*
|
||||
* Copyright 2012 Wolfson Microelectronics PLC.
|
||||
*
|
||||
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/mfd/arizona/core.h>
|
||||
#include <linux/mfd/arizona/pdata.h>
|
||||
#include <linux/mfd/arizona/registers.h>
|
||||
|
||||
#define ARIZONA_MICSUPP_MAX_SELECTOR 0x1f
|
||||
|
||||
struct arizona_micsupp {
|
||||
struct regulator_dev *regulator;
|
||||
struct arizona *arizona;
|
||||
|
||||
struct regulator_consumer_supply supply;
|
||||
struct regulator_init_data init_data;
|
||||
};
|
||||
|
||||
static int arizona_micsupp_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned int selector)
|
||||
{
|
||||
if (selector > ARIZONA_MICSUPP_MAX_SELECTOR)
|
||||
return -EINVAL;
|
||||
|
||||
if (selector == ARIZONA_MICSUPP_MAX_SELECTOR)
|
||||
return 3300000;
|
||||
else
|
||||
return (selector * 50000) + 1700000;
|
||||
}
|
||||
|
||||
static int arizona_micsupp_map_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
unsigned int voltage;
|
||||
int selector;
|
||||
|
||||
if (min_uV < 1700000)
|
||||
min_uV = 1700000;
|
||||
|
||||
if (min_uV > 3200000)
|
||||
selector = ARIZONA_MICSUPP_MAX_SELECTOR;
|
||||
else
|
||||
selector = DIV_ROUND_UP(min_uV - 1700000, 50000);
|
||||
|
||||
if (selector < 0)
|
||||
return -EINVAL;
|
||||
|
||||
voltage = arizona_micsupp_list_voltage(rdev, selector);
|
||||
if (voltage < min_uV || voltage > max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
return selector;
|
||||
}
|
||||
|
||||
static struct regulator_ops arizona_micsupp_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
|
||||
.list_voltage = arizona_micsupp_list_voltage,
|
||||
.map_voltage = arizona_micsupp_map_voltage,
|
||||
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
};
|
||||
|
||||
static const struct regulator_desc arizona_micsupp = {
|
||||
.name = "MICVDD",
|
||||
.supply_name = "CPVDD",
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = ARIZONA_MICSUPP_MAX_SELECTOR + 1,
|
||||
.ops = &arizona_micsupp_ops,
|
||||
|
||||
.vsel_reg = ARIZONA_LDO2_CONTROL_1,
|
||||
.vsel_mask = ARIZONA_LDO2_VSEL_MASK,
|
||||
.enable_reg = ARIZONA_MIC_CHARGE_PUMP_1,
|
||||
.enable_mask = ARIZONA_CPMIC_ENA,
|
||||
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static const struct regulator_init_data arizona_micsupp_default = {
|
||||
.constraints = {
|
||||
.valid_ops_mask = REGULATOR_CHANGE_STATUS |
|
||||
REGULATOR_CHANGE_VOLTAGE,
|
||||
.min_uV = 1700000,
|
||||
.max_uV = 3300000,
|
||||
},
|
||||
|
||||
.num_consumer_supplies = 1,
|
||||
};
|
||||
|
||||
static __devinit int arizona_micsupp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
|
||||
struct regulator_config config = { };
|
||||
struct arizona_micsupp *micsupp;
|
||||
int ret;
|
||||
|
||||
micsupp = devm_kzalloc(&pdev->dev, sizeof(*micsupp), GFP_KERNEL);
|
||||
if (micsupp == NULL) {
|
||||
dev_err(&pdev->dev, "Unable to allocate private data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
micsupp->arizona = arizona;
|
||||
|
||||
/*
|
||||
* Since the chip usually supplies itself we provide some
|
||||
* default init_data for it. This will be overridden with
|
||||
* platform data if provided.
|
||||
*/
|
||||
micsupp->init_data = arizona_micsupp_default;
|
||||
micsupp->init_data.consumer_supplies = &micsupp->supply;
|
||||
micsupp->supply.supply = "MICVDD";
|
||||
micsupp->supply.dev_name = dev_name(arizona->dev);
|
||||
|
||||
config.dev = arizona->dev;
|
||||
config.driver_data = micsupp;
|
||||
config.regmap = arizona->regmap;
|
||||
|
||||
if (arizona->pdata.micvdd)
|
||||
config.init_data = arizona->pdata.micvdd;
|
||||
else
|
||||
config.init_data = &micsupp->init_data;
|
||||
|
||||
/* Default to regulated mode until the API supports bypass */
|
||||
regmap_update_bits(arizona->regmap, ARIZONA_MIC_CHARGE_PUMP_1,
|
||||
ARIZONA_CPMIC_BYPASS, 0);
|
||||
|
||||
micsupp->regulator = regulator_register(&arizona_micsupp, &config);
|
||||
if (IS_ERR(micsupp->regulator)) {
|
||||
ret = PTR_ERR(micsupp->regulator);
|
||||
dev_err(arizona->dev, "Failed to register mic supply: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, micsupp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __devexit int arizona_micsupp_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct arizona_micsupp *micsupp = platform_get_drvdata(pdev);
|
||||
|
||||
regulator_unregister(micsupp->regulator);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver arizona_micsupp_driver = {
|
||||
.probe = arizona_micsupp_probe,
|
||||
.remove = __devexit_p(arizona_micsupp_remove),
|
||||
.driver = {
|
||||
.name = "arizona-micsupp",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(arizona_micsupp_driver);
|
||||
|
||||
/* Module information */
|
||||
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
|
||||
MODULE_DESCRIPTION("Arizona microphone supply driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:arizona-micsupp");
|
||||
+264
-146
@@ -23,6 +23,7 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
@@ -108,28 +109,6 @@ static const char *rdev_get_name(struct regulator_dev *rdev)
|
||||
return "";
|
||||
}
|
||||
|
||||
/* gets the regulator for a given consumer device */
|
||||
static struct regulator *get_device_regulator(struct device *dev)
|
||||
{
|
||||
struct regulator *regulator = NULL;
|
||||
struct regulator_dev *rdev;
|
||||
|
||||
mutex_lock(®ulator_list_mutex);
|
||||
list_for_each_entry(rdev, ®ulator_list, list) {
|
||||
mutex_lock(&rdev->mutex);
|
||||
list_for_each_entry(regulator, &rdev->consumer_list, list) {
|
||||
if (regulator->dev == dev) {
|
||||
mutex_unlock(&rdev->mutex);
|
||||
mutex_unlock(®ulator_list_mutex);
|
||||
return regulator;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&rdev->mutex);
|
||||
}
|
||||
mutex_unlock(®ulator_list_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* of_get_regulator - get a regulator device node based on supply name
|
||||
* @dev: Device pointer for the consumer (of regulator) device
|
||||
@@ -303,18 +282,6 @@ static int regulator_check_drms(struct regulator_dev *rdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t device_requested_uA_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct regulator *regulator;
|
||||
|
||||
regulator = get_device_regulator(dev);
|
||||
if (regulator == NULL)
|
||||
return 0;
|
||||
|
||||
return sprintf(buf, "%d\n", regulator->uA_load);
|
||||
}
|
||||
|
||||
static ssize_t regulator_uV_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
@@ -427,6 +394,9 @@ static ssize_t regulator_status_show(struct device *dev,
|
||||
case REGULATOR_STATUS_STANDBY:
|
||||
label = "standby";
|
||||
break;
|
||||
case REGULATOR_STATUS_UNDEFINED:
|
||||
label = "undefined";
|
||||
break;
|
||||
default:
|
||||
return -ERANGE;
|
||||
}
|
||||
@@ -967,6 +937,14 @@ static int set_machine_constraints(struct regulator_dev *rdev,
|
||||
}
|
||||
}
|
||||
|
||||
if (rdev->constraints->ramp_delay && ops->set_ramp_delay) {
|
||||
ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay);
|
||||
if (ret < 0) {
|
||||
rdev_err(rdev, "failed to set ramp_delay\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
print_constraints(rdev);
|
||||
return 0;
|
||||
out:
|
||||
@@ -1097,48 +1075,29 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
|
||||
list_add(®ulator->list, &rdev->consumer_list);
|
||||
|
||||
if (dev) {
|
||||
/* create a 'requested_microamps_name' sysfs entry */
|
||||
size = scnprintf(buf, REG_STR_SIZE,
|
||||
"microamps_requested_%s-%s",
|
||||
dev_name(dev), supply_name);
|
||||
if (size >= REG_STR_SIZE)
|
||||
goto overflow_err;
|
||||
|
||||
regulator->dev = dev;
|
||||
sysfs_attr_init(®ulator->dev_attr.attr);
|
||||
regulator->dev_attr.attr.name = kstrdup(buf, GFP_KERNEL);
|
||||
if (regulator->dev_attr.attr.name == NULL)
|
||||
goto attr_name_err;
|
||||
|
||||
regulator->dev_attr.attr.mode = 0444;
|
||||
regulator->dev_attr.show = device_requested_uA_show;
|
||||
err = device_create_file(dev, ®ulator->dev_attr);
|
||||
if (err < 0) {
|
||||
rdev_warn(rdev, "could not add regulator_dev requested microamps sysfs entry\n");
|
||||
goto attr_name_err;
|
||||
}
|
||||
|
||||
/* also add a link to the device sysfs entry */
|
||||
/* Add a link to the device sysfs entry */
|
||||
size = scnprintf(buf, REG_STR_SIZE, "%s-%s",
|
||||
dev->kobj.name, supply_name);
|
||||
if (size >= REG_STR_SIZE)
|
||||
goto attr_err;
|
||||
goto overflow_err;
|
||||
|
||||
regulator->supply_name = kstrdup(buf, GFP_KERNEL);
|
||||
if (regulator->supply_name == NULL)
|
||||
goto attr_err;
|
||||
goto overflow_err;
|
||||
|
||||
err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj,
|
||||
buf);
|
||||
if (err) {
|
||||
rdev_warn(rdev, "could not add device link %s err %d\n",
|
||||
dev->kobj.name, err);
|
||||
goto link_name_err;
|
||||
/* non-fatal */
|
||||
}
|
||||
} else {
|
||||
regulator->supply_name = kstrdup(supply_name, GFP_KERNEL);
|
||||
if (regulator->supply_name == NULL)
|
||||
goto attr_err;
|
||||
goto overflow_err;
|
||||
}
|
||||
|
||||
regulator->debugfs = debugfs_create_dir(regulator->supply_name,
|
||||
@@ -1165,12 +1124,6 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
|
||||
|
||||
mutex_unlock(&rdev->mutex);
|
||||
return regulator;
|
||||
link_name_err:
|
||||
kfree(regulator->supply_name);
|
||||
attr_err:
|
||||
device_remove_file(regulator->dev, ®ulator->dev_attr);
|
||||
attr_name_err:
|
||||
kfree(regulator->dev_attr.attr.name);
|
||||
overflow_err:
|
||||
list_del(®ulator->list);
|
||||
kfree(regulator);
|
||||
@@ -1181,7 +1134,7 @@ overflow_err:
|
||||
static int _regulator_get_enable_time(struct regulator_dev *rdev)
|
||||
{
|
||||
if (!rdev->desc->ops->enable_time)
|
||||
return 0;
|
||||
return rdev->desc->enable_time;
|
||||
return rdev->desc->ops->enable_time(rdev);
|
||||
}
|
||||
|
||||
@@ -1420,11 +1373,8 @@ void regulator_put(struct regulator *regulator)
|
||||
debugfs_remove_recursive(regulator->debugfs);
|
||||
|
||||
/* remove any sysfs entries */
|
||||
if (regulator->dev) {
|
||||
if (regulator->dev)
|
||||
sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
|
||||
device_remove_file(regulator->dev, ®ulator->dev_attr);
|
||||
kfree(regulator->dev_attr.attr.name);
|
||||
}
|
||||
kfree(regulator->supply_name);
|
||||
list_del(®ulator->list);
|
||||
kfree(regulator);
|
||||
@@ -1459,19 +1409,61 @@ void devm_regulator_put(struct regulator *regulator)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = devres_destroy(regulator->dev, devm_regulator_release,
|
||||
rc = devres_release(regulator->dev, devm_regulator_release,
|
||||
devm_regulator_match, regulator);
|
||||
if (rc == 0)
|
||||
regulator_put(regulator);
|
||||
else
|
||||
if (rc != 0)
|
||||
WARN_ON(rc);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_regulator_put);
|
||||
|
||||
static int _regulator_do_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
int ret, delay;
|
||||
|
||||
/* Query before enabling in case configuration dependent. */
|
||||
ret = _regulator_get_enable_time(rdev);
|
||||
if (ret >= 0) {
|
||||
delay = ret;
|
||||
} else {
|
||||
rdev_warn(rdev, "enable_time() failed: %d\n", ret);
|
||||
delay = 0;
|
||||
}
|
||||
|
||||
trace_regulator_enable(rdev_get_name(rdev));
|
||||
|
||||
if (rdev->ena_gpio) {
|
||||
gpio_set_value_cansleep(rdev->ena_gpio,
|
||||
!rdev->ena_gpio_invert);
|
||||
rdev->ena_gpio_state = 1;
|
||||
} else if (rdev->desc->ops->enable) {
|
||||
ret = rdev->desc->ops->enable(rdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Allow the regulator to ramp; it would be useful to extend
|
||||
* this for bulk operations so that the regulators can ramp
|
||||
* together. */
|
||||
trace_regulator_enable_delay(rdev_get_name(rdev));
|
||||
|
||||
if (delay >= 1000) {
|
||||
mdelay(delay / 1000);
|
||||
udelay(delay % 1000);
|
||||
} else if (delay) {
|
||||
udelay(delay);
|
||||
}
|
||||
|
||||
trace_regulator_enable_complete(rdev_get_name(rdev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* locks held by regulator_enable() */
|
||||
static int _regulator_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
int ret, delay;
|
||||
int ret;
|
||||
|
||||
/* check voltage and requested load before enabling */
|
||||
if (rdev->constraints &&
|
||||
@@ -1485,40 +1477,10 @@ static int _regulator_enable(struct regulator_dev *rdev)
|
||||
if (!_regulator_can_change_status(rdev))
|
||||
return -EPERM;
|
||||
|
||||
if (!rdev->desc->ops->enable)
|
||||
return -EINVAL;
|
||||
|
||||
/* Query before enabling in case configuration
|
||||
* dependent. */
|
||||
ret = _regulator_get_enable_time(rdev);
|
||||
if (ret >= 0) {
|
||||
delay = ret;
|
||||
} else {
|
||||
rdev_warn(rdev, "enable_time() failed: %d\n",
|
||||
ret);
|
||||
delay = 0;
|
||||
}
|
||||
|
||||
trace_regulator_enable(rdev_get_name(rdev));
|
||||
|
||||
/* Allow the regulator to ramp; it would be useful
|
||||
* to extend this for bulk operations so that the
|
||||
* regulators can ramp together. */
|
||||
ret = rdev->desc->ops->enable(rdev);
|
||||
ret = _regulator_do_enable(rdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
trace_regulator_enable_delay(rdev_get_name(rdev));
|
||||
|
||||
if (delay >= 1000) {
|
||||
mdelay(delay / 1000);
|
||||
udelay(delay % 1000);
|
||||
} else if (delay) {
|
||||
udelay(delay);
|
||||
}
|
||||
|
||||
trace_regulator_enable_complete(rdev_get_name(rdev));
|
||||
|
||||
} else if (ret < 0) {
|
||||
rdev_err(rdev, "is_enabled() failed: %d\n", ret);
|
||||
return ret;
|
||||
@@ -1567,6 +1529,30 @@ int regulator_enable(struct regulator *regulator)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_enable);
|
||||
|
||||
static int _regulator_do_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
trace_regulator_disable(rdev_get_name(rdev));
|
||||
|
||||
if (rdev->ena_gpio) {
|
||||
gpio_set_value_cansleep(rdev->ena_gpio,
|
||||
rdev->ena_gpio_invert);
|
||||
rdev->ena_gpio_state = 0;
|
||||
|
||||
} else if (rdev->desc->ops->disable) {
|
||||
ret = rdev->desc->ops->disable(rdev);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
trace_regulator_disable_complete(rdev_get_name(rdev));
|
||||
|
||||
_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
|
||||
NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* locks held by regulator_disable() */
|
||||
static int _regulator_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
@@ -1581,20 +1567,12 @@ static int _regulator_disable(struct regulator_dev *rdev)
|
||||
(rdev->constraints && !rdev->constraints->always_on)) {
|
||||
|
||||
/* we are last user */
|
||||
if (_regulator_can_change_status(rdev) &&
|
||||
rdev->desc->ops->disable) {
|
||||
trace_regulator_disable(rdev_get_name(rdev));
|
||||
|
||||
ret = rdev->desc->ops->disable(rdev);
|
||||
if (_regulator_can_change_status(rdev)) {
|
||||
ret = _regulator_do_disable(rdev);
|
||||
if (ret < 0) {
|
||||
rdev_err(rdev, "failed to disable\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
trace_regulator_disable_complete(rdev_get_name(rdev));
|
||||
|
||||
_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
rdev->use_count = 0;
|
||||
@@ -1812,6 +1790,10 @@ EXPORT_SYMBOL_GPL(regulator_disable_regmap);
|
||||
|
||||
static int _regulator_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
/* A GPIO control always takes precedence */
|
||||
if (rdev->ena_gpio)
|
||||
return rdev->ena_gpio_state;
|
||||
|
||||
/* If we don't know then assume that the regulator is always on */
|
||||
if (!rdev->desc->ops->is_enabled)
|
||||
return 1;
|
||||
@@ -1882,6 +1864,31 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
|
||||
|
||||
/**
|
||||
* regulator_list_voltage_table - List voltages with table based mapping
|
||||
*
|
||||
* @rdev: Regulator device
|
||||
* @selector: Selector to convert into a voltage
|
||||
*
|
||||
* Regulators with table based mapping between voltages and
|
||||
* selectors can set volt_table in the regulator descriptor
|
||||
* and then use this function as their list_voltage() operation.
|
||||
*/
|
||||
int regulator_list_voltage_table(struct regulator_dev *rdev,
|
||||
unsigned int selector)
|
||||
{
|
||||
if (!rdev->desc->volt_table) {
|
||||
BUG_ON(!rdev->desc->volt_table);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (selector >= rdev->desc->n_voltages)
|
||||
return -EINVAL;
|
||||
|
||||
return rdev->desc->volt_table[selector];
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_list_voltage_table);
|
||||
|
||||
/**
|
||||
* regulator_list_voltage - enumerate supported voltages
|
||||
* @regulator: regulator source
|
||||
@@ -1928,8 +1935,18 @@ EXPORT_SYMBOL_GPL(regulator_list_voltage);
|
||||
int regulator_is_supported_voltage(struct regulator *regulator,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
struct regulator_dev *rdev = regulator->rdev;
|
||||
int i, voltages, ret;
|
||||
|
||||
/* If we can't change voltage check the current voltage */
|
||||
if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
|
||||
ret = regulator_get_voltage(regulator);
|
||||
if (ret >= 0)
|
||||
return (min_uV >= ret && ret <= max_uV);
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_count_voltages(regulator);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -2045,6 +2062,14 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev,
|
||||
{
|
||||
int ret, voltage;
|
||||
|
||||
/* Allow uV_step to be 0 for fixed voltage */
|
||||
if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) {
|
||||
if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV)
|
||||
return 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!rdev->desc->uV_step) {
|
||||
BUG_ON(!rdev->desc->uV_step);
|
||||
return -EINVAL;
|
||||
@@ -2071,7 +2096,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
|
||||
{
|
||||
int ret;
|
||||
int delay = 0;
|
||||
int best_val;
|
||||
int best_val = 0;
|
||||
unsigned int selector;
|
||||
int old_selector = -1;
|
||||
|
||||
@@ -2084,7 +2109,8 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
|
||||
* If we can't obtain the old selector there is not enough
|
||||
* info to call set_voltage_time_sel().
|
||||
*/
|
||||
if (rdev->desc->ops->set_voltage_time_sel &&
|
||||
if (_regulator_is_enabled(rdev) &&
|
||||
rdev->desc->ops->set_voltage_time_sel &&
|
||||
rdev->desc->ops->get_voltage_sel) {
|
||||
old_selector = rdev->desc->ops->get_voltage_sel(rdev);
|
||||
if (old_selector < 0)
|
||||
@@ -2094,29 +2120,45 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
|
||||
if (rdev->desc->ops->set_voltage) {
|
||||
ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV,
|
||||
&selector);
|
||||
} else if (rdev->desc->ops->set_voltage_sel) {
|
||||
if (rdev->desc->ops->map_voltage)
|
||||
ret = rdev->desc->ops->map_voltage(rdev, min_uV,
|
||||
max_uV);
|
||||
else
|
||||
ret = regulator_map_voltage_iterate(rdev, min_uV,
|
||||
max_uV);
|
||||
|
||||
if (ret >= 0) {
|
||||
selector = ret;
|
||||
ret = rdev->desc->ops->set_voltage_sel(rdev, ret);
|
||||
if (rdev->desc->ops->list_voltage)
|
||||
best_val = rdev->desc->ops->list_voltage(rdev,
|
||||
selector);
|
||||
else
|
||||
best_val = _regulator_get_voltage(rdev);
|
||||
}
|
||||
|
||||
} else if (rdev->desc->ops->set_voltage_sel) {
|
||||
if (rdev->desc->ops->map_voltage) {
|
||||
ret = rdev->desc->ops->map_voltage(rdev, min_uV,
|
||||
max_uV);
|
||||
} else {
|
||||
if (rdev->desc->ops->list_voltage ==
|
||||
regulator_list_voltage_linear)
|
||||
ret = regulator_map_voltage_linear(rdev,
|
||||
min_uV, max_uV);
|
||||
else
|
||||
ret = regulator_map_voltage_iterate(rdev,
|
||||
min_uV, max_uV);
|
||||
}
|
||||
|
||||
if (ret >= 0) {
|
||||
best_val = rdev->desc->ops->list_voltage(rdev, ret);
|
||||
if (min_uV <= best_val && max_uV >= best_val) {
|
||||
selector = ret;
|
||||
ret = rdev->desc->ops->set_voltage_sel(rdev,
|
||||
ret);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
if (rdev->desc->ops->list_voltage)
|
||||
best_val = rdev->desc->ops->list_voltage(rdev, selector);
|
||||
else
|
||||
best_val = -1;
|
||||
|
||||
/* Call set_voltage_time_sel if successfully obtained old_selector */
|
||||
if (ret == 0 && old_selector >= 0 &&
|
||||
if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 &&
|
||||
rdev->desc->ops->set_voltage_time_sel) {
|
||||
|
||||
delay = rdev->desc->ops->set_voltage_time_sel(rdev,
|
||||
@@ -2126,19 +2168,19 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
|
||||
delay);
|
||||
delay = 0;
|
||||
}
|
||||
|
||||
/* Insert any necessary delays */
|
||||
if (delay >= 1000) {
|
||||
mdelay(delay / 1000);
|
||||
udelay(delay % 1000);
|
||||
} else if (delay) {
|
||||
udelay(delay);
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert any necessary delays */
|
||||
if (delay >= 1000) {
|
||||
mdelay(delay / 1000);
|
||||
udelay(delay % 1000);
|
||||
} else if (delay) {
|
||||
udelay(delay);
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
if (ret == 0 && best_val >= 0)
|
||||
_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
|
||||
NULL);
|
||||
(void *)best_val);
|
||||
|
||||
trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
|
||||
|
||||
@@ -2248,6 +2290,46 @@ int regulator_set_voltage_time(struct regulator *regulator,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_set_voltage_time);
|
||||
|
||||
/**
|
||||
*regulator_set_voltage_time_sel - get raise/fall time
|
||||
* @regulator: regulator source
|
||||
* @old_selector: selector for starting voltage
|
||||
* @new_selector: selector for target voltage
|
||||
*
|
||||
* Provided with the starting and target voltage selectors, this function
|
||||
* returns time in microseconds required to rise or fall to this new voltage
|
||||
*
|
||||
* Drivers providing ramp_delay in regulation_constraints can use this as their
|
||||
* set_voltage_time_sel() operation.
|
||||
*/
|
||||
int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
|
||||
unsigned int old_selector,
|
||||
unsigned int new_selector)
|
||||
{
|
||||
unsigned int ramp_delay = 0;
|
||||
int old_volt, new_volt;
|
||||
|
||||
if (rdev->constraints->ramp_delay)
|
||||
ramp_delay = rdev->constraints->ramp_delay;
|
||||
else if (rdev->desc->ramp_delay)
|
||||
ramp_delay = rdev->desc->ramp_delay;
|
||||
|
||||
if (ramp_delay == 0) {
|
||||
rdev_warn(rdev, "ramp_delay not set\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* sanity check */
|
||||
if (!rdev->desc->ops->list_voltage)
|
||||
return -EINVAL;
|
||||
|
||||
old_volt = rdev->desc->ops->list_voltage(rdev, old_selector);
|
||||
new_volt = rdev->desc->ops->list_voltage(rdev, new_selector);
|
||||
|
||||
return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel);
|
||||
|
||||
/**
|
||||
* regulator_sync_voltage - re-apply last regulator output voltage
|
||||
* @regulator: regulator source
|
||||
@@ -2628,7 +2710,7 @@ static void _notifier_call_chain(struct regulator_dev *rdev,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
/* call rdev chain first */
|
||||
blocking_notifier_call_chain(&rdev->notifier, event, NULL);
|
||||
blocking_notifier_call_chain(&rdev->notifier, event, data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2909,10 +2991,10 @@ int regulator_mode_to_status(unsigned int mode)
|
||||
return REGULATOR_STATUS_NORMAL;
|
||||
case REGULATOR_MODE_IDLE:
|
||||
return REGULATOR_STATUS_IDLE;
|
||||
case REGULATOR_STATUS_STANDBY:
|
||||
case REGULATOR_MODE_STANDBY:
|
||||
return REGULATOR_STATUS_STANDBY;
|
||||
default:
|
||||
return 0;
|
||||
return REGULATOR_STATUS_UNDEFINED;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_mode_to_status);
|
||||
@@ -3105,7 +3187,10 @@ regulator_register(const struct regulator_desc *regulator_desc,
|
||||
rdev->reg_data = config->driver_data;
|
||||
rdev->owner = regulator_desc->owner;
|
||||
rdev->desc = regulator_desc;
|
||||
rdev->regmap = config->regmap;
|
||||
if (config->regmap)
|
||||
rdev->regmap = config->regmap;
|
||||
else
|
||||
rdev->regmap = dev_get_regmap(dev, NULL);
|
||||
INIT_LIST_HEAD(&rdev->consumer_list);
|
||||
INIT_LIST_HEAD(&rdev->list);
|
||||
BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
|
||||
@@ -3132,6 +3217,26 @@ regulator_register(const struct regulator_desc *regulator_desc,
|
||||
|
||||
dev_set_drvdata(&rdev->dev, rdev);
|
||||
|
||||
if (config->ena_gpio) {
|
||||
ret = gpio_request_one(config->ena_gpio,
|
||||
GPIOF_DIR_OUT | config->ena_gpio_flags,
|
||||
rdev_get_name(rdev));
|
||||
if (ret != 0) {
|
||||
rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
|
||||
config->ena_gpio, ret);
|
||||
goto clean;
|
||||
}
|
||||
|
||||
rdev->ena_gpio = config->ena_gpio;
|
||||
rdev->ena_gpio_invert = config->ena_gpio_invert;
|
||||
|
||||
if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH)
|
||||
rdev->ena_gpio_state = 1;
|
||||
|
||||
if (rdev->ena_gpio_invert)
|
||||
rdev->ena_gpio_state = !rdev->ena_gpio_state;
|
||||
}
|
||||
|
||||
/* set regulator constraints */
|
||||
if (init_data)
|
||||
constraints = &init_data->constraints;
|
||||
@@ -3200,6 +3305,8 @@ unset_supplies:
|
||||
scrub:
|
||||
if (rdev->supply)
|
||||
regulator_put(rdev->supply);
|
||||
if (rdev->ena_gpio)
|
||||
gpio_free(rdev->ena_gpio);
|
||||
kfree(rdev->constraints);
|
||||
device_unregister(&rdev->dev);
|
||||
/* device core frees rdev */
|
||||
@@ -3233,6 +3340,8 @@ void regulator_unregister(struct regulator_dev *rdev)
|
||||
unset_regulator_supplies(rdev);
|
||||
list_del(&rdev->list);
|
||||
kfree(rdev->constraints);
|
||||
if (rdev->ena_gpio)
|
||||
gpio_free(rdev->ena_gpio);
|
||||
device_unregister(&rdev->dev);
|
||||
mutex_unlock(®ulator_list_mutex);
|
||||
}
|
||||
@@ -3472,6 +3581,15 @@ static int __init regulator_init_complete(void)
|
||||
struct regulation_constraints *c;
|
||||
int enabled, ret;
|
||||
|
||||
/*
|
||||
* Since DT doesn't provide an idiomatic mechanism for
|
||||
* enabling full constraints and since it's much more natural
|
||||
* with DT to provide them just assume that a DT enabled
|
||||
* system has full constraints.
|
||||
*/
|
||||
if (of_have_populated_dt())
|
||||
has_full_constraints = true;
|
||||
|
||||
mutex_lock(®ulator_list_mutex);
|
||||
|
||||
/* If we have a full configuration then disable any regulators
|
||||
|
||||
@@ -107,6 +107,9 @@ static int da903x_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
|
||||
struct device *da9034_dev = to_da903x_dev(rdev);
|
||||
uint8_t val, mask;
|
||||
|
||||
if (rdev->desc->n_voltages == 1)
|
||||
return -EINVAL;
|
||||
|
||||
val = selector << info->vol_shift;
|
||||
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
|
||||
|
||||
@@ -120,6 +123,9 @@ static int da903x_get_voltage_sel(struct regulator_dev *rdev)
|
||||
uint8_t val, mask;
|
||||
int ret;
|
||||
|
||||
if (rdev->desc->n_voltages == 1)
|
||||
return 0;
|
||||
|
||||
ret = da903x_read(da9034_dev, info->vol_reg, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -405,12 +405,12 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev)
|
||||
if (!nproot)
|
||||
return -ENODEV;
|
||||
|
||||
for (np = of_get_next_child(nproot, NULL); np;
|
||||
np = of_get_next_child(nproot, np)) {
|
||||
for_each_child_of_node(nproot, np) {
|
||||
if (!of_node_cmp(np->name,
|
||||
regulator->info->reg_desc.name)) {
|
||||
config.init_data = of_get_regulator_init_data(
|
||||
&pdev->dev, np);
|
||||
config.of_node = np;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/fixed.h>
|
||||
@@ -13,17 +14,20 @@ static void regulator_fixed_release(struct device *dev)
|
||||
{
|
||||
struct fixed_regulator_data *data = container_of(dev,
|
||||
struct fixed_regulator_data, pdev.dev);
|
||||
kfree(data->cfg.supply_name);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* regulator_register_fixed - register a no-op fixed regulator
|
||||
* regulator_register_fixed_name - register a no-op fixed regulator
|
||||
* @id: platform device id
|
||||
* @name: name to be used for the regulator
|
||||
* @supplies: consumers for this regulator
|
||||
* @num_supplies: number of consumers
|
||||
* @uv: voltage in microvolts
|
||||
*/
|
||||
struct platform_device *regulator_register_fixed(int id,
|
||||
struct regulator_consumer_supply *supplies, int num_supplies)
|
||||
struct platform_device *regulator_register_always_on(int id, const char *name,
|
||||
struct regulator_consumer_supply *supplies, int num_supplies, int uv)
|
||||
{
|
||||
struct fixed_regulator_data *data;
|
||||
|
||||
@@ -31,8 +35,13 @@ struct platform_device *regulator_register_fixed(int id,
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
data->cfg.supply_name = "fixed-dummy";
|
||||
data->cfg.microvolts = 0;
|
||||
data->cfg.supply_name = kstrdup(name, GFP_KERNEL);
|
||||
if (!data->cfg.supply_name) {
|
||||
kfree(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data->cfg.microvolts = uv;
|
||||
data->cfg.gpio = -EINVAL;
|
||||
data->cfg.enabled_at_boot = 1;
|
||||
data->cfg.init_data = &data->init_data;
|
||||
|
||||
+58
-105
@@ -35,10 +35,6 @@ struct fixed_voltage_data {
|
||||
struct regulator_desc desc;
|
||||
struct regulator_dev *dev;
|
||||
int microvolts;
|
||||
int gpio;
|
||||
unsigned startup_delay;
|
||||
bool enable_high;
|
||||
bool is_enabled;
|
||||
};
|
||||
|
||||
|
||||
@@ -61,11 +57,11 @@ of_get_fixed_voltage_config(struct device *dev)
|
||||
config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config),
|
||||
GFP_KERNEL);
|
||||
if (!config)
|
||||
return NULL;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
config->init_data = of_get_regulator_init_data(dev, dev->of_node);
|
||||
if (!config->init_data)
|
||||
return NULL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
init_data = config->init_data;
|
||||
init_data->constraints.apply_uV = 0;
|
||||
@@ -76,13 +72,26 @@ of_get_fixed_voltage_config(struct device *dev)
|
||||
} else {
|
||||
dev_err(dev,
|
||||
"Fixed regulator specified with variable voltages\n");
|
||||
return NULL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (init_data->constraints.boot_on)
|
||||
config->enabled_at_boot = true;
|
||||
|
||||
config->gpio = of_get_named_gpio(np, "gpio", 0);
|
||||
/*
|
||||
* of_get_named_gpio() currently returns ENODEV rather than
|
||||
* EPROBE_DEFER. This code attempts to be compatible with both
|
||||
* for now; the ENODEV check can be removed once the API is fixed.
|
||||
* of_get_named_gpio() doesn't differentiate between a missing
|
||||
* property (which would be fine here, since the GPIO is optional)
|
||||
* and some other error. Patches have been posted for both issues.
|
||||
* Once they are check in, we should replace this with:
|
||||
* if (config->gpio < 0 && config->gpio != -ENOENT)
|
||||
*/
|
||||
if ((config->gpio == -ENODEV) || (config->gpio == -EPROBE_DEFER))
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
delay = of_get_property(np, "startup-delay-us", NULL);
|
||||
if (delay)
|
||||
config->startup_delay = be32_to_cpu(*delay);
|
||||
@@ -93,43 +102,12 @@ of_get_fixed_voltage_config(struct device *dev)
|
||||
if (of_find_property(np, "gpio-open-drain", NULL))
|
||||
config->gpio_is_open_drain = true;
|
||||
|
||||
if (of_find_property(np, "vin-supply", NULL))
|
||||
config->input_supply = "vin";
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
static int fixed_voltage_is_enabled(struct regulator_dev *dev)
|
||||
{
|
||||
struct fixed_voltage_data *data = rdev_get_drvdata(dev);
|
||||
|
||||
return data->is_enabled;
|
||||
}
|
||||
|
||||
static int fixed_voltage_enable(struct regulator_dev *dev)
|
||||
{
|
||||
struct fixed_voltage_data *data = rdev_get_drvdata(dev);
|
||||
|
||||
gpio_set_value_cansleep(data->gpio, data->enable_high);
|
||||
data->is_enabled = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fixed_voltage_disable(struct regulator_dev *dev)
|
||||
{
|
||||
struct fixed_voltage_data *data = rdev_get_drvdata(dev);
|
||||
|
||||
gpio_set_value_cansleep(data->gpio, !data->enable_high);
|
||||
data->is_enabled = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fixed_voltage_enable_time(struct regulator_dev *dev)
|
||||
{
|
||||
struct fixed_voltage_data *data = rdev_get_drvdata(dev);
|
||||
|
||||
return data->startup_delay;
|
||||
}
|
||||
|
||||
static int fixed_voltage_get_voltage(struct regulator_dev *dev)
|
||||
{
|
||||
struct fixed_voltage_data *data = rdev_get_drvdata(dev);
|
||||
@@ -151,15 +129,6 @@ static int fixed_voltage_list_voltage(struct regulator_dev *dev,
|
||||
return data->microvolts;
|
||||
}
|
||||
|
||||
static struct regulator_ops fixed_voltage_gpio_ops = {
|
||||
.is_enabled = fixed_voltage_is_enabled,
|
||||
.enable = fixed_voltage_enable,
|
||||
.disable = fixed_voltage_disable,
|
||||
.enable_time = fixed_voltage_enable_time,
|
||||
.get_voltage = fixed_voltage_get_voltage,
|
||||
.list_voltage = fixed_voltage_list_voltage,
|
||||
};
|
||||
|
||||
static struct regulator_ops fixed_voltage_ops = {
|
||||
.get_voltage = fixed_voltage_get_voltage,
|
||||
.list_voltage = fixed_voltage_list_voltage,
|
||||
@@ -172,10 +141,13 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
|
||||
struct regulator_config cfg = { };
|
||||
int ret;
|
||||
|
||||
if (pdev->dev.of_node)
|
||||
if (pdev->dev.of_node) {
|
||||
config = of_get_fixed_voltage_config(&pdev->dev);
|
||||
else
|
||||
if (IS_ERR(config))
|
||||
return PTR_ERR(config);
|
||||
} else {
|
||||
config = pdev->dev.platform_data;
|
||||
}
|
||||
|
||||
if (!config)
|
||||
return -ENOMEM;
|
||||
@@ -196,59 +168,44 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
|
||||
}
|
||||
drvdata->desc.type = REGULATOR_VOLTAGE;
|
||||
drvdata->desc.owner = THIS_MODULE;
|
||||
drvdata->desc.ops = &fixed_voltage_ops;
|
||||
|
||||
drvdata->desc.enable_time = config->startup_delay;
|
||||
|
||||
if (config->input_supply) {
|
||||
drvdata->desc.supply_name = kstrdup(config->input_supply,
|
||||
GFP_KERNEL);
|
||||
if (!drvdata->desc.supply_name) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to allocate input supply\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_name;
|
||||
}
|
||||
}
|
||||
|
||||
if (config->microvolts)
|
||||
drvdata->desc.n_voltages = 1;
|
||||
|
||||
drvdata->microvolts = config->microvolts;
|
||||
drvdata->gpio = config->gpio;
|
||||
drvdata->startup_delay = config->startup_delay;
|
||||
|
||||
if (gpio_is_valid(config->gpio)) {
|
||||
int gpio_flag;
|
||||
drvdata->enable_high = config->enable_high;
|
||||
|
||||
/* FIXME: Remove below print warning
|
||||
*
|
||||
* config->gpio must be set to -EINVAL by platform code if
|
||||
* GPIO control is not required. However, early adopters
|
||||
* not requiring GPIO control may forget to initialize
|
||||
* config->gpio to -EINVAL. This will cause GPIO 0 to be used
|
||||
* for GPIO control.
|
||||
*
|
||||
* This warning will be removed once there are a couple of users
|
||||
* for this driver.
|
||||
*/
|
||||
if (!config->gpio)
|
||||
dev_warn(&pdev->dev,
|
||||
"using GPIO 0 for regulator enable control\n");
|
||||
|
||||
/*
|
||||
* set output direction without changing state
|
||||
* to prevent glitch
|
||||
*/
|
||||
drvdata->is_enabled = config->enabled_at_boot;
|
||||
ret = drvdata->is_enabled ?
|
||||
config->enable_high : !config->enable_high;
|
||||
gpio_flag = ret ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
|
||||
|
||||
if (config->gpio_is_open_drain)
|
||||
gpio_flag |= GPIOF_OPEN_DRAIN;
|
||||
|
||||
ret = gpio_request_one(config->gpio, gpio_flag,
|
||||
config->supply_name);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Could not obtain regulator enable GPIO %d: %d\n",
|
||||
config->gpio, ret);
|
||||
goto err_name;
|
||||
if (config->gpio >= 0)
|
||||
cfg.ena_gpio = config->gpio;
|
||||
cfg.ena_gpio_invert = !config->enable_high;
|
||||
if (config->enabled_at_boot) {
|
||||
if (config->enable_high) {
|
||||
cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
|
||||
} else {
|
||||
cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
|
||||
}
|
||||
|
||||
drvdata->desc.ops = &fixed_voltage_gpio_ops;
|
||||
|
||||
} else {
|
||||
drvdata->desc.ops = &fixed_voltage_ops;
|
||||
if (config->enable_high) {
|
||||
cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
|
||||
} else {
|
||||
cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
|
||||
}
|
||||
}
|
||||
if (config->gpio_is_open_drain)
|
||||
cfg.ena_gpio_flags |= GPIOF_OPEN_DRAIN;
|
||||
|
||||
cfg.dev = &pdev->dev;
|
||||
cfg.init_data = config->init_data;
|
||||
@@ -259,7 +216,7 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(drvdata->dev)) {
|
||||
ret = PTR_ERR(drvdata->dev);
|
||||
dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
|
||||
goto err_gpio;
|
||||
goto err_input;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, drvdata);
|
||||
@@ -269,9 +226,8 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
|
||||
err_gpio:
|
||||
if (gpio_is_valid(config->gpio))
|
||||
gpio_free(config->gpio);
|
||||
err_input:
|
||||
kfree(drvdata->desc.supply_name);
|
||||
err_name:
|
||||
kfree(drvdata->desc.name);
|
||||
err:
|
||||
@@ -283,8 +239,7 @@ static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev)
|
||||
struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev);
|
||||
|
||||
regulator_unregister(drvdata->dev);
|
||||
if (gpio_is_valid(drvdata->gpio))
|
||||
gpio_free(drvdata->gpio);
|
||||
kfree(drvdata->desc.supply_name);
|
||||
kfree(drvdata->desc.name);
|
||||
|
||||
return 0;
|
||||
@@ -296,8 +251,6 @@ static const struct of_device_id fixed_of_match[] __devinitconst = {
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, fixed_of_match);
|
||||
#else
|
||||
#define fixed_of_match NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver regulator_fixed_voltage_driver = {
|
||||
@@ -306,7 +259,7 @@ static struct platform_driver regulator_fixed_voltage_driver = {
|
||||
.driver = {
|
||||
.name = "reg-fixed-voltage",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = fixed_of_match,
|
||||
.of_match_table = of_match_ptr(fixed_of_match),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -36,11 +36,6 @@ struct gpio_regulator_data {
|
||||
struct regulator_desc desc;
|
||||
struct regulator_dev *dev;
|
||||
|
||||
int enable_gpio;
|
||||
bool enable_high;
|
||||
bool is_enabled;
|
||||
unsigned startup_delay;
|
||||
|
||||
struct gpio *gpios;
|
||||
int nr_gpios;
|
||||
|
||||
@@ -50,44 +45,6 @@ struct gpio_regulator_data {
|
||||
int state;
|
||||
};
|
||||
|
||||
static int gpio_regulator_is_enabled(struct regulator_dev *dev)
|
||||
{
|
||||
struct gpio_regulator_data *data = rdev_get_drvdata(dev);
|
||||
|
||||
return data->is_enabled;
|
||||
}
|
||||
|
||||
static int gpio_regulator_enable(struct regulator_dev *dev)
|
||||
{
|
||||
struct gpio_regulator_data *data = rdev_get_drvdata(dev);
|
||||
|
||||
if (gpio_is_valid(data->enable_gpio)) {
|
||||
gpio_set_value_cansleep(data->enable_gpio, data->enable_high);
|
||||
data->is_enabled = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_regulator_disable(struct regulator_dev *dev)
|
||||
{
|
||||
struct gpio_regulator_data *data = rdev_get_drvdata(dev);
|
||||
|
||||
if (gpio_is_valid(data->enable_gpio)) {
|
||||
gpio_set_value_cansleep(data->enable_gpio, !data->enable_high);
|
||||
data->is_enabled = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_regulator_enable_time(struct regulator_dev *dev)
|
||||
{
|
||||
struct gpio_regulator_data *data = rdev_get_drvdata(dev);
|
||||
|
||||
return data->startup_delay;
|
||||
}
|
||||
|
||||
static int gpio_regulator_get_value(struct regulator_dev *dev)
|
||||
{
|
||||
struct gpio_regulator_data *data = rdev_get_drvdata(dev);
|
||||
@@ -153,20 +110,12 @@ static int gpio_regulator_set_current_limit(struct regulator_dev *dev,
|
||||
}
|
||||
|
||||
static struct regulator_ops gpio_regulator_voltage_ops = {
|
||||
.is_enabled = gpio_regulator_is_enabled,
|
||||
.enable = gpio_regulator_enable,
|
||||
.disable = gpio_regulator_disable,
|
||||
.enable_time = gpio_regulator_enable_time,
|
||||
.get_voltage = gpio_regulator_get_value,
|
||||
.set_voltage = gpio_regulator_set_voltage,
|
||||
.list_voltage = gpio_regulator_list_voltage,
|
||||
};
|
||||
|
||||
static struct regulator_ops gpio_regulator_current_ops = {
|
||||
.is_enabled = gpio_regulator_is_enabled,
|
||||
.enable = gpio_regulator_enable,
|
||||
.disable = gpio_regulator_disable,
|
||||
.enable_time = gpio_regulator_enable_time,
|
||||
.get_current_limit = gpio_regulator_get_value,
|
||||
.set_current_limit = gpio_regulator_set_current_limit,
|
||||
};
|
||||
@@ -213,6 +162,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
|
||||
drvdata->nr_states = config->nr_states;
|
||||
|
||||
drvdata->desc.owner = THIS_MODULE;
|
||||
drvdata->desc.enable_time = config->startup_delay;
|
||||
|
||||
/* handle regulator type*/
|
||||
switch (config->type) {
|
||||
@@ -232,52 +182,12 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
|
||||
break;
|
||||
}
|
||||
|
||||
drvdata->enable_gpio = config->enable_gpio;
|
||||
drvdata->startup_delay = config->startup_delay;
|
||||
|
||||
if (gpio_is_valid(config->enable_gpio)) {
|
||||
drvdata->enable_high = config->enable_high;
|
||||
|
||||
ret = gpio_request(config->enable_gpio, config->supply_name);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Could not obtain regulator enable GPIO %d: %d\n",
|
||||
config->enable_gpio, ret);
|
||||
goto err_memstate;
|
||||
}
|
||||
|
||||
/* set output direction without changing state
|
||||
* to prevent glitch
|
||||
*/
|
||||
if (config->enabled_at_boot) {
|
||||
drvdata->is_enabled = true;
|
||||
ret = gpio_direction_output(config->enable_gpio,
|
||||
config->enable_high);
|
||||
} else {
|
||||
drvdata->is_enabled = false;
|
||||
ret = gpio_direction_output(config->enable_gpio,
|
||||
!config->enable_high);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Could not configure regulator enable GPIO %d direction: %d\n",
|
||||
config->enable_gpio, ret);
|
||||
goto err_enablegpio;
|
||||
}
|
||||
} else {
|
||||
/* Regulator without GPIO control is considered
|
||||
* always enabled
|
||||
*/
|
||||
drvdata->is_enabled = true;
|
||||
}
|
||||
|
||||
drvdata->nr_gpios = config->nr_gpios;
|
||||
ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Could not obtain regulator setting GPIOs: %d\n", ret);
|
||||
goto err_enablegpio;
|
||||
goto err_memstate;
|
||||
}
|
||||
|
||||
/* build initial state from gpio init data. */
|
||||
@@ -292,6 +202,21 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
|
||||
cfg.init_data = config->init_data;
|
||||
cfg.driver_data = drvdata;
|
||||
|
||||
if (config->enable_gpio >= 0)
|
||||
cfg.ena_gpio = config->enable_gpio;
|
||||
cfg.ena_gpio_invert = !config->enable_high;
|
||||
if (config->enabled_at_boot) {
|
||||
if (config->enable_high)
|
||||
cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
|
||||
else
|
||||
cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
|
||||
} else {
|
||||
if (config->enable_high)
|
||||
cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
|
||||
else
|
||||
cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
|
||||
}
|
||||
|
||||
drvdata->dev = regulator_register(&drvdata->desc, &cfg);
|
||||
if (IS_ERR(drvdata->dev)) {
|
||||
ret = PTR_ERR(drvdata->dev);
|
||||
@@ -305,9 +230,6 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
|
||||
|
||||
err_stategpio:
|
||||
gpio_free_array(drvdata->gpios, drvdata->nr_gpios);
|
||||
err_enablegpio:
|
||||
if (gpio_is_valid(config->enable_gpio))
|
||||
gpio_free(config->enable_gpio);
|
||||
err_memstate:
|
||||
kfree(drvdata->states);
|
||||
err_memgpio:
|
||||
@@ -329,9 +251,6 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev)
|
||||
kfree(drvdata->states);
|
||||
kfree(drvdata->gpios);
|
||||
|
||||
if (gpio_is_valid(drvdata->enable_gpio))
|
||||
gpio_free(drvdata->enable_gpio);
|
||||
|
||||
kfree(drvdata->desc.name);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -75,19 +75,12 @@ static struct regulator_ops isl_core_ops = {
|
||||
|
||||
static int isl6271a_get_fixed_voltage(struct regulator_dev *dev)
|
||||
{
|
||||
int id = rdev_get_id(dev);
|
||||
return (id == 1) ? 1100000 : 1300000;
|
||||
}
|
||||
|
||||
static int isl6271a_list_fixed_voltage(struct regulator_dev *dev, unsigned selector)
|
||||
{
|
||||
int id = rdev_get_id(dev);
|
||||
return (id == 1) ? 1100000 : 1300000;
|
||||
return dev->desc->min_uV;
|
||||
}
|
||||
|
||||
static struct regulator_ops isl_fixed_ops = {
|
||||
.get_voltage = isl6271a_get_fixed_voltage,
|
||||
.list_voltage = isl6271a_list_fixed_voltage,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
};
|
||||
|
||||
static const struct regulator_desc isl_rd[] = {
|
||||
@@ -107,6 +100,7 @@ static const struct regulator_desc isl_rd[] = {
|
||||
.ops = &isl_fixed_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.min_uV = 1100000,
|
||||
}, {
|
||||
.name = "LDO2",
|
||||
.id = 2,
|
||||
@@ -114,6 +108,7 @@ static const struct regulator_desc isl_rd[] = {
|
||||
.ops = &isl_fixed_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.min_uV = 1300000,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
+23
-43
@@ -65,11 +65,11 @@ static const int buck_base_addr[] = {
|
||||
#define LP3971_BUCK_TARGET_VOL1_REG(x) (buck_base_addr[x])
|
||||
#define LP3971_BUCK_TARGET_VOL2_REG(x) (buck_base_addr[x]+1)
|
||||
|
||||
static const int buck_voltage_map[] = {
|
||||
0, 800, 850, 900, 950, 1000, 1050, 1100,
|
||||
1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500,
|
||||
1550, 1600, 1650, 1700, 1800, 1900, 2500, 2800,
|
||||
3000, 3300,
|
||||
static const unsigned int buck_voltage_map[] = {
|
||||
0, 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000,
|
||||
1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
|
||||
1550000, 1600000, 1650000, 1700000, 1800000, 1900000, 2500000, 2800000,
|
||||
3000000, 3300000,
|
||||
};
|
||||
|
||||
#define BUCK_TARGET_VOL_MASK 0x3f
|
||||
@@ -98,39 +98,19 @@ static const int buck_voltage_map[] = {
|
||||
#define LDO_VOL_CONTR_SHIFT(x) ((x & 1) << 2)
|
||||
#define LDO_VOL_CONTR_MASK 0x0f
|
||||
|
||||
static const int ldo45_voltage_map[] = {
|
||||
1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350,
|
||||
1400, 1500, 1800, 1900, 2500, 2800, 3000, 3300,
|
||||
static const unsigned int ldo45_voltage_map[] = {
|
||||
1000000, 1050000, 1100000, 1150000, 1200000, 1250000, 1300000, 1350000,
|
||||
1400000, 1500000, 1800000, 1900000, 2500000, 2800000, 3000000, 3300000,
|
||||
};
|
||||
|
||||
static const int ldo123_voltage_map[] = {
|
||||
1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500,
|
||||
2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300,
|
||||
static const unsigned int ldo123_voltage_map[] = {
|
||||
1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
|
||||
2600000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000,
|
||||
};
|
||||
|
||||
static const int *ldo_voltage_map[] = {
|
||||
ldo123_voltage_map, /* LDO1 */
|
||||
ldo123_voltage_map, /* LDO2 */
|
||||
ldo123_voltage_map, /* LDO3 */
|
||||
ldo45_voltage_map, /* LDO4 */
|
||||
ldo45_voltage_map, /* LDO5 */
|
||||
};
|
||||
|
||||
#define LDO_VOL_VALUE_MAP(x) (ldo_voltage_map[(x - LP3971_LDO1)])
|
||||
|
||||
#define LDO_VOL_MIN_IDX 0x00
|
||||
#define LDO_VOL_MAX_IDX 0x0f
|
||||
|
||||
static int lp3971_ldo_list_voltage(struct regulator_dev *dev, unsigned index)
|
||||
{
|
||||
int ldo = rdev_get_id(dev) - LP3971_LDO1;
|
||||
|
||||
if (index > LDO_VOL_MAX_IDX)
|
||||
return -EINVAL;
|
||||
|
||||
return 1000 * LDO_VOL_VALUE_MAP(ldo)[index];
|
||||
}
|
||||
|
||||
static int lp3971_ldo_is_enabled(struct regulator_dev *dev)
|
||||
{
|
||||
struct lp3971 *lp3971 = rdev_get_drvdata(dev);
|
||||
@@ -169,7 +149,7 @@ static int lp3971_ldo_get_voltage(struct regulator_dev *dev)
|
||||
reg = lp3971_reg_read(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo));
|
||||
val = (reg >> LDO_VOL_CONTR_SHIFT(ldo)) & LDO_VOL_CONTR_MASK;
|
||||
|
||||
return 1000 * LDO_VOL_VALUE_MAP(ldo)[val];
|
||||
return dev->desc->volt_table[val];
|
||||
}
|
||||
|
||||
static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev,
|
||||
@@ -184,7 +164,7 @@ static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev,
|
||||
}
|
||||
|
||||
static struct regulator_ops lp3971_ldo_ops = {
|
||||
.list_voltage = lp3971_ldo_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.is_enabled = lp3971_ldo_is_enabled,
|
||||
.enable = lp3971_ldo_enable,
|
||||
.disable = lp3971_ldo_disable,
|
||||
@@ -192,14 +172,6 @@ static struct regulator_ops lp3971_ldo_ops = {
|
||||
.set_voltage_sel = lp3971_ldo_set_voltage_sel,
|
||||
};
|
||||
|
||||
static int lp3971_dcdc_list_voltage(struct regulator_dev *dev, unsigned index)
|
||||
{
|
||||
if (index < BUCK_TARGET_VOL_MIN_IDX || index > BUCK_TARGET_VOL_MAX_IDX)
|
||||
return -EINVAL;
|
||||
|
||||
return 1000 * buck_voltage_map[index];
|
||||
}
|
||||
|
||||
static int lp3971_dcdc_is_enabled(struct regulator_dev *dev)
|
||||
{
|
||||
struct lp3971 *lp3971 = rdev_get_drvdata(dev);
|
||||
@@ -240,7 +212,7 @@ static int lp3971_dcdc_get_voltage(struct regulator_dev *dev)
|
||||
reg &= BUCK_TARGET_VOL_MASK;
|
||||
|
||||
if (reg <= BUCK_TARGET_VOL_MAX_IDX)
|
||||
val = 1000 * buck_voltage_map[reg];
|
||||
val = buck_voltage_map[reg];
|
||||
else {
|
||||
val = 0;
|
||||
dev_warn(&dev->dev, "chip reported incorrect voltage value.\n");
|
||||
@@ -273,7 +245,7 @@ static int lp3971_dcdc_set_voltage_sel(struct regulator_dev *dev,
|
||||
}
|
||||
|
||||
static struct regulator_ops lp3971_dcdc_ops = {
|
||||
.list_voltage = lp3971_dcdc_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.is_enabled = lp3971_dcdc_is_enabled,
|
||||
.enable = lp3971_dcdc_enable,
|
||||
.disable = lp3971_dcdc_disable,
|
||||
@@ -287,6 +259,7 @@ static const struct regulator_desc regulators[] = {
|
||||
.id = LP3971_LDO1,
|
||||
.ops = &lp3971_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(ldo123_voltage_map),
|
||||
.volt_table = ldo123_voltage_map,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
@@ -295,6 +268,7 @@ static const struct regulator_desc regulators[] = {
|
||||
.id = LP3971_LDO2,
|
||||
.ops = &lp3971_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(ldo123_voltage_map),
|
||||
.volt_table = ldo123_voltage_map,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
@@ -303,6 +277,7 @@ static const struct regulator_desc regulators[] = {
|
||||
.id = LP3971_LDO3,
|
||||
.ops = &lp3971_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(ldo123_voltage_map),
|
||||
.volt_table = ldo123_voltage_map,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
@@ -311,6 +286,7 @@ static const struct regulator_desc regulators[] = {
|
||||
.id = LP3971_LDO4,
|
||||
.ops = &lp3971_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(ldo45_voltage_map),
|
||||
.volt_table = ldo45_voltage_map,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
@@ -319,6 +295,7 @@ static const struct regulator_desc regulators[] = {
|
||||
.id = LP3971_LDO5,
|
||||
.ops = &lp3971_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(ldo45_voltage_map),
|
||||
.volt_table = ldo45_voltage_map,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
@@ -327,6 +304,7 @@ static const struct regulator_desc regulators[] = {
|
||||
.id = LP3971_DCDC1,
|
||||
.ops = &lp3971_dcdc_ops,
|
||||
.n_voltages = ARRAY_SIZE(buck_voltage_map),
|
||||
.volt_table = buck_voltage_map,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
@@ -335,6 +313,7 @@ static const struct regulator_desc regulators[] = {
|
||||
.id = LP3971_DCDC2,
|
||||
.ops = &lp3971_dcdc_ops,
|
||||
.n_voltages = ARRAY_SIZE(buck_voltage_map),
|
||||
.volt_table = buck_voltage_map,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
@@ -343,6 +322,7 @@ static const struct regulator_desc regulators[] = {
|
||||
.id = LP3971_DCDC3,
|
||||
.ops = &lp3971_dcdc_ops,
|
||||
.n_voltages = ARRAY_SIZE(buck_voltage_map),
|
||||
.volt_table = buck_voltage_map,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
|
||||
+36
-66
@@ -74,54 +74,40 @@ struct lp3972 {
|
||||
#define LP3972_OVER2_LDO4_EN BIT(4)
|
||||
#define LP3972_OVER1_S_EN BIT(2)
|
||||
|
||||
static const int ldo1_voltage_map[] = {
|
||||
1700, 1725, 1750, 1775, 1800, 1825, 1850, 1875,
|
||||
1900, 1925, 1950, 1975, 2000,
|
||||
static const unsigned int ldo1_voltage_map[] = {
|
||||
1700000, 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000,
|
||||
1900000, 1925000, 1950000, 1975000, 2000000,
|
||||
};
|
||||
|
||||
static const int ldo23_voltage_map[] = {
|
||||
1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500,
|
||||
2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300,
|
||||
static const unsigned int ldo23_voltage_map[] = {
|
||||
1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
|
||||
2600000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000,
|
||||
};
|
||||
|
||||
static const int ldo4_voltage_map[] = {
|
||||
1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350,
|
||||
1400, 1500, 1800, 1900, 2500, 2800, 3000, 3300,
|
||||
static const unsigned int ldo4_voltage_map[] = {
|
||||
1000000, 1050000, 1100000, 1150000, 1200000, 1250000, 1300000, 1350000,
|
||||
1400000, 1500000, 1800000, 1900000, 2500000, 2800000, 3000000, 3300000,
|
||||
};
|
||||
|
||||
static const int ldo5_voltage_map[] = {
|
||||
0, 0, 0, 0, 0, 850, 875, 900,
|
||||
925, 950, 975, 1000, 1025, 1050, 1075, 1100,
|
||||
1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300,
|
||||
1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500,
|
||||
static const unsigned int ldo5_voltage_map[] = {
|
||||
0, 0, 0, 0, 0, 850000, 875000, 900000,
|
||||
925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000,
|
||||
1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
|
||||
1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
|
||||
};
|
||||
|
||||
static const int buck1_voltage_map[] = {
|
||||
725, 750, 775, 800, 825, 850, 875, 900,
|
||||
925, 950, 975, 1000, 1025, 1050, 1075, 1100,
|
||||
1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300,
|
||||
1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500,
|
||||
static const unsigned int buck1_voltage_map[] = {
|
||||
725000, 750000, 775000, 800000, 825000, 850000, 875000, 900000,
|
||||
925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000,
|
||||
1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
|
||||
1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
|
||||
};
|
||||
|
||||
static const int buck23_voltage_map[] = {
|
||||
0, 800, 850, 900, 950, 1000, 1050, 1100,
|
||||
1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500,
|
||||
1550, 1600, 1650, 1700, 1800, 1900, 2500, 2800,
|
||||
3000, 3300,
|
||||
};
|
||||
|
||||
static const int *ldo_voltage_map[] = {
|
||||
ldo1_voltage_map,
|
||||
ldo23_voltage_map,
|
||||
ldo23_voltage_map,
|
||||
ldo4_voltage_map,
|
||||
ldo5_voltage_map,
|
||||
};
|
||||
|
||||
static const int *buck_voltage_map[] = {
|
||||
buck1_voltage_map,
|
||||
buck23_voltage_map,
|
||||
buck23_voltage_map,
|
||||
static const unsigned int buck23_voltage_map[] = {
|
||||
0, 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000,
|
||||
1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
|
||||
1550000, 1600000, 1650000, 1700000, 1800000, 1900000, 2500000, 2800000,
|
||||
3000000, 3300000,
|
||||
};
|
||||
|
||||
static const int ldo_output_enable_mask[] = {
|
||||
@@ -160,7 +146,6 @@ static const int buck_base_addr[] = {
|
||||
LP3972_B3TV_REG,
|
||||
};
|
||||
|
||||
#define LP3972_LDO_VOL_VALUE_MAP(x) (ldo_voltage_map[x])
|
||||
#define LP3972_LDO_OUTPUT_ENABLE_MASK(x) (ldo_output_enable_mask[x])
|
||||
#define LP3972_LDO_OUTPUT_ENABLE_REG(x) (ldo_output_enable_addr[x])
|
||||
|
||||
@@ -177,7 +162,6 @@ static const int buck_base_addr[] = {
|
||||
#define LP3972_LDO_VOL_MIN_IDX(x) (((x) == 4) ? 0x05 : 0x00)
|
||||
#define LP3972_LDO_VOL_MAX_IDX(x) ((x) ? (((x) == 4) ? 0x1f : 0x0f) : 0x0c)
|
||||
|
||||
#define LP3972_BUCK_VOL_VALUE_MAP(x) (buck_voltage_map[x])
|
||||
#define LP3972_BUCK_VOL_ENABLE_REG(x) (buck_vol_enable_addr[x])
|
||||
#define LP3972_BUCK_VOL1_REG(x) (buck_base_addr[x])
|
||||
#define LP3972_BUCK_VOL_MASK 0x1f
|
||||
@@ -242,17 +226,6 @@ static int lp3972_set_bits(struct lp3972 *lp3972, u8 reg, u16 mask, u16 val)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lp3972_ldo_list_voltage(struct regulator_dev *dev, unsigned index)
|
||||
{
|
||||
int ldo = rdev_get_id(dev) - LP3972_LDO1;
|
||||
|
||||
if (index < LP3972_LDO_VOL_MIN_IDX(ldo) ||
|
||||
index > LP3972_LDO_VOL_MAX_IDX(ldo))
|
||||
return -EINVAL;
|
||||
|
||||
return 1000 * LP3972_LDO_VOL_VALUE_MAP(ldo)[index];
|
||||
}
|
||||
|
||||
static int lp3972_ldo_is_enabled(struct regulator_dev *dev)
|
||||
{
|
||||
struct lp3972 *lp3972 = rdev_get_drvdata(dev);
|
||||
@@ -294,7 +267,7 @@ static int lp3972_ldo_get_voltage(struct regulator_dev *dev)
|
||||
reg = lp3972_reg_read(lp3972, LP3972_LDO_VOL_CONTR_REG(ldo));
|
||||
val = (reg >> LP3972_LDO_VOL_CONTR_SHIFT(ldo)) & mask;
|
||||
|
||||
return 1000 * LP3972_LDO_VOL_VALUE_MAP(ldo)[val];
|
||||
return dev->desc->volt_table[val];
|
||||
}
|
||||
|
||||
static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev,
|
||||
@@ -337,7 +310,7 @@ static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev,
|
||||
}
|
||||
|
||||
static struct regulator_ops lp3972_ldo_ops = {
|
||||
.list_voltage = lp3972_ldo_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.is_enabled = lp3972_ldo_is_enabled,
|
||||
.enable = lp3972_ldo_enable,
|
||||
.disable = lp3972_ldo_disable,
|
||||
@@ -345,17 +318,6 @@ static struct regulator_ops lp3972_ldo_ops = {
|
||||
.set_voltage_sel = lp3972_ldo_set_voltage_sel,
|
||||
};
|
||||
|
||||
static int lp3972_dcdc_list_voltage(struct regulator_dev *dev, unsigned index)
|
||||
{
|
||||
int buck = rdev_get_id(dev) - LP3972_DCDC1;
|
||||
|
||||
if (index < LP3972_BUCK_VOL_MIN_IDX(buck) ||
|
||||
index > LP3972_BUCK_VOL_MAX_IDX(buck))
|
||||
return -EINVAL;
|
||||
|
||||
return 1000 * buck_voltage_map[buck][index];
|
||||
}
|
||||
|
||||
static int lp3972_dcdc_is_enabled(struct regulator_dev *dev)
|
||||
{
|
||||
struct lp3972 *lp3972 = rdev_get_drvdata(dev);
|
||||
@@ -401,7 +363,7 @@ static int lp3972_dcdc_get_voltage(struct regulator_dev *dev)
|
||||
reg = lp3972_reg_read(lp3972, LP3972_BUCK_VOL1_REG(buck));
|
||||
reg &= LP3972_BUCK_VOL_MASK;
|
||||
if (reg <= LP3972_BUCK_VOL_MAX_IDX(buck))
|
||||
val = 1000 * buck_voltage_map[buck][reg];
|
||||
val = dev->desc->volt_table[reg];
|
||||
else {
|
||||
val = 0;
|
||||
dev_warn(&dev->dev, "chip reported incorrect voltage value."
|
||||
@@ -436,7 +398,7 @@ static int lp3972_dcdc_set_voltage_sel(struct regulator_dev *dev,
|
||||
}
|
||||
|
||||
static struct regulator_ops lp3972_dcdc_ops = {
|
||||
.list_voltage = lp3972_dcdc_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.is_enabled = lp3972_dcdc_is_enabled,
|
||||
.enable = lp3972_dcdc_enable,
|
||||
.disable = lp3972_dcdc_disable,
|
||||
@@ -450,6 +412,7 @@ static const struct regulator_desc regulators[] = {
|
||||
.id = LP3972_LDO1,
|
||||
.ops = &lp3972_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(ldo1_voltage_map),
|
||||
.volt_table = ldo1_voltage_map,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
@@ -458,6 +421,7 @@ static const struct regulator_desc regulators[] = {
|
||||
.id = LP3972_LDO2,
|
||||
.ops = &lp3972_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(ldo23_voltage_map),
|
||||
.volt_table = ldo23_voltage_map,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
@@ -466,6 +430,7 @@ static const struct regulator_desc regulators[] = {
|
||||
.id = LP3972_LDO3,
|
||||
.ops = &lp3972_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(ldo23_voltage_map),
|
||||
.volt_table = ldo23_voltage_map,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
@@ -474,6 +439,7 @@ static const struct regulator_desc regulators[] = {
|
||||
.id = LP3972_LDO4,
|
||||
.ops = &lp3972_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(ldo4_voltage_map),
|
||||
.volt_table = ldo4_voltage_map,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
@@ -482,6 +448,7 @@ static const struct regulator_desc regulators[] = {
|
||||
.id = LP3972_LDO5,
|
||||
.ops = &lp3972_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(ldo5_voltage_map),
|
||||
.volt_table = ldo5_voltage_map,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
@@ -490,6 +457,7 @@ static const struct regulator_desc regulators[] = {
|
||||
.id = LP3972_DCDC1,
|
||||
.ops = &lp3972_dcdc_ops,
|
||||
.n_voltages = ARRAY_SIZE(buck1_voltage_map),
|
||||
.volt_table = buck1_voltage_map,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
@@ -498,6 +466,7 @@ static const struct regulator_desc regulators[] = {
|
||||
.id = LP3972_DCDC2,
|
||||
.ops = &lp3972_dcdc_ops,
|
||||
.n_voltages = ARRAY_SIZE(buck23_voltage_map),
|
||||
.volt_table = buck23_voltage_map,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
@@ -506,6 +475,7 @@ static const struct regulator_desc regulators[] = {
|
||||
.id = LP3972_DCDC3,
|
||||
.ops = &lp3972_dcdc_ops,
|
||||
.n_voltages = ARRAY_SIZE(buck23_voltage_map),
|
||||
.volt_table = buck23_voltage_map,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
|
||||
@@ -0,0 +1,943 @@
|
||||
/*
|
||||
* Copyright 2012 Texas Instruments
|
||||
*
|
||||
* Author: Milo(Woogyom) 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/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/regulator/lp872x.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
/* Registers : LP8720/8725 shared */
|
||||
#define LP872X_GENERAL_CFG 0x00
|
||||
#define LP872X_LDO1_VOUT 0x01
|
||||
#define LP872X_LDO2_VOUT 0x02
|
||||
#define LP872X_LDO3_VOUT 0x03
|
||||
#define LP872X_LDO4_VOUT 0x04
|
||||
#define LP872X_LDO5_VOUT 0x05
|
||||
|
||||
/* Registers : LP8720 */
|
||||
#define LP8720_BUCK_VOUT1 0x06
|
||||
#define LP8720_BUCK_VOUT2 0x07
|
||||
#define LP8720_ENABLE 0x08
|
||||
|
||||
/* Registers : LP8725 */
|
||||
#define LP8725_LILO1_VOUT 0x06
|
||||
#define LP8725_LILO2_VOUT 0x07
|
||||
#define LP8725_BUCK1_VOUT1 0x08
|
||||
#define LP8725_BUCK1_VOUT2 0x09
|
||||
#define LP8725_BUCK2_VOUT1 0x0A
|
||||
#define LP8725_BUCK2_VOUT2 0x0B
|
||||
#define LP8725_BUCK_CTRL 0x0C
|
||||
#define LP8725_LDO_CTRL 0x0D
|
||||
|
||||
/* Mask/shift : LP8720/LP8725 shared */
|
||||
#define LP872X_VOUT_M 0x1F
|
||||
#define LP872X_START_DELAY_M 0xE0
|
||||
#define LP872X_START_DELAY_S 5
|
||||
#define LP872X_EN_LDO1_M BIT(0)
|
||||
#define LP872X_EN_LDO2_M BIT(1)
|
||||
#define LP872X_EN_LDO3_M BIT(2)
|
||||
#define LP872X_EN_LDO4_M BIT(3)
|
||||
#define LP872X_EN_LDO5_M BIT(4)
|
||||
|
||||
/* Mask/shift : LP8720 */
|
||||
#define LP8720_TIMESTEP_S 0 /* Addr 00h */
|
||||
#define LP8720_TIMESTEP_M BIT(0)
|
||||
#define LP8720_EXT_DVS_M BIT(2)
|
||||
#define LP8720_BUCK_FPWM_S 5 /* Addr 07h */
|
||||
#define LP8720_BUCK_FPWM_M BIT(5)
|
||||
#define LP8720_EN_BUCK_M BIT(5) /* Addr 08h */
|
||||
#define LP8720_DVS_SEL_M BIT(7)
|
||||
|
||||
/* Mask/shift : LP8725 */
|
||||
#define LP8725_TIMESTEP_M 0xC0 /* Addr 00h */
|
||||
#define LP8725_TIMESTEP_S 6
|
||||
#define LP8725_BUCK1_EN_M BIT(0)
|
||||
#define LP8725_DVS1_M BIT(2)
|
||||
#define LP8725_DVS2_M BIT(3)
|
||||
#define LP8725_BUCK2_EN_M BIT(4)
|
||||
#define LP8725_BUCK_CL_M 0xC0 /* Addr 09h, 0Bh */
|
||||
#define LP8725_BUCK_CL_S 6
|
||||
#define LP8725_BUCK1_FPWM_S 1 /* Addr 0Ch */
|
||||
#define LP8725_BUCK1_FPWM_M BIT(1)
|
||||
#define LP8725_BUCK2_FPWM_S 5
|
||||
#define LP8725_BUCK2_FPWM_M BIT(5)
|
||||
#define LP8725_EN_LILO1_M BIT(5) /* Addr 0Dh */
|
||||
#define LP8725_EN_LILO2_M BIT(6)
|
||||
|
||||
/* PWM mode */
|
||||
#define LP872X_FORCE_PWM 1
|
||||
#define LP872X_AUTO_PWM 0
|
||||
|
||||
#define LP8720_NUM_REGULATORS 6
|
||||
#define LP8725_NUM_REGULATORS 9
|
||||
#define EXTERN_DVS_USED 0
|
||||
#define MAX_DELAY 6
|
||||
|
||||
/* dump registers in regmap-debugfs */
|
||||
#define MAX_REGISTERS 0x0F
|
||||
|
||||
enum lp872x_id {
|
||||
LP8720,
|
||||
LP8725,
|
||||
};
|
||||
|
||||
struct lp872x {
|
||||
struct regmap *regmap;
|
||||
struct device *dev;
|
||||
enum lp872x_id chipid;
|
||||
struct lp872x_platform_data *pdata;
|
||||
struct regulator_dev **regulators;
|
||||
int num_regulators;
|
||||
enum lp872x_dvs_state dvs_pin;
|
||||
int dvs_gpio;
|
||||
};
|
||||
|
||||
/* LP8720/LP8725 shared voltage table for LDOs */
|
||||
static const unsigned int lp872x_ldo_vtbl[] = {
|
||||
1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000,
|
||||
1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 2000000,
|
||||
2100000, 2200000, 2300000, 2400000, 2500000, 2600000, 2650000, 2700000,
|
||||
2750000, 2800000, 2850000, 2900000, 2950000, 3000000, 3100000, 3300000,
|
||||
};
|
||||
|
||||
/* LP8720 LDO4 voltage table */
|
||||
static const unsigned int lp8720_ldo4_vtbl[] = {
|
||||
800000, 850000, 900000, 1000000, 1100000, 1200000, 1250000, 1300000,
|
||||
1350000, 1400000, 1450000, 1500000, 1550000, 1600000, 1650000, 1700000,
|
||||
1750000, 1800000, 1850000, 1900000, 2000000, 2100000, 2200000, 2300000,
|
||||
2400000, 2500000, 2600000, 2650000, 2700000, 2750000, 2800000, 2850000,
|
||||
};
|
||||
|
||||
/* LP8725 LILO(Low Input Low Output) voltage table */
|
||||
static const unsigned int lp8725_lilo_vtbl[] = {
|
||||
800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000,
|
||||
1200000, 1250000, 1300000, 1350000, 1400000, 1500000, 1600000, 1700000,
|
||||
1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
|
||||
2600000, 2700000, 2800000, 2850000, 2900000, 3000000, 3100000, 3300000,
|
||||
};
|
||||
|
||||
/* LP8720 BUCK voltage table */
|
||||
#define EXT_R 0 /* external resistor divider */
|
||||
static const unsigned int lp8720_buck_vtbl[] = {
|
||||
EXT_R, 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000,
|
||||
1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
|
||||
1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000,
|
||||
1950000, 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000,
|
||||
};
|
||||
|
||||
/* LP8725 BUCK voltage table */
|
||||
static const unsigned int lp8725_buck_vtbl[] = {
|
||||
800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000,
|
||||
1200000, 1250000, 1300000, 1350000, 1400000, 1500000, 1600000, 1700000,
|
||||
1750000, 1800000, 1850000, 1900000, 2000000, 2100000, 2200000, 2300000,
|
||||
2400000, 2500000, 2600000, 2700000, 2800000, 2850000, 2900000, 3000000,
|
||||
};
|
||||
|
||||
/* LP8725 BUCK current limit */
|
||||
static const unsigned int lp8725_buck_uA[] = {
|
||||
460000, 780000, 1050000, 1370000,
|
||||
};
|
||||
|
||||
static int lp872x_read_byte(struct lp872x *lp, u8 addr, u8 *data)
|
||||
{
|
||||
int ret;
|
||||
unsigned int val;
|
||||
|
||||
ret = regmap_read(lp->regmap, addr, &val);
|
||||
if (ret < 0) {
|
||||
dev_err(lp->dev, "failed to read 0x%.2x\n", addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*data = (u8)val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int lp872x_write_byte(struct lp872x *lp, u8 addr, u8 data)
|
||||
{
|
||||
return regmap_write(lp->regmap, addr, data);
|
||||
}
|
||||
|
||||
static inline int lp872x_update_bits(struct lp872x *lp, u8 addr,
|
||||
unsigned int mask, u8 data)
|
||||
{
|
||||
return regmap_update_bits(lp->regmap, addr, mask, data);
|
||||
}
|
||||
|
||||
static int _rdev_to_offset(struct regulator_dev *rdev)
|
||||
{
|
||||
enum lp872x_regulator_id id = rdev_get_id(rdev);
|
||||
|
||||
switch (id) {
|
||||
case LP8720_ID_LDO1 ... LP8720_ID_BUCK:
|
||||
return id;
|
||||
case LP8725_ID_LDO1 ... LP8725_ID_BUCK2:
|
||||
return id - LP8725_ID_BASE;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int lp872x_get_timestep_usec(struct lp872x *lp)
|
||||
{
|
||||
enum lp872x_id chip = lp->chipid;
|
||||
u8 val, mask, shift;
|
||||
int *time_usec, size, ret;
|
||||
int lp8720_time_usec[] = { 25, 50 };
|
||||
int lp8725_time_usec[] = { 32, 64, 128, 256 };
|
||||
|
||||
switch (chip) {
|
||||
case LP8720:
|
||||
mask = LP8720_TIMESTEP_M;
|
||||
shift = LP8720_TIMESTEP_S;
|
||||
time_usec = &lp8720_time_usec[0];
|
||||
size = ARRAY_SIZE(lp8720_time_usec);
|
||||
break;
|
||||
case LP8725:
|
||||
mask = LP8725_TIMESTEP_M;
|
||||
shift = LP8725_TIMESTEP_S;
|
||||
time_usec = &lp8725_time_usec[0];
|
||||
size = ARRAY_SIZE(lp8725_time_usec);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
val = (val & mask) >> shift;
|
||||
if (val >= size)
|
||||
return -EINVAL;
|
||||
|
||||
return *(time_usec + val);
|
||||
}
|
||||
|
||||
static int lp872x_regulator_enable_time(struct regulator_dev *rdev)
|
||||
{
|
||||
struct lp872x *lp = rdev_get_drvdata(rdev);
|
||||
enum lp872x_regulator_id regulator = rdev_get_id(rdev);
|
||||
int time_step_us = lp872x_get_timestep_usec(lp);
|
||||
int ret, offset;
|
||||
u8 addr, val;
|
||||
|
||||
if (time_step_us < 0)
|
||||
return -EINVAL;
|
||||
|
||||
switch (regulator) {
|
||||
case LP8720_ID_LDO1 ... LP8720_ID_LDO5:
|
||||
case LP8725_ID_LDO1 ... LP8725_ID_LILO2:
|
||||
offset = _rdev_to_offset(rdev);
|
||||
if (offset < 0)
|
||||
return -EINVAL;
|
||||
|
||||
addr = LP872X_LDO1_VOUT + offset;
|
||||
break;
|
||||
case LP8720_ID_BUCK:
|
||||
addr = LP8720_BUCK_VOUT1;
|
||||
break;
|
||||
case LP8725_ID_BUCK1:
|
||||
addr = LP8725_BUCK1_VOUT1;
|
||||
break;
|
||||
case LP8725_ID_BUCK2:
|
||||
addr = LP8725_BUCK2_VOUT1;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = lp872x_read_byte(lp, addr, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = (val & LP872X_START_DELAY_M) >> LP872X_START_DELAY_S;
|
||||
|
||||
return val > MAX_DELAY ? 0 : val * time_step_us;
|
||||
}
|
||||
|
||||
static void lp872x_set_dvs(struct lp872x *lp, int gpio)
|
||||
{
|
||||
enum lp872x_dvs_sel dvs_sel = lp->pdata->dvs->vsel;
|
||||
enum lp872x_dvs_state state;
|
||||
|
||||
state = dvs_sel == SEL_V1 ? DVS_HIGH : DVS_LOW;
|
||||
gpio_set_value(gpio, state);
|
||||
lp->dvs_pin = state;
|
||||
}
|
||||
|
||||
static u8 lp872x_select_buck_vout_addr(struct lp872x *lp,
|
||||
enum lp872x_regulator_id buck)
|
||||
{
|
||||
u8 val, addr;
|
||||
|
||||
if (lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val))
|
||||
return 0;
|
||||
|
||||
switch (buck) {
|
||||
case LP8720_ID_BUCK:
|
||||
if (val & LP8720_EXT_DVS_M) {
|
||||
addr = (lp->dvs_pin == DVS_HIGH) ?
|
||||
LP8720_BUCK_VOUT1 : LP8720_BUCK_VOUT2;
|
||||
} else {
|
||||
if (lp872x_read_byte(lp, LP8720_ENABLE, &val))
|
||||
return 0;
|
||||
|
||||
addr = val & LP8720_DVS_SEL_M ?
|
||||
LP8720_BUCK_VOUT1 : LP8720_BUCK_VOUT2;
|
||||
}
|
||||
break;
|
||||
case LP8725_ID_BUCK1:
|
||||
if (val & LP8725_DVS1_M)
|
||||
addr = LP8725_BUCK1_VOUT1;
|
||||
else
|
||||
addr = (lp->dvs_pin == DVS_HIGH) ?
|
||||
LP8725_BUCK1_VOUT1 : LP8725_BUCK1_VOUT2;
|
||||
break;
|
||||
case LP8725_ID_BUCK2:
|
||||
addr = val & LP8725_DVS2_M ?
|
||||
LP8725_BUCK2_VOUT1 : LP8725_BUCK2_VOUT2;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static bool lp872x_is_valid_buck_addr(u8 addr)
|
||||
{
|
||||
switch (addr) {
|
||||
case LP8720_BUCK_VOUT1:
|
||||
case LP8720_BUCK_VOUT2:
|
||||
case LP8725_BUCK1_VOUT1:
|
||||
case LP8725_BUCK1_VOUT2:
|
||||
case LP8725_BUCK2_VOUT1:
|
||||
case LP8725_BUCK2_VOUT2:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int lp872x_buck_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct lp872x *lp = rdev_get_drvdata(rdev);
|
||||
enum lp872x_regulator_id buck = rdev_get_id(rdev);
|
||||
u8 addr, mask = LP872X_VOUT_M;
|
||||
struct lp872x_dvs *dvs = lp->pdata->dvs;
|
||||
|
||||
if (dvs && gpio_is_valid(dvs->gpio))
|
||||
lp872x_set_dvs(lp, dvs->gpio);
|
||||
|
||||
addr = lp872x_select_buck_vout_addr(lp, buck);
|
||||
if (!lp872x_is_valid_buck_addr(addr))
|
||||
return -EINVAL;
|
||||
|
||||
return lp872x_update_bits(lp, addr, mask, selector);
|
||||
}
|
||||
|
||||
static int lp872x_buck_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct lp872x *lp = rdev_get_drvdata(rdev);
|
||||
enum lp872x_regulator_id buck = rdev_get_id(rdev);
|
||||
u8 addr, val;
|
||||
int ret;
|
||||
|
||||
addr = lp872x_select_buck_vout_addr(lp, buck);
|
||||
if (!lp872x_is_valid_buck_addr(addr))
|
||||
return -EINVAL;
|
||||
|
||||
ret = lp872x_read_byte(lp, addr, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return val & LP872X_VOUT_M;
|
||||
}
|
||||
|
||||
static int lp8725_buck_set_current_limit(struct regulator_dev *rdev,
|
||||
int min_uA, int max_uA)
|
||||
{
|
||||
struct lp872x *lp = rdev_get_drvdata(rdev);
|
||||
enum lp872x_regulator_id buck = rdev_get_id(rdev);
|
||||
int i, max = ARRAY_SIZE(lp8725_buck_uA);
|
||||
u8 addr, val;
|
||||
|
||||
switch (buck) {
|
||||
case LP8725_ID_BUCK1:
|
||||
addr = LP8725_BUCK1_VOUT2;
|
||||
break;
|
||||
case LP8725_ID_BUCK2:
|
||||
addr = LP8725_BUCK2_VOUT2;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < max ; i++)
|
||||
if (lp8725_buck_uA[i] >= min_uA &&
|
||||
lp8725_buck_uA[i] <= max_uA)
|
||||
break;
|
||||
|
||||
if (i == max)
|
||||
return -EINVAL;
|
||||
|
||||
val = i << LP8725_BUCK_CL_S;
|
||||
|
||||
return lp872x_update_bits(lp, addr, LP8725_BUCK_CL_M, val);
|
||||
}
|
||||
|
||||
static int lp8725_buck_get_current_limit(struct regulator_dev *rdev)
|
||||
{
|
||||
struct lp872x *lp = rdev_get_drvdata(rdev);
|
||||
enum lp872x_regulator_id buck = rdev_get_id(rdev);
|
||||
u8 addr, val;
|
||||
int ret;
|
||||
|
||||
switch (buck) {
|
||||
case LP8725_ID_BUCK1:
|
||||
addr = LP8725_BUCK1_VOUT2;
|
||||
break;
|
||||
case LP8725_ID_BUCK2:
|
||||
addr = LP8725_BUCK2_VOUT2;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = lp872x_read_byte(lp, addr, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = (val & LP8725_BUCK_CL_M) >> LP8725_BUCK_CL_S;
|
||||
|
||||
return (val < ARRAY_SIZE(lp8725_buck_uA)) ?
|
||||
lp8725_buck_uA[val] : -EINVAL;
|
||||
}
|
||||
|
||||
static int lp872x_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
{
|
||||
struct lp872x *lp = rdev_get_drvdata(rdev);
|
||||
enum lp872x_regulator_id buck = rdev_get_id(rdev);
|
||||
u8 addr, mask, shift, val;
|
||||
|
||||
switch (buck) {
|
||||
case LP8720_ID_BUCK:
|
||||
addr = LP8720_BUCK_VOUT2;
|
||||
mask = LP8720_BUCK_FPWM_M;
|
||||
shift = LP8720_BUCK_FPWM_S;
|
||||
break;
|
||||
case LP8725_ID_BUCK1:
|
||||
addr = LP8725_BUCK_CTRL;
|
||||
mask = LP8725_BUCK1_FPWM_M;
|
||||
shift = LP8725_BUCK1_FPWM_S;
|
||||
break;
|
||||
case LP8725_ID_BUCK2:
|
||||
addr = LP8725_BUCK_CTRL;
|
||||
mask = LP8725_BUCK2_FPWM_M;
|
||||
shift = LP8725_BUCK2_FPWM_S;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mode == REGULATOR_MODE_FAST)
|
||||
val = LP872X_FORCE_PWM << shift;
|
||||
else if (mode == REGULATOR_MODE_NORMAL)
|
||||
val = LP872X_AUTO_PWM << shift;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return lp872x_update_bits(lp, addr, mask, val);
|
||||
}
|
||||
|
||||
static unsigned int lp872x_buck_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
struct lp872x *lp = rdev_get_drvdata(rdev);
|
||||
enum lp872x_regulator_id buck = rdev_get_id(rdev);
|
||||
u8 addr, mask, val;
|
||||
int ret;
|
||||
|
||||
switch (buck) {
|
||||
case LP8720_ID_BUCK:
|
||||
addr = LP8720_BUCK_VOUT2;
|
||||
mask = LP8720_BUCK_FPWM_M;
|
||||
break;
|
||||
case LP8725_ID_BUCK1:
|
||||
addr = LP8725_BUCK_CTRL;
|
||||
mask = LP8725_BUCK1_FPWM_M;
|
||||
break;
|
||||
case LP8725_ID_BUCK2:
|
||||
addr = LP8725_BUCK_CTRL;
|
||||
mask = LP8725_BUCK2_FPWM_M;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = lp872x_read_byte(lp, addr, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return val & mask ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static struct regulator_ops lp872x_ldo_ops = {
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.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 = lp872x_regulator_enable_time,
|
||||
};
|
||||
|
||||
static struct regulator_ops lp8720_buck_ops = {
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.set_voltage_sel = lp872x_buck_set_voltage_sel,
|
||||
.get_voltage_sel = lp872x_buck_get_voltage_sel,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable_time = lp872x_regulator_enable_time,
|
||||
.set_mode = lp872x_buck_set_mode,
|
||||
.get_mode = lp872x_buck_get_mode,
|
||||
};
|
||||
|
||||
static struct regulator_ops lp8725_buck_ops = {
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.set_voltage_sel = lp872x_buck_set_voltage_sel,
|
||||
.get_voltage_sel = lp872x_buck_get_voltage_sel,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable_time = lp872x_regulator_enable_time,
|
||||
.set_mode = lp872x_buck_set_mode,
|
||||
.get_mode = lp872x_buck_get_mode,
|
||||
.set_current_limit = lp8725_buck_set_current_limit,
|
||||
.get_current_limit = lp8725_buck_get_current_limit,
|
||||
};
|
||||
|
||||
static struct regulator_desc lp8720_regulator_desc[] = {
|
||||
{
|
||||
.name = "ldo1",
|
||||
.id = LP8720_ID_LDO1,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
.volt_table = lp872x_ldo_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP872X_LDO1_VOUT,
|
||||
.vsel_mask = LP872X_VOUT_M,
|
||||
.enable_reg = LP8720_ENABLE,
|
||||
.enable_mask = LP872X_EN_LDO1_M,
|
||||
},
|
||||
{
|
||||
.name = "ldo2",
|
||||
.id = LP8720_ID_LDO2,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
.volt_table = lp872x_ldo_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP872X_LDO2_VOUT,
|
||||
.vsel_mask = LP872X_VOUT_M,
|
||||
.enable_reg = LP8720_ENABLE,
|
||||
.enable_mask = LP872X_EN_LDO2_M,
|
||||
},
|
||||
{
|
||||
.name = "ldo3",
|
||||
.id = LP8720_ID_LDO3,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
.volt_table = lp872x_ldo_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP872X_LDO3_VOUT,
|
||||
.vsel_mask = LP872X_VOUT_M,
|
||||
.enable_reg = LP8720_ENABLE,
|
||||
.enable_mask = LP872X_EN_LDO3_M,
|
||||
},
|
||||
{
|
||||
.name = "ldo4",
|
||||
.id = LP8720_ID_LDO4,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8720_ldo4_vtbl),
|
||||
.volt_table = lp8720_ldo4_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP872X_LDO4_VOUT,
|
||||
.vsel_mask = LP872X_VOUT_M,
|
||||
.enable_reg = LP8720_ENABLE,
|
||||
.enable_mask = LP872X_EN_LDO4_M,
|
||||
},
|
||||
{
|
||||
.name = "ldo5",
|
||||
.id = LP8720_ID_LDO5,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
.volt_table = lp872x_ldo_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP872X_LDO5_VOUT,
|
||||
.vsel_mask = LP872X_VOUT_M,
|
||||
.enable_reg = LP8720_ENABLE,
|
||||
.enable_mask = LP872X_EN_LDO5_M,
|
||||
},
|
||||
{
|
||||
.name = "buck",
|
||||
.id = LP8720_ID_BUCK,
|
||||
.ops = &lp8720_buck_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8720_buck_vtbl),
|
||||
.volt_table = lp8720_buck_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = LP8720_ENABLE,
|
||||
.enable_mask = LP8720_EN_BUCK_M,
|
||||
},
|
||||
};
|
||||
|
||||
static struct regulator_desc lp8725_regulator_desc[] = {
|
||||
{
|
||||
.name = "ldo1",
|
||||
.id = LP8725_ID_LDO1,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
.volt_table = lp872x_ldo_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP872X_LDO1_VOUT,
|
||||
.vsel_mask = LP872X_VOUT_M,
|
||||
.enable_reg = LP8725_LDO_CTRL,
|
||||
.enable_mask = LP872X_EN_LDO1_M,
|
||||
},
|
||||
{
|
||||
.name = "ldo2",
|
||||
.id = LP8725_ID_LDO2,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
.volt_table = lp872x_ldo_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP872X_LDO2_VOUT,
|
||||
.vsel_mask = LP872X_VOUT_M,
|
||||
.enable_reg = LP8725_LDO_CTRL,
|
||||
.enable_mask = LP872X_EN_LDO2_M,
|
||||
},
|
||||
{
|
||||
.name = "ldo3",
|
||||
.id = LP8725_ID_LDO3,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
.volt_table = lp872x_ldo_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP872X_LDO3_VOUT,
|
||||
.vsel_mask = LP872X_VOUT_M,
|
||||
.enable_reg = LP8725_LDO_CTRL,
|
||||
.enable_mask = LP872X_EN_LDO3_M,
|
||||
},
|
||||
{
|
||||
.name = "ldo4",
|
||||
.id = LP8725_ID_LDO4,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
.volt_table = lp872x_ldo_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP872X_LDO4_VOUT,
|
||||
.vsel_mask = LP872X_VOUT_M,
|
||||
.enable_reg = LP8725_LDO_CTRL,
|
||||
.enable_mask = LP872X_EN_LDO4_M,
|
||||
},
|
||||
{
|
||||
.name = "ldo5",
|
||||
.id = LP8725_ID_LDO5,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
|
||||
.volt_table = lp872x_ldo_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP872X_LDO5_VOUT,
|
||||
.vsel_mask = LP872X_VOUT_M,
|
||||
.enable_reg = LP8725_LDO_CTRL,
|
||||
.enable_mask = LP872X_EN_LDO5_M,
|
||||
},
|
||||
{
|
||||
.name = "lilo1",
|
||||
.id = LP8725_ID_LILO1,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8725_lilo_vtbl),
|
||||
.volt_table = lp8725_lilo_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8725_LILO1_VOUT,
|
||||
.vsel_mask = LP872X_VOUT_M,
|
||||
.enable_reg = LP8725_LDO_CTRL,
|
||||
.enable_mask = LP8725_EN_LILO1_M,
|
||||
},
|
||||
{
|
||||
.name = "lilo2",
|
||||
.id = LP8725_ID_LILO2,
|
||||
.ops = &lp872x_ldo_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8725_lilo_vtbl),
|
||||
.volt_table = lp8725_lilo_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8725_LILO2_VOUT,
|
||||
.vsel_mask = LP872X_VOUT_M,
|
||||
.enable_reg = LP8725_LDO_CTRL,
|
||||
.enable_mask = LP8725_EN_LILO2_M,
|
||||
},
|
||||
{
|
||||
.name = "buck1",
|
||||
.id = LP8725_ID_BUCK1,
|
||||
.ops = &lp8725_buck_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8725_buck_vtbl),
|
||||
.volt_table = lp8725_buck_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = LP872X_GENERAL_CFG,
|
||||
.enable_mask = LP8725_BUCK1_EN_M,
|
||||
},
|
||||
{
|
||||
.name = "buck2",
|
||||
.id = LP8725_ID_BUCK2,
|
||||
.ops = &lp8725_buck_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8725_buck_vtbl),
|
||||
.volt_table = lp8725_buck_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = LP872X_GENERAL_CFG,
|
||||
.enable_mask = LP8725_BUCK2_EN_M,
|
||||
},
|
||||
};
|
||||
|
||||
static int lp872x_check_dvs_validity(struct lp872x *lp)
|
||||
{
|
||||
struct lp872x_dvs *dvs = lp->pdata->dvs;
|
||||
u8 val = 0;
|
||||
int ret;
|
||||
|
||||
ret = lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = 0;
|
||||
if (lp->chipid == LP8720) {
|
||||
if (val & LP8720_EXT_DVS_M)
|
||||
ret = dvs ? 0 : -EINVAL;
|
||||
} else {
|
||||
if ((val & LP8725_DVS1_M) == EXTERN_DVS_USED)
|
||||
ret = dvs ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lp872x_init_dvs(struct lp872x *lp)
|
||||
{
|
||||
int ret, gpio;
|
||||
struct lp872x_dvs *dvs = lp->pdata->dvs;
|
||||
enum lp872x_dvs_state pinstate;
|
||||
|
||||
ret = lp872x_check_dvs_validity(lp);
|
||||
if (ret) {
|
||||
dev_warn(lp->dev, "invalid dvs data: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpio = dvs->gpio;
|
||||
if (!gpio_is_valid(gpio)) {
|
||||
dev_err(lp->dev, "invalid gpio: %d\n", gpio);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pinstate = dvs->init_state;
|
||||
ret = devm_gpio_request_one(lp->dev, gpio, pinstate, "LP872X DVS");
|
||||
if (ret) {
|
||||
dev_err(lp->dev, "gpio request err: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
lp->dvs_pin = pinstate;
|
||||
lp->dvs_gpio = gpio;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lp872x_config(struct lp872x *lp)
|
||||
{
|
||||
struct lp872x_platform_data *pdata = lp->pdata;
|
||||
int ret;
|
||||
|
||||
if (!pdata->update_config)
|
||||
return 0;
|
||||
|
||||
ret = lp872x_write_byte(lp, LP872X_GENERAL_CFG, pdata->general_config);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return lp872x_init_dvs(lp);
|
||||
}
|
||||
|
||||
static struct regulator_init_data
|
||||
*lp872x_find_regulator_init_data(int id, struct lp872x *lp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < lp->num_regulators; i++) {
|
||||
if (lp->pdata->regulator_data[i].id == id)
|
||||
return lp->pdata->regulator_data[i].init_data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int lp872x_regulator_register(struct lp872x *lp)
|
||||
{
|
||||
struct regulator_desc *desc;
|
||||
struct regulator_config cfg = { };
|
||||
struct regulator_dev *rdev;
|
||||
int i, ret;
|
||||
|
||||
for (i = 0 ; i < lp->num_regulators ; i++) {
|
||||
desc = (lp->chipid == LP8720) ? &lp8720_regulator_desc[i] :
|
||||
&lp8725_regulator_desc[i];
|
||||
|
||||
cfg.dev = lp->dev;
|
||||
cfg.init_data = lp872x_find_regulator_init_data(desc->id, lp);
|
||||
cfg.driver_data = lp;
|
||||
cfg.regmap = lp->regmap;
|
||||
|
||||
rdev = regulator_register(desc, &cfg);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(lp->dev, "regulator register err");
|
||||
ret = PTR_ERR(rdev);
|
||||
goto err;
|
||||
}
|
||||
|
||||
*(lp->regulators + i) = rdev;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
while (--i >= 0) {
|
||||
rdev = *(lp->regulators + i);
|
||||
regulator_unregister(rdev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lp872x_regulator_unregister(struct lp872x *lp)
|
||||
{
|
||||
struct regulator_dev *rdev;
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < lp->num_regulators ; i++) {
|
||||
rdev = *(lp->regulators + i);
|
||||
regulator_unregister(rdev);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct regmap_config lp872x_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = MAX_REGISTERS,
|
||||
};
|
||||
|
||||
static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
|
||||
{
|
||||
struct lp872x *lp;
|
||||
struct lp872x_platform_data *pdata = cl->dev.platform_data;
|
||||
int ret, size, num_regulators;
|
||||
const int lp872x_num_regulators[] = {
|
||||
[LP8720] = LP8720_NUM_REGULATORS,
|
||||
[LP8725] = LP8725_NUM_REGULATORS,
|
||||
};
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&cl->dev, "no platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
lp = devm_kzalloc(&cl->dev, sizeof(struct lp872x), GFP_KERNEL);
|
||||
if (!lp)
|
||||
goto err_mem;
|
||||
|
||||
num_regulators = lp872x_num_regulators[id->driver_data];
|
||||
size = sizeof(struct regulator_dev *) * num_regulators;
|
||||
|
||||
lp->regulators = devm_kzalloc(&cl->dev, size, GFP_KERNEL);
|
||||
if (!lp->regulators)
|
||||
goto err_mem;
|
||||
|
||||
lp->regmap = devm_regmap_init_i2c(cl, &lp872x_regmap_config);
|
||||
if (IS_ERR(lp->regmap)) {
|
||||
ret = PTR_ERR(lp->regmap);
|
||||
dev_err(&cl->dev, "regmap init i2c err: %d\n", ret);
|
||||
goto err_dev;
|
||||
}
|
||||
|
||||
lp->dev = &cl->dev;
|
||||
lp->pdata = pdata;
|
||||
lp->chipid = id->driver_data;
|
||||
lp->num_regulators = num_regulators;
|
||||
i2c_set_clientdata(cl, lp);
|
||||
|
||||
ret = lp872x_config(lp);
|
||||
if (ret)
|
||||
goto err_dev;
|
||||
|
||||
return lp872x_regulator_register(lp);
|
||||
|
||||
err_mem:
|
||||
return -ENOMEM;
|
||||
err_dev:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit lp872x_remove(struct i2c_client *cl)
|
||||
{
|
||||
struct lp872x *lp = i2c_get_clientdata(cl);
|
||||
|
||||
lp872x_regulator_unregister(lp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id lp872x_ids[] = {
|
||||
{"lp8720", LP8720},
|
||||
{"lp8725", LP8725},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, lp872x_ids);
|
||||
|
||||
static struct i2c_driver lp872x_driver = {
|
||||
.driver = {
|
||||
.name = "lp872x",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = lp872x_probe,
|
||||
.remove = __devexit_p(lp872x_remove),
|
||||
.id_table = lp872x_ids,
|
||||
};
|
||||
|
||||
module_i2c_driver(lp872x_driver);
|
||||
|
||||
MODULE_DESCRIPTION("TI/National Semiconductor LP872x PMU Regulator Driver");
|
||||
MODULE_AUTHOR("Milo Kim");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,629 @@
|
||||
/*
|
||||
* TI LP8788 MFD - buck regulator driver
|
||||
*
|
||||
* Copyright 2012 Texas Instruments
|
||||
*
|
||||
* Author: Milo(Woogyom) 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/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/mfd/lp8788.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
/* register address */
|
||||
#define LP8788_EN_BUCK 0x0C
|
||||
#define LP8788_BUCK_DVS_SEL 0x1D
|
||||
#define LP8788_BUCK1_VOUT0 0x1E
|
||||
#define LP8788_BUCK1_VOUT1 0x1F
|
||||
#define LP8788_BUCK1_VOUT2 0x20
|
||||
#define LP8788_BUCK1_VOUT3 0x21
|
||||
#define LP8788_BUCK2_VOUT0 0x22
|
||||
#define LP8788_BUCK2_VOUT1 0x23
|
||||
#define LP8788_BUCK2_VOUT2 0x24
|
||||
#define LP8788_BUCK2_VOUT3 0x25
|
||||
#define LP8788_BUCK3_VOUT 0x26
|
||||
#define LP8788_BUCK4_VOUT 0x27
|
||||
#define LP8788_BUCK1_TIMESTEP 0x28
|
||||
#define LP8788_BUCK_PWM 0x2D
|
||||
|
||||
/* mask/shift bits */
|
||||
#define LP8788_EN_BUCK1_M BIT(0) /* Addr 0Ch */
|
||||
#define LP8788_EN_BUCK2_M BIT(1)
|
||||
#define LP8788_EN_BUCK3_M BIT(2)
|
||||
#define LP8788_EN_BUCK4_M BIT(3)
|
||||
#define LP8788_BUCK1_DVS_SEL_M 0x04 /* Addr 1Dh */
|
||||
#define LP8788_BUCK1_DVS_M 0x03
|
||||
#define LP8788_BUCK1_DVS_S 0
|
||||
#define LP8788_BUCK2_DVS_SEL_M 0x40
|
||||
#define LP8788_BUCK2_DVS_M 0x30
|
||||
#define LP8788_BUCK2_DVS_S 4
|
||||
#define LP8788_BUCK1_DVS_I2C BIT(2)
|
||||
#define LP8788_BUCK2_DVS_I2C BIT(6)
|
||||
#define LP8788_BUCK1_DVS_PIN (0 << 2)
|
||||
#define LP8788_BUCK2_DVS_PIN (0 << 6)
|
||||
#define LP8788_VOUT_M 0x1F /* Addr 1Eh ~ 27h */
|
||||
#define LP8788_STARTUP_TIME_M 0xF8 /* Addr 28h ~ 2Bh */
|
||||
#define LP8788_STARTUP_TIME_S 3
|
||||
#define LP8788_FPWM_BUCK1_M BIT(0) /* Addr 2Dh */
|
||||
#define LP8788_FPWM_BUCK1_S 0
|
||||
#define LP8788_FPWM_BUCK2_M BIT(1)
|
||||
#define LP8788_FPWM_BUCK2_S 1
|
||||
#define LP8788_FPWM_BUCK3_M BIT(2)
|
||||
#define LP8788_FPWM_BUCK3_S 2
|
||||
#define LP8788_FPWM_BUCK4_M BIT(3)
|
||||
#define LP8788_FPWM_BUCK4_S 3
|
||||
|
||||
#define INVALID_ADDR 0xFF
|
||||
#define LP8788_FORCE_PWM 1
|
||||
#define LP8788_AUTO_PWM 0
|
||||
#define PIN_LOW 0
|
||||
#define PIN_HIGH 1
|
||||
#define ENABLE_TIME_USEC 32
|
||||
|
||||
enum lp8788_dvs_state {
|
||||
DVS_LOW = GPIOF_OUT_INIT_LOW,
|
||||
DVS_HIGH = GPIOF_OUT_INIT_HIGH,
|
||||
};
|
||||
|
||||
enum lp8788_dvs_mode {
|
||||
REGISTER,
|
||||
EXTPIN,
|
||||
};
|
||||
|
||||
enum lp8788_buck_id {
|
||||
BUCK1,
|
||||
BUCK2,
|
||||
BUCK3,
|
||||
BUCK4,
|
||||
};
|
||||
|
||||
struct lp8788_pwm_map {
|
||||
u8 mask;
|
||||
u8 shift;
|
||||
};
|
||||
|
||||
struct lp8788_buck {
|
||||
struct lp8788 *lp;
|
||||
struct regulator_dev *regulator;
|
||||
struct lp8788_pwm_map *pmap;
|
||||
void *dvs;
|
||||
};
|
||||
|
||||
/* BUCK 1 ~ 4 voltage table */
|
||||
static const int lp8788_buck_vtbl[] = {
|
||||
500000, 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000,
|
||||
1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
|
||||
1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000,
|
||||
1950000, 2000000,
|
||||
};
|
||||
|
||||
/* buck pwm mode selection : used for set/get_mode in regulator ops
|
||||
* @forced pwm : fast mode
|
||||
* @auto pwm : normal mode
|
||||
*/
|
||||
static struct lp8788_pwm_map buck_pmap[] = {
|
||||
[BUCK1] = {
|
||||
.mask = LP8788_FPWM_BUCK1_M,
|
||||
.shift = LP8788_FPWM_BUCK1_S,
|
||||
},
|
||||
[BUCK2] = {
|
||||
.mask = LP8788_FPWM_BUCK2_M,
|
||||
.shift = LP8788_FPWM_BUCK2_S,
|
||||
},
|
||||
[BUCK3] = {
|
||||
.mask = LP8788_FPWM_BUCK3_M,
|
||||
.shift = LP8788_FPWM_BUCK3_S,
|
||||
},
|
||||
[BUCK4] = {
|
||||
.mask = LP8788_FPWM_BUCK4_M,
|
||||
.shift = LP8788_FPWM_BUCK4_S,
|
||||
},
|
||||
};
|
||||
|
||||
static const u8 buck1_vout_addr[] = {
|
||||
LP8788_BUCK1_VOUT0, LP8788_BUCK1_VOUT1,
|
||||
LP8788_BUCK1_VOUT2, LP8788_BUCK1_VOUT3,
|
||||
};
|
||||
|
||||
static const u8 buck2_vout_addr[] = {
|
||||
LP8788_BUCK2_VOUT0, LP8788_BUCK2_VOUT1,
|
||||
LP8788_BUCK2_VOUT2, LP8788_BUCK2_VOUT3,
|
||||
};
|
||||
|
||||
static void lp8788_buck1_set_dvs(struct lp8788_buck *buck)
|
||||
{
|
||||
struct lp8788_buck1_dvs *dvs = (struct lp8788_buck1_dvs *)buck->dvs;
|
||||
enum lp8788_dvs_state pinstate;
|
||||
|
||||
if (!dvs)
|
||||
return;
|
||||
|
||||
pinstate = dvs->vsel == DVS_SEL_V0 ? DVS_LOW : DVS_HIGH;
|
||||
if (gpio_is_valid(dvs->gpio))
|
||||
gpio_set_value(dvs->gpio, pinstate);
|
||||
}
|
||||
|
||||
static void lp8788_buck2_set_dvs(struct lp8788_buck *buck)
|
||||
{
|
||||
struct lp8788_buck2_dvs *dvs = (struct lp8788_buck2_dvs *)buck->dvs;
|
||||
enum lp8788_dvs_state pin1, pin2;
|
||||
|
||||
if (!dvs)
|
||||
return;
|
||||
|
||||
switch (dvs->vsel) {
|
||||
case DVS_SEL_V0:
|
||||
pin1 = DVS_LOW;
|
||||
pin2 = DVS_LOW;
|
||||
break;
|
||||
case DVS_SEL_V1:
|
||||
pin1 = DVS_HIGH;
|
||||
pin2 = DVS_LOW;
|
||||
break;
|
||||
case DVS_SEL_V2:
|
||||
pin1 = DVS_LOW;
|
||||
pin2 = DVS_HIGH;
|
||||
break;
|
||||
case DVS_SEL_V3:
|
||||
pin1 = DVS_HIGH;
|
||||
pin2 = DVS_HIGH;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(dvs->gpio[0]))
|
||||
gpio_set_value(dvs->gpio[0], pin1);
|
||||
|
||||
if (gpio_is_valid(dvs->gpio[1]))
|
||||
gpio_set_value(dvs->gpio[1], pin2);
|
||||
}
|
||||
|
||||
static void lp8788_set_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id)
|
||||
{
|
||||
switch (id) {
|
||||
case BUCK1:
|
||||
lp8788_buck1_set_dvs(buck);
|
||||
break;
|
||||
case BUCK2:
|
||||
lp8788_buck2_set_dvs(buck);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static enum lp8788_dvs_mode
|
||||
lp8788_get_buck_dvs_ctrl_mode(struct lp8788_buck *buck, enum lp8788_buck_id id)
|
||||
{
|
||||
u8 val, mask;
|
||||
|
||||
switch (id) {
|
||||
case BUCK1:
|
||||
mask = LP8788_BUCK1_DVS_SEL_M;
|
||||
break;
|
||||
case BUCK2:
|
||||
mask = LP8788_BUCK2_DVS_SEL_M;
|
||||
break;
|
||||
default:
|
||||
return REGISTER;
|
||||
}
|
||||
|
||||
lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
|
||||
|
||||
return val & mask ? REGISTER : EXTPIN;
|
||||
}
|
||||
|
||||
static bool lp8788_is_valid_buck_addr(u8 addr)
|
||||
{
|
||||
switch (addr) {
|
||||
case LP8788_BUCK1_VOUT0:
|
||||
case LP8788_BUCK1_VOUT1:
|
||||
case LP8788_BUCK1_VOUT2:
|
||||
case LP8788_BUCK1_VOUT3:
|
||||
case LP8788_BUCK2_VOUT0:
|
||||
case LP8788_BUCK2_VOUT1:
|
||||
case LP8788_BUCK2_VOUT2:
|
||||
case LP8788_BUCK2_VOUT3:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static u8 lp8788_select_buck_vout_addr(struct lp8788_buck *buck,
|
||||
enum lp8788_buck_id id)
|
||||
{
|
||||
enum lp8788_dvs_mode mode = lp8788_get_buck_dvs_ctrl_mode(buck, id);
|
||||
struct lp8788_buck1_dvs *b1_dvs;
|
||||
struct lp8788_buck2_dvs *b2_dvs;
|
||||
u8 val, idx, addr;
|
||||
int pin1, pin2;
|
||||
|
||||
switch (id) {
|
||||
case BUCK1:
|
||||
if (mode == EXTPIN) {
|
||||
b1_dvs = (struct lp8788_buck1_dvs *)buck->dvs;
|
||||
if (!b1_dvs)
|
||||
goto err;
|
||||
|
||||
idx = gpio_get_value(b1_dvs->gpio) ? 1 : 0;
|
||||
} else {
|
||||
lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
|
||||
idx = (val & LP8788_BUCK1_DVS_M) >> LP8788_BUCK1_DVS_S;
|
||||
}
|
||||
addr = buck1_vout_addr[idx];
|
||||
break;
|
||||
case BUCK2:
|
||||
if (mode == EXTPIN) {
|
||||
b2_dvs = (struct lp8788_buck2_dvs *)buck->dvs;
|
||||
if (!b2_dvs)
|
||||
goto err;
|
||||
|
||||
pin1 = gpio_get_value(b2_dvs->gpio[0]);
|
||||
pin2 = gpio_get_value(b2_dvs->gpio[1]);
|
||||
|
||||
if (pin1 == PIN_LOW && pin2 == PIN_LOW)
|
||||
idx = 0;
|
||||
else if (pin1 == PIN_LOW && pin2 == PIN_HIGH)
|
||||
idx = 2;
|
||||
else if (pin1 == PIN_HIGH && pin2 == PIN_LOW)
|
||||
idx = 1;
|
||||
else
|
||||
idx = 3;
|
||||
} else {
|
||||
lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
|
||||
idx = (val & LP8788_BUCK2_DVS_M) >> LP8788_BUCK2_DVS_S;
|
||||
}
|
||||
addr = buck2_vout_addr[idx];
|
||||
break;
|
||||
default:
|
||||
goto err;
|
||||
}
|
||||
|
||||
return addr;
|
||||
err:
|
||||
return INVALID_ADDR;
|
||||
}
|
||||
|
||||
static int lp8788_buck12_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct lp8788_buck *buck = rdev_get_drvdata(rdev);
|
||||
enum lp8788_buck_id id = rdev_get_id(rdev);
|
||||
u8 addr;
|
||||
|
||||
if (buck->dvs)
|
||||
lp8788_set_dvs(buck, id);
|
||||
|
||||
addr = lp8788_select_buck_vout_addr(buck, id);
|
||||
if (!lp8788_is_valid_buck_addr(addr))
|
||||
return -EINVAL;
|
||||
|
||||
return lp8788_update_bits(buck->lp, addr, LP8788_VOUT_M, selector);
|
||||
}
|
||||
|
||||
static int lp8788_buck12_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct lp8788_buck *buck = rdev_get_drvdata(rdev);
|
||||
enum lp8788_buck_id id = rdev_get_id(rdev);
|
||||
int ret;
|
||||
u8 val, addr;
|
||||
|
||||
addr = lp8788_select_buck_vout_addr(buck, id);
|
||||
if (!lp8788_is_valid_buck_addr(addr))
|
||||
return -EINVAL;
|
||||
|
||||
ret = lp8788_read_byte(buck->lp, addr, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return val & LP8788_VOUT_M;
|
||||
}
|
||||
|
||||
static int lp8788_buck_enable_time(struct regulator_dev *rdev)
|
||||
{
|
||||
struct lp8788_buck *buck = rdev_get_drvdata(rdev);
|
||||
enum lp8788_buck_id id = rdev_get_id(rdev);
|
||||
u8 val, addr = LP8788_BUCK1_TIMESTEP + id;
|
||||
|
||||
if (lp8788_read_byte(buck->lp, addr, &val))
|
||||
return -EINVAL;
|
||||
|
||||
val = (val & LP8788_STARTUP_TIME_M) >> LP8788_STARTUP_TIME_S;
|
||||
|
||||
return ENABLE_TIME_USEC * val;
|
||||
}
|
||||
|
||||
static int lp8788_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
{
|
||||
struct lp8788_buck *buck = rdev_get_drvdata(rdev);
|
||||
struct lp8788_pwm_map *pmap = buck->pmap;
|
||||
u8 val;
|
||||
|
||||
if (!pmap)
|
||||
return -EINVAL;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_FAST:
|
||||
val = LP8788_FORCE_PWM << pmap->shift;
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
val = LP8788_AUTO_PWM << pmap->shift;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return lp8788_update_bits(buck->lp, LP8788_BUCK_PWM, pmap->mask, val);
|
||||
}
|
||||
|
||||
static unsigned int lp8788_buck_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
struct lp8788_buck *buck = rdev_get_drvdata(rdev);
|
||||
struct lp8788_pwm_map *pmap = buck->pmap;
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
if (!pmap)
|
||||
return -EINVAL;
|
||||
|
||||
ret = lp8788_read_byte(buck->lp, LP8788_BUCK_PWM, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return val & pmap->mask ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static struct regulator_ops lp8788_buck12_ops = {
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.set_voltage_sel = lp8788_buck12_set_voltage_sel,
|
||||
.get_voltage_sel = lp8788_buck12_get_voltage_sel,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable_time = lp8788_buck_enable_time,
|
||||
.set_mode = lp8788_buck_set_mode,
|
||||
.get_mode = lp8788_buck_get_mode,
|
||||
};
|
||||
|
||||
static struct regulator_ops lp8788_buck34_ops = {
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.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 = lp8788_buck_enable_time,
|
||||
.set_mode = lp8788_buck_set_mode,
|
||||
.get_mode = lp8788_buck_get_mode,
|
||||
};
|
||||
|
||||
static struct regulator_desc lp8788_buck_desc[] = {
|
||||
{
|
||||
.name = "buck1",
|
||||
.id = BUCK1,
|
||||
.ops = &lp8788_buck12_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
|
||||
.volt_table = lp8788_buck_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = LP8788_EN_BUCK,
|
||||
.enable_mask = LP8788_EN_BUCK1_M,
|
||||
},
|
||||
{
|
||||
.name = "buck2",
|
||||
.id = BUCK2,
|
||||
.ops = &lp8788_buck12_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
|
||||
.volt_table = lp8788_buck_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = LP8788_EN_BUCK,
|
||||
.enable_mask = LP8788_EN_BUCK2_M,
|
||||
},
|
||||
{
|
||||
.name = "buck3",
|
||||
.id = BUCK3,
|
||||
.ops = &lp8788_buck34_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
|
||||
.volt_table = lp8788_buck_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8788_BUCK3_VOUT,
|
||||
.vsel_mask = LP8788_VOUT_M,
|
||||
.enable_reg = LP8788_EN_BUCK,
|
||||
.enable_mask = LP8788_EN_BUCK3_M,
|
||||
},
|
||||
{
|
||||
.name = "buck4",
|
||||
.id = BUCK4,
|
||||
.ops = &lp8788_buck34_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
|
||||
.volt_table = lp8788_buck_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8788_BUCK4_VOUT,
|
||||
.vsel_mask = LP8788_VOUT_M,
|
||||
.enable_reg = LP8788_EN_BUCK,
|
||||
.enable_mask = LP8788_EN_BUCK4_M,
|
||||
},
|
||||
};
|
||||
|
||||
static int lp8788_set_default_dvs_ctrl_mode(struct lp8788 *lp,
|
||||
enum lp8788_buck_id id)
|
||||
{
|
||||
u8 mask, val;
|
||||
|
||||
switch (id) {
|
||||
case BUCK1:
|
||||
mask = LP8788_BUCK1_DVS_SEL_M;
|
||||
val = LP8788_BUCK1_DVS_I2C;
|
||||
break;
|
||||
case BUCK2:
|
||||
mask = LP8788_BUCK2_DVS_SEL_M;
|
||||
val = LP8788_BUCK2_DVS_I2C;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return lp8788_update_bits(lp, LP8788_BUCK_DVS_SEL, mask, val);
|
||||
}
|
||||
|
||||
static int _gpio_request(struct lp8788_buck *buck, int gpio, char *name)
|
||||
{
|
||||
struct device *dev = buck->lp->dev;
|
||||
|
||||
if (!gpio_is_valid(gpio)) {
|
||||
dev_err(dev, "invalid gpio: %d\n", gpio);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return devm_gpio_request_one(dev, gpio, DVS_LOW, name);
|
||||
}
|
||||
|
||||
static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
|
||||
enum lp8788_buck_id id)
|
||||
{
|
||||
struct lp8788_platform_data *pdata = buck->lp->pdata;
|
||||
char *b1_name = "LP8788_B1_DVS";
|
||||
char *b2_name[] = { "LP8788_B2_DVS1", "LP8788_B2_DVS2" };
|
||||
int i, gpio, ret;
|
||||
|
||||
switch (id) {
|
||||
case BUCK1:
|
||||
gpio = pdata->buck1_dvs->gpio;
|
||||
ret = _gpio_request(buck, gpio, b1_name);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
buck->dvs = pdata->buck1_dvs;
|
||||
break;
|
||||
case BUCK2:
|
||||
for (i = 0 ; i < LP8788_NUM_BUCK2_DVS ; i++) {
|
||||
gpio = pdata->buck2_dvs->gpio[i];
|
||||
ret = _gpio_request(buck, gpio, b2_name[i]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
buck->dvs = pdata->buck2_dvs;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lp8788_init_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id)
|
||||
{
|
||||
struct lp8788_platform_data *pdata = buck->lp->pdata;
|
||||
u8 mask[] = { LP8788_BUCK1_DVS_SEL_M, LP8788_BUCK2_DVS_SEL_M };
|
||||
u8 val[] = { LP8788_BUCK1_DVS_PIN, LP8788_BUCK2_DVS_PIN };
|
||||
|
||||
/* no dvs for buck3, 4 */
|
||||
if (id == BUCK3 || id == BUCK4)
|
||||
return 0;
|
||||
|
||||
/* no dvs platform data, then dvs will be selected by I2C registers */
|
||||
if (!pdata)
|
||||
goto set_default_dvs_mode;
|
||||
|
||||
if ((id == BUCK1 && !pdata->buck1_dvs) ||
|
||||
(id == BUCK2 && !pdata->buck2_dvs))
|
||||
goto set_default_dvs_mode;
|
||||
|
||||
if (lp8788_dvs_gpio_request(buck, id))
|
||||
goto set_default_dvs_mode;
|
||||
|
||||
return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id],
|
||||
val[id]);
|
||||
|
||||
set_default_dvs_mode:
|
||||
return lp8788_set_default_dvs_ctrl_mode(buck->lp, id);
|
||||
}
|
||||
|
||||
static __devinit int lp8788_buck_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
|
||||
int id = pdev->id;
|
||||
struct lp8788_buck *buck;
|
||||
struct regulator_config cfg = { };
|
||||
struct regulator_dev *rdev;
|
||||
int ret;
|
||||
|
||||
buck = devm_kzalloc(lp->dev, sizeof(struct lp8788_buck), GFP_KERNEL);
|
||||
if (!buck)
|
||||
return -ENOMEM;
|
||||
|
||||
buck->lp = lp;
|
||||
buck->pmap = &buck_pmap[id];
|
||||
|
||||
ret = lp8788_init_dvs(buck, id);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cfg.dev = lp->dev;
|
||||
cfg.init_data = lp->pdata ? lp->pdata->buck_data[id] : NULL;
|
||||
cfg.driver_data = buck;
|
||||
cfg.regmap = lp->regmap;
|
||||
|
||||
rdev = regulator_register(&lp8788_buck_desc[id], &cfg);
|
||||
if (IS_ERR(rdev)) {
|
||||
ret = PTR_ERR(rdev);
|
||||
dev_err(lp->dev, "BUCK%d regulator register err = %d\n",
|
||||
id + 1, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
buck->regulator = rdev;
|
||||
platform_set_drvdata(pdev, buck);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit lp8788_buck_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct lp8788_buck *buck = platform_get_drvdata(pdev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
regulator_unregister(buck->regulator);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver lp8788_buck_driver = {
|
||||
.probe = lp8788_buck_probe,
|
||||
.remove = __devexit_p(lp8788_buck_remove),
|
||||
.driver = {
|
||||
.name = LP8788_DEV_BUCK,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init lp8788_buck_init(void)
|
||||
{
|
||||
return platform_driver_register(&lp8788_buck_driver);
|
||||
}
|
||||
subsys_initcall(lp8788_buck_init);
|
||||
|
||||
static void __exit lp8788_buck_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&lp8788_buck_driver);
|
||||
}
|
||||
module_exit(lp8788_buck_exit);
|
||||
|
||||
MODULE_DESCRIPTION("TI LP8788 BUCK Driver");
|
||||
MODULE_AUTHOR("Milo Kim");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:lp8788-buck");
|
||||
@@ -0,0 +1,842 @@
|
||||
/*
|
||||
* TI LP8788 MFD - ldo regulator driver
|
||||
*
|
||||
* Copyright 2012 Texas Instruments
|
||||
*
|
||||
* Author: Milo(Woogyom) 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/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/mfd/lp8788.h>
|
||||
|
||||
/* register address */
|
||||
#define LP8788_EN_LDO_A 0x0D /* DLDO 1 ~ 8 */
|
||||
#define LP8788_EN_LDO_B 0x0E /* DLDO 9 ~ 12, ALDO 1 ~ 4 */
|
||||
#define LP8788_EN_LDO_C 0x0F /* ALDO 5 ~ 10 */
|
||||
#define LP8788_EN_SEL 0x10
|
||||
#define LP8788_DLDO1_VOUT 0x2E
|
||||
#define LP8788_DLDO2_VOUT 0x2F
|
||||
#define LP8788_DLDO3_VOUT 0x30
|
||||
#define LP8788_DLDO4_VOUT 0x31
|
||||
#define LP8788_DLDO5_VOUT 0x32
|
||||
#define LP8788_DLDO6_VOUT 0x33
|
||||
#define LP8788_DLDO7_VOUT 0x34
|
||||
#define LP8788_DLDO8_VOUT 0x35
|
||||
#define LP8788_DLDO9_VOUT 0x36
|
||||
#define LP8788_DLDO10_VOUT 0x37
|
||||
#define LP8788_DLDO11_VOUT 0x38
|
||||
#define LP8788_DLDO12_VOUT 0x39
|
||||
#define LP8788_ALDO1_VOUT 0x3A
|
||||
#define LP8788_ALDO2_VOUT 0x3B
|
||||
#define LP8788_ALDO3_VOUT 0x3C
|
||||
#define LP8788_ALDO4_VOUT 0x3D
|
||||
#define LP8788_ALDO5_VOUT 0x3E
|
||||
#define LP8788_ALDO6_VOUT 0x3F
|
||||
#define LP8788_ALDO7_VOUT 0x40
|
||||
#define LP8788_ALDO8_VOUT 0x41
|
||||
#define LP8788_ALDO9_VOUT 0x42
|
||||
#define LP8788_ALDO10_VOUT 0x43
|
||||
#define LP8788_DLDO1_TIMESTEP 0x44
|
||||
|
||||
/* mask/shift bits */
|
||||
#define LP8788_EN_DLDO1_M BIT(0) /* Addr 0Dh ~ 0Fh */
|
||||
#define LP8788_EN_DLDO2_M BIT(1)
|
||||
#define LP8788_EN_DLDO3_M BIT(2)
|
||||
#define LP8788_EN_DLDO4_M BIT(3)
|
||||
#define LP8788_EN_DLDO5_M BIT(4)
|
||||
#define LP8788_EN_DLDO6_M BIT(5)
|
||||
#define LP8788_EN_DLDO7_M BIT(6)
|
||||
#define LP8788_EN_DLDO8_M BIT(7)
|
||||
#define LP8788_EN_DLDO9_M BIT(0)
|
||||
#define LP8788_EN_DLDO10_M BIT(1)
|
||||
#define LP8788_EN_DLDO11_M BIT(2)
|
||||
#define LP8788_EN_DLDO12_M BIT(3)
|
||||
#define LP8788_EN_ALDO1_M BIT(4)
|
||||
#define LP8788_EN_ALDO2_M BIT(5)
|
||||
#define LP8788_EN_ALDO3_M BIT(6)
|
||||
#define LP8788_EN_ALDO4_M BIT(7)
|
||||
#define LP8788_EN_ALDO5_M BIT(0)
|
||||
#define LP8788_EN_ALDO6_M BIT(1)
|
||||
#define LP8788_EN_ALDO7_M BIT(2)
|
||||
#define LP8788_EN_ALDO8_M BIT(3)
|
||||
#define LP8788_EN_ALDO9_M BIT(4)
|
||||
#define LP8788_EN_ALDO10_M BIT(5)
|
||||
#define LP8788_EN_SEL_DLDO911_M BIT(0) /* Addr 10h */
|
||||
#define LP8788_EN_SEL_DLDO7_M BIT(1)
|
||||
#define LP8788_EN_SEL_ALDO7_M BIT(2)
|
||||
#define LP8788_EN_SEL_ALDO5_M BIT(3)
|
||||
#define LP8788_EN_SEL_ALDO234_M BIT(4)
|
||||
#define LP8788_EN_SEL_ALDO1_M BIT(5)
|
||||
#define LP8788_VOUT_5BIT_M 0x1F /* Addr 2Eh ~ 43h */
|
||||
#define LP8788_VOUT_4BIT_M 0x0F
|
||||
#define LP8788_VOUT_3BIT_M 0x07
|
||||
#define LP8788_VOUT_1BIT_M 0x01
|
||||
#define LP8788_STARTUP_TIME_M 0xF8 /* Addr 44h ~ 59h */
|
||||
#define LP8788_STARTUP_TIME_S 3
|
||||
|
||||
#define ENABLE_TIME_USEC 32
|
||||
#define ENABLE GPIOF_OUT_INIT_HIGH
|
||||
#define DISABLE GPIOF_OUT_INIT_LOW
|
||||
|
||||
enum lp8788_enable_mode {
|
||||
REGISTER,
|
||||
EXTPIN,
|
||||
};
|
||||
|
||||
enum lp8788_ldo_id {
|
||||
DLDO1,
|
||||
DLDO2,
|
||||
DLDO3,
|
||||
DLDO4,
|
||||
DLDO5,
|
||||
DLDO6,
|
||||
DLDO7,
|
||||
DLDO8,
|
||||
DLDO9,
|
||||
DLDO10,
|
||||
DLDO11,
|
||||
DLDO12,
|
||||
ALDO1,
|
||||
ALDO2,
|
||||
ALDO3,
|
||||
ALDO4,
|
||||
ALDO5,
|
||||
ALDO6,
|
||||
ALDO7,
|
||||
ALDO8,
|
||||
ALDO9,
|
||||
ALDO10,
|
||||
};
|
||||
|
||||
struct lp8788_ldo {
|
||||
struct lp8788 *lp;
|
||||
struct regulator_desc *desc;
|
||||
struct regulator_dev *regulator;
|
||||
struct lp8788_ldo_enable_pin *en_pin;
|
||||
};
|
||||
|
||||
/* DLDO 1, 2, 3, 9 voltage table */
|
||||
const int lp8788_dldo1239_vtbl[] = {
|
||||
1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
|
||||
2600000, 2700000, 2800000, 2900000, 3000000, 2850000, 2850000, 2850000,
|
||||
2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000,
|
||||
2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000,
|
||||
};
|
||||
|
||||
/* DLDO 4 voltage table */
|
||||
static const int lp8788_dldo4_vtbl[] = { 1800000, 3000000 };
|
||||
|
||||
/* DLDO 5, 7, 8 and ALDO 6 voltage table */
|
||||
static const int lp8788_dldo578_aldo6_vtbl[] = {
|
||||
1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
|
||||
2600000, 2700000, 2800000, 2900000, 3000000, 3000000, 3000000, 3000000,
|
||||
};
|
||||
|
||||
/* DLDO 6 voltage table */
|
||||
static const int lp8788_dldo6_vtbl[] = {
|
||||
3000000, 3100000, 3200000, 3300000, 3400000, 3500000, 3600000, 3600000,
|
||||
};
|
||||
|
||||
/* DLDO 10, 11 voltage table */
|
||||
static const int lp8788_dldo1011_vtbl[] = {
|
||||
1100000, 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000,
|
||||
1500000, 1500000, 1500000, 1500000, 1500000, 1500000, 1500000, 1500000,
|
||||
};
|
||||
|
||||
/* ALDO 1 voltage table */
|
||||
static const int lp8788_aldo1_vtbl[] = { 1800000, 2850000 };
|
||||
|
||||
/* ALDO 7 voltage table */
|
||||
static const int lp8788_aldo7_vtbl[] = {
|
||||
1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1800000,
|
||||
};
|
||||
|
||||
static enum lp8788_ldo_id lp8788_dldo_id[] = {
|
||||
DLDO1,
|
||||
DLDO2,
|
||||
DLDO3,
|
||||
DLDO4,
|
||||
DLDO5,
|
||||
DLDO6,
|
||||
DLDO7,
|
||||
DLDO8,
|
||||
DLDO9,
|
||||
DLDO10,
|
||||
DLDO11,
|
||||
DLDO12,
|
||||
};
|
||||
|
||||
static enum lp8788_ldo_id lp8788_aldo_id[] = {
|
||||
ALDO1,
|
||||
ALDO2,
|
||||
ALDO3,
|
||||
ALDO4,
|
||||
ALDO5,
|
||||
ALDO6,
|
||||
ALDO7,
|
||||
ALDO8,
|
||||
ALDO9,
|
||||
ALDO10,
|
||||
};
|
||||
|
||||
/* DLDO 7, 9 and 11, ALDO 1 ~ 5 and 7
|
||||
: can be enabled either by external pin or by i2c register */
|
||||
static enum lp8788_enable_mode
|
||||
lp8788_get_ldo_enable_mode(struct lp8788_ldo *ldo, enum lp8788_ldo_id id)
|
||||
{
|
||||
int ret;
|
||||
u8 val, mask;
|
||||
|
||||
ret = lp8788_read_byte(ldo->lp, LP8788_EN_SEL, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (id) {
|
||||
case DLDO7:
|
||||
mask = LP8788_EN_SEL_DLDO7_M;
|
||||
break;
|
||||
case DLDO9:
|
||||
case DLDO11:
|
||||
mask = LP8788_EN_SEL_DLDO911_M;
|
||||
break;
|
||||
case ALDO1:
|
||||
mask = LP8788_EN_SEL_ALDO1_M;
|
||||
break;
|
||||
case ALDO2 ... ALDO4:
|
||||
mask = LP8788_EN_SEL_ALDO234_M;
|
||||
break;
|
||||
case ALDO5:
|
||||
mask = LP8788_EN_SEL_ALDO5_M;
|
||||
break;
|
||||
case ALDO7:
|
||||
mask = LP8788_EN_SEL_ALDO7_M;
|
||||
break;
|
||||
default:
|
||||
return REGISTER;
|
||||
}
|
||||
|
||||
return val & mask ? EXTPIN : REGISTER;
|
||||
}
|
||||
|
||||
static int lp8788_ldo_ctrl_by_extern_pin(struct lp8788_ldo *ldo, int pinstate)
|
||||
{
|
||||
struct lp8788_ldo_enable_pin *pin = ldo->en_pin;
|
||||
|
||||
if (!pin)
|
||||
return -EINVAL;
|
||||
|
||||
if (gpio_is_valid(pin->gpio))
|
||||
gpio_set_value(pin->gpio, pinstate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lp8788_ldo_is_enabled_by_extern_pin(struct lp8788_ldo *ldo)
|
||||
{
|
||||
struct lp8788_ldo_enable_pin *pin = ldo->en_pin;
|
||||
|
||||
if (!pin)
|
||||
return -EINVAL;
|
||||
|
||||
return gpio_get_value(pin->gpio) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int lp8788_ldo_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
enum lp8788_ldo_id id = rdev_get_id(rdev);
|
||||
enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id);
|
||||
|
||||
switch (mode) {
|
||||
case EXTPIN:
|
||||
return lp8788_ldo_ctrl_by_extern_pin(ldo, ENABLE);
|
||||
case REGISTER:
|
||||
return regulator_enable_regmap(rdev);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int lp8788_ldo_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
enum lp8788_ldo_id id = rdev_get_id(rdev);
|
||||
enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id);
|
||||
|
||||
switch (mode) {
|
||||
case EXTPIN:
|
||||
return lp8788_ldo_ctrl_by_extern_pin(ldo, DISABLE);
|
||||
case REGISTER:
|
||||
return regulator_disable_regmap(rdev);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int lp8788_ldo_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
enum lp8788_ldo_id id = rdev_get_id(rdev);
|
||||
enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id);
|
||||
|
||||
switch (mode) {
|
||||
case EXTPIN:
|
||||
return lp8788_ldo_is_enabled_by_extern_pin(ldo);
|
||||
case REGISTER:
|
||||
return regulator_is_enabled_regmap(rdev);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int lp8788_ldo_enable_time(struct regulator_dev *rdev)
|
||||
{
|
||||
struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
enum lp8788_ldo_id id = rdev_get_id(rdev);
|
||||
u8 val, addr = LP8788_DLDO1_TIMESTEP + id;
|
||||
|
||||
if (lp8788_read_byte(ldo->lp, addr, &val))
|
||||
return -EINVAL;
|
||||
|
||||
val = (val & LP8788_STARTUP_TIME_M) >> LP8788_STARTUP_TIME_S;
|
||||
|
||||
return ENABLE_TIME_USEC * val;
|
||||
}
|
||||
|
||||
static int lp8788_ldo_fixed_get_voltage(struct regulator_dev *rdev)
|
||||
{
|
||||
enum lp8788_ldo_id id = rdev_get_id(rdev);
|
||||
|
||||
switch (id) {
|
||||
case ALDO2 ... ALDO5:
|
||||
return 2850000;
|
||||
case DLDO12:
|
||||
case ALDO8 ... ALDO9:
|
||||
return 2500000;
|
||||
case ALDO10:
|
||||
return 1100000;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static 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,
|
||||
.enable = lp8788_ldo_enable,
|
||||
.disable = lp8788_ldo_disable,
|
||||
.is_enabled = lp8788_ldo_is_enabled,
|
||||
.enable_time = lp8788_ldo_enable_time,
|
||||
};
|
||||
|
||||
static struct regulator_ops lp8788_ldo_voltage_fixed_ops = {
|
||||
.get_voltage = lp8788_ldo_fixed_get_voltage,
|
||||
.enable = lp8788_ldo_enable,
|
||||
.disable = lp8788_ldo_disable,
|
||||
.is_enabled = lp8788_ldo_is_enabled,
|
||||
.enable_time = lp8788_ldo_enable_time,
|
||||
};
|
||||
|
||||
static struct regulator_desc lp8788_dldo_desc[] = {
|
||||
{
|
||||
.name = "dldo1",
|
||||
.id = DLDO1,
|
||||
.ops = &lp8788_ldo_voltage_table_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
|
||||
.volt_table = lp8788_dldo1239_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8788_DLDO1_VOUT,
|
||||
.vsel_mask = LP8788_VOUT_5BIT_M,
|
||||
.enable_reg = LP8788_EN_LDO_A,
|
||||
.enable_mask = LP8788_EN_DLDO1_M,
|
||||
},
|
||||
{
|
||||
.name = "dldo2",
|
||||
.id = DLDO2,
|
||||
.ops = &lp8788_ldo_voltage_table_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
|
||||
.volt_table = lp8788_dldo1239_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8788_DLDO2_VOUT,
|
||||
.vsel_mask = LP8788_VOUT_5BIT_M,
|
||||
.enable_reg = LP8788_EN_LDO_A,
|
||||
.enable_mask = LP8788_EN_DLDO2_M,
|
||||
},
|
||||
{
|
||||
.name = "dldo3",
|
||||
.id = DLDO3,
|
||||
.ops = &lp8788_ldo_voltage_table_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
|
||||
.volt_table = lp8788_dldo1239_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8788_DLDO3_VOUT,
|
||||
.vsel_mask = LP8788_VOUT_5BIT_M,
|
||||
.enable_reg = LP8788_EN_LDO_A,
|
||||
.enable_mask = LP8788_EN_DLDO3_M,
|
||||
},
|
||||
{
|
||||
.name = "dldo4",
|
||||
.id = DLDO4,
|
||||
.ops = &lp8788_ldo_voltage_table_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_dldo4_vtbl),
|
||||
.volt_table = lp8788_dldo4_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8788_DLDO4_VOUT,
|
||||
.vsel_mask = LP8788_VOUT_1BIT_M,
|
||||
.enable_reg = LP8788_EN_LDO_A,
|
||||
.enable_mask = LP8788_EN_DLDO4_M,
|
||||
},
|
||||
{
|
||||
.name = "dldo5",
|
||||
.id = DLDO5,
|
||||
.ops = &lp8788_ldo_voltage_table_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
|
||||
.volt_table = lp8788_dldo578_aldo6_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8788_DLDO5_VOUT,
|
||||
.vsel_mask = LP8788_VOUT_4BIT_M,
|
||||
.enable_reg = LP8788_EN_LDO_A,
|
||||
.enable_mask = LP8788_EN_DLDO5_M,
|
||||
},
|
||||
{
|
||||
.name = "dldo6",
|
||||
.id = DLDO6,
|
||||
.ops = &lp8788_ldo_voltage_table_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_dldo6_vtbl),
|
||||
.volt_table = lp8788_dldo6_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8788_DLDO6_VOUT,
|
||||
.vsel_mask = LP8788_VOUT_3BIT_M,
|
||||
.enable_reg = LP8788_EN_LDO_A,
|
||||
.enable_mask = LP8788_EN_DLDO6_M,
|
||||
},
|
||||
{
|
||||
.name = "dldo7",
|
||||
.id = DLDO7,
|
||||
.ops = &lp8788_ldo_voltage_table_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
|
||||
.volt_table = lp8788_dldo578_aldo6_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8788_DLDO7_VOUT,
|
||||
.vsel_mask = LP8788_VOUT_4BIT_M,
|
||||
.enable_reg = LP8788_EN_LDO_A,
|
||||
.enable_mask = LP8788_EN_DLDO7_M,
|
||||
},
|
||||
{
|
||||
.name = "dldo8",
|
||||
.id = DLDO8,
|
||||
.ops = &lp8788_ldo_voltage_table_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
|
||||
.volt_table = lp8788_dldo578_aldo6_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8788_DLDO8_VOUT,
|
||||
.vsel_mask = LP8788_VOUT_4BIT_M,
|
||||
.enable_reg = LP8788_EN_LDO_A,
|
||||
.enable_mask = LP8788_EN_DLDO8_M,
|
||||
},
|
||||
{
|
||||
.name = "dldo9",
|
||||
.id = DLDO9,
|
||||
.ops = &lp8788_ldo_voltage_table_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
|
||||
.volt_table = lp8788_dldo1239_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8788_DLDO9_VOUT,
|
||||
.vsel_mask = LP8788_VOUT_5BIT_M,
|
||||
.enable_reg = LP8788_EN_LDO_B,
|
||||
.enable_mask = LP8788_EN_DLDO9_M,
|
||||
},
|
||||
{
|
||||
.name = "dldo10",
|
||||
.id = DLDO10,
|
||||
.ops = &lp8788_ldo_voltage_table_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_dldo1011_vtbl),
|
||||
.volt_table = lp8788_dldo1011_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8788_DLDO10_VOUT,
|
||||
.vsel_mask = LP8788_VOUT_4BIT_M,
|
||||
.enable_reg = LP8788_EN_LDO_B,
|
||||
.enable_mask = LP8788_EN_DLDO10_M,
|
||||
},
|
||||
{
|
||||
.name = "dldo11",
|
||||
.id = DLDO11,
|
||||
.ops = &lp8788_ldo_voltage_table_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_dldo1011_vtbl),
|
||||
.volt_table = lp8788_dldo1011_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8788_DLDO11_VOUT,
|
||||
.vsel_mask = LP8788_VOUT_4BIT_M,
|
||||
.enable_reg = LP8788_EN_LDO_B,
|
||||
.enable_mask = LP8788_EN_DLDO11_M,
|
||||
},
|
||||
{
|
||||
.name = "dldo12",
|
||||
.id = DLDO12,
|
||||
.ops = &lp8788_ldo_voltage_fixed_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = LP8788_EN_LDO_B,
|
||||
.enable_mask = LP8788_EN_DLDO12_M,
|
||||
},
|
||||
};
|
||||
|
||||
static struct regulator_desc lp8788_aldo_desc[] = {
|
||||
{
|
||||
.name = "aldo1",
|
||||
.id = ALDO1,
|
||||
.ops = &lp8788_ldo_voltage_table_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_aldo1_vtbl),
|
||||
.volt_table = lp8788_aldo1_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8788_ALDO1_VOUT,
|
||||
.vsel_mask = LP8788_VOUT_1BIT_M,
|
||||
.enable_reg = LP8788_EN_LDO_B,
|
||||
.enable_mask = LP8788_EN_ALDO1_M,
|
||||
},
|
||||
{
|
||||
.name = "aldo2",
|
||||
.id = ALDO2,
|
||||
.ops = &lp8788_ldo_voltage_fixed_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = LP8788_EN_LDO_B,
|
||||
.enable_mask = LP8788_EN_ALDO2_M,
|
||||
},
|
||||
{
|
||||
.name = "aldo3",
|
||||
.id = ALDO3,
|
||||
.ops = &lp8788_ldo_voltage_fixed_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = LP8788_EN_LDO_B,
|
||||
.enable_mask = LP8788_EN_ALDO3_M,
|
||||
},
|
||||
{
|
||||
.name = "aldo4",
|
||||
.id = ALDO4,
|
||||
.ops = &lp8788_ldo_voltage_fixed_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = LP8788_EN_LDO_B,
|
||||
.enable_mask = LP8788_EN_ALDO4_M,
|
||||
},
|
||||
{
|
||||
.name = "aldo5",
|
||||
.id = ALDO5,
|
||||
.ops = &lp8788_ldo_voltage_fixed_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = LP8788_EN_LDO_C,
|
||||
.enable_mask = LP8788_EN_ALDO5_M,
|
||||
},
|
||||
{
|
||||
.name = "aldo6",
|
||||
.id = ALDO6,
|
||||
.ops = &lp8788_ldo_voltage_table_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
|
||||
.volt_table = lp8788_dldo578_aldo6_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8788_ALDO6_VOUT,
|
||||
.vsel_mask = LP8788_VOUT_4BIT_M,
|
||||
.enable_reg = LP8788_EN_LDO_C,
|
||||
.enable_mask = LP8788_EN_ALDO6_M,
|
||||
},
|
||||
{
|
||||
.name = "aldo7",
|
||||
.id = ALDO7,
|
||||
.ops = &lp8788_ldo_voltage_table_ops,
|
||||
.n_voltages = ARRAY_SIZE(lp8788_aldo7_vtbl),
|
||||
.volt_table = lp8788_aldo7_vtbl,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.vsel_reg = LP8788_ALDO7_VOUT,
|
||||
.vsel_mask = LP8788_VOUT_3BIT_M,
|
||||
.enable_reg = LP8788_EN_LDO_C,
|
||||
.enable_mask = LP8788_EN_ALDO7_M,
|
||||
},
|
||||
{
|
||||
.name = "aldo8",
|
||||
.id = ALDO8,
|
||||
.ops = &lp8788_ldo_voltage_fixed_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = LP8788_EN_LDO_C,
|
||||
.enable_mask = LP8788_EN_ALDO8_M,
|
||||
},
|
||||
{
|
||||
.name = "aldo9",
|
||||
.id = ALDO9,
|
||||
.ops = &lp8788_ldo_voltage_fixed_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = LP8788_EN_LDO_C,
|
||||
.enable_mask = LP8788_EN_ALDO9_M,
|
||||
},
|
||||
{
|
||||
.name = "aldo10",
|
||||
.id = ALDO10,
|
||||
.ops = &lp8788_ldo_voltage_fixed_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = LP8788_EN_LDO_C,
|
||||
.enable_mask = LP8788_EN_ALDO10_M,
|
||||
},
|
||||
};
|
||||
|
||||
static int lp8788_gpio_request_ldo_en(struct lp8788_ldo *ldo,
|
||||
enum lp8788_ext_ldo_en_id id)
|
||||
{
|
||||
struct device *dev = ldo->lp->dev;
|
||||
struct lp8788_ldo_enable_pin *pin = ldo->en_pin;
|
||||
int ret, gpio, pinstate;
|
||||
char *name[] = {
|
||||
[EN_ALDO1] = "LP8788_EN_ALDO1",
|
||||
[EN_ALDO234] = "LP8788_EN_ALDO234",
|
||||
[EN_ALDO5] = "LP8788_EN_ALDO5",
|
||||
[EN_ALDO7] = "LP8788_EN_ALDO7",
|
||||
[EN_DLDO7] = "LP8788_EN_DLDO7",
|
||||
[EN_DLDO911] = "LP8788_EN_DLDO911",
|
||||
};
|
||||
|
||||
gpio = pin->gpio;
|
||||
if (!gpio_is_valid(gpio)) {
|
||||
dev_err(dev, "invalid gpio: %d\n", gpio);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pinstate = pin->init_state;
|
||||
ret = devm_gpio_request_one(dev, gpio, pinstate, name[id]);
|
||||
if (ret == -EBUSY) {
|
||||
dev_warn(dev, "gpio%d already used\n", gpio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo,
|
||||
enum lp8788_ldo_id id)
|
||||
{
|
||||
int ret;
|
||||
struct lp8788 *lp = ldo->lp;
|
||||
struct lp8788_platform_data *pdata = lp->pdata;
|
||||
enum lp8788_ext_ldo_en_id enable_id;
|
||||
u8 en_mask[] = {
|
||||
[EN_ALDO1] = LP8788_EN_SEL_ALDO1_M,
|
||||
[EN_ALDO234] = LP8788_EN_SEL_ALDO234_M,
|
||||
[EN_ALDO5] = LP8788_EN_SEL_ALDO5_M,
|
||||
[EN_ALDO7] = LP8788_EN_SEL_ALDO7_M,
|
||||
[EN_DLDO7] = LP8788_EN_SEL_DLDO7_M,
|
||||
[EN_DLDO911] = LP8788_EN_SEL_DLDO911_M,
|
||||
};
|
||||
u8 val[] = {
|
||||
[EN_ALDO1] = 0 << 5,
|
||||
[EN_ALDO234] = 0 << 4,
|
||||
[EN_ALDO5] = 0 << 3,
|
||||
[EN_ALDO7] = 0 << 2,
|
||||
[EN_DLDO7] = 0 << 1,
|
||||
[EN_DLDO911] = 0 << 0,
|
||||
};
|
||||
|
||||
switch (id) {
|
||||
case DLDO7:
|
||||
enable_id = EN_DLDO7;
|
||||
break;
|
||||
case DLDO9:
|
||||
case DLDO11:
|
||||
enable_id = EN_DLDO911;
|
||||
break;
|
||||
case ALDO1:
|
||||
enable_id = EN_ALDO1;
|
||||
break;
|
||||
case ALDO2 ... ALDO4:
|
||||
enable_id = EN_ALDO234;
|
||||
break;
|
||||
case ALDO5:
|
||||
enable_id = EN_ALDO5;
|
||||
break;
|
||||
case ALDO7:
|
||||
enable_id = EN_ALDO7;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if no platform data for ldo pin, then set default enable mode */
|
||||
if (!pdata || !pdata->ldo_pin || !pdata->ldo_pin[enable_id])
|
||||
goto set_default_ldo_enable_mode;
|
||||
|
||||
ldo->en_pin = pdata->ldo_pin[enable_id];
|
||||
|
||||
ret = lp8788_gpio_request_ldo_en(ldo, enable_id);
|
||||
if (ret)
|
||||
goto set_default_ldo_enable_mode;
|
||||
|
||||
return ret;
|
||||
|
||||
set_default_ldo_enable_mode:
|
||||
return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id],
|
||||
val[enable_id]);
|
||||
}
|
||||
|
||||
static __devinit int lp8788_dldo_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
|
||||
int id = pdev->id;
|
||||
struct lp8788_ldo *ldo;
|
||||
struct regulator_config cfg = { };
|
||||
struct regulator_dev *rdev;
|
||||
int ret;
|
||||
|
||||
ldo = devm_kzalloc(lp->dev, sizeof(struct lp8788_ldo), GFP_KERNEL);
|
||||
if (!ldo)
|
||||
return -ENOMEM;
|
||||
|
||||
ldo->lp = lp;
|
||||
ret = lp8788_config_ldo_enable_mode(ldo, lp8788_dldo_id[id]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cfg.dev = lp->dev;
|
||||
cfg.init_data = lp->pdata ? lp->pdata->dldo_data[id] : NULL;
|
||||
cfg.driver_data = ldo;
|
||||
cfg.regmap = lp->regmap;
|
||||
|
||||
rdev = regulator_register(&lp8788_dldo_desc[id], &cfg);
|
||||
if (IS_ERR(rdev)) {
|
||||
ret = PTR_ERR(rdev);
|
||||
dev_err(lp->dev, "DLDO%d regulator register err = %d\n",
|
||||
id + 1, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ldo->regulator = rdev;
|
||||
platform_set_drvdata(pdev, ldo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit lp8788_dldo_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
regulator_unregister(ldo->regulator);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver lp8788_dldo_driver = {
|
||||
.probe = lp8788_dldo_probe,
|
||||
.remove = __devexit_p(lp8788_dldo_remove),
|
||||
.driver = {
|
||||
.name = LP8788_DEV_DLDO,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static __devinit int lp8788_aldo_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
|
||||
int id = pdev->id;
|
||||
struct lp8788_ldo *ldo;
|
||||
struct regulator_config cfg = { };
|
||||
struct regulator_dev *rdev;
|
||||
int ret;
|
||||
|
||||
ldo = devm_kzalloc(lp->dev, sizeof(struct lp8788_ldo), GFP_KERNEL);
|
||||
if (!ldo)
|
||||
return -ENOMEM;
|
||||
|
||||
ldo->lp = lp;
|
||||
ret = lp8788_config_ldo_enable_mode(ldo, lp8788_aldo_id[id]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cfg.dev = lp->dev;
|
||||
cfg.init_data = lp->pdata ? lp->pdata->aldo_data[id] : NULL;
|
||||
cfg.driver_data = ldo;
|
||||
cfg.regmap = lp->regmap;
|
||||
|
||||
rdev = regulator_register(&lp8788_aldo_desc[id], &cfg);
|
||||
if (IS_ERR(rdev)) {
|
||||
ret = PTR_ERR(rdev);
|
||||
dev_err(lp->dev, "ALDO%d regulator register err = %d\n",
|
||||
id + 1, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ldo->regulator = rdev;
|
||||
platform_set_drvdata(pdev, ldo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit lp8788_aldo_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
regulator_unregister(ldo->regulator);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver lp8788_aldo_driver = {
|
||||
.probe = lp8788_aldo_probe,
|
||||
.remove = __devexit_p(lp8788_aldo_remove),
|
||||
.driver = {
|
||||
.name = LP8788_DEV_ALDO,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
subsys_initcall(lp8788_ldo_init);
|
||||
|
||||
static void __exit lp8788_ldo_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&lp8788_aldo_driver);
|
||||
platform_driver_unregister(&lp8788_dldo_driver);
|
||||
}
|
||||
module_exit(lp8788_ldo_exit);
|
||||
|
||||
MODULE_DESCRIPTION("TI LP8788 LDO Driver");
|
||||
MODULE_AUTHOR("Milo Kim");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:lp8788-dldo");
|
||||
MODULE_ALIAS("platform:lp8788-aldo");
|
||||
+30
-78
@@ -47,6 +47,14 @@ struct max1586_data {
|
||||
struct regulator_dev *rdev[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* V6 voltage
|
||||
* On I2C bus, sending a "x" byte to the max1586 means :
|
||||
* set V6 to either 0V, 1.8V, 2.5V, 3V depending on (x & 0x3)
|
||||
* As regulator framework doesn't accept voltages to be 0V, we use 1uV.
|
||||
*/
|
||||
static int v6_voltages_uv[] = { 1, 1800000, 2500000, 3000000 };
|
||||
|
||||
/*
|
||||
* V3 voltage
|
||||
* On I2C bus, sending a "x" byte to the max1586 means :
|
||||
@@ -55,113 +63,49 @@ struct max1586_data {
|
||||
* R24 and R25=100kOhm as described in the data sheet.
|
||||
* The gain is approximately: 1 + R24/R25 + R24/185.5kOhm
|
||||
*/
|
||||
static int max1586_v3_calc_voltage(struct max1586_data *max1586,
|
||||
unsigned selector)
|
||||
{
|
||||
unsigned range_uV = max1586->max_uV - max1586->min_uV;
|
||||
|
||||
return max1586->min_uV + (selector * range_uV / MAX1586_V3_MAX_VSEL);
|
||||
}
|
||||
|
||||
static int max1586_v3_set(struct regulator_dev *rdev, int min_uV, int max_uV,
|
||||
unsigned *selector)
|
||||
static int max1586_v3_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct max1586_data *max1586 = rdev_get_drvdata(rdev);
|
||||
struct i2c_client *client = max1586->client;
|
||||
unsigned range_uV = max1586->max_uV - max1586->min_uV;
|
||||
u8 v3_prog;
|
||||
|
||||
if (min_uV > max1586->max_uV || max_uV < max1586->min_uV)
|
||||
return -EINVAL;
|
||||
if (min_uV < max1586->min_uV)
|
||||
min_uV = max1586->min_uV;
|
||||
|
||||
*selector = DIV_ROUND_UP((min_uV - max1586->min_uV) *
|
||||
MAX1586_V3_MAX_VSEL, range_uV);
|
||||
if (max1586_v3_calc_voltage(max1586, *selector) > max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
dev_dbg(&client->dev, "changing voltage v3 to %dmv\n",
|
||||
max1586_v3_calc_voltage(max1586, *selector) / 1000);
|
||||
regulator_list_voltage_linear(rdev, selector) / 1000);
|
||||
|
||||
v3_prog = I2C_V3_SELECT | (u8) *selector;
|
||||
v3_prog = I2C_V3_SELECT | (u8) selector;
|
||||
return i2c_smbus_write_byte(client, v3_prog);
|
||||
}
|
||||
|
||||
static int max1586_v3_list(struct regulator_dev *rdev, unsigned selector)
|
||||
{
|
||||
struct max1586_data *max1586 = rdev_get_drvdata(rdev);
|
||||
|
||||
if (selector > MAX1586_V3_MAX_VSEL)
|
||||
return -EINVAL;
|
||||
return max1586_v3_calc_voltage(max1586, selector);
|
||||
}
|
||||
|
||||
/*
|
||||
* V6 voltage
|
||||
* On I2C bus, sending a "x" byte to the max1586 means :
|
||||
* set V6 to either 0V, 1.8V, 2.5V, 3V depending on (x & 0x3)
|
||||
* As regulator framework doesn't accept voltages to be 0V, we use 1uV.
|
||||
*/
|
||||
static int max1586_v6_calc_voltage(unsigned selector)
|
||||
{
|
||||
static int voltages_uv[] = { 1, 1800000, 2500000, 3000000 };
|
||||
|
||||
return voltages_uv[selector];
|
||||
}
|
||||
|
||||
static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV,
|
||||
unsigned int *selector)
|
||||
static int max1586_v6_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned int selector)
|
||||
{
|
||||
struct i2c_client *client = rdev_get_drvdata(rdev);
|
||||
u8 v6_prog;
|
||||
|
||||
if (min_uV < MAX1586_V6_MIN_UV || min_uV > MAX1586_V6_MAX_UV)
|
||||
return -EINVAL;
|
||||
if (max_uV < MAX1586_V6_MIN_UV || max_uV > MAX1586_V6_MAX_UV)
|
||||
return -EINVAL;
|
||||
|
||||
if (min_uV < 1800000)
|
||||
*selector = 0;
|
||||
else if (min_uV < 2500000)
|
||||
*selector = 1;
|
||||
else if (min_uV < 3000000)
|
||||
*selector = 2;
|
||||
else if (min_uV >= 3000000)
|
||||
*selector = 3;
|
||||
|
||||
if (max1586_v6_calc_voltage(*selector) > max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
dev_dbg(&client->dev, "changing voltage v6 to %dmv\n",
|
||||
max1586_v6_calc_voltage(*selector) / 1000);
|
||||
rdev->desc->volt_table[selector] / 1000);
|
||||
|
||||
v6_prog = I2C_V6_SELECT | (u8) *selector;
|
||||
v6_prog = I2C_V6_SELECT | (u8) selector;
|
||||
return i2c_smbus_write_byte(client, v6_prog);
|
||||
}
|
||||
|
||||
static int max1586_v6_list(struct regulator_dev *rdev, unsigned selector)
|
||||
{
|
||||
if (selector > MAX1586_V6_MAX_VSEL)
|
||||
return -EINVAL;
|
||||
return max1586_v6_calc_voltage(selector);
|
||||
}
|
||||
|
||||
/*
|
||||
* The Maxim 1586 controls V3 and V6 voltages, but offers no way of reading back
|
||||
* the set up value.
|
||||
*/
|
||||
static struct regulator_ops max1586_v3_ops = {
|
||||
.set_voltage = max1586_v3_set,
|
||||
.list_voltage = max1586_v3_list,
|
||||
.set_voltage_sel = max1586_v3_set_voltage_sel,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
};
|
||||
|
||||
static struct regulator_ops max1586_v6_ops = {
|
||||
.set_voltage = max1586_v6_set,
|
||||
.list_voltage = max1586_v6_list,
|
||||
.set_voltage_sel = max1586_v6_set_voltage_sel,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
};
|
||||
|
||||
static const struct regulator_desc max1586_reg[] = {
|
||||
static struct regulator_desc max1586_reg[] = {
|
||||
{
|
||||
.name = "Output_V3",
|
||||
.id = MAX1586_V3,
|
||||
@@ -176,6 +120,7 @@ static const struct regulator_desc max1586_reg[] = {
|
||||
.ops = &max1586_v6_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = MAX1586_V6_MAX_VSEL + 1,
|
||||
.volt_table = v6_voltages_uv,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
@@ -213,6 +158,13 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (id == MAX1586_V3) {
|
||||
max1586_reg[id].min_uV = max1586->min_uV;
|
||||
max1586_reg[id].uV_step =
|
||||
(max1586->max_uV - max1586->min_uV) /
|
||||
MAX1586_V3_MAX_VSEL;
|
||||
}
|
||||
|
||||
config.dev = &client->dev;
|
||||
config.init_data = pdata->subdevs[i].platform_data;
|
||||
config.driver_data = max1586;
|
||||
|
||||
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* max77686.c - Regulator driver for the Maxim 77686
|
||||
*
|
||||
* Copyright (C) 2012 Samsung Electronics
|
||||
* Chiwoong Byun <woong.byun@smasung.com>
|
||||
* Jonghwa Lee <jonghwa3.lee@samsung.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* This driver is based on max8997.c
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/mfd/max77686.h>
|
||||
#include <linux/mfd/max77686-private.h>
|
||||
|
||||
#define MAX77686_LDO_MINUV 800000
|
||||
#define MAX77686_LDO_UVSTEP 50000
|
||||
#define MAX77686_LDO_LOW_MINUV 800000
|
||||
#define MAX77686_LDO_LOW_UVSTEP 25000
|
||||
#define MAX77686_BUCK_MINUV 750000
|
||||
#define MAX77686_BUCK_UVSTEP 50000
|
||||
#define MAX77686_RAMP_DELAY 100000 /* uV/us */
|
||||
#define MAX77686_DVS_RAMP_DELAY 27500 /* uV/us */
|
||||
#define MAX77686_DVS_MINUV 600000
|
||||
#define MAX77686_DVS_UVSTEP 12500
|
||||
|
||||
#define MAX77686_OPMODE_SHIFT 6
|
||||
#define MAX77686_OPMODE_BUCK234_SHIFT 4
|
||||
#define MAX77686_OPMODE_MASK 0x3
|
||||
|
||||
#define MAX77686_VSEL_MASK 0x3F
|
||||
#define MAX77686_DVS_VSEL_MASK 0xFF
|
||||
|
||||
#define MAX77686_RAMP_RATE_MASK 0xC0
|
||||
|
||||
#define MAX77686_REGULATORS MAX77686_REG_MAX
|
||||
#define MAX77686_LDOS 26
|
||||
|
||||
enum max77686_ramp_rate {
|
||||
RAMP_RATE_13P75MV,
|
||||
RAMP_RATE_27P5MV,
|
||||
RAMP_RATE_55MV,
|
||||
RAMP_RATE_NO_CTRL, /* 100mV/us */
|
||||
};
|
||||
|
||||
struct max77686_data {
|
||||
struct regulator_dev **rdev;
|
||||
};
|
||||
|
||||
static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
|
||||
{
|
||||
unsigned int ramp_value = RAMP_RATE_NO_CTRL;
|
||||
|
||||
switch (ramp_delay) {
|
||||
case 1 ... 13750:
|
||||
ramp_value = RAMP_RATE_13P75MV;
|
||||
break;
|
||||
case 13751 ... 27500:
|
||||
ramp_value = RAMP_RATE_27P5MV;
|
||||
break;
|
||||
case 27501 ... 55000:
|
||||
ramp_value = RAMP_RATE_55MV;
|
||||
break;
|
||||
case 55001 ... 100000:
|
||||
break;
|
||||
default:
|
||||
pr_warn("%s: ramp_delay: %d not supported, setting 100000\n",
|
||||
rdev->desc->name, ramp_delay);
|
||||
}
|
||||
|
||||
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
|
||||
MAX77686_RAMP_RATE_MASK, ramp_value << 6);
|
||||
}
|
||||
|
||||
static struct regulator_ops max77686_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
};
|
||||
|
||||
static struct regulator_ops max77686_buck_dvs_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.set_ramp_delay = max77686_set_ramp_delay,
|
||||
};
|
||||
|
||||
#define regulator_desc_ldo(num) { \
|
||||
.name = "LDO"#num, \
|
||||
.id = MAX77686_LDO##num, \
|
||||
.ops = &max77686_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = MAX77686_LDO_MINUV, \
|
||||
.uV_step = MAX77686_LDO_UVSTEP, \
|
||||
.ramp_delay = MAX77686_RAMP_DELAY, \
|
||||
.n_voltages = MAX77686_VSEL_MASK + 1, \
|
||||
.vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
|
||||
.vsel_mask = MAX77686_VSEL_MASK, \
|
||||
.enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
|
||||
.enable_mask = MAX77686_OPMODE_MASK \
|
||||
<< MAX77686_OPMODE_SHIFT, \
|
||||
}
|
||||
#define regulator_desc_ldo_low(num) { \
|
||||
.name = "LDO"#num, \
|
||||
.id = MAX77686_LDO##num, \
|
||||
.ops = &max77686_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = MAX77686_LDO_LOW_MINUV, \
|
||||
.uV_step = MAX77686_LDO_LOW_UVSTEP, \
|
||||
.ramp_delay = MAX77686_RAMP_DELAY, \
|
||||
.n_voltages = MAX77686_VSEL_MASK + 1, \
|
||||
.vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
|
||||
.vsel_mask = MAX77686_VSEL_MASK, \
|
||||
.enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
|
||||
.enable_mask = MAX77686_OPMODE_MASK \
|
||||
<< MAX77686_OPMODE_SHIFT, \
|
||||
}
|
||||
#define regulator_desc_buck(num) { \
|
||||
.name = "BUCK"#num, \
|
||||
.id = MAX77686_BUCK##num, \
|
||||
.ops = &max77686_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = MAX77686_BUCK_MINUV, \
|
||||
.uV_step = MAX77686_BUCK_UVSTEP, \
|
||||
.ramp_delay = MAX77686_RAMP_DELAY, \
|
||||
.n_voltages = MAX77686_VSEL_MASK + 1, \
|
||||
.vsel_reg = MAX77686_REG_BUCK5OUT + (num - 5) * 2, \
|
||||
.vsel_mask = MAX77686_VSEL_MASK, \
|
||||
.enable_reg = MAX77686_REG_BUCK5CTRL + (num - 5) * 2, \
|
||||
.enable_mask = MAX77686_OPMODE_MASK, \
|
||||
}
|
||||
#define regulator_desc_buck1(num) { \
|
||||
.name = "BUCK"#num, \
|
||||
.id = MAX77686_BUCK##num, \
|
||||
.ops = &max77686_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = MAX77686_BUCK_MINUV, \
|
||||
.uV_step = MAX77686_BUCK_UVSTEP, \
|
||||
.ramp_delay = MAX77686_RAMP_DELAY, \
|
||||
.n_voltages = MAX77686_VSEL_MASK + 1, \
|
||||
.vsel_reg = MAX77686_REG_BUCK1OUT, \
|
||||
.vsel_mask = MAX77686_VSEL_MASK, \
|
||||
.enable_reg = MAX77686_REG_BUCK1CTRL, \
|
||||
.enable_mask = MAX77686_OPMODE_MASK, \
|
||||
}
|
||||
#define regulator_desc_buck_dvs(num) { \
|
||||
.name = "BUCK"#num, \
|
||||
.id = MAX77686_BUCK##num, \
|
||||
.ops = &max77686_buck_dvs_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = MAX77686_DVS_MINUV, \
|
||||
.uV_step = MAX77686_DVS_UVSTEP, \
|
||||
.ramp_delay = MAX77686_DVS_RAMP_DELAY, \
|
||||
.n_voltages = MAX77686_DVS_VSEL_MASK + 1, \
|
||||
.vsel_reg = MAX77686_REG_BUCK2DVS1 + (num - 2) * 10, \
|
||||
.vsel_mask = MAX77686_DVS_VSEL_MASK, \
|
||||
.enable_reg = MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10, \
|
||||
.enable_mask = MAX77686_OPMODE_MASK \
|
||||
<< MAX77686_OPMODE_BUCK234_SHIFT, \
|
||||
}
|
||||
|
||||
static struct regulator_desc regulators[] = {
|
||||
regulator_desc_ldo_low(1),
|
||||
regulator_desc_ldo_low(2),
|
||||
regulator_desc_ldo(3),
|
||||
regulator_desc_ldo(4),
|
||||
regulator_desc_ldo(5),
|
||||
regulator_desc_ldo_low(6),
|
||||
regulator_desc_ldo_low(7),
|
||||
regulator_desc_ldo_low(8),
|
||||
regulator_desc_ldo(9),
|
||||
regulator_desc_ldo(10),
|
||||
regulator_desc_ldo(11),
|
||||
regulator_desc_ldo(12),
|
||||
regulator_desc_ldo(13),
|
||||
regulator_desc_ldo(14),
|
||||
regulator_desc_ldo_low(15),
|
||||
regulator_desc_ldo(16),
|
||||
regulator_desc_ldo(17),
|
||||
regulator_desc_ldo(18),
|
||||
regulator_desc_ldo(19),
|
||||
regulator_desc_ldo(20),
|
||||
regulator_desc_ldo(21),
|
||||
regulator_desc_ldo(22),
|
||||
regulator_desc_ldo(23),
|
||||
regulator_desc_ldo(24),
|
||||
regulator_desc_ldo(25),
|
||||
regulator_desc_ldo(26),
|
||||
regulator_desc_buck1(1),
|
||||
regulator_desc_buck_dvs(2),
|
||||
regulator_desc_buck_dvs(3),
|
||||
regulator_desc_buck_dvs(4),
|
||||
regulator_desc_buck(5),
|
||||
regulator_desc_buck(6),
|
||||
regulator_desc_buck(7),
|
||||
regulator_desc_buck(8),
|
||||
regulator_desc_buck(9),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
|
||||
struct max77686_platform_data *pdata)
|
||||
{
|
||||
struct device_node *pmic_np, *regulators_np;
|
||||
struct max77686_regulator_data *rdata;
|
||||
struct of_regulator_match rmatch;
|
||||
unsigned int i;
|
||||
|
||||
pmic_np = iodev->dev->of_node;
|
||||
regulators_np = of_find_node_by_name(pmic_np, "voltage-regulators");
|
||||
if (!regulators_np) {
|
||||
dev_err(iodev->dev, "could not find regulators sub-node\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdata->num_regulators = ARRAY_SIZE(regulators);
|
||||
rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
|
||||
pdata->num_regulators, GFP_KERNEL);
|
||||
if (!rdata) {
|
||||
dev_err(iodev->dev,
|
||||
"could not allocate memory for regulator data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < pdata->num_regulators; i++) {
|
||||
rmatch.name = regulators[i].name;
|
||||
rmatch.init_data = NULL;
|
||||
rmatch.of_node = NULL;
|
||||
of_regulator_match(iodev->dev, regulators_np, &rmatch, 1);
|
||||
rdata[i].initdata = rmatch.init_data;
|
||||
}
|
||||
|
||||
pdata->regulators = rdata;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
|
||||
struct max77686_platform_data *pdata)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static __devinit int max77686_pmic_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
|
||||
struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
|
||||
struct regulator_dev **rdev;
|
||||
struct max77686_data *max77686;
|
||||
int i, size;
|
||||
int ret = 0;
|
||||
struct regulator_config config = { };
|
||||
|
||||
dev_dbg(&pdev->dev, "%s\n", __func__);
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "no platform data found for regulator\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (iodev->dev->of_node) {
|
||||
ret = max77686_pmic_dt_parse_pdata(iodev, pdata);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pdata->num_regulators != MAX77686_REGULATORS) {
|
||||
dev_err(&pdev->dev,
|
||||
"Invalid initial data for regulator's initialiation\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data),
|
||||
GFP_KERNEL);
|
||||
if (!max77686)
|
||||
return -ENOMEM;
|
||||
|
||||
size = sizeof(struct regulator_dev *) * MAX77686_REGULATORS;
|
||||
max77686->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
|
||||
if (!max77686->rdev)
|
||||
return -ENOMEM;
|
||||
|
||||
rdev = max77686->rdev;
|
||||
config.dev = &pdev->dev;
|
||||
config.regmap = iodev->regmap;
|
||||
platform_set_drvdata(pdev, max77686);
|
||||
|
||||
for (i = 0; i < MAX77686_REGULATORS; i++) {
|
||||
config.init_data = pdata->regulators[i].initdata;
|
||||
|
||||
rdev[i] = regulator_register(®ulators[i], &config);
|
||||
if (IS_ERR(rdev[i])) {
|
||||
ret = PTR_ERR(rdev[i]);
|
||||
dev_err(&pdev->dev,
|
||||
"regulator init failed for %d\n", i);
|
||||
rdev[i] = NULL;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
while (--i >= 0)
|
||||
regulator_unregister(rdev[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit max77686_pmic_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct max77686_data *max77686 = platform_get_drvdata(pdev);
|
||||
struct regulator_dev **rdev = max77686->rdev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX77686_REGULATORS; i++)
|
||||
if (rdev[i])
|
||||
regulator_unregister(rdev[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id max77686_pmic_id[] = {
|
||||
{"max77686-pmic", 0},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, max77686_pmic_id);
|
||||
|
||||
static struct platform_driver max77686_pmic_driver = {
|
||||
.driver = {
|
||||
.name = "max77686-pmic",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = max77686_pmic_probe,
|
||||
.remove = __devexit_p(max77686_pmic_remove),
|
||||
.id_table = max77686_pmic_id,
|
||||
};
|
||||
|
||||
static int __init max77686_pmic_init(void)
|
||||
{
|
||||
return platform_driver_register(&max77686_pmic_driver);
|
||||
}
|
||||
subsys_initcall(max77686_pmic_init);
|
||||
|
||||
static void __exit max77686_pmic_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&max77686_pmic_driver);
|
||||
}
|
||||
module_exit(max77686_pmic_cleanup);
|
||||
|
||||
MODULE_DESCRIPTION("MAXIM 77686 Regulator Driver");
|
||||
MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -51,7 +51,6 @@ struct max8952_data {
|
||||
|
||||
bool vid0;
|
||||
bool vid1;
|
||||
bool en;
|
||||
};
|
||||
|
||||
static int max8952_read_reg(struct max8952_data *max8952, u8 reg)
|
||||
@@ -80,38 +79,6 @@ static int max8952_list_voltage(struct regulator_dev *rdev,
|
||||
return (max8952->pdata->dvs_mode[selector] * 10 + 770) * 1000;
|
||||
}
|
||||
|
||||
static int max8952_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8952_data *max8952 = rdev_get_drvdata(rdev);
|
||||
return max8952->en;
|
||||
}
|
||||
|
||||
static int max8952_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8952_data *max8952 = rdev_get_drvdata(rdev);
|
||||
|
||||
/* If not valid, assume "ALWAYS_HIGH" */
|
||||
if (gpio_is_valid(max8952->pdata->gpio_en))
|
||||
gpio_set_value(max8952->pdata->gpio_en, 1);
|
||||
|
||||
max8952->en = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max8952_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8952_data *max8952 = rdev_get_drvdata(rdev);
|
||||
|
||||
/* If not valid, assume "ALWAYS_HIGH" -> not permitted */
|
||||
if (gpio_is_valid(max8952->pdata->gpio_en))
|
||||
gpio_set_value(max8952->pdata->gpio_en, 0);
|
||||
else
|
||||
return -EPERM;
|
||||
|
||||
max8952->en = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max8952_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8952_data *max8952 = rdev_get_drvdata(rdev);
|
||||
@@ -146,12 +113,8 @@ static int max8952_set_voltage_sel(struct regulator_dev *rdev,
|
||||
|
||||
static struct regulator_ops max8952_ops = {
|
||||
.list_voltage = max8952_list_voltage,
|
||||
.is_enabled = max8952_is_enabled,
|
||||
.enable = max8952_enable,
|
||||
.disable = max8952_disable,
|
||||
.get_voltage_sel = max8952_get_voltage_sel,
|
||||
.set_voltage_sel = max8952_set_voltage_sel,
|
||||
.set_suspend_disable = max8952_disable,
|
||||
};
|
||||
|
||||
static const struct regulator_desc regulator = {
|
||||
@@ -194,6 +157,10 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
|
||||
config.init_data = &pdata->reg_data;
|
||||
config.driver_data = max8952;
|
||||
|
||||
config.ena_gpio = pdata->gpio_en;
|
||||
if (pdata->reg_data.constraints.boot_on)
|
||||
config.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
|
||||
|
||||
max8952->rdev = regulator_register(®ulator, &config);
|
||||
|
||||
if (IS_ERR(max8952->rdev)) {
|
||||
@@ -202,27 +169,9 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
|
||||
return ret;
|
||||
}
|
||||
|
||||
max8952->en = !!(pdata->reg_data.constraints.boot_on);
|
||||
max8952->vid0 = pdata->default_mode & 0x1;
|
||||
max8952->vid1 = (pdata->default_mode >> 1) & 0x1;
|
||||
|
||||
if (gpio_is_valid(pdata->gpio_en)) {
|
||||
if (!gpio_request(pdata->gpio_en, "MAX8952 EN"))
|
||||
gpio_direction_output(pdata->gpio_en, max8952->en);
|
||||
else
|
||||
err = 1;
|
||||
} else
|
||||
err = 2;
|
||||
|
||||
if (err) {
|
||||
dev_info(max8952->dev, "EN gpio invalid: assume that EN"
|
||||
"is always High\n");
|
||||
max8952->en = 1;
|
||||
pdata->gpio_en = -1; /* Mark invalid */
|
||||
}
|
||||
|
||||
err = 0;
|
||||
|
||||
if (gpio_is_valid(pdata->gpio_vid0) &&
|
||||
gpio_is_valid(pdata->gpio_vid1)) {
|
||||
if (!gpio_request(pdata->gpio_vid0, "MAX8952 VID0"))
|
||||
@@ -308,7 +257,6 @@ static int __devexit max8952_pmic_remove(struct i2c_client *client)
|
||||
|
||||
gpio_free(pdata->gpio_vid0);
|
||||
gpio_free(pdata->gpio_vid1);
|
||||
gpio_free(pdata->gpio_en);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1025,7 +1025,6 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
|
||||
*/
|
||||
if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||
|
||||
pdata->buck5_gpiodvs) {
|
||||
bool gpio1set = false, gpio2set = false;
|
||||
|
||||
if (!gpio_is_valid(pdata->buck125_gpios[0]) ||
|
||||
!gpio_is_valid(pdata->buck125_gpios[1]) ||
|
||||
@@ -1035,40 +1034,20 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
ret = gpio_request(pdata->buck125_gpios[0],
|
||||
"MAX8997 SET1");
|
||||
if (ret == -EBUSY)
|
||||
dev_warn(&pdev->dev, "Duplicated gpio request"
|
||||
" on SET1\n");
|
||||
else if (ret)
|
||||
ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[0],
|
||||
"MAX8997 SET1");
|
||||
if (ret)
|
||||
goto err_out;
|
||||
else
|
||||
gpio1set = true;
|
||||
|
||||
ret = gpio_request(pdata->buck125_gpios[1],
|
||||
"MAX8997 SET2");
|
||||
if (ret == -EBUSY)
|
||||
dev_warn(&pdev->dev, "Duplicated gpio request"
|
||||
" on SET2\n");
|
||||
else if (ret) {
|
||||
if (gpio1set)
|
||||
gpio_free(pdata->buck125_gpios[0]);
|
||||
ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[1],
|
||||
"MAX8997 SET2");
|
||||
if (ret)
|
||||
goto err_out;
|
||||
} else
|
||||
gpio2set = true;
|
||||
|
||||
ret = gpio_request(pdata->buck125_gpios[2],
|
||||
ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[2],
|
||||
"MAX8997 SET3");
|
||||
if (ret == -EBUSY)
|
||||
dev_warn(&pdev->dev, "Duplicated gpio request"
|
||||
" on SET3\n");
|
||||
else if (ret) {
|
||||
if (gpio1set)
|
||||
gpio_free(pdata->buck125_gpios[0]);
|
||||
if (gpio2set)
|
||||
gpio_free(pdata->buck125_gpios[1]);
|
||||
if (ret)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
gpio_direction_output(pdata->buck125_gpios[0],
|
||||
(max8997->buck125_gpioindex >> 2)
|
||||
@@ -1079,7 +1058,6 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
|
||||
gpio_direction_output(pdata->buck125_gpios[2],
|
||||
(max8997->buck125_gpioindex >> 0)
|
||||
& 0x1); /* SET3 */
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
/* DVS-GPIO disabled */
|
||||
|
||||
+33
-100
@@ -111,27 +111,6 @@ static const struct voltage_map_desc *ldo_voltage_map[] = {
|
||||
&buck4_voltage_map_desc, /* BUCK4 */
|
||||
};
|
||||
|
||||
static int max8998_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned int selector)
|
||||
{
|
||||
const struct voltage_map_desc *desc;
|
||||
int ldo = rdev_get_id(rdev);
|
||||
int val;
|
||||
|
||||
if (ldo >= ARRAY_SIZE(ldo_voltage_map))
|
||||
return -EINVAL;
|
||||
|
||||
desc = ldo_voltage_map[ldo];
|
||||
if (desc == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
val = desc->min + desc->step * selector;
|
||||
if (val > desc->max)
|
||||
return -EINVAL;
|
||||
|
||||
return val * 1000;
|
||||
}
|
||||
|
||||
static int max8998_get_enable_register(struct regulator_dev *rdev,
|
||||
int *reg, int *shift)
|
||||
{
|
||||
@@ -297,41 +276,18 @@ static int max8998_get_voltage_sel(struct regulator_dev *rdev)
|
||||
return val;
|
||||
}
|
||||
|
||||
static int max8998_set_voltage_ldo(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV, unsigned *selector)
|
||||
static int max8998_set_voltage_ldo_sel(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct max8998_data *max8998 = rdev_get_drvdata(rdev);
|
||||
struct i2c_client *i2c = max8998->iodev->i2c;
|
||||
int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
|
||||
const struct voltage_map_desc *desc;
|
||||
int ldo = rdev_get_id(rdev);
|
||||
int reg, shift = 0, mask, ret, i;
|
||||
|
||||
if (ldo >= ARRAY_SIZE(ldo_voltage_map))
|
||||
return -EINVAL;
|
||||
|
||||
desc = ldo_voltage_map[ldo];
|
||||
if (desc == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (max_vol < desc->min || min_vol > desc->max)
|
||||
return -EINVAL;
|
||||
|
||||
if (min_vol < desc->min)
|
||||
min_vol = desc->min;
|
||||
|
||||
i = DIV_ROUND_UP(min_vol - desc->min, desc->step);
|
||||
|
||||
if (desc->min + desc->step*i > max_vol)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = i;
|
||||
int reg, shift = 0, mask, ret;
|
||||
|
||||
ret = max8998_get_voltage_register(rdev, ®, &shift, &mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = max8998_update_reg(i2c, reg, i<<shift, mask<<shift);
|
||||
ret = max8998_update_reg(i2c, reg, selector<<shift, mask<<shift);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -347,41 +303,18 @@ static inline void buck2_gpio_set(int gpio, int v)
|
||||
gpio_set_value(gpio, v & 0x1);
|
||||
}
|
||||
|
||||
static int max8998_set_voltage_buck(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV, unsigned *selector)
|
||||
static int max8998_set_voltage_buck_sel(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct max8998_data *max8998 = rdev_get_drvdata(rdev);
|
||||
struct max8998_platform_data *pdata =
|
||||
dev_get_platdata(max8998->iodev->dev);
|
||||
struct i2c_client *i2c = max8998->iodev->i2c;
|
||||
int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
|
||||
const struct voltage_map_desc *desc;
|
||||
int buck = rdev_get_id(rdev);
|
||||
int reg, shift = 0, mask, ret;
|
||||
int i, j, previous_sel;
|
||||
int j, previous_sel;
|
||||
static u8 buck1_last_val;
|
||||
|
||||
if (buck >= ARRAY_SIZE(ldo_voltage_map))
|
||||
return -EINVAL;
|
||||
|
||||
desc = ldo_voltage_map[buck];
|
||||
|
||||
if (desc == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (max_vol < desc->min || min_vol > desc->max)
|
||||
return -EINVAL;
|
||||
|
||||
if (min_vol < desc->min)
|
||||
min_vol = desc->min;
|
||||
|
||||
i = DIV_ROUND_UP(min_vol - desc->min, desc->step);
|
||||
|
||||
if (desc->min + desc->step*i > max_vol)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = i;
|
||||
|
||||
ret = max8998_get_voltage_register(rdev, ®, &shift, &mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -390,19 +323,19 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
|
||||
|
||||
/* Check if voltage needs to be changed */
|
||||
/* if previous_voltage equal new voltage, return */
|
||||
if (previous_sel == i) {
|
||||
if (previous_sel == selector) {
|
||||
dev_dbg(max8998->dev, "No voltage change, old:%d, new:%d\n",
|
||||
max8998_list_voltage(rdev, previous_sel),
|
||||
max8998_list_voltage(rdev, i));
|
||||
regulator_list_voltage_linear(rdev, previous_sel),
|
||||
regulator_list_voltage_linear(rdev, selector));
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (buck) {
|
||||
case MAX8998_BUCK1:
|
||||
dev_dbg(max8998->dev,
|
||||
"BUCK1, i:%d, buck1_vol1:%d, buck1_vol2:%d\n"
|
||||
"BUCK1, selector:%d, buck1_vol1:%d, buck1_vol2:%d\n"
|
||||
"buck1_vol3:%d, buck1_vol4:%d\n",
|
||||
i, max8998->buck1_vol[0], max8998->buck1_vol[1],
|
||||
selector, max8998->buck1_vol[0], max8998->buck1_vol[1],
|
||||
max8998->buck1_vol[2], max8998->buck1_vol[3]);
|
||||
|
||||
if (gpio_is_valid(pdata->buck1_set1) &&
|
||||
@@ -411,7 +344,7 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
|
||||
/* check if requested voltage */
|
||||
/* value is already defined */
|
||||
for (j = 0; j < ARRAY_SIZE(max8998->buck1_vol); j++) {
|
||||
if (max8998->buck1_vol[j] == i) {
|
||||
if (max8998->buck1_vol[j] == selector) {
|
||||
max8998->buck1_idx = j;
|
||||
buck1_gpio_set(pdata->buck1_set1,
|
||||
pdata->buck1_set2, j);
|
||||
@@ -426,11 +359,11 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
|
||||
max8998->buck1_idx = (buck1_last_val % 2) + 2;
|
||||
dev_dbg(max8998->dev, "max8998->buck1_idx:%d\n",
|
||||
max8998->buck1_idx);
|
||||
max8998->buck1_vol[max8998->buck1_idx] = i;
|
||||
max8998->buck1_vol[max8998->buck1_idx] = selector;
|
||||
ret = max8998_get_voltage_register(rdev, ®,
|
||||
&shift,
|
||||
&mask);
|
||||
ret = max8998_write_reg(i2c, reg, i);
|
||||
ret = max8998_write_reg(i2c, reg, selector);
|
||||
buck1_gpio_set(pdata->buck1_set1,
|
||||
pdata->buck1_set2, max8998->buck1_idx);
|
||||
buck1_last_val++;
|
||||
@@ -440,20 +373,20 @@ buck1_exit:
|
||||
gpio_get_value(pdata->buck1_set2));
|
||||
break;
|
||||
} else {
|
||||
ret = max8998_write_reg(i2c, reg, i);
|
||||
ret = max8998_write_reg(i2c, reg, selector);
|
||||
}
|
||||
break;
|
||||
|
||||
case MAX8998_BUCK2:
|
||||
dev_dbg(max8998->dev,
|
||||
"BUCK2, i:%d buck2_vol1:%d, buck2_vol2:%d\n"
|
||||
, i, max8998->buck2_vol[0], max8998->buck2_vol[1]);
|
||||
"BUCK2, selector:%d buck2_vol1:%d, buck2_vol2:%d\n",
|
||||
selector, max8998->buck2_vol[0], max8998->buck2_vol[1]);
|
||||
if (gpio_is_valid(pdata->buck2_set3)) {
|
||||
|
||||
/* check if requested voltage */
|
||||
/* value is already defined */
|
||||
for (j = 0; j < ARRAY_SIZE(max8998->buck2_vol); j++) {
|
||||
if (max8998->buck2_vol[j] == i) {
|
||||
if (max8998->buck2_vol[j] == selector) {
|
||||
max8998->buck2_idx = j;
|
||||
buck2_gpio_set(pdata->buck2_set3, j);
|
||||
goto buck2_exit;
|
||||
@@ -465,20 +398,21 @@ buck1_exit:
|
||||
|
||||
max8998_get_voltage_register(rdev,
|
||||
®, &shift, &mask);
|
||||
ret = max8998_write_reg(i2c, reg, i);
|
||||
max8998->buck2_vol[max8998->buck2_idx] = i;
|
||||
ret = max8998_write_reg(i2c, reg, selector);
|
||||
max8998->buck2_vol[max8998->buck2_idx] = selector;
|
||||
buck2_gpio_set(pdata->buck2_set3, max8998->buck2_idx);
|
||||
buck2_exit:
|
||||
dev_dbg(max8998->dev, "%s: SET3:%d\n", i2c->name,
|
||||
gpio_get_value(pdata->buck2_set3));
|
||||
} else {
|
||||
ret = max8998_write_reg(i2c, reg, i);
|
||||
ret = max8998_write_reg(i2c, reg, selector);
|
||||
}
|
||||
break;
|
||||
|
||||
case MAX8998_BUCK3:
|
||||
case MAX8998_BUCK4:
|
||||
ret = max8998_update_reg(i2c, reg, i<<shift, mask<<shift);
|
||||
ret = max8998_update_reg(i2c, reg, selector<<shift,
|
||||
mask<<shift);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -519,34 +453,30 @@ static int max8998_set_voltage_buck_time_sel(struct regulator_dev *rdev,
|
||||
}
|
||||
|
||||
static struct regulator_ops max8998_ldo_ops = {
|
||||
.list_voltage = max8998_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.is_enabled = max8998_ldo_is_enabled,
|
||||
.enable = max8998_ldo_enable,
|
||||
.disable = max8998_ldo_disable,
|
||||
.get_voltage_sel = max8998_get_voltage_sel,
|
||||
.set_voltage = max8998_set_voltage_ldo,
|
||||
.set_suspend_enable = max8998_ldo_enable,
|
||||
.set_suspend_disable = max8998_ldo_disable,
|
||||
.set_voltage_sel = max8998_set_voltage_ldo_sel,
|
||||
};
|
||||
|
||||
static struct regulator_ops max8998_buck_ops = {
|
||||
.list_voltage = max8998_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.is_enabled = max8998_ldo_is_enabled,
|
||||
.enable = max8998_ldo_enable,
|
||||
.disable = max8998_ldo_disable,
|
||||
.get_voltage_sel = max8998_get_voltage_sel,
|
||||
.set_voltage = max8998_set_voltage_buck,
|
||||
.set_voltage_sel = max8998_set_voltage_buck_sel,
|
||||
.set_voltage_time_sel = max8998_set_voltage_buck_time_sel,
|
||||
.set_suspend_enable = max8998_ldo_enable,
|
||||
.set_suspend_disable = max8998_ldo_disable,
|
||||
};
|
||||
|
||||
static struct regulator_ops max8998_others_ops = {
|
||||
.is_enabled = max8998_ldo_is_enabled,
|
||||
.enable = max8998_ldo_enable,
|
||||
.disable = max8998_ldo_disable,
|
||||
.set_suspend_enable = max8998_ldo_enable,
|
||||
.set_suspend_disable = max8998_ldo_disable,
|
||||
};
|
||||
|
||||
static struct regulator_desc regulators[] = {
|
||||
@@ -860,7 +790,10 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
|
||||
desc = ldo_voltage_map[id];
|
||||
if (desc && regulators[index].ops != &max8998_others_ops) {
|
||||
int count = (desc->max - desc->min) / desc->step + 1;
|
||||
|
||||
regulators[index].n_voltages = count;
|
||||
regulators[index].min_uV = desc->min * 1000;
|
||||
regulators[index].uV_step = desc->step * 1000;
|
||||
}
|
||||
|
||||
config.dev = max8998->dev;
|
||||
|
||||
@@ -93,78 +93,78 @@
|
||||
|
||||
|
||||
/* Voltage Values */
|
||||
static const int mc13783_sw3_val[] = {
|
||||
static const unsigned int mc13783_sw3_val[] = {
|
||||
5000000, 5000000, 5000000, 5500000,
|
||||
};
|
||||
|
||||
static const int mc13783_vaudio_val[] = {
|
||||
static const unsigned int mc13783_vaudio_val[] = {
|
||||
2775000,
|
||||
};
|
||||
|
||||
static const int mc13783_viohi_val[] = {
|
||||
static const unsigned int mc13783_viohi_val[] = {
|
||||
2775000,
|
||||
};
|
||||
|
||||
static const int mc13783_violo_val[] = {
|
||||
static const unsigned int mc13783_violo_val[] = {
|
||||
1200000, 1300000, 1500000, 1800000,
|
||||
};
|
||||
|
||||
static const int mc13783_vdig_val[] = {
|
||||
static const unsigned int mc13783_vdig_val[] = {
|
||||
1200000, 1300000, 1500000, 1800000,
|
||||
};
|
||||
|
||||
static const int mc13783_vgen_val[] = {
|
||||
static const unsigned int mc13783_vgen_val[] = {
|
||||
1200000, 1300000, 1500000, 1800000,
|
||||
1100000, 2000000, 2775000, 2400000,
|
||||
};
|
||||
|
||||
static const int mc13783_vrfdig_val[] = {
|
||||
static const unsigned int mc13783_vrfdig_val[] = {
|
||||
1200000, 1500000, 1800000, 1875000,
|
||||
};
|
||||
|
||||
static const int mc13783_vrfref_val[] = {
|
||||
static const unsigned int mc13783_vrfref_val[] = {
|
||||
2475000, 2600000, 2700000, 2775000,
|
||||
};
|
||||
|
||||
static const int mc13783_vrfcp_val[] = {
|
||||
static const unsigned int mc13783_vrfcp_val[] = {
|
||||
2700000, 2775000,
|
||||
};
|
||||
|
||||
static const int mc13783_vsim_val[] = {
|
||||
static const unsigned int mc13783_vsim_val[] = {
|
||||
1800000, 2900000, 3000000,
|
||||
};
|
||||
|
||||
static const int mc13783_vesim_val[] = {
|
||||
static const unsigned int mc13783_vesim_val[] = {
|
||||
1800000, 2900000,
|
||||
};
|
||||
|
||||
static const int mc13783_vcam_val[] = {
|
||||
static const unsigned int mc13783_vcam_val[] = {
|
||||
1500000, 1800000, 2500000, 2550000,
|
||||
2600000, 2750000, 2800000, 3000000,
|
||||
};
|
||||
|
||||
static const int mc13783_vrfbg_val[] = {
|
||||
static const unsigned int mc13783_vrfbg_val[] = {
|
||||
1250000,
|
||||
};
|
||||
|
||||
static const int mc13783_vvib_val[] = {
|
||||
static const unsigned int mc13783_vvib_val[] = {
|
||||
1300000, 1800000, 2000000, 3000000,
|
||||
};
|
||||
|
||||
static const int mc13783_vmmc_val[] = {
|
||||
static const unsigned int mc13783_vmmc_val[] = {
|
||||
1600000, 1800000, 2000000, 2600000,
|
||||
2700000, 2800000, 2900000, 3000000,
|
||||
};
|
||||
|
||||
static const int mc13783_vrf_val[] = {
|
||||
static const unsigned int mc13783_vrf_val[] = {
|
||||
1500000, 1875000, 2700000, 2775000,
|
||||
};
|
||||
|
||||
static const int mc13783_gpo_val[] = {
|
||||
static const unsigned int mc13783_gpo_val[] = {
|
||||
3100000,
|
||||
};
|
||||
|
||||
static const int mc13783_pwgtdrv_val[] = {
|
||||
static const unsigned int mc13783_pwgtdrv_val[] = {
|
||||
5500000,
|
||||
};
|
||||
|
||||
@@ -328,7 +328,7 @@ static struct regulator_ops mc13783_gpo_regulator_ops = {
|
||||
.enable = mc13783_gpo_regulator_enable,
|
||||
.disable = mc13783_gpo_regulator_disable,
|
||||
.is_enabled = mc13783_gpo_regulator_is_enabled,
|
||||
.list_voltage = mc13xxx_regulator_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.set_voltage = mc13xxx_fixed_regulator_set_voltage,
|
||||
.get_voltage = mc13xxx_fixed_regulator_get_voltage,
|
||||
};
|
||||
|
||||
@@ -150,12 +150,12 @@
|
||||
#define MC13892_USB1 50
|
||||
#define MC13892_USB1_VUSBEN (1<<3)
|
||||
|
||||
static const int mc13892_vcoincell[] = {
|
||||
static const unsigned int mc13892_vcoincell[] = {
|
||||
2500000, 2700000, 2800000, 2900000, 3000000, 3100000,
|
||||
3200000, 3300000,
|
||||
};
|
||||
|
||||
static const int mc13892_sw1[] = {
|
||||
static const unsigned int mc13892_sw1[] = {
|
||||
600000, 625000, 650000, 675000, 700000, 725000,
|
||||
750000, 775000, 800000, 825000, 850000, 875000,
|
||||
900000, 925000, 950000, 975000, 1000000, 1025000,
|
||||
@@ -164,7 +164,7 @@ static const int mc13892_sw1[] = {
|
||||
1350000, 1375000
|
||||
};
|
||||
|
||||
static const int mc13892_sw[] = {
|
||||
static const unsigned int mc13892_sw[] = {
|
||||
600000, 625000, 650000, 675000, 700000, 725000,
|
||||
750000, 775000, 800000, 825000, 850000, 875000,
|
||||
900000, 925000, 950000, 975000, 1000000, 1025000,
|
||||
@@ -176,65 +176,65 @@ static const int mc13892_sw[] = {
|
||||
1800000, 1825000, 1850000, 1875000
|
||||
};
|
||||
|
||||
static const int mc13892_swbst[] = {
|
||||
static const unsigned int mc13892_swbst[] = {
|
||||
5000000,
|
||||
};
|
||||
|
||||
static const int mc13892_viohi[] = {
|
||||
static const unsigned int mc13892_viohi[] = {
|
||||
2775000,
|
||||
};
|
||||
|
||||
static const int mc13892_vpll[] = {
|
||||
static const unsigned int mc13892_vpll[] = {
|
||||
1050000, 1250000, 1650000, 1800000,
|
||||
};
|
||||
|
||||
static const int mc13892_vdig[] = {
|
||||
static const unsigned int mc13892_vdig[] = {
|
||||
1050000, 1250000, 1650000, 1800000,
|
||||
};
|
||||
|
||||
static const int mc13892_vsd[] = {
|
||||
static const unsigned int mc13892_vsd[] = {
|
||||
1800000, 2000000, 2600000, 2700000,
|
||||
2800000, 2900000, 3000000, 3150000,
|
||||
};
|
||||
|
||||
static const int mc13892_vusb2[] = {
|
||||
static const unsigned int mc13892_vusb2[] = {
|
||||
2400000, 2600000, 2700000, 2775000,
|
||||
};
|
||||
|
||||
static const int mc13892_vvideo[] = {
|
||||
static const unsigned int mc13892_vvideo[] = {
|
||||
2700000, 2775000, 2500000, 2600000,
|
||||
};
|
||||
|
||||
static const int mc13892_vaudio[] = {
|
||||
static const unsigned int mc13892_vaudio[] = {
|
||||
2300000, 2500000, 2775000, 3000000,
|
||||
};
|
||||
|
||||
static const int mc13892_vcam[] = {
|
||||
static const unsigned int mc13892_vcam[] = {
|
||||
2500000, 2600000, 2750000, 3000000,
|
||||
};
|
||||
|
||||
static const int mc13892_vgen1[] = {
|
||||
static const unsigned int mc13892_vgen1[] = {
|
||||
1200000, 1500000, 2775000, 3150000,
|
||||
};
|
||||
|
||||
static const int mc13892_vgen2[] = {
|
||||
static const unsigned int mc13892_vgen2[] = {
|
||||
1200000, 1500000, 1600000, 1800000,
|
||||
2700000, 2800000, 3000000, 3150000,
|
||||
};
|
||||
|
||||
static const int mc13892_vgen3[] = {
|
||||
static const unsigned int mc13892_vgen3[] = {
|
||||
1800000, 2900000,
|
||||
};
|
||||
|
||||
static const int mc13892_vusb[] = {
|
||||
static const unsigned int mc13892_vusb[] = {
|
||||
3300000,
|
||||
};
|
||||
|
||||
static const int mc13892_gpo[] = {
|
||||
static const unsigned int mc13892_gpo[] = {
|
||||
2750000,
|
||||
};
|
||||
|
||||
static const int mc13892_pwgtdrv[] = {
|
||||
static const unsigned int mc13892_pwgtdrv[] = {
|
||||
5000000,
|
||||
};
|
||||
|
||||
@@ -394,7 +394,7 @@ static struct regulator_ops mc13892_gpo_regulator_ops = {
|
||||
.enable = mc13892_gpo_regulator_enable,
|
||||
.disable = mc13892_gpo_regulator_disable,
|
||||
.is_enabled = mc13892_gpo_regulator_is_enabled,
|
||||
.list_voltage = mc13xxx_regulator_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.set_voltage = mc13xxx_fixed_regulator_set_voltage,
|
||||
.get_voltage = mc13xxx_fixed_regulator_get_voltage,
|
||||
};
|
||||
@@ -436,7 +436,7 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev,
|
||||
u32 valread;
|
||||
int ret;
|
||||
|
||||
value = mc13892_regulators[id].voltages[selector];
|
||||
value = rdev->desc->volt_table[selector];
|
||||
|
||||
mc13xxx_lock(priv->mc13xxx);
|
||||
ret = mc13xxx_reg_read(priv->mc13xxx,
|
||||
@@ -469,8 +469,7 @@ err:
|
||||
}
|
||||
|
||||
static struct regulator_ops mc13892_sw_regulator_ops = {
|
||||
.is_enabled = mc13xxx_sw_regulator_is_enabled,
|
||||
.list_voltage = mc13xxx_regulator_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.set_voltage_sel = mc13892_sw_regulator_set_voltage_sel,
|
||||
.get_voltage = mc13892_sw_regulator_get_voltage,
|
||||
};
|
||||
|
||||
@@ -80,20 +80,6 @@ static int mc13xxx_regulator_is_enabled(struct regulator_dev *rdev)
|
||||
return (val & mc13xxx_regulators[id].enable_bit) != 0;
|
||||
}
|
||||
|
||||
int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
int id = rdev_get_id(rdev);
|
||||
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
|
||||
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
|
||||
|
||||
if (selector >= mc13xxx_regulators[id].desc.n_voltages)
|
||||
return -EINVAL;
|
||||
|
||||
return mc13xxx_regulators[id].voltages[selector];
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mc13xxx_regulator_list_voltage);
|
||||
|
||||
static int mc13xxx_regulator_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
@@ -135,14 +121,14 @@ static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev)
|
||||
|
||||
BUG_ON(val >= mc13xxx_regulators[id].desc.n_voltages);
|
||||
|
||||
return mc13xxx_regulators[id].voltages[val];
|
||||
return rdev->desc->volt_table[val];
|
||||
}
|
||||
|
||||
struct regulator_ops mc13xxx_regulator_ops = {
|
||||
.enable = mc13xxx_regulator_enable,
|
||||
.disable = mc13xxx_regulator_disable,
|
||||
.is_enabled = mc13xxx_regulator_is_enabled,
|
||||
.list_voltage = mc13xxx_regulator_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.set_voltage_sel = mc13xxx_regulator_set_voltage_sel,
|
||||
.get_voltage = mc13xxx_regulator_get_voltage,
|
||||
};
|
||||
@@ -151,15 +137,13 @@ EXPORT_SYMBOL_GPL(mc13xxx_regulator_ops);
|
||||
int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
|
||||
int max_uV, unsigned *selector)
|
||||
{
|
||||
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
|
||||
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
|
||||
int id = rdev_get_id(rdev);
|
||||
|
||||
dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
|
||||
__func__, id, min_uV, max_uV);
|
||||
|
||||
if (min_uV >= mc13xxx_regulators[id].voltages[0] &&
|
||||
max_uV <= mc13xxx_regulators[id].voltages[0])
|
||||
if (min_uV <= rdev->desc->volt_table[0] &&
|
||||
rdev->desc->volt_table[0] <= max_uV)
|
||||
return 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
@@ -168,13 +152,11 @@ EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_set_voltage);
|
||||
|
||||
int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev)
|
||||
{
|
||||
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
|
||||
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
|
||||
int id = rdev_get_id(rdev);
|
||||
|
||||
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
|
||||
|
||||
return mc13xxx_regulators[id].voltages[0];
|
||||
return rdev->desc->volt_table[0];
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_get_voltage);
|
||||
|
||||
@@ -182,18 +164,12 @@ struct regulator_ops mc13xxx_fixed_regulator_ops = {
|
||||
.enable = mc13xxx_regulator_enable,
|
||||
.disable = mc13xxx_regulator_disable,
|
||||
.is_enabled = mc13xxx_regulator_is_enabled,
|
||||
.list_voltage = mc13xxx_regulator_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.set_voltage = mc13xxx_fixed_regulator_set_voltage,
|
||||
.get_voltage = mc13xxx_fixed_regulator_get_voltage,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops);
|
||||
|
||||
int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mc13xxx_sw_regulator_is_enabled);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
|
||||
{
|
||||
|
||||
@@ -22,7 +22,6 @@ struct mc13xxx_regulator {
|
||||
int vsel_shift;
|
||||
int vsel_mask;
|
||||
int hi_bit;
|
||||
int const *voltages;
|
||||
};
|
||||
|
||||
struct mc13xxx_regulator_priv {
|
||||
@@ -33,10 +32,6 @@ struct mc13xxx_regulator_priv {
|
||||
struct regulator_dev *regulators[];
|
||||
};
|
||||
|
||||
extern int mc13xxx_sw_regulator(struct regulator_dev *rdev);
|
||||
extern int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev);
|
||||
extern int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned selector);
|
||||
extern int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV, unsigned *selector);
|
||||
extern int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev);
|
||||
@@ -68,6 +63,7 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
|
||||
.desc = { \
|
||||
.name = #_name, \
|
||||
.n_voltages = ARRAY_SIZE(_voltages), \
|
||||
.volt_table = _voltages, \
|
||||
.ops = &_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = prefix ## _name, \
|
||||
@@ -78,7 +74,6 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
|
||||
.vsel_reg = prefix ## _vsel_reg, \
|
||||
.vsel_shift = prefix ## _vsel_reg ## _ ## _name ## VSEL,\
|
||||
.vsel_mask = prefix ## _vsel_reg ## _ ## _name ## VSEL_M,\
|
||||
.voltages = _voltages, \
|
||||
}
|
||||
|
||||
#define MC13xxx_FIXED_DEFINE(prefix, _name, _reg, _voltages, _ops) \
|
||||
@@ -86,6 +81,7 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
|
||||
.desc = { \
|
||||
.name = #_name, \
|
||||
.n_voltages = ARRAY_SIZE(_voltages), \
|
||||
.volt_table = _voltages, \
|
||||
.ops = &_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = prefix ## _name, \
|
||||
@@ -93,7 +89,6 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
|
||||
}, \
|
||||
.reg = prefix ## _reg, \
|
||||
.enable_bit = prefix ## _reg ## _ ## _name ## EN, \
|
||||
.voltages = _voltages, \
|
||||
}
|
||||
|
||||
#define MC13xxx_GPO_DEFINE(prefix, _name, _reg, _voltages, _ops) \
|
||||
@@ -101,6 +96,7 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
|
||||
.desc = { \
|
||||
.name = #_name, \
|
||||
.n_voltages = ARRAY_SIZE(_voltages), \
|
||||
.volt_table = _voltages, \
|
||||
.ops = &_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = prefix ## _name, \
|
||||
@@ -108,7 +104,6 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
|
||||
}, \
|
||||
.reg = prefix ## _reg, \
|
||||
.enable_bit = prefix ## _reg ## _ ## _name ## EN, \
|
||||
.voltages = _voltages, \
|
||||
}
|
||||
|
||||
#define MC13xxx_DEFINE_SW(_name, _reg, _vsel_reg, _voltages, ops) \
|
||||
|
||||
@@ -20,7 +20,7 @@ static void of_get_regulation_constraints(struct device_node *np,
|
||||
struct regulator_init_data **init_data)
|
||||
{
|
||||
const __be32 *min_uV, *max_uV, *uV_offset;
|
||||
const __be32 *min_uA, *max_uA;
|
||||
const __be32 *min_uA, *max_uA, *ramp_delay;
|
||||
struct regulation_constraints *constraints = &(*init_data)->constraints;
|
||||
|
||||
constraints->name = of_get_property(np, "regulator-name", NULL);
|
||||
@@ -60,6 +60,10 @@ static void of_get_regulation_constraints(struct device_node *np,
|
||||
constraints->always_on = true;
|
||||
else /* status change should be possible if not always on. */
|
||||
constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;
|
||||
|
||||
ramp_delay = of_get_property(np, "regulator-ramp-delay", NULL);
|
||||
if (ramp_delay)
|
||||
constraints->ramp_delay = be32_to_cpu(*ramp_delay);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,15 +92,17 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
|
||||
EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
|
||||
|
||||
/**
|
||||
* of_regulator_match - extract regulator init data
|
||||
* of_regulator_match - extract regulator init data when node
|
||||
* property "regulator-compatible" matches with the regulator name.
|
||||
* @dev: device requesting the data
|
||||
* @node: parent device node of the regulators
|
||||
* @matches: match table for the regulators
|
||||
* @num_matches: number of entries in match table
|
||||
*
|
||||
* This function uses a match table specified by the regulator driver and
|
||||
* looks up the corresponding init data in the device tree. Note that the
|
||||
* match table is modified in place.
|
||||
* looks up the corresponding init data in the device tree if
|
||||
* regulator-compatible matches. Note that the match table is modified
|
||||
* in place.
|
||||
*
|
||||
* Returns the number of matches found or a negative error code on failure.
|
||||
*/
|
||||
@@ -106,27 +112,40 @@ int of_regulator_match(struct device *dev, struct device_node *node,
|
||||
{
|
||||
unsigned int count = 0;
|
||||
unsigned int i;
|
||||
const char *regulator_comp;
|
||||
struct device_node *child;
|
||||
|
||||
if (!dev || !node)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < num_matches; i++) {
|
||||
struct of_regulator_match *match = &matches[i];
|
||||
struct device_node *child;
|
||||
|
||||
child = of_find_node_by_name(node, match->name);
|
||||
if (!child)
|
||||
continue;
|
||||
|
||||
match->init_data = of_get_regulator_init_data(dev, child);
|
||||
if (!match->init_data) {
|
||||
dev_err(dev, "failed to parse DT for regulator %s\n",
|
||||
for_each_child_of_node(node, child) {
|
||||
regulator_comp = of_get_property(child,
|
||||
"regulator-compatible", NULL);
|
||||
if (!regulator_comp) {
|
||||
dev_err(dev, "regulator-compatible is missing for node %s\n",
|
||||
child->name);
|
||||
return -EINVAL;
|
||||
continue;
|
||||
}
|
||||
for (i = 0; i < num_matches; i++) {
|
||||
struct of_regulator_match *match = &matches[i];
|
||||
if (match->of_node)
|
||||
continue;
|
||||
|
||||
match->of_node = child;
|
||||
count++;
|
||||
if (strcmp(match->name, regulator_comp))
|
||||
continue;
|
||||
|
||||
match->init_data =
|
||||
of_get_regulator_init_data(dev, child);
|
||||
if (!match->init_data) {
|
||||
dev_err(dev,
|
||||
"failed to parse DT for regulator %s\n",
|
||||
child->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
match->of_node = child;
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
|
||||
@@ -257,8 +257,7 @@ static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode)
|
||||
unsigned int reg;
|
||||
|
||||
palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, ®);
|
||||
reg &= ~PALMAS_SMPS12_CTRL_STATUS_MASK;
|
||||
reg >>= PALMAS_SMPS12_CTRL_STATUS_SHIFT;
|
||||
reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
@@ -374,11 +373,22 @@ static int palmas_set_voltage_smps_sel(struct regulator_dev *dev,
|
||||
static int palmas_map_voltage_smps(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
struct palmas_pmic *pmic = rdev_get_drvdata(rdev);
|
||||
int id = rdev_get_id(rdev);
|
||||
int ret, voltage;
|
||||
|
||||
ret = ((min_uV - 500000) / 10000) + 1;
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (min_uV == 0)
|
||||
return 0;
|
||||
|
||||
if (pmic->range[id]) { /* RANGE is x2 */
|
||||
if (min_uV < 1000000)
|
||||
min_uV = 1000000;
|
||||
ret = DIV_ROUND_UP(min_uV - 1000000, 20000) + 1;
|
||||
} else { /* RANGE is x1 */
|
||||
if (min_uV < 500000)
|
||||
min_uV = 500000;
|
||||
ret = DIV_ROUND_UP(min_uV - 500000, 10000) + 1;
|
||||
}
|
||||
|
||||
/* Map back into a voltage to verify we're still in bounds */
|
||||
voltage = palmas_list_voltage_smps(rdev, ret);
|
||||
@@ -400,19 +410,14 @@ static struct regulator_ops palmas_ops_smps = {
|
||||
.map_voltage = palmas_map_voltage_smps,
|
||||
};
|
||||
|
||||
static int palmas_list_voltage_smps10(struct regulator_dev *dev,
|
||||
unsigned selector)
|
||||
{
|
||||
return 3750000 + (selector * 1250000);
|
||||
}
|
||||
|
||||
static struct regulator_ops palmas_ops_smps10 = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.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 = palmas_list_voltage_smps10,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
};
|
||||
|
||||
static int palmas_is_enabled_ldo(struct regulator_dev *dev)
|
||||
@@ -522,7 +527,15 @@ static int palmas_smps_init(struct palmas *palmas, int id,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (id != PALMAS_REG_SMPS10) {
|
||||
switch (id) {
|
||||
case PALMAS_REG_SMPS10:
|
||||
if (reg_init->mode_sleep) {
|
||||
reg &= ~PALMAS_SMPS10_CTRL_MODE_SLEEP_MASK;
|
||||
reg |= reg_init->mode_sleep <<
|
||||
PALMAS_SMPS10_CTRL_MODE_SLEEP_SHIFT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (reg_init->warm_reset)
|
||||
reg |= PALMAS_SMPS12_CTRL_WR_S;
|
||||
|
||||
@@ -534,14 +547,8 @@ static int palmas_smps_init(struct palmas *palmas, int id,
|
||||
reg |= reg_init->mode_sleep <<
|
||||
PALMAS_SMPS12_CTRL_MODE_SLEEP_SHIFT;
|
||||
}
|
||||
} else {
|
||||
if (reg_init->mode_sleep) {
|
||||
reg &= ~PALMAS_SMPS10_CTRL_MODE_SLEEP_MASK;
|
||||
reg |= reg_init->mode_sleep <<
|
||||
PALMAS_SMPS10_CTRL_MODE_SLEEP_SHIFT;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ret = palmas_smps_write(palmas, addr, reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -665,10 +672,8 @@ static __devinit int palmas_probe(struct platform_device *pdev)
|
||||
pmic->desc[id].name = palmas_regs_info[id].name;
|
||||
pmic->desc[id].id = id;
|
||||
|
||||
if (id != PALMAS_REG_SMPS10) {
|
||||
pmic->desc[id].ops = &palmas_ops_smps;
|
||||
pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
|
||||
} else {
|
||||
switch (id) {
|
||||
case PALMAS_REG_SMPS10:
|
||||
pmic->desc[id].n_voltages = PALMAS_SMPS10_NUM_VOLTAGES;
|
||||
pmic->desc[id].ops = &palmas_ops_smps10;
|
||||
pmic->desc[id].vsel_reg = PALMAS_SMPS10_CTRL;
|
||||
@@ -677,6 +682,12 @@ static __devinit int palmas_probe(struct platform_device *pdev)
|
||||
PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
|
||||
PALMAS_SMPS10_STATUS);
|
||||
pmic->desc[id].enable_mask = SMPS10_BOOST_EN;
|
||||
pmic->desc[id].min_uV = 3750000;
|
||||
pmic->desc[id].uV_step = 1250000;
|
||||
break;
|
||||
default:
|
||||
pmic->desc[id].ops = &palmas_ops_smps;
|
||||
pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
|
||||
}
|
||||
|
||||
pmic->desc[id].type = REGULATOR_VOLTAGE;
|
||||
|
||||
@@ -18,80 +18,80 @@
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/mfd/ezx-pcap.h>
|
||||
|
||||
static const u16 V1_table[] = {
|
||||
2775, 1275, 1600, 1725, 1825, 1925, 2075, 2275,
|
||||
static const unsigned int V1_table[] = {
|
||||
2775000, 1275000, 1600000, 1725000, 1825000, 1925000, 2075000, 2275000,
|
||||
};
|
||||
|
||||
static const u16 V2_table[] = {
|
||||
2500, 2775,
|
||||
static const unsigned int V2_table[] = {
|
||||
2500000, 2775000,
|
||||
};
|
||||
|
||||
static const u16 V3_table[] = {
|
||||
1075, 1275, 1550, 1725, 1876, 1950, 2075, 2275,
|
||||
static const unsigned int V3_table[] = {
|
||||
1075000, 1275000, 1550000, 1725000, 1876000, 1950000, 2075000, 2275000,
|
||||
};
|
||||
|
||||
static const u16 V4_table[] = {
|
||||
1275, 1550, 1725, 1875, 1950, 2075, 2275, 2775,
|
||||
static const unsigned int V4_table[] = {
|
||||
1275000, 1550000, 1725000, 1875000, 1950000, 2075000, 2275000, 2775000,
|
||||
};
|
||||
|
||||
static const u16 V5_table[] = {
|
||||
1875, 2275, 2475, 2775,
|
||||
static const unsigned int V5_table[] = {
|
||||
1875000, 2275000, 2475000, 2775000,
|
||||
};
|
||||
|
||||
static const u16 V6_table[] = {
|
||||
2475, 2775,
|
||||
static const unsigned int V6_table[] = {
|
||||
2475000, 2775000,
|
||||
};
|
||||
|
||||
static const u16 V7_table[] = {
|
||||
1875, 2775,
|
||||
static const unsigned int V7_table[] = {
|
||||
1875000, 2775000,
|
||||
};
|
||||
|
||||
#define V8_table V4_table
|
||||
|
||||
static const u16 V9_table[] = {
|
||||
1575, 1875, 2475, 2775,
|
||||
static const unsigned int V9_table[] = {
|
||||
1575000, 1875000, 2475000, 2775000,
|
||||
};
|
||||
|
||||
static const u16 V10_table[] = {
|
||||
5000,
|
||||
static const unsigned int V10_table[] = {
|
||||
5000000,
|
||||
};
|
||||
|
||||
static const u16 VAUX1_table[] = {
|
||||
1875, 2475, 2775, 3000,
|
||||
static const unsigned int VAUX1_table[] = {
|
||||
1875000, 2475000, 2775000, 3000000,
|
||||
};
|
||||
|
||||
#define VAUX2_table VAUX1_table
|
||||
|
||||
static const u16 VAUX3_table[] = {
|
||||
1200, 1200, 1200, 1200, 1400, 1600, 1800, 2000,
|
||||
2200, 2400, 2600, 2800, 3000, 3200, 3400, 3600,
|
||||
static const unsigned int VAUX3_table[] = {
|
||||
1200000, 1200000, 1200000, 1200000, 1400000, 1600000, 1800000, 2000000,
|
||||
2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000, 3600000,
|
||||
};
|
||||
|
||||
static const u16 VAUX4_table[] = {
|
||||
1800, 1800, 3000, 5000,
|
||||
static const unsigned int VAUX4_table[] = {
|
||||
1800000, 1800000, 3000000, 5000000,
|
||||
};
|
||||
|
||||
static const u16 VSIM_table[] = {
|
||||
1875, 3000,
|
||||
static const unsigned int VSIM_table[] = {
|
||||
1875000, 3000000,
|
||||
};
|
||||
|
||||
static const u16 VSIM2_table[] = {
|
||||
1875,
|
||||
static const unsigned int VSIM2_table[] = {
|
||||
1875000,
|
||||
};
|
||||
|
||||
static const u16 VVIB_table[] = {
|
||||
1300, 1800, 2000, 3000,
|
||||
static const unsigned int VVIB_table[] = {
|
||||
1300000, 1800000, 2000000, 3000000,
|
||||
};
|
||||
|
||||
static const u16 SW1_table[] = {
|
||||
900, 950, 1000, 1050, 1100, 1150, 1200, 1250,
|
||||
1300, 1350, 1400, 1450, 1500, 1600, 1875, 2250,
|
||||
static const unsigned int SW1_table[] = {
|
||||
900000, 950000, 1000000, 1050000, 1100000, 1150000, 1200000, 1250000,
|
||||
1300000, 1350000, 1400000, 1450000, 1500000, 1600000, 1875000, 2250000,
|
||||
};
|
||||
|
||||
#define SW2_table SW1_table
|
||||
|
||||
static const u16 SW3_table[] = {
|
||||
4000, 4500, 5000, 5500,
|
||||
static const unsigned int SW3_table[] = {
|
||||
4000000, 4500000, 5000000, 5500000,
|
||||
};
|
||||
|
||||
struct pcap_regulator {
|
||||
@@ -100,8 +100,6 @@ struct pcap_regulator {
|
||||
const u8 index;
|
||||
const u8 stby;
|
||||
const u8 lowpwr;
|
||||
const u8 n_voltages;
|
||||
const u16 *voltage_table;
|
||||
};
|
||||
|
||||
#define NA 0xff
|
||||
@@ -113,8 +111,6 @@ struct pcap_regulator {
|
||||
.index = _index, \
|
||||
.stby = _stby, \
|
||||
.lowpwr = _lowpwr, \
|
||||
.n_voltages = ARRAY_SIZE(_vreg##_table), \
|
||||
.voltage_table = _vreg##_table, \
|
||||
}
|
||||
|
||||
static struct pcap_regulator vreg_table[] = {
|
||||
@@ -157,11 +153,11 @@ static int pcap_regulator_set_voltage_sel(struct regulator_dev *rdev,
|
||||
void *pcap = rdev_get_drvdata(rdev);
|
||||
|
||||
/* the regulator doesn't support voltage switching */
|
||||
if (vreg->n_voltages == 1)
|
||||
if (rdev->desc->n_voltages == 1)
|
||||
return -EINVAL;
|
||||
|
||||
return ezx_pcap_set_bits(pcap, vreg->reg,
|
||||
(vreg->n_voltages - 1) << vreg->index,
|
||||
(rdev->desc->n_voltages - 1) << vreg->index,
|
||||
selector << vreg->index);
|
||||
}
|
||||
|
||||
@@ -171,11 +167,11 @@ static int pcap_regulator_get_voltage_sel(struct regulator_dev *rdev)
|
||||
void *pcap = rdev_get_drvdata(rdev);
|
||||
u32 tmp;
|
||||
|
||||
if (vreg->n_voltages == 1)
|
||||
if (rdev->desc->n_voltages == 1)
|
||||
return 0;
|
||||
|
||||
ezx_pcap_read(pcap, vreg->reg, &tmp);
|
||||
tmp = ((tmp >> vreg->index) & (vreg->n_voltages - 1));
|
||||
tmp = ((tmp >> vreg->index) & (rdev->desc->n_voltages - 1));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -214,16 +210,8 @@ static int pcap_regulator_is_enabled(struct regulator_dev *rdev)
|
||||
return (tmp >> vreg->en) & 1;
|
||||
}
|
||||
|
||||
static int pcap_regulator_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned int index)
|
||||
{
|
||||
struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
|
||||
|
||||
return vreg->voltage_table[index] * 1000;
|
||||
}
|
||||
|
||||
static struct regulator_ops pcap_regulator_ops = {
|
||||
.list_voltage = pcap_regulator_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.set_voltage_sel = pcap_regulator_set_voltage_sel,
|
||||
.get_voltage_sel = pcap_regulator_get_voltage_sel,
|
||||
.enable = pcap_regulator_enable,
|
||||
@@ -236,6 +224,7 @@ static struct regulator_ops pcap_regulator_ops = {
|
||||
.name = #_vreg, \
|
||||
.id = _vreg, \
|
||||
.n_voltages = ARRAY_SIZE(_vreg##_table), \
|
||||
.volt_table = _vreg##_table, \
|
||||
.ops = &pcap_regulator_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
|
||||
@@ -100,13 +100,12 @@ static unsigned int ldo_voltage_value(u8 bits)
|
||||
return 900 + (bits * 100);
|
||||
}
|
||||
|
||||
static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV,
|
||||
unsigned *selector)
|
||||
static int pcf50633_regulator_map_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
struct pcf50633 *pcf;
|
||||
int regulator_id, millivolts;
|
||||
u8 volt_bits, regnr;
|
||||
u8 volt_bits;
|
||||
|
||||
pcf = rdev_get_drvdata(rdev);
|
||||
|
||||
@@ -116,15 +115,11 @@ static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
|
||||
|
||||
millivolts = min_uV / 1000;
|
||||
|
||||
regnr = rdev->desc->vsel_reg;
|
||||
|
||||
switch (regulator_id) {
|
||||
case PCF50633_REGULATOR_AUTO:
|
||||
volt_bits = auto_voltage_bits(millivolts);
|
||||
break;
|
||||
case PCF50633_REGULATOR_DOWN1:
|
||||
volt_bits = down_voltage_bits(millivolts);
|
||||
break;
|
||||
case PCF50633_REGULATOR_DOWN2:
|
||||
volt_bits = down_voltage_bits(millivolts);
|
||||
break;
|
||||
@@ -142,9 +137,7 @@ static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*selector = volt_bits;
|
||||
|
||||
return pcf50633_reg_write(pcf, regnr, volt_bits);
|
||||
return volt_bits;
|
||||
}
|
||||
|
||||
static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
|
||||
@@ -159,8 +152,6 @@ static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
|
||||
millivolts = auto_voltage_value(index);
|
||||
break;
|
||||
case PCF50633_REGULATOR_DOWN1:
|
||||
millivolts = down_voltage_value(index);
|
||||
break;
|
||||
case PCF50633_REGULATOR_DOWN2:
|
||||
millivolts = down_voltage_value(index);
|
||||
break;
|
||||
@@ -182,9 +173,10 @@ static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
|
||||
}
|
||||
|
||||
static struct regulator_ops pcf50633_regulator_ops = {
|
||||
.set_voltage = pcf50633_regulator_set_voltage,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.list_voltage = pcf50633_regulator_list_voltage,
|
||||
.map_voltage = pcf50633_regulator_map_voltage,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
|
||||
@@ -42,7 +42,6 @@ struct rc5t583_regulator_info {
|
||||
|
||||
/* Regulator specific turn-on delay and voltage settling time*/
|
||||
int enable_uv_per_us;
|
||||
int change_uv_per_us;
|
||||
|
||||
/* Used by regulator core */
|
||||
struct regulator_desc desc;
|
||||
@@ -66,25 +65,6 @@ static int rc5t583_regulator_enable_time(struct regulator_dev *rdev)
|
||||
return DIV_ROUND_UP(curr_uV, reg->reg_info->enable_uv_per_us);
|
||||
}
|
||||
|
||||
static int rc5t583_set_voltage_time_sel(struct regulator_dev *rdev,
|
||||
unsigned int old_selector, unsigned int new_selector)
|
||||
{
|
||||
struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
|
||||
int old_uV, new_uV;
|
||||
old_uV = regulator_list_voltage_linear(rdev, old_selector);
|
||||
|
||||
if (old_uV < 0)
|
||||
return old_uV;
|
||||
|
||||
new_uV = regulator_list_voltage_linear(rdev, new_selector);
|
||||
if (new_uV < 0)
|
||||
return new_uV;
|
||||
|
||||
return DIV_ROUND_UP(abs(old_uV - new_uV),
|
||||
reg->reg_info->change_uv_per_us);
|
||||
}
|
||||
|
||||
|
||||
static struct regulator_ops rc5t583_ops = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
@@ -94,7 +74,7 @@ static struct regulator_ops rc5t583_ops = {
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.set_voltage_time_sel = rc5t583_set_voltage_time_sel,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
};
|
||||
|
||||
#define RC5T583_REG(_id, _en_reg, _en_bit, _disc_reg, _disc_bit, \
|
||||
@@ -104,7 +84,6 @@ static struct regulator_ops rc5t583_ops = {
|
||||
.disc_bit = _disc_bit, \
|
||||
.deepsleep_reg = RC5T583_REG_##_id##DAC_DS, \
|
||||
.enable_uv_per_us = _enable_mv * 1000, \
|
||||
.change_uv_per_us = 40 * 1000, \
|
||||
.deepsleep_id = RC5T583_DS_##_id, \
|
||||
.desc = { \
|
||||
.name = "rc5t583-regulator-"#_id, \
|
||||
@@ -119,6 +98,7 @@ static struct regulator_ops rc5t583_ops = {
|
||||
.enable_mask = BIT(_en_bit), \
|
||||
.min_uV = _min_mv * 1000, \
|
||||
.uV_step = _step_uV, \
|
||||
.ramp_delay = 40 * 1000, \
|
||||
}, \
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
* s2mps11.c
|
||||
*
|
||||
* Copyright (c) 2012 Samsung Electronics Co., Ltd
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/mfd/samsung/core.h>
|
||||
#include <linux/mfd/samsung/s2mps11.h>
|
||||
|
||||
struct s2mps11_info {
|
||||
struct regulator_dev **rdev;
|
||||
|
||||
int ramp_delay2;
|
||||
int ramp_delay34;
|
||||
int ramp_delay5;
|
||||
int ramp_delay16;
|
||||
int ramp_delay7810;
|
||||
int ramp_delay9;
|
||||
|
||||
bool buck6_ramp;
|
||||
bool buck2_ramp;
|
||||
bool buck3_ramp;
|
||||
bool buck4_ramp;
|
||||
};
|
||||
|
||||
static int get_ramp_delay(int ramp_delay)
|
||||
{
|
||||
unsigned char cnt = 0;
|
||||
|
||||
ramp_delay /= 6;
|
||||
|
||||
while (true) {
|
||||
ramp_delay = ramp_delay >> 1;
|
||||
if (ramp_delay == 0)
|
||||
break;
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static struct regulator_ops s2mps11_ldo_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
};
|
||||
|
||||
static struct regulator_ops s2mps11_buck_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
};
|
||||
|
||||
#define regulator_desc_ldo1(num) { \
|
||||
.name = "LDO"#num, \
|
||||
.id = S2MPS11_LDO##num, \
|
||||
.ops = &s2mps11_ldo_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = S2MPS11_LDO_MIN, \
|
||||
.uV_step = S2MPS11_LDO_STEP1, \
|
||||
.n_voltages = S2MPS11_LDO_N_VOLTAGES, \
|
||||
.vsel_reg = S2MPS11_REG_L1CTRL + num - 1, \
|
||||
.vsel_mask = S2MPS11_LDO_VSEL_MASK, \
|
||||
.enable_reg = S2MPS11_REG_L1CTRL + num - 1, \
|
||||
.enable_mask = S2MPS11_ENABLE_MASK \
|
||||
}
|
||||
#define regulator_desc_ldo2(num) { \
|
||||
.name = "LDO"#num, \
|
||||
.id = S2MPS11_LDO##num, \
|
||||
.ops = &s2mps11_ldo_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = S2MPS11_LDO_MIN, \
|
||||
.uV_step = S2MPS11_LDO_STEP2, \
|
||||
.n_voltages = S2MPS11_LDO_N_VOLTAGES, \
|
||||
.vsel_reg = S2MPS11_REG_L1CTRL + num - 1, \
|
||||
.vsel_mask = S2MPS11_LDO_VSEL_MASK, \
|
||||
.enable_reg = S2MPS11_REG_L1CTRL + num - 1, \
|
||||
.enable_mask = S2MPS11_ENABLE_MASK \
|
||||
}
|
||||
|
||||
#define regulator_desc_buck1_4(num) { \
|
||||
.name = "BUCK"#num, \
|
||||
.id = S2MPS11_BUCK##num, \
|
||||
.ops = &s2mps11_buck_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = S2MPS11_BUCK_MIN1, \
|
||||
.uV_step = S2MPS11_BUCK_STEP1, \
|
||||
.n_voltages = S2MPS11_BUCK_N_VOLTAGES, \
|
||||
.vsel_reg = S2MPS11_REG_B1CTRL2 + (num - 1) * 2, \
|
||||
.vsel_mask = S2MPS11_BUCK_VSEL_MASK, \
|
||||
.enable_reg = S2MPS11_REG_B1CTRL1 + (num - 1) * 2, \
|
||||
.enable_mask = S2MPS11_ENABLE_MASK \
|
||||
}
|
||||
|
||||
#define regulator_desc_buck5 { \
|
||||
.name = "BUCK5", \
|
||||
.id = S2MPS11_BUCK5, \
|
||||
.ops = &s2mps11_buck_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = S2MPS11_BUCK_MIN1, \
|
||||
.uV_step = S2MPS11_BUCK_STEP1, \
|
||||
.n_voltages = S2MPS11_BUCK_N_VOLTAGES, \
|
||||
.vsel_reg = S2MPS11_REG_B5CTRL2, \
|
||||
.vsel_mask = S2MPS11_BUCK_VSEL_MASK, \
|
||||
.enable_reg = S2MPS11_REG_B5CTRL1, \
|
||||
.enable_mask = S2MPS11_ENABLE_MASK \
|
||||
}
|
||||
|
||||
#define regulator_desc_buck6_8(num) { \
|
||||
.name = "BUCK"#num, \
|
||||
.id = S2MPS11_BUCK##num, \
|
||||
.ops = &s2mps11_buck_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = S2MPS11_BUCK_MIN1, \
|
||||
.uV_step = S2MPS11_BUCK_STEP1, \
|
||||
.n_voltages = S2MPS11_BUCK_N_VOLTAGES, \
|
||||
.vsel_reg = S2MPS11_REG_B6CTRL2 + (num - 6) * 2, \
|
||||
.vsel_mask = S2MPS11_BUCK_VSEL_MASK, \
|
||||
.enable_reg = S2MPS11_REG_B6CTRL1 + (num - 6) * 2, \
|
||||
.enable_mask = S2MPS11_ENABLE_MASK \
|
||||
}
|
||||
|
||||
#define regulator_desc_buck9 { \
|
||||
.name = "BUCK9", \
|
||||
.id = S2MPS11_BUCK9, \
|
||||
.ops = &s2mps11_buck_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = S2MPS11_BUCK_MIN3, \
|
||||
.uV_step = S2MPS11_BUCK_STEP3, \
|
||||
.n_voltages = S2MPS11_BUCK_N_VOLTAGES, \
|
||||
.vsel_reg = S2MPS11_REG_B9CTRL2, \
|
||||
.vsel_mask = S2MPS11_BUCK_VSEL_MASK, \
|
||||
.enable_reg = S2MPS11_REG_B9CTRL1, \
|
||||
.enable_mask = S2MPS11_ENABLE_MASK \
|
||||
}
|
||||
|
||||
#define regulator_desc_buck10 { \
|
||||
.name = "BUCK10", \
|
||||
.id = S2MPS11_BUCK10, \
|
||||
.ops = &s2mps11_buck_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = S2MPS11_BUCK_MIN2, \
|
||||
.uV_step = S2MPS11_BUCK_STEP2, \
|
||||
.n_voltages = S2MPS11_BUCK_N_VOLTAGES, \
|
||||
.vsel_reg = S2MPS11_REG_B9CTRL2, \
|
||||
.vsel_mask = S2MPS11_BUCK_VSEL_MASK, \
|
||||
.enable_reg = S2MPS11_REG_B9CTRL1, \
|
||||
.enable_mask = S2MPS11_ENABLE_MASK \
|
||||
}
|
||||
|
||||
static struct regulator_desc regulators[] = {
|
||||
regulator_desc_ldo2(1),
|
||||
regulator_desc_ldo1(2),
|
||||
regulator_desc_ldo1(3),
|
||||
regulator_desc_ldo1(4),
|
||||
regulator_desc_ldo1(5),
|
||||
regulator_desc_ldo2(6),
|
||||
regulator_desc_ldo1(7),
|
||||
regulator_desc_ldo1(8),
|
||||
regulator_desc_ldo1(9),
|
||||
regulator_desc_ldo1(10),
|
||||
regulator_desc_ldo2(11),
|
||||
regulator_desc_ldo1(12),
|
||||
regulator_desc_ldo1(13),
|
||||
regulator_desc_ldo1(14),
|
||||
regulator_desc_ldo1(15),
|
||||
regulator_desc_ldo1(16),
|
||||
regulator_desc_ldo1(17),
|
||||
regulator_desc_ldo1(18),
|
||||
regulator_desc_ldo1(19),
|
||||
regulator_desc_ldo1(20),
|
||||
regulator_desc_ldo1(21),
|
||||
regulator_desc_ldo2(22),
|
||||
regulator_desc_ldo2(23),
|
||||
regulator_desc_ldo1(24),
|
||||
regulator_desc_ldo1(25),
|
||||
regulator_desc_ldo1(26),
|
||||
regulator_desc_ldo2(27),
|
||||
regulator_desc_ldo1(28),
|
||||
regulator_desc_ldo1(29),
|
||||
regulator_desc_ldo1(30),
|
||||
regulator_desc_ldo1(31),
|
||||
regulator_desc_ldo1(32),
|
||||
regulator_desc_ldo1(33),
|
||||
regulator_desc_ldo1(34),
|
||||
regulator_desc_ldo1(35),
|
||||
regulator_desc_ldo1(36),
|
||||
regulator_desc_ldo1(37),
|
||||
regulator_desc_ldo1(38),
|
||||
regulator_desc_buck1_4(1),
|
||||
regulator_desc_buck1_4(2),
|
||||
regulator_desc_buck1_4(3),
|
||||
regulator_desc_buck1_4(4),
|
||||
regulator_desc_buck5,
|
||||
regulator_desc_buck6_8(6),
|
||||
regulator_desc_buck6_8(7),
|
||||
regulator_desc_buck6_8(8),
|
||||
regulator_desc_buck9,
|
||||
regulator_desc_buck10,
|
||||
};
|
||||
|
||||
static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
|
||||
struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
|
||||
struct regulator_config config = { };
|
||||
struct regulator_dev **rdev;
|
||||
struct s2mps11_info *s2mps11;
|
||||
int i, ret, size;
|
||||
unsigned char ramp_enable, ramp_reg = 0;
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(pdev->dev.parent, "Platform data not supplied\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info),
|
||||
GFP_KERNEL);
|
||||
if (!s2mps11)
|
||||
return -ENOMEM;
|
||||
|
||||
size = sizeof(struct regulator_dev *) * S2MPS11_REGULATOR_MAX;
|
||||
s2mps11->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
|
||||
if (!s2mps11->rdev) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rdev = s2mps11->rdev;
|
||||
platform_set_drvdata(pdev, s2mps11);
|
||||
|
||||
s2mps11->ramp_delay2 = pdata->buck2_ramp_delay;
|
||||
s2mps11->ramp_delay34 = pdata->buck34_ramp_delay;
|
||||
s2mps11->ramp_delay5 = pdata->buck5_ramp_delay;
|
||||
s2mps11->ramp_delay16 = pdata->buck16_ramp_delay;
|
||||
s2mps11->ramp_delay7810 = pdata->buck7810_ramp_delay;
|
||||
s2mps11->ramp_delay9 = pdata->buck9_ramp_delay;
|
||||
|
||||
s2mps11->buck6_ramp = pdata->buck6_ramp_enable;
|
||||
s2mps11->buck2_ramp = pdata->buck2_ramp_enable;
|
||||
s2mps11->buck3_ramp = pdata->buck3_ramp_enable;
|
||||
s2mps11->buck4_ramp = pdata->buck4_ramp_enable;
|
||||
|
||||
ramp_enable = (s2mps11->buck2_ramp << 3) | (s2mps11->buck3_ramp << 2) |
|
||||
(s2mps11->buck4_ramp << 1) | s2mps11->buck6_ramp ;
|
||||
|
||||
if (ramp_enable) {
|
||||
if (s2mps11->buck2_ramp)
|
||||
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) >> 6;
|
||||
if (s2mps11->buck3_ramp || s2mps11->buck4_ramp)
|
||||
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) >> 4;
|
||||
sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable);
|
||||
}
|
||||
|
||||
ramp_reg &= 0x00;
|
||||
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) >> 6;
|
||||
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) >> 4;
|
||||
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) >> 2;
|
||||
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9);
|
||||
sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg);
|
||||
|
||||
for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) {
|
||||
|
||||
config.dev = &pdev->dev;
|
||||
config.regmap = iodev->regmap;
|
||||
config.init_data = pdata->regulators[i].initdata;
|
||||
config.driver_data = s2mps11;
|
||||
|
||||
rdev[i] = regulator_register(®ulators[i], &config);
|
||||
if (IS_ERR(rdev[i])) {
|
||||
ret = PTR_ERR(rdev[i]);
|
||||
dev_err(&pdev->dev, "regulator init failed for %d\n",
|
||||
i);
|
||||
rdev[i] = NULL;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
for (i = 0; i < S2MPS11_REGULATOR_MAX; i++)
|
||||
if (rdev[i])
|
||||
regulator_unregister(rdev[i]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit s2mps11_pmic_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev);
|
||||
struct regulator_dev **rdev = s2mps11->rdev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < S2MPS11_REGULATOR_MAX; i++)
|
||||
if (rdev[i])
|
||||
regulator_unregister(rdev[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id s2mps11_pmic_id[] = {
|
||||
{ "s2mps11-pmic", 0},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id);
|
||||
|
||||
static struct platform_driver s2mps11_pmic_driver = {
|
||||
.driver = {
|
||||
.name = "s2mps11-pmic",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = s2mps11_pmic_probe,
|
||||
.remove = __devexit_p(s2mps11_pmic_remove),
|
||||
.id_table = s2mps11_pmic_id,
|
||||
};
|
||||
|
||||
static int __init s2mps11_pmic_init(void)
|
||||
{
|
||||
return platform_driver_register(&s2mps11_pmic_driver);
|
||||
}
|
||||
subsys_initcall(s2mps11_pmic_init);
|
||||
|
||||
static void __exit s2mps11_pmic_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&s2mps11_pmic_driver);
|
||||
}
|
||||
module_exit(s2mps11_pmic_exit);
|
||||
|
||||
/* Module information */
|
||||
MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
|
||||
MODULE_DESCRIPTION("SAMSUNG S2MPS11 Regulator Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
+132
-97
@@ -41,6 +41,7 @@ struct s5m8767_info {
|
||||
u8 buck3_vol[8];
|
||||
u8 buck4_vol[8];
|
||||
int buck_gpios[3];
|
||||
int buck_ds[3];
|
||||
int buck_gpioindex;
|
||||
};
|
||||
|
||||
@@ -120,27 +121,6 @@ static const struct s5m_voltage_desc *reg_voltage_map[] = {
|
||||
[S5M8767_BUCK9] = &buck_voltage_val3,
|
||||
};
|
||||
|
||||
static int s5m8767_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned int selector)
|
||||
{
|
||||
const struct s5m_voltage_desc *desc;
|
||||
int reg_id = rdev_get_id(rdev);
|
||||
int val;
|
||||
|
||||
if (reg_id >= ARRAY_SIZE(reg_voltage_map) || reg_id < 0)
|
||||
return -EINVAL;
|
||||
|
||||
desc = reg_voltage_map[reg_id];
|
||||
if (desc == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
val = desc->min + desc->step * selector;
|
||||
if (val > desc->max)
|
||||
return -EINVAL;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static unsigned int s5m8767_opmode_reg[][4] = {
|
||||
/* {OFF, ON, LOWPOWER, SUSPEND} */
|
||||
/* LDO1 ... LDO28 */
|
||||
@@ -283,17 +263,17 @@ static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg)
|
||||
reg = S5M8767_REG_BUCK1CTRL2;
|
||||
break;
|
||||
case S5M8767_BUCK2:
|
||||
reg = S5M8767_REG_BUCK2DVS1;
|
||||
reg = S5M8767_REG_BUCK2DVS2;
|
||||
if (s5m8767->buck2_gpiodvs)
|
||||
reg += s5m8767->buck_gpioindex;
|
||||
break;
|
||||
case S5M8767_BUCK3:
|
||||
reg = S5M8767_REG_BUCK3DVS1;
|
||||
reg = S5M8767_REG_BUCK3DVS2;
|
||||
if (s5m8767->buck3_gpiodvs)
|
||||
reg += s5m8767->buck_gpioindex;
|
||||
break;
|
||||
case S5M8767_BUCK4:
|
||||
reg = S5M8767_REG_BUCK4DVS1;
|
||||
reg = S5M8767_REG_BUCK4DVS2;
|
||||
if (s5m8767->buck4_gpiodvs)
|
||||
reg += s5m8767->buck_gpioindex;
|
||||
break;
|
||||
@@ -357,32 +337,34 @@ static int s5m8767_convert_voltage_to_sel(
|
||||
return selector;
|
||||
}
|
||||
|
||||
static inline void s5m8767_set_high(struct s5m8767_info *s5m8767)
|
||||
static inline int s5m8767_set_high(struct s5m8767_info *s5m8767)
|
||||
{
|
||||
int temp_index = s5m8767->buck_gpioindex;
|
||||
|
||||
gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
|
||||
gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
|
||||
gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void s5m8767_set_low(struct s5m8767_info *s5m8767)
|
||||
static inline int s5m8767_set_low(struct s5m8767_info *s5m8767)
|
||||
{
|
||||
int temp_index = s5m8767->buck_gpioindex;
|
||||
|
||||
gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
|
||||
gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
|
||||
gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s5m8767_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV, unsigned *selector)
|
||||
static int s5m8767_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
|
||||
const struct s5m_voltage_desc *desc;
|
||||
int reg_id = rdev_get_id(rdev);
|
||||
int sel, reg, mask, ret = 0, old_index, index = 0;
|
||||
u8 val;
|
||||
int reg, mask, ret = 0, old_index, index = 0;
|
||||
u8 *buck234_vol = NULL;
|
||||
|
||||
switch (reg_id) {
|
||||
@@ -407,15 +389,9 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
desc = reg_voltage_map[reg_id];
|
||||
|
||||
sel = s5m8767_convert_voltage_to_sel(desc, min_uV, max_uV);
|
||||
if (sel < 0)
|
||||
return sel;
|
||||
|
||||
/* buck234_vol != NULL means to control buck234 voltage via DVS GPIO */
|
||||
if (buck234_vol) {
|
||||
while (*buck234_vol != sel) {
|
||||
while (*buck234_vol != selector) {
|
||||
buck234_vol++;
|
||||
index++;
|
||||
}
|
||||
@@ -423,22 +399,16 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev,
|
||||
s5m8767->buck_gpioindex = index;
|
||||
|
||||
if (index > old_index)
|
||||
s5m8767_set_high(s5m8767);
|
||||
return s5m8767_set_high(s5m8767);
|
||||
else
|
||||
s5m8767_set_low(s5m8767);
|
||||
return s5m8767_set_low(s5m8767);
|
||||
} else {
|
||||
ret = s5m8767_get_voltage_register(rdev, ®);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
s5m_reg_read(s5m8767->iodev, reg, &val);
|
||||
val = (val & ~mask) | sel;
|
||||
|
||||
ret = s5m_reg_write(s5m8767->iodev, reg, val);
|
||||
return s5m_reg_update(s5m8767->iodev, reg, selector, mask);
|
||||
}
|
||||
|
||||
*selector = sel;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,
|
||||
@@ -458,15 +428,21 @@ static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,
|
||||
}
|
||||
|
||||
static struct regulator_ops s5m8767_ops = {
|
||||
.list_voltage = s5m8767_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.is_enabled = s5m8767_reg_is_enabled,
|
||||
.enable = s5m8767_reg_enable,
|
||||
.disable = s5m8767_reg_disable,
|
||||
.get_voltage_sel = s5m8767_get_voltage_sel,
|
||||
.set_voltage = s5m8767_set_voltage,
|
||||
.set_voltage_sel = s5m8767_set_voltage_sel,
|
||||
.set_voltage_time_sel = s5m8767_set_voltage_time_sel,
|
||||
};
|
||||
|
||||
static struct regulator_ops s5m8767_buck78_ops = {
|
||||
.is_enabled = s5m8767_reg_is_enabled,
|
||||
.enable = s5m8767_reg_enable,
|
||||
.disable = s5m8767_reg_disable,
|
||||
};
|
||||
|
||||
#define s5m8767_regulator_desc(_name) { \
|
||||
.name = #_name, \
|
||||
.id = S5M8767_##_name, \
|
||||
@@ -475,6 +451,14 @@ static struct regulator_ops s5m8767_ops = {
|
||||
.owner = THIS_MODULE, \
|
||||
}
|
||||
|
||||
#define s5m8767_regulator_buck78_desc(_name) { \
|
||||
.name = #_name, \
|
||||
.id = S5M8767_##_name, \
|
||||
.ops = &s5m8767_buck78_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
}
|
||||
|
||||
static struct regulator_desc regulators[] = {
|
||||
s5m8767_regulator_desc(LDO1),
|
||||
s5m8767_regulator_desc(LDO2),
|
||||
@@ -510,8 +494,8 @@ static struct regulator_desc regulators[] = {
|
||||
s5m8767_regulator_desc(BUCK4),
|
||||
s5m8767_regulator_desc(BUCK5),
|
||||
s5m8767_regulator_desc(BUCK6),
|
||||
s5m8767_regulator_desc(BUCK7),
|
||||
s5m8767_regulator_desc(BUCK8),
|
||||
s5m8767_regulator_buck78_desc(BUCK7),
|
||||
s5m8767_regulator_buck78_desc(BUCK8),
|
||||
s5m8767_regulator_desc(BUCK9),
|
||||
};
|
||||
|
||||
@@ -522,7 +506,7 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
|
||||
struct regulator_config config = { };
|
||||
struct regulator_dev **rdev;
|
||||
struct s5m8767_info *s5m8767;
|
||||
int i, ret, size;
|
||||
int i, ret, size, buck_init;
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(pdev->dev.parent, "Platform data not supplied\n");
|
||||
@@ -573,12 +557,37 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
|
||||
s5m8767->buck_gpios[0] = pdata->buck_gpios[0];
|
||||
s5m8767->buck_gpios[1] = pdata->buck_gpios[1];
|
||||
s5m8767->buck_gpios[2] = pdata->buck_gpios[2];
|
||||
s5m8767->buck_ds[0] = pdata->buck_ds[0];
|
||||
s5m8767->buck_ds[1] = pdata->buck_ds[1];
|
||||
s5m8767->buck_ds[2] = pdata->buck_ds[2];
|
||||
|
||||
s5m8767->ramp_delay = pdata->buck_ramp_delay;
|
||||
s5m8767->buck2_ramp = pdata->buck2_ramp_enable;
|
||||
s5m8767->buck3_ramp = pdata->buck3_ramp_enable;
|
||||
s5m8767->buck4_ramp = pdata->buck4_ramp_enable;
|
||||
s5m8767->opmode = pdata->opmode;
|
||||
|
||||
buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
|
||||
pdata->buck2_init,
|
||||
pdata->buck2_init +
|
||||
buck_voltage_val2.step);
|
||||
|
||||
s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK2DVS2, buck_init);
|
||||
|
||||
buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
|
||||
pdata->buck3_init,
|
||||
pdata->buck3_init +
|
||||
buck_voltage_val2.step);
|
||||
|
||||
s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK3DVS2, buck_init);
|
||||
|
||||
buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
|
||||
pdata->buck4_init,
|
||||
pdata->buck4_init +
|
||||
buck_voltage_val2.step);
|
||||
|
||||
s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK4DVS2, buck_init);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (s5m8767->buck2_gpiodvs) {
|
||||
s5m8767->buck2_vol[i] =
|
||||
@@ -608,48 +617,70 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
|
||||
pdata->buck4_gpiodvs) {
|
||||
if (gpio_is_valid(pdata->buck_gpios[0]) &&
|
||||
gpio_is_valid(pdata->buck_gpios[1]) &&
|
||||
gpio_is_valid(pdata->buck_gpios[2])) {
|
||||
ret = gpio_request(pdata->buck_gpios[0],
|
||||
"S5M8767 SET1");
|
||||
if (ret == -EBUSY)
|
||||
dev_warn(&pdev->dev, "Duplicated gpio request for SET1\n");
|
||||
|
||||
ret = gpio_request(pdata->buck_gpios[1],
|
||||
"S5M8767 SET2");
|
||||
if (ret == -EBUSY)
|
||||
dev_warn(&pdev->dev, "Duplicated gpio request for SET2\n");
|
||||
|
||||
ret = gpio_request(pdata->buck_gpios[2],
|
||||
"S5M8767 SET3");
|
||||
if (ret == -EBUSY)
|
||||
dev_warn(&pdev->dev, "Duplicated gpio request for SET3\n");
|
||||
/* SET1 GPIO */
|
||||
gpio_direction_output(pdata->buck_gpios[0],
|
||||
(s5m8767->buck_gpioindex >> 2) & 0x1);
|
||||
/* SET2 GPIO */
|
||||
gpio_direction_output(pdata->buck_gpios[1],
|
||||
(s5m8767->buck_gpioindex >> 1) & 0x1);
|
||||
/* SET3 GPIO */
|
||||
gpio_direction_output(pdata->buck_gpios[2],
|
||||
(s5m8767->buck_gpioindex >> 0) & 0x1);
|
||||
ret = 0;
|
||||
} else {
|
||||
dev_err(&pdev->dev, "GPIO NOT VALID\n");
|
||||
ret = -EINVAL;
|
||||
if (gpio_is_valid(pdata->buck_gpios[0]) &&
|
||||
gpio_is_valid(pdata->buck_gpios[1]) &&
|
||||
gpio_is_valid(pdata->buck_gpios[2])) {
|
||||
ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[0],
|
||||
"S5M8767 SET1");
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[1],
|
||||
"S5M8767 SET2");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[2],
|
||||
"S5M8767 SET3");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* SET1 GPIO */
|
||||
gpio_direction_output(pdata->buck_gpios[0],
|
||||
(s5m8767->buck_gpioindex >> 2) & 0x1);
|
||||
/* SET2 GPIO */
|
||||
gpio_direction_output(pdata->buck_gpios[1],
|
||||
(s5m8767->buck_gpioindex >> 1) & 0x1);
|
||||
/* SET3 GPIO */
|
||||
gpio_direction_output(pdata->buck_gpios[2],
|
||||
(s5m8767->buck_gpioindex >> 0) & 0x1);
|
||||
} else {
|
||||
dev_err(&pdev->dev, "GPIO NOT VALID\n");
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL,
|
||||
(pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
|
||||
s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL,
|
||||
(pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
|
||||
s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL,
|
||||
(pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
|
||||
ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[0], "S5M8767 DS2");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[1], "S5M8767 DS3");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[2], "S5M8767 DS4");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* DS2 GPIO */
|
||||
gpio_direction_output(pdata->buck_ds[0], 0x0);
|
||||
/* DS3 GPIO */
|
||||
gpio_direction_output(pdata->buck_ds[1], 0x0);
|
||||
/* DS4 GPIO */
|
||||
gpio_direction_output(pdata->buck_ds[2], 0x0);
|
||||
|
||||
if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
|
||||
pdata->buck4_gpiodvs) {
|
||||
s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL,
|
||||
(pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1),
|
||||
1 << 1);
|
||||
s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL,
|
||||
(pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1),
|
||||
1 << 1);
|
||||
s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL,
|
||||
(pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1),
|
||||
1 << 1);
|
||||
}
|
||||
|
||||
/* Initialize GPIO DVS registers */
|
||||
for (i = 0; i < 8; i++) {
|
||||
@@ -668,9 +699,6 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
|
||||
s5m8767->buck4_vol[i]);
|
||||
}
|
||||
}
|
||||
s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL, 0x78, 0xff);
|
||||
s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL, 0x58, 0xff);
|
||||
s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL, 0x78, 0xff);
|
||||
|
||||
if (s5m8767->buck2_ramp)
|
||||
s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x08, 0x08);
|
||||
@@ -684,9 +712,13 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
|
||||
if (s5m8767->buck2_ramp || s5m8767->buck3_ramp
|
||||
|| s5m8767->buck4_ramp) {
|
||||
switch (s5m8767->ramp_delay) {
|
||||
case 15:
|
||||
case 5:
|
||||
s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
|
||||
0xc0, 0xf0);
|
||||
0x40, 0xf0);
|
||||
break;
|
||||
case 10:
|
||||
s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
|
||||
0x90, 0xf0);
|
||||
break;
|
||||
case 25:
|
||||
s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
|
||||
@@ -711,9 +743,12 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
|
||||
int id = pdata->regulators[i].id;
|
||||
|
||||
desc = reg_voltage_map[id];
|
||||
if (desc)
|
||||
if (desc) {
|
||||
regulators[id].n_voltages =
|
||||
(desc->max - desc->min) / desc->step + 1;
|
||||
regulators[id].min_uV = desc->min;
|
||||
regulators[id].uV_step = desc->step;
|
||||
}
|
||||
|
||||
config.dev = s5m8767->dev;
|
||||
config.init_data = pdata->regulators[i].initdata;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/tps6105x.h>
|
||||
|
||||
static const int tps6105x_voltages[] = {
|
||||
static const unsigned int tps6105x_voltages[] = {
|
||||
4500000,
|
||||
5000000,
|
||||
5250000,
|
||||
@@ -105,22 +105,13 @@ static int tps6105x_regulator_set_voltage_sel(struct regulator_dev *rdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps6105x_regulator_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
if (selector >= ARRAY_SIZE(tps6105x_voltages))
|
||||
return -EINVAL;
|
||||
|
||||
return tps6105x_voltages[selector];
|
||||
}
|
||||
|
||||
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,
|
||||
.list_voltage = tps6105x_regulator_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
};
|
||||
|
||||
static const struct regulator_desc tps6105x_regulator_desc = {
|
||||
@@ -130,6 +121,7 @@ static const struct regulator_desc tps6105x_regulator_desc = {
|
||||
.id = 0,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = ARRAY_SIZE(tps6105x_voltages),
|
||||
.volt_table = tps6105x_voltages,
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -65,10 +65,8 @@ struct tps62360_chip {
|
||||
struct regulator_desc desc;
|
||||
struct regulator_dev *rdev;
|
||||
struct regmap *regmap;
|
||||
int chip_id;
|
||||
int vsel0_gpio;
|
||||
int vsel1_gpio;
|
||||
int voltage_base;
|
||||
u8 voltage_reg_mask;
|
||||
bool en_internal_pulldn;
|
||||
bool en_discharge;
|
||||
@@ -76,7 +74,6 @@ struct tps62360_chip {
|
||||
int lru_index[4];
|
||||
int curr_vset_vsel[4];
|
||||
int curr_vset_id;
|
||||
int change_uv_per_us;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -175,23 +172,6 @@ static int tps62360_dcdc_set_voltage_sel(struct regulator_dev *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps62360_set_voltage_time_sel(struct regulator_dev *rdev,
|
||||
unsigned int old_selector, unsigned int new_selector)
|
||||
{
|
||||
struct tps62360_chip *tps = rdev_get_drvdata(rdev);
|
||||
int old_uV, new_uV;
|
||||
|
||||
old_uV = regulator_list_voltage_linear(rdev, old_selector);
|
||||
if (old_uV < 0)
|
||||
return old_uV;
|
||||
|
||||
new_uV = regulator_list_voltage_linear(rdev, new_selector);
|
||||
if (new_uV < 0)
|
||||
return new_uV;
|
||||
|
||||
return DIV_ROUND_UP(abs(old_uV - new_uV), tps->change_uv_per_us);
|
||||
}
|
||||
|
||||
static int tps62360_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
{
|
||||
struct tps62360_chip *tps = rdev_get_drvdata(rdev);
|
||||
@@ -258,7 +238,7 @@ static struct regulator_ops tps62360_dcdc_ops = {
|
||||
.set_voltage_sel = tps62360_dcdc_set_voltage_sel,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.set_voltage_time_sel = tps62360_set_voltage_time_sel,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.set_mode = tps62360_set_mode,
|
||||
.get_mode = tps62360_get_mode,
|
||||
};
|
||||
@@ -301,7 +281,7 @@ static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps,
|
||||
ramp_ctrl = (ramp_ctrl >> 4) & 0x7;
|
||||
|
||||
/* ramp mV/us = 32/(2^ramp_ctrl) */
|
||||
tps->change_uv_per_us = DIV_ROUND_UP(32000, BIT(ramp_ctrl));
|
||||
tps->desc.ramp_delay = DIV_ROUND_UP(32000, BIT(ramp_ctrl));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -408,13 +388,13 @@ static int __devinit tps62360_probe(struct i2c_client *client,
|
||||
switch (chip_id) {
|
||||
case TPS62360:
|
||||
case TPS62362:
|
||||
tps->voltage_base = TPS62360_BASE_VOLTAGE;
|
||||
tps->desc.min_uV = TPS62360_BASE_VOLTAGE;
|
||||
tps->voltage_reg_mask = 0x3F;
|
||||
tps->desc.n_voltages = TPS62360_N_VOLTAGES;
|
||||
break;
|
||||
case TPS62361:
|
||||
case TPS62363:
|
||||
tps->voltage_base = TPS62361_BASE_VOLTAGE;
|
||||
tps->desc.min_uV = TPS62361_BASE_VOLTAGE;
|
||||
tps->voltage_reg_mask = 0x7F;
|
||||
tps->desc.n_voltages = TPS62361_N_VOLTAGES;
|
||||
break;
|
||||
@@ -427,7 +407,6 @@ static int __devinit tps62360_probe(struct i2c_client *client,
|
||||
tps->desc.ops = &tps62360_dcdc_ops;
|
||||
tps->desc.type = REGULATOR_VOLTAGE;
|
||||
tps->desc.owner = THIS_MODULE;
|
||||
tps->desc.min_uV = tps->voltage_base;
|
||||
tps->desc.uV_step = 10000;
|
||||
|
||||
tps->regmap = devm_regmap_init_i2c(client, &tps62360_regmap_config);
|
||||
@@ -449,24 +428,24 @@ static int __devinit tps62360_probe(struct i2c_client *client,
|
||||
int gpio_flags;
|
||||
gpio_flags = (pdata->vsel0_def_state) ?
|
||||
GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
|
||||
ret = gpio_request_one(tps->vsel0_gpio,
|
||||
ret = devm_gpio_request_one(&client->dev, tps->vsel0_gpio,
|
||||
gpio_flags, "tps62360-vsel0");
|
||||
if (ret) {
|
||||
dev_err(&client->dev,
|
||||
"%s(): Could not obtain vsel0 GPIO %d: %d\n",
|
||||
__func__, tps->vsel0_gpio, ret);
|
||||
goto err_gpio0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpio_flags = (pdata->vsel1_def_state) ?
|
||||
GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
|
||||
ret = gpio_request_one(tps->vsel1_gpio,
|
||||
ret = devm_gpio_request_one(&client->dev, tps->vsel1_gpio,
|
||||
gpio_flags, "tps62360-vsel1");
|
||||
if (ret) {
|
||||
dev_err(&client->dev,
|
||||
"%s(): Could not obtain vsel1 GPIO %d: %d\n",
|
||||
__func__, tps->vsel1_gpio, ret);
|
||||
goto err_gpio1;
|
||||
return ret;
|
||||
}
|
||||
tps->valid_gpios = true;
|
||||
|
||||
@@ -484,7 +463,7 @@ static int __devinit tps62360_probe(struct i2c_client *client,
|
||||
if (ret < 0) {
|
||||
dev_err(tps->dev, "%s(): Init failed with err = %d\n",
|
||||
__func__, ret);
|
||||
goto err_init;
|
||||
return ret;
|
||||
}
|
||||
|
||||
config.dev = &client->dev;
|
||||
@@ -498,21 +477,11 @@ static int __devinit tps62360_probe(struct i2c_client *client,
|
||||
dev_err(tps->dev,
|
||||
"%s(): regulator register failed with err %s\n",
|
||||
__func__, id->name);
|
||||
ret = PTR_ERR(rdev);
|
||||
goto err_init;
|
||||
return PTR_ERR(rdev);
|
||||
}
|
||||
|
||||
tps->rdev = rdev;
|
||||
return 0;
|
||||
|
||||
err_init:
|
||||
if (gpio_is_valid(tps->vsel1_gpio))
|
||||
gpio_free(tps->vsel1_gpio);
|
||||
err_gpio1:
|
||||
if (gpio_is_valid(tps->vsel0_gpio))
|
||||
gpio_free(tps->vsel0_gpio);
|
||||
err_gpio0:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -525,12 +494,6 @@ static int __devexit tps62360_remove(struct i2c_client *client)
|
||||
{
|
||||
struct tps62360_chip *tps = i2c_get_clientdata(client);
|
||||
|
||||
if (gpio_is_valid(tps->vsel1_gpio))
|
||||
gpio_free(tps->vsel1_gpio);
|
||||
|
||||
if (gpio_is_valid(tps->vsel0_gpio))
|
||||
gpio_free(tps->vsel0_gpio);
|
||||
|
||||
regulator_unregister(tps->rdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -69,10 +69,6 @@
|
||||
#define TPS65023_REG_CTRL2_DCDC1 BIT(1)
|
||||
#define TPS65023_REG_CTRL2_DCDC3 BIT(0)
|
||||
|
||||
/* LDO_CTRL bitfields */
|
||||
#define TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_id) ((ldo_id)*4)
|
||||
#define TPS65023_LDO_CTRL_LDOx_MASK(ldo_id) (0x07 << ((ldo_id)*4))
|
||||
|
||||
/* Number of step-down converters available */
|
||||
#define TPS65023_NUM_DCDC 3
|
||||
/* Number of LDO voltage regulators available */
|
||||
@@ -91,48 +87,53 @@
|
||||
#define TPS65023_MAX_REG_ID TPS65023_LDO_2
|
||||
|
||||
/* Supported voltage values for regulators */
|
||||
static const u16 VCORE_VSEL_table[] = {
|
||||
800, 825, 850, 875,
|
||||
900, 925, 950, 975,
|
||||
1000, 1025, 1050, 1075,
|
||||
1100, 1125, 1150, 1175,
|
||||
1200, 1225, 1250, 1275,
|
||||
1300, 1325, 1350, 1375,
|
||||
1400, 1425, 1450, 1475,
|
||||
1500, 1525, 1550, 1600,
|
||||
static const unsigned int VCORE_VSEL_table[] = {
|
||||
800000, 825000, 850000, 875000,
|
||||
900000, 925000, 950000, 975000,
|
||||
1000000, 1025000, 1050000, 1075000,
|
||||
1100000, 1125000, 1150000, 1175000,
|
||||
1200000, 1225000, 1250000, 1275000,
|
||||
1300000, 1325000, 1350000, 1375000,
|
||||
1400000, 1425000, 1450000, 1475000,
|
||||
1500000, 1525000, 1550000, 1600000,
|
||||
};
|
||||
|
||||
static const unsigned int DCDC_FIXED_3300000_VSEL_table[] = {
|
||||
3300000,
|
||||
};
|
||||
|
||||
static const unsigned int DCDC_FIXED_1800000_VSEL_table[] = {
|
||||
1800000,
|
||||
};
|
||||
|
||||
/* Supported voltage values for LDO regulators for tps65020 */
|
||||
static const u16 TPS65020_LDO1_VSEL_table[] = {
|
||||
1000, 1050, 1100, 1300,
|
||||
1800, 2500, 3000, 3300,
|
||||
static const unsigned int TPS65020_LDO1_VSEL_table[] = {
|
||||
1000000, 1050000, 1100000, 1300000,
|
||||
1800000, 2500000, 3000000, 3300000,
|
||||
};
|
||||
|
||||
static const u16 TPS65020_LDO2_VSEL_table[] = {
|
||||
1000, 1050, 1100, 1300,
|
||||
1800, 2500, 3000, 3300,
|
||||
static const unsigned int TPS65020_LDO2_VSEL_table[] = {
|
||||
1000000, 1050000, 1100000, 1300000,
|
||||
1800000, 2500000, 3000000, 3300000,
|
||||
};
|
||||
|
||||
/* Supported voltage values for LDO regulators
|
||||
* for tps65021 and tps65023 */
|
||||
static const u16 TPS65023_LDO1_VSEL_table[] = {
|
||||
1000, 1100, 1300, 1800,
|
||||
2200, 2600, 2800, 3150,
|
||||
static const unsigned int TPS65023_LDO1_VSEL_table[] = {
|
||||
1000000, 1100000, 1300000, 1800000,
|
||||
2200000, 2600000, 2800000, 3150000,
|
||||
};
|
||||
|
||||
static const u16 TPS65023_LDO2_VSEL_table[] = {
|
||||
1050, 1200, 1300, 1800,
|
||||
2500, 2800, 3000, 3300,
|
||||
static const unsigned int TPS65023_LDO2_VSEL_table[] = {
|
||||
1050000, 1200000, 1300000, 1800000,
|
||||
2500000, 2800000, 3000000, 3300000,
|
||||
};
|
||||
|
||||
/* Regulator specific details */
|
||||
struct tps_info {
|
||||
const char *name;
|
||||
unsigned min_uV;
|
||||
unsigned max_uV;
|
||||
bool fixed;
|
||||
u8 table_len;
|
||||
const u16 *table;
|
||||
const unsigned int *table;
|
||||
};
|
||||
|
||||
/* PMIC details */
|
||||
@@ -150,7 +151,7 @@ struct tps_driver_data {
|
||||
u8 core_regulator;
|
||||
};
|
||||
|
||||
static int tps65023_dcdc_get_voltage(struct regulator_dev *dev)
|
||||
static int tps65023_dcdc_get_voltage_sel(struct regulator_dev *dev)
|
||||
{
|
||||
struct tps_pmic *tps = rdev_get_drvdata(dev);
|
||||
int ret;
|
||||
@@ -164,9 +165,9 @@ static int tps65023_dcdc_get_voltage(struct regulator_dev *dev)
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
data &= (tps->info[dcdc]->table_len - 1);
|
||||
return tps->info[dcdc]->table[data] * 1000;
|
||||
return data;
|
||||
} else
|
||||
return tps->info[dcdc]->min_uV;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps65023_dcdc_set_voltage_sel(struct regulator_dev *dev,
|
||||
@@ -193,76 +194,14 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps65023_ldo_get_voltage(struct regulator_dev *dev)
|
||||
{
|
||||
struct tps_pmic *tps = rdev_get_drvdata(dev);
|
||||
int data, ldo = rdev_get_id(dev);
|
||||
int ret;
|
||||
|
||||
if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
|
||||
return -EINVAL;
|
||||
|
||||
ret = regmap_read(tps->regmap, TPS65023_REG_LDO_CTRL, &data);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
data >>= (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1));
|
||||
data &= (tps->info[ldo]->table_len - 1);
|
||||
return tps->info[ldo]->table[data] * 1000;
|
||||
}
|
||||
|
||||
static int tps65023_ldo_set_voltage_sel(struct regulator_dev *dev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct tps_pmic *tps = rdev_get_drvdata(dev);
|
||||
int ldo_index = rdev_get_id(dev) - TPS65023_LDO_1;
|
||||
|
||||
return regmap_update_bits(tps->regmap, TPS65023_REG_LDO_CTRL,
|
||||
TPS65023_LDO_CTRL_LDOx_MASK(ldo_index),
|
||||
selector << TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_index));
|
||||
}
|
||||
|
||||
static int tps65023_dcdc_list_voltage(struct regulator_dev *dev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct tps_pmic *tps = rdev_get_drvdata(dev);
|
||||
int dcdc = rdev_get_id(dev);
|
||||
|
||||
if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
|
||||
return -EINVAL;
|
||||
|
||||
if (dcdc == tps->core_regulator) {
|
||||
if (selector >= tps->info[dcdc]->table_len)
|
||||
return -EINVAL;
|
||||
else
|
||||
return tps->info[dcdc]->table[selector] * 1000;
|
||||
} else
|
||||
return tps->info[dcdc]->min_uV;
|
||||
}
|
||||
|
||||
static int tps65023_ldo_list_voltage(struct regulator_dev *dev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct tps_pmic *tps = rdev_get_drvdata(dev);
|
||||
int ldo = rdev_get_id(dev);
|
||||
|
||||
if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
|
||||
return -EINVAL;
|
||||
|
||||
if (selector >= tps->info[ldo]->table_len)
|
||||
return -EINVAL;
|
||||
else
|
||||
return tps->info[ldo]->table[selector] * 1000;
|
||||
}
|
||||
|
||||
/* Operations permitted on VDCDCx */
|
||||
static struct regulator_ops tps65023_dcdc_ops = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage = tps65023_dcdc_get_voltage,
|
||||
.get_voltage_sel = tps65023_dcdc_get_voltage_sel,
|
||||
.set_voltage_sel = tps65023_dcdc_set_voltage_sel,
|
||||
.list_voltage = tps65023_dcdc_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
};
|
||||
|
||||
/* Operations permitted on LDOx */
|
||||
@@ -270,9 +209,9 @@ static struct regulator_ops tps65023_ldo_ops = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage = tps65023_ldo_get_voltage,
|
||||
.set_voltage_sel = tps65023_ldo_set_voltage_sel,
|
||||
.list_voltage = tps65023_ldo_list_voltage,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
};
|
||||
|
||||
static struct regmap_config tps65023_regmap_config = {
|
||||
@@ -325,19 +264,28 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
|
||||
tps->desc[i].name = info->name;
|
||||
tps->desc[i].id = i;
|
||||
tps->desc[i].n_voltages = info->table_len;
|
||||
tps->desc[i].volt_table = info->table;
|
||||
tps->desc[i].ops = (i > TPS65023_DCDC_3 ?
|
||||
&tps65023_ldo_ops : &tps65023_dcdc_ops);
|
||||
tps->desc[i].type = REGULATOR_VOLTAGE;
|
||||
tps->desc[i].owner = THIS_MODULE;
|
||||
|
||||
tps->desc[i].enable_reg = TPS65023_REG_REG_CTRL;
|
||||
if (i == TPS65023_LDO_1)
|
||||
switch (i) {
|
||||
case TPS65023_LDO_1:
|
||||
tps->desc[i].vsel_reg = TPS65023_REG_LDO_CTRL;
|
||||
tps->desc[i].vsel_mask = 0x07;
|
||||
tps->desc[i].enable_mask = 1 << 1;
|
||||
else if (i == TPS65023_LDO_2)
|
||||
break;
|
||||
case TPS65023_LDO_2:
|
||||
tps->desc[i].vsel_reg = TPS65023_REG_LDO_CTRL;
|
||||
tps->desc[i].vsel_mask = 0x70;
|
||||
tps->desc[i].enable_mask = 1 << 2;
|
||||
else /* DCDCx */
|
||||
break;
|
||||
default: /* DCDCx */
|
||||
tps->desc[i].enable_mask =
|
||||
1 << (TPS65023_NUM_REGULATOR - i);
|
||||
}
|
||||
|
||||
config.dev = &client->dev;
|
||||
config.init_data = init_data;
|
||||
@@ -384,35 +332,26 @@ static int __devexit tps_65023_remove(struct i2c_client *client)
|
||||
static const struct tps_info tps65020_regs[] = {
|
||||
{
|
||||
.name = "VDCDC1",
|
||||
.min_uV = 3300000,
|
||||
.max_uV = 3300000,
|
||||
.fixed = 1,
|
||||
.table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table),
|
||||
.table = DCDC_FIXED_3300000_VSEL_table,
|
||||
},
|
||||
{
|
||||
.name = "VDCDC2",
|
||||
.min_uV = 1800000,
|
||||
.max_uV = 1800000,
|
||||
.fixed = 1,
|
||||
.table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table),
|
||||
.table = DCDC_FIXED_1800000_VSEL_table,
|
||||
},
|
||||
{
|
||||
.name = "VDCDC3",
|
||||
.min_uV = 800000,
|
||||
.max_uV = 1600000,
|
||||
.table_len = ARRAY_SIZE(VCORE_VSEL_table),
|
||||
.table = VCORE_VSEL_table,
|
||||
},
|
||||
|
||||
{
|
||||
.name = "LDO1",
|
||||
.min_uV = 1000000,
|
||||
.max_uV = 3150000,
|
||||
.table_len = ARRAY_SIZE(TPS65020_LDO1_VSEL_table),
|
||||
.table = TPS65020_LDO1_VSEL_table,
|
||||
},
|
||||
{
|
||||
.name = "LDO2",
|
||||
.min_uV = 1050000,
|
||||
.max_uV = 3300000,
|
||||
.table_len = ARRAY_SIZE(TPS65020_LDO2_VSEL_table),
|
||||
.table = TPS65020_LDO2_VSEL_table,
|
||||
},
|
||||
@@ -421,34 +360,26 @@ static const struct tps_info tps65020_regs[] = {
|
||||
static const struct tps_info tps65021_regs[] = {
|
||||
{
|
||||
.name = "VDCDC1",
|
||||
.min_uV = 3300000,
|
||||
.max_uV = 3300000,
|
||||
.fixed = 1,
|
||||
.table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table),
|
||||
.table = DCDC_FIXED_3300000_VSEL_table,
|
||||
},
|
||||
{
|
||||
.name = "VDCDC2",
|
||||
.min_uV = 1800000,
|
||||
.max_uV = 1800000,
|
||||
.fixed = 1,
|
||||
.table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table),
|
||||
.table = DCDC_FIXED_1800000_VSEL_table,
|
||||
},
|
||||
{
|
||||
.name = "VDCDC3",
|
||||
.min_uV = 800000,
|
||||
.max_uV = 1600000,
|
||||
.table_len = ARRAY_SIZE(VCORE_VSEL_table),
|
||||
.table = VCORE_VSEL_table,
|
||||
},
|
||||
{
|
||||
.name = "LDO1",
|
||||
.min_uV = 1000000,
|
||||
.max_uV = 3150000,
|
||||
.table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),
|
||||
.table = TPS65023_LDO1_VSEL_table,
|
||||
},
|
||||
{
|
||||
.name = "LDO2",
|
||||
.min_uV = 1050000,
|
||||
.max_uV = 3300000,
|
||||
.table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),
|
||||
.table = TPS65023_LDO2_VSEL_table,
|
||||
},
|
||||
@@ -457,34 +388,26 @@ static const struct tps_info tps65021_regs[] = {
|
||||
static const struct tps_info tps65023_regs[] = {
|
||||
{
|
||||
.name = "VDCDC1",
|
||||
.min_uV = 800000,
|
||||
.max_uV = 1600000,
|
||||
.table_len = ARRAY_SIZE(VCORE_VSEL_table),
|
||||
.table = VCORE_VSEL_table,
|
||||
},
|
||||
{
|
||||
.name = "VDCDC2",
|
||||
.min_uV = 3300000,
|
||||
.max_uV = 3300000,
|
||||
.fixed = 1,
|
||||
.table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table),
|
||||
.table = DCDC_FIXED_3300000_VSEL_table,
|
||||
},
|
||||
{
|
||||
.name = "VDCDC3",
|
||||
.min_uV = 1800000,
|
||||
.max_uV = 1800000,
|
||||
.fixed = 1,
|
||||
.table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table),
|
||||
.table = DCDC_FIXED_1800000_VSEL_table,
|
||||
},
|
||||
{
|
||||
.name = "LDO1",
|
||||
.min_uV = 1000000,
|
||||
.max_uV = 3150000,
|
||||
.table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),
|
||||
.table = TPS65023_LDO1_VSEL_table,
|
||||
},
|
||||
{
|
||||
.name = "LDO2",
|
||||
.min_uV = 1050000,
|
||||
.max_uV = 3300000,
|
||||
.table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),
|
||||
.table = TPS65023_LDO2_VSEL_table,
|
||||
},
|
||||
|
||||
@@ -43,58 +43,40 @@
|
||||
/* Number of total regulators available */
|
||||
#define TPS6507X_NUM_REGULATOR (TPS6507X_NUM_DCDC + TPS6507X_NUM_LDO)
|
||||
|
||||
/* Supported voltage values for regulators (in milliVolts) */
|
||||
static const u16 VDCDCx_VSEL_table[] = {
|
||||
725, 750, 775, 800,
|
||||
825, 850, 875, 900,
|
||||
925, 950, 975, 1000,
|
||||
1025, 1050, 1075, 1100,
|
||||
1125, 1150, 1175, 1200,
|
||||
1225, 1250, 1275, 1300,
|
||||
1325, 1350, 1375, 1400,
|
||||
1425, 1450, 1475, 1500,
|
||||
1550, 1600, 1650, 1700,
|
||||
1750, 1800, 1850, 1900,
|
||||
1950, 2000, 2050, 2100,
|
||||
2150, 2200, 2250, 2300,
|
||||
2350, 2400, 2450, 2500,
|
||||
2550, 2600, 2650, 2700,
|
||||
2750, 2800, 2850, 2900,
|
||||
3000, 3100, 3200, 3300,
|
||||
/* Supported voltage values for regulators (in microVolts) */
|
||||
static const unsigned int VDCDCx_VSEL_table[] = {
|
||||
725000, 750000, 775000, 800000,
|
||||
825000, 850000, 875000, 900000,
|
||||
925000, 950000, 975000, 1000000,
|
||||
1025000, 1050000, 1075000, 1100000,
|
||||
1125000, 1150000, 1175000, 1200000,
|
||||
1225000, 1250000, 1275000, 1300000,
|
||||
1325000, 1350000, 1375000, 1400000,
|
||||
1425000, 1450000, 1475000, 1500000,
|
||||
1550000, 1600000, 1650000, 1700000,
|
||||
1750000, 1800000, 1850000, 1900000,
|
||||
1950000, 2000000, 2050000, 2100000,
|
||||
2150000, 2200000, 2250000, 2300000,
|
||||
2350000, 2400000, 2450000, 2500000,
|
||||
2550000, 2600000, 2650000, 2700000,
|
||||
2750000, 2800000, 2850000, 2900000,
|
||||
3000000, 3100000, 3200000, 3300000,
|
||||
};
|
||||
|
||||
static const u16 LDO1_VSEL_table[] = {
|
||||
1000, 1100, 1200, 1250,
|
||||
1300, 1350, 1400, 1500,
|
||||
1600, 1800, 2500, 2750,
|
||||
2800, 3000, 3100, 3300,
|
||||
static const unsigned int LDO1_VSEL_table[] = {
|
||||
1000000, 1100000, 1200000, 1250000,
|
||||
1300000, 1350000, 1400000, 1500000,
|
||||
1600000, 1800000, 2500000, 2750000,
|
||||
2800000, 3000000, 3100000, 3300000,
|
||||
};
|
||||
|
||||
static const u16 LDO2_VSEL_table[] = {
|
||||
725, 750, 775, 800,
|
||||
825, 850, 875, 900,
|
||||
925, 950, 975, 1000,
|
||||
1025, 1050, 1075, 1100,
|
||||
1125, 1150, 1175, 1200,
|
||||
1225, 1250, 1275, 1300,
|
||||
1325, 1350, 1375, 1400,
|
||||
1425, 1450, 1475, 1500,
|
||||
1550, 1600, 1650, 1700,
|
||||
1750, 1800, 1850, 1900,
|
||||
1950, 2000, 2050, 2100,
|
||||
2150, 2200, 2250, 2300,
|
||||
2350, 2400, 2450, 2500,
|
||||
2550, 2600, 2650, 2700,
|
||||
2750, 2800, 2850, 2900,
|
||||
3000, 3100, 3200, 3300,
|
||||
};
|
||||
/* The voltage mapping table for LDO2 is the same as VDCDCx */
|
||||
#define LDO2_VSEL_table VDCDCx_VSEL_table
|
||||
|
||||
struct tps_info {
|
||||
const char *name;
|
||||
unsigned min_uV;
|
||||
unsigned max_uV;
|
||||
u8 table_len;
|
||||
const u16 *table;
|
||||
const unsigned int *table;
|
||||
|
||||
/* Does DCDC high or the low register defines output voltage? */
|
||||
bool defdcdc_default;
|
||||
@@ -103,36 +85,26 @@ struct tps_info {
|
||||
static struct tps_info tps6507x_pmic_regs[] = {
|
||||
{
|
||||
.name = "VDCDC1",
|
||||
.min_uV = 725000,
|
||||
.max_uV = 3300000,
|
||||
.table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
|
||||
.table = VDCDCx_VSEL_table,
|
||||
},
|
||||
{
|
||||
.name = "VDCDC2",
|
||||
.min_uV = 725000,
|
||||
.max_uV = 3300000,
|
||||
.table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
|
||||
.table = VDCDCx_VSEL_table,
|
||||
},
|
||||
{
|
||||
.name = "VDCDC3",
|
||||
.min_uV = 725000,
|
||||
.max_uV = 3300000,
|
||||
.table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
|
||||
.table = VDCDCx_VSEL_table,
|
||||
},
|
||||
{
|
||||
.name = "LDO1",
|
||||
.min_uV = 1000000,
|
||||
.max_uV = 3300000,
|
||||
.table_len = ARRAY_SIZE(LDO1_VSEL_table),
|
||||
.table = LDO1_VSEL_table,
|
||||
},
|
||||
{
|
||||
.name = "LDO2",
|
||||
.min_uV = 725000,
|
||||
.max_uV = 3300000,
|
||||
.table_len = ARRAY_SIZE(LDO2_VSEL_table),
|
||||
.table = LDO2_VSEL_table,
|
||||
},
|
||||
@@ -375,28 +347,13 @@ static int tps6507x_pmic_set_voltage_sel(struct regulator_dev *dev,
|
||||
return tps6507x_pmic_reg_write(tps, reg, data);
|
||||
}
|
||||
|
||||
static int tps6507x_pmic_list_voltage(struct regulator_dev *dev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
|
||||
int rid = rdev_get_id(dev);
|
||||
|
||||
if (rid < TPS6507X_DCDC_1 || rid > TPS6507X_LDO_2)
|
||||
return -EINVAL;
|
||||
|
||||
if (selector >= tps->info[rid]->table_len)
|
||||
return -EINVAL;
|
||||
else
|
||||
return tps->info[rid]->table[selector] * 1000;
|
||||
}
|
||||
|
||||
static struct regulator_ops tps6507x_pmic_ops = {
|
||||
.is_enabled = tps6507x_pmic_is_enabled,
|
||||
.enable = tps6507x_pmic_enable,
|
||||
.disable = tps6507x_pmic_disable,
|
||||
.get_voltage_sel = tps6507x_pmic_get_voltage_sel,
|
||||
.set_voltage_sel = tps6507x_pmic_set_voltage_sel,
|
||||
.list_voltage = tps6507x_pmic_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
};
|
||||
|
||||
static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
|
||||
@@ -449,6 +406,7 @@ static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
|
||||
tps->desc[i].name = info->name;
|
||||
tps->desc[i].id = i;
|
||||
tps->desc[i].n_voltages = info->table_len;
|
||||
tps->desc[i].volt_table = info->table;
|
||||
tps->desc[i].ops = &tps6507x_pmic_ops;
|
||||
tps->desc[i].type = REGULATOR_VOLTAGE;
|
||||
tps->desc[i].owner = THIS_MODULE;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/mfd/tps65217.h>
|
||||
|
||||
#define TPS65217_REGULATOR(_name, _id, _ops, _n) \
|
||||
#define TPS65217_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _em, _t) \
|
||||
{ \
|
||||
.name = _name, \
|
||||
.id = _id, \
|
||||
@@ -34,23 +34,23 @@
|
||||
.n_voltages = _n, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.vsel_reg = _vr, \
|
||||
.vsel_mask = _vm, \
|
||||
.enable_reg = TPS65217_REG_ENABLE, \
|
||||
.enable_mask = _em, \
|
||||
.volt_table = _t, \
|
||||
} \
|
||||
|
||||
#define TPS65217_INFO(_nm, _min, _max, _f1, _f2, _t, _n, _em, _vr, _vm) \
|
||||
#define TPS65217_INFO(_nm, _min, _max, _f1, _f2) \
|
||||
{ \
|
||||
.name = _nm, \
|
||||
.min_uV = _min, \
|
||||
.max_uV = _max, \
|
||||
.vsel_to_uv = _f1, \
|
||||
.uv_to_vsel = _f2, \
|
||||
.table = _t, \
|
||||
.table_len = _n, \
|
||||
.enable_mask = _em, \
|
||||
.set_vout_reg = _vr, \
|
||||
.set_vout_mask = _vm, \
|
||||
}
|
||||
|
||||
static const int LDO1_VSEL_table[] = {
|
||||
static const unsigned int LDO1_VSEL_table[] = {
|
||||
1000000, 1100000, 1200000, 1250000,
|
||||
1300000, 1350000, 1400000, 1500000,
|
||||
1600000, 1800000, 2500000, 2750000,
|
||||
@@ -78,7 +78,7 @@ static int tps65217_vsel_to_uv1(unsigned int vsel)
|
||||
|
||||
static int tps65217_uv_to_vsel1(int uV, unsigned int *vsel)
|
||||
{
|
||||
if ((uV < 0) && (uV > 3300000))
|
||||
if (uV < 0 || uV > 3300000)
|
||||
return -EINVAL;
|
||||
|
||||
if (uV <= 1500000)
|
||||
@@ -112,7 +112,7 @@ static int tps65217_vsel_to_uv2(unsigned int vsel)
|
||||
|
||||
static int tps65217_uv_to_vsel2(int uV, unsigned int *vsel)
|
||||
{
|
||||
if ((uV < 0) && (uV > 3300000))
|
||||
if (uV < 0 || uV > 3300000)
|
||||
return -EINVAL;
|
||||
|
||||
if (uV <= 1900000)
|
||||
@@ -127,46 +127,20 @@ static int tps65217_uv_to_vsel2(int uV, unsigned int *vsel)
|
||||
|
||||
static struct tps_info tps65217_pmic_regs[] = {
|
||||
TPS65217_INFO("DCDC1", 900000, 1800000, tps65217_vsel_to_uv1,
|
||||
tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_DC1_EN,
|
||||
TPS65217_REG_DEFDCDC1, TPS65217_DEFDCDCX_DCDC_MASK),
|
||||
tps65217_uv_to_vsel1),
|
||||
TPS65217_INFO("DCDC2", 900000, 3300000, tps65217_vsel_to_uv1,
|
||||
tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_DC2_EN,
|
||||
TPS65217_REG_DEFDCDC2, TPS65217_DEFDCDCX_DCDC_MASK),
|
||||
tps65217_uv_to_vsel1),
|
||||
TPS65217_INFO("DCDC3", 900000, 1500000, tps65217_vsel_to_uv1,
|
||||
tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_DC3_EN,
|
||||
TPS65217_REG_DEFDCDC3, TPS65217_DEFDCDCX_DCDC_MASK),
|
||||
TPS65217_INFO("LDO1", 1000000, 3300000, NULL, NULL, LDO1_VSEL_table,
|
||||
16, TPS65217_ENABLE_LDO1_EN, TPS65217_REG_DEFLDO1,
|
||||
TPS65217_DEFLDO1_LDO1_MASK),
|
||||
tps65217_uv_to_vsel1),
|
||||
TPS65217_INFO("LDO1", 1000000, 3300000, NULL, NULL),
|
||||
TPS65217_INFO("LDO2", 900000, 3300000, tps65217_vsel_to_uv1,
|
||||
tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_LDO2_EN,
|
||||
TPS65217_REG_DEFLDO2, TPS65217_DEFLDO2_LDO2_MASK),
|
||||
tps65217_uv_to_vsel1),
|
||||
TPS65217_INFO("LDO3", 1800000, 3300000, tps65217_vsel_to_uv2,
|
||||
tps65217_uv_to_vsel2, NULL, 32,
|
||||
TPS65217_ENABLE_LS1_EN | TPS65217_DEFLDO3_LDO3_EN,
|
||||
TPS65217_REG_DEFLS1, TPS65217_DEFLDO3_LDO3_MASK),
|
||||
tps65217_uv_to_vsel2),
|
||||
TPS65217_INFO("LDO4", 1800000, 3300000, tps65217_vsel_to_uv2,
|
||||
tps65217_uv_to_vsel2, NULL, 32,
|
||||
TPS65217_ENABLE_LS2_EN | TPS65217_DEFLDO4_LDO4_EN,
|
||||
TPS65217_REG_DEFLS2, TPS65217_DEFLDO4_LDO4_MASK),
|
||||
tps65217_uv_to_vsel2),
|
||||
};
|
||||
|
||||
static int tps65217_pmic_is_enabled(struct regulator_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
struct tps65217 *tps = rdev_get_drvdata(dev);
|
||||
unsigned int data, rid = rdev_get_id(dev);
|
||||
|
||||
if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
|
||||
return -EINVAL;
|
||||
|
||||
ret = tps65217_reg_read(tps, TPS65217_REG_ENABLE, &data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return (data & tps->info[rid]->enable_mask) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int tps65217_pmic_enable(struct regulator_dev *dev)
|
||||
{
|
||||
struct tps65217 *tps = rdev_get_drvdata(dev);
|
||||
@@ -177,9 +151,8 @@ static int tps65217_pmic_enable(struct regulator_dev *dev)
|
||||
|
||||
/* Enable the regulator and password protection is level 1 */
|
||||
return tps65217_set_bits(tps, TPS65217_REG_ENABLE,
|
||||
tps->info[rid]->enable_mask,
|
||||
tps->info[rid]->enable_mask,
|
||||
TPS65217_PROTECT_L1);
|
||||
dev->desc->enable_mask, dev->desc->enable_mask,
|
||||
TPS65217_PROTECT_L1);
|
||||
}
|
||||
|
||||
static int tps65217_pmic_disable(struct regulator_dev *dev)
|
||||
@@ -192,25 +165,7 @@ static int tps65217_pmic_disable(struct regulator_dev *dev)
|
||||
|
||||
/* Disable the regulator and password protection is level 1 */
|
||||
return tps65217_clear_bits(tps, TPS65217_REG_ENABLE,
|
||||
tps->info[rid]->enable_mask, TPS65217_PROTECT_L1);
|
||||
}
|
||||
|
||||
static int tps65217_pmic_get_voltage_sel(struct regulator_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
struct tps65217 *tps = rdev_get_drvdata(dev);
|
||||
unsigned int selector, rid = rdev_get_id(dev);
|
||||
|
||||
if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
|
||||
return -EINVAL;
|
||||
|
||||
ret = tps65217_reg_read(tps, tps->info[rid]->set_vout_reg, &selector);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
selector &= tps->info[rid]->set_vout_mask;
|
||||
|
||||
return selector;
|
||||
dev->desc->enable_mask, TPS65217_PROTECT_L1);
|
||||
}
|
||||
|
||||
static int tps65217_pmic_set_voltage_sel(struct regulator_dev *dev,
|
||||
@@ -221,8 +176,7 @@ static int tps65217_pmic_set_voltage_sel(struct regulator_dev *dev,
|
||||
unsigned int rid = rdev_get_id(dev);
|
||||
|
||||
/* Set the voltage based on vsel value and write protect level is 2 */
|
||||
ret = tps65217_set_bits(tps, tps->info[rid]->set_vout_reg,
|
||||
tps->info[rid]->set_vout_mask,
|
||||
ret = tps65217_set_bits(tps, dev->desc->vsel_reg, dev->desc->vsel_mask,
|
||||
selector, TPS65217_PROTECT_L2);
|
||||
|
||||
/* Set GO bit for DCDCx to initiate voltage transistion */
|
||||
@@ -252,10 +206,10 @@ static int tps65217_pmic_map_voltage(struct regulator_dev *dev,
|
||||
if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
|
||||
return -EINVAL;
|
||||
|
||||
if (min_uV < tps->info[rid]->min_uV || min_uV > tps->info[rid]->max_uV)
|
||||
return -EINVAL;
|
||||
if (min_uV < tps->info[rid]->min_uV)
|
||||
min_uV = tps->info[rid]->min_uV;
|
||||
|
||||
if (max_uV < tps->info[rid]->min_uV || max_uV > tps->info[rid]->max_uV)
|
||||
if (max_uV < tps->info[rid]->min_uV || min_uV > tps->info[rid]->max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
ret = tps->info[rid]->uv_to_vsel(min_uV, &sel);
|
||||
@@ -274,21 +228,18 @@ static int tps65217_pmic_list_voltage(struct regulator_dev *dev,
|
||||
if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
|
||||
return -EINVAL;
|
||||
|
||||
if (selector >= tps->info[rid]->table_len)
|
||||
if (selector >= dev->desc->n_voltages)
|
||||
return -EINVAL;
|
||||
|
||||
if (tps->info[rid]->table)
|
||||
return tps->info[rid]->table[selector];
|
||||
|
||||
return tps->info[rid]->vsel_to_uv(selector);
|
||||
}
|
||||
|
||||
/* Operations permitted on DCDCx, LDO2, LDO3 and LDO4 */
|
||||
static struct regulator_ops tps65217_pmic_ops = {
|
||||
.is_enabled = tps65217_pmic_is_enabled,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = tps65217_pmic_enable,
|
||||
.disable = tps65217_pmic_disable,
|
||||
.get_voltage_sel = tps65217_pmic_get_voltage_sel,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = tps65217_pmic_set_voltage_sel,
|
||||
.list_voltage = tps65217_pmic_list_voltage,
|
||||
.map_voltage = tps65217_pmic_map_voltage,
|
||||
@@ -296,22 +247,38 @@ static struct regulator_ops tps65217_pmic_ops = {
|
||||
|
||||
/* Operations permitted on LDO1 */
|
||||
static struct regulator_ops tps65217_pmic_ldo1_ops = {
|
||||
.is_enabled = tps65217_pmic_is_enabled,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = tps65217_pmic_enable,
|
||||
.disable = tps65217_pmic_disable,
|
||||
.get_voltage_sel = tps65217_pmic_get_voltage_sel,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = tps65217_pmic_set_voltage_sel,
|
||||
.list_voltage = tps65217_pmic_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
};
|
||||
|
||||
static const struct regulator_desc regulators[] = {
|
||||
TPS65217_REGULATOR("DCDC1", TPS65217_DCDC_1, tps65217_pmic_ops, 64),
|
||||
TPS65217_REGULATOR("DCDC2", TPS65217_DCDC_2, tps65217_pmic_ops, 64),
|
||||
TPS65217_REGULATOR("DCDC3", TPS65217_DCDC_3, tps65217_pmic_ops, 64),
|
||||
TPS65217_REGULATOR("LDO1", TPS65217_LDO_1, tps65217_pmic_ldo1_ops, 16),
|
||||
TPS65217_REGULATOR("LDO2", TPS65217_LDO_2, tps65217_pmic_ops, 64),
|
||||
TPS65217_REGULATOR("LDO3", TPS65217_LDO_3, tps65217_pmic_ops, 32),
|
||||
TPS65217_REGULATOR("LDO4", TPS65217_LDO_4, tps65217_pmic_ops, 32),
|
||||
TPS65217_REGULATOR("DCDC1", TPS65217_DCDC_1, tps65217_pmic_ops, 64,
|
||||
TPS65217_REG_DEFDCDC1, TPS65217_DEFDCDCX_DCDC_MASK,
|
||||
TPS65217_ENABLE_DC1_EN, NULL),
|
||||
TPS65217_REGULATOR("DCDC2", TPS65217_DCDC_2, tps65217_pmic_ops, 64,
|
||||
TPS65217_REG_DEFDCDC2, TPS65217_DEFDCDCX_DCDC_MASK,
|
||||
TPS65217_ENABLE_DC2_EN, NULL),
|
||||
TPS65217_REGULATOR("DCDC3", TPS65217_DCDC_3, tps65217_pmic_ops, 64,
|
||||
TPS65217_REG_DEFDCDC3, TPS65217_DEFDCDCX_DCDC_MASK,
|
||||
TPS65217_ENABLE_DC3_EN, NULL),
|
||||
TPS65217_REGULATOR("LDO1", TPS65217_LDO_1, tps65217_pmic_ldo1_ops, 16,
|
||||
TPS65217_REG_DEFLDO1, TPS65217_DEFLDO1_LDO1_MASK,
|
||||
TPS65217_ENABLE_LDO1_EN, LDO1_VSEL_table),
|
||||
TPS65217_REGULATOR("LDO2", TPS65217_LDO_2, tps65217_pmic_ops, 64,
|
||||
TPS65217_REG_DEFLDO2, TPS65217_DEFLDO2_LDO2_MASK,
|
||||
TPS65217_ENABLE_LDO2_EN, NULL),
|
||||
TPS65217_REGULATOR("LDO3", TPS65217_LDO_3, tps65217_pmic_ops, 32,
|
||||
TPS65217_REG_DEFLS1, TPS65217_DEFLDO3_LDO3_MASK,
|
||||
TPS65217_ENABLE_LS1_EN | TPS65217_DEFLDO3_LDO3_EN,
|
||||
NULL),
|
||||
TPS65217_REGULATOR("LDO4", TPS65217_LDO_4, tps65217_pmic_ops, 32,
|
||||
TPS65217_REG_DEFLS2, TPS65217_DEFLDO4_LDO4_MASK,
|
||||
TPS65217_ENABLE_LS2_EN | TPS65217_DEFLDO4_LDO4_EN,
|
||||
NULL),
|
||||
};
|
||||
|
||||
static int __devinit tps65217_regulator_probe(struct platform_device *pdev)
|
||||
@@ -326,6 +293,7 @@ static int __devinit tps65217_regulator_probe(struct platform_device *pdev)
|
||||
tps->info[pdev->id] = info;
|
||||
|
||||
config.dev = &pdev->dev;
|
||||
config.of_node = pdev->dev.of_node;
|
||||
config.init_data = pdev->dev.platform_data;
|
||||
config.driver_data = tps;
|
||||
|
||||
|
||||
@@ -110,9 +110,6 @@
|
||||
#define N_SWITCH 2
|
||||
#define N_REGULATORS (N_DCDC + N_LDO + N_SWITCH)
|
||||
|
||||
#define FIXED_ILIMSEL BIT(0)
|
||||
#define FIXED_VOLTAGE BIT(1)
|
||||
|
||||
#define CMD_READ(reg) ((reg) << 6)
|
||||
#define CMD_WRITE(reg) (BIT(5) | (reg) << 6)
|
||||
#define STAT_CLK BIT(3)
|
||||
@@ -129,12 +126,9 @@ struct field {
|
||||
struct supply_info {
|
||||
const char *name;
|
||||
int n_voltages;
|
||||
const int *voltages;
|
||||
int fixed_voltage;
|
||||
const unsigned int *voltages;
|
||||
int n_ilimsels;
|
||||
const int *ilimsels;
|
||||
int fixed_ilimsel;
|
||||
int flags;
|
||||
const unsigned int *ilimsels;
|
||||
struct field enable, voltage, ilimsel;
|
||||
};
|
||||
|
||||
@@ -307,7 +301,7 @@ static int write_field(struct tps6524x *hw, const struct field *field,
|
||||
val << field->shift);
|
||||
}
|
||||
|
||||
static const int dcdc1_voltages[] = {
|
||||
static const unsigned int dcdc1_voltages[] = {
|
||||
800000, 825000, 850000, 875000,
|
||||
900000, 925000, 950000, 975000,
|
||||
1000000, 1025000, 1050000, 1075000,
|
||||
@@ -318,7 +312,7 @@ static const int dcdc1_voltages[] = {
|
||||
1500000, 1525000, 1550000, 1575000,
|
||||
};
|
||||
|
||||
static const int dcdc2_voltages[] = {
|
||||
static const unsigned int dcdc2_voltages[] = {
|
||||
1400000, 1450000, 1500000, 1550000,
|
||||
1600000, 1650000, 1700000, 1750000,
|
||||
1800000, 1850000, 1900000, 1950000,
|
||||
@@ -329,7 +323,7 @@ static const int dcdc2_voltages[] = {
|
||||
2800000, 2850000, 2900000, 2950000,
|
||||
};
|
||||
|
||||
static const int dcdc3_voltages[] = {
|
||||
static const unsigned int dcdc3_voltages[] = {
|
||||
2400000, 2450000, 2500000, 2550000, 2600000,
|
||||
2650000, 2700000, 2750000, 2800000, 2850000,
|
||||
2900000, 2950000, 3000000, 3050000, 3100000,
|
||||
@@ -337,38 +331,54 @@ static const int dcdc3_voltages[] = {
|
||||
3400000, 3450000, 3500000, 3550000, 3600000,
|
||||
};
|
||||
|
||||
static const int ldo1_voltages[] = {
|
||||
static const unsigned int ldo1_voltages[] = {
|
||||
4300000, 4350000, 4400000, 4450000,
|
||||
4500000, 4550000, 4600000, 4650000,
|
||||
4700000, 4750000, 4800000, 4850000,
|
||||
4900000, 4950000, 5000000, 5050000,
|
||||
};
|
||||
|
||||
static const int ldo2_voltages[] = {
|
||||
static const unsigned int ldo2_voltages[] = {
|
||||
1100000, 1150000, 1200000, 1250000,
|
||||
1300000, 1700000, 1750000, 1800000,
|
||||
1850000, 1900000, 3150000, 3200000,
|
||||
3250000, 3300000, 3350000, 3400000,
|
||||
};
|
||||
|
||||
static const int ldo_ilimsel[] = {
|
||||
static const unsigned int fixed_5000000_voltage[] = {
|
||||
5000000
|
||||
};
|
||||
|
||||
static const unsigned int ldo_ilimsel[] = {
|
||||
400000, 1500000
|
||||
};
|
||||
|
||||
static const int usb_ilimsel[] = {
|
||||
static const unsigned int usb_ilimsel[] = {
|
||||
200000, 400000, 800000, 1000000
|
||||
};
|
||||
|
||||
static const unsigned int fixed_2400000_ilimsel[] = {
|
||||
2400000
|
||||
};
|
||||
|
||||
static const unsigned int fixed_1200000_ilimsel[] = {
|
||||
1200000
|
||||
};
|
||||
|
||||
static const unsigned int fixed_400000_ilimsel[] = {
|
||||
400000
|
||||
};
|
||||
|
||||
#define __MK_FIELD(_reg, _mask, _shift) \
|
||||
{ .reg = (_reg), .mask = (_mask), .shift = (_shift), }
|
||||
|
||||
static const struct supply_info supply_info[N_REGULATORS] = {
|
||||
{
|
||||
.name = "DCDC1",
|
||||
.flags = FIXED_ILIMSEL,
|
||||
.n_voltages = ARRAY_SIZE(dcdc1_voltages),
|
||||
.voltages = dcdc1_voltages,
|
||||
.fixed_ilimsel = 2400000,
|
||||
.n_ilimsels = ARRAY_SIZE(fixed_2400000_ilimsel),
|
||||
.ilimsels = fixed_2400000_ilimsel,
|
||||
.enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
|
||||
DCDCDCDC1_EN_SHIFT),
|
||||
.voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
|
||||
@@ -376,10 +386,10 @@ static const struct supply_info supply_info[N_REGULATORS] = {
|
||||
},
|
||||
{
|
||||
.name = "DCDC2",
|
||||
.flags = FIXED_ILIMSEL,
|
||||
.n_voltages = ARRAY_SIZE(dcdc2_voltages),
|
||||
.voltages = dcdc2_voltages,
|
||||
.fixed_ilimsel = 1200000,
|
||||
.n_ilimsels = ARRAY_SIZE(fixed_1200000_ilimsel),
|
||||
.ilimsels = fixed_1200000_ilimsel,
|
||||
.enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
|
||||
DCDCDCDC2_EN_SHIFT),
|
||||
.voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
|
||||
@@ -387,10 +397,10 @@ static const struct supply_info supply_info[N_REGULATORS] = {
|
||||
},
|
||||
{
|
||||
.name = "DCDC3",
|
||||
.flags = FIXED_ILIMSEL,
|
||||
.n_voltages = ARRAY_SIZE(dcdc3_voltages),
|
||||
.voltages = dcdc3_voltages,
|
||||
.fixed_ilimsel = 1200000,
|
||||
.n_ilimsels = ARRAY_SIZE(fixed_1200000_ilimsel),
|
||||
.ilimsels = fixed_1200000_ilimsel,
|
||||
.enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
|
||||
DCDCDCDC3_EN_SHIFT),
|
||||
.voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
|
||||
@@ -424,8 +434,8 @@ static const struct supply_info supply_info[N_REGULATORS] = {
|
||||
},
|
||||
{
|
||||
.name = "USB",
|
||||
.flags = FIXED_VOLTAGE,
|
||||
.fixed_voltage = 5000000,
|
||||
.n_voltages = ARRAY_SIZE(fixed_5000000_voltage),
|
||||
.voltages = fixed_5000000_voltage,
|
||||
.n_ilimsels = ARRAY_SIZE(usb_ilimsel),
|
||||
.ilimsels = usb_ilimsel,
|
||||
.enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
|
||||
@@ -435,29 +445,15 @@ static const struct supply_info supply_info[N_REGULATORS] = {
|
||||
},
|
||||
{
|
||||
.name = "LCD",
|
||||
.flags = FIXED_VOLTAGE | FIXED_ILIMSEL,
|
||||
.fixed_voltage = 5000000,
|
||||
.fixed_ilimsel = 400000,
|
||||
.n_voltages = ARRAY_SIZE(fixed_5000000_voltage),
|
||||
.voltages = fixed_5000000_voltage,
|
||||
.n_ilimsels = ARRAY_SIZE(fixed_400000_ilimsel),
|
||||
.ilimsels = fixed_400000_ilimsel,
|
||||
.enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
|
||||
BLOCK_LCD_SHIFT),
|
||||
},
|
||||
};
|
||||
|
||||
static int list_voltage(struct regulator_dev *rdev, unsigned selector)
|
||||
{
|
||||
const struct supply_info *info;
|
||||
struct tps6524x *hw;
|
||||
|
||||
hw = rdev_get_drvdata(rdev);
|
||||
info = &supply_info[rdev_get_id(rdev)];
|
||||
|
||||
if (info->flags & FIXED_VOLTAGE)
|
||||
return selector ? -EINVAL : info->fixed_voltage;
|
||||
|
||||
return ((selector < info->n_voltages) ?
|
||||
info->voltages[selector] : -EINVAL);
|
||||
}
|
||||
|
||||
static int set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
|
||||
{
|
||||
const struct supply_info *info;
|
||||
@@ -466,7 +462,7 @@ static int set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
|
||||
hw = rdev_get_drvdata(rdev);
|
||||
info = &supply_info[rdev_get_id(rdev)];
|
||||
|
||||
if (info->flags & FIXED_VOLTAGE)
|
||||
if (rdev->desc->n_voltages == 1)
|
||||
return -EINVAL;
|
||||
|
||||
return write_field(hw, &info->voltage, selector);
|
||||
@@ -481,7 +477,7 @@ static int get_voltage_sel(struct regulator_dev *rdev)
|
||||
hw = rdev_get_drvdata(rdev);
|
||||
info = &supply_info[rdev_get_id(rdev)];
|
||||
|
||||
if (info->flags & FIXED_VOLTAGE)
|
||||
if (rdev->desc->n_voltages == 1)
|
||||
return 0;
|
||||
|
||||
ret = read_field(hw, &info->voltage);
|
||||
@@ -503,7 +499,7 @@ static int set_current_limit(struct regulator_dev *rdev, int min_uA,
|
||||
hw = rdev_get_drvdata(rdev);
|
||||
info = &supply_info[rdev_get_id(rdev)];
|
||||
|
||||
if (info->flags & FIXED_ILIMSEL)
|
||||
if (info->n_ilimsels == 1)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < info->n_ilimsels; i++)
|
||||
@@ -526,8 +522,8 @@ static int get_current_limit(struct regulator_dev *rdev)
|
||||
hw = rdev_get_drvdata(rdev);
|
||||
info = &supply_info[rdev_get_id(rdev)];
|
||||
|
||||
if (info->flags & FIXED_ILIMSEL)
|
||||
return info->fixed_ilimsel;
|
||||
if (info->n_ilimsels == 1)
|
||||
return info->ilimsels[0];
|
||||
|
||||
ret = read_field(hw, &info->ilimsel);
|
||||
if (ret < 0)
|
||||
@@ -577,7 +573,7 @@ static struct regulator_ops regulator_ops = {
|
||||
.disable = disable_supply,
|
||||
.get_voltage_sel = get_voltage_sel,
|
||||
.set_voltage_sel = set_voltage_sel,
|
||||
.list_voltage = list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.set_current_limit = set_current_limit,
|
||||
.get_current_limit = get_current_limit,
|
||||
};
|
||||
@@ -629,13 +625,11 @@ static int __devinit pmic_probe(struct spi_device *spi)
|
||||
hw->desc[i].name = info->name;
|
||||
hw->desc[i].id = i;
|
||||
hw->desc[i].n_voltages = info->n_voltages;
|
||||
hw->desc[i].volt_table = info->voltages;
|
||||
hw->desc[i].ops = ®ulator_ops;
|
||||
hw->desc[i].type = REGULATOR_VOLTAGE;
|
||||
hw->desc[i].owner = THIS_MODULE;
|
||||
|
||||
if (info->flags & FIXED_VOLTAGE)
|
||||
hw->desc[i].n_voltages = 1;
|
||||
|
||||
config.dev = dev;
|
||||
config.init_data = init_data;
|
||||
config.driver_data = hw;
|
||||
|
||||
@@ -63,8 +63,6 @@ struct tps6586x_regulator {
|
||||
int enable_bit[2];
|
||||
int enable_reg[2];
|
||||
|
||||
int *voltages;
|
||||
|
||||
/* for DVM regulators */
|
||||
int go_reg;
|
||||
int go_bit;
|
||||
@@ -72,22 +70,9 @@ struct tps6586x_regulator {
|
||||
|
||||
static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev)
|
||||
{
|
||||
return rdev_get_dev(rdev)->parent->parent;
|
||||
return rdev_get_dev(rdev)->parent;
|
||||
}
|
||||
|
||||
static int tps6586x_list_voltage(struct regulator_dev *rdev, unsigned selector)
|
||||
{
|
||||
struct tps6586x_regulator *info = rdev_get_drvdata(rdev);
|
||||
int rid = rdev_get_id(rdev);
|
||||
|
||||
/* LDO0 has minimal voltage 1.2V rather than 1.25V */
|
||||
if ((rid == TPS6586X_ID_LDO_0) && (selector == 0))
|
||||
return (info->voltages[0] - 50) * 1000;
|
||||
|
||||
return info->voltages[selector] * 1000;
|
||||
}
|
||||
|
||||
|
||||
static int tps6586x_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
@@ -168,7 +153,7 @@ static int tps6586x_regulator_is_enabled(struct regulator_dev *rdev)
|
||||
}
|
||||
|
||||
static struct regulator_ops tps6586x_regulator_ops = {
|
||||
.list_voltage = tps6586x_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.get_voltage_sel = tps6586x_get_voltage_sel,
|
||||
.set_voltage_sel = tps6586x_set_voltage_sel,
|
||||
|
||||
@@ -177,39 +162,45 @@ static struct regulator_ops tps6586x_regulator_ops = {
|
||||
.disable = tps6586x_regulator_disable,
|
||||
};
|
||||
|
||||
static int tps6586x_ldo_voltages[] = {
|
||||
1250, 1500, 1800, 2500, 2700, 2850, 3100, 3300,
|
||||
static const unsigned int tps6586x_ldo0_voltages[] = {
|
||||
1200000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
|
||||
};
|
||||
|
||||
static int tps6586x_ldo4_voltages[] = {
|
||||
1700, 1725, 1750, 1775, 1800, 1825, 1850, 1875,
|
||||
1900, 1925, 1950, 1975, 2000, 2025, 2050, 2075,
|
||||
2100, 2125, 2150, 2175, 2200, 2225, 2250, 2275,
|
||||
2300, 2325, 2350, 2375, 2400, 2425, 2450, 2475,
|
||||
static const unsigned int tps6586x_ldo4_voltages[] = {
|
||||
1700000, 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000,
|
||||
1900000, 1925000, 1950000, 1975000, 2000000, 2025000, 2050000, 2075000,
|
||||
2100000, 2125000, 2150000, 2175000, 2200000, 2225000, 2250000, 2275000,
|
||||
2300000, 2325000, 2350000, 2375000, 2400000, 2425000, 2450000, 2475000,
|
||||
};
|
||||
|
||||
static int tps6586x_sm2_voltages[] = {
|
||||
3000, 3050, 3100, 3150, 3200, 3250, 3300, 3350,
|
||||
3400, 3450, 3500, 3550, 3600, 3650, 3700, 3750,
|
||||
3800, 3850, 3900, 3950, 4000, 4050, 4100, 4150,
|
||||
4200, 4250, 4300, 4350, 4400, 4450, 4500, 4550,
|
||||
static const unsigned int tps6586x_ldo_voltages[] = {
|
||||
1250000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
|
||||
};
|
||||
|
||||
static int tps6586x_dvm_voltages[] = {
|
||||
725, 750, 775, 800, 825, 850, 875, 900,
|
||||
925, 950, 975, 1000, 1025, 1050, 1075, 1100,
|
||||
1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300,
|
||||
1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500,
|
||||
static const unsigned int tps6586x_sm2_voltages[] = {
|
||||
3000000, 3050000, 3100000, 3150000, 3200000, 3250000, 3300000, 3350000,
|
||||
3400000, 3450000, 3500000, 3550000, 3600000, 3650000, 3700000, 3750000,
|
||||
3800000, 3850000, 3900000, 3950000, 4000000, 4050000, 4100000, 4150000,
|
||||
4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000,
|
||||
};
|
||||
|
||||
#define TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits, \
|
||||
static const unsigned int tps6586x_dvm_voltages[] = {
|
||||
725000, 750000, 775000, 800000, 825000, 850000, 875000, 900000,
|
||||
925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000,
|
||||
1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
|
||||
1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
|
||||
};
|
||||
|
||||
#define TPS6586X_REGULATOR(_id, _pin_name, vdata, vreg, shift, nbits, \
|
||||
ereg0, ebit0, ereg1, ebit1) \
|
||||
.desc = { \
|
||||
.supply_name = _pin_name, \
|
||||
.name = "REG-" #_id, \
|
||||
.ops = &tps6586x_regulator_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = TPS6586X_ID_##_id, \
|
||||
.n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages), \
|
||||
.volt_table = tps6586x_##vdata##_voltages, \
|
||||
.owner = THIS_MODULE, \
|
||||
}, \
|
||||
.volt_reg = TPS6586X_##vreg, \
|
||||
@@ -218,44 +209,45 @@ static int tps6586x_dvm_voltages[] = {
|
||||
.enable_reg[0] = TPS6586X_SUPPLY##ereg0, \
|
||||
.enable_bit[0] = (ebit0), \
|
||||
.enable_reg[1] = TPS6586X_SUPPLY##ereg1, \
|
||||
.enable_bit[1] = (ebit1), \
|
||||
.voltages = tps6586x_##vdata##_voltages,
|
||||
.enable_bit[1] = (ebit1),
|
||||
|
||||
#define TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \
|
||||
.go_reg = TPS6586X_##goreg, \
|
||||
.go_bit = (gobit),
|
||||
|
||||
#define TPS6586X_LDO(_id, vdata, vreg, shift, nbits, \
|
||||
#define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits, \
|
||||
ereg0, ebit0, ereg1, ebit1) \
|
||||
{ \
|
||||
TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits, \
|
||||
TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits, \
|
||||
ereg0, ebit0, ereg1, ebit1) \
|
||||
}
|
||||
|
||||
#define TPS6586X_DVM(_id, vdata, vreg, shift, nbits, \
|
||||
#define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits, \
|
||||
ereg0, ebit0, ereg1, ebit1, goreg, gobit) \
|
||||
{ \
|
||||
TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits, \
|
||||
TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits, \
|
||||
ereg0, ebit0, ereg1, ebit1) \
|
||||
TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \
|
||||
}
|
||||
|
||||
static struct tps6586x_regulator tps6586x_regulator[] = {
|
||||
TPS6586X_LDO(LDO_0, ldo, SUPPLYV1, 5, 3, ENC, 0, END, 0),
|
||||
TPS6586X_LDO(LDO_3, ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2),
|
||||
TPS6586X_LDO(LDO_5, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
|
||||
TPS6586X_LDO(LDO_6, ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4),
|
||||
TPS6586X_LDO(LDO_7, ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5),
|
||||
TPS6586X_LDO(LDO_8, ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6),
|
||||
TPS6586X_LDO(LDO_9, ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),
|
||||
TPS6586X_LDO(LDO_RTC, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
|
||||
TPS6586X_LDO(LDO_1, dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1),
|
||||
TPS6586X_LDO(SM_2, sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),
|
||||
TPS6586X_LDO(LDO_0, "vinldo01", ldo0, SUPPLYV1, 5, 3, ENC, 0, END, 0),
|
||||
TPS6586X_LDO(LDO_3, "vinldo23", ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2),
|
||||
TPS6586X_LDO(LDO_5, NULL, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
|
||||
TPS6586X_LDO(LDO_6, "vinldo678", ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4),
|
||||
TPS6586X_LDO(LDO_7, "vinldo678", ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5),
|
||||
TPS6586X_LDO(LDO_8, "vinldo678", ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6),
|
||||
TPS6586X_LDO(LDO_9, "vinldo9", ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),
|
||||
TPS6586X_LDO(LDO_RTC, NULL, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
|
||||
TPS6586X_LDO(LDO_1, "vinldo01", dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1),
|
||||
TPS6586X_LDO(SM_2, "sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),
|
||||
|
||||
TPS6586X_DVM(LDO_2, dvm, LDO2BV1, 0, 5, ENA, 3, ENB, 3, VCC2, 6),
|
||||
TPS6586X_DVM(LDO_4, ldo4, LDO4V1, 0, 5, ENC, 3, END, 3, VCC1, 6),
|
||||
TPS6586X_DVM(SM_0, dvm, SM0V1, 0, 5, ENA, 1, ENB, 1, VCC1, 2),
|
||||
TPS6586X_DVM(SM_1, dvm, SM1V1, 0, 5, ENA, 0, ENB, 0, VCC1, 0),
|
||||
TPS6586X_DVM(LDO_2, "vinldo23", dvm, LDO2BV1, 0, 5, ENA, 3,
|
||||
ENB, 3, VCC2, 6),
|
||||
TPS6586X_DVM(LDO_4, "vinldo4", ldo4, LDO4V1, 0, 5, ENC, 3,
|
||||
END, 3, VCC1, 6),
|
||||
TPS6586X_DVM(SM_0, "sm0", dvm, SM0V1, 0, 5, ENA, 1, ENB, 1, VCC1, 2),
|
||||
TPS6586X_DVM(SM_1, "sm1", dvm, SM1V1, 0, 5, ENA, 0, ENB, 0, VCC1, 0),
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -362,7 +354,7 @@ static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
config.dev = &pdev->dev;
|
||||
config.dev = pdev->dev.parent;
|
||||
config.of_node = pdev->dev.of_node;
|
||||
config.init_data = pdev->dev.platform_data;
|
||||
config.driver_data = ri;
|
||||
|
||||
@@ -31,160 +31,147 @@
|
||||
TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3 | \
|
||||
TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP)
|
||||
|
||||
/* supported VIO voltages in millivolts */
|
||||
static const u16 VIO_VSEL_table[] = {
|
||||
1500, 1800, 2500, 3300,
|
||||
/* supported VIO voltages in microvolts */
|
||||
static const unsigned int VIO_VSEL_table[] = {
|
||||
1500000, 1800000, 2500000, 3300000,
|
||||
};
|
||||
|
||||
/* VSEL tables for TPS65910 specific LDOs and dcdc's */
|
||||
|
||||
/* supported VDD3 voltages in millivolts */
|
||||
static const u16 VDD3_VSEL_table[] = {
|
||||
5000,
|
||||
/* supported VDD3 voltages in microvolts */
|
||||
static const unsigned int VDD3_VSEL_table[] = {
|
||||
5000000,
|
||||
};
|
||||
|
||||
/* supported VDIG1 voltages in millivolts */
|
||||
static const u16 VDIG1_VSEL_table[] = {
|
||||
1200, 1500, 1800, 2700,
|
||||
/* supported VDIG1 voltages in microvolts */
|
||||
static const unsigned int VDIG1_VSEL_table[] = {
|
||||
1200000, 1500000, 1800000, 2700000,
|
||||
};
|
||||
|
||||
/* supported VDIG2 voltages in millivolts */
|
||||
static const u16 VDIG2_VSEL_table[] = {
|
||||
1000, 1100, 1200, 1800,
|
||||
/* supported VDIG2 voltages in microvolts */
|
||||
static const unsigned int VDIG2_VSEL_table[] = {
|
||||
1000000, 1100000, 1200000, 1800000,
|
||||
};
|
||||
|
||||
/* supported VPLL voltages in millivolts */
|
||||
static const u16 VPLL_VSEL_table[] = {
|
||||
1000, 1100, 1800, 2500,
|
||||
/* supported VPLL voltages in microvolts */
|
||||
static const unsigned int VPLL_VSEL_table[] = {
|
||||
1000000, 1100000, 1800000, 2500000,
|
||||
};
|
||||
|
||||
/* supported VDAC voltages in millivolts */
|
||||
static const u16 VDAC_VSEL_table[] = {
|
||||
1800, 2600, 2800, 2850,
|
||||
/* supported VDAC voltages in microvolts */
|
||||
static const unsigned int VDAC_VSEL_table[] = {
|
||||
1800000, 2600000, 2800000, 2850000,
|
||||
};
|
||||
|
||||
/* supported VAUX1 voltages in millivolts */
|
||||
static const u16 VAUX1_VSEL_table[] = {
|
||||
1800, 2500, 2800, 2850,
|
||||
/* supported VAUX1 voltages in microvolts */
|
||||
static const unsigned int VAUX1_VSEL_table[] = {
|
||||
1800000, 2500000, 2800000, 2850000,
|
||||
};
|
||||
|
||||
/* supported VAUX2 voltages in millivolts */
|
||||
static const u16 VAUX2_VSEL_table[] = {
|
||||
1800, 2800, 2900, 3300,
|
||||
/* supported VAUX2 voltages in microvolts */
|
||||
static const unsigned int VAUX2_VSEL_table[] = {
|
||||
1800000, 2800000, 2900000, 3300000,
|
||||
};
|
||||
|
||||
/* supported VAUX33 voltages in millivolts */
|
||||
static const u16 VAUX33_VSEL_table[] = {
|
||||
1800, 2000, 2800, 3300,
|
||||
/* supported VAUX33 voltages in microvolts */
|
||||
static const unsigned int VAUX33_VSEL_table[] = {
|
||||
1800000, 2000000, 2800000, 3300000,
|
||||
};
|
||||
|
||||
/* supported VMMC voltages in millivolts */
|
||||
static const u16 VMMC_VSEL_table[] = {
|
||||
1800, 2800, 3000, 3300,
|
||||
/* supported VMMC voltages in microvolts */
|
||||
static const unsigned int VMMC_VSEL_table[] = {
|
||||
1800000, 2800000, 3000000, 3300000,
|
||||
};
|
||||
|
||||
struct tps_info {
|
||||
const char *name;
|
||||
unsigned min_uV;
|
||||
unsigned max_uV;
|
||||
const char *vin_name;
|
||||
u8 n_voltages;
|
||||
const u16 *voltage_table;
|
||||
const unsigned int *voltage_table;
|
||||
int enable_time_us;
|
||||
};
|
||||
|
||||
static struct tps_info tps65910_regs[] = {
|
||||
{
|
||||
.name = "vrtc",
|
||||
.vin_name = "vcc7",
|
||||
.enable_time_us = 2200,
|
||||
},
|
||||
{
|
||||
.name = "vio",
|
||||
.min_uV = 1500000,
|
||||
.max_uV = 3300000,
|
||||
.vin_name = "vccio",
|
||||
.n_voltages = ARRAY_SIZE(VIO_VSEL_table),
|
||||
.voltage_table = VIO_VSEL_table,
|
||||
.enable_time_us = 350,
|
||||
},
|
||||
{
|
||||
.name = "vdd1",
|
||||
.min_uV = 600000,
|
||||
.max_uV = 4500000,
|
||||
.vin_name = "vcc1",
|
||||
.enable_time_us = 350,
|
||||
},
|
||||
{
|
||||
.name = "vdd2",
|
||||
.min_uV = 600000,
|
||||
.max_uV = 4500000,
|
||||
.vin_name = "vcc2",
|
||||
.enable_time_us = 350,
|
||||
},
|
||||
{
|
||||
.name = "vdd3",
|
||||
.min_uV = 5000000,
|
||||
.max_uV = 5000000,
|
||||
.n_voltages = ARRAY_SIZE(VDD3_VSEL_table),
|
||||
.voltage_table = VDD3_VSEL_table,
|
||||
.enable_time_us = 200,
|
||||
},
|
||||
{
|
||||
.name = "vdig1",
|
||||
.min_uV = 1200000,
|
||||
.max_uV = 2700000,
|
||||
.vin_name = "vcc6",
|
||||
.n_voltages = ARRAY_SIZE(VDIG1_VSEL_table),
|
||||
.voltage_table = VDIG1_VSEL_table,
|
||||
.enable_time_us = 100,
|
||||
},
|
||||
{
|
||||
.name = "vdig2",
|
||||
.min_uV = 1000000,
|
||||
.max_uV = 1800000,
|
||||
.vin_name = "vcc6",
|
||||
.n_voltages = ARRAY_SIZE(VDIG2_VSEL_table),
|
||||
.voltage_table = VDIG2_VSEL_table,
|
||||
.enable_time_us = 100,
|
||||
},
|
||||
{
|
||||
.name = "vpll",
|
||||
.min_uV = 1000000,
|
||||
.max_uV = 2500000,
|
||||
.vin_name = "vcc5",
|
||||
.n_voltages = ARRAY_SIZE(VPLL_VSEL_table),
|
||||
.voltage_table = VPLL_VSEL_table,
|
||||
.enable_time_us = 100,
|
||||
},
|
||||
{
|
||||
.name = "vdac",
|
||||
.min_uV = 1800000,
|
||||
.max_uV = 2850000,
|
||||
.vin_name = "vcc5",
|
||||
.n_voltages = ARRAY_SIZE(VDAC_VSEL_table),
|
||||
.voltage_table = VDAC_VSEL_table,
|
||||
.enable_time_us = 100,
|
||||
},
|
||||
{
|
||||
.name = "vaux1",
|
||||
.min_uV = 1800000,
|
||||
.max_uV = 2850000,
|
||||
.vin_name = "vcc4",
|
||||
.n_voltages = ARRAY_SIZE(VAUX1_VSEL_table),
|
||||
.voltage_table = VAUX1_VSEL_table,
|
||||
.enable_time_us = 100,
|
||||
},
|
||||
{
|
||||
.name = "vaux2",
|
||||
.min_uV = 1800000,
|
||||
.max_uV = 3300000,
|
||||
.vin_name = "vcc4",
|
||||
.n_voltages = ARRAY_SIZE(VAUX2_VSEL_table),
|
||||
.voltage_table = VAUX2_VSEL_table,
|
||||
.enable_time_us = 100,
|
||||
},
|
||||
{
|
||||
.name = "vaux33",
|
||||
.min_uV = 1800000,
|
||||
.max_uV = 3300000,
|
||||
.vin_name = "vcc3",
|
||||
.n_voltages = ARRAY_SIZE(VAUX33_VSEL_table),
|
||||
.voltage_table = VAUX33_VSEL_table,
|
||||
.enable_time_us = 100,
|
||||
},
|
||||
{
|
||||
.name = "vmmc",
|
||||
.min_uV = 1800000,
|
||||
.max_uV = 3300000,
|
||||
.vin_name = "vcc3",
|
||||
.n_voltages = ARRAY_SIZE(VMMC_VSEL_table),
|
||||
.voltage_table = VMMC_VSEL_table,
|
||||
.enable_time_us = 100,
|
||||
@@ -194,91 +181,79 @@ static struct tps_info tps65910_regs[] = {
|
||||
static struct tps_info tps65911_regs[] = {
|
||||
{
|
||||
.name = "vrtc",
|
||||
.vin_name = "vcc7",
|
||||
.enable_time_us = 2200,
|
||||
},
|
||||
{
|
||||
.name = "vio",
|
||||
.min_uV = 1500000,
|
||||
.max_uV = 3300000,
|
||||
.vin_name = "vccio",
|
||||
.n_voltages = ARRAY_SIZE(VIO_VSEL_table),
|
||||
.voltage_table = VIO_VSEL_table,
|
||||
.enable_time_us = 350,
|
||||
},
|
||||
{
|
||||
.name = "vdd1",
|
||||
.min_uV = 600000,
|
||||
.max_uV = 4500000,
|
||||
.n_voltages = 73,
|
||||
.vin_name = "vcc1",
|
||||
.n_voltages = 0x4C,
|
||||
.enable_time_us = 350,
|
||||
},
|
||||
{
|
||||
.name = "vdd2",
|
||||
.min_uV = 600000,
|
||||
.max_uV = 4500000,
|
||||
.n_voltages = 73,
|
||||
.vin_name = "vcc2",
|
||||
.n_voltages = 0x4C,
|
||||
.enable_time_us = 350,
|
||||
},
|
||||
{
|
||||
.name = "vddctrl",
|
||||
.min_uV = 600000,
|
||||
.max_uV = 1400000,
|
||||
.n_voltages = 65,
|
||||
.n_voltages = 0x44,
|
||||
.enable_time_us = 900,
|
||||
},
|
||||
{
|
||||
.name = "ldo1",
|
||||
.min_uV = 1000000,
|
||||
.max_uV = 3300000,
|
||||
.n_voltages = 47,
|
||||
.vin_name = "vcc6",
|
||||
.n_voltages = 0x33,
|
||||
.enable_time_us = 420,
|
||||
},
|
||||
{
|
||||
.name = "ldo2",
|
||||
.min_uV = 1000000,
|
||||
.max_uV = 3300000,
|
||||
.n_voltages = 47,
|
||||
.vin_name = "vcc6",
|
||||
.n_voltages = 0x33,
|
||||
.enable_time_us = 420,
|
||||
},
|
||||
{
|
||||
.name = "ldo3",
|
||||
.min_uV = 1000000,
|
||||
.max_uV = 3300000,
|
||||
.n_voltages = 24,
|
||||
.vin_name = "vcc5",
|
||||
.n_voltages = 0x1A,
|
||||
.enable_time_us = 230,
|
||||
},
|
||||
{
|
||||
.name = "ldo4",
|
||||
.min_uV = 1000000,
|
||||
.max_uV = 3300000,
|
||||
.n_voltages = 47,
|
||||
.vin_name = "vcc5",
|
||||
.n_voltages = 0x33,
|
||||
.enable_time_us = 230,
|
||||
},
|
||||
{
|
||||
.name = "ldo5",
|
||||
.min_uV = 1000000,
|
||||
.max_uV = 3300000,
|
||||
.n_voltages = 24,
|
||||
.vin_name = "vcc4",
|
||||
.n_voltages = 0x1A,
|
||||
.enable_time_us = 230,
|
||||
},
|
||||
{
|
||||
.name = "ldo6",
|
||||
.min_uV = 1000000,
|
||||
.max_uV = 3300000,
|
||||
.n_voltages = 24,
|
||||
.vin_name = "vcc3",
|
||||
.n_voltages = 0x1A,
|
||||
.enable_time_us = 230,
|
||||
},
|
||||
{
|
||||
.name = "ldo7",
|
||||
.min_uV = 1000000,
|
||||
.max_uV = 3300000,
|
||||
.n_voltages = 24,
|
||||
.vin_name = "vcc3",
|
||||
.n_voltages = 0x1A,
|
||||
.enable_time_us = 230,
|
||||
},
|
||||
{
|
||||
.name = "ldo8",
|
||||
.min_uV = 1000000,
|
||||
.max_uV = 3300000,
|
||||
.n_voltages = 24,
|
||||
.vin_name = "vcc3",
|
||||
.n_voltages = 0x1A,
|
||||
.enable_time_us = 230,
|
||||
},
|
||||
};
|
||||
@@ -321,7 +296,6 @@ struct tps65910_reg {
|
||||
struct tps65910 *mfd;
|
||||
struct regulator_dev **rdev;
|
||||
struct tps_info **info;
|
||||
struct mutex mutex;
|
||||
int num_regulators;
|
||||
int mode;
|
||||
int (*get_ctrl_reg)(int);
|
||||
@@ -329,71 +303,6 @@ struct tps65910_reg {
|
||||
unsigned int board_ext_control[TPS65910_NUM_REGS];
|
||||
};
|
||||
|
||||
static inline int tps65910_read(struct tps65910_reg *pmic, u8 reg)
|
||||
{
|
||||
unsigned int val;
|
||||
int err;
|
||||
|
||||
err = tps65910_reg_read(pmic->mfd, reg, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int tps65910_modify_bits(struct tps65910_reg *pmic, u8 reg,
|
||||
u8 set_mask, u8 clear_mask)
|
||||
{
|
||||
int err, data;
|
||||
|
||||
mutex_lock(&pmic->mutex);
|
||||
|
||||
data = tps65910_read(pmic, reg);
|
||||
if (data < 0) {
|
||||
dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg);
|
||||
err = data;
|
||||
goto out;
|
||||
}
|
||||
|
||||
data &= ~clear_mask;
|
||||
data |= set_mask;
|
||||
err = tps65910_reg_write(pmic->mfd, reg, data);
|
||||
if (err)
|
||||
dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg);
|
||||
|
||||
out:
|
||||
mutex_unlock(&pmic->mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tps65910_reg_read_locked(struct tps65910_reg *pmic, u8 reg)
|
||||
{
|
||||
int data;
|
||||
|
||||
mutex_lock(&pmic->mutex);
|
||||
|
||||
data = tps65910_read(pmic, reg);
|
||||
if (data < 0)
|
||||
dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg);
|
||||
|
||||
mutex_unlock(&pmic->mutex);
|
||||
return data;
|
||||
}
|
||||
|
||||
static int tps65910_reg_write_locked(struct tps65910_reg *pmic, u8 reg, u8 val)
|
||||
{
|
||||
int err;
|
||||
|
||||
mutex_lock(&pmic->mutex);
|
||||
|
||||
err = tps65910_reg_write(pmic->mfd, reg, val);
|
||||
if (err < 0)
|
||||
dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg);
|
||||
|
||||
mutex_unlock(&pmic->mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tps65910_get_ctrl_register(int id)
|
||||
{
|
||||
switch (id) {
|
||||
@@ -462,13 +371,6 @@ static int tps65911_get_ctrl_register(int id)
|
||||
}
|
||||
}
|
||||
|
||||
static int tps65910_enable_time(struct regulator_dev *dev)
|
||||
{
|
||||
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
|
||||
int id = rdev_get_id(dev);
|
||||
return pmic->info[id]->enable_time_us;
|
||||
}
|
||||
|
||||
static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode)
|
||||
{
|
||||
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
|
||||
@@ -481,8 +383,9 @@ static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode)
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
return tps65910_modify_bits(pmic, reg, LDO_ST_ON_BIT,
|
||||
LDO_ST_MODE_BIT);
|
||||
return tps65910_reg_update_bits(pmic->mfd, reg,
|
||||
LDO_ST_MODE_BIT | LDO_ST_ON_BIT,
|
||||
LDO_ST_ON_BIT);
|
||||
case REGULATOR_MODE_IDLE:
|
||||
value = LDO_ST_ON_BIT | LDO_ST_MODE_BIT;
|
||||
return tps65910_reg_set_bits(mfd, reg, value);
|
||||
@@ -496,15 +399,15 @@ static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode)
|
||||
static unsigned int tps65910_get_mode(struct regulator_dev *dev)
|
||||
{
|
||||
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
|
||||
int reg, value, id = rdev_get_id(dev);
|
||||
int ret, reg, value, id = rdev_get_id(dev);
|
||||
|
||||
reg = pmic->get_ctrl_reg(id);
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
|
||||
value = tps65910_reg_read_locked(pmic, reg);
|
||||
if (value < 0)
|
||||
return value;
|
||||
ret = tps65910_reg_read(pmic->mfd, reg, &value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!(value & LDO_ST_ON_BIT))
|
||||
return REGULATOR_MODE_STANDBY;
|
||||
@@ -517,33 +420,51 @@ static unsigned int tps65910_get_mode(struct regulator_dev *dev)
|
||||
static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev)
|
||||
{
|
||||
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
|
||||
int id = rdev_get_id(dev);
|
||||
int ret, id = rdev_get_id(dev);
|
||||
int opvsel = 0, srvsel = 0, vselmax = 0, mult = 0, sr = 0;
|
||||
|
||||
switch (id) {
|
||||
case TPS65910_REG_VDD1:
|
||||
opvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD1_OP);
|
||||
mult = tps65910_reg_read_locked(pmic, TPS65910_VDD1);
|
||||
ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1_OP, &opvsel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1, &mult);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
mult = (mult & VDD1_VGAIN_SEL_MASK) >> VDD1_VGAIN_SEL_SHIFT;
|
||||
srvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD1_SR);
|
||||
ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1_SR, &srvsel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
sr = opvsel & VDD1_OP_CMD_MASK;
|
||||
opvsel &= VDD1_OP_SEL_MASK;
|
||||
srvsel &= VDD1_SR_SEL_MASK;
|
||||
vselmax = 75;
|
||||
break;
|
||||
case TPS65910_REG_VDD2:
|
||||
opvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD2_OP);
|
||||
mult = tps65910_reg_read_locked(pmic, TPS65910_VDD2);
|
||||
ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2_OP, &opvsel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2, &mult);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
mult = (mult & VDD2_VGAIN_SEL_MASK) >> VDD2_VGAIN_SEL_SHIFT;
|
||||
srvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD2_SR);
|
||||
ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2_SR, &srvsel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
sr = opvsel & VDD2_OP_CMD_MASK;
|
||||
opvsel &= VDD2_OP_SEL_MASK;
|
||||
srvsel &= VDD2_SR_SEL_MASK;
|
||||
vselmax = 75;
|
||||
break;
|
||||
case TPS65911_REG_VDDCTRL:
|
||||
opvsel = tps65910_reg_read_locked(pmic, TPS65911_VDDCTRL_OP);
|
||||
srvsel = tps65910_reg_read_locked(pmic, TPS65911_VDDCTRL_SR);
|
||||
ret = tps65910_reg_read(pmic->mfd, TPS65911_VDDCTRL_OP,
|
||||
&opvsel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = tps65910_reg_read(pmic->mfd, TPS65911_VDDCTRL_SR,
|
||||
&srvsel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
sr = opvsel & VDDCTRL_OP_CMD_MASK;
|
||||
opvsel &= VDDCTRL_OP_SEL_MASK;
|
||||
srvsel &= VDDCTRL_SR_SEL_MASK;
|
||||
@@ -577,15 +498,15 @@ static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev)
|
||||
static int tps65910_get_voltage_sel(struct regulator_dev *dev)
|
||||
{
|
||||
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
|
||||
int reg, value, id = rdev_get_id(dev);
|
||||
int ret, reg, value, id = rdev_get_id(dev);
|
||||
|
||||
reg = pmic->get_ctrl_reg(id);
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
|
||||
value = tps65910_reg_read_locked(pmic, reg);
|
||||
if (value < 0)
|
||||
return value;
|
||||
ret = tps65910_reg_read(pmic->mfd, reg, &value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (id) {
|
||||
case TPS65910_REG_VIO:
|
||||
@@ -609,18 +530,20 @@ static int tps65910_get_voltage_sel(struct regulator_dev *dev)
|
||||
|
||||
static int tps65910_get_voltage_vdd3(struct regulator_dev *dev)
|
||||
{
|
||||
return 5 * 1000 * 1000;
|
||||
return dev->desc->volt_table[0];
|
||||
}
|
||||
|
||||
static int tps65911_get_voltage_sel(struct regulator_dev *dev)
|
||||
{
|
||||
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
|
||||
int id = rdev_get_id(dev);
|
||||
u8 value, reg;
|
||||
int ret, id = rdev_get_id(dev);
|
||||
unsigned int value, reg;
|
||||
|
||||
reg = pmic->get_ctrl_reg(id);
|
||||
|
||||
value = tps65910_reg_read_locked(pmic, reg);
|
||||
ret = tps65910_reg_read(pmic->mfd, reg, &value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (id) {
|
||||
case TPS65911_REG_LDO1:
|
||||
@@ -662,10 +585,10 @@ static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev,
|
||||
dcdc_mult--;
|
||||
vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3;
|
||||
|
||||
tps65910_modify_bits(pmic, TPS65910_VDD1,
|
||||
(dcdc_mult << VDD1_VGAIN_SEL_SHIFT),
|
||||
VDD1_VGAIN_SEL_MASK);
|
||||
tps65910_reg_write_locked(pmic, TPS65910_VDD1_OP, vsel);
|
||||
tps65910_reg_update_bits(pmic->mfd, TPS65910_VDD1,
|
||||
VDD1_VGAIN_SEL_MASK,
|
||||
dcdc_mult << VDD1_VGAIN_SEL_SHIFT);
|
||||
tps65910_reg_write(pmic->mfd, TPS65910_VDD1_OP, vsel);
|
||||
break;
|
||||
case TPS65910_REG_VDD2:
|
||||
dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;
|
||||
@@ -673,14 +596,14 @@ static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev,
|
||||
dcdc_mult--;
|
||||
vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3;
|
||||
|
||||
tps65910_modify_bits(pmic, TPS65910_VDD2,
|
||||
(dcdc_mult << VDD2_VGAIN_SEL_SHIFT),
|
||||
VDD1_VGAIN_SEL_MASK);
|
||||
tps65910_reg_write_locked(pmic, TPS65910_VDD2_OP, vsel);
|
||||
tps65910_reg_update_bits(pmic->mfd, TPS65910_VDD2,
|
||||
VDD1_VGAIN_SEL_MASK,
|
||||
dcdc_mult << VDD2_VGAIN_SEL_SHIFT);
|
||||
tps65910_reg_write(pmic->mfd, TPS65910_VDD2_OP, vsel);
|
||||
break;
|
||||
case TPS65911_REG_VDDCTRL:
|
||||
vsel = selector + 3;
|
||||
tps65910_reg_write_locked(pmic, TPS65911_VDDCTRL_OP, vsel);
|
||||
tps65910_reg_write(pmic->mfd, TPS65911_VDDCTRL_OP, vsel);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -706,8 +629,8 @@ static int tps65910_set_voltage_sel(struct regulator_dev *dev,
|
||||
case TPS65910_REG_VAUX2:
|
||||
case TPS65910_REG_VAUX33:
|
||||
case TPS65910_REG_VMMC:
|
||||
return tps65910_modify_bits(pmic, reg,
|
||||
(selector << LDO_SEL_SHIFT), LDO_SEL_MASK);
|
||||
return tps65910_reg_update_bits(pmic->mfd, reg, LDO_SEL_MASK,
|
||||
selector << LDO_SEL_SHIFT);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
@@ -727,18 +650,18 @@ static int tps65911_set_voltage_sel(struct regulator_dev *dev,
|
||||
case TPS65911_REG_LDO1:
|
||||
case TPS65911_REG_LDO2:
|
||||
case TPS65911_REG_LDO4:
|
||||
return tps65910_modify_bits(pmic, reg,
|
||||
(selector << LDO_SEL_SHIFT), LDO1_SEL_MASK);
|
||||
return tps65910_reg_update_bits(pmic->mfd, reg, LDO1_SEL_MASK,
|
||||
selector << LDO_SEL_SHIFT);
|
||||
case TPS65911_REG_LDO3:
|
||||
case TPS65911_REG_LDO5:
|
||||
case TPS65911_REG_LDO6:
|
||||
case TPS65911_REG_LDO7:
|
||||
case TPS65911_REG_LDO8:
|
||||
return tps65910_modify_bits(pmic, reg,
|
||||
(selector << LDO_SEL_SHIFT), LDO3_SEL_MASK);
|
||||
return tps65910_reg_update_bits(pmic->mfd, reg, LDO3_SEL_MASK,
|
||||
selector << LDO_SEL_SHIFT);
|
||||
case TPS65910_REG_VIO:
|
||||
return tps65910_modify_bits(pmic, reg,
|
||||
(selector << LDO_SEL_SHIFT), LDO_SEL_MASK);
|
||||
return tps65910_reg_update_bits(pmic->mfd, reg, LDO_SEL_MASK,
|
||||
selector << LDO_SEL_SHIFT);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
@@ -768,23 +691,6 @@ static int tps65910_list_voltage_dcdc(struct regulator_dev *dev,
|
||||
return volt * 100 * mult;
|
||||
}
|
||||
|
||||
static int tps65910_list_voltage(struct regulator_dev *dev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
|
||||
int id = rdev_get_id(dev), voltage;
|
||||
|
||||
if (id < TPS65910_REG_VIO || id > TPS65910_REG_VMMC)
|
||||
return -EINVAL;
|
||||
|
||||
if (selector >= pmic->info[id]->n_voltages)
|
||||
return -EINVAL;
|
||||
else
|
||||
voltage = pmic->info[id]->voltage_table[selector] * 1000;
|
||||
|
||||
return voltage;
|
||||
}
|
||||
|
||||
static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector)
|
||||
{
|
||||
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
|
||||
@@ -816,7 +722,7 @@ static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector)
|
||||
step_mv = 100;
|
||||
break;
|
||||
case TPS65910_REG_VIO:
|
||||
return pmic->info[id]->voltage_table[selector] * 1000;
|
||||
return pmic->info[id]->voltage_table[selector];
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -824,42 +730,16 @@ static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector)
|
||||
return (LDO_MIN_VOLT + selector * step_mv) * 1000;
|
||||
}
|
||||
|
||||
static int tps65910_set_voltage_dcdc_time_sel(struct regulator_dev *dev,
|
||||
unsigned int old_selector, unsigned int new_selector)
|
||||
{
|
||||
int id = rdev_get_id(dev);
|
||||
int old_volt, new_volt;
|
||||
|
||||
old_volt = tps65910_list_voltage_dcdc(dev, old_selector);
|
||||
if (old_volt < 0)
|
||||
return old_volt;
|
||||
|
||||
new_volt = tps65910_list_voltage_dcdc(dev, new_selector);
|
||||
if (new_volt < 0)
|
||||
return new_volt;
|
||||
|
||||
/* VDD1 and VDD2 are 12.5mV/us, VDDCTRL is 100mV/20us */
|
||||
switch (id) {
|
||||
case TPS65910_REG_VDD1:
|
||||
case TPS65910_REG_VDD2:
|
||||
return DIV_ROUND_UP(abs(old_volt - new_volt), 12500);
|
||||
case TPS65911_REG_VDDCTRL:
|
||||
return DIV_ROUND_UP(abs(old_volt - new_volt), 5000);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Regulator ops (except VRTC) */
|
||||
static struct regulator_ops tps65910_ops_dcdc = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.enable_time = tps65910_enable_time,
|
||||
.set_mode = tps65910_set_mode,
|
||||
.get_mode = tps65910_get_mode,
|
||||
.get_voltage_sel = tps65910_get_voltage_dcdc_sel,
|
||||
.set_voltage_sel = tps65910_set_voltage_dcdc_sel,
|
||||
.set_voltage_time_sel = tps65910_set_voltage_dcdc_time_sel,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.list_voltage = tps65910_list_voltage_dcdc,
|
||||
};
|
||||
|
||||
@@ -867,30 +747,27 @@ static struct regulator_ops tps65910_ops_vdd3 = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.enable_time = tps65910_enable_time,
|
||||
.set_mode = tps65910_set_mode,
|
||||
.get_mode = tps65910_get_mode,
|
||||
.get_voltage = tps65910_get_voltage_vdd3,
|
||||
.list_voltage = tps65910_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
};
|
||||
|
||||
static struct regulator_ops tps65910_ops = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.enable_time = tps65910_enable_time,
|
||||
.set_mode = tps65910_set_mode,
|
||||
.get_mode = tps65910_get_mode,
|
||||
.get_voltage_sel = tps65910_get_voltage_sel,
|
||||
.set_voltage_sel = tps65910_set_voltage_sel,
|
||||
.list_voltage = tps65910_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
};
|
||||
|
||||
static struct regulator_ops tps65911_ops = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.enable_time = tps65910_enable_time,
|
||||
.set_mode = tps65910_set_mode,
|
||||
.get_mode = tps65910_get_mode,
|
||||
.get_voltage_sel = tps65911_get_voltage_sel,
|
||||
@@ -996,19 +873,27 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic,
|
||||
(tps65910_chip_id(mfd) == TPS65911))) {
|
||||
int op_reg_add = pmic->get_ctrl_reg(id) + 1;
|
||||
int sr_reg_add = pmic->get_ctrl_reg(id) + 2;
|
||||
int opvsel = tps65910_reg_read_locked(pmic, op_reg_add);
|
||||
int srvsel = tps65910_reg_read_locked(pmic, sr_reg_add);
|
||||
int opvsel, srvsel;
|
||||
|
||||
ret = tps65910_reg_read(pmic->mfd, op_reg_add, &opvsel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = tps65910_reg_read(pmic->mfd, sr_reg_add, &srvsel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (opvsel & VDD1_OP_CMD_MASK) {
|
||||
u8 reg_val = srvsel & VDD1_OP_SEL_MASK;
|
||||
ret = tps65910_reg_write_locked(pmic, op_reg_add,
|
||||
reg_val);
|
||||
|
||||
ret = tps65910_reg_write(pmic->mfd, op_reg_add,
|
||||
reg_val);
|
||||
if (ret < 0) {
|
||||
dev_err(mfd->dev,
|
||||
"Error in configuring op register\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret = tps65910_reg_write_locked(pmic, sr_reg_add, 0);
|
||||
ret = tps65910_reg_write(pmic->mfd, sr_reg_add, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(mfd->dev, "Error in settting sr register\n");
|
||||
return ret;
|
||||
@@ -1126,6 +1011,7 @@ static struct tps65910_board *tps65910_parse_dt_reg_data(
|
||||
"ti,regulator-ext-sleep-control", &prop);
|
||||
if (!ret)
|
||||
pmic_plat_data->regulator_ext_sleep_control[idx] = prop;
|
||||
|
||||
}
|
||||
|
||||
return pmic_plat_data;
|
||||
@@ -1136,7 +1022,7 @@ static inline struct tps65910_board *tps65910_parse_dt_reg_data(
|
||||
struct of_regulator_match **tps65910_reg_matches)
|
||||
{
|
||||
*tps65910_reg_matches = NULL;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1168,7 +1054,6 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mutex_init(&pmic->mutex);
|
||||
pmic->mfd = tps65910;
|
||||
platform_set_drvdata(pdev, pmic);
|
||||
|
||||
@@ -1229,23 +1114,31 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
|
||||
pmic->info[i] = info;
|
||||
|
||||
pmic->desc[i].name = info->name;
|
||||
pmic->desc[i].supply_name = info->vin_name;
|
||||
pmic->desc[i].id = i;
|
||||
pmic->desc[i].n_voltages = info->n_voltages;
|
||||
pmic->desc[i].enable_time = info->enable_time_us;
|
||||
|
||||
if (i == TPS65910_REG_VDD1 || i == TPS65910_REG_VDD2) {
|
||||
pmic->desc[i].ops = &tps65910_ops_dcdc;
|
||||
pmic->desc[i].n_voltages = VDD1_2_NUM_VOLT_FINE *
|
||||
VDD1_2_NUM_VOLT_COARSE;
|
||||
pmic->desc[i].ramp_delay = 12500;
|
||||
} else if (i == TPS65910_REG_VDD3) {
|
||||
if (tps65910_chip_id(tps65910) == TPS65910)
|
||||
if (tps65910_chip_id(tps65910) == TPS65910) {
|
||||
pmic->desc[i].ops = &tps65910_ops_vdd3;
|
||||
else
|
||||
pmic->desc[i].volt_table = info->voltage_table;
|
||||
} else {
|
||||
pmic->desc[i].ops = &tps65910_ops_dcdc;
|
||||
pmic->desc[i].ramp_delay = 5000;
|
||||
}
|
||||
} else {
|
||||
if (tps65910_chip_id(tps65910) == TPS65910)
|
||||
if (tps65910_chip_id(tps65910) == TPS65910) {
|
||||
pmic->desc[i].ops = &tps65910_ops;
|
||||
else
|
||||
pmic->desc[i].volt_table = info->voltage_table;
|
||||
} else {
|
||||
pmic->desc[i].ops = &tps65911_ops;
|
||||
}
|
||||
}
|
||||
|
||||
err = tps65910_set_ext_sleep_config(pmic, i,
|
||||
|
||||
@@ -43,9 +43,6 @@ struct twlreg_info {
|
||||
u8 table_len;
|
||||
const u16 *table;
|
||||
|
||||
/* regulator specific turn-on delay */
|
||||
u16 delay;
|
||||
|
||||
/* State REMAP default configuration */
|
||||
u8 remap;
|
||||
|
||||
@@ -223,20 +220,6 @@ static int twl6030reg_enable(struct regulator_dev *rdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int twl4030reg_enable_time(struct regulator_dev *rdev)
|
||||
{
|
||||
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
return info->delay;
|
||||
}
|
||||
|
||||
static int twl6030reg_enable_time(struct regulator_dev *rdev)
|
||||
{
|
||||
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
return info->delay;
|
||||
}
|
||||
|
||||
static int twl4030reg_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||
@@ -508,7 +491,6 @@ static struct regulator_ops twl4030ldo_ops = {
|
||||
.enable = twl4030reg_enable,
|
||||
.disable = twl4030reg_disable,
|
||||
.is_enabled = twl4030reg_is_enabled,
|
||||
.enable_time = twl4030reg_enable_time,
|
||||
|
||||
.set_mode = twl4030reg_set_mode,
|
||||
|
||||
@@ -577,59 +559,53 @@ static struct regulator_ops twl6030coresmps_ops = {
|
||||
.get_voltage = twl6030coresmps_get_voltage,
|
||||
};
|
||||
|
||||
static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
|
||||
static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned sel)
|
||||
{
|
||||
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
return ((info->min_mV + (index * 100)) * 1000);
|
||||
switch (sel) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1 ... 24:
|
||||
/* Linear mapping from 00000001 to 00011000:
|
||||
* Absolute voltage value = 1.0 V + 0.1 V × (sel – 00000001)
|
||||
*/
|
||||
return (info->min_mV + 100 * (sel - 1)) * 1000;
|
||||
case 25 ... 30:
|
||||
return -EINVAL;
|
||||
case 31:
|
||||
return 2750000;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
twl6030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
|
||||
unsigned *selector)
|
||||
twl6030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
|
||||
{
|
||||
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||
int vsel;
|
||||
|
||||
if ((min_uV/1000 < info->min_mV) || (max_uV/1000 > info->max_mV))
|
||||
return -EDOM;
|
||||
|
||||
/*
|
||||
* Use the below formula to calculate vsel
|
||||
* mV = 1000mv + 100mv * (vsel - 1)
|
||||
*/
|
||||
vsel = (min_uV/1000 - 1000)/100 + 1;
|
||||
*selector = vsel;
|
||||
return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, vsel);
|
||||
|
||||
return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE,
|
||||
selector);
|
||||
}
|
||||
|
||||
static int twl6030ldo_get_voltage(struct regulator_dev *rdev)
|
||||
static int twl6030ldo_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||
int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER,
|
||||
VREG_VOLTAGE);
|
||||
int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE);
|
||||
|
||||
if (vsel < 0)
|
||||
return vsel;
|
||||
|
||||
/*
|
||||
* Use the below formula to calculate vsel
|
||||
* mV = 1000mv + 100mv * (vsel - 1)
|
||||
*/
|
||||
return (1000 + (100 * (vsel - 1))) * 1000;
|
||||
return vsel;
|
||||
}
|
||||
|
||||
static struct regulator_ops twl6030ldo_ops = {
|
||||
.list_voltage = twl6030ldo_list_voltage,
|
||||
|
||||
.set_voltage = twl6030ldo_set_voltage,
|
||||
.get_voltage = twl6030ldo_get_voltage,
|
||||
.set_voltage_sel = twl6030ldo_set_voltage_sel,
|
||||
.get_voltage_sel = twl6030ldo_get_voltage_sel,
|
||||
|
||||
.enable = twl6030reg_enable,
|
||||
.disable = twl6030reg_disable,
|
||||
.is_enabled = twl6030reg_is_enabled,
|
||||
.enable_time = twl6030reg_enable_time,
|
||||
|
||||
.set_mode = twl6030reg_set_mode,
|
||||
|
||||
@@ -663,7 +639,6 @@ static struct regulator_ops twl4030fixed_ops = {
|
||||
.enable = twl4030reg_enable,
|
||||
.disable = twl4030reg_disable,
|
||||
.is_enabled = twl4030reg_is_enabled,
|
||||
.enable_time = twl4030reg_enable_time,
|
||||
|
||||
.set_mode = twl4030reg_set_mode,
|
||||
|
||||
@@ -678,7 +653,6 @@ static struct regulator_ops twl6030fixed_ops = {
|
||||
.enable = twl6030reg_enable,
|
||||
.disable = twl6030reg_disable,
|
||||
.is_enabled = twl6030reg_is_enabled,
|
||||
.enable_time = twl6030reg_enable_time,
|
||||
|
||||
.set_mode = twl6030reg_set_mode,
|
||||
|
||||
@@ -689,7 +663,6 @@ static struct regulator_ops twl6030_fixed_resource = {
|
||||
.enable = twl6030reg_enable,
|
||||
.disable = twl6030reg_disable,
|
||||
.is_enabled = twl6030reg_is_enabled,
|
||||
.enable_time = twl6030reg_enable_time,
|
||||
.get_status = twl6030reg_get_status,
|
||||
};
|
||||
|
||||
@@ -886,7 +859,6 @@ static struct regulator_ops twlsmps_ops = {
|
||||
.enable = twl6030reg_enable,
|
||||
.disable = twl6030reg_disable,
|
||||
.is_enabled = twl6030reg_is_enabled,
|
||||
.enable_time = twl6030reg_enable_time,
|
||||
|
||||
.set_mode = twl6030reg_set_mode,
|
||||
|
||||
@@ -909,7 +881,6 @@ static struct twlreg_info TWL4030_INFO_##label = { \
|
||||
.id = num, \
|
||||
.table_len = ARRAY_SIZE(label##_VSEL_table), \
|
||||
.table = label##_VSEL_table, \
|
||||
.delay = turnon_delay, \
|
||||
.remap = remap_conf, \
|
||||
.desc = { \
|
||||
.name = #label, \
|
||||
@@ -918,6 +889,7 @@ static struct twlreg_info TWL4030_INFO_##label = { \
|
||||
.ops = &twl4030ldo_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.enable_time = turnon_delay, \
|
||||
}, \
|
||||
}
|
||||
|
||||
@@ -925,7 +897,6 @@ static struct twlreg_info TWL4030_INFO_##label = { \
|
||||
static struct twlreg_info TWL4030_INFO_##label = { \
|
||||
.base = offset, \
|
||||
.id = num, \
|
||||
.delay = turnon_delay, \
|
||||
.remap = remap_conf, \
|
||||
.desc = { \
|
||||
.name = #label, \
|
||||
@@ -933,6 +904,7 @@ static struct twlreg_info TWL4030_INFO_##label = { \
|
||||
.ops = &twl4030smps_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.enable_time = turnon_delay, \
|
||||
}, \
|
||||
}
|
||||
|
||||
@@ -955,7 +927,7 @@ static struct twlreg_info TWL6030_INFO_##label = { \
|
||||
.desc = { \
|
||||
.name = #label, \
|
||||
.id = TWL6030_REG_##label, \
|
||||
.n_voltages = (max_mVolts - min_mVolts)/100 + 1, \
|
||||
.n_voltages = 32, \
|
||||
.ops = &twl6030ldo_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
@@ -970,7 +942,7 @@ static struct twlreg_info TWL6025_INFO_##label = { \
|
||||
.desc = { \
|
||||
.name = #label, \
|
||||
.id = TWL6025_REG_##label, \
|
||||
.n_voltages = ((max_mVolts - min_mVolts)/100) + 1, \
|
||||
.n_voltages = 32, \
|
||||
.ops = &twl6030ldo_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
@@ -983,7 +955,6 @@ static struct twlreg_info TWLFIXED_INFO_##label = { \
|
||||
.base = offset, \
|
||||
.id = num, \
|
||||
.min_mV = mVolts, \
|
||||
.delay = turnon_delay, \
|
||||
.remap = remap_conf, \
|
||||
.desc = { \
|
||||
.name = #label, \
|
||||
@@ -992,19 +963,20 @@ static struct twlreg_info TWLFIXED_INFO_##label = { \
|
||||
.ops = &operations, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.enable_time = turnon_delay, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define TWL6030_FIXED_RESOURCE(label, offset, turnon_delay) \
|
||||
static struct twlreg_info TWLRES_INFO_##label = { \
|
||||
.base = offset, \
|
||||
.delay = turnon_delay, \
|
||||
.desc = { \
|
||||
.name = #label, \
|
||||
.id = TWL6030_REG_##label, \
|
||||
.ops = &twl6030_fixed_resource, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.enable_time = turnon_delay, \
|
||||
}, \
|
||||
}
|
||||
|
||||
@@ -1109,7 +1081,6 @@ static u8 twl_get_smps_mult(void)
|
||||
#define TWL6030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6030, label)
|
||||
#define TWL6025_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6025, label)
|
||||
#define TWLFIXED_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLFIXED, label)
|
||||
#define TWLRES_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLRES, label)
|
||||
#define TWLSMPS_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLSMPS, label)
|
||||
|
||||
static const struct of_device_id twl_of_match[] __devinitconst = {
|
||||
@@ -1157,7 +1128,6 @@ static const struct of_device_id twl_of_match[] __devinitconst = {
|
||||
TWLFIXED_OF_MATCH("ti,twl6030-vusb", VUSB),
|
||||
TWLFIXED_OF_MATCH("ti,twl6030-v1v8", V1V8),
|
||||
TWLFIXED_OF_MATCH("ti,twl6030-v2v1", V2V1),
|
||||
TWLRES_OF_MATCH("ti,twl6030-clk32kg", CLK32KG),
|
||||
TWLSMPS_OF_MATCH("ti,twl6025-smps3", SMPS3),
|
||||
TWLSMPS_OF_MATCH("ti,twl6025-smps4", SMPS4),
|
||||
TWLSMPS_OF_MATCH("ti,twl6025-vio", VIO),
|
||||
|
||||
@@ -215,8 +215,8 @@ static int wm831x_buckv_list_voltage(struct regulator_dev *rdev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int wm831x_buckv_select_min_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
static int wm831x_buckv_map_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
u16 vsel;
|
||||
|
||||
@@ -251,20 +251,14 @@ static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm831x_buckv_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV, unsigned *selector)
|
||||
static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned vsel)
|
||||
{
|
||||
struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
|
||||
struct wm831x *wm831x = dcdc->wm831x;
|
||||
int on_reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
|
||||
int dvs_reg = dcdc->base + WM831X_DCDC_DVS_CONTROL;
|
||||
int vsel, ret;
|
||||
|
||||
vsel = wm831x_buckv_select_min_voltage(rdev, min_uV, max_uV);
|
||||
if (vsel < 0)
|
||||
return vsel;
|
||||
|
||||
*selector = vsel;
|
||||
int ret;
|
||||
|
||||
/* If this value is already set then do a GPIO update if we can */
|
||||
if (dcdc->dvs_gpio && dcdc->on_vsel == vsel)
|
||||
@@ -315,7 +309,7 @@ static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev,
|
||||
u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;
|
||||
int vsel;
|
||||
|
||||
vsel = wm831x_buckv_select_min_voltage(rdev, uV, uV);
|
||||
vsel = wm831x_buckv_map_voltage(rdev, uV, uV);
|
||||
if (vsel < 0)
|
||||
return vsel;
|
||||
|
||||
@@ -373,9 +367,10 @@ static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev)
|
||||
}
|
||||
|
||||
static struct regulator_ops wm831x_buckv_ops = {
|
||||
.set_voltage = wm831x_buckv_set_voltage,
|
||||
.set_voltage_sel = wm831x_buckv_set_voltage_sel,
|
||||
.get_voltage_sel = wm831x_buckv_get_voltage_sel,
|
||||
.list_voltage = wm831x_buckv_list_voltage,
|
||||
.map_voltage = wm831x_buckv_map_voltage,
|
||||
.set_suspend_voltage = wm831x_buckv_set_suspend_voltage,
|
||||
.set_current_limit = wm831x_buckv_set_current_limit,
|
||||
.get_current_limit = wm831x_buckv_get_current_limit,
|
||||
@@ -599,60 +594,25 @@ static struct platform_driver wm831x_buckv_driver = {
|
||||
* BUCKP specifics
|
||||
*/
|
||||
|
||||
static int wm831x_buckp_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
if (selector <= WM831X_BUCKP_MAX_SELECTOR)
|
||||
return 850000 + (selector * 25000);
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int wm831x_buckp_set_voltage_int(struct regulator_dev *rdev, int reg,
|
||||
int min_uV, int max_uV, int *selector)
|
||||
static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev, int uV)
|
||||
{
|
||||
struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
|
||||
struct wm831x *wm831x = dcdc->wm831x;
|
||||
u16 vsel;
|
||||
|
||||
if (min_uV <= 34000000)
|
||||
vsel = (min_uV - 850000) / 25000;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (wm831x_buckp_list_voltage(rdev, vsel) > max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = vsel;
|
||||
|
||||
return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, vsel);
|
||||
}
|
||||
|
||||
static int wm831x_buckp_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV,
|
||||
unsigned *selector)
|
||||
{
|
||||
struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
|
||||
u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
|
||||
|
||||
return wm831x_buckp_set_voltage_int(rdev, reg, min_uV, max_uV,
|
||||
selector);
|
||||
}
|
||||
|
||||
static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev,
|
||||
int uV)
|
||||
{
|
||||
struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
|
||||
u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;
|
||||
unsigned selector;
|
||||
int sel;
|
||||
|
||||
return wm831x_buckp_set_voltage_int(rdev, reg, uV, uV, &selector);
|
||||
sel = regulator_map_voltage_linear(rdev, uV, uV);
|
||||
if (sel < 0)
|
||||
return sel;
|
||||
|
||||
return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, sel);
|
||||
}
|
||||
|
||||
static struct regulator_ops wm831x_buckp_ops = {
|
||||
.set_voltage = wm831x_buckp_set_voltage,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.list_voltage = wm831x_buckp_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.set_suspend_voltage = wm831x_buckp_set_suspend_voltage,
|
||||
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
@@ -715,6 +675,8 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
|
||||
dcdc->desc.vsel_mask = WM831X_DC3_ON_VSEL_MASK;
|
||||
dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;
|
||||
dcdc->desc.enable_mask = 1 << id;
|
||||
dcdc->desc.min_uV = 850000;
|
||||
dcdc->desc.uV_step = 25000;
|
||||
|
||||
config.dev = pdev->dev.parent;
|
||||
if (pdata)
|
||||
|
||||
@@ -78,13 +78,10 @@ static int wm831x_gp_ldo_list_voltage(struct regulator_dev *rdev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int wm831x_gp_ldo_set_voltage_int(struct regulator_dev *rdev, int reg,
|
||||
int min_uV, int max_uV,
|
||||
unsigned *selector)
|
||||
static int wm831x_gp_ldo_map_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
struct wm831x *wm831x = ldo->wm831x;
|
||||
int vsel, ret;
|
||||
int volt, vsel;
|
||||
|
||||
if (min_uV < 900000)
|
||||
vsel = 0;
|
||||
@@ -94,36 +91,25 @@ static int wm831x_gp_ldo_set_voltage_int(struct regulator_dev *rdev, int reg,
|
||||
vsel = ((min_uV - 1700000) / 100000)
|
||||
+ WM831X_GP_LDO_SELECTOR_LOW + 1;
|
||||
|
||||
ret = wm831x_gp_ldo_list_voltage(rdev, vsel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret < min_uV || ret > max_uV)
|
||||
volt = wm831x_gp_ldo_list_voltage(rdev, vsel);
|
||||
if (volt < min_uV || volt > max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = vsel;
|
||||
|
||||
return wm831x_set_bits(wm831x, reg, WM831X_LDO1_ON_VSEL_MASK, vsel);
|
||||
}
|
||||
|
||||
static int wm831x_gp_ldo_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV,
|
||||
unsigned *selector)
|
||||
{
|
||||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
int reg = ldo->base + WM831X_LDO_ON_CONTROL;
|
||||
|
||||
return wm831x_gp_ldo_set_voltage_int(rdev, reg, min_uV, max_uV,
|
||||
selector);
|
||||
return vsel;
|
||||
}
|
||||
|
||||
static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,
|
||||
int uV)
|
||||
{
|
||||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
|
||||
unsigned int selector;
|
||||
struct wm831x *wm831x = ldo->wm831x;
|
||||
int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
|
||||
|
||||
return wm831x_gp_ldo_set_voltage_int(rdev, reg, uV, uV, &selector);
|
||||
sel = wm831x_gp_ldo_map_voltage(rdev, uV, uV);
|
||||
if (sel < 0)
|
||||
return sel;
|
||||
|
||||
return wm831x_set_bits(wm831x, reg, WM831X_LDO1_ON_VSEL_MASK, sel);
|
||||
}
|
||||
|
||||
static unsigned int wm831x_gp_ldo_get_mode(struct regulator_dev *rdev)
|
||||
@@ -243,8 +229,9 @@ static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev,
|
||||
|
||||
static struct regulator_ops wm831x_gp_ldo_ops = {
|
||||
.list_voltage = wm831x_gp_ldo_list_voltage,
|
||||
.map_voltage = wm831x_gp_ldo_map_voltage,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage = wm831x_gp_ldo_set_voltage,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage,
|
||||
.get_mode = wm831x_gp_ldo_get_mode,
|
||||
.set_mode = wm831x_gp_ldo_set_mode,
|
||||
@@ -384,13 +371,10 @@ static int wm831x_aldo_list_voltage(struct regulator_dev *rdev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int wm831x_aldo_set_voltage_int(struct regulator_dev *rdev, int reg,
|
||||
int min_uV, int max_uV,
|
||||
unsigned *selector)
|
||||
static int wm831x_aldo_map_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
struct wm831x *wm831x = ldo->wm831x;
|
||||
int vsel, ret;
|
||||
int volt, vsel;
|
||||
|
||||
if (min_uV < 1000000)
|
||||
vsel = 0;
|
||||
@@ -400,35 +384,26 @@ static int wm831x_aldo_set_voltage_int(struct regulator_dev *rdev, int reg,
|
||||
vsel = ((min_uV - 1700000) / 100000)
|
||||
+ WM831X_ALDO_SELECTOR_LOW + 1;
|
||||
|
||||
ret = wm831x_aldo_list_voltage(rdev, vsel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret < min_uV || ret > max_uV)
|
||||
volt = wm831x_aldo_list_voltage(rdev, vsel);
|
||||
if (volt < min_uV || volt > max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = vsel;
|
||||
return vsel;
|
||||
|
||||
return wm831x_set_bits(wm831x, reg, WM831X_LDO7_ON_VSEL_MASK, vsel);
|
||||
}
|
||||
|
||||
static int wm831x_aldo_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV, unsigned *selector)
|
||||
{
|
||||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
int reg = ldo->base + WM831X_LDO_ON_CONTROL;
|
||||
|
||||
return wm831x_aldo_set_voltage_int(rdev, reg, min_uV, max_uV,
|
||||
selector);
|
||||
}
|
||||
|
||||
static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,
|
||||
int uV)
|
||||
{
|
||||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
|
||||
unsigned int selector;
|
||||
struct wm831x *wm831x = ldo->wm831x;
|
||||
int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
|
||||
|
||||
return wm831x_aldo_set_voltage_int(rdev, reg, uV, uV, &selector);
|
||||
sel = wm831x_aldo_map_voltage(rdev, uV, uV);
|
||||
if (sel < 0)
|
||||
return sel;
|
||||
|
||||
return wm831x_set_bits(wm831x, reg, WM831X_LDO7_ON_VSEL_MASK, sel);
|
||||
}
|
||||
|
||||
static unsigned int wm831x_aldo_get_mode(struct regulator_dev *rdev)
|
||||
@@ -506,8 +481,9 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev)
|
||||
|
||||
static struct regulator_ops wm831x_aldo_ops = {
|
||||
.list_voltage = wm831x_aldo_list_voltage,
|
||||
.map_voltage = wm831x_aldo_map_voltage,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage = wm831x_aldo_set_voltage,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.set_suspend_voltage = wm831x_aldo_set_suspend_voltage,
|
||||
.get_mode = wm831x_aldo_get_mode,
|
||||
.set_mode = wm831x_aldo_set_mode,
|
||||
@@ -628,47 +604,18 @@ static struct platform_driver wm831x_aldo_driver = {
|
||||
|
||||
#define WM831X_ALIVE_LDO_MAX_SELECTOR 0xf
|
||||
|
||||
static int wm831x_alive_ldo_set_voltage_int(struct regulator_dev *rdev,
|
||||
int reg,
|
||||
int min_uV, int max_uV,
|
||||
unsigned *selector)
|
||||
{
|
||||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
struct wm831x *wm831x = ldo->wm831x;
|
||||
int vsel, ret;
|
||||
|
||||
vsel = (min_uV - 800000) / 50000;
|
||||
|
||||
ret = regulator_list_voltage_linear(rdev, vsel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret < min_uV || ret > max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
*selector = vsel;
|
||||
|
||||
return wm831x_set_bits(wm831x, reg, WM831X_LDO11_ON_VSEL_MASK, vsel);
|
||||
}
|
||||
|
||||
static int wm831x_alive_ldo_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV,
|
||||
unsigned *selector)
|
||||
{
|
||||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
int reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL;
|
||||
|
||||
return wm831x_alive_ldo_set_voltage_int(rdev, reg, min_uV, max_uV,
|
||||
selector);
|
||||
}
|
||||
|
||||
static int wm831x_alive_ldo_set_suspend_voltage(struct regulator_dev *rdev,
|
||||
int uV)
|
||||
{
|
||||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
int reg = ldo->base + WM831X_ALIVE_LDO_SLEEP_CONTROL;
|
||||
unsigned selector;
|
||||
struct wm831x *wm831x = ldo->wm831x;
|
||||
int sel, reg = ldo->base + WM831X_ALIVE_LDO_SLEEP_CONTROL;
|
||||
|
||||
return wm831x_alive_ldo_set_voltage_int(rdev, reg, uV, uV, &selector);
|
||||
sel = regulator_map_voltage_linear(rdev, uV, uV);
|
||||
if (sel < 0)
|
||||
return sel;
|
||||
|
||||
return wm831x_set_bits(wm831x, reg, WM831X_LDO11_ON_VSEL_MASK, sel);
|
||||
}
|
||||
|
||||
static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev)
|
||||
@@ -690,8 +637,9 @@ static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev)
|
||||
|
||||
static 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,
|
||||
.set_voltage = wm831x_alive_ldo_set_voltage,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.set_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage,
|
||||
.get_status = wm831x_alive_ldo_get_status,
|
||||
|
||||
@@ -753,6 +701,7 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
|
||||
ldo->desc.enable_mask = 1 << id;
|
||||
ldo->desc.min_uV = 800000;
|
||||
ldo->desc.uV_step = 50000;
|
||||
ldo->desc.enable_time = 1000;
|
||||
|
||||
config.dev = pdev->dev.parent;
|
||||
if (pdata)
|
||||
|
||||
@@ -108,33 +108,6 @@ static int get_isink_val(int min_uA, int max_uA, u16 *setting)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int wm8350_ldo_val_to_mvolts(unsigned int val)
|
||||
{
|
||||
if (val < 16)
|
||||
return (val * 50) + 900;
|
||||
else
|
||||
return ((val - 16) * 100) + 1800;
|
||||
|
||||
}
|
||||
|
||||
static inline unsigned int wm8350_ldo_mvolts_to_val(int mV)
|
||||
{
|
||||
if (mV < 1800)
|
||||
return (mV - 900) / 50;
|
||||
else
|
||||
return ((mV - 1800) / 100) + 16;
|
||||
}
|
||||
|
||||
static inline int wm8350_dcdc_val_to_mvolts(unsigned int val)
|
||||
{
|
||||
return (val * 25) + 850;
|
||||
}
|
||||
|
||||
static inline unsigned int wm8350_dcdc_mvolts_to_val(int mV)
|
||||
{
|
||||
return (mV - 850) / 25;
|
||||
}
|
||||
|
||||
static int wm8350_isink_set_current(struct regulator_dev *rdev, int min_uA,
|
||||
int max_uA)
|
||||
{
|
||||
@@ -359,104 +332,13 @@ int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm8350_isink_set_flash);
|
||||
|
||||
static int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV,
|
||||
int max_uV, unsigned *selector)
|
||||
{
|
||||
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
|
||||
int volt_reg, dcdc = rdev_get_id(rdev), mV,
|
||||
min_mV = min_uV / 1000, max_mV = max_uV / 1000;
|
||||
u16 val;
|
||||
|
||||
if (min_mV < 850 || min_mV > 4025)
|
||||
return -EINVAL;
|
||||
if (max_mV < 850 || max_mV > 4025)
|
||||
return -EINVAL;
|
||||
|
||||
/* step size is 25mV */
|
||||
mV = (min_mV - 826) / 25;
|
||||
if (wm8350_dcdc_val_to_mvolts(mV) > max_mV)
|
||||
return -EINVAL;
|
||||
BUG_ON(wm8350_dcdc_val_to_mvolts(mV) < min_mV);
|
||||
|
||||
switch (dcdc) {
|
||||
case WM8350_DCDC_1:
|
||||
volt_reg = WM8350_DCDC1_CONTROL;
|
||||
break;
|
||||
case WM8350_DCDC_3:
|
||||
volt_reg = WM8350_DCDC3_CONTROL;
|
||||
break;
|
||||
case WM8350_DCDC_4:
|
||||
volt_reg = WM8350_DCDC4_CONTROL;
|
||||
break;
|
||||
case WM8350_DCDC_6:
|
||||
volt_reg = WM8350_DCDC6_CONTROL;
|
||||
break;
|
||||
case WM8350_DCDC_2:
|
||||
case WM8350_DCDC_5:
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*selector = mV;
|
||||
|
||||
/* all DCDCs have same mV bits */
|
||||
val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
|
||||
wm8350_reg_write(wm8350, volt_reg, val | mV);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8350_dcdc_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
|
||||
int volt_reg, dcdc = rdev_get_id(rdev);
|
||||
|
||||
switch (dcdc) {
|
||||
case WM8350_DCDC_1:
|
||||
volt_reg = WM8350_DCDC1_CONTROL;
|
||||
break;
|
||||
case WM8350_DCDC_3:
|
||||
volt_reg = WM8350_DCDC3_CONTROL;
|
||||
break;
|
||||
case WM8350_DCDC_4:
|
||||
volt_reg = WM8350_DCDC4_CONTROL;
|
||||
break;
|
||||
case WM8350_DCDC_6:
|
||||
volt_reg = WM8350_DCDC6_CONTROL;
|
||||
break;
|
||||
case WM8350_DCDC_2:
|
||||
case WM8350_DCDC_5:
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* all DCDCs have same mV bits */
|
||||
return wm8350_reg_read(wm8350, volt_reg) & WM8350_DC1_VSEL_MASK;
|
||||
}
|
||||
|
||||
static int wm8350_dcdc_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
if (selector > WM8350_DCDC_MAX_VSEL)
|
||||
return -EINVAL;
|
||||
return wm8350_dcdc_val_to_mvolts(selector) * 1000;
|
||||
}
|
||||
|
||||
static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV)
|
||||
{
|
||||
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
|
||||
int volt_reg, mV = uV / 1000, dcdc = rdev_get_id(rdev);
|
||||
int sel, volt_reg, dcdc = rdev_get_id(rdev);
|
||||
u16 val;
|
||||
|
||||
dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, dcdc, mV);
|
||||
|
||||
if (mV && (mV < 850 || mV > 4025)) {
|
||||
dev_err(wm8350->dev,
|
||||
"DCDC%d suspend voltage %d mV out of range\n",
|
||||
dcdc, mV);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mV == 0)
|
||||
mV = 850;
|
||||
dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, dcdc, uV / 1000);
|
||||
|
||||
switch (dcdc) {
|
||||
case WM8350_DCDC_1:
|
||||
@@ -477,10 +359,13 @@ static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sel = regulator_map_voltage_linear(rdev, uV, uV);
|
||||
if (sel < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* all DCDCs have same mV bits */
|
||||
val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
|
||||
wm8350_reg_write(wm8350, volt_reg,
|
||||
val | wm8350_dcdc_mvolts_to_val(mV));
|
||||
wm8350_reg_write(wm8350, volt_reg, val | sel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -657,19 +542,49 @@ static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8350_ldo_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
if (selector > WM8350_LDO1_VSEL_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
if (selector < 16)
|
||||
return (selector * 50000) + 900000;
|
||||
else
|
||||
return ((selector - 16) * 100000) + 1800000;
|
||||
}
|
||||
|
||||
static int wm8350_ldo_map_voltage(struct regulator_dev *rdev, int min_uV,
|
||||
int max_uV)
|
||||
{
|
||||
int volt, sel;
|
||||
int min_mV = min_uV / 1000;
|
||||
int max_mV = max_uV / 1000;
|
||||
|
||||
if (min_mV < 900 || min_mV > 3300)
|
||||
return -EINVAL;
|
||||
if (max_mV < 900 || max_mV > 3300)
|
||||
return -EINVAL;
|
||||
|
||||
if (min_mV < 1800) /* step size is 50mV < 1800mV */
|
||||
sel = DIV_ROUND_UP(min_uV - 900, 50);
|
||||
else /* step size is 100mV > 1800mV */
|
||||
sel = DIV_ROUND_UP(min_uV - 1800, 100) + 16;
|
||||
|
||||
volt = wm8350_ldo_list_voltage(rdev, sel);
|
||||
if (volt < min_uV || volt > max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
return sel;
|
||||
}
|
||||
|
||||
static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
|
||||
{
|
||||
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
|
||||
int volt_reg, mV = uV / 1000, ldo = rdev_get_id(rdev);
|
||||
int sel, volt_reg, ldo = rdev_get_id(rdev);
|
||||
u16 val;
|
||||
|
||||
dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, ldo, mV);
|
||||
|
||||
if (mV < 900 || mV > 3300) {
|
||||
dev_err(wm8350->dev, "LDO%d voltage %d mV out of range\n",
|
||||
ldo, mV);
|
||||
return -EINVAL;
|
||||
}
|
||||
dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, ldo, uV / 1000);
|
||||
|
||||
switch (ldo) {
|
||||
case WM8350_LDO_1:
|
||||
@@ -688,10 +603,13 @@ static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sel = wm8350_ldo_map_voltage(rdev, uV, uV);
|
||||
if (sel < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* all LDOs have same mV bits */
|
||||
val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
|
||||
wm8350_reg_write(wm8350, volt_reg,
|
||||
val | wm8350_ldo_mvolts_to_val(mV));
|
||||
wm8350_reg_write(wm8350, volt_reg, val | sel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -753,92 +671,6 @@ static int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV,
|
||||
int max_uV, unsigned *selector)
|
||||
{
|
||||
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
|
||||
int volt_reg, ldo = rdev_get_id(rdev), mV, min_mV = min_uV / 1000,
|
||||
max_mV = max_uV / 1000;
|
||||
u16 val;
|
||||
|
||||
if (min_mV < 900 || min_mV > 3300)
|
||||
return -EINVAL;
|
||||
if (max_mV < 900 || max_mV > 3300)
|
||||
return -EINVAL;
|
||||
|
||||
if (min_mV < 1800) {
|
||||
/* step size is 50mV < 1800mV */
|
||||
mV = (min_mV - 851) / 50;
|
||||
if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
|
||||
return -EINVAL;
|
||||
BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
|
||||
} else {
|
||||
/* step size is 100mV > 1800mV */
|
||||
mV = ((min_mV - 1701) / 100) + 16;
|
||||
if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
|
||||
return -EINVAL;
|
||||
BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
|
||||
}
|
||||
|
||||
switch (ldo) {
|
||||
case WM8350_LDO_1:
|
||||
volt_reg = WM8350_LDO1_CONTROL;
|
||||
break;
|
||||
case WM8350_LDO_2:
|
||||
volt_reg = WM8350_LDO2_CONTROL;
|
||||
break;
|
||||
case WM8350_LDO_3:
|
||||
volt_reg = WM8350_LDO3_CONTROL;
|
||||
break;
|
||||
case WM8350_LDO_4:
|
||||
volt_reg = WM8350_LDO4_CONTROL;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*selector = mV;
|
||||
|
||||
/* all LDOs have same mV bits */
|
||||
val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
|
||||
wm8350_reg_write(wm8350, volt_reg, val | mV);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8350_ldo_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
|
||||
int volt_reg, ldo = rdev_get_id(rdev);
|
||||
|
||||
switch (ldo) {
|
||||
case WM8350_LDO_1:
|
||||
volt_reg = WM8350_LDO1_CONTROL;
|
||||
break;
|
||||
case WM8350_LDO_2:
|
||||
volt_reg = WM8350_LDO2_CONTROL;
|
||||
break;
|
||||
case WM8350_LDO_3:
|
||||
volt_reg = WM8350_LDO3_CONTROL;
|
||||
break;
|
||||
case WM8350_LDO_4:
|
||||
volt_reg = WM8350_LDO4_CONTROL;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* all LDOs have same mV bits */
|
||||
return wm8350_reg_read(wm8350, volt_reg) & WM8350_LDO1_VSEL_MASK;
|
||||
}
|
||||
|
||||
static int wm8350_ldo_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
if (selector > WM8350_LDO1_VSEL_MASK)
|
||||
return -EINVAL;
|
||||
return wm8350_ldo_val_to_mvolts(selector) * 1000;
|
||||
}
|
||||
|
||||
int wm8350_dcdc_set_slot(struct wm8350 *wm8350, int dcdc, u16 start,
|
||||
u16 stop, u16 fault)
|
||||
{
|
||||
@@ -959,63 +791,6 @@ int wm8350_dcdc25_set_mode(struct wm8350 *wm8350, int dcdc, u16 mode,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm8350_dcdc25_set_mode);
|
||||
|
||||
static int wm8350_dcdc_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
|
||||
int dcdc = rdev_get_id(rdev);
|
||||
u16 shift;
|
||||
|
||||
if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
|
||||
return -EINVAL;
|
||||
|
||||
shift = dcdc - WM8350_DCDC_1;
|
||||
wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8350_dcdc_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
|
||||
int dcdc = rdev_get_id(rdev);
|
||||
u16 shift;
|
||||
|
||||
if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
|
||||
return -EINVAL;
|
||||
|
||||
shift = dcdc - WM8350_DCDC_1;
|
||||
wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8350_ldo_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
|
||||
int ldo = rdev_get_id(rdev);
|
||||
u16 shift;
|
||||
|
||||
if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
|
||||
return -EINVAL;
|
||||
|
||||
shift = (ldo - WM8350_LDO_1) + 8;
|
||||
wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8350_ldo_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
|
||||
int ldo = rdev_get_id(rdev);
|
||||
u16 shift;
|
||||
|
||||
if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
|
||||
return -EINVAL;
|
||||
|
||||
shift = (ldo - WM8350_LDO_1) + 8;
|
||||
wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int force_continuous_enable(struct wm8350 *wm8350, int dcdc, int enable)
|
||||
{
|
||||
int reg = 0, ret;
|
||||
@@ -1197,42 +972,17 @@ static unsigned int wm8350_dcdc_get_optimum_mode(struct regulator_dev *rdev,
|
||||
return mode;
|
||||
}
|
||||
|
||||
static int wm8350_dcdc_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
|
||||
int dcdc = rdev_get_id(rdev), shift;
|
||||
|
||||
if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
|
||||
return -EINVAL;
|
||||
|
||||
shift = dcdc - WM8350_DCDC_1;
|
||||
return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED)
|
||||
& (1 << shift);
|
||||
}
|
||||
|
||||
static int wm8350_ldo_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
|
||||
int ldo = rdev_get_id(rdev), shift;
|
||||
|
||||
if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
|
||||
return -EINVAL;
|
||||
|
||||
shift = (ldo - WM8350_LDO_1) + 8;
|
||||
return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED)
|
||||
& (1 << shift);
|
||||
}
|
||||
|
||||
static struct regulator_ops wm8350_dcdc_ops = {
|
||||
.set_voltage = wm8350_dcdc_set_voltage,
|
||||
.get_voltage_sel = wm8350_dcdc_get_voltage_sel,
|
||||
.list_voltage = wm8350_dcdc_list_voltage,
|
||||
.enable = wm8350_dcdc_enable,
|
||||
.disable = wm8350_dcdc_disable,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.get_mode = wm8350_dcdc_get_mode,
|
||||
.set_mode = wm8350_dcdc_set_mode,
|
||||
.get_optimum_mode = wm8350_dcdc_get_optimum_mode,
|
||||
.is_enabled = wm8350_dcdc_is_enabled,
|
||||
.set_suspend_voltage = wm8350_dcdc_set_suspend_voltage,
|
||||
.set_suspend_enable = wm8350_dcdc_set_suspend_enable,
|
||||
.set_suspend_disable = wm8350_dcdc_set_suspend_disable,
|
||||
@@ -1240,20 +990,21 @@ static struct regulator_ops wm8350_dcdc_ops = {
|
||||
};
|
||||
|
||||
static struct regulator_ops wm8350_dcdc2_5_ops = {
|
||||
.enable = wm8350_dcdc_enable,
|
||||
.disable = wm8350_dcdc_disable,
|
||||
.is_enabled = wm8350_dcdc_is_enabled,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_suspend_enable = wm8350_dcdc25_set_suspend_enable,
|
||||
.set_suspend_disable = wm8350_dcdc25_set_suspend_disable,
|
||||
};
|
||||
|
||||
static struct regulator_ops wm8350_ldo_ops = {
|
||||
.set_voltage = wm8350_ldo_set_voltage,
|
||||
.get_voltage_sel = wm8350_ldo_get_voltage_sel,
|
||||
.map_voltage = wm8350_ldo_map_voltage,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.list_voltage = wm8350_ldo_list_voltage,
|
||||
.enable = wm8350_ldo_enable,
|
||||
.disable = wm8350_ldo_disable,
|
||||
.is_enabled = wm8350_ldo_is_enabled,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.get_mode = wm8350_ldo_get_mode,
|
||||
.set_suspend_voltage = wm8350_ldo_set_suspend_voltage,
|
||||
.set_suspend_enable = wm8350_ldo_set_suspend_enable,
|
||||
@@ -1277,6 +1028,12 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||
.irq = WM8350_IRQ_UV_DC1,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = WM8350_DCDC_MAX_VSEL + 1,
|
||||
.min_uV = 850000,
|
||||
.uV_step = 25000,
|
||||
.vsel_reg = WM8350_DCDC1_CONTROL,
|
||||
.vsel_mask = WM8350_DC1_VSEL_MASK,
|
||||
.enable_reg = WM8350_DCDC_LDO_REQUESTED,
|
||||
.enable_mask = WM8350_DC1_ENA,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
@@ -1285,6 +1042,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||
.ops = &wm8350_dcdc2_5_ops,
|
||||
.irq = WM8350_IRQ_UV_DC2,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.enable_reg = WM8350_DCDC_LDO_REQUESTED,
|
||||
.enable_mask = WM8350_DC2_ENA,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
@@ -1294,6 +1053,12 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||
.irq = WM8350_IRQ_UV_DC3,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = WM8350_DCDC_MAX_VSEL + 1,
|
||||
.min_uV = 850000,
|
||||
.uV_step = 25000,
|
||||
.vsel_reg = WM8350_DCDC3_CONTROL,
|
||||
.vsel_mask = WM8350_DC3_VSEL_MASK,
|
||||
.enable_reg = WM8350_DCDC_LDO_REQUESTED,
|
||||
.enable_mask = WM8350_DC3_ENA,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
@@ -1303,6 +1068,12 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||
.irq = WM8350_IRQ_UV_DC4,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = WM8350_DCDC_MAX_VSEL + 1,
|
||||
.min_uV = 850000,
|
||||
.uV_step = 25000,
|
||||
.vsel_reg = WM8350_DCDC4_CONTROL,
|
||||
.vsel_mask = WM8350_DC4_VSEL_MASK,
|
||||
.enable_reg = WM8350_DCDC_LDO_REQUESTED,
|
||||
.enable_mask = WM8350_DC4_ENA,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
@@ -1311,6 +1082,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||
.ops = &wm8350_dcdc2_5_ops,
|
||||
.irq = WM8350_IRQ_UV_DC5,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.enable_reg = WM8350_DCDC_LDO_REQUESTED,
|
||||
.enable_mask = WM8350_DC5_ENA,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
@@ -1320,6 +1093,12 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||
.irq = WM8350_IRQ_UV_DC6,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = WM8350_DCDC_MAX_VSEL + 1,
|
||||
.min_uV = 850000,
|
||||
.uV_step = 25000,
|
||||
.vsel_reg = WM8350_DCDC6_CONTROL,
|
||||
.vsel_mask = WM8350_DC6_VSEL_MASK,
|
||||
.enable_reg = WM8350_DCDC_LDO_REQUESTED,
|
||||
.enable_mask = WM8350_DC6_ENA,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
@@ -1329,6 +1108,10 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||
.irq = WM8350_IRQ_UV_LDO1,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = WM8350_LDO1_VSEL_MASK + 1,
|
||||
.vsel_reg = WM8350_LDO1_CONTROL,
|
||||
.vsel_mask = WM8350_LDO1_VSEL_MASK,
|
||||
.enable_reg = WM8350_DCDC_LDO_REQUESTED,
|
||||
.enable_mask = WM8350_LDO1_ENA,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
@@ -1338,6 +1121,10 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||
.irq = WM8350_IRQ_UV_LDO2,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = WM8350_LDO2_VSEL_MASK + 1,
|
||||
.vsel_reg = WM8350_LDO2_CONTROL,
|
||||
.vsel_mask = WM8350_LDO2_VSEL_MASK,
|
||||
.enable_reg = WM8350_DCDC_LDO_REQUESTED,
|
||||
.enable_mask = WM8350_LDO2_ENA,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
@@ -1347,6 +1134,10 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||
.irq = WM8350_IRQ_UV_LDO3,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = WM8350_LDO3_VSEL_MASK + 1,
|
||||
.vsel_reg = WM8350_LDO3_CONTROL,
|
||||
.vsel_mask = WM8350_LDO3_VSEL_MASK,
|
||||
.enable_reg = WM8350_DCDC_LDO_REQUESTED,
|
||||
.enable_mask = WM8350_LDO3_ENA,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
@@ -1356,6 +1147,10 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||
.irq = WM8350_IRQ_UV_LDO4,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = WM8350_LDO4_VSEL_MASK + 1,
|
||||
.vsel_reg = WM8350_LDO4_CONTROL,
|
||||
.vsel_mask = WM8350_LDO4_VSEL_MASK,
|
||||
.enable_reg = WM8350_DCDC_LDO_REQUESTED,
|
||||
.enable_mask = WM8350_LDO4_ENA,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
@@ -1429,6 +1224,7 @@ static int wm8350_regulator_probe(struct platform_device *pdev)
|
||||
config.dev = &pdev->dev;
|
||||
config.init_data = pdev->dev.platform_data;
|
||||
config.driver_data = dev_get_drvdata(&pdev->dev);
|
||||
config.regmap = wm8350->regmap;
|
||||
|
||||
/* register regulator */
|
||||
rdev = regulator_register(&wm8350_reg[pdev->id], &config);
|
||||
|
||||
@@ -28,34 +28,26 @@ static int wm8400_ldo_list_voltage(struct regulator_dev *dev,
|
||||
if (selector < 15)
|
||||
return 900000 + (selector * 50000);
|
||||
else
|
||||
return 1600000 + ((selector - 14) * 100000);
|
||||
return 1700000 + ((selector - 15) * 100000);
|
||||
}
|
||||
|
||||
static int wm8400_ldo_map_voltage(struct regulator_dev *dev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
u16 val;
|
||||
int volt;
|
||||
|
||||
if (min_uV < 900000 || min_uV > 3300000)
|
||||
return -EINVAL;
|
||||
|
||||
if (min_uV < 1700000) {
|
||||
/* Steps of 50mV from 900mV; */
|
||||
if (min_uV < 1700000) /* Steps of 50mV from 900mV; */
|
||||
val = DIV_ROUND_UP(min_uV - 900000, 50000);
|
||||
else /* Steps of 100mV from 1700mV */
|
||||
val = DIV_ROUND_UP(min_uV - 1700000, 100000) + 15;
|
||||
|
||||
if ((val * 50000) + 900000 > max_uV)
|
||||
return -EINVAL;
|
||||
BUG_ON((val * 50000) + 900000 < min_uV);
|
||||
} else {
|
||||
/* Steps of 100mV from 1700mV */
|
||||
val = DIV_ROUND_UP(min_uV - 1700000, 100000);
|
||||
|
||||
if ((val * 100000) + 1700000 > max_uV)
|
||||
return -EINVAL;
|
||||
BUG_ON((val * 100000) + 1700000 < min_uV);
|
||||
|
||||
val += 0xf;
|
||||
}
|
||||
volt = wm8400_ldo_list_voltage(dev, val);
|
||||
if (volt < min_uV || volt > max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
return val;
|
||||
}
|
||||
@@ -152,6 +144,7 @@ static struct regulator_ops wm8400_dcdc_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_mode = wm8400_dcdc_get_mode,
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
#include <linux/mfd/wm8994/pdata.h>
|
||||
|
||||
struct wm8994_ldo {
|
||||
int enable;
|
||||
bool is_enabled;
|
||||
struct regulator_dev *regulator;
|
||||
struct wm8994 *wm8994;
|
||||
};
|
||||
@@ -35,64 +33,9 @@ struct wm8994_ldo {
|
||||
#define WM8994_LDO1_MAX_SELECTOR 0x7
|
||||
#define WM8994_LDO2_MAX_SELECTOR 0x3
|
||||
|
||||
static int wm8994_ldo_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
|
||||
/* If we have no soft control assume that the LDO is always enabled. */
|
||||
if (!ldo->enable)
|
||||
return 0;
|
||||
|
||||
gpio_set_value_cansleep(ldo->enable, 1);
|
||||
ldo->is_enabled = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8994_ldo_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
|
||||
/* If we have no soft control assume that the LDO is always enabled. */
|
||||
if (!ldo->enable)
|
||||
return -EINVAL;
|
||||
|
||||
gpio_set_value_cansleep(ldo->enable, 0);
|
||||
ldo->is_enabled = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8994_ldo_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
|
||||
return ldo->is_enabled;
|
||||
}
|
||||
|
||||
static int wm8994_ldo_enable_time(struct regulator_dev *rdev)
|
||||
{
|
||||
/* 3ms is fairly conservative but this shouldn't be too performance
|
||||
* critical; can be tweaked per-system if required. */
|
||||
return 3000;
|
||||
}
|
||||
|
||||
static int wm8994_ldo1_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned int selector)
|
||||
{
|
||||
if (selector > WM8994_LDO1_MAX_SELECTOR)
|
||||
return -EINVAL;
|
||||
|
||||
return (selector * 100000) + 2400000;
|
||||
}
|
||||
|
||||
static struct regulator_ops wm8994_ldo1_ops = {
|
||||
.enable = wm8994_ldo_enable,
|
||||
.disable = wm8994_ldo_disable,
|
||||
.is_enabled = wm8994_ldo_is_enabled,
|
||||
.enable_time = wm8994_ldo_enable_time,
|
||||
|
||||
.list_voltage = wm8994_ldo1_list_voltage,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
};
|
||||
@@ -124,11 +67,6 @@ static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev,
|
||||
}
|
||||
|
||||
static struct regulator_ops wm8994_ldo2_ops = {
|
||||
.enable = wm8994_ldo_enable,
|
||||
.disable = wm8994_ldo_disable,
|
||||
.is_enabled = wm8994_ldo_is_enabled,
|
||||
.enable_time = wm8994_ldo_enable_time,
|
||||
|
||||
.list_voltage = wm8994_ldo2_list_voltage,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
@@ -143,6 +81,9 @@ static const struct regulator_desc wm8994_ldo_desc[] = {
|
||||
.vsel_reg = WM8994_LDO_1,
|
||||
.vsel_mask = WM8994_LDO1_VSEL_MASK,
|
||||
.ops = &wm8994_ldo1_ops,
|
||||
.min_uV = 2400000,
|
||||
.uV_step = 100000,
|
||||
.enable_time = 3000,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
@@ -153,6 +94,7 @@ static const struct regulator_desc wm8994_ldo_desc[] = {
|
||||
.vsel_reg = WM8994_LDO_2,
|
||||
.vsel_mask = WM8994_LDO2_VSEL_MASK,
|
||||
.ops = &wm8994_ldo2_ops,
|
||||
.enable_time = 3000,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
@@ -176,39 +118,26 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev)
|
||||
|
||||
ldo->wm8994 = wm8994;
|
||||
|
||||
if (pdata->ldo[id].enable && gpio_is_valid(pdata->ldo[id].enable)) {
|
||||
ldo->enable = pdata->ldo[id].enable;
|
||||
|
||||
ret = gpio_request_one(ldo->enable, 0, "WM8994 LDO enable");
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to get enable GPIO: %d\n",
|
||||
ret);
|
||||
goto err;
|
||||
}
|
||||
} else
|
||||
ldo->is_enabled = true;
|
||||
|
||||
config.dev = wm8994->dev;
|
||||
config.driver_data = ldo;
|
||||
config.regmap = wm8994->regmap;
|
||||
if (pdata)
|
||||
if (pdata) {
|
||||
config.init_data = pdata->ldo[id].init_data;
|
||||
config.ena_gpio = pdata->ldo[id].enable;
|
||||
}
|
||||
|
||||
ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &config);
|
||||
if (IS_ERR(ldo->regulator)) {
|
||||
ret = PTR_ERR(ldo->regulator);
|
||||
dev_err(wm8994->dev, "Failed to register LDO%d: %d\n",
|
||||
id + 1, ret);
|
||||
goto err_gpio;
|
||||
goto err;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, ldo);
|
||||
|
||||
return 0;
|
||||
|
||||
err_gpio:
|
||||
if (gpio_is_valid(ldo->enable))
|
||||
gpio_free(ldo->enable);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@@ -220,8 +149,6 @@ static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
regulator_unregister(ldo->regulator);
|
||||
if (gpio_is_valid(ldo->enable))
|
||||
gpio_free(ldo->enable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -347,6 +347,7 @@ struct s5m_platform_data {
|
||||
bool buck_voltage_lock;
|
||||
|
||||
int buck_gpios[3];
|
||||
int buck_ds[3];
|
||||
int buck2_voltage[8];
|
||||
bool buck2_gpiodvs;
|
||||
int buck3_voltage[8];
|
||||
@@ -369,6 +370,10 @@ struct s5m_platform_data {
|
||||
bool buck2_ramp_enable;
|
||||
bool buck3_ramp_enable;
|
||||
bool buck4_ramp_enable;
|
||||
|
||||
int buck2_init;
|
||||
int buck3_init;
|
||||
int buck4_init;
|
||||
};
|
||||
|
||||
#endif /* __LINUX_MFD_S5M_CORE_H */
|
||||
|
||||
@@ -217,7 +217,8 @@ enum tps65217_regulator_id {
|
||||
* Board data may be used to initialize regulator.
|
||||
*/
|
||||
struct tps65217_board {
|
||||
struct regulator_init_data *tps65217_init_data;
|
||||
struct regulator_init_data *tps65217_init_data[TPS65217_NUM_REGULATOR];
|
||||
struct device_node *of_node[TPS65217_NUM_REGULATOR];
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -227,11 +228,6 @@ struct tps65217_board {
|
||||
* @max_uV: minimum micro volts
|
||||
* @vsel_to_uv: Function pointer to get voltage from selector
|
||||
* @uv_to_vsel: Function pointer to get selector from voltage
|
||||
* @table: Table for non-uniform voltage step-size
|
||||
* @table_len: Length of the voltage table
|
||||
* @enable_mask: Regulator enable mask bits
|
||||
* @set_vout_reg: Regulator output voltage set register
|
||||
* @set_vout_mask: Regulator output voltage set mask
|
||||
*
|
||||
* This data is used to check the regualtor voltage limits while setting.
|
||||
*/
|
||||
@@ -241,11 +237,6 @@ struct tps_info {
|
||||
int max_uV;
|
||||
int (*vsel_to_uv)(unsigned int vsel);
|
||||
int (*uv_to_vsel)(int uV, unsigned int *vsel);
|
||||
const int *table;
|
||||
unsigned int table_len;
|
||||
unsigned int enable_mask;
|
||||
unsigned int set_vout_reg;
|
||||
unsigned int set_vout_mask;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -880,4 +880,10 @@ static inline int tps65910_reg_clear_bits(struct tps65910 *tps65910, u8 reg,
|
||||
return regmap_update_bits(tps65910->regmap, reg, mask, 0);
|
||||
}
|
||||
|
||||
static inline int tps65910_reg_update_bits(struct tps65910 *tps65910, u8 reg,
|
||||
u8 mask, u8 val)
|
||||
{
|
||||
return regmap_update_bits(tps65910->regmap, reg, mask, val);
|
||||
}
|
||||
|
||||
#endif /* __LINUX_MFD_TPS65910_H */
|
||||
|
||||
@@ -290,6 +290,12 @@ static inline int regulator_set_voltage(struct regulator *regulator,
|
||||
}
|
||||
|
||||
static inline int regulator_get_voltage(struct regulator *regulator)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int regulator_is_supported_voltage(struct regulator *regulator,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@ enum regulator_status {
|
||||
REGULATOR_STATUS_NORMAL,
|
||||
REGULATOR_STATUS_IDLE,
|
||||
REGULATOR_STATUS_STANDBY,
|
||||
/* in case that any other status doesn't apply */
|
||||
REGULATOR_STATUS_UNDEFINED,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -67,6 +69,8 @@ enum regulator_status {
|
||||
*
|
||||
* @enable_time: Time taken for the regulator voltage output voltage to
|
||||
* stabilise after being enabled, in microseconds.
|
||||
* @set_ramp_delay: Set the ramp delay for the regulator. The driver should
|
||||
* select ramp delay equal to or less than(closest) ramp_delay.
|
||||
* @set_voltage_time_sel: Time taken for the regulator voltage output voltage
|
||||
* to stabilise after being set to a new value, in microseconds.
|
||||
* The function provides the from and to voltage selector, the
|
||||
@@ -113,6 +117,7 @@ struct regulator_ops {
|
||||
|
||||
/* Time taken to enable or set voltage on the regulator */
|
||||
int (*enable_time) (struct regulator_dev *);
|
||||
int (*set_ramp_delay) (struct regulator_dev *, int ramp_delay);
|
||||
int (*set_voltage_time_sel) (struct regulator_dev *,
|
||||
unsigned int old_selector,
|
||||
unsigned int new_selector);
|
||||
@@ -170,11 +175,15 @@ enum regulator_type {
|
||||
*
|
||||
* @min_uV: Voltage given by the lowest selector (if linear mapping)
|
||||
* @uV_step: Voltage increase with each selector (if linear mapping)
|
||||
* @ramp_delay: Time to settle down after voltage change (unit: uV/us)
|
||||
* @volt_table: Voltage mapping table (if table based mapping)
|
||||
*
|
||||
* @vsel_reg: Register for selector when using regulator_regmap_X_voltage_
|
||||
* @vsel_mask: Mask for register bitfield used for selector
|
||||
* @enable_reg: Register for control when using regmap enable/disable ops
|
||||
* @enable_mask: Mask for control when using regmap enable/disable ops
|
||||
*
|
||||
* @enable_time: Time taken for initial enable of regulator (in uS).
|
||||
*/
|
||||
struct regulator_desc {
|
||||
const char *name;
|
||||
@@ -188,11 +197,16 @@ struct regulator_desc {
|
||||
|
||||
unsigned int min_uV;
|
||||
unsigned int uV_step;
|
||||
unsigned int ramp_delay;
|
||||
|
||||
const unsigned int *volt_table;
|
||||
|
||||
unsigned int vsel_reg;
|
||||
unsigned int vsel_mask;
|
||||
unsigned int enable_reg;
|
||||
unsigned int enable_mask;
|
||||
|
||||
unsigned int enable_time;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -208,6 +222,9 @@ struct regulator_desc {
|
||||
* @of_node: OpenFirmware node to parse for device tree bindings (may be
|
||||
* NULL).
|
||||
* @regmap: regmap to use for core regmap helpers
|
||||
* @ena_gpio: GPIO controlling regulator enable.
|
||||
* @ena_gpio_invert: Sense for GPIO enable control.
|
||||
* @ena_gpio_flags: Flags to use when calling gpio_request_one()
|
||||
*/
|
||||
struct regulator_config {
|
||||
struct device *dev;
|
||||
@@ -215,6 +232,10 @@ struct regulator_config {
|
||||
void *driver_data;
|
||||
struct device_node *of_node;
|
||||
struct regmap *regmap;
|
||||
|
||||
int ena_gpio;
|
||||
unsigned int ena_gpio_invert:1;
|
||||
unsigned int ena_gpio_flags;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -253,6 +274,10 @@ struct regulator_dev {
|
||||
void *reg_data; /* regulator_dev data */
|
||||
|
||||
struct dentry *debugfs;
|
||||
|
||||
int ena_gpio;
|
||||
unsigned int ena_gpio_invert:1;
|
||||
unsigned int ena_gpio_state:1;
|
||||
};
|
||||
|
||||
struct regulator_dev *
|
||||
@@ -271,6 +296,8 @@ int regulator_mode_to_status(unsigned int);
|
||||
|
||||
int regulator_list_voltage_linear(struct regulator_dev *rdev,
|
||||
unsigned int selector);
|
||||
int regulator_list_voltage_table(struct regulator_dev *rdev,
|
||||
unsigned int selector);
|
||||
int regulator_map_voltage_linear(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV);
|
||||
int regulator_map_voltage_iterate(struct regulator_dev *rdev,
|
||||
@@ -280,6 +307,9 @@ int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel);
|
||||
int regulator_is_enabled_regmap(struct regulator_dev *rdev);
|
||||
int regulator_enable_regmap(struct regulator_dev *rdev);
|
||||
int regulator_disable_regmap(struct regulator_dev *rdev);
|
||||
int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
|
||||
unsigned int old_selector,
|
||||
unsigned int new_selector);
|
||||
|
||||
void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data);
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ struct regulator_init_data;
|
||||
/**
|
||||
* struct fixed_voltage_config - fixed_voltage_config structure
|
||||
* @supply_name: Name of the regulator supply
|
||||
* @input_supply: Name of the input regulator supply
|
||||
* @microvolts: Output voltage of regulator
|
||||
* @gpio: GPIO to use for enable control
|
||||
* set to -EINVAL if not used
|
||||
@@ -46,6 +47,7 @@ struct regulator_init_data;
|
||||
*/
|
||||
struct fixed_voltage_config {
|
||||
const char *supply_name;
|
||||
const char *input_supply;
|
||||
int microvolts;
|
||||
int gpio;
|
||||
unsigned startup_delay;
|
||||
@@ -58,14 +60,17 @@ struct fixed_voltage_config {
|
||||
struct regulator_consumer_supply;
|
||||
|
||||
#if IS_ENABLED(CONFIG_REGULATOR)
|
||||
struct platform_device *regulator_register_fixed(int id,
|
||||
struct regulator_consumer_supply *supplies, int num_supplies);
|
||||
struct platform_device *regulator_register_always_on(int id, const char *name,
|
||||
struct regulator_consumer_supply *supplies, int num_supplies, int uv);
|
||||
#else
|
||||
static inline struct platform_device *regulator_register_fixed(int id,
|
||||
struct regulator_consumer_supply *supplies, int num_supplies)
|
||||
static inline struct platform_device *regulator_register_always_on(int id, const char *name,
|
||||
struct regulator_consumer_supply *supplies, int num_supplies, int uv)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define regulator_register_fixed(id, s, ns) regulator_register_always_on(id, \
|
||||
"fixed-dummy", s, ns, 0)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2012 Texas Instruments
|
||||
*
|
||||
* Author: Milo(Woogyom) 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LP872X_REGULATOR_H__
|
||||
#define __LP872X_REGULATOR_H__
|
||||
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#define LP872X_MAX_REGULATORS 9
|
||||
|
||||
enum lp872x_regulator_id {
|
||||
LP8720_ID_BASE,
|
||||
LP8720_ID_LDO1 = LP8720_ID_BASE,
|
||||
LP8720_ID_LDO2,
|
||||
LP8720_ID_LDO3,
|
||||
LP8720_ID_LDO4,
|
||||
LP8720_ID_LDO5,
|
||||
LP8720_ID_BUCK,
|
||||
|
||||
LP8725_ID_BASE,
|
||||
LP8725_ID_LDO1 = LP8725_ID_BASE,
|
||||
LP8725_ID_LDO2,
|
||||
LP8725_ID_LDO3,
|
||||
LP8725_ID_LDO4,
|
||||
LP8725_ID_LDO5,
|
||||
LP8725_ID_LILO1,
|
||||
LP8725_ID_LILO2,
|
||||
LP8725_ID_BUCK1,
|
||||
LP8725_ID_BUCK2,
|
||||
|
||||
LP872X_ID_MAX,
|
||||
};
|
||||
|
||||
enum lp872x_dvs_state {
|
||||
DVS_LOW = GPIOF_OUT_INIT_LOW,
|
||||
DVS_HIGH = GPIOF_OUT_INIT_HIGH,
|
||||
};
|
||||
|
||||
enum lp872x_dvs_sel {
|
||||
SEL_V1,
|
||||
SEL_V2,
|
||||
};
|
||||
|
||||
/**
|
||||
* lp872x_dvs
|
||||
* @gpio : gpio pin number for dvs control
|
||||
* @vsel : dvs selector for buck v1 or buck v2 register
|
||||
* @init_state : initial dvs pin state
|
||||
*/
|
||||
struct lp872x_dvs {
|
||||
int gpio;
|
||||
enum lp872x_dvs_sel vsel;
|
||||
enum lp872x_dvs_state init_state;
|
||||
};
|
||||
|
||||
/**
|
||||
* lp872x_regdata
|
||||
* @id : regulator id
|
||||
* @init_data : init data for each regulator
|
||||
*/
|
||||
struct lp872x_regulator_data {
|
||||
enum lp872x_regulator_id id;
|
||||
struct regulator_init_data *init_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* lp872x_platform_data
|
||||
* @general_config : the value of LP872X_GENERAL_CFG register
|
||||
* @update_config : if LP872X_GENERAL_CFG register is updated, set true
|
||||
* @regulator_data : platform regulator id and init data
|
||||
* @dvs : dvs data for buck voltage control
|
||||
*/
|
||||
struct lp872x_platform_data {
|
||||
u8 general_config;
|
||||
bool update_config;
|
||||
struct lp872x_regulator_data regulator_data[LP872X_MAX_REGULATORS];
|
||||
struct lp872x_dvs *dvs;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -92,6 +92,7 @@ struct regulator_state {
|
||||
* mode.
|
||||
* @initial_state: Suspend state to set by default.
|
||||
* @initial_mode: Mode to set at startup.
|
||||
* @ramp_delay: Time to settle down after voltage change (unit: uV/us)
|
||||
*/
|
||||
struct regulation_constraints {
|
||||
|
||||
@@ -125,6 +126,8 @@ struct regulation_constraints {
|
||||
/* mode to set on startup */
|
||||
unsigned int initial_mode;
|
||||
|
||||
unsigned int ramp_delay;
|
||||
|
||||
/* constraint flags */
|
||||
unsigned always_on:1; /* regulator never off when system is on */
|
||||
unsigned boot_on:1; /* bootloader/firmware enabled regulator */
|
||||
|
||||
Reference in New Issue
Block a user