diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-22 13:05:23 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-22 13:05:23 -0700 | 
| commit | 4d460fd3abf9a14e21d55ab9b67b6c58e26398eb (patch) | |
| tree | 601bded16bf110f72d2c9c04d121325387440a6a | |
| parent | 7cd58b0a3b33ca9e1f1dd15b30c708ef77ba6d3e (diff) | |
| parent | 3384fb98845dc014770caa224d61a2effd258ca5 (diff) | |
| download | olio-linux-3.10-4d460fd3abf9a14e21d55ab9b67b6c58e26398eb.tar.xz olio-linux-3.10-4d460fd3abf9a14e21d55ab9b67b6c58e26398eb.zip  | |
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
  ...
67 files changed, 5519 insertions, 2645 deletions
diff --git a/Documentation/devicetree/bindings/mfd/tps65910.txt b/Documentation/devicetree/bindings/mfd/tps65910.txt index 645f5eaadb3..d2802d4717b 100644 --- a/Documentation/devicetree/bindings/mfd/tps65910.txt +++ b/Documentation/devicetree/bindings/mfd/tps65910.txt @@ -17,18 +17,46 @@ Required properties:    device need to be present. The definition for each of these nodes is defined    using the standard binding for regulators found at    Documentation/devicetree/bindings/regulator/regulator.txt. +  The regulator is matched with the regulator-compatible. -  The valid names for regulators are: +  The valid regulator-compatible values are:    tps65910: vrtc, vio, vdd1, vdd2, vdd3, vdig1, vdig2, vpll, vdac, vaux1,              vaux2, vaux33, vmmc    tps65911: vrtc, vio, vdd1, vdd3, vddctrl, ldo1, ldo2, ldo3, ldo4, ldo5,              ldo6, ldo7, ldo8 +- xxx-supply: Input voltage supply regulator. +  These entries are require if regulators are enabled for a device. Missing of these +  properties can cause the regulator registration fails. +  If some of input supply is powered through battery or always-on supply then +  also it is require to have these parameters with proper node handle of always +  on power supply. +  tps65910: +	vcc1-supply: VDD1 input. +	vcc2-supply: VDD2 input. +	vcc3-supply: VAUX33 and VMMC input. +	vcc4-supply: VAUX1 and VAUX2 input. +	vcc5-supply: VPLL and VDAC input. +	vcc6-supply: VDIG1 and VDIG2 input. +	vcc7-supply: VRTC input. +	vccio-supply: VIO input. +  tps65911: +	vcc1-supply: VDD1 input. +	vcc2-supply: VDD2 input. +	vcc3-supply: LDO6, LDO7 and LDO8 input. +	vcc4-supply: LDO5 input. +	vcc5-supply: LDO3 and LDO4 input. +	vcc6-supply: LDO1 and LDO2 input. +	vcc7-supply: VRTC input. +	vccio-supply: VIO input. +  Optional properties:  - ti,vmbch-threshold: (tps65911) main battery charged threshold    comparator. (see VMBCH_VSEL in TPS65910 datasheet)  - ti,vmbch2-threshold: (tps65911) main battery discharged threshold    comparator. (see VMBCH_VSEL in TPS65910 datasheet) +- ti,en-ck32k-xtal: enable external 32-kHz crystal oscillator (see CK32K_CTRL +  in TPS6591X datasheet)  - ti,en-gpio-sleep: enable sleep control for gpios    There should be 9 entries here, one for each gpio. @@ -56,74 +84,110 @@ Example:  		ti,en-gpio-sleep = <0 0 1 0 0 0 0 0 0>; +		vcc1-supply = <®_parent>; +		vcc2-supply = <&some_reg>; +		vcc3-supply = <...>; +		vcc4-supply = <...>; +		vcc5-supply = <...>; +		vcc6-supply = <...>; +		vcc7-supply = <...>; +		vccio-supply = <...>; +  		regulators { -			vdd1_reg: vdd1 { +			#address-cells = <1>; +			#size-cells = <0>; + +			vdd1_reg: regulator@0 { +				regulator-compatible = "vdd1"; +				reg = <0>;  				regulator-min-microvolt = < 600000>;  				regulator-max-microvolt = <1500000>;  				regulator-always-on;  				regulator-boot-on;  				ti,regulator-ext-sleep-control = <0>;  			}; -			vdd2_reg: vdd2 { +			vdd2_reg: regulator@1 { +				regulator-compatible = "vdd2"; +				reg = <1>;  				regulator-min-microvolt = < 600000>;  				regulator-max-microvolt = <1500000>;  				regulator-always-on;  				regulator-boot-on;  				ti,regulator-ext-sleep-control = <4>;  			}; -			vddctrl_reg: vddctrl { +			vddctrl_reg: regulator@2 { +				regulator-compatible = "vddctrl"; +				reg = <2>;  				regulator-min-microvolt = < 600000>;  				regulator-max-microvolt = <1400000>;  				regulator-always-on;  				regulator-boot-on;  				ti,regulator-ext-sleep-control = <0>;  			}; -			vio_reg: vio { +			vio_reg: regulator@3 { +				regulator-compatible = "vio"; +				reg = <3>;  				regulator-min-microvolt = <1500000>;  				regulator-max-microvolt = <1800000>;  				regulator-always-on;  				regulator-boot-on;  				ti,regulator-ext-sleep-control = <1>;  			}; -			ldo1_reg: ldo1 { +			ldo1_reg: regulator@4 { +				regulator-compatible = "ldo1"; +				reg = <4>;  				regulator-min-microvolt = <1000000>;  				regulator-max-microvolt = <3300000>;  				ti,regulator-ext-sleep-control = <0>;  			}; -			ldo2_reg: ldo2 { +			ldo2_reg: regulator@5 { +				regulator-compatible = "ldo2"; +				reg = <5>;  				regulator-min-microvolt = <1050000>;  				regulator-max-microvolt = <1050000>;  				ti,regulator-ext-sleep-control = <0>;  			}; -			ldo3_reg: ldo3 { +			ldo3_reg: regulator@6 { +				regulator-compatible = "ldo3"; +				reg = <6>;  				regulator-min-microvolt = <1000000>;  				regulator-max-microvolt = <3300000>;  				ti,regulator-ext-sleep-control = <0>;  			}; -			ldo4_reg: ldo4 { +			ldo4_reg: regulator@7 { +				regulator-compatible = "ldo4"; +				reg = <7>;  				regulator-min-microvolt = <1000000>;  				regulator-max-microvolt = <3300000>;  				regulator-always-on;  				ti,regulator-ext-sleep-control = <0>;  			}; -			ldo5_reg: ldo5 { +			ldo5_reg: regulator@8 { +				regulator-compatible = "ldo5"; +				reg = <8>;  				regulator-min-microvolt = <1000000>;  				regulator-max-microvolt = <3300000>;  				ti,regulator-ext-sleep-control = <0>;  			}; -			ldo6_reg: ldo6 { +			ldo6_reg: regulator@9 { +				regulator-compatible = "ldo6"; +				reg = <9>;  				regulator-min-microvolt = <1200000>;  				regulator-max-microvolt = <1200000>;  				ti,regulator-ext-sleep-control = <0>;  			}; -			ldo7_reg: ldo7 { +			ldo7_reg: regulator@10 { +				regulator-compatible = "ldo7"; +				reg = <10>;  				regulator-min-microvolt = <1200000>;  				regulator-max-microvolt = <1200000>;  				regulator-always-on;  				regulator-boot-on;  				ti,regulator-ext-sleep-control = <1>;  			}; -			ldo8_reg: ldo8 { +			ldo8_reg: regulator@11 { +				regulator-compatible = "ldo8"; +				reg = <11>;  				regulator-min-microvolt = <1000000>;  				regulator-max-microvolt = <3300000>;  				regulator-always-on; diff --git a/Documentation/devicetree/bindings/regulator/fixed-regulator.txt b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt index 2f5b6b1ba15..4fae41d5479 100644 --- a/Documentation/devicetree/bindings/regulator/fixed-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt @@ -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>;  	}; diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt index 5b7a408acda..66ece3f87bb 100644 --- a/Documentation/devicetree/bindings/regulator/regulator.txt +++ b/Documentation/devicetree/bindings/regulator/regulator.txt @@ -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: diff --git a/Documentation/devicetree/bindings/regulator/tps65217.txt b/Documentation/devicetree/bindings/regulator/tps65217.txt new file mode 100644 index 00000000000..0487e9675ba --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/tps65217.txt @@ -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; +			}; +		}; +	}; diff --git a/Documentation/devicetree/bindings/regulator/tps6586x.txt b/Documentation/devicetree/bindings/regulator/tps6586x.txt index 0fcabaa3baa..d156e1b5db1 100644 --- a/Documentation/devicetree/bindings/regulator/tps6586x.txt +++ b/Documentation/devicetree/bindings/regulator/tps6586x.txt @@ -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>;  			}; diff --git a/Documentation/devicetree/bindings/regulator/twl-regulator.txt b/Documentation/devicetree/bindings/regulator/twl-regulator.txt index 0c3395d55ac..658749b90b9 100644 --- a/Documentation/devicetree/bindings/regulator/twl-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/twl-regulator.txt @@ -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 diff --git a/arch/arm/boot/dts/db8500.dtsi b/arch/arm/boot/dts/db8500.dtsi index 4ad5160018c..ec2be92b270 100644 --- a/arch/arm/boot/dts/db8500.dtsi +++ b/arch/arm/boot/dts/db8500.dtsi @@ -206,62 +206,74 @@  				// DB8500_REGULATOR_VAPE  				db8500_vape_reg: db8500_vape { +					regulator-compatible = "db8500_vape";  					regulator-name = "db8500-vape";  					regulator-always-on;  				};  				// DB8500_REGULATOR_VARM  				db8500_varm_reg: db8500_varm { +					regulator-compatible = "db8500_varm";  					regulator-name = "db8500-varm";  				};  				// DB8500_REGULATOR_VMODEM  				db8500_vmodem_reg: db8500_vmodem { +					regulator-compatible = "db8500_vmodem";  					regulator-name = "db8500-vmodem";  				};  				// DB8500_REGULATOR_VPLL  				db8500_vpll_reg: db8500_vpll { +					regulator-compatible = "db8500_vpll";  					regulator-name = "db8500-vpll";  				};  				// DB8500_REGULATOR_VSMPS1  				db8500_vsmps1_reg: db8500_vsmps1 { +					regulator-compatible = "db8500_vsmps1";  					regulator-name = "db8500-vsmps1";  				};  				// DB8500_REGULATOR_VSMPS2  				db8500_vsmps2_reg: db8500_vsmps2 { +					regulator-compatible = "db8500_vsmps2";  					regulator-name = "db8500-vsmps2";  				};  				// DB8500_REGULATOR_VSMPS3  				db8500_vsmps3_reg: db8500_vsmps3 { +					regulator-compatible = "db8500_vsmps3";  					regulator-name = "db8500-vsmps3";  				};  				// DB8500_REGULATOR_VRF1  				db8500_vrf1_reg: db8500_vrf1 { +					regulator-compatible = "db8500_vrf1";  					regulator-name = "db8500-vrf1";  				};  				// DB8500_REGULATOR_SWITCH_SVAMMDSP  				db8500_sva_mmdsp_reg: db8500_sva_mmdsp { +					regulator-compatible = "db8500_sva_mmdsp";  					regulator-name = "db8500-sva-mmdsp";  				};  				// DB8500_REGULATOR_SWITCH_SVAMMDSPRET  				db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret { +					regulator-compatible = "db8500_sva_mmdsp_ret";  					regulator-name = "db8500-sva-mmdsp-ret";  				};  				// DB8500_REGULATOR_SWITCH_SVAPIPE  				db8500_sva_pipe_reg: db8500_sva_pipe { +					regulator-compatible = "db8500_sva_pipe";  					regulator-name = "db8500_sva_pipe";  				};  				// DB8500_REGULATOR_SWITCH_SIAMMDSP  				db8500_sia_mmdsp_reg: db8500_sia_mmdsp { +					regulator-compatible = "db8500_sia_mmdsp";  					regulator-name = "db8500_sia_mmdsp";  				}; @@ -272,38 +284,45 @@  				// DB8500_REGULATOR_SWITCH_SIAPIPE  				db8500_sia_pipe_reg: db8500_sia_pipe { +					regulator-compatible = "db8500_sia_pipe";  					regulator-name = "db8500-sia-pipe";  				};  				// DB8500_REGULATOR_SWITCH_SGA  				db8500_sga_reg: db8500_sga { +					regulator-compatible = "db8500_sga";  					regulator-name = "db8500-sga";  					vin-supply = <&db8500_vape_reg>;  				};  				// DB8500_REGULATOR_SWITCH_B2R2_MCDE  				db8500_b2r2_mcde_reg: db8500_b2r2_mcde { +					regulator-compatible = "db8500_b2r2_mcde";  					regulator-name = "db8500-b2r2-mcde";  					vin-supply = <&db8500_vape_reg>;  				};  				// DB8500_REGULATOR_SWITCH_ESRAM12  				db8500_esram12_reg: db8500_esram12 { +					regulator-compatible = "db8500_esram12";  					regulator-name = "db8500-esram12";  				};  				// DB8500_REGULATOR_SWITCH_ESRAM12RET  				db8500_esram12_ret_reg: db8500_esram12_ret { +					regulator-compatible = "db8500_esram12_ret";  					regulator-name = "db8500-esram12-ret";  				};  				// DB8500_REGULATOR_SWITCH_ESRAM34  				db8500_esram34_reg: db8500_esram34 { +					regulator-compatible = "db8500_esram34";  					regulator-name = "db8500-esram34";  				};  				// DB8500_REGULATOR_SWITCH_ESRAM34RET  				db8500_esram34_ret_reg: db8500_esram34_ret { +					regulator-compatible = "db8500_esram34_ret";  					regulator-name = "db8500-esram34-ret";  				};  			}; @@ -318,6 +337,7 @@  					// supplies to the display/camera  					ab8500_ldo_aux1_reg: ab8500_ldo_aux1 { +						regulator-compatible = "ab8500_ldo_aux1";  						regulator-name = "V-DISPLAY";  						regulator-min-microvolt = <2500000>;  						regulator-max-microvolt = <2900000>; @@ -328,6 +348,7 @@  					// supplies to the on-board eMMC  					ab8500_ldo_aux2_reg: ab8500_ldo_aux2 { +						regulator-compatible = "ab8500_ldo_aux2";  						regulator-name = "V-eMMC1";  						regulator-min-microvolt = <1100000>;  						regulator-max-microvolt = <3300000>; @@ -335,6 +356,7 @@  					// supply for VAUX3; SDcard slots  					ab8500_ldo_aux3_reg: ab8500_ldo_aux3 { +						regulator-compatible = "ab8500_ldo_aux3";  						regulator-name = "V-MMC-SD";  						regulator-min-microvolt = <1100000>;  						regulator-max-microvolt = <3300000>; @@ -342,41 +364,49 @@  					// supply for v-intcore12; VINTCORE12 LDO  					ab8500_ldo_initcore_reg: ab8500_ldo_initcore { +						regulator-compatible = "ab8500_ldo_initcore";  						regulator-name = "V-INTCORE";  					};  					// supply for tvout; gpadc; TVOUT LDO  					ab8500_ldo_tvout_reg: ab8500_ldo_tvout { +						regulator-compatible = "ab8500_ldo_tvout";  						regulator-name = "V-TVOUT";  					};  					// supply for ab8500-usb; USB LDO  					ab8500_ldo_usb_reg: ab8500_ldo_usb { +						regulator-compatible = "ab8500_ldo_usb";  						regulator-name = "dummy";  					};  					// supply for ab8500-vaudio; VAUDIO LDO  					ab8500_ldo_audio_reg: ab8500_ldo_audio { +						regulator-compatible = "ab8500_ldo_audio";  						regulator-name = "V-AUD";  					};  					// supply for v-anamic1 VAMic1-LDO  					ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 { +						regulator-compatible = "ab8500_ldo_anamic1";  						regulator-name = "V-AMIC1";  					};  					// supply for v-amic2; VAMIC2 LDO; reuse constants for AMIC1  					ab8500_ldo_amamic2_reg: ab8500_ldo_amamic2 { +						regulator-compatible = "ab8500_ldo_amamic2";  						regulator-name = "V-AMIC2";  					};  					// supply for v-dmic; VDMIC LDO  					ab8500_ldo_dmic_reg: ab8500_ldo_dmic { +						regulator-compatible = "ab8500_ldo_dmic";  						regulator-name = "V-DMIC";  					};  					// supply for U8500 CSI/DSI; VANA LDO  					ab8500_ldo_ana_reg: ab8500_ldo_ana { +						regulator-compatible = "ab8500_ldo_ana";  						regulator-name = "V-CSI/DSI";  					};  				}; diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index db194e433c0..61c097a98f5 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -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, diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index c86b8864e41..f34c3be6c9f 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -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 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 977fd46909a..3342615cf25 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -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 diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index 06776ca945f..6f45bfd22e8 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -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[] = { diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 03f4d9c604e..182b553059c 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -43,20 +43,12 @@   * @dev: handle to the device   * @plfdata: AB3100 platform data passed in at probe time   * @regreg: regulator register number in the AB3100 - * @fixed_voltage: a fixed voltage for this regulator, if this - *          0 the voltages array is used instead. - * @typ_voltages: an array of available typical voltages for - *          this regulator - * @voltages_len: length of the array of available voltages   */  struct ab3100_regulator {  	struct regulator_dev *rdev;  	struct device *dev;  	struct ab3100_platform_data *plfdata;  	u8 regreg; -	int fixed_voltage; -	int const *typ_voltages; -	u8 voltages_len;  };  /* The order in which registers are initialized */ @@ -80,7 +72,7 @@ static const u8 ab3100_reg_init_order[AB3100_NUM_REGULATORS+2] = {  #define LDO_C_VOLTAGE 2650000  #define LDO_D_VOLTAGE 2650000 -static const int ldo_e_buck_typ_voltages[] = { +static const unsigned int ldo_e_buck_typ_voltages[] = {  	1800000,  	1400000,  	1300000, @@ -90,7 +82,7 @@ static const int ldo_e_buck_typ_voltages[] = {  	900000,  }; -static const int ldo_f_typ_voltages[] = { +static const unsigned int ldo_f_typ_voltages[] = {  	1800000,  	1400000,  	1300000, @@ -101,21 +93,21 @@ static const int ldo_f_typ_voltages[] = {  	2650000,  }; -static const int ldo_g_typ_voltages[] = { +static const unsigned int ldo_g_typ_voltages[] = {  	2850000,  	2750000,  	1800000,  	1500000,  }; -static const int ldo_h_typ_voltages[] = { +static const unsigned int ldo_h_typ_voltages[] = {  	2750000,  	1800000,  	1500000,  	1200000,  }; -static const int ldo_k_typ_voltages[] = { +static const unsigned int ldo_k_typ_voltages[] = {  	2750000,  	1800000,  }; @@ -126,40 +118,27 @@ static struct ab3100_regulator  ab3100_regulators[AB3100_NUM_REGULATORS] = {  	{  		.regreg = AB3100_LDO_A, -		.fixed_voltage = LDO_A_VOLTAGE,  	},  	{  		.regreg = AB3100_LDO_C, -		.fixed_voltage = LDO_C_VOLTAGE,  	},  	{  		.regreg = AB3100_LDO_D, -		.fixed_voltage = LDO_D_VOLTAGE,  	},  	{  		.regreg = AB3100_LDO_E, -		.typ_voltages = ldo_e_buck_typ_voltages, -		.voltages_len = ARRAY_SIZE(ldo_e_buck_typ_voltages),  	},  	{  		.regreg = AB3100_LDO_F, -		.typ_voltages = ldo_f_typ_voltages, -		.voltages_len = ARRAY_SIZE(ldo_f_typ_voltages),  	},  	{  		.regreg = AB3100_LDO_G, -		.typ_voltages = ldo_g_typ_voltages, -		.voltages_len = ARRAY_SIZE(ldo_g_typ_voltages),  	},  	{  		.regreg = AB3100_LDO_H, -		.typ_voltages = ldo_h_typ_voltages, -		.voltages_len = ARRAY_SIZE(ldo_h_typ_voltages),  	},  	{  		.regreg = AB3100_LDO_K, -		.typ_voltages = ldo_k_typ_voltages, -		.voltages_len = ARRAY_SIZE(ldo_k_typ_voltages),  	},  	{  		.regreg = AB3100_LDO_EXT, @@ -167,8 +146,6 @@ ab3100_regulators[AB3100_NUM_REGULATORS] = {  	},  	{  		.regreg = AB3100_BUCK, -		.typ_voltages = ldo_e_buck_typ_voltages, -		.voltages_len = ARRAY_SIZE(ldo_e_buck_typ_voltages),  	},  }; @@ -178,7 +155,7 @@ ab3100_regulators[AB3100_NUM_REGULATORS] = {   */  static int ab3100_enable_regulator(struct regulator_dev *reg)  { -	struct ab3100_regulator *abreg = reg->reg_data; +	struct ab3100_regulator *abreg = rdev_get_drvdata(reg);  	int err;  	u8 regval; @@ -209,7 +186,7 @@ static int ab3100_enable_regulator(struct regulator_dev *reg)  static int ab3100_disable_regulator(struct regulator_dev *reg)  { -	struct ab3100_regulator *abreg = reg->reg_data; +	struct ab3100_regulator *abreg = rdev_get_drvdata(reg);  	int err;  	u8 regval; @@ -242,7 +219,7 @@ static int ab3100_disable_regulator(struct regulator_dev *reg)  static int ab3100_is_enabled_regulator(struct regulator_dev *reg)  { -	struct ab3100_regulator *abreg = reg->reg_data; +	struct ab3100_regulator *abreg = rdev_get_drvdata(reg);  	u8 regval;  	int err; @@ -257,26 +234,12 @@ static int ab3100_is_enabled_regulator(struct regulator_dev *reg)  	return regval & AB3100_REG_ON_MASK;  } -static int ab3100_list_voltage_regulator(struct regulator_dev *reg, -					 unsigned selector) -{ -	struct ab3100_regulator *abreg = reg->reg_data; - -	if (selector >= abreg->voltages_len) -		return -EINVAL; -	return abreg->typ_voltages[selector]; -} -  static int ab3100_get_voltage_regulator(struct regulator_dev *reg)  { -	struct ab3100_regulator *abreg = reg->reg_data; +	struct ab3100_regulator *abreg = rdev_get_drvdata(reg);  	u8 regval;  	int err; -	/* Return the voltage for fixed regulators immediately */ -	if (abreg->fixed_voltage) -		return abreg->fixed_voltage; -  	/*  	 * For variable types, read out setting and index into  	 * supplied voltage list. @@ -294,20 +257,20 @@ static int ab3100_get_voltage_regulator(struct regulator_dev *reg)  	regval &= 0xE0;  	regval >>= 5; -	if (regval >= abreg->voltages_len) { +	if (regval >= reg->desc->n_voltages) {  		dev_err(®->dev,  			"regulator register %02x contains an illegal voltage setting\n",  			abreg->regreg);  		return -EINVAL;  	} -	return abreg->typ_voltages[regval]; +	return reg->desc->volt_table[regval];  }  static int ab3100_set_voltage_regulator_sel(struct regulator_dev *reg,  					    unsigned selector)  { -	struct ab3100_regulator *abreg = reg->reg_data; +	struct ab3100_regulator *abreg = rdev_get_drvdata(reg);  	u8 regval;  	int err; @@ -336,7 +299,7 @@ static int ab3100_set_voltage_regulator_sel(struct regulator_dev *reg,  static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg,  						int uV)  { -	struct ab3100_regulator *abreg = reg->reg_data; +	struct ab3100_regulator *abreg = rdev_get_drvdata(reg);  	u8 regval;  	int err;  	int bestindex; @@ -379,42 +342,22 @@ static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg,   */  static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg)  { -	struct ab3100_regulator *abreg = reg->reg_data; +	struct ab3100_regulator *abreg = rdev_get_drvdata(reg);  	return abreg->plfdata->external_voltage;  } -static int ab3100_enable_time_regulator(struct regulator_dev *reg) +static int ab3100_get_fixed_voltage_regulator(struct regulator_dev *reg)  { -	struct ab3100_regulator *abreg = reg->reg_data; - -	/* Per-regulator power on delay from spec */ -	switch (abreg->regreg) { -	case AB3100_LDO_A: /* Fallthrough */ -	case AB3100_LDO_C: /* Fallthrough */ -	case AB3100_LDO_D: /* Fallthrough */ -	case AB3100_LDO_E: /* Fallthrough */ -	case AB3100_LDO_H: /* Fallthrough */ -	case AB3100_LDO_K: -		return 200; -	case AB3100_LDO_F: -		return 600; -	case AB3100_LDO_G: -		return 400; -	case AB3100_BUCK: -		return 1000; -	default: -		break; -	} -	return 0; +	return reg->desc->min_uV;  }  static struct regulator_ops regulator_ops_fixed = { +	.list_voltage = regulator_list_voltage_linear,  	.enable      = ab3100_enable_regulator,  	.disable     = ab3100_disable_regulator,  	.is_enabled  = ab3100_is_enabled_regulator, -	.get_voltage = ab3100_get_voltage_regulator, -	.enable_time = ab3100_enable_time_regulator, +	.get_voltage = ab3100_get_fixed_voltage_regulator,  };  static struct regulator_ops regulator_ops_variable = { @@ -423,8 +366,7 @@ static struct regulator_ops regulator_ops_variable = {  	.is_enabled  = ab3100_is_enabled_regulator,  	.get_voltage = ab3100_get_voltage_regulator,  	.set_voltage_sel = ab3100_set_voltage_regulator_sel, -	.list_voltage = ab3100_list_voltage_regulator, -	.enable_time = ab3100_enable_time_regulator, +	.list_voltage = regulator_list_voltage_table,  };  static struct regulator_ops regulator_ops_variable_sleepable = { @@ -434,8 +376,7 @@ static struct regulator_ops regulator_ops_variable_sleepable = {  	.get_voltage = ab3100_get_voltage_regulator,  	.set_voltage_sel = ab3100_set_voltage_regulator_sel,  	.set_suspend_voltage = ab3100_set_suspend_voltage_regulator, -	.list_voltage = ab3100_list_voltage_regulator, -	.enable_time = ab3100_enable_time_regulator, +	.list_voltage = regulator_list_voltage_table,  };  /* @@ -457,62 +398,81 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {  		.name = "LDO_A",  		.id   = AB3100_LDO_A,  		.ops  = ®ulator_ops_fixed, +		.n_voltages = 1,  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE, +		.min_uV = LDO_A_VOLTAGE, +		.enable_time = 200,  	},  	{  		.name = "LDO_C",  		.id   = AB3100_LDO_C,  		.ops  = ®ulator_ops_fixed, +		.n_voltages = 1,  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE, +		.min_uV = LDO_C_VOLTAGE, +		.enable_time = 200,  	},  	{  		.name = "LDO_D",  		.id   = AB3100_LDO_D,  		.ops  = ®ulator_ops_fixed, +		.n_voltages = 1,  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE, +		.min_uV = LDO_D_VOLTAGE, +		.enable_time = 200,  	},  	{  		.name = "LDO_E",  		.id   = AB3100_LDO_E,  		.ops  = ®ulator_ops_variable_sleepable,  		.n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages), +		.volt_table = ldo_e_buck_typ_voltages,  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE, +		.enable_time = 200,  	},  	{  		.name = "LDO_F",  		.id   = AB3100_LDO_F,  		.ops  = ®ulator_ops_variable,  		.n_voltages = ARRAY_SIZE(ldo_f_typ_voltages), +		.volt_table = ldo_f_typ_voltages,  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE, +		.enable_time = 600,  	},  	{  		.name = "LDO_G",  		.id   = AB3100_LDO_G,  		.ops  = ®ulator_ops_variable,  		.n_voltages = ARRAY_SIZE(ldo_g_typ_voltages), +		.volt_table = ldo_g_typ_voltages,  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE, +		.enable_time = 400,  	},  	{  		.name = "LDO_H",  		.id   = AB3100_LDO_H,  		.ops  = ®ulator_ops_variable,  		.n_voltages = ARRAY_SIZE(ldo_h_typ_voltages), +		.volt_table = ldo_h_typ_voltages,  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE, +		.enable_time = 200,  	},  	{  		.name = "LDO_K",  		.id   = AB3100_LDO_K,  		.ops  = ®ulator_ops_variable,  		.n_voltages = ARRAY_SIZE(ldo_k_typ_voltages), +		.volt_table = ldo_k_typ_voltages,  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE, +		.enable_time = 200,  	},  	{  		.name = "LDO_EXT", @@ -528,6 +488,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {  		.n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages),  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE, +		.enable_time = 1000,  	},  }; diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index a739f5ca936..13d424fc1c1 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -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;  		}  	} diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index 46d05f38baf..f123f7e3b75 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c @@ -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, diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index e82e7eaac0f..e9c2085f9df 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c @@ -43,33 +43,15 @@ struct anatop_regulator {  	struct regulator_init_data *initdata;  }; -static int anatop_set_voltage(struct regulator_dev *reg, int min_uV, -				  int max_uV, unsigned *selector) +static int anatop_set_voltage_sel(struct regulator_dev *reg, unsigned selector)  {  	struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); -	u32 val, sel, mask; -	int uv; - -	uv = min_uV; -	dev_dbg(®->dev, "%s: uv %d, min %d, max %d\n", __func__, -		uv, anatop_reg->min_voltage, -		anatop_reg->max_voltage); - -	if (uv < anatop_reg->min_voltage) { -		if (max_uV > anatop_reg->min_voltage) -			uv = anatop_reg->min_voltage; -		else -			return -EINVAL; -	} +	u32 val, mask;  	if (!anatop_reg->control_reg)  		return -ENOTSUPP; -	sel = DIV_ROUND_UP(uv - anatop_reg->min_voltage, 25000); -	if (sel * 25000 + anatop_reg->min_voltage > anatop_reg->max_voltage) -		return -EINVAL; -	val = anatop_reg->min_bit_val + sel; -	*selector = sel; +	val = anatop_reg->min_bit_val + selector;  	dev_dbg(®->dev, "%s: calculated val %d\n", __func__, val);  	mask = ((1 << anatop_reg->vol_bit_width) - 1) <<  		anatop_reg->vol_bit_shift; @@ -94,21 +76,11 @@ static int anatop_get_voltage_sel(struct regulator_dev *reg)  	return val - anatop_reg->min_bit_val;  } -static int anatop_list_voltage(struct regulator_dev *reg, unsigned selector) -{ -	struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); -	int uv; - -	uv = anatop_reg->min_voltage + selector * 25000; -	dev_dbg(®->dev, "vddio = %d, selector = %u\n", uv, selector); - -	return uv; -} -  static struct regulator_ops anatop_rops = { -	.set_voltage     = anatop_set_voltage, +	.set_voltage_sel = anatop_set_voltage_sel,  	.get_voltage_sel = anatop_get_voltage_sel, -	.list_voltage    = anatop_list_voltage, +	.list_voltage = regulator_list_voltage_linear, +	.map_voltage = regulator_map_voltage_linear,  };  static int __devinit anatop_regulator_probe(struct platform_device *pdev) @@ -176,6 +148,8 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev)  	rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage)  		/ 25000 + 1; +	rdesc->min_uV = sreg->min_voltage; +	rdesc->uV_step = 25000;  	config.dev = &pdev->dev;  	config.init_data = initdata; diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c new file mode 100644 index 00000000000..c8f95c07adb --- /dev/null +++ b/drivers/regulator/arizona-ldo1.c @@ -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"); diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c new file mode 100644 index 00000000000..450a069aa9b --- /dev/null +++ b/drivers/regulator/arizona-micsupp.c @@ -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"); diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 8b4b3829d9e..2e31dffbefe 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -23,6 +23,7 @@  #include <linux/mutex.h>  #include <linux/suspend.h>  #include <linux/delay.h> +#include <linux/gpio.h>  #include <linux/of.h>  #include <linux/regmap.h>  #include <linux/regulator/of_regulator.h> @@ -108,28 +109,6 @@ static const char *rdev_get_name(struct regulator_dev *rdev)  		return "";  } -/* gets the regulator for a given consumer device */ -static struct regulator *get_device_regulator(struct device *dev) -{ -	struct regulator *regulator = NULL; -	struct regulator_dev *rdev; - -	mutex_lock(®ulator_list_mutex); -	list_for_each_entry(rdev, ®ulator_list, list) { -		mutex_lock(&rdev->mutex); -		list_for_each_entry(regulator, &rdev->consumer_list, list) { -			if (regulator->dev == dev) { -				mutex_unlock(&rdev->mutex); -				mutex_unlock(®ulator_list_mutex); -				return regulator; -			} -		} -		mutex_unlock(&rdev->mutex); -	} -	mutex_unlock(®ulator_list_mutex); -	return NULL; -} -  /**   * of_get_regulator - get a regulator device node based on supply name   * @dev: Device pointer for the consumer (of regulator) device @@ -303,18 +282,6 @@ static int regulator_check_drms(struct regulator_dev *rdev)  	return 0;  } -static ssize_t device_requested_uA_show(struct device *dev, -			     struct device_attribute *attr, char *buf) -{ -	struct regulator *regulator; - -	regulator = get_device_regulator(dev); -	if (regulator == NULL) -		return 0; - -	return sprintf(buf, "%d\n", regulator->uA_load); -} -  static ssize_t regulator_uV_show(struct device *dev,  				struct device_attribute *attr, char *buf)  { @@ -427,6 +394,9 @@ static ssize_t regulator_status_show(struct device *dev,  	case REGULATOR_STATUS_STANDBY:  		label = "standby";  		break; +	case REGULATOR_STATUS_UNDEFINED: +		label = "undefined"; +		break;  	default:  		return -ERANGE;  	} @@ -967,6 +937,14 @@ static int set_machine_constraints(struct regulator_dev *rdev,  		}  	} +	if (rdev->constraints->ramp_delay && ops->set_ramp_delay) { +		ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); +		if (ret < 0) { +			rdev_err(rdev, "failed to set ramp_delay\n"); +			goto out; +		} +	} +  	print_constraints(rdev);  	return 0;  out: @@ -1097,48 +1075,29 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,  	list_add(®ulator->list, &rdev->consumer_list);  	if (dev) { -		/* create a 'requested_microamps_name' sysfs entry */ -		size = scnprintf(buf, REG_STR_SIZE, -				 "microamps_requested_%s-%s", -				 dev_name(dev), supply_name); -		if (size >= REG_STR_SIZE) -			goto overflow_err; -  		regulator->dev = dev; -		sysfs_attr_init(®ulator->dev_attr.attr); -		regulator->dev_attr.attr.name = kstrdup(buf, GFP_KERNEL); -		if (regulator->dev_attr.attr.name == NULL) -			goto attr_name_err; -		regulator->dev_attr.attr.mode = 0444; -		regulator->dev_attr.show = device_requested_uA_show; -		err = device_create_file(dev, ®ulator->dev_attr); -		if (err < 0) { -			rdev_warn(rdev, "could not add regulator_dev requested microamps sysfs entry\n"); -			goto attr_name_err; -		} - -		/* also add a link to the device sysfs entry */ +		/* Add a link to the device sysfs entry */  		size = scnprintf(buf, REG_STR_SIZE, "%s-%s",  				 dev->kobj.name, supply_name);  		if (size >= REG_STR_SIZE) -			goto attr_err; +			goto overflow_err;  		regulator->supply_name = kstrdup(buf, GFP_KERNEL);  		if (regulator->supply_name == NULL) -			goto attr_err; +			goto overflow_err;  		err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj,  					buf);  		if (err) {  			rdev_warn(rdev, "could not add device link %s err %d\n",  				  dev->kobj.name, err); -			goto link_name_err; +			/* non-fatal */  		}  	} else {  		regulator->supply_name = kstrdup(supply_name, GFP_KERNEL);  		if (regulator->supply_name == NULL) -			goto attr_err; +			goto overflow_err;  	}  	regulator->debugfs = debugfs_create_dir(regulator->supply_name, @@ -1165,12 +1124,6 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,  	mutex_unlock(&rdev->mutex);  	return regulator; -link_name_err: -	kfree(regulator->supply_name); -attr_err: -	device_remove_file(regulator->dev, ®ulator->dev_attr); -attr_name_err: -	kfree(regulator->dev_attr.attr.name);  overflow_err:  	list_del(®ulator->list);  	kfree(regulator); @@ -1181,7 +1134,7 @@ overflow_err:  static int _regulator_get_enable_time(struct regulator_dev *rdev)  {  	if (!rdev->desc->ops->enable_time) -		return 0; +		return rdev->desc->enable_time;  	return rdev->desc->ops->enable_time(rdev);  } @@ -1420,11 +1373,8 @@ void regulator_put(struct regulator *regulator)  	debugfs_remove_recursive(regulator->debugfs);  	/* remove any sysfs entries */ -	if (regulator->dev) { +	if (regulator->dev)  		sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); -		device_remove_file(regulator->dev, ®ulator->dev_attr); -		kfree(regulator->dev_attr.attr.name); -	}  	kfree(regulator->supply_name);  	list_del(®ulator->list);  	kfree(regulator); @@ -1459,19 +1409,61 @@ void devm_regulator_put(struct regulator *regulator)  {  	int rc; -	rc = devres_destroy(regulator->dev, devm_regulator_release, +	rc = devres_release(regulator->dev, devm_regulator_release,  			    devm_regulator_match, regulator); -	if (rc == 0) -		regulator_put(regulator); -	else +	if (rc != 0)  		WARN_ON(rc);  }  EXPORT_SYMBOL_GPL(devm_regulator_put); +static int _regulator_do_enable(struct regulator_dev *rdev) +{ +	int ret, delay; + +	/* Query before enabling in case configuration dependent.  */ +	ret = _regulator_get_enable_time(rdev); +	if (ret >= 0) { +		delay = ret; +	} else { +		rdev_warn(rdev, "enable_time() failed: %d\n", ret); +		delay = 0; +	} + +	trace_regulator_enable(rdev_get_name(rdev)); + +	if (rdev->ena_gpio) { +		gpio_set_value_cansleep(rdev->ena_gpio, +					!rdev->ena_gpio_invert); +		rdev->ena_gpio_state = 1; +	} else if (rdev->desc->ops->enable) { +		ret = rdev->desc->ops->enable(rdev); +		if (ret < 0) +			return ret; +	} else { +		return -EINVAL; +	} + +	/* Allow the regulator to ramp; it would be useful to extend +	 * this for bulk operations so that the regulators can ramp +	 * together.  */ +	trace_regulator_enable_delay(rdev_get_name(rdev)); + +	if (delay >= 1000) { +		mdelay(delay / 1000); +		udelay(delay % 1000); +	} else if (delay) { +		udelay(delay); +	} + +	trace_regulator_enable_complete(rdev_get_name(rdev)); + +	return 0; +} +  /* locks held by regulator_enable() */  static int _regulator_enable(struct regulator_dev *rdev)  { -	int ret, delay; +	int ret;  	/* check voltage and requested load before enabling */  	if (rdev->constraints && @@ -1485,40 +1477,10 @@ static int _regulator_enable(struct regulator_dev *rdev)  			if (!_regulator_can_change_status(rdev))  				return -EPERM; -			if (!rdev->desc->ops->enable) -				return -EINVAL; - -			/* Query before enabling in case configuration -			 * dependent.  */ -			ret = _regulator_get_enable_time(rdev); -			if (ret >= 0) { -				delay = ret; -			} else { -				rdev_warn(rdev, "enable_time() failed: %d\n", -					   ret); -				delay = 0; -			} - -			trace_regulator_enable(rdev_get_name(rdev)); - -			/* Allow the regulator to ramp; it would be useful -			 * to extend this for bulk operations so that the -			 * regulators can ramp together.  */ -			ret = rdev->desc->ops->enable(rdev); +			ret = _regulator_do_enable(rdev);  			if (ret < 0)  				return ret; -			trace_regulator_enable_delay(rdev_get_name(rdev)); - -			if (delay >= 1000) { -				mdelay(delay / 1000); -				udelay(delay % 1000); -			} else if (delay) { -				udelay(delay); -			} - -			trace_regulator_enable_complete(rdev_get_name(rdev)); -  		} else if (ret < 0) {  			rdev_err(rdev, "is_enabled() failed: %d\n", ret);  			return ret; @@ -1567,6 +1529,30 @@ int regulator_enable(struct regulator *regulator)  }  EXPORT_SYMBOL_GPL(regulator_enable); +static int _regulator_do_disable(struct regulator_dev *rdev) +{ +	int ret; + +	trace_regulator_disable(rdev_get_name(rdev)); + +	if (rdev->ena_gpio) { +		gpio_set_value_cansleep(rdev->ena_gpio, +					rdev->ena_gpio_invert); +		rdev->ena_gpio_state = 0; + +	} else if (rdev->desc->ops->disable) { +		ret = rdev->desc->ops->disable(rdev); +		if (ret != 0) +			return ret; +	} + +	trace_regulator_disable_complete(rdev_get_name(rdev)); + +	_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, +			     NULL); +	return 0; +} +  /* locks held by regulator_disable() */  static int _regulator_disable(struct regulator_dev *rdev)  { @@ -1581,20 +1567,12 @@ static int _regulator_disable(struct regulator_dev *rdev)  	    (rdev->constraints && !rdev->constraints->always_on)) {  		/* we are last user */ -		if (_regulator_can_change_status(rdev) && -		    rdev->desc->ops->disable) { -			trace_regulator_disable(rdev_get_name(rdev)); - -			ret = rdev->desc->ops->disable(rdev); +		if (_regulator_can_change_status(rdev)) { +			ret = _regulator_do_disable(rdev);  			if (ret < 0) {  				rdev_err(rdev, "failed to disable\n");  				return ret;  			} - -			trace_regulator_disable_complete(rdev_get_name(rdev)); - -			_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, -					     NULL);  		}  		rdev->use_count = 0; @@ -1812,6 +1790,10 @@ EXPORT_SYMBOL_GPL(regulator_disable_regmap);  static int _regulator_is_enabled(struct regulator_dev *rdev)  { +	/* A GPIO control always takes precedence */ +	if (rdev->ena_gpio) +		return rdev->ena_gpio_state; +  	/* If we don't know then assume that the regulator is always on */  	if (!rdev->desc->ops->is_enabled)  		return 1; @@ -1883,6 +1865,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   * @selector: identify voltage to list @@ -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); + +		if (ret >= 0) { +			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) +		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); +		} 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) { -			selector = ret; -			ret = rdev->desc->ops->set_voltage_sel(rdev, ret); +			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); @@ -2249,6 +2291,46 @@ int regulator_set_voltage_time(struct regulator *regulator,  EXPORT_SYMBOL_GPL(regulator_set_voltage_time);  /** + *regulator_set_voltage_time_sel - get raise/fall time + * @regulator: regulator source + * @old_selector: selector for starting voltage + * @new_selector: selector for target voltage + * + * Provided with the starting and target voltage selectors, this function + * returns time in microseconds required to rise or fall to this new voltage + * + * Drivers providing ramp_delay in regulation_constraints can use this as their + * set_voltage_time_sel() operation. + */ +int regulator_set_voltage_time_sel(struct regulator_dev *rdev, +				   unsigned int old_selector, +				   unsigned int new_selector) +{ +	unsigned int ramp_delay = 0; +	int old_volt, new_volt; + +	if (rdev->constraints->ramp_delay) +		ramp_delay = rdev->constraints->ramp_delay; +	else if (rdev->desc->ramp_delay) +		ramp_delay = rdev->desc->ramp_delay; + +	if (ramp_delay == 0) { +		rdev_warn(rdev, "ramp_delay not set\n"); +		return 0; +	} + +	/* sanity check */ +	if (!rdev->desc->ops->list_voltage) +		return -EINVAL; + +	old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); +	new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); + +	return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); +} +EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); + +/**   * regulator_sync_voltage - re-apply last regulator output voltage   * @regulator: regulator source   * @@ -2628,7 +2710,7 @@ static void _notifier_call_chain(struct regulator_dev *rdev,  				  unsigned long event, void *data)  {  	/* call rdev chain first */ -	blocking_notifier_call_chain(&rdev->notifier, event, NULL); +	blocking_notifier_call_chain(&rdev->notifier, event, data);  }  /** @@ -2909,10 +2991,10 @@ int regulator_mode_to_status(unsigned int mode)  		return REGULATOR_STATUS_NORMAL;  	case REGULATOR_MODE_IDLE:  		return REGULATOR_STATUS_IDLE; -	case REGULATOR_STATUS_STANDBY: +	case REGULATOR_MODE_STANDBY:  		return REGULATOR_STATUS_STANDBY;  	default: -		return 0; +		return REGULATOR_STATUS_UNDEFINED;  	}  }  EXPORT_SYMBOL_GPL(regulator_mode_to_status); @@ -3105,7 +3187,10 @@ regulator_register(const struct regulator_desc *regulator_desc,  	rdev->reg_data = config->driver_data;  	rdev->owner = regulator_desc->owner;  	rdev->desc = regulator_desc; -	rdev->regmap = config->regmap; +	if (config->regmap) +		rdev->regmap = config->regmap; +	else +		rdev->regmap = dev_get_regmap(dev, NULL);  	INIT_LIST_HEAD(&rdev->consumer_list);  	INIT_LIST_HEAD(&rdev->list);  	BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); @@ -3132,6 +3217,26 @@ regulator_register(const struct regulator_desc *regulator_desc,  	dev_set_drvdata(&rdev->dev, rdev); +	if (config->ena_gpio) { +		ret = gpio_request_one(config->ena_gpio, +				       GPIOF_DIR_OUT | config->ena_gpio_flags, +				       rdev_get_name(rdev)); +		if (ret != 0) { +			rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", +				 config->ena_gpio, ret); +			goto clean; +		} + +		rdev->ena_gpio = config->ena_gpio; +		rdev->ena_gpio_invert = config->ena_gpio_invert; + +		if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH) +			rdev->ena_gpio_state = 1; + +		if (rdev->ena_gpio_invert) +			rdev->ena_gpio_state = !rdev->ena_gpio_state; +	} +  	/* set regulator constraints */  	if (init_data)  		constraints = &init_data->constraints; @@ -3200,6 +3305,8 @@ unset_supplies:  scrub:  	if (rdev->supply)  		regulator_put(rdev->supply); +	if (rdev->ena_gpio) +		gpio_free(rdev->ena_gpio);  	kfree(rdev->constraints);  	device_unregister(&rdev->dev);  	/* device core frees rdev */ @@ -3233,6 +3340,8 @@ void regulator_unregister(struct regulator_dev *rdev)  	unset_regulator_supplies(rdev);  	list_del(&rdev->list);  	kfree(rdev->constraints); +	if (rdev->ena_gpio) +		gpio_free(rdev->ena_gpio);  	device_unregister(&rdev->dev);  	mutex_unlock(®ulator_list_mutex);  } @@ -3472,6 +3581,15 @@ static int __init regulator_init_complete(void)  	struct regulation_constraints *c;  	int enabled, ret; +	/* +	 * Since DT doesn't provide an idiomatic mechanism for +	 * enabling full constraints and since it's much more natural +	 * with DT to provide them just assume that a DT enabled +	 * system has full constraints. +	 */ +	if (of_have_populated_dt()) +		has_full_constraints = true; +  	mutex_lock(®ulator_list_mutex);  	/* If we have a full configuration then disable any regulators diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index 1005f5f7e60..36c5b92fe0a 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c @@ -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; diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index 88976d8d44e..903299cf15c 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -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;  			}  		} diff --git a/drivers/regulator/fixed-helper.c b/drivers/regulator/fixed-helper.c index cacd33c9d04..f9d027992aa 100644 --- a/drivers/regulator/fixed-helper.c +++ b/drivers/regulator/fixed-helper.c @@ -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; diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index f09fe7b20e8..185468c4d38 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -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,41 +102,10 @@ of_get_fixed_voltage_config(struct device *dev)  	if (of_find_property(np, "gpio-open-drain", NULL))  		config->gpio_is_open_drain = true; -	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); +	if (of_find_property(np, "vin-supply", NULL)) +		config->input_supply = "vin"; -	return data->startup_delay; +	return config;  }  static int fixed_voltage_get_voltage(struct regulator_dev *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; -	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"); +	drvdata->desc.enable_time = config->startup_delay; -		/* -		 * 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) { +	if (config->input_supply) { +		drvdata->desc.supply_name = kstrdup(config->input_supply, +							GFP_KERNEL); +		if (!drvdata->desc.supply_name) {  			dev_err(&pdev->dev, -			   "Could not obtain regulator enable GPIO %d: %d\n", -							config->gpio, ret); +				"Failed to allocate input supply\n"); +			ret = -ENOMEM;  			goto err_name;  		} +	} -		drvdata->desc.ops = &fixed_voltage_gpio_ops; +	if (config->microvolts) +		drvdata->desc.n_voltages = 1; + +	drvdata->microvolts = config->microvolts; +	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; +		}  	} 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),  	},  }; diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 242851a4c1a..34b67bee932 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -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; diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index 56d273f2560..1d145a07ada 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -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,  	},  }; diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 981bea9cb9d..7c6e3b8ff48 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -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,  	}, diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index de073df7d34..3cdc755d9b2 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -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,  	}, diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c new file mode 100644 index 00000000000..212c38eaba7 --- /dev/null +++ b/drivers/regulator/lp872x.c @@ -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"); diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c new file mode 100644 index 00000000000..6356e821400 --- /dev/null +++ b/drivers/regulator/lp8788-buck.c @@ -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"); diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c new file mode 100644 index 00000000000..d2122e41a96 --- /dev/null +++ b/drivers/regulator/lp8788-ldo.c @@ -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"); diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index b9444ee08da..f67af3c1b96 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -48,6 +48,14 @@ struct max1586_data {  };  /* + * 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 :   *   set V3 to 0.700V + (x & 0x1f) * 0.025V @@ -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; diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c new file mode 100644 index 00000000000..c564af6f05a --- /dev/null +++ b/drivers/regulator/max77686.c @@ -0,0 +1,389 @@ +/* + * max77686.c - Regulator driver for the Maxim 77686 + * + * Copyright (C) 2012 Samsung Electronics + * Chiwoong Byun <woong.byun@smasung.com> + * Jonghwa Lee <jonghwa3.lee@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + * This driver is based on max8997.c + */ + +#include <linux/kernel.h> +#include <linux/bug.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/slab.h> +#include <linux/platform_device.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> +#include <linux/mfd/max77686.h> +#include <linux/mfd/max77686-private.h> + +#define MAX77686_LDO_MINUV	800000 +#define MAX77686_LDO_UVSTEP	50000 +#define MAX77686_LDO_LOW_MINUV	800000 +#define MAX77686_LDO_LOW_UVSTEP	25000 +#define MAX77686_BUCK_MINUV	750000 +#define MAX77686_BUCK_UVSTEP	50000 +#define MAX77686_RAMP_DELAY	100000			/* uV/us */ +#define MAX77686_DVS_RAMP_DELAY	27500			/* uV/us */ +#define MAX77686_DVS_MINUV	600000 +#define MAX77686_DVS_UVSTEP	12500 + +#define MAX77686_OPMODE_SHIFT	6 +#define MAX77686_OPMODE_BUCK234_SHIFT	4 +#define MAX77686_OPMODE_MASK	0x3 + +#define MAX77686_VSEL_MASK	0x3F +#define MAX77686_DVS_VSEL_MASK	0xFF + +#define MAX77686_RAMP_RATE_MASK	0xC0 + +#define MAX77686_REGULATORS	MAX77686_REG_MAX +#define MAX77686_LDOS		26 + +enum max77686_ramp_rate { +	RAMP_RATE_13P75MV, +	RAMP_RATE_27P5MV, +	RAMP_RATE_55MV, +	RAMP_RATE_NO_CTRL,	/* 100mV/us */ +}; + +struct max77686_data { +	struct regulator_dev **rdev; +}; + +static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) +{ +	unsigned int ramp_value = RAMP_RATE_NO_CTRL; + +	switch (ramp_delay) { +	case 1 ... 13750: +		ramp_value = RAMP_RATE_13P75MV; +		break; +	case 13751 ... 27500: +		ramp_value = RAMP_RATE_27P5MV; +		break; +	case 27501 ... 55000: +		ramp_value = RAMP_RATE_55MV; +		break; +	case 55001 ... 100000: +		break; +	default: +		pr_warn("%s: ramp_delay: %d not supported, setting 100000\n", +			rdev->desc->name, ramp_delay); +	} + +	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, +				  MAX77686_RAMP_RATE_MASK, ramp_value << 6); +} + +static struct regulator_ops max77686_ops = { +	.list_voltage		= regulator_list_voltage_linear, +	.map_voltage		= regulator_map_voltage_linear, +	.is_enabled		= regulator_is_enabled_regmap, +	.enable			= regulator_enable_regmap, +	.disable		= regulator_disable_regmap, +	.get_voltage_sel	= regulator_get_voltage_sel_regmap, +	.set_voltage_sel	= regulator_set_voltage_sel_regmap, +	.set_voltage_time_sel	= regulator_set_voltage_time_sel, +}; + +static struct regulator_ops max77686_buck_dvs_ops = { +	.list_voltage		= regulator_list_voltage_linear, +	.map_voltage		= regulator_map_voltage_linear, +	.is_enabled		= regulator_is_enabled_regmap, +	.enable			= regulator_enable_regmap, +	.disable		= regulator_disable_regmap, +	.get_voltage_sel	= regulator_get_voltage_sel_regmap, +	.set_voltage_sel	= regulator_set_voltage_sel_regmap, +	.set_voltage_time_sel	= regulator_set_voltage_time_sel, +	.set_ramp_delay		= max77686_set_ramp_delay, +}; + +#define regulator_desc_ldo(num)		{				\ +	.name		= "LDO"#num,					\ +	.id		= MAX77686_LDO##num,				\ +	.ops		= &max77686_ops,				\ +	.type		= REGULATOR_VOLTAGE,				\ +	.owner		= THIS_MODULE,					\ +	.min_uV		= MAX77686_LDO_MINUV,				\ +	.uV_step	= MAX77686_LDO_UVSTEP,				\ +	.ramp_delay	= MAX77686_RAMP_DELAY,				\ +	.n_voltages	= MAX77686_VSEL_MASK + 1,			\ +	.vsel_reg	= MAX77686_REG_LDO1CTRL1 + num - 1,		\ +	.vsel_mask	= MAX77686_VSEL_MASK,				\ +	.enable_reg	= MAX77686_REG_LDO1CTRL1 + num - 1,		\ +	.enable_mask	= MAX77686_OPMODE_MASK				\ +			<< MAX77686_OPMODE_SHIFT,			\ +} +#define regulator_desc_ldo_low(num)		{			\ +	.name		= "LDO"#num,					\ +	.id		= MAX77686_LDO##num,				\ +	.ops		= &max77686_ops,				\ +	.type		= REGULATOR_VOLTAGE,				\ +	.owner		= THIS_MODULE,					\ +	.min_uV		= MAX77686_LDO_LOW_MINUV,			\ +	.uV_step	= MAX77686_LDO_LOW_UVSTEP,			\ +	.ramp_delay	= MAX77686_RAMP_DELAY,				\ +	.n_voltages	= MAX77686_VSEL_MASK + 1,			\ +	.vsel_reg	= MAX77686_REG_LDO1CTRL1 + num - 1,		\ +	.vsel_mask	= MAX77686_VSEL_MASK,				\ +	.enable_reg	= MAX77686_REG_LDO1CTRL1 + num - 1,		\ +	.enable_mask	= MAX77686_OPMODE_MASK				\ +			<< MAX77686_OPMODE_SHIFT,			\ +} +#define regulator_desc_buck(num)		{			\ +	.name		= "BUCK"#num,					\ +	.id		= MAX77686_BUCK##num,				\ +	.ops		= &max77686_ops,				\ +	.type		= REGULATOR_VOLTAGE,				\ +	.owner		= THIS_MODULE,					\ +	.min_uV		= MAX77686_BUCK_MINUV,				\ +	.uV_step	= MAX77686_BUCK_UVSTEP,				\ +	.ramp_delay	= MAX77686_RAMP_DELAY,				\ +	.n_voltages	= MAX77686_VSEL_MASK + 1,			\ +	.vsel_reg	= MAX77686_REG_BUCK5OUT + (num - 5) * 2,	\ +	.vsel_mask	= MAX77686_VSEL_MASK,				\ +	.enable_reg	= MAX77686_REG_BUCK5CTRL + (num - 5) * 2,	\ +	.enable_mask	= MAX77686_OPMODE_MASK,				\ +} +#define regulator_desc_buck1(num)		{			\ +	.name		= "BUCK"#num,					\ +	.id		= MAX77686_BUCK##num,				\ +	.ops		= &max77686_ops,				\ +	.type		= REGULATOR_VOLTAGE,				\ +	.owner		= THIS_MODULE,					\ +	.min_uV		= MAX77686_BUCK_MINUV,				\ +	.uV_step	= MAX77686_BUCK_UVSTEP,				\ +	.ramp_delay	= MAX77686_RAMP_DELAY,				\ +	.n_voltages	= MAX77686_VSEL_MASK + 1,			\ +	.vsel_reg	= MAX77686_REG_BUCK1OUT,			\ +	.vsel_mask	= MAX77686_VSEL_MASK,				\ +	.enable_reg	= MAX77686_REG_BUCK1CTRL,			\ +	.enable_mask	= MAX77686_OPMODE_MASK,				\ +} +#define regulator_desc_buck_dvs(num)		{			\ +	.name		= "BUCK"#num,					\ +	.id		= MAX77686_BUCK##num,				\ +	.ops		= &max77686_buck_dvs_ops,			\ +	.type		= REGULATOR_VOLTAGE,				\ +	.owner		= THIS_MODULE,					\ +	.min_uV		= MAX77686_DVS_MINUV,				\ +	.uV_step	= MAX77686_DVS_UVSTEP,				\ +	.ramp_delay	= MAX77686_DVS_RAMP_DELAY,			\ +	.n_voltages	= MAX77686_DVS_VSEL_MASK + 1,			\ +	.vsel_reg	= MAX77686_REG_BUCK2DVS1 + (num - 2) * 10,	\ +	.vsel_mask	= MAX77686_DVS_VSEL_MASK,			\ +	.enable_reg	= MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10,	\ +	.enable_mask	= MAX77686_OPMODE_MASK				\ +			<< MAX77686_OPMODE_BUCK234_SHIFT,		\ +} + +static struct regulator_desc regulators[] = { +	regulator_desc_ldo_low(1), +	regulator_desc_ldo_low(2), +	regulator_desc_ldo(3), +	regulator_desc_ldo(4), +	regulator_desc_ldo(5), +	regulator_desc_ldo_low(6), +	regulator_desc_ldo_low(7), +	regulator_desc_ldo_low(8), +	regulator_desc_ldo(9), +	regulator_desc_ldo(10), +	regulator_desc_ldo(11), +	regulator_desc_ldo(12), +	regulator_desc_ldo(13), +	regulator_desc_ldo(14), +	regulator_desc_ldo_low(15), +	regulator_desc_ldo(16), +	regulator_desc_ldo(17), +	regulator_desc_ldo(18), +	regulator_desc_ldo(19), +	regulator_desc_ldo(20), +	regulator_desc_ldo(21), +	regulator_desc_ldo(22), +	regulator_desc_ldo(23), +	regulator_desc_ldo(24), +	regulator_desc_ldo(25), +	regulator_desc_ldo(26), +	regulator_desc_buck1(1), +	regulator_desc_buck_dvs(2), +	regulator_desc_buck_dvs(3), +	regulator_desc_buck_dvs(4), +	regulator_desc_buck(5), +	regulator_desc_buck(6), +	regulator_desc_buck(7), +	regulator_desc_buck(8), +	regulator_desc_buck(9), +}; + +#ifdef CONFIG_OF +static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, +					struct max77686_platform_data *pdata) +{ +	struct device_node *pmic_np, *regulators_np; +	struct max77686_regulator_data *rdata; +	struct of_regulator_match rmatch; +	unsigned int i; + +	pmic_np = iodev->dev->of_node; +	regulators_np = of_find_node_by_name(pmic_np, "voltage-regulators"); +	if (!regulators_np) { +		dev_err(iodev->dev, "could not find regulators sub-node\n"); +		return -EINVAL; +	} + +	pdata->num_regulators = ARRAY_SIZE(regulators); +	rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) * +			     pdata->num_regulators, GFP_KERNEL); +	if (!rdata) { +		dev_err(iodev->dev, +			"could not allocate memory for regulator data\n"); +		return -ENOMEM; +	} + +	for (i = 0; i < pdata->num_regulators; i++) { +		rmatch.name = regulators[i].name; +		rmatch.init_data = NULL; +		rmatch.of_node = NULL; +		of_regulator_match(iodev->dev, regulators_np, &rmatch, 1); +		rdata[i].initdata = rmatch.init_data; +	} + +	pdata->regulators = rdata; + +	return 0; +} +#else +static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, +					struct max77686_platform_data *pdata) +{ +	return 0; +} +#endif /* CONFIG_OF */ + +static __devinit int max77686_pmic_probe(struct platform_device *pdev) +{ +	struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); +	struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev); +	struct regulator_dev **rdev; +	struct max77686_data *max77686; +	int i,  size; +	int ret = 0; +	struct regulator_config config = { }; + +	dev_dbg(&pdev->dev, "%s\n", __func__); + +	if (!pdata) { +		dev_err(&pdev->dev, "no platform data found for regulator\n"); +		return -ENODEV; +	} + +	if (iodev->dev->of_node) { +		ret = max77686_pmic_dt_parse_pdata(iodev, pdata); +		if (ret) +			return ret; +	} + +	if (pdata->num_regulators != MAX77686_REGULATORS) { +		dev_err(&pdev->dev, +			"Invalid initial data for regulator's initialiation\n"); +		return -EINVAL; +	} + +	max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data), +				GFP_KERNEL); +	if (!max77686) +		return -ENOMEM; + +	size = sizeof(struct regulator_dev *) * MAX77686_REGULATORS; +	max77686->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); +	if (!max77686->rdev) +		return -ENOMEM; + +	rdev = max77686->rdev; +	config.dev = &pdev->dev; +	config.regmap = iodev->regmap; +	platform_set_drvdata(pdev, max77686); + +	for (i = 0; i < MAX77686_REGULATORS; i++) { +		config.init_data = pdata->regulators[i].initdata; + +		rdev[i] = regulator_register(®ulators[i], &config); +		if (IS_ERR(rdev[i])) { +			ret = PTR_ERR(rdev[i]); +			dev_err(&pdev->dev, +				"regulator init failed for %d\n", i); +				rdev[i] = NULL; +				goto err; +		} +	} + +	return 0; +err: +	while (--i >= 0) +		regulator_unregister(rdev[i]); +	return ret; +} + +static int __devexit max77686_pmic_remove(struct platform_device *pdev) +{ +	struct max77686_data *max77686 = platform_get_drvdata(pdev); +	struct regulator_dev **rdev = max77686->rdev; +	int i; + +	for (i = 0; i < MAX77686_REGULATORS; i++) +		if (rdev[i]) +			regulator_unregister(rdev[i]); + +	return 0; +} + +static const struct platform_device_id max77686_pmic_id[] = { +	{"max77686-pmic", 0}, +	{ }, +}; +MODULE_DEVICE_TABLE(platform, max77686_pmic_id); + +static struct platform_driver max77686_pmic_driver = { +	.driver = { +		.name = "max77686-pmic", +		.owner = THIS_MODULE, +	}, +	.probe = max77686_pmic_probe, +	.remove = __devexit_p(max77686_pmic_remove), +	.id_table = max77686_pmic_id, +}; + +static int __init max77686_pmic_init(void) +{ +	return platform_driver_register(&max77686_pmic_driver); +} +subsys_initcall(max77686_pmic_init); + +static void __exit max77686_pmic_cleanup(void) +{ +	platform_driver_unregister(&max77686_pmic_driver); +} +module_exit(max77686_pmic_cleanup); + +MODULE_DESCRIPTION("MAXIM 77686 Regulator Driver"); +MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index 910c9b26d49..355ca7bad9d 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -51,7 +51,6 @@ struct max8952_data {  	bool vid0;  	bool vid1; -	bool en;  };  static int max8952_read_reg(struct max8952_data *max8952, u8 reg) @@ -80,38 +79,6 @@ static int max8952_list_voltage(struct regulator_dev *rdev,  	return (max8952->pdata->dvs_mode[selector] * 10 + 770) * 1000;  } -static int max8952_is_enabled(struct regulator_dev *rdev) -{ -	struct max8952_data *max8952 = rdev_get_drvdata(rdev); -	return max8952->en; -} - -static int max8952_enable(struct regulator_dev *rdev) -{ -	struct max8952_data *max8952 = rdev_get_drvdata(rdev); - -	/* If not valid, assume "ALWAYS_HIGH" */ -	if (gpio_is_valid(max8952->pdata->gpio_en)) -		gpio_set_value(max8952->pdata->gpio_en, 1); - -	max8952->en = true; -	return 0; -} - -static int max8952_disable(struct regulator_dev *rdev) -{ -	struct max8952_data *max8952 = rdev_get_drvdata(rdev); - -	/* If not valid, assume "ALWAYS_HIGH" -> not permitted */ -	if (gpio_is_valid(max8952->pdata->gpio_en)) -		gpio_set_value(max8952->pdata->gpio_en, 0); -	else -		return -EPERM; - -	max8952->en = false; -	return 0; -} -  static int max8952_get_voltage_sel(struct regulator_dev *rdev)  {  	struct max8952_data *max8952 = rdev_get_drvdata(rdev); @@ -146,12 +113,8 @@ static int max8952_set_voltage_sel(struct regulator_dev *rdev,  static struct regulator_ops max8952_ops = {  	.list_voltage		= max8952_list_voltage, -	.is_enabled		= max8952_is_enabled, -	.enable			= max8952_enable, -	.disable		= max8952_disable,  	.get_voltage_sel	= max8952_get_voltage_sel,  	.set_voltage_sel	= max8952_set_voltage_sel, -	.set_suspend_disable	= max8952_disable,  };  static const struct regulator_desc regulator = { @@ -194,6 +157,10 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,  	config.init_data = &pdata->reg_data;  	config.driver_data = max8952; +	config.ena_gpio = pdata->gpio_en; +	if (pdata->reg_data.constraints.boot_on) +		config.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH; +  	max8952->rdev = regulator_register(®ulator, &config);  	if (IS_ERR(max8952->rdev)) { @@ -202,27 +169,9 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,  		return ret;  	} -	max8952->en = !!(pdata->reg_data.constraints.boot_on);  	max8952->vid0 = pdata->default_mode & 0x1;  	max8952->vid1 = (pdata->default_mode >> 1) & 0x1; -	if (gpio_is_valid(pdata->gpio_en)) { -		if (!gpio_request(pdata->gpio_en, "MAX8952 EN")) -			gpio_direction_output(pdata->gpio_en, max8952->en); -		else -			err = 1; -	} else -		err = 2; - -	if (err) { -		dev_info(max8952->dev, "EN gpio invalid: assume that EN" -				"is always High\n"); -		max8952->en = 1; -		pdata->gpio_en = -1; /* Mark invalid */ -	} - -	err = 0; -  	if (gpio_is_valid(pdata->gpio_vid0) &&  			gpio_is_valid(pdata->gpio_vid1)) {  		if (!gpio_request(pdata->gpio_vid0, "MAX8952 VID0")) @@ -308,7 +257,6 @@ static int __devexit max8952_pmic_remove(struct i2c_client *client)  	gpio_free(pdata->gpio_vid0);  	gpio_free(pdata->gpio_vid1); -	gpio_free(pdata->gpio_en);  	return 0;  } diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 704cd49ef37..e39a0c7260d 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -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 */ diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 18bb58b9b96..5dfa920ff0c 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -111,27 +111,6 @@ static const struct voltage_map_desc *ldo_voltage_map[] = {  	&buck4_voltage_map_desc,	/* BUCK4 */  }; -static int max8998_list_voltage(struct regulator_dev *rdev, -				unsigned int selector) -{ -	const struct voltage_map_desc *desc; -	int ldo = rdev_get_id(rdev); -	int val; - -	if (ldo >= ARRAY_SIZE(ldo_voltage_map)) -		return -EINVAL; - -	desc = ldo_voltage_map[ldo]; -	if (desc == NULL) -		return -EINVAL; - -	val = desc->min + desc->step * selector; -	if (val > desc->max) -		return -EINVAL; - -	return val * 1000; -} -  static int max8998_get_enable_register(struct regulator_dev *rdev,  					int *reg, int *shift)  { @@ -297,41 +276,18 @@ static int max8998_get_voltage_sel(struct regulator_dev *rdev)  	return val;  } -static int max8998_set_voltage_ldo(struct regulator_dev *rdev, -				   int min_uV, int max_uV, unsigned *selector) +static int max8998_set_voltage_ldo_sel(struct regulator_dev *rdev, +				       unsigned selector)  {  	struct max8998_data *max8998 = rdev_get_drvdata(rdev);  	struct i2c_client *i2c = max8998->iodev->i2c; -	int min_vol = min_uV / 1000, max_vol = max_uV / 1000; -	const struct voltage_map_desc *desc; -	int ldo = rdev_get_id(rdev); -	int reg, shift = 0, mask, ret, i; - -	if (ldo >= ARRAY_SIZE(ldo_voltage_map)) -		return -EINVAL; - -	desc = ldo_voltage_map[ldo]; -	if (desc == NULL) -		return -EINVAL; - -	if (max_vol < desc->min || min_vol > desc->max) -		return -EINVAL; - -	if (min_vol < desc->min) -		min_vol = desc->min; - -	i = DIV_ROUND_UP(min_vol - desc->min, desc->step); - -	if (desc->min + desc->step*i > max_vol) -		return -EINVAL; - -	*selector = i; +	int reg, shift = 0, mask, ret;  	ret = max8998_get_voltage_register(rdev, ®, &shift, &mask);  	if (ret)  		return ret; -	ret = max8998_update_reg(i2c, reg, i<<shift, mask<<shift); +	ret = max8998_update_reg(i2c, reg, selector<<shift, mask<<shift);  	return ret;  } @@ -347,41 +303,18 @@ static inline void buck2_gpio_set(int gpio, int v)  	gpio_set_value(gpio, v & 0x1);  } -static int max8998_set_voltage_buck(struct regulator_dev *rdev, -				    int min_uV, int max_uV, unsigned *selector) +static int max8998_set_voltage_buck_sel(struct regulator_dev *rdev, +					unsigned selector)  {  	struct max8998_data *max8998 = rdev_get_drvdata(rdev);  	struct max8998_platform_data *pdata =  		dev_get_platdata(max8998->iodev->dev);  	struct i2c_client *i2c = max8998->iodev->i2c; -	int min_vol = min_uV / 1000, max_vol = max_uV / 1000; -	const struct voltage_map_desc *desc;  	int buck = rdev_get_id(rdev);  	int reg, shift = 0, mask, ret; -	int i, j, previous_sel; +	int j, previous_sel;  	static u8 buck1_last_val; -	if (buck >= ARRAY_SIZE(ldo_voltage_map)) -		return -EINVAL; - -	desc = ldo_voltage_map[buck]; - -	if (desc == NULL) -		return -EINVAL; - -	if (max_vol < desc->min || min_vol > desc->max) -		return -EINVAL; - -	if (min_vol < desc->min) -		min_vol = desc->min; - -	i = DIV_ROUND_UP(min_vol - desc->min, desc->step); - -	if (desc->min + desc->step*i > max_vol) -		return -EINVAL; - -	*selector = i; -  	ret = max8998_get_voltage_register(rdev, ®, &shift, &mask);  	if (ret)  		return ret; @@ -390,19 +323,19 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,  	/* Check if voltage needs to be changed */  	/* if previous_voltage equal new voltage, return */ -	if (previous_sel == i) { +	if (previous_sel == selector) {  		dev_dbg(max8998->dev, "No voltage change, old:%d, new:%d\n", -			max8998_list_voltage(rdev, previous_sel), -			max8998_list_voltage(rdev, i)); +			regulator_list_voltage_linear(rdev, previous_sel), +			regulator_list_voltage_linear(rdev, selector));  		return ret;  	}  	switch (buck) {  	case MAX8998_BUCK1:  		dev_dbg(max8998->dev, -			"BUCK1, i:%d, buck1_vol1:%d, buck1_vol2:%d\n" +			"BUCK1, selector:%d, buck1_vol1:%d, buck1_vol2:%d\n"  			"buck1_vol3:%d, buck1_vol4:%d\n", -			i, max8998->buck1_vol[0], max8998->buck1_vol[1], +			selector, max8998->buck1_vol[0], max8998->buck1_vol[1],  			max8998->buck1_vol[2], max8998->buck1_vol[3]);  		if (gpio_is_valid(pdata->buck1_set1) && @@ -411,7 +344,7 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,  			/* check if requested voltage */  			/* value is already defined */  			for (j = 0; j < ARRAY_SIZE(max8998->buck1_vol); j++) { -				if (max8998->buck1_vol[j] == i) { +				if (max8998->buck1_vol[j] == selector) {  					max8998->buck1_idx = j;  					buck1_gpio_set(pdata->buck1_set1,  						       pdata->buck1_set2, j); @@ -426,11 +359,11 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,  			max8998->buck1_idx = (buck1_last_val % 2) + 2;  			dev_dbg(max8998->dev, "max8998->buck1_idx:%d\n",  				max8998->buck1_idx); -			max8998->buck1_vol[max8998->buck1_idx] = i; +			max8998->buck1_vol[max8998->buck1_idx] = selector;  			ret = max8998_get_voltage_register(rdev, ®,  							   &shift,  							   &mask); -			ret = max8998_write_reg(i2c, reg, i); +			ret = max8998_write_reg(i2c, reg, selector);  			buck1_gpio_set(pdata->buck1_set1,  				       pdata->buck1_set2, max8998->buck1_idx);  			buck1_last_val++; @@ -440,20 +373,20 @@ buck1_exit:  				gpio_get_value(pdata->buck1_set2));  			break;  		} else { -			ret = max8998_write_reg(i2c, reg, i); +			ret = max8998_write_reg(i2c, reg, selector);  		}  		break;  	case MAX8998_BUCK2:  		dev_dbg(max8998->dev, -			"BUCK2, i:%d buck2_vol1:%d, buck2_vol2:%d\n" -			, i, max8998->buck2_vol[0], max8998->buck2_vol[1]); +			"BUCK2, selector:%d buck2_vol1:%d, buck2_vol2:%d\n", +			selector, max8998->buck2_vol[0], max8998->buck2_vol[1]);  		if (gpio_is_valid(pdata->buck2_set3)) {  			/* check if requested voltage */  			/* value is already defined */  			for (j = 0; j < ARRAY_SIZE(max8998->buck2_vol); j++) { -				if (max8998->buck2_vol[j] == i) { +				if (max8998->buck2_vol[j] == selector) {  					max8998->buck2_idx = j;  					buck2_gpio_set(pdata->buck2_set3, j);  					goto buck2_exit; @@ -465,20 +398,21 @@ buck1_exit:  			max8998_get_voltage_register(rdev,  					®, &shift, &mask); -			ret = max8998_write_reg(i2c, reg, i); -			max8998->buck2_vol[max8998->buck2_idx] = i; +			ret = max8998_write_reg(i2c, reg, selector); +			max8998->buck2_vol[max8998->buck2_idx] = selector;  			buck2_gpio_set(pdata->buck2_set3, max8998->buck2_idx);  buck2_exit:  			dev_dbg(max8998->dev, "%s: SET3:%d\n", i2c->name,  				gpio_get_value(pdata->buck2_set3));  		} else { -			ret = max8998_write_reg(i2c, reg, i); +			ret = max8998_write_reg(i2c, reg, selector);  		}  		break;  	case MAX8998_BUCK3:  	case MAX8998_BUCK4: -		ret = max8998_update_reg(i2c, reg, i<<shift, mask<<shift); +		ret = max8998_update_reg(i2c, reg, selector<<shift, +					 mask<<shift);  		break;  	} @@ -519,34 +453,30 @@ static int max8998_set_voltage_buck_time_sel(struct regulator_dev *rdev,  }  static struct regulator_ops max8998_ldo_ops = { -	.list_voltage		= max8998_list_voltage, +	.list_voltage		= regulator_list_voltage_linear, +	.map_voltage		= regulator_map_voltage_linear,  	.is_enabled		= max8998_ldo_is_enabled,  	.enable			= max8998_ldo_enable,  	.disable		= max8998_ldo_disable,  	.get_voltage_sel	= max8998_get_voltage_sel, -	.set_voltage		= max8998_set_voltage_ldo, -	.set_suspend_enable	= max8998_ldo_enable, -	.set_suspend_disable	= max8998_ldo_disable, +	.set_voltage_sel	= max8998_set_voltage_ldo_sel,  };  static struct regulator_ops max8998_buck_ops = { -	.list_voltage		= max8998_list_voltage, +	.list_voltage		= regulator_list_voltage_linear, +	.map_voltage		= regulator_map_voltage_linear,  	.is_enabled		= max8998_ldo_is_enabled,  	.enable			= max8998_ldo_enable,  	.disable		= max8998_ldo_disable,  	.get_voltage_sel	= max8998_get_voltage_sel, -	.set_voltage		= max8998_set_voltage_buck, +	.set_voltage_sel	= max8998_set_voltage_buck_sel,  	.set_voltage_time_sel	= max8998_set_voltage_buck_time_sel, -	.set_suspend_enable	= max8998_ldo_enable, -	.set_suspend_disable	= max8998_ldo_disable,  };  static struct regulator_ops max8998_others_ops = {  	.is_enabled		= max8998_ldo_is_enabled,  	.enable			= max8998_ldo_enable,  	.disable		= max8998_ldo_disable, -	.set_suspend_enable	= max8998_ldo_enable, -	.set_suspend_disable	= max8998_ldo_disable,  };  static struct regulator_desc regulators[] = { @@ -860,7 +790,10 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)  		desc = ldo_voltage_map[id];  		if (desc && regulators[index].ops != &max8998_others_ops) {  			int count = (desc->max - desc->min) / desc->step + 1; +  			regulators[index].n_voltages = count; +			regulators[index].min_uV = desc->min * 1000; +			regulators[index].uV_step = desc->step * 1000;  		}  		config.dev = max8998->dev; diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index 7dcdfa283e9..4932e3449fe 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c @@ -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,  }; diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 970a233dbe4..b388b746452 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -150,12 +150,12 @@  #define MC13892_USB1				50  #define MC13892_USB1_VUSBEN			(1<<3) -static const int mc13892_vcoincell[] = { +static const unsigned int mc13892_vcoincell[] = {  	2500000, 2700000, 2800000, 2900000, 3000000, 3100000,  	3200000, 3300000,  }; -static const int mc13892_sw1[] = { +static const unsigned int mc13892_sw1[] = {  	600000,   625000,  650000,  675000,  700000,  725000,  	750000,   775000,  800000,  825000,  850000,  875000,  	900000,   925000,  950000,  975000, 1000000, 1025000, @@ -164,7 +164,7 @@ static const int mc13892_sw1[] = {  	1350000, 1375000  }; -static const int mc13892_sw[] = { +static const unsigned int mc13892_sw[] = {  	600000,   625000,  650000,  675000,  700000,  725000,  	750000,   775000,  800000,  825000,  850000,  875000,  	900000,   925000,  950000,  975000, 1000000, 1025000, @@ -176,65 +176,65 @@ static const int mc13892_sw[] = {  	1800000, 1825000, 1850000, 1875000  }; -static const int mc13892_swbst[] = { +static const unsigned int mc13892_swbst[] = {  	5000000,  }; -static const int mc13892_viohi[] = { +static const unsigned int mc13892_viohi[] = {  	2775000,  }; -static const int mc13892_vpll[] = { +static const unsigned int mc13892_vpll[] = {  	1050000, 1250000, 1650000, 1800000,  }; -static const int mc13892_vdig[] = { +static const unsigned int mc13892_vdig[] = {  	1050000, 1250000, 1650000, 1800000,  }; -static const int mc13892_vsd[] = { +static const unsigned int mc13892_vsd[] = {  	1800000, 2000000, 2600000, 2700000,  	2800000, 2900000, 3000000, 3150000,  }; -static const int mc13892_vusb2[] = { +static const unsigned int mc13892_vusb2[] = {  	2400000, 2600000, 2700000, 2775000,  }; -static const int mc13892_vvideo[] = { +static const unsigned int mc13892_vvideo[] = {  	2700000, 2775000, 2500000, 2600000,  }; -static const int mc13892_vaudio[] = { +static const unsigned int mc13892_vaudio[] = {  	2300000, 2500000, 2775000, 3000000,  }; -static const int mc13892_vcam[] = { +static const unsigned int mc13892_vcam[] = {  	2500000, 2600000, 2750000, 3000000,  }; -static const int mc13892_vgen1[] = { +static const unsigned int mc13892_vgen1[] = {  	1200000, 1500000, 2775000, 3150000,  }; -static const int mc13892_vgen2[] = { +static const unsigned int mc13892_vgen2[] = {  	1200000, 1500000, 1600000, 1800000,  	2700000, 2800000, 3000000, 3150000,  }; -static const int mc13892_vgen3[] = { +static const unsigned int mc13892_vgen3[] = {  	1800000, 2900000,  }; -static const int mc13892_vusb[] = { +static const unsigned int mc13892_vusb[] = {  	3300000,  }; -static const int mc13892_gpo[] = { +static const unsigned int mc13892_gpo[] = {  	2750000,  }; -static const int mc13892_pwgtdrv[] = { +static const unsigned int mc13892_pwgtdrv[] = {  	5000000,  }; @@ -394,7 +394,7 @@ static struct regulator_ops mc13892_gpo_regulator_ops = {  	.enable = mc13892_gpo_regulator_enable,  	.disable = mc13892_gpo_regulator_disable,  	.is_enabled = mc13892_gpo_regulator_is_enabled, -	.list_voltage = mc13xxx_regulator_list_voltage, +	.list_voltage = regulator_list_voltage_table,  	.set_voltage = mc13xxx_fixed_regulator_set_voltage,  	.get_voltage = mc13xxx_fixed_regulator_get_voltage,  }; @@ -436,7 +436,7 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev,  	u32 valread;  	int ret; -	value = mc13892_regulators[id].voltages[selector]; +	value = rdev->desc->volt_table[selector];  	mc13xxx_lock(priv->mc13xxx);  	ret = mc13xxx_reg_read(priv->mc13xxx, @@ -469,8 +469,7 @@ err:  }  static struct regulator_ops mc13892_sw_regulator_ops = { -	.is_enabled = mc13xxx_sw_regulator_is_enabled, -	.list_voltage = mc13xxx_regulator_list_voltage, +	.list_voltage = regulator_list_voltage_table,  	.set_voltage_sel = mc13892_sw_regulator_set_voltage_sel,  	.get_voltage = mc13892_sw_regulator_get_voltage,  }; diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c index 4fa9704739b..d6eda28ca5d 100644 --- a/drivers/regulator/mc13xxx-regulator-core.c +++ b/drivers/regulator/mc13xxx-regulator-core.c @@ -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)  { diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h index 044aba4d28e..eaff5510b6d 100644 --- a/drivers/regulator/mc13xxx.h +++ b/drivers/regulator/mc13xxx.h @@ -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)	\ diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 56593b75168..3e4106f2bda 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -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; + +			if (strcmp(match->name, regulator_comp)) +				continue; -		match->of_node = child; -		count++; +			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; diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 795f75a6ac3..17d19fbbc49 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -257,8 +257,7 @@ static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode)  	unsigned int reg;  	palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, ®); -	reg &= ~PALMAS_SMPS12_CTRL_STATUS_MASK; -	reg >>= PALMAS_SMPS12_CTRL_STATUS_SHIFT; +	reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;  	switch (mode) {  	case REGULATOR_MODE_NORMAL: @@ -374,11 +373,22 @@ static int palmas_set_voltage_smps_sel(struct regulator_dev *dev,  static int palmas_map_voltage_smps(struct regulator_dev *rdev,  		int min_uV, int max_uV)  { +	struct palmas_pmic *pmic = rdev_get_drvdata(rdev); +	int id = rdev_get_id(rdev);  	int ret, voltage; -	ret = ((min_uV - 500000) / 10000) + 1; -	if (ret < 0) -		return ret; +	if (min_uV == 0) +		return 0; + +	if (pmic->range[id]) { /* RANGE is x2 */ +		if (min_uV < 1000000) +			min_uV = 1000000; +		ret = DIV_ROUND_UP(min_uV - 1000000, 20000) + 1; +	} else {		/* RANGE is x1 */ +		if (min_uV < 500000) +			min_uV = 500000; +		ret = DIV_ROUND_UP(min_uV - 500000, 10000) + 1; +	}  	/* Map back into a voltage to verify we're still in bounds */  	voltage = palmas_list_voltage_smps(rdev, ret); @@ -400,19 +410,14 @@ static struct regulator_ops palmas_ops_smps = {  	.map_voltage		= palmas_map_voltage_smps,  }; -static int palmas_list_voltage_smps10(struct regulator_dev *dev, -					unsigned selector) -{ -	return 3750000 + (selector * 1250000); -} -  static struct regulator_ops palmas_ops_smps10 = {  	.is_enabled		= regulator_is_enabled_regmap,  	.enable			= regulator_enable_regmap,  	.disable		= regulator_disable_regmap,  	.get_voltage_sel	= regulator_get_voltage_sel_regmap,  	.set_voltage_sel	= regulator_set_voltage_sel_regmap, -	.list_voltage		= palmas_list_voltage_smps10, +	.list_voltage		= regulator_list_voltage_linear, +	.map_voltage		= regulator_map_voltage_linear,  };  static int palmas_is_enabled_ldo(struct regulator_dev *dev) @@ -522,7 +527,15 @@ static int palmas_smps_init(struct palmas *palmas, int id,  	if (ret)  		return ret; -	if (id != PALMAS_REG_SMPS10) { +	switch (id) { +	case PALMAS_REG_SMPS10: +		if (reg_init->mode_sleep) { +			reg &= ~PALMAS_SMPS10_CTRL_MODE_SLEEP_MASK; +			reg |= reg_init->mode_sleep << +					PALMAS_SMPS10_CTRL_MODE_SLEEP_SHIFT; +		} +		break; +	default:  		if (reg_init->warm_reset)  			reg |= PALMAS_SMPS12_CTRL_WR_S; @@ -534,14 +547,8 @@ static int palmas_smps_init(struct palmas *palmas, int id,  			reg |= reg_init->mode_sleep <<  					PALMAS_SMPS12_CTRL_MODE_SLEEP_SHIFT;  		} -	} else { -		if (reg_init->mode_sleep) { -			reg &= ~PALMAS_SMPS10_CTRL_MODE_SLEEP_MASK; -			reg |= reg_init->mode_sleep << -					PALMAS_SMPS10_CTRL_MODE_SLEEP_SHIFT; -		} -  	} +  	ret = palmas_smps_write(palmas, addr, reg);  	if (ret)  		return ret; @@ -665,10 +672,8 @@ static __devinit int palmas_probe(struct platform_device *pdev)  		pmic->desc[id].name = palmas_regs_info[id].name;  		pmic->desc[id].id = id; -		if (id != PALMAS_REG_SMPS10) { -			pmic->desc[id].ops = &palmas_ops_smps; -			pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES; -		} else { +		switch (id) { +		case PALMAS_REG_SMPS10:  			pmic->desc[id].n_voltages = PALMAS_SMPS10_NUM_VOLTAGES;  			pmic->desc[id].ops = &palmas_ops_smps10;  			pmic->desc[id].vsel_reg = PALMAS_SMPS10_CTRL; @@ -677,6 +682,12 @@ static __devinit int palmas_probe(struct platform_device *pdev)  					PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,  							PALMAS_SMPS10_STATUS);  			pmic->desc[id].enable_mask = SMPS10_BOOST_EN; +			pmic->desc[id].min_uV = 3750000; +			pmic->desc[id].uV_step = 1250000; +			break; +		default: +			pmic->desc[id].ops = &palmas_ops_smps; +			pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;  		}  		pmic->desc[id].type = REGULATOR_VOLTAGE; diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c index 8211101121f..68777acc099 100644 --- a/drivers/regulator/pcap-regulator.c +++ b/drivers/regulator/pcap-regulator.c @@ -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,			\ diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index 3c9d14c0017..092e5cb848a 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c @@ -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, diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index 1d34e64a130..8bf4e8c9de9 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -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,			\  	},							\  } diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c new file mode 100644 index 00000000000..4669dc9ac74 --- /dev/null +++ b/drivers/regulator/s2mps11.c @@ -0,0 +1,363 @@ +/* + * s2mps11.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd + *              http://www.samsung.com + * + *  This program is free software; you can redistribute  it and/or modify it + *  under  the terms of  the GNU General  Public License as published by the + *  Free Software Foundation;  either version 2 of the  License, or (at your + *  option) any later version. + * + */ + +#include <linux/bug.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/mfd/samsung/core.h> +#include <linux/mfd/samsung/s2mps11.h> + +struct s2mps11_info { +	struct regulator_dev **rdev; + +	int ramp_delay2; +	int ramp_delay34; +	int ramp_delay5; +	int ramp_delay16; +	int ramp_delay7810; +	int ramp_delay9; + +	bool buck6_ramp; +	bool buck2_ramp; +	bool buck3_ramp; +	bool buck4_ramp; +}; + +static int get_ramp_delay(int ramp_delay) +{ +	unsigned char cnt = 0; + +	ramp_delay /= 6; + +	while (true) { +		ramp_delay = ramp_delay >> 1; +		if (ramp_delay == 0) +			break; +		cnt++; +	} +	return cnt; +} + +static struct regulator_ops s2mps11_ldo_ops = { +	.list_voltage		= regulator_list_voltage_linear, +	.map_voltage		= regulator_map_voltage_linear, +	.is_enabled		= regulator_is_enabled_regmap, +	.enable			= regulator_enable_regmap, +	.disable		= regulator_disable_regmap, +	.get_voltage_sel	= regulator_get_voltage_sel_regmap, +	.set_voltage_sel	= regulator_set_voltage_sel_regmap, +	.set_voltage_time_sel	= regulator_set_voltage_time_sel, +}; + +static struct regulator_ops s2mps11_buck_ops = { +	.list_voltage		= regulator_list_voltage_linear, +	.map_voltage		= regulator_map_voltage_linear, +	.is_enabled		= regulator_is_enabled_regmap, +	.enable			= regulator_enable_regmap, +	.disable		= regulator_disable_regmap, +	.get_voltage_sel	= regulator_get_voltage_sel_regmap, +	.set_voltage_sel	= regulator_set_voltage_sel_regmap, +	.set_voltage_time_sel	= regulator_set_voltage_time_sel, +}; + +#define regulator_desc_ldo1(num)	{		\ +	.name		= "LDO"#num,			\ +	.id		= S2MPS11_LDO##num,		\ +	.ops		= &s2mps11_ldo_ops,		\ +	.type		= REGULATOR_VOLTAGE,		\ +	.owner		= THIS_MODULE,			\ +	.min_uV		= S2MPS11_LDO_MIN,		\ +	.uV_step	= S2MPS11_LDO_STEP1,		\ +	.n_voltages	= S2MPS11_LDO_N_VOLTAGES,	\ +	.vsel_reg	= S2MPS11_REG_L1CTRL + num - 1,	\ +	.vsel_mask	= S2MPS11_LDO_VSEL_MASK,	\ +	.enable_reg	= S2MPS11_REG_L1CTRL + num - 1,	\ +	.enable_mask	= S2MPS11_ENABLE_MASK		\ +} +#define regulator_desc_ldo2(num)	{		\ +	.name		= "LDO"#num,			\ +	.id		= S2MPS11_LDO##num,		\ +	.ops		= &s2mps11_ldo_ops,		\ +	.type		= REGULATOR_VOLTAGE,		\ +	.owner		= THIS_MODULE,			\ +	.min_uV		= S2MPS11_LDO_MIN,		\ +	.uV_step	= S2MPS11_LDO_STEP2,		\ +	.n_voltages	= S2MPS11_LDO_N_VOLTAGES,	\ +	.vsel_reg	= S2MPS11_REG_L1CTRL + num - 1,	\ +	.vsel_mask	= S2MPS11_LDO_VSEL_MASK,	\ +	.enable_reg	= S2MPS11_REG_L1CTRL + num - 1,	\ +	.enable_mask	= S2MPS11_ENABLE_MASK		\ +} + +#define regulator_desc_buck1_4(num)	{			\ +	.name		= "BUCK"#num,				\ +	.id		= S2MPS11_BUCK##num,			\ +	.ops		= &s2mps11_buck_ops,			\ +	.type		= REGULATOR_VOLTAGE,			\ +	.owner		= THIS_MODULE,				\ +	.min_uV		= S2MPS11_BUCK_MIN1,			\ +	.uV_step	= S2MPS11_BUCK_STEP1,			\ +	.n_voltages	= S2MPS11_BUCK_N_VOLTAGES,		\ +	.vsel_reg	= S2MPS11_REG_B1CTRL2 + (num - 1) * 2,	\ +	.vsel_mask	= S2MPS11_BUCK_VSEL_MASK,		\ +	.enable_reg	= S2MPS11_REG_B1CTRL1 + (num - 1) * 2,	\ +	.enable_mask	= S2MPS11_ENABLE_MASK			\ +} + +#define regulator_desc_buck5	{				\ +	.name		= "BUCK5",				\ +	.id		= S2MPS11_BUCK5,			\ +	.ops		= &s2mps11_buck_ops,			\ +	.type		= REGULATOR_VOLTAGE,			\ +	.owner		= THIS_MODULE,				\ +	.min_uV		= S2MPS11_BUCK_MIN1,			\ +	.uV_step	= S2MPS11_BUCK_STEP1,			\ +	.n_voltages	= S2MPS11_BUCK_N_VOLTAGES,		\ +	.vsel_reg	= S2MPS11_REG_B5CTRL2,			\ +	.vsel_mask	= S2MPS11_BUCK_VSEL_MASK,		\ +	.enable_reg	= S2MPS11_REG_B5CTRL1,			\ +	.enable_mask	= S2MPS11_ENABLE_MASK			\ +} + +#define regulator_desc_buck6_8(num)	{			\ +	.name		= "BUCK"#num,				\ +	.id		= S2MPS11_BUCK##num,			\ +	.ops		= &s2mps11_buck_ops,			\ +	.type		= REGULATOR_VOLTAGE,			\ +	.owner		= THIS_MODULE,				\ +	.min_uV		= S2MPS11_BUCK_MIN1,			\ +	.uV_step	= S2MPS11_BUCK_STEP1,			\ +	.n_voltages	= S2MPS11_BUCK_N_VOLTAGES,		\ +	.vsel_reg	= S2MPS11_REG_B6CTRL2 + (num - 6) * 2,	\ +	.vsel_mask	= S2MPS11_BUCK_VSEL_MASK,		\ +	.enable_reg	= S2MPS11_REG_B6CTRL1 + (num - 6) * 2,	\ +	.enable_mask	= S2MPS11_ENABLE_MASK			\ +} + +#define regulator_desc_buck9	{				\ +	.name		= "BUCK9",				\ +	.id		= S2MPS11_BUCK9,			\ +	.ops		= &s2mps11_buck_ops,			\ +	.type		= REGULATOR_VOLTAGE,			\ +	.owner		= THIS_MODULE,				\ +	.min_uV		= S2MPS11_BUCK_MIN3,			\ +	.uV_step	= S2MPS11_BUCK_STEP3,			\ +	.n_voltages	= S2MPS11_BUCK_N_VOLTAGES,		\ +	.vsel_reg	= S2MPS11_REG_B9CTRL2,			\ +	.vsel_mask	= S2MPS11_BUCK_VSEL_MASK,		\ +	.enable_reg	= S2MPS11_REG_B9CTRL1,			\ +	.enable_mask	= S2MPS11_ENABLE_MASK			\ +} + +#define regulator_desc_buck10	{				\ +	.name		= "BUCK10",				\ +	.id		= S2MPS11_BUCK10,			\ +	.ops		= &s2mps11_buck_ops,			\ +	.type		= REGULATOR_VOLTAGE,			\ +	.owner		= THIS_MODULE,				\ +	.min_uV		= S2MPS11_BUCK_MIN2,			\ +	.uV_step	= S2MPS11_BUCK_STEP2,			\ +	.n_voltages	= S2MPS11_BUCK_N_VOLTAGES,		\ +	.vsel_reg	= S2MPS11_REG_B9CTRL2,			\ +	.vsel_mask	= S2MPS11_BUCK_VSEL_MASK,		\ +	.enable_reg	= S2MPS11_REG_B9CTRL1,			\ +	.enable_mask	= S2MPS11_ENABLE_MASK			\ +} + +static struct regulator_desc regulators[] = { +	regulator_desc_ldo2(1), +	regulator_desc_ldo1(2), +	regulator_desc_ldo1(3), +	regulator_desc_ldo1(4), +	regulator_desc_ldo1(5), +	regulator_desc_ldo2(6), +	regulator_desc_ldo1(7), +	regulator_desc_ldo1(8), +	regulator_desc_ldo1(9), +	regulator_desc_ldo1(10), +	regulator_desc_ldo2(11), +	regulator_desc_ldo1(12), +	regulator_desc_ldo1(13), +	regulator_desc_ldo1(14), +	regulator_desc_ldo1(15), +	regulator_desc_ldo1(16), +	regulator_desc_ldo1(17), +	regulator_desc_ldo1(18), +	regulator_desc_ldo1(19), +	regulator_desc_ldo1(20), +	regulator_desc_ldo1(21), +	regulator_desc_ldo2(22), +	regulator_desc_ldo2(23), +	regulator_desc_ldo1(24), +	regulator_desc_ldo1(25), +	regulator_desc_ldo1(26), +	regulator_desc_ldo2(27), +	regulator_desc_ldo1(28), +	regulator_desc_ldo1(29), +	regulator_desc_ldo1(30), +	regulator_desc_ldo1(31), +	regulator_desc_ldo1(32), +	regulator_desc_ldo1(33), +	regulator_desc_ldo1(34), +	regulator_desc_ldo1(35), +	regulator_desc_ldo1(36), +	regulator_desc_ldo1(37), +	regulator_desc_ldo1(38), +	regulator_desc_buck1_4(1), +	regulator_desc_buck1_4(2), +	regulator_desc_buck1_4(3), +	regulator_desc_buck1_4(4), +	regulator_desc_buck5, +	regulator_desc_buck6_8(6), +	regulator_desc_buck6_8(7), +	regulator_desc_buck6_8(8), +	regulator_desc_buck9, +	regulator_desc_buck10, +}; + +static __devinit int s2mps11_pmic_probe(struct platform_device *pdev) +{ +	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); +	struct sec_platform_data *pdata = dev_get_platdata(iodev->dev); +	struct regulator_config config = { }; +	struct regulator_dev **rdev; +	struct s2mps11_info *s2mps11; +	int i, ret, size; +	unsigned char ramp_enable, ramp_reg = 0; + +	if (!pdata) { +		dev_err(pdev->dev.parent, "Platform data not supplied\n"); +		return -ENODEV; +	} + +	s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info), +				GFP_KERNEL); +	if (!s2mps11) +		return -ENOMEM; + +	size = sizeof(struct regulator_dev *) * S2MPS11_REGULATOR_MAX; +	s2mps11->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); +	if (!s2mps11->rdev) { +		return -ENOMEM; +	} + +	rdev = s2mps11->rdev; +	platform_set_drvdata(pdev, s2mps11); + +	s2mps11->ramp_delay2 = pdata->buck2_ramp_delay; +	s2mps11->ramp_delay34 = pdata->buck34_ramp_delay; +	s2mps11->ramp_delay5 = pdata->buck5_ramp_delay; +	s2mps11->ramp_delay16 = pdata->buck16_ramp_delay; +	s2mps11->ramp_delay7810 = pdata->buck7810_ramp_delay; +	s2mps11->ramp_delay9 = pdata->buck9_ramp_delay; + +	s2mps11->buck6_ramp = pdata->buck6_ramp_enable; +	s2mps11->buck2_ramp = pdata->buck2_ramp_enable; +	s2mps11->buck3_ramp = pdata->buck3_ramp_enable; +	s2mps11->buck4_ramp = pdata->buck4_ramp_enable; + +	ramp_enable = (s2mps11->buck2_ramp << 3) | (s2mps11->buck3_ramp << 2) | +		(s2mps11->buck4_ramp << 1) | s2mps11->buck6_ramp ; + +	if (ramp_enable) { +		if (s2mps11->buck2_ramp) +			ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) >> 6; +		if (s2mps11->buck3_ramp || s2mps11->buck4_ramp) +			ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) >> 4; +		sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable); +	} + +	ramp_reg &= 0x00; +	ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) >> 6; +	ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) >> 4; +	ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) >> 2; +	ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9); +	sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg); + +	for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) { + +		config.dev = &pdev->dev; +		config.regmap = iodev->regmap; +		config.init_data = pdata->regulators[i].initdata; +		config.driver_data = s2mps11; + +		rdev[i] = regulator_register(®ulators[i], &config); +		if (IS_ERR(rdev[i])) { +			ret = PTR_ERR(rdev[i]); +			dev_err(&pdev->dev, "regulator init failed for %d\n", +				i); +			rdev[i] = NULL; +			goto err; +		} +	} + +	return 0; +err: +	for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) +		if (rdev[i]) +			regulator_unregister(rdev[i]); + +	return ret; +} + +static int __devexit s2mps11_pmic_remove(struct platform_device *pdev) +{ +	struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev); +	struct regulator_dev **rdev = s2mps11->rdev; +	int i; + +	for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) +		if (rdev[i]) +			regulator_unregister(rdev[i]); + +	return 0; +} + +static const struct platform_device_id s2mps11_pmic_id[] = { +	{ "s2mps11-pmic", 0}, +	{ }, +}; +MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id); + +static struct platform_driver s2mps11_pmic_driver = { +	.driver = { +		.name = "s2mps11-pmic", +		.owner = THIS_MODULE, +	}, +	.probe = s2mps11_pmic_probe, +	.remove = __devexit_p(s2mps11_pmic_remove), +	.id_table = s2mps11_pmic_id, +}; + +static int __init s2mps11_pmic_init(void) +{ +	return platform_driver_register(&s2mps11_pmic_driver); +} +subsys_initcall(s2mps11_pmic_init); + +static void __exit s2mps11_pmic_exit(void) +{ +	platform_driver_unregister(&s2mps11_pmic_driver); +} +module_exit(s2mps11_pmic_exit); + +/* Module information */ +MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>"); +MODULE_DESCRIPTION("SAMSUNG S2MPS11 Regulator Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 9caadb48217..102287fa7ec 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -41,6 +41,7 @@ struct s5m8767_info {  	u8 buck3_vol[8];  	u8 buck4_vol[8];  	int buck_gpios[3]; +	int buck_ds[3];  	int buck_gpioindex;  }; @@ -120,27 +121,6 @@ static const struct s5m_voltage_desc *reg_voltage_map[] = {  	[S5M8767_BUCK9] = &buck_voltage_val3,  }; -static int s5m8767_list_voltage(struct regulator_dev *rdev, -				unsigned int selector) -{ -	const struct s5m_voltage_desc *desc; -	int reg_id = rdev_get_id(rdev); -	int val; - -	if (reg_id >= ARRAY_SIZE(reg_voltage_map) || reg_id < 0) -		return -EINVAL; - -	desc = reg_voltage_map[reg_id]; -	if (desc == NULL) -		return -EINVAL; - -	val = desc->min + desc->step * selector; -	if (val > desc->max) -		return -EINVAL; - -	return val; -} -  static unsigned int s5m8767_opmode_reg[][4] = {  	/* {OFF, ON, LOWPOWER, SUSPEND} */  	/* LDO1 ... LDO28 */ @@ -283,17 +263,17 @@ static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg)  		reg = S5M8767_REG_BUCK1CTRL2;  		break;  	case S5M8767_BUCK2: -		reg = S5M8767_REG_BUCK2DVS1; +		reg = S5M8767_REG_BUCK2DVS2;  		if (s5m8767->buck2_gpiodvs)  			reg += s5m8767->buck_gpioindex;  		break;  	case S5M8767_BUCK3: -		reg = S5M8767_REG_BUCK3DVS1; +		reg = S5M8767_REG_BUCK3DVS2;  		if (s5m8767->buck3_gpiodvs)  			reg += s5m8767->buck_gpioindex;  		break;  	case S5M8767_BUCK4: -		reg = S5M8767_REG_BUCK4DVS1; +		reg = S5M8767_REG_BUCK4DVS2;  		if (s5m8767->buck4_gpiodvs)  			reg += s5m8767->buck_gpioindex;  		break; @@ -357,32 +337,34 @@ static int s5m8767_convert_voltage_to_sel(  	return selector;  } -static inline void s5m8767_set_high(struct s5m8767_info *s5m8767) +static inline int s5m8767_set_high(struct s5m8767_info *s5m8767)  {  	int temp_index = s5m8767->buck_gpioindex;  	gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);  	gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);  	gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1); + +	return 0;  } -static inline void s5m8767_set_low(struct s5m8767_info *s5m8767) +static inline int s5m8767_set_low(struct s5m8767_info *s5m8767)  {  	int temp_index = s5m8767->buck_gpioindex;  	gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);  	gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);  	gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1); + +	return 0;  } -static int s5m8767_set_voltage(struct regulator_dev *rdev, -				int min_uV, int max_uV, unsigned *selector) +static int s5m8767_set_voltage_sel(struct regulator_dev *rdev, +				   unsigned selector)  {  	struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); -	const struct s5m_voltage_desc *desc;  	int reg_id = rdev_get_id(rdev); -	int sel, reg, mask, ret = 0, old_index, index = 0; -	u8 val; +	int reg, mask, ret = 0, old_index, index = 0;  	u8 *buck234_vol = NULL;  	switch (reg_id) { @@ -407,15 +389,9 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev,  		return -EINVAL;  	} -	desc = reg_voltage_map[reg_id]; - -	sel = s5m8767_convert_voltage_to_sel(desc, min_uV, max_uV); -	if (sel < 0) -		return sel; -  	/* buck234_vol != NULL means to control buck234 voltage via DVS GPIO */  	if (buck234_vol) { -		while (*buck234_vol != sel) { +		while (*buck234_vol != selector) {  			buck234_vol++;  			index++;  		} @@ -423,22 +399,16 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev,  		s5m8767->buck_gpioindex = index;  		if (index > old_index) -			s5m8767_set_high(s5m8767); +			return s5m8767_set_high(s5m8767);  		else -			s5m8767_set_low(s5m8767); +			return s5m8767_set_low(s5m8767);  	} else {  		ret = s5m8767_get_voltage_register(rdev, ®);  		if (ret)  			return ret; -		s5m_reg_read(s5m8767->iodev, reg, &val); -		val = (val & ~mask) | sel; - -		ret = s5m_reg_write(s5m8767->iodev, reg, val); +		return s5m_reg_update(s5m8767->iodev, reg, selector, mask);  	} - -	*selector = sel; -	return ret;  }  static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev, @@ -458,15 +428,21 @@ static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,  }  static struct regulator_ops s5m8767_ops = { -	.list_voltage		= s5m8767_list_voltage, +	.list_voltage		= regulator_list_voltage_linear,  	.is_enabled		= s5m8767_reg_is_enabled,  	.enable			= s5m8767_reg_enable,  	.disable		= s5m8767_reg_disable,  	.get_voltage_sel	= s5m8767_get_voltage_sel, -	.set_voltage		= s5m8767_set_voltage, +	.set_voltage_sel	= s5m8767_set_voltage_sel,  	.set_voltage_time_sel	= s5m8767_set_voltage_time_sel,  }; +static struct regulator_ops s5m8767_buck78_ops = { +	.is_enabled		= s5m8767_reg_is_enabled, +	.enable			= s5m8767_reg_enable, +	.disable		= s5m8767_reg_disable, +}; +  #define s5m8767_regulator_desc(_name) {		\  	.name		= #_name,		\  	.id		= S5M8767_##_name,	\ @@ -475,6 +451,14 @@ static struct regulator_ops s5m8767_ops = {  	.owner		= THIS_MODULE,		\  } +#define s5m8767_regulator_buck78_desc(_name) {	\ +	.name		= #_name,		\ +	.id		= S5M8767_##_name,	\ +	.ops		= &s5m8767_buck78_ops,	\ +	.type		= REGULATOR_VOLTAGE,	\ +	.owner		= THIS_MODULE,		\ +} +  static struct regulator_desc regulators[] = {  	s5m8767_regulator_desc(LDO1),  	s5m8767_regulator_desc(LDO2), @@ -510,8 +494,8 @@ static struct regulator_desc regulators[] = {  	s5m8767_regulator_desc(BUCK4),  	s5m8767_regulator_desc(BUCK5),  	s5m8767_regulator_desc(BUCK6), -	s5m8767_regulator_desc(BUCK7), -	s5m8767_regulator_desc(BUCK8), +	s5m8767_regulator_buck78_desc(BUCK7), +	s5m8767_regulator_buck78_desc(BUCK8),  	s5m8767_regulator_desc(BUCK9),  }; @@ -522,7 +506,7 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)  	struct regulator_config config = { };  	struct regulator_dev **rdev;  	struct s5m8767_info *s5m8767; -	int i, ret, size; +	int i, ret, size, buck_init;  	if (!pdata) {  		dev_err(pdev->dev.parent, "Platform data not supplied\n"); @@ -573,12 +557,37 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)  	s5m8767->buck_gpios[0] = pdata->buck_gpios[0];  	s5m8767->buck_gpios[1] = pdata->buck_gpios[1];  	s5m8767->buck_gpios[2] = pdata->buck_gpios[2]; +	s5m8767->buck_ds[0] = pdata->buck_ds[0]; +	s5m8767->buck_ds[1] = pdata->buck_ds[1]; +	s5m8767->buck_ds[2] = pdata->buck_ds[2]; +  	s5m8767->ramp_delay = pdata->buck_ramp_delay;  	s5m8767->buck2_ramp = pdata->buck2_ramp_enable;  	s5m8767->buck3_ramp = pdata->buck3_ramp_enable;  	s5m8767->buck4_ramp = pdata->buck4_ramp_enable;  	s5m8767->opmode = pdata->opmode; +	buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2, +						pdata->buck2_init, +						pdata->buck2_init + +						buck_voltage_val2.step); + +	s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK2DVS2, buck_init); + +	buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2, +						pdata->buck3_init, +						pdata->buck3_init + +						buck_voltage_val2.step); + +	s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK3DVS2, buck_init); + +	buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2, +						pdata->buck4_init, +						pdata->buck4_init + +						buck_voltage_val2.step); + +	s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK4DVS2, buck_init); +  	for (i = 0; i < 8; i++) {  		if (s5m8767->buck2_gpiodvs) {  			s5m8767->buck2_vol[i] = @@ -608,48 +617,70 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)  		}  	} -	if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs || -		pdata->buck4_gpiodvs) { -		if (gpio_is_valid(pdata->buck_gpios[0]) && -			gpio_is_valid(pdata->buck_gpios[1]) && -			gpio_is_valid(pdata->buck_gpios[2])) { -			ret = gpio_request(pdata->buck_gpios[0], -						"S5M8767 SET1"); -			if (ret == -EBUSY) -				dev_warn(&pdev->dev, "Duplicated gpio request for SET1\n"); +	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 = gpio_request(pdata->buck_gpios[1], -					   "S5M8767 SET2"); -			if (ret == -EBUSY) -				dev_warn(&pdev->dev, "Duplicated gpio request for SET2\n"); +		ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[1], +					"S5M8767 SET2"); +		if (ret) +			return ret; -			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; +		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; diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c index d840d8440a9..1378409efae 100644 --- a/drivers/regulator/tps6105x-regulator.c +++ b/drivers/regulator/tps6105x-regulator.c @@ -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,  };  /* diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index e534269ed44..68729a7c870 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -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;  } diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 8f1be8586c7..6998d579d07 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -69,10 +69,6 @@  #define TPS65023_REG_CTRL2_DCDC1	BIT(1)  #define TPS65023_REG_CTRL2_DCDC3	BIT(0) -/* LDO_CTRL bitfields */ -#define TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_id)	((ldo_id)*4) -#define TPS65023_LDO_CTRL_LDOx_MASK(ldo_id)	(0x07 << ((ldo_id)*4)) -  /* Number of step-down converters available */  #define TPS65023_NUM_DCDC		3  /* Number of LDO voltage regulators  available */ @@ -91,48 +87,53 @@  #define TPS65023_MAX_REG_ID		TPS65023_LDO_2  /* Supported voltage values for regulators */ -static const u16 VCORE_VSEL_table[] = { -	800, 825, 850, 875, -	900, 925, 950, 975, -	1000, 1025, 1050, 1075, -	1100, 1125, 1150, 1175, -	1200, 1225, 1250, 1275, -	1300, 1325, 1350, 1375, -	1400, 1425, 1450, 1475, -	1500, 1525, 1550, 1600, +static const unsigned int VCORE_VSEL_table[] = { +	800000, 825000, 850000, 875000, +	900000, 925000, 950000, 975000, +	1000000, 1025000, 1050000, 1075000, +	1100000, 1125000, 1150000, 1175000, +	1200000, 1225000, 1250000, 1275000, +	1300000, 1325000, 1350000, 1375000, +	1400000, 1425000, 1450000, 1475000, +	1500000, 1525000, 1550000, 1600000, +}; + +static const unsigned int DCDC_FIXED_3300000_VSEL_table[] = { +	3300000, +}; + +static const unsigned int DCDC_FIXED_1800000_VSEL_table[] = { +	1800000,  };  /* Supported voltage values for LDO regulators for tps65020 */ -static const u16 TPS65020_LDO1_VSEL_table[] = { -	1000, 1050, 1100, 1300, -	1800, 2500, 3000, 3300, +static const unsigned int TPS65020_LDO1_VSEL_table[] = { +	1000000, 1050000, 1100000, 1300000, +	1800000, 2500000, 3000000, 3300000,  }; -static const u16 TPS65020_LDO2_VSEL_table[] = { -	1000, 1050, 1100, 1300, -	1800, 2500, 3000, 3300, +static const unsigned int TPS65020_LDO2_VSEL_table[] = { +	1000000, 1050000, 1100000, 1300000, +	1800000, 2500000, 3000000, 3300000,  };  /* Supported voltage values for LDO regulators   * for tps65021 and tps65023 */ -static const u16 TPS65023_LDO1_VSEL_table[] = { -	1000, 1100, 1300, 1800, -	2200, 2600, 2800, 3150, +static const unsigned int TPS65023_LDO1_VSEL_table[] = { +	1000000, 1100000, 1300000, 1800000, +	2200000, 2600000, 2800000, 3150000,  }; -static const u16 TPS65023_LDO2_VSEL_table[] = { -	1050, 1200, 1300, 1800, -	2500, 2800, 3000, 3300, +static const unsigned int TPS65023_LDO2_VSEL_table[] = { +	1050000, 1200000, 1300000, 1800000, +	2500000, 2800000, 3000000, 3300000,  };  /* Regulator specific details */  struct tps_info {  	const char *name; -	unsigned min_uV; -	unsigned max_uV; -	bool fixed;  	u8 table_len; -	const u16 *table; +	const unsigned int *table;  };  /* PMIC details */ @@ -150,7 +151,7 @@ struct tps_driver_data {  	u8 core_regulator;  }; -static int tps65023_dcdc_get_voltage(struct regulator_dev *dev) +static int tps65023_dcdc_get_voltage_sel(struct regulator_dev *dev)  {  	struct tps_pmic *tps = rdev_get_drvdata(dev);  	int ret; @@ -164,9 +165,9 @@ static int tps65023_dcdc_get_voltage(struct regulator_dev *dev)  		if (ret != 0)  			return ret;  		data &= (tps->info[dcdc]->table_len - 1); -		return tps->info[dcdc]->table[data] * 1000; +		return data;  	} else -		return tps->info[dcdc]->min_uV; +		return 0;  }  static int tps65023_dcdc_set_voltage_sel(struct regulator_dev *dev, @@ -193,76 +194,14 @@ out:  	return ret;  } -static int tps65023_ldo_get_voltage(struct regulator_dev *dev) -{ -	struct tps_pmic *tps = rdev_get_drvdata(dev); -	int data, ldo = rdev_get_id(dev); -	int ret; - -	if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2) -		return -EINVAL; - -	ret = regmap_read(tps->regmap, TPS65023_REG_LDO_CTRL, &data); -	if (ret != 0) -		return ret; - -	data >>= (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1)); -	data &= (tps->info[ldo]->table_len - 1); -	return tps->info[ldo]->table[data] * 1000; -} - -static int tps65023_ldo_set_voltage_sel(struct regulator_dev *dev, -					unsigned selector) -{ -	struct tps_pmic *tps = rdev_get_drvdata(dev); -	int ldo_index = rdev_get_id(dev) - TPS65023_LDO_1; - -	return regmap_update_bits(tps->regmap, TPS65023_REG_LDO_CTRL, -			TPS65023_LDO_CTRL_LDOx_MASK(ldo_index), -			selector << TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_index)); -} - -static int tps65023_dcdc_list_voltage(struct regulator_dev *dev, -					unsigned selector) -{ -	struct tps_pmic *tps = rdev_get_drvdata(dev); -	int dcdc = rdev_get_id(dev); - -	if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3) -		return -EINVAL; - -	if (dcdc == tps->core_regulator) { -		if (selector >= tps->info[dcdc]->table_len) -			return -EINVAL; -		else -			return tps->info[dcdc]->table[selector] * 1000; -	} else -		return tps->info[dcdc]->min_uV; -} - -static int tps65023_ldo_list_voltage(struct regulator_dev *dev, -					unsigned selector) -{ -	struct tps_pmic *tps = rdev_get_drvdata(dev); -	int ldo = rdev_get_id(dev); - -	if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2) -		return -EINVAL; - -	if (selector >= tps->info[ldo]->table_len) -		return -EINVAL; -	else -		return tps->info[ldo]->table[selector] * 1000; -} -  /* Operations permitted on VDCDCx */  static struct regulator_ops tps65023_dcdc_ops = {  	.is_enabled = regulator_is_enabled_regmap,  	.enable = regulator_enable_regmap,  	.disable = regulator_disable_regmap, -	.get_voltage = tps65023_dcdc_get_voltage, +	.get_voltage_sel = tps65023_dcdc_get_voltage_sel,  	.set_voltage_sel = tps65023_dcdc_set_voltage_sel, -	.list_voltage = tps65023_dcdc_list_voltage, +	.list_voltage = regulator_list_voltage_table,  };  /* Operations permitted on LDOx */ @@ -270,9 +209,9 @@ static struct regulator_ops tps65023_ldo_ops = {  	.is_enabled = regulator_is_enabled_regmap,  	.enable = regulator_enable_regmap,  	.disable = regulator_disable_regmap, -	.get_voltage = tps65023_ldo_get_voltage, -	.set_voltage_sel = tps65023_ldo_set_voltage_sel, -	.list_voltage = tps65023_ldo_list_voltage, +	.get_voltage_sel = regulator_get_voltage_sel_regmap, +	.set_voltage_sel = regulator_set_voltage_sel_regmap, +	.list_voltage = regulator_list_voltage_table,  };  static struct regmap_config tps65023_regmap_config = { @@ -325,19 +264,28 @@ static int __devinit tps_65023_probe(struct i2c_client *client,  		tps->desc[i].name = info->name;  		tps->desc[i].id = i;  		tps->desc[i].n_voltages = info->table_len; +		tps->desc[i].volt_table = info->table;  		tps->desc[i].ops = (i > TPS65023_DCDC_3 ?  					&tps65023_ldo_ops : &tps65023_dcdc_ops);  		tps->desc[i].type = REGULATOR_VOLTAGE;  		tps->desc[i].owner = THIS_MODULE;  		tps->desc[i].enable_reg = TPS65023_REG_REG_CTRL; -		if (i == TPS65023_LDO_1) +		switch (i) { +		case TPS65023_LDO_1: +			tps->desc[i].vsel_reg = TPS65023_REG_LDO_CTRL; +			tps->desc[i].vsel_mask = 0x07;  			tps->desc[i].enable_mask = 1 << 1; -		else if (i == TPS65023_LDO_2) +			break; +		case TPS65023_LDO_2: +			tps->desc[i].vsel_reg = TPS65023_REG_LDO_CTRL; +			tps->desc[i].vsel_mask = 0x70;  			tps->desc[i].enable_mask = 1 << 2; -		else /* DCDCx */ +			break; +		default: /* DCDCx */  			tps->desc[i].enable_mask =  					1 << (TPS65023_NUM_REGULATOR - i); +		}  		config.dev = &client->dev;  		config.init_data = init_data; @@ -384,35 +332,26 @@ static int __devexit tps_65023_remove(struct i2c_client *client)  static const struct tps_info tps65020_regs[] = {  	{  		.name = "VDCDC1", -		.min_uV = 3300000, -		.max_uV = 3300000, -		.fixed	= 1, +		.table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table), +		.table = DCDC_FIXED_3300000_VSEL_table,  	},  	{  		.name = "VDCDC2", -		.min_uV =  1800000, -		.max_uV = 1800000, -		.fixed = 1, +		.table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table), +		.table = DCDC_FIXED_1800000_VSEL_table,  	},  	{  		.name = "VDCDC3", -		.min_uV =  800000, -		.max_uV = 1600000,  		.table_len = ARRAY_SIZE(VCORE_VSEL_table),  		.table = VCORE_VSEL_table,  	}, -  	{  		.name = "LDO1", -		.min_uV = 1000000, -		.max_uV = 3150000,  		.table_len = ARRAY_SIZE(TPS65020_LDO1_VSEL_table),  		.table = TPS65020_LDO1_VSEL_table,  	},  	{  		.name = "LDO2", -		.min_uV = 1050000, -		.max_uV = 3300000,  		.table_len = ARRAY_SIZE(TPS65020_LDO2_VSEL_table),  		.table = TPS65020_LDO2_VSEL_table,  	}, @@ -421,34 +360,26 @@ static const struct tps_info tps65020_regs[] = {  static const struct tps_info tps65021_regs[] = {  	{  		.name = "VDCDC1", -		.min_uV =  3300000, -		.max_uV = 3300000, -		.fixed = 1, +		.table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table), +		.table = DCDC_FIXED_3300000_VSEL_table,  	},  	{  		.name = "VDCDC2", -		.min_uV =  1800000, -		.max_uV = 1800000, -		.fixed = 1, +		.table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table), +		.table = DCDC_FIXED_1800000_VSEL_table,  	},  	{  		.name = "VDCDC3", -		.min_uV =  800000, -		.max_uV = 1600000,  		.table_len = ARRAY_SIZE(VCORE_VSEL_table),  		.table = VCORE_VSEL_table,  	},  	{  		.name = "LDO1", -		.min_uV = 1000000, -		.max_uV = 3150000,  		.table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),  		.table = TPS65023_LDO1_VSEL_table,  	},  	{  		.name = "LDO2", -		.min_uV = 1050000, -		.max_uV = 3300000,  		.table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),  		.table = TPS65023_LDO2_VSEL_table,  	}, @@ -457,34 +388,26 @@ static const struct tps_info tps65021_regs[] = {  static const struct tps_info tps65023_regs[] = {  	{  		.name = "VDCDC1", -		.min_uV =  800000, -		.max_uV = 1600000,  		.table_len = ARRAY_SIZE(VCORE_VSEL_table),  		.table = VCORE_VSEL_table,  	},  	{  		.name = "VDCDC2", -		.min_uV =  3300000, -		.max_uV = 3300000, -		.fixed = 1, +		.table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table), +		.table = DCDC_FIXED_3300000_VSEL_table,  	},  	{  		.name = "VDCDC3", -		.min_uV =  1800000, -		.max_uV = 1800000, -		.fixed = 1, +		.table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table), +		.table = DCDC_FIXED_1800000_VSEL_table,  	},  	{  		.name = "LDO1", -		.min_uV = 1000000, -		.max_uV = 3150000,  		.table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),  		.table = TPS65023_LDO1_VSEL_table,  	},  	{  		.name = "LDO2", -		.min_uV = 1050000, -		.max_uV = 3300000,  		.table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),  		.table = TPS65023_LDO2_VSEL_table,  	}, diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index da38be1016a..07d01ccdf30 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -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; diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index 9d371d2cbca..6caa222af77 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -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; diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c index 1b299aacf22..947ece933d9 100644 --- a/drivers/regulator/tps6524x-regulator.c +++ b/drivers/regulator/tps6524x-regulator.c @@ -110,9 +110,6 @@  #define N_SWITCH		2  #define N_REGULATORS		(N_DCDC + N_LDO + N_SWITCH) -#define FIXED_ILIMSEL		BIT(0) -#define FIXED_VOLTAGE		BIT(1) -  #define CMD_READ(reg)		((reg) << 6)  #define CMD_WRITE(reg)		(BIT(5) | (reg) << 6)  #define STAT_CLK		BIT(3) @@ -129,12 +126,9 @@ struct field {  struct supply_info {  	const char	*name;  	int		n_voltages; -	const int	*voltages; -	int		fixed_voltage; +	const unsigned int *voltages;  	int		n_ilimsels; -	const int	*ilimsels; -	int		fixed_ilimsel; -	int		flags; +	const unsigned int *ilimsels;  	struct field	enable, voltage, ilimsel;  }; @@ -307,7 +301,7 @@ static int write_field(struct tps6524x *hw, const struct field *field,  				    val << field->shift);  } -static const int dcdc1_voltages[] = { +static const unsigned int dcdc1_voltages[] = {  	 800000,  825000,  850000,  875000,  	 900000,  925000,  950000,  975000,  	1000000, 1025000, 1050000, 1075000, @@ -318,7 +312,7 @@ static const int dcdc1_voltages[] = {  	1500000, 1525000, 1550000, 1575000,  }; -static const int dcdc2_voltages[] = { +static const unsigned int dcdc2_voltages[] = {  	1400000, 1450000, 1500000, 1550000,  	1600000, 1650000, 1700000, 1750000,  	1800000, 1850000, 1900000, 1950000, @@ -329,7 +323,7 @@ static const int dcdc2_voltages[] = {  	2800000, 2850000, 2900000, 2950000,  }; -static const int dcdc3_voltages[] = { +static const unsigned int dcdc3_voltages[] = {  	2400000, 2450000, 2500000, 2550000, 2600000,  	2650000, 2700000, 2750000, 2800000, 2850000,  	2900000, 2950000, 3000000, 3050000, 3100000, @@ -337,38 +331,54 @@ static const int dcdc3_voltages[] = {  	3400000, 3450000, 3500000, 3550000, 3600000,  }; -static const int ldo1_voltages[] = { +static const unsigned int ldo1_voltages[] = {  	4300000, 4350000, 4400000, 4450000,  	4500000, 4550000, 4600000, 4650000,  	4700000, 4750000, 4800000, 4850000,  	4900000, 4950000, 5000000, 5050000,  }; -static const int ldo2_voltages[] = { +static const unsigned int ldo2_voltages[] = {  	1100000, 1150000, 1200000, 1250000,  	1300000, 1700000, 1750000, 1800000,  	1850000, 1900000, 3150000, 3200000,  	3250000, 3300000, 3350000, 3400000,  }; -static const int ldo_ilimsel[] = { +static const unsigned int fixed_5000000_voltage[] = { +	5000000 +}; + +static const unsigned int ldo_ilimsel[] = {  	400000, 1500000  }; -static const int usb_ilimsel[] = { +static const unsigned int usb_ilimsel[] = {  	200000, 400000, 800000, 1000000  }; +static const unsigned int fixed_2400000_ilimsel[] = { +	2400000 +}; + +static const unsigned int fixed_1200000_ilimsel[] = { +	1200000 +}; + +static const unsigned int fixed_400000_ilimsel[] = { +	400000 +}; +  #define __MK_FIELD(_reg, _mask, _shift) \  	{ .reg = (_reg), .mask = (_mask), .shift = (_shift), }  static const struct supply_info supply_info[N_REGULATORS] = {  	{  		.name		= "DCDC1", -		.flags		= FIXED_ILIMSEL,  		.n_voltages	= ARRAY_SIZE(dcdc1_voltages),  		.voltages	= dcdc1_voltages, -		.fixed_ilimsel	= 2400000, +		.n_ilimsels	= ARRAY_SIZE(fixed_2400000_ilimsel), +		.ilimsels	= fixed_2400000_ilimsel,  		.enable		= __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,  					     DCDCDCDC1_EN_SHIFT),  		.voltage	= __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK, @@ -376,10 +386,10 @@ static const struct supply_info supply_info[N_REGULATORS] = {  	},  	{  		.name		= "DCDC2", -		.flags		= FIXED_ILIMSEL,  		.n_voltages	= ARRAY_SIZE(dcdc2_voltages),  		.voltages	= dcdc2_voltages, -		.fixed_ilimsel	= 1200000, +		.n_ilimsels	= ARRAY_SIZE(fixed_1200000_ilimsel), +		.ilimsels	= fixed_1200000_ilimsel,  		.enable		= __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,  					     DCDCDCDC2_EN_SHIFT),  		.voltage	= __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK, @@ -387,10 +397,10 @@ static const struct supply_info supply_info[N_REGULATORS] = {  	},  	{  		.name		= "DCDC3", -		.flags		= FIXED_ILIMSEL,  		.n_voltages	= ARRAY_SIZE(dcdc3_voltages),  		.voltages	= dcdc3_voltages, -		.fixed_ilimsel	= 1200000, +		.n_ilimsels	= ARRAY_SIZE(fixed_1200000_ilimsel), +		.ilimsels	= fixed_1200000_ilimsel,  		.enable		= __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,  					DCDCDCDC3_EN_SHIFT),  		.voltage	= __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK, @@ -424,8 +434,8 @@ static const struct supply_info supply_info[N_REGULATORS] = {  	},  	{  		.name		= "USB", -		.flags		= FIXED_VOLTAGE, -		.fixed_voltage	= 5000000, +		.n_voltages	= ARRAY_SIZE(fixed_5000000_voltage), +		.voltages	= fixed_5000000_voltage,  		.n_ilimsels	= ARRAY_SIZE(usb_ilimsel),  		.ilimsels	= usb_ilimsel,  		.enable		= __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK, @@ -435,29 +445,15 @@ static const struct supply_info supply_info[N_REGULATORS] = {  	},  	{  		.name		= "LCD", -		.flags		= FIXED_VOLTAGE | FIXED_ILIMSEL, -		.fixed_voltage	= 5000000, -		.fixed_ilimsel	=  400000, +		.n_voltages	= ARRAY_SIZE(fixed_5000000_voltage), +		.voltages	= fixed_5000000_voltage, +		.n_ilimsels	= ARRAY_SIZE(fixed_400000_ilimsel), +		.ilimsels	= fixed_400000_ilimsel,  		.enable		= __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,  					     BLOCK_LCD_SHIFT),  	},  }; -static int list_voltage(struct regulator_dev *rdev, unsigned selector) -{ -	const struct supply_info *info; -	struct tps6524x *hw; - -	hw	= rdev_get_drvdata(rdev); -	info	= &supply_info[rdev_get_id(rdev)]; - -	if (info->flags & FIXED_VOLTAGE) -		return selector ? -EINVAL : info->fixed_voltage; - -	return ((selector < info->n_voltages) ? -		info->voltages[selector] : -EINVAL); -} -  static int set_voltage_sel(struct regulator_dev *rdev, unsigned selector)  {  	const struct supply_info *info; @@ -466,7 +462,7 @@ static int set_voltage_sel(struct regulator_dev *rdev, unsigned selector)  	hw	= rdev_get_drvdata(rdev);  	info	= &supply_info[rdev_get_id(rdev)]; -	if (info->flags & FIXED_VOLTAGE) +	if (rdev->desc->n_voltages == 1)  		return -EINVAL;  	return write_field(hw, &info->voltage, selector); @@ -481,7 +477,7 @@ static int get_voltage_sel(struct regulator_dev *rdev)  	hw	= rdev_get_drvdata(rdev);  	info	= &supply_info[rdev_get_id(rdev)]; -	if (info->flags & FIXED_VOLTAGE) +	if (rdev->desc->n_voltages == 1)  		return 0;  	ret = read_field(hw, &info->voltage); @@ -503,7 +499,7 @@ static int set_current_limit(struct regulator_dev *rdev, int min_uA,  	hw	= rdev_get_drvdata(rdev);  	info	= &supply_info[rdev_get_id(rdev)]; -	if (info->flags & FIXED_ILIMSEL) +	if (info->n_ilimsels == 1)  		return -EINVAL;  	for (i = 0; i < info->n_ilimsels; i++) @@ -526,8 +522,8 @@ static int get_current_limit(struct regulator_dev *rdev)  	hw	= rdev_get_drvdata(rdev);  	info	= &supply_info[rdev_get_id(rdev)]; -	if (info->flags & FIXED_ILIMSEL) -		return info->fixed_ilimsel; +	if (info->n_ilimsels == 1) +		return info->ilimsels[0];  	ret = read_field(hw, &info->ilimsel);  	if (ret < 0) @@ -577,7 +573,7 @@ static struct regulator_ops regulator_ops = {  	.disable		= disable_supply,  	.get_voltage_sel	= get_voltage_sel,  	.set_voltage_sel	= set_voltage_sel, -	.list_voltage		= list_voltage, +	.list_voltage		= regulator_list_voltage_table,  	.set_current_limit	= set_current_limit,  	.get_current_limit	= get_current_limit,  }; @@ -629,13 +625,11 @@ static int __devinit pmic_probe(struct spi_device *spi)  		hw->desc[i].name	= info->name;  		hw->desc[i].id		= i;  		hw->desc[i].n_voltages	= info->n_voltages; +		hw->desc[i].volt_table	= info->voltages;  		hw->desc[i].ops		= ®ulator_ops;  		hw->desc[i].type	= REGULATOR_VOLTAGE;  		hw->desc[i].owner	= THIS_MODULE; -		if (info->flags & FIXED_VOLTAGE) -			hw->desc[i].n_voltages = 1; -  		config.dev = dev;  		config.init_data = init_data;  		config.driver_data = hw; diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index c0a21457538..e6da90ab515 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -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 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_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_ldo_voltages[] = { +	1250000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,  }; -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_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,  }; -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_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, vdata, vreg, shift, nbits,		\ +#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; diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 6bf864b4bdf..793adda560c 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -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, diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index c7390711d95..242fe90dc56 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -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); - -	if (vsel < 0) -		return vsel; +	int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE); -	/* -	 * 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), diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 099da11e989..7413885be01 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -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; + +	sel = regulator_map_voltage_linear(rdev, uV, uV); +	if (sel < 0) +		return sel; -	return wm831x_buckp_set_voltage_int(rdev, reg, uV, uV, &selector); +	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) diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index a9a28d8ac18..5cb70ca1e98 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -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 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 vsel; -	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; + +	sel = wm831x_aldo_map_voltage(rdev, uV, uV); +	if (sel < 0) +		return sel; -	return wm831x_aldo_set_voltage_int(rdev, reg, uV, uV, &selector); +	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; + +	sel = regulator_map_voltage_linear(rdev, uV, uV); +	if (sel < 0) +		return sel; -	return wm831x_alive_ldo_set_voltage_int(rdev, reg, uV, uV, &selector); +	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) diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 94e550dc70b..7f0fa22ef2a 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -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); diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c index 69a2b7ce5e4..9035dd05361 100644 --- a/drivers/regulator/wm8400-regulator.c +++ b/drivers/regulator/wm8400-regulator.c @@ -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, diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index 9a994316e63..86bb48db149 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -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;  } diff --git a/include/linux/mfd/s5m87xx/s5m-core.h b/include/linux/mfd/s5m87xx/s5m-core.h index 21603b42f22..0b2e0ed309f 100644 --- a/include/linux/mfd/s5m87xx/s5m-core.h +++ b/include/linux/mfd/s5m87xx/s5m-core.h @@ -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 */ diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h index e030ef9a64e..12c06870829 100644 --- a/include/linux/mfd/tps65217.h +++ b/include/linux/mfd/tps65217.h @@ -217,7 +217,8 @@ enum tps65217_regulator_id {   * Board data may be used to initialize regulator.   */  struct tps65217_board { -	struct regulator_init_data *tps65217_init_data; +	struct regulator_init_data *tps65217_init_data[TPS65217_NUM_REGULATOR]; +	struct device_node *of_node[TPS65217_NUM_REGULATOR];  };  /** @@ -227,11 +228,6 @@ struct tps65217_board {   * @max_uV:		minimum micro volts   * @vsel_to_uv:		Function pointer to get voltage from selector   * @uv_to_vsel:		Function pointer to get selector from voltage - * @table:		Table for non-uniform voltage step-size - * @table_len:		Length of the voltage table - * @enable_mask:	Regulator enable mask bits - * @set_vout_reg:	Regulator output voltage set register - * @set_vout_mask:	Regulator output voltage set mask   *   * This data is used to check the regualtor voltage limits while setting.   */ @@ -241,11 +237,6 @@ struct tps_info {  	int max_uV;  	int (*vsel_to_uv)(unsigned int vsel);  	int (*uv_to_vsel)(int uV, unsigned int *vsel); -	const int *table; -	unsigned int table_len; -	unsigned int enable_mask; -	unsigned int set_vout_reg; -	unsigned int set_vout_mask;  };  /** diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h index dd8dc0a6c46..6c4c478e21a 100644 --- a/include/linux/mfd/tps65910.h +++ b/include/linux/mfd/tps65910.h @@ -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 */ diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 4ed1b30ac5f..da339fd8c75 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -291,6 +291,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;  } diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index b0432cc2b16..bac4c871f3b 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -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); diff --git a/include/linux/regulator/fixed.h b/include/linux/regulator/fixed.h index f83f7440b48..48918be649d 100644 --- a/include/linux/regulator/fixed.h +++ b/include/linux/regulator/fixed.h @@ -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 diff --git a/include/linux/regulator/lp872x.h b/include/linux/regulator/lp872x.h new file mode 100644 index 00000000000..132e05c4666 --- /dev/null +++ b/include/linux/regulator/lp872x.h @@ -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 diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index b02108446be..40dd0a394cf 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h @@ -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 */  |