regulator: Updates for 3.6

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.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iQIcBAABAgAGBQJQDEjqAAoJEBus8iNuMP3dZcYQAI251d4Y7gZdbKJ1E8eSmZty
 TNuILxnISaIBUlRkFRjnKziWqRfRbkkoDq7eQTBOuomXqDppeXwo1taaoJJMt/O0
 3qsxANDpwo86zWBCrotZHRwlY6z2w+NWrXC0uE/Tk8tIKXQ4vSuNM3+7XOO9AVKS
 fs3jrv8CfI5Qw9Y4a1g45YR+tWGLnJZKYeI+oHJgryHJbSy0o1mqytg3zVt4/fnv
 mIS4/tpdLmSOXlXacE7GsR+W0AWKy1Z4Sdf+lfqugNJtOheU5aR8R+9HAIMtM8j3
 FA5ALYib+EsKoqP6AxPD4mpow0hsC+t6qIyQCz66KIbKkFBGrGnx31X6HyF1ERrL
 qb6LD7y5aQyx6Pniy5q4vNHwoPvMhqcHL72Tu7XSyhoCs+7Hi38h37tnCMCxIrCe
 v/aKa20vUfj66qBUc58sgDcmytbjG2fkjUlBBRE1b6byc9VBh5xNli3s53IFlG2R
 Bd46knJjYky3KOy5B7O+dFQH2QPhzK8RnpPJWnBU/Cut1upFGDpi+g5XpS/UQxyA
 XF2fUPyt5BkYtNleFL/qorBEnDg6xfPiMVXjlS+Bv6iQp13waAvlYGtI18JFj1HW
 yhZrVnHuzniT/FJWRB0MioEG+ZHryIXTRelA+WPqI/rJziqeeYLLSZYixYLlvqCV
 ZzvvhEqx9FXNzdzDMh4G
 =Nv8m
 -----END PGP SIGNATURE-----

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:
Linus Torvalds 2012-07-22 13:05:23 -07:00
commit 4d460fd3ab
67 changed files with 5525 additions and 2651 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -206,62 +206,74 @@ db8500-prcmu-regulators {
// 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_sia_mmdsp_ret_reg: db8500_sia_mmdsp_ret {
// 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 @@ ab8500-regulators {
// 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 @@ ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
// 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 @@ ab8500_ldo_aux2_reg: ab8500_ldo_aux2 {
// 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 @@ ab8500_ldo_aux3_reg: ab8500_ldo_aux3 {
// 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";
};
};

View File

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

View File

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

View File

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

View File

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

View File

@ -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(&reg->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 = &regulator_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 = &regulator_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 = &regulator_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 = &regulator_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 = &regulator_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 = &regulator_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 = &regulator_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 = &regulator_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,
},
};

View File

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

View File

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

View File

@ -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(&reg->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(&reg->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(&reg->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;

View File

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

View File

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

View File

@ -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(&regulator_list_mutex);
list_for_each_entry(rdev, &regulator_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(&regulator_list_mutex);
return regulator;
}
}
mutex_unlock(&rdev->mutex);
}
mutex_unlock(&regulator_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(&regulator->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(&regulator->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, &regulator->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, &regulator->dev_attr);
attr_name_err:
kfree(regulator->dev_attr.attr.name);
overflow_err:
list_del(&regulator->list);
kfree(regulator);
@ -1181,7 +1134,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
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, &regulator->dev_attr);
kfree(regulator->dev_attr.attr.name);
}
kfree(regulator->supply_name);
list_del(&regulator->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 @@ regulator_register(const struct regulator_desc *regulator_desc,
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(&regulator_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(&regulator_list_mutex);
/* If we have a full configuration then disable any regulators

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

943
drivers/regulator/lp872x.c Normal file
View File

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

View File

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

View File

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

View File

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

View File

@ -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(&regulators[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");

View File

@ -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(&regulator, &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;
}

View File

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

View File

@ -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, &reg, &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, &reg, &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, &reg,
&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 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
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 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
max8998_get_voltage_register(rdev,
&reg, &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;

View File

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

View File

@ -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 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev,
}
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,
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

363
drivers/regulator/s2mps11.c Normal file
View File

@ -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(&regulators[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");

View File

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

View File

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

View File

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

View File

@ -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 @@ static int tps65023_dcdc_set_voltage_sel(struct regulator_dev *dev,
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,
},

View File

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

View File

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

View File

@ -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 = &regulator_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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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