regulator: Updates for v3.7

- Support for putting regulators into bypass mode where they simply
   switch their input to the output (mainly used for low power retention).
 - A new API for setting voltages based on a voltage plus tolerance
   rather than an explicit voltage range.
 - Lots of cleanups and API updates from Axel Lin.
 - New driver for MAX8907.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iQIcBAABAgAGBQJQZanxAAoJEOoSHmUN5Tg4X+0P/AvZNTJMNya8qapG1uOjdgML
 w+gQTGw6g+7libJ8m3+M8YfoR0KRF3tGihGU9yZt8M7VkvZht/Q88eDOM0xw5FQo
 XfpQjOb7+jc6CcVF8qGWz3DkXteqThRzwcqLR47/pv6EiNQB/2F/SWOp/btf/9hR
 7YLFlKpv2LV4DwDnONGfJibe5Rrt0mj6dsy8ndmj/RMs7AVxN3H9V/L9q/kGNYIL
 nnyRJIWTZ2R7L04shZBLaInnvARPbnrGiSUymZMwYO+5Op6qyuSWDf5IlfHZqsAc
 pOWksUSHxvxAmh2MmH9cV4OT31e04qhAHxwxOzH4vpKMHdN1X92X56NwiF5K15/s
 HJ86+TVU3JRnsHAPxVVWuplL4cY1UbaueMTt3FpA1xF9Y6W7DvIK/Y0S5FXHmYzN
 RClrlvtlIU8m71QaroQmVaprLz0odrC0gyIO9TdW4KP+fkomKKNQLiSr7Wkv1Deg
 lnjwlXSForW3Rqf9GLx3SJI29nHuy8F4RG55KvaxoXKm2TZdgtDG5x3ol1RW0/bd
 OxF7SC/gEgnU0S4oOOdmrLOuUME2LY3wzi9TZT31kqieCQ3L257LHRtjBS8oZJpk
 jnU5Fk+q+7nIxdxawgv11BS/z28T3ucRq1gkIC2Bxv138cF5UDsNNw6uKqjUcK7x
 AmvUqMPwVCk8SIEAs2Oh
 =Kg66
 -----END PGP SIGNATURE-----

Merge tag 'regulator-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator

Pull regulator updates from Mark Brown:
 - Support for putting regulators into bypass mode where they simply
   switch their input to the output (mainly used for low power
   retention).
 - A new API for setting voltages based on a voltage plus tolerance
   rather than an explicit voltage range.
 - Lots of cleanups and API updates from Axel Lin.
 - New driver for MAX8907.

* tag 'regulator-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (71 commits)
  regulator: arizona-ldo: Remove top voltage
  regulator: tps6586x: remove regulator-compatible from DT docs
  regulator: tps65217.txt: remove regulator-compatible from DT docs
  regulator: deprecate regulator-compatible DT property
  regulator: fan53555: remove vsel_max not used
  regulator: aat2870: Don't explicitly initialise the first field
  extcon: arizona: Use bypass mode for MICVDD
  regulator: wm831x-ldo: Add bypass support
  regulator: arizona-micsupp: Support get/set bypass
  regulator: arizona-ldo: Support get/set bypass
  regulator: core: Provide regmap get/set bypass operations
  regulator: core: Support bypass mode
  regulator: Fairchild fan53555 support
  regulator: twl: Remove another unused variable warning
  regulator: core: Try using the parent device for the default regmap
  regulator: core: Fast path non-deferred disables
  regulator: core: Report microvolts in sysfs even with only list_voltage()
  regulator: tps6586x: add support for SYS rail
  regulator: lp872x: remove unnecessary function
  regulator: lp872x: fix NULL pointer access problem
  ...
This commit is contained in:
Linus Torvalds 2012-10-01 08:58:47 -07:00
commit aae6f989c6
43 changed files with 1417 additions and 563 deletions

View File

@ -349,3 +349,24 @@ Description:
This will be one of the same strings reported by
the "state" attribute.
What: /sys/class/regulator/.../bypass
Date: September 2012
KernelVersion: 3.7
Contact: Mark Brown <broonie@opensource.wolfsonmicro.com>
Description:
Some regulator directories will contain a field called
bypass. This indicates if the device is in bypass mode.
This will be one of the following strings:
'enabled'
'disabled'
'unknown'
'enabled' means the regulator is in bypass mode.
'disabled' means that the regulator is regulating.
'unknown' means software cannot determine the state, or
the reported state is invalid.

View File

@ -11,10 +11,13 @@ Optional properties:
- 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)
Deprecated properties:
- 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.
this child node is intended to configure. If this property is missing,
the node's name will be used instead.
Example:

View File

@ -22,66 +22,49 @@ Example:
compatible = "ti,tps65217";
regulators {
#address-cells = <1>;
#size-cells = <0>;
dcdc1_reg: regulator@0 {
reg = <0>;
regulator-compatible = "dcdc1";
dcdc1_reg: dcdc1 {
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-always-on;
};
dcdc2_reg: regulator@1 {
reg = <1>;
regulator-compatible = "dcdc2";
dcdc2_reg: dcdc2 {
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
dcdc3_reg: regulator@2 {
reg = <2>;
regulator-compatible = "dcdc3";
dcdc3_reg: dcc3 {
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <1500000>;
regulator-boot-on;
regulator-always-on;
};
ldo1_reg: regulator@3 {
reg = <3>;
regulator-compatible = "ldo1";
ldo1_reg: ldo1 {
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
ldo2_reg: regulator@4 {
reg = <4>;
regulator-compatible = "ldo2";
ldo2_reg: ldo2 {
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
ldo3_reg: regulator@5 {
reg = <5>;
regulator-compatible = "ldo3";
ldo3_reg: ldo3 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
ldo4_reg: regulator@6 {
reg = <6>;
regulator-compatible = "ldo4";
ldo4_reg: ldo4 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;

View File

@ -6,9 +6,13 @@ 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 have
property "regulator-compatible" to match their hardware counterparts:
sm[0-2], ldo[0-9] and ldo_rtc
- regulators: A node that houses a sub-node for each regulator within the
device. Each sub-node is identified using the node's name (or the deprecated
regulator-compatible property if present), with valid values listed below.
The content of each sub-node is defined by the standard binding for
regulators; see regulator.txt.
sys, sm[0-2], ldo[0-9] and ldo_rtc
- sys-supply: The input supply for SYS.
- vin-sm0-supply: The input supply for the SM0.
- vin-sm1-supply: The input supply for the SM1.
- vin-sm2-supply: The input supply for the SM2.
@ -20,6 +24,9 @@ Required properties:
Each regulator is defined using the standard binding for regulators.
Note: LDO5 and LDO_RTC is supplied by SYS regulator internally and driver
take care of making proper parent child relationship.
Example:
pmu: tps6586x@34 {
@ -30,6 +37,7 @@ Example:
#gpio-cells = <2>;
gpio-controller;
sys-supply = <&some_reg>;
vin-sm0-supply = <&some_reg>;
vin-sm1-supply = <&some_reg>;
vin-sm2-supply = <&some_reg>;
@ -40,103 +48,80 @@ Example:
vinldo9-supply = <...>;
regulators {
#address-cells = <1>;
#size-cells = <0>;
sys_reg: sys {
regulator-name = "vdd_sys";
regulator-boot-on;
regulator-always-on;
};
sm0_reg: regulator@0 {
reg = <0>;
regulator-compatible = "sm0";
sm0_reg: sm0 {
regulator-min-microvolt = < 725000>;
regulator-max-microvolt = <1500000>;
regulator-boot-on;
regulator-always-on;
};
sm1_reg: regulator@1 {
reg = <1>;
regulator-compatible = "sm1";
sm1_reg: sm1 {
regulator-min-microvolt = < 725000>;
regulator-max-microvolt = <1500000>;
regulator-boot-on;
regulator-always-on;
};
sm2_reg: regulator@2 {
reg = <2>;
regulator-compatible = "sm2";
sm2_reg: sm2 {
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <4550000>;
regulator-boot-on;
regulator-always-on;
};
ldo0_reg: regulator@3 {
reg = <3>;
regulator-compatible = "ldo0";
ldo0_reg: ldo0 {
regulator-name = "PCIE CLK";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
ldo1_reg: regulator@4 {
reg = <4>;
regulator-compatible = "ldo1";
ldo1_reg: ldo1 {
regulator-min-microvolt = < 725000>;
regulator-max-microvolt = <1500000>;
};
ldo2_reg: regulator@5 {
reg = <5>;
regulator-compatible = "ldo2";
ldo2_reg: ldo2 {
regulator-min-microvolt = < 725000>;
regulator-max-microvolt = <1500000>;
};
ldo3_reg: regulator@6 {
reg = <6>;
regulator-compatible = "ldo3";
ldo3_reg: ldo3 {
regulator-min-microvolt = <1250000>;
regulator-max-microvolt = <3300000>;
};
ldo4_reg: regulator@7 {
reg = <7>;
regulator-compatible = "ldo4";
ldo4_reg: ldo4 {
regulator-min-microvolt = <1700000>;
regulator-max-microvolt = <2475000>;
};
ldo5_reg: regulator@8 {
reg = <8>;
regulator-compatible = "ldo5";
ldo5_reg: ldo5 {
regulator-min-microvolt = <1250000>;
regulator-max-microvolt = <3300000>;
};
ldo6_reg: regulator@9 {
reg = <9>;
regulator-compatible = "ldo6";
ldo6_reg: ldo6 {
regulator-min-microvolt = <1250000>;
regulator-max-microvolt = <3300000>;
};
ldo7_reg: regulator@10 {
reg = <10>;
regulator-compatible = "ldo7";
ldo7_reg: ldo7 {
regulator-min-microvolt = <1250000>;
regulator-max-microvolt = <3300000>;
};
ldo8_reg: regulator@11 {
reg = <11>;
regulator-compatible = "ldo8";
ldo8_reg: ldo8 {
regulator-min-microvolt = <1250000>;
regulator-max-microvolt = <3300000>;
};
ldo9_reg: regulator@12 {
reg = <12>;
regulator-compatible = "ldo9";
ldo9_reg: ldo9 {
regulator-min-microvolt = <1250000>;
regulator-max-microvolt = <3300000>;
};

View File

@ -67,6 +67,13 @@ static struct regulator_init_data ldo0_data = {
}, \
}
static struct regulator_init_data sys_data = {
.supply_regulator = "vdd_5v0",
.constraints = {
.name = "vdd_sys",
},
};
HARMONY_REGULATOR_INIT(sm0, "vdd_sm0", "vdd_sys", 725, 1500, 1);
HARMONY_REGULATOR_INIT(sm1, "vdd_sm1", "vdd_sys", 725, 1500, 1);
HARMONY_REGULATOR_INIT(sm2, "vdd_sm2", "vdd_sys", 3000, 4550, 1);
@ -74,7 +81,7 @@ HARMONY_REGULATOR_INIT(ldo1, "vdd_ldo1", "vdd_sm2", 725, 1500, 1);
HARMONY_REGULATOR_INIT(ldo2, "vdd_ldo2", "vdd_sm2", 725, 1500, 0);
HARMONY_REGULATOR_INIT(ldo3, "vdd_ldo3", "vdd_sm2", 1250, 3300, 1);
HARMONY_REGULATOR_INIT(ldo4, "vdd_ldo4", "vdd_sm2", 1700, 2475, 1);
HARMONY_REGULATOR_INIT(ldo5, "vdd_ldo5", NULL, 1250, 3300, 1);
HARMONY_REGULATOR_INIT(ldo5, "vdd_ldo5", "vdd_sys", 1250, 3300, 1);
HARMONY_REGULATOR_INIT(ldo6, "vdd_ldo6", "vdd_sm2", 1250, 3300, 0);
HARMONY_REGULATOR_INIT(ldo7, "vdd_ldo7", "vdd_sm2", 1250, 3300, 0);
HARMONY_REGULATOR_INIT(ldo8, "vdd_ldo8", "vdd_sm2", 1250, 3300, 0);
@ -88,6 +95,7 @@ HARMONY_REGULATOR_INIT(ldo9, "vdd_ldo9", "vdd_sm2", 1250, 3300, 1);
}
static struct tps6586x_subdev_info tps_devs[] = {
TPS_REG(SYS, &sys_data),
TPS_REG(SM_0, &sm0_data),
TPS_REG(SM_1, &sm1_data),
TPS_REG(SM_2, &sm2_data),
@ -120,7 +128,7 @@ static struct i2c_board_info __initdata harmony_regulators[] = {
int __init harmony_regulator_init(void)
{
regulator_register_always_on(0, "vdd_sys",
regulator_register_always_on(0, "vdd_5v0",
NULL, 0, 5000000);
if (machine_is_harmony()) {

View File

@ -434,6 +434,11 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev)
regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
ARIZONA_JD1_ENA, ARIZONA_JD1_ENA);
ret = regulator_allow_bypass(info->micvdd, true);
if (ret != 0)
dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n",
ret);
pm_runtime_put(&pdev->dev);
return 0;

View File

@ -25,6 +25,7 @@
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/machine.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps6586x.h>
@ -346,6 +347,7 @@ failed:
#ifdef CONFIG_OF
static struct of_regulator_match tps6586x_matches[] = {
{ .name = "sys", .driver_data = (void *)TPS6586X_ID_SYS },
{ .name = "sm0", .driver_data = (void *)TPS6586X_ID_SM_0 },
{ .name = "sm1", .driver_data = (void *)TPS6586X_ID_SM_1 },
{ .name = "sm2", .driver_data = (void *)TPS6586X_ID_SM_2 },
@ -369,6 +371,7 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien
struct tps6586x_platform_data *pdata;
struct tps6586x_subdev_info *devs;
struct device_node *regs;
const char *sys_rail_name = NULL;
unsigned int count;
unsigned int i, j;
int err;
@ -391,12 +394,22 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien
return NULL;
for (i = 0, j = 0; i < num && j < count; i++) {
struct regulator_init_data *reg_idata;
if (!tps6586x_matches[i].init_data)
continue;
reg_idata = tps6586x_matches[i].init_data;
devs[j].name = "tps6586x-regulator";
devs[j].platform_data = tps6586x_matches[i].init_data;
devs[j].id = (int)tps6586x_matches[i].driver_data;
if (devs[j].id == TPS6586X_ID_SYS)
sys_rail_name = reg_idata->constraints.name;
if ((devs[j].id == TPS6586X_ID_LDO_5) ||
(devs[j].id == TPS6586X_ID_LDO_RTC))
reg_idata->supply_regulator = sys_rail_name;
devs[j].of_node = tps6586x_matches[i].of_node;
j++;
}

View File

@ -33,9 +33,8 @@ config REGULATOR_DUMMY
help
If this option is enabled then when a regulator lookup fails
and the board has not specified that it has provided full
constraints then the regulator core will provide an always
enabled dummy regulator will be provided, allowing consumer
drivers to continue.
constraints the regulator core will provide an always
enabled dummy regulator, allowing consumer drivers to continue.
A warning will be generated when this substitution is done.
@ -50,11 +49,11 @@ config REGULATOR_VIRTUAL_CONSUMER
tristate "Virtual regulator consumer support"
help
This driver provides a virtual consumer for the voltage and
current regulator API which provides sysfs controls for
configuring the supplies requested. This is mainly useful
for test purposes.
current regulator API which provides sysfs controls for
configuring the supplies requested. This is mainly useful
for test purposes.
If unsure, say no.
If unsure, say no.
config REGULATOR_USERSPACE_CONSUMER
tristate "Userspace regulator consumer support"
@ -63,7 +62,7 @@ config REGULATOR_USERSPACE_CONSUMER
from user space. Userspace consumer driver provides ability to
control power supplies for such devices.
If unsure, say no.
If unsure, say no.
config REGULATOR_GPIO
tristate "GPIO regulator support"
@ -110,6 +109,17 @@ config REGULATOR_DA9052
This driver supports the voltage regulators of DA9052-BC and
DA9053-AA/Bx PMIC.
config REGULATOR_FAN53555
tristate "Fairchild FAN53555 Regulator"
depends on I2C
select REGMAP_I2C
help
This driver supports Fairchild FAN53555 Digitally Programmable
TinyBuck Regulator. The FAN53555 is a step-down switching voltage
regulator that delivers a digitally programmable output from an
input voltage supply of 2.5V to 5.5V. The output voltage is
programmed through an I2C interface.
config REGULATOR_ANATOP
tristate "Freescale i.MX on-chip ANATOP LDO regulators"
depends on MFD_ANATOP
@ -172,6 +182,14 @@ config REGULATOR_MAX8660
This driver controls a Maxim 8660/8661 voltage output
regulator via I2C bus.
config REGULATOR_MAX8907
tristate "Maxim 8907 voltage regulator"
depends on MFD_MAX8907
help
This driver controls a Maxim 8907 voltage output regulator
via I2C bus. The provided regulator is suitable for Tegra
chip to control Step-Down DC-DC and LDOs.
config REGULATOR_MAX8925
tristate "Maxim MAX8925 Power Management IC"
depends on MFD_MAX8925
@ -247,7 +265,7 @@ config REGULATOR_LP8788
config REGULATOR_PCF50633
tristate "NXP PCF50633 regulator driver"
depends on MFD_PCF50633
depends on MFD_PCF50633
help
Say Y here to support the voltage regulators and convertors
on PCF50633
@ -416,7 +434,7 @@ config REGULATOR_WM8350
depends on MFD_WM8350
help
This driver provides support for the voltage and current regulators
of the WM8350 AudioPlus PMIC.
of the WM8350 AudioPlus PMIC.
config REGULATOR_WM8400
tristate "Wolfson Microelectronics WM8400 AudioPlus PMIC"

View File

@ -20,6 +20,7 @@ obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
@ -30,6 +31,7 @@ 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
obj-$(CONFIG_REGULATOR_MAX8907) += max8907-regulator.o
obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o
obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o

View File

@ -162,7 +162,7 @@ static struct aat2870_regulator *aat2870_get_regulator(int id)
static int aat2870_regulator_probe(struct platform_device *pdev)
{
struct aat2870_regulator *ri;
struct regulator_config config = { 0 };
struct regulator_config config = { };
struct regulator_dev *rdev;
ri = aat2870_get_regulator(pdev->id);

View File

@ -347,17 +347,11 @@ static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg)
return abreg->plfdata->external_voltage;
}
static int ab3100_get_fixed_voltage_regulator(struct regulator_dev *reg)
{
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_fixed_voltage_regulator,
};
static struct regulator_ops regulator_ops_variable = {

View File

@ -37,6 +37,7 @@
* @voltage_bank: bank to control regulator voltage
* @voltage_reg: register to control regulator voltage
* @voltage_mask: mask to control regulator voltage
* @voltage_shift: shift to control regulator voltage
* @delay: startup/set voltage delay in us
*/
struct ab8500_regulator_info {
@ -50,6 +51,7 @@ struct ab8500_regulator_info {
u8 voltage_bank;
u8 voltage_reg;
u8 voltage_mask;
u8 voltage_shift;
unsigned int delay;
};
@ -195,17 +197,14 @@ static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev)
}
dev_vdbg(rdev_get_dev(rdev),
"%s-get_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x,"
" 0x%x\n",
info->desc.name, info->voltage_bank, info->voltage_reg,
info->voltage_mask, regval);
"%s-get_voltage (bank, reg, mask, shift, value): "
"0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
info->desc.name, info->voltage_bank,
info->voltage_reg, info->voltage_mask,
info->voltage_shift, regval);
/* vintcore has a different layout */
val = regval & info->voltage_mask;
if (info->desc.id == AB8500_LDO_INTCORE)
return val >> 0x3;
else
return val;
return val >> info->voltage_shift;
}
static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev,
@ -221,7 +220,7 @@ static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev,
}
/* set the registers for the request */
regval = (u8)selector;
regval = (u8)selector << info->voltage_shift;
ret = abx500_mask_and_set_register_interruptible(info->dev,
info->voltage_bank, info->voltage_reg,
info->voltage_mask, regval);
@ -238,13 +237,6 @@ static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev,
return ret;
}
static int ab8500_regulator_enable_time(struct regulator_dev *rdev)
{
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
return info->delay;
}
static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
unsigned int old_sel,
unsigned int new_sel)
@ -261,22 +253,14 @@ static struct regulator_ops ab8500_regulator_ops = {
.get_voltage_sel = ab8500_regulator_get_voltage_sel,
.set_voltage_sel = ab8500_regulator_set_voltage_sel,
.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)
{
return rdev->desc->min_uV;
}
static struct regulator_ops ab8500_regulator_fixed_ops = {
.enable = ab8500_regulator_enable,
.disable = ab8500_regulator_disable,
.is_enabled = ab8500_regulator_is_enabled,
.get_voltage = ab8500_fixed_get_voltage,
.list_voltage = regulator_list_voltage_linear,
.enable_time = ab8500_regulator_enable_time,
};
static struct ab8500_regulator_info
@ -358,6 +342,7 @@ static struct ab8500_regulator_info
.voltage_bank = 0x03,
.voltage_reg = 0x80,
.voltage_mask = 0x38,
.voltage_shift = 3,
},
/*
@ -374,6 +359,7 @@ static struct ab8500_regulator_info
.owner = THIS_MODULE,
.n_voltages = 1,
.min_uV = 2000000,
.enable_time = 10000,
},
.delay = 10000,
.update_bank = 0x03,

View File

@ -39,6 +39,8 @@ static struct regulator_ops arizona_ldo1_ops = {
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_bypass = regulator_get_bypass_regmap,
.set_bypass = regulator_set_bypass_regmap,
};
static const struct regulator_desc arizona_ldo1 = {
@ -49,9 +51,11 @@ static const struct regulator_desc arizona_ldo1 = {
.vsel_reg = ARIZONA_LDO1_CONTROL_1,
.vsel_mask = ARIZONA_LDO1_VSEL_MASK,
.bypass_reg = ARIZONA_LDO1_CONTROL_1,
.bypass_mask = ARIZONA_LDO1_BYPASS,
.min_uV = 900000,
.uV_step = 50000,
.n_voltages = 7,
.n_voltages = 6,
.owner = THIS_MODULE,
};

View File

@ -82,6 +82,9 @@ static struct regulator_ops arizona_micsupp_ops = {
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_bypass = regulator_get_bypass_regmap,
.set_bypass = regulator_set_bypass_regmap,
};
static const struct regulator_desc arizona_micsupp = {
@ -95,6 +98,8 @@ static const struct regulator_desc arizona_micsupp = {
.vsel_mask = ARIZONA_LDO2_VSEL_MASK,
.enable_reg = ARIZONA_MIC_CHARGE_PUMP_1,
.enable_mask = ARIZONA_CPMIC_ENA,
.bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1,
.bypass_mask = ARIZONA_CPMIC_BYPASS,
.owner = THIS_MODULE,
};

View File

@ -77,6 +77,7 @@ struct regulator {
struct device *dev;
struct list_head list;
unsigned int always_on:1;
unsigned int bypass:1;
int uA_load;
int min_uV;
int max_uV;
@ -394,6 +395,9 @@ static ssize_t regulator_status_show(struct device *dev,
case REGULATOR_STATUS_STANDBY:
label = "standby";
break;
case REGULATOR_STATUS_BYPASS:
label = "bypass";
break;
case REGULATOR_STATUS_UNDEFINED:
label = "undefined";
break;
@ -585,6 +589,27 @@ static ssize_t regulator_suspend_standby_state_show(struct device *dev,
static DEVICE_ATTR(suspend_standby_state, 0444,
regulator_suspend_standby_state_show, NULL);
static ssize_t regulator_bypass_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct regulator_dev *rdev = dev_get_drvdata(dev);
const char *report;
bool bypass;
int ret;
ret = rdev->desc->ops->get_bypass(rdev, &bypass);
if (ret != 0)
report = "unknown";
else if (bypass)
report = "enabled";
else
report = "disabled";
return sprintf(buf, "%s\n", report);
}
static DEVICE_ATTR(bypass, 0444,
regulator_bypass_show, NULL);
/*
* These are the only attributes are present for all regulators.
@ -778,6 +803,9 @@ static void print_constraints(struct regulator_dev *rdev)
if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY)
count += sprintf(buf + count, "standby");
if (!count)
sprintf(buf, "no parameters");
rdev_info(rdev, "%s\n", buf);
if ((constraints->min_uV != constraints->max_uV) &&
@ -974,6 +1002,7 @@ static int set_supply(struct regulator_dev *rdev,
err = -ENOMEM;
return err;
}
supply_rdev->open_count++;
return 0;
}
@ -1720,6 +1749,9 @@ int regulator_disable_deferred(struct regulator *regulator, int ms)
if (regulator->always_on)
return 0;
if (!ms)
return regulator_disable(regulator);
mutex_lock(&rdev->mutex);
rdev->deferred_disables++;
mutex_unlock(&rdev->mutex);
@ -2178,9 +2210,12 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
}
}
if (ret == 0 && best_val >= 0)
if (ret == 0 && best_val >= 0) {
unsigned long data = best_val;
_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
(void *)best_val);
(void *)data);
}
trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
@ -2291,8 +2326,8 @@ 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
* regulator_set_voltage_time_sel - get raise/fall time
* @rdev: regulator source device
* @old_selector: selector for starting voltage
* @new_selector: selector for target voltage
*
@ -2388,6 +2423,8 @@ static int _regulator_get_voltage(struct regulator_dev *rdev)
ret = rdev->desc->ops->list_voltage(rdev, sel);
} else if (rdev->desc->ops->get_voltage) {
ret = rdev->desc->ops->get_voltage(rdev);
} else if (rdev->desc->ops->list_voltage) {
ret = rdev->desc->ops->list_voltage(rdev, 0);
} else {
return -EINVAL;
}
@ -2673,6 +2710,100 @@ out:
}
EXPORT_SYMBOL_GPL(regulator_set_optimum_mode);
/**
* regulator_set_bypass_regmap - Default set_bypass() using regmap
*
* @rdev: device to operate on.
* @enable: state to set.
*/
int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable)
{
unsigned int val;
if (enable)
val = rdev->desc->bypass_mask;
else
val = 0;
return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg,
rdev->desc->bypass_mask, val);
}
EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap);
/**
* regulator_get_bypass_regmap - Default get_bypass() using regmap
*
* @rdev: device to operate on.
* @enable: current state.
*/
int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable)
{
unsigned int val;
int ret;
ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val);
if (ret != 0)
return ret;
*enable = val & rdev->desc->bypass_mask;
return 0;
}
EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap);
/**
* regulator_allow_bypass - allow the regulator to go into bypass mode
*
* @regulator: Regulator to configure
* @allow: enable or disable bypass mode
*
* Allow the regulator to go into bypass mode if all other consumers
* for the regulator also enable bypass mode and the machine
* constraints allow this. Bypass mode means that the regulator is
* simply passing the input directly to the output with no regulation.
*/
int regulator_allow_bypass(struct regulator *regulator, bool enable)
{
struct regulator_dev *rdev = regulator->rdev;
int ret = 0;
if (!rdev->desc->ops->set_bypass)
return 0;
if (rdev->constraints &&
!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS))
return 0;
mutex_lock(&rdev->mutex);
if (enable && !regulator->bypass) {
rdev->bypass_count++;
if (rdev->bypass_count == rdev->open_count) {
ret = rdev->desc->ops->set_bypass(rdev, enable);
if (ret != 0)
rdev->bypass_count--;
}
} else if (!enable && regulator->bypass) {
rdev->bypass_count--;
if (rdev->bypass_count != rdev->open_count) {
ret = rdev->desc->ops->set_bypass(rdev, enable);
if (ret != 0)
rdev->bypass_count++;
}
}
if (ret == 0)
regulator->bypass = enable;
mutex_unlock(&rdev->mutex);
return ret;
}
EXPORT_SYMBOL_GPL(regulator_allow_bypass);
/**
* regulator_register_notifier - register regulator event notifier
* @regulator: regulator source
@ -3011,7 +3142,8 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
/* some attributes need specific methods to be displayed */
if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) ||
(ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0)) {
(ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) ||
(ops->list_voltage && ops->list_voltage(rdev, 0) >= 0)) {
status = device_create_file(dev, &dev_attr_microvolts);
if (status < 0)
return status;
@ -3036,6 +3168,11 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
if (status < 0)
return status;
}
if (ops->get_bypass) {
status = device_create_file(dev, &dev_attr_bypass);
if (status < 0)
return status;
}
/* some attributes are type-specific */
if (rdev->desc->type == REGULATOR_CURRENT) {
@ -3124,6 +3261,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
&rdev->use_count);
debugfs_create_u32("open_count", 0444, rdev->debugfs,
&rdev->open_count);
debugfs_create_u32("bypass_count", 0444, rdev->debugfs,
&rdev->bypass_count);
}
/**
@ -3189,8 +3328,10 @@ regulator_register(const struct regulator_desc *regulator_desc,
rdev->desc = regulator_desc;
if (config->regmap)
rdev->regmap = config->regmap;
else
else if (dev_get_regmap(dev, NULL))
rdev->regmap = dev_get_regmap(dev, NULL);
else if (dev->parent)
rdev->regmap = dev_get_regmap(dev->parent, NULL);
INIT_LIST_HEAD(&rdev->consumer_list);
INIT_LIST_HEAD(&rdev->list);
BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);

View File

@ -133,8 +133,8 @@ static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA,
max_uA < da9052_current_limits[row][DA9052_MIN_UA])
return -EINVAL;
for (i = 0; i < DA9052_CURRENT_RANGE; i++) {
if (min_uA <= da9052_current_limits[row][i]) {
for (i = DA9052_CURRENT_RANGE - 1; i >= 0; i--) {
if (da9052_current_limits[row][i] <= max_uA) {
reg_val = i;
break;
}

View File

@ -30,7 +30,7 @@ static struct regulator_init_data dummy_initdata;
static struct regulator_ops dummy_ops;
static struct regulator_desc dummy_desc = {
.name = "dummy",
.name = "regulator-dummy",
.id = -1,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,

View File

@ -0,0 +1,322 @@
/*
* FAN53555 Fairchild Digitally Programmable TinyBuck Regulator Driver.
*
* Supported Part Numbers:
* FAN53555UC00X/01X/03X/04X/05X
*
* Copyright (c) 2012 Marvell Technology Ltd.
* Yunfan Zhang <yfzhang@marvell.com>
*
* This package 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/param.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/regmap.h>
#include <linux/regulator/fan53555.h>
/* Voltage setting */
#define FAN53555_VSEL0 0x00
#define FAN53555_VSEL1 0x01
/* Control register */
#define FAN53555_CONTROL 0x02
/* IC Type */
#define FAN53555_ID1 0x03
/* IC mask version */
#define FAN53555_ID2 0x04
/* Monitor register */
#define FAN53555_MONITOR 0x05
/* VSEL bit definitions */
#define VSEL_BUCK_EN (1 << 7)
#define VSEL_MODE (1 << 6)
#define VSEL_NSEL_MASK 0x3F
/* Chip ID and Verison */
#define DIE_ID 0x0F /* ID1 */
#define DIE_REV 0x0F /* ID2 */
/* Control bit definitions */
#define CTL_OUTPUT_DISCHG (1 << 7)
#define CTL_SLEW_MASK (0x7 << 4)
#define CTL_SLEW_SHIFT 4
#define CTL_RESET (1 << 2)
#define FAN53555_NVOLTAGES 64 /* Numbers of voltages */
/* IC Type */
enum {
FAN53555_CHIP_ID_00 = 0,
FAN53555_CHIP_ID_01,
FAN53555_CHIP_ID_02,
FAN53555_CHIP_ID_03,
FAN53555_CHIP_ID_04,
FAN53555_CHIP_ID_05,
};
struct fan53555_device_info {
struct regmap *regmap;
struct device *dev;
struct regulator_desc desc;
struct regulator_dev *rdev;
struct regulator_init_data *regulator;
/* IC Type and Rev */
int chip_id;
int chip_rev;
/* Voltage setting register */
unsigned int vol_reg;
unsigned int sleep_reg;
/* Voltage range and step(linear) */
unsigned int vsel_min;
unsigned int vsel_step;
/* Voltage slew rate limiting */
unsigned int slew_rate;
/* Sleep voltage cache */
unsigned int sleep_vol_cache;
};
static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV)
{
struct fan53555_device_info *di = rdev_get_drvdata(rdev);
int ret;
if (di->sleep_vol_cache == uV)
return 0;
ret = regulator_map_voltage_linear(rdev, uV, uV);
if (ret < 0)
return -EINVAL;
ret = regmap_update_bits(di->regmap, di->sleep_reg,
VSEL_NSEL_MASK, ret);
if (ret < 0)
return -EINVAL;
/* Cache the sleep voltage setting.
* Might not be the real voltage which is rounded */
di->sleep_vol_cache = uV;
return 0;
}
static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct fan53555_device_info *di = rdev_get_drvdata(rdev);
switch (mode) {
case REGULATOR_MODE_FAST:
regmap_update_bits(di->regmap, di->vol_reg,
VSEL_MODE, VSEL_MODE);
break;
case REGULATOR_MODE_NORMAL:
regmap_update_bits(di->regmap, di->vol_reg, VSEL_MODE, 0);
break;
default:
return -EINVAL;
}
return 0;
}
static unsigned int fan53555_get_mode(struct regulator_dev *rdev)
{
struct fan53555_device_info *di = rdev_get_drvdata(rdev);
unsigned int val;
int ret = 0;
ret = regmap_read(di->regmap, di->vol_reg, &val);
if (ret < 0)
return ret;
if (val & VSEL_MODE)
return REGULATOR_MODE_FAST;
else
return REGULATOR_MODE_NORMAL;
}
static struct regulator_ops fan53555_regulator_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.map_voltage = regulator_map_voltage_linear,
.list_voltage = regulator_list_voltage_linear,
.set_suspend_voltage = fan53555_set_suspend_voltage,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.set_mode = fan53555_set_mode,
.get_mode = fan53555_get_mode,
};
/* For 00,01,03,05 options:
* VOUT = 0.60V + NSELx * 10mV, from 0.60 to 1.23V.
* For 04 option:
* VOUT = 0.603V + NSELx * 12.826mV, from 0.603 to 1.411V.
* */
static int fan53555_device_setup(struct fan53555_device_info *di,
struct fan53555_platform_data *pdata)
{
unsigned int reg, data, mask;
/* Setup voltage control register */
switch (pdata->sleep_vsel_id) {
case FAN53555_VSEL_ID_0:
di->sleep_reg = FAN53555_VSEL0;
di->vol_reg = FAN53555_VSEL1;
break;
case FAN53555_VSEL_ID_1:
di->sleep_reg = FAN53555_VSEL1;
di->vol_reg = FAN53555_VSEL0;
break;
default:
dev_err(di->dev, "Invalid VSEL ID!\n");
return -EINVAL;
}
/* Init voltage range and step */
switch (di->chip_id) {
case FAN53555_CHIP_ID_00:
case FAN53555_CHIP_ID_01:
case FAN53555_CHIP_ID_03:
case FAN53555_CHIP_ID_05:
di->vsel_min = 600000;
di->vsel_step = 10000;
break;
case FAN53555_CHIP_ID_04:
di->vsel_min = 603000;
di->vsel_step = 12826;
break;
default:
dev_err(di->dev,
"Chip ID[%d]\n not supported!\n", di->chip_id);
return -EINVAL;
}
/* Init slew rate */
if (pdata->slew_rate & 0x7)
di->slew_rate = pdata->slew_rate;
else
di->slew_rate = FAN53555_SLEW_RATE_64MV;
reg = FAN53555_CONTROL;
data = di->slew_rate << CTL_SLEW_SHIFT;
mask = CTL_SLEW_MASK;
return regmap_update_bits(di->regmap, reg, mask, data);
}
static int fan53555_regulator_register(struct fan53555_device_info *di,
struct regulator_config *config)
{
struct regulator_desc *rdesc = &di->desc;
rdesc->name = "fan53555-reg";
rdesc->ops = &fan53555_regulator_ops;
rdesc->type = REGULATOR_VOLTAGE;
rdesc->n_voltages = FAN53555_NVOLTAGES;
rdesc->enable_reg = di->vol_reg;
rdesc->enable_mask = VSEL_BUCK_EN;
rdesc->min_uV = di->vsel_min;
rdesc->uV_step = di->vsel_step;
rdesc->vsel_reg = di->vol_reg;
rdesc->vsel_mask = VSEL_NSEL_MASK;
rdesc->owner = THIS_MODULE;
di->rdev = regulator_register(&di->desc, config);
if (IS_ERR(di->rdev))
return PTR_ERR(di->rdev);
return 0;
}
static struct regmap_config fan53555_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static int __devinit fan53555_regulator_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct fan53555_device_info *di;
struct fan53555_platform_data *pdata;
struct regulator_config config = { };
unsigned int val;
int ret;
pdata = client->dev.platform_data;
if (!pdata || !pdata->regulator) {
dev_err(&client->dev, "Platform data not found!\n");
return -ENODEV;
}
di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info),
GFP_KERNEL);
if (!di) {
dev_err(&client->dev, "Failed to allocate device info data!\n");
return -ENOMEM;
}
di->regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config);
if (IS_ERR(di->regmap)) {
dev_err(&client->dev, "Failed to allocate regmap!\n");
return PTR_ERR(di->regmap);
}
di->dev = &client->dev;
di->regulator = pdata->regulator;
i2c_set_clientdata(client, di);
/* Get chip ID */
ret = regmap_read(di->regmap, FAN53555_ID1, &val);
if (ret < 0) {
dev_err(&client->dev, "Failed to get chip ID!\n");
return -ENODEV;
}
di->chip_id = val & DIE_ID;
/* Get chip revision */
ret = regmap_read(di->regmap, FAN53555_ID2, &val);
if (ret < 0) {
dev_err(&client->dev, "Failed to get chip Rev!\n");
return -ENODEV;
}
di->chip_rev = val & DIE_REV;
dev_info(&client->dev, "FAN53555 Option[%d] Rev[%d] Detected!\n",
di->chip_id, di->chip_rev);
/* Device init */
ret = fan53555_device_setup(di, pdata);
if (ret < 0) {
dev_err(&client->dev, "Failed to setup device!\n");
return ret;
}
/* Register regulator */
config.dev = di->dev;
config.init_data = di->regulator;
config.regmap = di->regmap;
config.driver_data = di;
ret = fan53555_regulator_register(di, &config);
if (ret < 0)
dev_err(&client->dev, "Failed to register regulator!\n");
return ret;
}
static int __devexit fan53555_regulator_remove(struct i2c_client *client)
{
struct fan53555_device_info *di = i2c_get_clientdata(client);
regulator_unregister(di->rdev);
return 0;
}
static const struct i2c_device_id fan53555_id[] = {
{"fan53555", -1},
{ },
};
static struct i2c_driver fan53555_regulator_driver = {
.driver = {
.name = "fan53555-regulator",
},
.probe = fan53555_regulator_probe,
.remove = __devexit_p(fan53555_regulator_remove),
.id_table = fan53555_id,
};
module_i2c_driver(fan53555_regulator_driver);
MODULE_AUTHOR("Yunfan Zhang <yfzhang@marvell.com>");
MODULE_DESCRIPTION("FAN53555 regulator driver");
MODULE_LICENSE("GPL v2");

View File

@ -73,13 +73,7 @@ static struct regulator_ops isl_core_ops = {
.map_voltage = regulator_map_voltage_linear,
};
static int isl6271a_get_fixed_voltage(struct regulator_dev *dev)
{
return dev->desc->min_uV;
}
static struct regulator_ops isl_fixed_ops = {
.get_voltage = isl6271a_get_fixed_voltage,
.list_voltage = regulator_list_voltage_linear,
};

View File

@ -86,6 +86,10 @@
#define EXTERN_DVS_USED 0
#define MAX_DELAY 6
/* Default DVS Mode */
#define LP8720_DEFAULT_DVS 0
#define LP8725_DEFAULT_DVS BIT(2)
/* dump registers in regmap-debugfs */
#define MAX_REGISTERS 0x0F
@ -269,9 +273,9 @@ static int lp872x_regulator_enable_time(struct regulator_dev *rdev)
return val > MAX_DELAY ? 0 : val * time_step_us;
}
static void lp872x_set_dvs(struct lp872x *lp, int gpio)
static void lp872x_set_dvs(struct lp872x *lp, enum lp872x_dvs_sel dvs_sel,
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;
@ -339,10 +343,10 @@ static int lp872x_buck_set_voltage_sel(struct regulator_dev *rdev,
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;
struct lp872x_dvs *dvs = lp->pdata ? lp->pdata->dvs : NULL;
if (dvs && gpio_is_valid(dvs->gpio))
lp872x_set_dvs(lp, dvs->gpio);
lp872x_set_dvs(lp, dvs->vsel, dvs->gpio);
addr = lp872x_select_buck_vout_addr(lp, buck);
if (!lp872x_is_valid_buck_addr(addr))
@ -374,8 +378,8 @@ static int lp8725_buck_set_current_limit(struct regulator_dev *rdev,
{
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;
int i;
u8 addr;
switch (buck) {
case LP8725_ID_BUCK1:
@ -388,17 +392,15 @@ static int lp8725_buck_set_current_limit(struct regulator_dev *rdev,
return -EINVAL;
}
for (i = 0 ; i < max ; i++)
for (i = ARRAY_SIZE(lp8725_buck_uA) - 1 ; i >= 0; i--) {
if (lp8725_buck_uA[i] >= min_uA &&
lp8725_buck_uA[i] <= max_uA)
break;
return lp872x_update_bits(lp, addr,
LP8725_BUCK_CL_M,
i << LP8725_BUCK_CL_S);
}
if (i == max)
return -EINVAL;
val = i << LP8725_BUCK_CL_S;
return lp872x_update_bits(lp, addr, LP8725_BUCK_CL_M, val);
return -EINVAL;
}
static int lp8725_buck_get_current_limit(struct regulator_dev *rdev)
@ -727,39 +729,16 @@ static struct regulator_desc lp8725_regulator_desc[] = {
},
};
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;
struct lp872x_dvs *dvs = lp->pdata ? lp->pdata->dvs : NULL;
enum lp872x_dvs_state pinstate;
u8 mask[] = { LP8720_EXT_DVS_M, LP8725_DVS1_M | LP8725_DVS2_M };
u8 default_dvs_mode[] = { LP8720_DEFAULT_DVS, LP8725_DEFAULT_DVS };
ret = lp872x_check_dvs_validity(lp);
if (ret) {
dev_warn(lp->dev, "invalid dvs data: %d\n", ret);
return ret;
}
if (!dvs)
goto set_default_dvs_mode;
gpio = dvs->gpio;
if (!gpio_is_valid(gpio)) {
@ -778,6 +757,10 @@ static int lp872x_init_dvs(struct lp872x *lp)
lp->dvs_gpio = gpio;
return 0;
set_default_dvs_mode:
return lp872x_update_bits(lp, LP872X_GENERAL_CFG, mask[lp->chipid],
default_dvs_mode[lp->chipid]);
}
static int lp872x_config(struct lp872x *lp)
@ -785,24 +768,29 @@ static int lp872x_config(struct lp872x *lp)
struct lp872x_platform_data *pdata = lp->pdata;
int ret;
if (!pdata->update_config)
return 0;
if (!pdata || !pdata->update_config)
goto init_dvs;
ret = lp872x_write_byte(lp, LP872X_GENERAL_CFG, pdata->general_config);
if (ret)
return ret;
init_dvs:
return lp872x_init_dvs(lp);
}
static struct regulator_init_data
*lp872x_find_regulator_init_data(int id, struct lp872x *lp)
{
struct lp872x_platform_data *pdata = lp->pdata;
int i;
if (!pdata)
return NULL;
for (i = 0; i < lp->num_regulators; i++) {
if (lp->pdata->regulator_data[i].id == id)
return lp->pdata->regulator_data[i].init_data;
if (pdata->regulator_data[i].id == id)
return pdata->regulator_data[i].init_data;
}
return NULL;
@ -863,18 +851,12 @@ static const struct regmap_config lp872x_regmap_config = {
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;
@ -894,7 +876,7 @@ static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
}
lp->dev = &cl->dev;
lp->pdata = pdata;
lp->pdata = cl->dev.platform_data;
lp->chipid = id->driver_data;
lp->num_regulators = num_regulators;
i2c_set_clientdata(cl, lp);

View File

@ -69,6 +69,9 @@
#define PIN_HIGH 1
#define ENABLE_TIME_USEC 32
#define BUCK_FPWM_MASK(x) (1 << (x))
#define BUCK_FPWM_SHIFT(x) (x)
enum lp8788_dvs_state {
DVS_LOW = GPIOF_OUT_INIT_LOW,
DVS_HIGH = GPIOF_OUT_INIT_HIGH,
@ -86,15 +89,9 @@ enum lp8788_buck_id {
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;
};
@ -106,29 +103,6 @@ static const int lp8788_buck_vtbl[] = {
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,
@ -347,41 +321,37 @@ static int lp8788_buck_enable_time(struct regulator_dev *rdev)
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;
enum lp8788_buck_id id = rdev_get_id(rdev);
u8 mask, val;
mask = BUCK_FPWM_MASK(id);
switch (mode) {
case REGULATOR_MODE_FAST:
val = LP8788_FORCE_PWM << pmap->shift;
val = LP8788_FORCE_PWM << BUCK_FPWM_SHIFT(id);
break;
case REGULATOR_MODE_NORMAL:
val = LP8788_AUTO_PWM << pmap->shift;
val = LP8788_AUTO_PWM << BUCK_FPWM_SHIFT(id);
break;
default:
return -EINVAL;
}
return lp8788_update_bits(buck->lp, LP8788_BUCK_PWM, pmap->mask, val);
return lp8788_update_bits(buck->lp, LP8788_BUCK_PWM, 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;
enum lp8788_buck_id id = rdev_get_id(rdev);
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;
return val & BUCK_FPWM_MASK(id) ?
REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
}
static struct regulator_ops lp8788_buck12_ops = {
@ -459,27 +429,6 @@ static struct regulator_desc lp8788_buck_desc[] = {
},
};
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;
@ -530,6 +479,7 @@ 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 };
u8 default_dvs_mode[] = { LP8788_BUCK1_DVS_I2C, LP8788_BUCK2_DVS_I2C };
/* no dvs for buck3, 4 */
if (id == BUCK3 || id == BUCK4)
@ -550,7 +500,8 @@ static int lp8788_init_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id)
val[id]);
set_default_dvs_mode:
return lp8788_set_default_dvs_ctrl_mode(buck->lp, id);
return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id],
default_dvs_mode[id]);
}
static __devinit int lp8788_buck_probe(struct platform_device *pdev)
@ -567,7 +518,6 @@ static __devinit int lp8788_buck_probe(struct platform_device *pdev)
return -ENOMEM;
buck->lp = lp;
buck->pmap = &buck_pmap[id];
ret = lp8788_init_dvs(buck, id);
if (ret)

View File

@ -496,6 +496,7 @@ static struct regulator_desc lp8788_dldo_desc[] = {
.name = "dldo12",
.id = DLDO12,
.ops = &lp8788_ldo_voltage_fixed_ops,
.n_voltages = 1,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.enable_reg = LP8788_EN_LDO_B,
@ -521,6 +522,7 @@ static struct regulator_desc lp8788_aldo_desc[] = {
.name = "aldo2",
.id = ALDO2,
.ops = &lp8788_ldo_voltage_fixed_ops,
.n_voltages = 1,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.enable_reg = LP8788_EN_LDO_B,
@ -530,6 +532,7 @@ static struct regulator_desc lp8788_aldo_desc[] = {
.name = "aldo3",
.id = ALDO3,
.ops = &lp8788_ldo_voltage_fixed_ops,
.n_voltages = 1,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.enable_reg = LP8788_EN_LDO_B,
@ -539,6 +542,7 @@ static struct regulator_desc lp8788_aldo_desc[] = {
.name = "aldo4",
.id = ALDO4,
.ops = &lp8788_ldo_voltage_fixed_ops,
.n_voltages = 1,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.enable_reg = LP8788_EN_LDO_B,
@ -548,6 +552,7 @@ static struct regulator_desc lp8788_aldo_desc[] = {
.name = "aldo5",
.id = ALDO5,
.ops = &lp8788_ldo_voltage_fixed_ops,
.n_voltages = 1,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.enable_reg = LP8788_EN_LDO_C,
@ -583,6 +588,7 @@ static struct regulator_desc lp8788_aldo_desc[] = {
.name = "aldo8",
.id = ALDO8,
.ops = &lp8788_ldo_voltage_fixed_ops,
.n_voltages = 1,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.enable_reg = LP8788_EN_LDO_C,
@ -592,6 +598,7 @@ static struct regulator_desc lp8788_aldo_desc[] = {
.name = "aldo9",
.id = ALDO9,
.ops = &lp8788_ldo_voltage_fixed_ops,
.n_voltages = 1,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.enable_reg = LP8788_EN_LDO_C,
@ -601,6 +608,7 @@ static struct regulator_desc lp8788_aldo_desc[] = {
.name = "aldo10",
.id = ALDO10,
.ops = &lp8788_ldo_voltage_fixed_ops,
.n_voltages = 1,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.enable_reg = LP8788_EN_LDO_C,

View File

@ -66,7 +66,7 @@ enum max77686_ramp_rate {
};
struct max77686_data {
struct regulator_dev **rdev;
struct regulator_dev *rdev[MAX77686_REGULATORS];
};
static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
@ -265,6 +265,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
rmatch.of_node = NULL;
of_regulator_match(iodev->dev, regulators_np, &rmatch, 1);
rdata[i].initdata = rmatch.init_data;
rdata[i].of_node = rmatch.of_node;
}
pdata->regulators = rdata;
@ -283,10 +284,8 @@ 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;
int i, ret = 0;
struct regulator_config config = { };
dev_dbg(&pdev->dev, "%s\n", __func__);
@ -313,45 +312,38 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev)
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;
config.of_node = pdata->regulators[i].of_node;
rdev[i] = regulator_register(&regulators[i], &config);
if (IS_ERR(rdev[i])) {
ret = PTR_ERR(rdev[i]);
max77686->rdev[i] = regulator_register(&regulators[i], &config);
if (IS_ERR(max77686->rdev[i])) {
ret = PTR_ERR(max77686->rdev[i]);
dev_err(&pdev->dev,
"regulator init failed for %d\n", i);
rdev[i] = NULL;
goto err;
max77686->rdev[i] = NULL;
goto err;
}
}
return 0;
err:
while (--i >= 0)
regulator_unregister(rdev[i]);
regulator_unregister(max77686->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]);
regulator_unregister(max77686->rdev[i]);
return 0;
}

View File

@ -0,0 +1,408 @@
/*
* max8907-regulator.c -- support regulators in max8907
*
* Copyright (C) 2010 Gyungoh Yoo <jack.yoo@maxim-ic.com>
* Copyright (C) 2010-2012, NVIDIA CORPORATION. All rights reserved.
*
* Portions based on drivers/regulator/tps65910-regulator.c,
* Copyright 2010 Texas Instruments Inc.
* Author: Graeme Gregory <gg@slimlogic.co.uk>
* Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/mfd/core.h>
#include <linux/mfd/max8907.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#define MAX8907_II2RR_VERSION_MASK 0xF0
#define MAX8907_II2RR_VERSION_REV_A 0x00
#define MAX8907_II2RR_VERSION_REV_B 0x10
#define MAX8907_II2RR_VERSION_REV_C 0x30
struct max8907_regulator {
struct regulator_desc desc[MAX8907_NUM_REGULATORS];
struct regulator_dev *rdev[MAX8907_NUM_REGULATORS];
};
#define REG_MBATT() \
[MAX8907_MBATT] = { \
.name = "MBATT", \
.supply_name = "mbatt", \
.id = MAX8907_MBATT, \
.ops = &max8907_mbatt_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}
#define REG_LDO(ids, supply, base, min, max, step) \
[MAX8907_##ids] = { \
.name = #ids, \
.supply_name = supply, \
.id = MAX8907_##ids, \
.n_voltages = ((max) - (min)) / (step) + 1, \
.ops = &max8907_ldo_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.min_uV = (min), \
.uV_step = (step), \
.vsel_reg = (base) + MAX8907_VOUT, \
.vsel_mask = 0x3f, \
.enable_reg = (base) + MAX8907_CTL, \
.enable_mask = MAX8907_MASK_LDO_EN, \
}
#define REG_FIXED(ids, supply, voltage) \
[MAX8907_##ids] = { \
.name = #ids, \
.supply_name = supply, \
.id = MAX8907_##ids, \
.n_voltages = 1, \
.ops = &max8907_fixed_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.min_uV = (voltage), \
}
#define REG_OUT5V(ids, supply, base, voltage) \
[MAX8907_##ids] = { \
.name = #ids, \
.supply_name = supply, \
.id = MAX8907_##ids, \
.n_voltages = 1, \
.ops = &max8907_out5v_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.min_uV = (voltage), \
.enable_reg = (base), \
.enable_mask = MAX8907_MASK_OUT5V_EN, \
}
#define REG_BBAT(ids, supply, base, min, max, step) \
[MAX8907_##ids] = { \
.name = #ids, \
.supply_name = supply, \
.id = MAX8907_##ids, \
.n_voltages = ((max) - (min)) / (step) + 1, \
.ops = &max8907_bbat_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.min_uV = (min), \
.uV_step = (step), \
.vsel_reg = (base), \
.vsel_mask = MAX8907_MASK_VBBATTCV, \
}
#define LDO_750_50(id, supply, base) REG_LDO(id, supply, (base), \
750000, 3900000, 50000)
#define LDO_650_25(id, supply, base) REG_LDO(id, supply, (base), \
650000, 2225000, 25000)
static struct regulator_ops max8907_mbatt_ops = {
};
static struct regulator_ops max8907_ldo_ops = {
.list_voltage = regulator_list_voltage_linear,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
};
static struct regulator_ops max8907_ldo_hwctl_ops = {
.list_voltage = regulator_list_voltage_linear,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
};
static struct regulator_ops max8907_fixed_ops = {
.list_voltage = regulator_list_voltage_linear,
};
static struct regulator_ops max8907_out5v_ops = {
.list_voltage = regulator_list_voltage_linear,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
};
static struct regulator_ops max8907_out5v_hwctl_ops = {
.list_voltage = regulator_list_voltage_linear,
};
static struct regulator_ops max8907_bbat_ops = {
.list_voltage = regulator_list_voltage_linear,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
};
static struct regulator_desc max8907_regulators[] = {
REG_MBATT(),
REG_LDO(SD1, "in-v1", MAX8907_REG_SDCTL1, 650000, 2225000, 25000),
REG_LDO(SD2, "in-v2", MAX8907_REG_SDCTL2, 637500, 1425000, 12500),
REG_LDO(SD3, "in-v3", MAX8907_REG_SDCTL3, 750000, 3900000, 50000),
LDO_750_50(LDO1, "in1", MAX8907_REG_LDOCTL1),
LDO_650_25(LDO2, "in2", MAX8907_REG_LDOCTL2),
LDO_650_25(LDO3, "in3", MAX8907_REG_LDOCTL3),
LDO_750_50(LDO4, "in4", MAX8907_REG_LDOCTL4),
LDO_750_50(LDO5, "in5", MAX8907_REG_LDOCTL5),
LDO_750_50(LDO6, "in6", MAX8907_REG_LDOCTL6),
LDO_750_50(LDO7, "in7", MAX8907_REG_LDOCTL7),
LDO_750_50(LDO8, "in8", MAX8907_REG_LDOCTL8),
LDO_750_50(LDO9, "in9", MAX8907_REG_LDOCTL9),
LDO_750_50(LDO10, "in10", MAX8907_REG_LDOCTL10),
LDO_750_50(LDO11, "in11", MAX8907_REG_LDOCTL11),
LDO_750_50(LDO12, "in12", MAX8907_REG_LDOCTL12),
LDO_750_50(LDO13, "in13", MAX8907_REG_LDOCTL13),
LDO_750_50(LDO14, "in14", MAX8907_REG_LDOCTL14),
LDO_750_50(LDO15, "in15", MAX8907_REG_LDOCTL15),
LDO_750_50(LDO16, "in16", MAX8907_REG_LDOCTL16),
LDO_650_25(LDO17, "in17", MAX8907_REG_LDOCTL17),
LDO_650_25(LDO18, "in18", MAX8907_REG_LDOCTL18),
LDO_750_50(LDO19, "in19", MAX8907_REG_LDOCTL19),
LDO_750_50(LDO20, "in20", MAX8907_REG_LDOCTL20),
REG_OUT5V(OUT5V, "mbatt", MAX8907_REG_OUT5VEN, 5000000),
REG_OUT5V(OUT33V, "mbatt", MAX8907_REG_OUT33VEN, 3300000),
REG_BBAT(BBAT, "MBATT", MAX8907_REG_BBAT_CNFG,
2400000, 3000000, 200000),
REG_FIXED(SDBY, "MBATT", 1200000),
REG_FIXED(VRTC, "MBATT", 3300000),
};
#ifdef CONFIG_OF
#define MATCH(_name, _id) \
[MAX8907_##_id] = { \
.name = #_name, \
.driver_data = (void *)&max8907_regulators[MAX8907_##_id], \
}
static struct of_regulator_match max8907_matches[] = {
MATCH(mbatt, MBATT),
MATCH(sd1, SD1),
MATCH(sd2, SD2),
MATCH(sd3, SD3),
MATCH(ldo1, LDO1),
MATCH(ldo2, LDO2),
MATCH(ldo3, LDO3),
MATCH(ldo4, LDO4),
MATCH(ldo5, LDO5),
MATCH(ldo6, LDO6),
MATCH(ldo7, LDO7),
MATCH(ldo8, LDO8),
MATCH(ldo9, LDO9),
MATCH(ldo10, LDO10),
MATCH(ldo11, LDO11),
MATCH(ldo12, LDO12),
MATCH(ldo13, LDO13),
MATCH(ldo14, LDO14),
MATCH(ldo15, LDO15),
MATCH(ldo16, LDO16),
MATCH(ldo17, LDO17),
MATCH(ldo18, LDO18),
MATCH(ldo19, LDO19),
MATCH(ldo20, LDO20),
MATCH(out5v, OUT5V),
MATCH(out33v, OUT33V),
MATCH(bbat, BBAT),
MATCH(sdby, SDBY),
MATCH(vrtc, VRTC),
};
static int max8907_regulator_parse_dt(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.parent->of_node;
struct device_node *regulators;
int ret;
if (!pdev->dev.parent->of_node)
return 0;
regulators = of_find_node_by_name(np, "regulators");
if (!regulators) {
dev_err(&pdev->dev, "regulators node not found\n");
return -EINVAL;
}
ret = of_regulator_match(pdev->dev.parent, regulators,
max8907_matches,
ARRAY_SIZE(max8907_matches));
if (ret < 0) {
dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",
ret);
return ret;
}
return 0;
}
static inline struct regulator_init_data *match_init_data(int index)
{
return max8907_matches[index].init_data;
}
static inline struct device_node *match_of_node(int index)
{
return max8907_matches[index].of_node;
}
#else
static int max8907_regulator_parse_dt(struct platform_device *pdev)
{
return 0;
}
static inline struct regulator_init_data *match_init_data(int index)
{
return NULL;
}
static inline struct device_node *match_of_node(int index)
{
return NULL;
}
#endif
static __devinit int max8907_regulator_probe(struct platform_device *pdev)
{
struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);
struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev);
int ret;
struct max8907_regulator *pmic;
unsigned int val;
int i;
struct regulator_config config = {};
struct regulator_init_data *idata;
const char *mbatt_rail_name = NULL;
ret = max8907_regulator_parse_dt(pdev);
if (ret)
return ret;
pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
if (!pmic) {
dev_err(&pdev->dev, "Failed to alloc pmic\n");
return -ENOMEM;
}
platform_set_drvdata(pdev, pmic);
memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc));
/* Backwards compatibility with MAX8907B; SD1 uses different voltages */
regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val);
if ((val & MAX8907_II2RR_VERSION_MASK) ==
MAX8907_II2RR_VERSION_REV_B) {
pmic->desc[MAX8907_SD1].min_uV = 637500;
pmic->desc[MAX8907_SD1].uV_step = 12500;
pmic->desc[MAX8907_SD1].n_voltages =
(1425000 - 637500) / 12500 + 1;
}
for (i = 0; i < MAX8907_NUM_REGULATORS; i++) {
config.dev = pdev->dev.parent;
if (pdata)
idata = pdata->init_data[i];
else
idata = match_init_data(i);
config.init_data = idata;
config.driver_data = pmic;
config.regmap = max8907->regmap_gen;
config.of_node = match_of_node(i);
switch (pmic->desc[i].id) {
case MAX8907_MBATT:
if (idata && idata->constraints.name)
mbatt_rail_name = idata->constraints.name;
else
mbatt_rail_name = pmic->desc[i].name;
break;
case MAX8907_BBAT:
case MAX8907_SDBY:
case MAX8907_VRTC:
idata->supply_regulator = mbatt_rail_name;
break;
}
if (pmic->desc[i].ops == &max8907_ldo_ops) {
regmap_read(config.regmap, pmic->desc[i].enable_reg,
&val);
if ((val & MAX8907_MASK_LDO_SEQ) !=
MAX8907_MASK_LDO_SEQ)
pmic->desc[i].ops = &max8907_ldo_hwctl_ops;
} else if (pmic->desc[i].ops == &max8907_out5v_ops) {
regmap_read(config.regmap, pmic->desc[i].enable_reg,
&val);
if ((val & (MAX8907_MASK_OUT5V_VINEN |
MAX8907_MASK_OUT5V_ENSRC)) !=
MAX8907_MASK_OUT5V_ENSRC)
pmic->desc[i].ops = &max8907_out5v_hwctl_ops;
}
pmic->rdev[i] = regulator_register(&pmic->desc[i], &config);
if (IS_ERR(pmic->rdev[i])) {
dev_err(&pdev->dev,
"failed to register %s regulator\n",
pmic->desc[i].name);
ret = PTR_ERR(pmic->rdev[i]);
goto err_unregister_regulator;
}
}
return 0;
err_unregister_regulator:
while (--i >= 0)
regulator_unregister(pmic->rdev[i]);
return ret;
}
static __devexit int max8907_regulator_remove(struct platform_device *pdev)
{
struct max8907_regulator *pmic = platform_get_drvdata(pdev);
int i;
for (i = 0; i < MAX8907_NUM_REGULATORS; i++)
regulator_unregister(pmic->rdev[i]);
return 0;
}
static struct platform_driver max8907_regulator_driver = {
.driver = {
.name = "max8907-regulator",
.owner = THIS_MODULE,
},
.probe = max8907_regulator_probe,
.remove = __devexit_p(max8907_regulator_remove),
};
static int __init max8907_regulator_init(void)
{
return platform_driver_register(&max8907_regulator_driver);
}
subsys_initcall(max8907_regulator_init);
static void __exit max8907_reg_exit(void)
{
platform_driver_unregister(&max8907_regulator_driver);
}
module_exit(max8907_reg_exit);
MODULE_DESCRIPTION("MAX8907 regulator driver");
MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@maxim-ic.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:max8907-regulator");

View File

@ -21,6 +21,30 @@
#include <linux/module.h>
#include "mc13xxx.h"
#define MC13783_REG_SWITCHERS0 24
/* Enable does not exist for SW1A */
#define MC13783_REG_SWITCHERS0_SW1AEN 0
#define MC13783_REG_SWITCHERS0_SW1AVSEL 0
#define MC13783_REG_SWITCHERS0_SW1AVSEL_M (63 << 0)
#define MC13783_REG_SWITCHERS1 25
/* Enable does not exist for SW1B */
#define MC13783_REG_SWITCHERS1_SW1BEN 0
#define MC13783_REG_SWITCHERS1_SW1BVSEL 0
#define MC13783_REG_SWITCHERS1_SW1BVSEL_M (63 << 0)
#define MC13783_REG_SWITCHERS2 26
/* Enable does not exist for SW2A */
#define MC13783_REG_SWITCHERS2_SW2AEN 0
#define MC13783_REG_SWITCHERS2_SW2AVSEL 0
#define MC13783_REG_SWITCHERS2_SW2AVSEL_M (63 << 0)
#define MC13783_REG_SWITCHERS3 27
/* Enable does not exist for SW2B */
#define MC13783_REG_SWITCHERS3_SW2BEN 0
#define MC13783_REG_SWITCHERS3_SW2BVSEL 0
#define MC13783_REG_SWITCHERS3_SW2BVSEL_M (63 << 0)
#define MC13783_REG_SWITCHERS5 29
#define MC13783_REG_SWITCHERS5_SW3EN (1 << 20)
#define MC13783_REG_SWITCHERS5_SW3VSEL 18
@ -93,6 +117,44 @@
/* Voltage Values */
static const int mc13783_sw1x_val[] = {
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, 1575000,
1600000, 1625000, 1650000, 1675000,
1700000, 1700000, 1700000, 1700000,
1800000, 1800000, 1800000, 1800000,
1850000, 1850000, 1850000, 1850000,
2000000, 2000000, 2000000, 2000000,
2100000, 2100000, 2100000, 2100000,
2200000, 2200000, 2200000, 2200000,
2200000, 2200000, 2200000, 2200000,
2200000, 2200000, 2200000, 2200000,
};
static const int mc13783_sw2x_val[] = {
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, 1575000,
1600000, 1625000, 1650000, 1675000,
1700000, 1700000, 1700000, 1700000,
1800000, 1800000, 1800000, 1800000,
1900000, 1900000, 1900000, 1900000,
2000000, 2000000, 2000000, 2000000,
2100000, 2100000, 2100000, 2100000,
2200000, 2200000, 2200000, 2200000,
2200000, 2200000, 2200000, 2200000,
2200000, 2200000, 2200000, 2200000,
};
static const unsigned int mc13783_sw3_val[] = {
5000000, 5000000, 5000000, 5500000,
};
@ -188,6 +250,10 @@ static struct regulator_ops mc13783_gpo_regulator_ops;
MC13783_DEFINE(REG, _name, _reg, _vsel_reg, _voltages)
static struct mc13xxx_regulator mc13783_regulators[] = {
MC13783_DEFINE_SW(SW1A, SWITCHERS0, SWITCHERS0, mc13783_sw1x_val),
MC13783_DEFINE_SW(SW1B, SWITCHERS1, SWITCHERS1, mc13783_sw1x_val),
MC13783_DEFINE_SW(SW2A, SWITCHERS2, SWITCHERS2, mc13783_sw2x_val),
MC13783_DEFINE_SW(SW2B, SWITCHERS3, SWITCHERS3, mc13783_sw2x_val),
MC13783_DEFINE_SW(SW3, SWITCHERS5, SWITCHERS5, mc13783_sw3_val),
MC13783_FIXED_DEFINE(REG, VAUDIO, REGULATORMODE0, mc13783_vaudio_val),
@ -238,9 +304,10 @@ static int mc13783_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask,
BUG_ON(val & ~mask);
mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_read(mc13783, MC13783_REG_POWERMISC, &valread);
if (ret)
return ret;
goto out;
/* Update the stored state for Power Gates. */
priv->powermisc_pwgt_state =
@ -253,7 +320,10 @@ static int mc13783_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask,
valread = (valread & ~MC13783_REG_POWERMISC_PWGTSPI_M) |
priv->powermisc_pwgt_state;
return mc13xxx_reg_write(mc13783, MC13783_REG_POWERMISC, valread);
ret = mc13xxx_reg_write(mc13783, MC13783_REG_POWERMISC, valread);
out:
mc13xxx_unlock(priv->mc13xxx);
return ret;
}
static int mc13783_gpo_regulator_enable(struct regulator_dev *rdev)
@ -261,7 +331,6 @@ static int mc13783_gpo_regulator_enable(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);
int ret;
u32 en_val = mc13xxx_regulators[id].enable_bit;
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
@ -271,12 +340,8 @@ static int mc13783_gpo_regulator_enable(struct regulator_dev *rdev)
id == MC13783_REG_PWGT2SPI)
en_val = 0;
mc13xxx_lock(priv->mc13xxx);
ret = mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit,
return mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit,
en_val);
mc13xxx_unlock(priv->mc13xxx);
return ret;
}
static int mc13783_gpo_regulator_disable(struct regulator_dev *rdev)
@ -284,7 +349,6 @@ static int mc13783_gpo_regulator_disable(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);
int ret;
u32 dis_val = 0;
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
@ -294,12 +358,8 @@ static int mc13783_gpo_regulator_disable(struct regulator_dev *rdev)
id == MC13783_REG_PWGT2SPI)
dis_val = mc13xxx_regulators[id].enable_bit;
mc13xxx_lock(priv->mc13xxx);
ret = mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit,
return mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit,
dis_val);
mc13xxx_unlock(priv->mc13xxx);
return ret;
}
static int mc13783_gpo_regulator_is_enabled(struct regulator_dev *rdev)
@ -330,7 +390,6 @@ static struct regulator_ops mc13783_gpo_regulator_ops = {
.is_enabled = mc13783_gpo_regulator_is_enabled,
.list_voltage = regulator_list_voltage_table,
.set_voltage = mc13xxx_fixed_regulator_set_voltage,
.get_voltage = mc13xxx_fixed_regulator_get_voltage,
};
static int __devinit mc13783_regulator_probe(struct platform_device *pdev)

View File

@ -305,9 +305,10 @@ static int mc13892_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask,
BUG_ON(val & ~mask);
mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_read(mc13892, MC13892_POWERMISC, &valread);
if (ret)
return ret;
goto out;
/* Update the stored state for Power Gates. */
priv->powermisc_pwgt_state =
@ -320,14 +321,16 @@ static int mc13892_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask,
valread = (valread & ~MC13892_POWERMISC_PWGTSPI_M) |
priv->powermisc_pwgt_state;
return mc13xxx_reg_write(mc13892, MC13892_POWERMISC, valread);
ret = mc13xxx_reg_write(mc13892, MC13892_POWERMISC, valread);
out:
mc13xxx_unlock(priv->mc13xxx);
return ret;
}
static int mc13892_gpo_regulator_enable(struct regulator_dev *rdev)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
int id = rdev_get_id(rdev);
int ret;
u32 en_val = mc13892_regulators[id].enable_bit;
u32 mask = mc13892_regulators[id].enable_bit;
@ -340,18 +343,13 @@ static int mc13892_gpo_regulator_enable(struct regulator_dev *rdev)
if (id == MC13892_GPO4)
mask |= MC13892_POWERMISC_GPO4ADINEN;
mc13xxx_lock(priv->mc13xxx);
ret = mc13892_powermisc_rmw(priv, mask, en_val);
mc13xxx_unlock(priv->mc13xxx);
return ret;
return mc13892_powermisc_rmw(priv, mask, en_val);
}
static int mc13892_gpo_regulator_disable(struct regulator_dev *rdev)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
int id = rdev_get_id(rdev);
int ret;
u32 dis_val = 0;
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
@ -360,12 +358,8 @@ static int mc13892_gpo_regulator_disable(struct regulator_dev *rdev)
if (id == MC13892_PWGT1SPI || id == MC13892_PWGT2SPI)
dis_val = mc13892_regulators[id].enable_bit;
mc13xxx_lock(priv->mc13xxx);
ret = mc13892_powermisc_rmw(priv, mc13892_regulators[id].enable_bit,
return mc13892_powermisc_rmw(priv, mc13892_regulators[id].enable_bit,
dis_val);
mc13xxx_unlock(priv->mc13xxx);
return ret;
}
static int mc13892_gpo_regulator_is_enabled(struct regulator_dev *rdev)
@ -396,14 +390,13 @@ static struct regulator_ops mc13892_gpo_regulator_ops = {
.is_enabled = mc13892_gpo_regulator_is_enabled,
.list_voltage = regulator_list_voltage_table,
.set_voltage = mc13xxx_fixed_regulator_set_voltage,
.get_voltage = mc13xxx_fixed_regulator_get_voltage,
};
static int mc13892_sw_regulator_get_voltage(struct regulator_dev *rdev)
static int mc13892_sw_regulator_get_voltage_sel(struct regulator_dev *rdev)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
int ret, id = rdev_get_id(rdev);
unsigned int val, hi;
unsigned int val;
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
@ -414,17 +407,11 @@ static int mc13892_sw_regulator_get_voltage(struct regulator_dev *rdev)
if (ret)
return ret;
hi = val & MC13892_SWITCHERS0_SWxHI;
val = (val & mc13892_regulators[id].vsel_mask)
>> mc13892_regulators[id].vsel_shift;
dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val);
if (hi)
val = (25000 * val) + 1100000;
else
val = (25000 * val) + 600000;
return val;
}
@ -432,37 +419,25 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev,
unsigned selector)
{
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
int hi, value, mask, id = rdev_get_id(rdev);
u32 valread;
int volt, mask, id = rdev_get_id(rdev);
u32 reg_value;
int ret;
value = rdev->desc->volt_table[selector];
volt = rdev->desc->volt_table[selector];
mask = mc13892_regulators[id].vsel_mask;
reg_value = selector << mc13892_regulators[id].vsel_shift;
if (volt > 1375000) {
mask |= MC13892_SWITCHERS0_SWxHI;
reg_value |= MC13892_SWITCHERS0_SWxHI;
} else if (volt < 1100000) {
mask |= MC13892_SWITCHERS0_SWxHI;
reg_value &= ~MC13892_SWITCHERS0_SWxHI;
}
mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_read(priv->mc13xxx,
mc13892_regulators[id].vsel_reg, &valread);
if (ret)
goto err;
if (value > 1375000)
hi = 1;
else if (value < 1100000)
hi = 0;
else
hi = valread & MC13892_SWITCHERS0_SWxHI;
if (hi) {
value = (value - 1100000) / 25000;
value |= MC13892_SWITCHERS0_SWxHI;
} else
value = (value - 600000) / 25000;
mask = mc13892_regulators[id].vsel_mask | MC13892_SWITCHERS0_SWxHI;
valread = (valread & ~mask) |
(value << mc13892_regulators[id].vsel_shift);
ret = mc13xxx_reg_write(priv->mc13xxx, mc13892_regulators[id].vsel_reg,
valread);
err:
ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].reg, mask,
reg_value);
mc13xxx_unlock(priv->mc13xxx);
return ret;
@ -471,7 +446,7 @@ err:
static struct regulator_ops mc13892_sw_regulator_ops = {
.list_voltage = regulator_list_voltage_table,
.set_voltage_sel = mc13892_sw_regulator_set_voltage_sel,
.get_voltage = mc13892_sw_regulator_get_voltage,
.get_voltage_sel = mc13892_sw_regulator_get_voltage_sel,
};
static int mc13892_vcam_set_mode(struct regulator_dev *rdev, unsigned int mode)

View File

@ -143,30 +143,21 @@ int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
__func__, id, min_uV, max_uV);
if (min_uV <= rdev->desc->volt_table[0] &&
rdev->desc->volt_table[0] <= max_uV)
rdev->desc->volt_table[0] <= max_uV) {
*selector = 0;
return 0;
else
} else {
return -EINVAL;
}
}
EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_set_voltage);
int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev)
{
int id = rdev_get_id(rdev);
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
return rdev->desc->volt_table[0];
}
EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_get_voltage);
struct regulator_ops mc13xxx_fixed_regulator_ops = {
.enable = mc13xxx_regulator_enable,
.disable = mc13xxx_regulator_disable,
.is_enabled = mc13xxx_regulator_is_enabled,
.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);

View File

@ -34,7 +34,6 @@ struct mc13xxx_regulator_priv {
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);
#ifdef CONFIG_OF
extern int mc13xxx_get_num_regulators_dt(struct platform_device *pdev);

View File

@ -92,16 +92,18 @@ 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 when node
* property "regulator-compatible" matches with the regulator name.
* of_regulator_match - extract multiple regulator init data from device tree.
* @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 if
* regulator-compatible matches. Note that the match table is modified
* This function uses a match table specified by the regulator driver to
* parse regulator init data from the device tree. @node is expected to
* contain a set of child nodes, each providing the init data for one
* regulator. The data parsed from a child node will be matched to a regulator
* based on either the deprecated property regulator-compatible if present,
* or otherwise the child node's name. Note that the match table is modified
* in place.
*
* Returns the number of matches found or a negative error code on failure.
@ -112,26 +114,23 @@ int of_regulator_match(struct device *dev, struct device_node *node,
{
unsigned int count = 0;
unsigned int i;
const char *regulator_comp;
const char *name;
struct device_node *child;
if (!dev || !node)
return -EINVAL;
for_each_child_of_node(node, child) {
regulator_comp = of_get_property(child,
name = of_get_property(child,
"regulator-compatible", NULL);
if (!regulator_comp) {
dev_err(dev, "regulator-compatible is missing for node %s\n",
child->name);
continue;
}
if (!name)
name = child->name;
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))
if (strcmp(match->name, name))
continue;
match->init_data =

View File

@ -443,44 +443,6 @@ static int palmas_list_voltage_ldo(struct regulator_dev *dev,
return 850000 + (selector * 50000);
}
static int palmas_get_voltage_ldo_sel(struct regulator_dev *dev)
{
struct palmas_pmic *pmic = rdev_get_drvdata(dev);
int id = rdev_get_id(dev);
int selector;
unsigned int reg;
unsigned int addr;
addr = palmas_regs_info[id].vsel_addr;
palmas_ldo_read(pmic->palmas, addr, &reg);
selector = reg & PALMAS_LDO1_VOLTAGE_VSEL_MASK;
/* Adjust selector to match list_voltage ranges */
if (selector > 49)
selector = 49;
return selector;
}
static int palmas_set_voltage_ldo_sel(struct regulator_dev *dev,
unsigned selector)
{
struct palmas_pmic *pmic = rdev_get_drvdata(dev);
int id = rdev_get_id(dev);
unsigned int reg = 0;
unsigned int addr;
addr = palmas_regs_info[id].vsel_addr;
reg = selector;
palmas_ldo_write(pmic->palmas, addr, reg);
return 0;
}
static int palmas_map_voltage_ldo(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
@ -505,8 +467,8 @@ static struct regulator_ops palmas_ops_ldo = {
.is_enabled = palmas_is_enabled_ldo,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.get_voltage_sel = palmas_get_voltage_ldo_sel,
.set_voltage_sel = palmas_set_voltage_ldo_sel,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.list_voltage = palmas_list_voltage_ldo,
.map_voltage = palmas_map_voltage_ldo,
};
@ -757,6 +719,9 @@ static __devinit int palmas_probe(struct platform_device *pdev)
pmic->desc[id].type = REGULATOR_VOLTAGE;
pmic->desc[id].owner = THIS_MODULE;
pmic->desc[id].vsel_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
palmas_regs_info[id].vsel_addr);
pmic->desc[id].vsel_mask = PALMAS_LDO1_VOLTAGE_VSEL_MASK;
pmic->desc[id].enable_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
palmas_regs_info[id].ctrl_addr);
pmic->desc[id].enable_mask = PALMAS_LDO1_CTRL_MODE_ACTIVE;

View File

@ -24,7 +24,7 @@
#include <linux/mfd/samsung/s2mps11.h>
struct s2mps11_info {
struct regulator_dev **rdev;
struct regulator_dev *rdev[S2MPS11_REGULATOR_MAX];
int ramp_delay2;
int ramp_delay34;
@ -236,9 +236,8 @@ 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;
int i, ret;
unsigned char ramp_enable, ramp_reg = 0;
if (!pdata) {
@ -251,13 +250,6 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
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;
@ -297,12 +289,12 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
config.init_data = pdata->regulators[i].initdata;
config.driver_data = s2mps11;
rdev[i] = regulator_register(&regulators[i], &config);
if (IS_ERR(rdev[i])) {
ret = PTR_ERR(rdev[i]);
s2mps11->rdev[i] = regulator_register(&regulators[i], &config);
if (IS_ERR(s2mps11->rdev[i])) {
ret = PTR_ERR(s2mps11->rdev[i]);
dev_err(&pdev->dev, "regulator init failed for %d\n",
i);
rdev[i] = NULL;
s2mps11->rdev[i] = NULL;
goto err;
}
}
@ -310,8 +302,7 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
return 0;
err:
for (i = 0; i < S2MPS11_REGULATOR_MAX; i++)
if (rdev[i])
regulator_unregister(rdev[i]);
regulator_unregister(s2mps11->rdev[i]);
return ret;
}
@ -319,12 +310,10 @@ err:
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]);
regulator_unregister(s2mps11->rdev[i]);
return 0;
}

View File

@ -502,15 +502,13 @@ static int set_current_limit(struct regulator_dev *rdev, int min_uA,
if (info->n_ilimsels == 1)
return -EINVAL;
for (i = 0; i < info->n_ilimsels; i++)
for (i = info->n_ilimsels - 1; i >= 0; i--) {
if (min_uA <= info->ilimsels[i] &&
max_uA >= info->ilimsels[i])
break;
return write_field(hw, &info->ilimsel, i);
}
if (i >= info->n_ilimsels)
return -EINVAL;
return write_field(hw, &info->ilimsel, i);
return -EINVAL;
}
static int get_current_limit(struct regulator_dev *rdev)

View File

@ -57,9 +57,6 @@
struct tps6586x_regulator {
struct regulator_desc desc;
int volt_reg;
int volt_shift;
int volt_nbits;
int enable_bit[2];
int enable_reg[2];
@ -81,10 +78,10 @@ static int tps6586x_set_voltage_sel(struct regulator_dev *rdev,
int ret, val, rid = rdev_get_id(rdev);
uint8_t mask;
val = selector << ri->volt_shift;
mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift;
val = selector << (ffs(rdev->desc->vsel_mask) - 1);
mask = rdev->desc->vsel_mask;
ret = tps6586x_update(parent, ri->volt_reg, val, mask);
ret = tps6586x_update(parent, rdev->desc->vsel_reg, val, mask);
if (ret)
return ret;
@ -100,66 +97,17 @@ static int tps6586x_set_voltage_sel(struct regulator_dev *rdev,
return ret;
}
static int tps6586x_get_voltage_sel(struct regulator_dev *rdev)
{
struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_tps6586x_dev(rdev);
uint8_t val, mask;
int ret;
ret = tps6586x_read(parent, ri->volt_reg, &val);
if (ret)
return ret;
mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift;
val = (val & mask) >> ri->volt_shift;
if (val >= ri->desc.n_voltages)
BUG();
return val;
}
static int tps6586x_regulator_enable(struct regulator_dev *rdev)
{
struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_tps6586x_dev(rdev);
return tps6586x_set_bits(parent, ri->enable_reg[0],
1 << ri->enable_bit[0]);
}
static int tps6586x_regulator_disable(struct regulator_dev *rdev)
{
struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_tps6586x_dev(rdev);
return tps6586x_clr_bits(parent, ri->enable_reg[0],
1 << ri->enable_bit[0]);
}
static int tps6586x_regulator_is_enabled(struct regulator_dev *rdev)
{
struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_tps6586x_dev(rdev);
uint8_t reg_val;
int ret;
ret = tps6586x_read(parent, ri->enable_reg[0], &reg_val);
if (ret)
return ret;
return !!(reg_val & (1 << ri->enable_bit[0]));
}
static struct regulator_ops tps6586x_regulator_ops = {
.list_voltage = regulator_list_voltage_table,
.get_voltage_sel = tps6586x_get_voltage_sel,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = tps6586x_set_voltage_sel,
.is_enabled = tps6586x_regulator_is_enabled,
.enable = tps6586x_regulator_enable,
.disable = tps6586x_regulator_disable,
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
};
static struct regulator_ops tps6586x_sys_regulator_ops = {
};
static const unsigned int tps6586x_ldo0_voltages[] = {
@ -202,10 +150,11 @@ static const unsigned int tps6586x_dvm_voltages[] = {
.n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages), \
.volt_table = tps6586x_##vdata##_voltages, \
.owner = THIS_MODULE, \
.enable_reg = TPS6586X_SUPPLY##ereg0, \
.enable_mask = 1 << (ebit0), \
.vsel_reg = TPS6586X_##vreg, \
.vsel_mask = ((1 << (nbits)) - 1) << (shift), \
}, \
.volt_reg = TPS6586X_##vreg, \
.volt_shift = (shift), \
.volt_nbits = (nbits), \
.enable_reg[0] = TPS6586X_SUPPLY##ereg0, \
.enable_bit[0] = (ebit0), \
.enable_reg[1] = TPS6586X_SUPPLY##ereg1, \
@ -230,15 +179,28 @@ static const unsigned int tps6586x_dvm_voltages[] = {
TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \
}
#define TPS6586X_SYS_REGULATOR() \
{ \
.desc = { \
.supply_name = "sys", \
.name = "REG-SYS", \
.ops = &tps6586x_sys_regulator_ops, \
.type = REGULATOR_VOLTAGE, \
.id = TPS6586X_ID_SYS, \
.owner = THIS_MODULE, \
}, \
}
static struct tps6586x_regulator tps6586x_regulator[] = {
TPS6586X_SYS_REGULATOR(),
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_5, "REG-SYS", 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_RTC, "REG-SYS", 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, "vin-sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),

View File

@ -10,6 +10,8 @@
*/
#include <linux/module.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/platform_device.h>
@ -624,18 +626,9 @@ static int twlfixed_list_voltage(struct regulator_dev *rdev, unsigned index)
return info->min_mV * 1000;
}
static int twlfixed_get_voltage(struct regulator_dev *rdev)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
return info->min_mV * 1000;
}
static struct regulator_ops twl4030fixed_ops = {
.list_voltage = twlfixed_list_voltage,
.get_voltage = twlfixed_get_voltage,
.enable = twl4030reg_enable,
.disable = twl4030reg_disable,
.is_enabled = twl4030reg_is_enabled,
@ -648,8 +641,6 @@ static struct regulator_ops twl4030fixed_ops = {
static struct regulator_ops twl6030fixed_ops = {
.list_voltage = twlfixed_list_voltage,
.get_voltage = twlfixed_get_voltage,
.enable = twl6030reg_enable,
.disable = twl6030reg_disable,
.is_enabled = twl6030reg_is_enabled,
@ -659,13 +650,6 @@ static struct regulator_ops twl6030fixed_ops = {
.get_status = twl6030reg_get_status,
};
static struct regulator_ops twl6030_fixed_resource = {
.enable = twl6030reg_enable,
.disable = twl6030reg_disable,
.is_enabled = twl6030reg_is_enabled,
.get_status = twl6030reg_get_status,
};
/*
* SMPS status and control
*/
@ -757,37 +741,32 @@ static int twl6030smps_list_voltage(struct regulator_dev *rdev, unsigned index)
return voltage;
}
static int
twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
unsigned int *selector)
static int twl6030smps_map_voltage(struct regulator_dev *rdev, int min_uV,
int max_uV)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
int vsel = 0;
struct twlreg_info *info = rdev_get_drvdata(rdev);
int vsel = 0;
switch (info->flags) {
case 0:
if (min_uV == 0)
vsel = 0;
else if ((min_uV >= 600000) && (min_uV <= 1300000)) {
int calc_uV;
vsel = DIV_ROUND_UP(min_uV - 600000, 12500);
vsel++;
calc_uV = twl6030smps_list_voltage(rdev, vsel);
if (calc_uV > max_uV)
return -EINVAL;
}
/* Values 1..57 for vsel are linear and can be calculated
* values 58..62 are non linear.
*/
else if ((min_uV > 1900000) && (max_uV >= 2100000))
else if ((min_uV > 1900000) && (min_uV <= 2100000))
vsel = 62;
else if ((min_uV > 1800000) && (max_uV >= 1900000))
else if ((min_uV > 1800000) && (min_uV <= 1900000))
vsel = 61;
else if ((min_uV > 1500000) && (max_uV >= 1800000))
else if ((min_uV > 1500000) && (min_uV <= 1800000))
vsel = 60;
else if ((min_uV > 1350000) && (max_uV >= 1500000))
else if ((min_uV > 1350000) && (min_uV <= 1500000))
vsel = 59;
else if ((min_uV > 1300000) && (max_uV >= 1350000))
else if ((min_uV > 1300000) && (min_uV <= 1350000))
vsel = 58;
else
return -EINVAL;
@ -796,25 +775,21 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
if (min_uV == 0)
vsel = 0;
else if ((min_uV >= 700000) && (min_uV <= 1420000)) {
int calc_uV;
vsel = DIV_ROUND_UP(min_uV - 700000, 12500);
vsel++;
calc_uV = twl6030smps_list_voltage(rdev, vsel);
if (calc_uV > max_uV)
return -EINVAL;
}
/* Values 1..57 for vsel are linear and can be calculated
* values 58..62 are non linear.
*/
else if ((min_uV > 1900000) && (max_uV >= 2100000))
else if ((min_uV > 1900000) && (min_uV <= 2100000))
vsel = 62;
else if ((min_uV > 1800000) && (max_uV >= 1900000))
else if ((min_uV > 1800000) && (min_uV <= 1900000))
vsel = 61;
else if ((min_uV > 1350000) && (max_uV >= 1800000))
else if ((min_uV > 1350000) && (min_uV <= 1800000))
vsel = 60;
else if ((min_uV > 1350000) && (max_uV >= 1500000))
else if ((min_uV > 1350000) && (min_uV <= 1500000))
vsel = 59;
else if ((min_uV > 1300000) && (max_uV >= 1350000))
else if ((min_uV > 1300000) && (min_uV <= 1350000))
vsel = 58;
else
return -EINVAL;
@ -830,17 +805,23 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
case SMPS_OFFSET_EN|SMPS_EXTENDED_EN:
if (min_uV == 0) {
vsel = 0;
} else if ((min_uV >= 2161000) && (max_uV <= 4321000)) {
} else if ((min_uV >= 2161000) && (min_uV <= 4321000)) {
vsel = DIV_ROUND_UP(min_uV - 2161000, 38600);
vsel++;
}
break;
}
*selector = vsel;
return vsel;
}
static int twl6030smps_set_voltage_sel(struct regulator_dev *rdev,
unsigned int selector)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS,
vsel);
selector);
}
static int twl6030smps_get_voltage_sel(struct regulator_dev *rdev)
@ -852,8 +833,9 @@ static int twl6030smps_get_voltage_sel(struct regulator_dev *rdev)
static struct regulator_ops twlsmps_ops = {
.list_voltage = twl6030smps_list_voltage,
.map_voltage = twl6030smps_map_voltage,
.set_voltage = twl6030smps_set_voltage,
.set_voltage_sel = twl6030smps_set_voltage_sel,
.get_voltage_sel = twl6030smps_get_voltage_sel,
.enable = twl6030reg_enable,
@ -876,7 +858,7 @@ static struct regulator_ops twlsmps_ops = {
0x0, TWL6030, twl6030fixed_ops)
#define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) \
static struct twlreg_info TWL4030_INFO_##label = { \
static const struct twlreg_info TWL4030_INFO_##label = { \
.base = offset, \
.id = num, \
.table_len = ARRAY_SIZE(label##_VSEL_table), \
@ -894,7 +876,7 @@ static struct twlreg_info TWL4030_INFO_##label = { \
}
#define TWL4030_ADJUSTABLE_SMPS(label, offset, num, turnon_delay, remap_conf) \
static struct twlreg_info TWL4030_INFO_##label = { \
static const struct twlreg_info TWL4030_INFO_##label = { \
.base = offset, \
.id = num, \
.remap = remap_conf, \
@ -909,7 +891,7 @@ static struct twlreg_info TWL4030_INFO_##label = { \
}
#define TWL6030_ADJUSTABLE_SMPS(label) \
static struct twlreg_info TWL6030_INFO_##label = { \
static const struct twlreg_info TWL6030_INFO_##label = { \
.desc = { \
.name = #label, \
.id = TWL6030_REG_##label, \
@ -920,7 +902,7 @@ static struct twlreg_info TWL6030_INFO_##label = { \
}
#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \
static struct twlreg_info TWL6030_INFO_##label = { \
static const struct twlreg_info TWL6030_INFO_##label = { \
.base = offset, \
.min_mV = min_mVolts, \
.max_mV = max_mVolts, \
@ -935,7 +917,7 @@ static struct twlreg_info TWL6030_INFO_##label = { \
}
#define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \
static struct twlreg_info TWL6025_INFO_##label = { \
static const struct twlreg_info TWL6025_INFO_##label = { \
.base = offset, \
.min_mV = min_mVolts, \
.max_mV = max_mVolts, \
@ -951,7 +933,7 @@ static struct twlreg_info TWL6025_INFO_##label = { \
#define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \
family, operations) \
static struct twlreg_info TWLFIXED_INFO_##label = { \
static const struct twlreg_info TWLFIXED_INFO_##label = { \
.base = offset, \
.id = num, \
.min_mV = mVolts, \
@ -981,7 +963,7 @@ static struct twlreg_info TWLRES_INFO_##label = { \
}
#define TWL6025_ADJUSTABLE_SMPS(label, offset) \
static struct twlreg_info TWLSMPS_INFO_##label = { \
static const struct twlreg_info TWLSMPS_INFO_##label = { \
.base = offset, \
.min_mV = 600, \
.max_mV = 2100, \
@ -1138,6 +1120,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
{
int i, id;
struct twlreg_info *info;
const struct twlreg_info *template;
struct regulator_init_data *initdata;
struct regulation_constraints *c;
struct regulator_dev *rdev;
@ -1147,17 +1130,17 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
match = of_match_device(twl_of_match, &pdev->dev);
if (match) {
info = match->data;
id = info->desc.id;
template = match->data;
id = template->desc.id;
initdata = of_get_regulator_init_data(&pdev->dev,
pdev->dev.of_node);
drvdata = NULL;
} else {
id = pdev->id;
initdata = pdev->dev.platform_data;
for (i = 0, info = NULL; i < ARRAY_SIZE(twl_of_match); i++) {
info = twl_of_match[i].data;
if (info && info->desc.id == id)
for (i = 0, template = NULL; i < ARRAY_SIZE(twl_of_match); i++) {
template = twl_of_match[i].data;
if (template && template->desc.id == id)
break;
}
if (i == ARRAY_SIZE(twl_of_match))
@ -1168,12 +1151,16 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
return -EINVAL;
}
if (!info)
if (!template)
return -ENODEV;
if (!initdata)
return -EINVAL;
info = kmemdup(template, sizeof (*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
if (drvdata) {
/* copy the driver data into regulator data */
info->features = drvdata->features;
@ -1234,6 +1221,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "can't register %s, %ld\n",
info->desc.name, PTR_ERR(rdev));
kfree(info);
return PTR_ERR(rdev);
}
platform_set_drvdata(pdev, rdev);
@ -1255,7 +1243,11 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
static int __devexit twlreg_remove(struct platform_device *pdev)
{
regulator_unregister(platform_get_drvdata(pdev));
struct regulator_dev *rdev = platform_get_drvdata(pdev);
struct twlreg_info *info = rdev->reg_data;
regulator_unregister(rdev);
kfree(info);
return 0;
}

View File

@ -339,16 +339,15 @@ static int wm831x_buckv_set_current_limit(struct regulator_dev *rdev,
u16 reg = dcdc->base + WM831X_DCDC_CONTROL_2;
int i;
for (i = 0; i < ARRAY_SIZE(wm831x_dcdc_ilim); i++) {
for (i = ARRAY_SIZE(wm831x_dcdc_ilim) - 1; i >= 0; i--) {
if ((min_uA <= wm831x_dcdc_ilim[i]) &&
(wm831x_dcdc_ilim[i] <= max_uA))
break;
return wm831x_set_bits(wm831x, reg,
WM831X_DC1_HC_THR_MASK,
i << WM831X_DC1_HC_THR_SHIFT);
}
if (i == ARRAY_SIZE(wm831x_dcdc_ilim))
return -EINVAL;
return wm831x_set_bits(wm831x, reg, WM831X_DC1_HC_THR_MASK,
i << WM831X_DC1_HC_THR_SHIFT);
return -EINVAL;
}
static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev)

View File

@ -205,6 +205,8 @@ static int wm831x_gp_ldo_get_status(struct regulator_dev *rdev)
/* Is it reporting under voltage? */
ret = wm831x_reg_read(wm831x, WM831X_LDO_UV_STATUS);
if (ret < 0)
return ret;
if (ret & mask)
return REGULATOR_STATUS_ERROR;
@ -237,6 +239,8 @@ static struct regulator_ops wm831x_gp_ldo_ops = {
.set_mode = wm831x_gp_ldo_set_mode,
.get_status = wm831x_gp_ldo_get_status,
.get_optimum_mode = wm831x_gp_ldo_get_optimum_mode,
.get_bypass = regulator_get_bypass_regmap,
.set_bypass = regulator_set_bypass_regmap,
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
@ -293,6 +297,8 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
ldo->desc.vsel_mask = WM831X_LDO1_ON_VSEL_MASK;
ldo->desc.enable_reg = WM831X_LDO_ENABLE;
ldo->desc.enable_mask = 1 << id;
ldo->desc.bypass_reg = ldo->base;
ldo->desc.bypass_mask = WM831X_LDO1_SWI;
config.dev = pdev->dev.parent;
if (pdata)
@ -469,6 +475,8 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev)
/* Is it reporting under voltage? */
ret = wm831x_reg_read(wm831x, WM831X_LDO_UV_STATUS);
if (ret < 0)
return ret;
if (ret & mask)
return REGULATOR_STATUS_ERROR;
@ -488,6 +496,8 @@ static struct regulator_ops wm831x_aldo_ops = {
.get_mode = wm831x_aldo_get_mode,
.set_mode = wm831x_aldo_set_mode,
.get_status = wm831x_aldo_get_status,
.set_bypass = regulator_set_bypass_regmap,
.get_bypass = regulator_get_bypass_regmap,
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
@ -544,6 +554,8 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
ldo->desc.vsel_mask = WM831X_LDO7_ON_VSEL_MASK;
ldo->desc.enable_reg = WM831X_LDO_ENABLE;
ldo->desc.enable_mask = 1 << id;
ldo->desc.bypass_reg = ldo->base;
ldo->desc.bypass_mask = WM831X_LDO7_SWI;
config.dev = pdev->dev.parent;
if (pdata)

View File

@ -120,13 +120,8 @@ static int wm8400_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode)
case REGULATOR_MODE_IDLE:
/* Datasheet: standby */
ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
WM8400_DC1_ACTIVE, 0);
if (ret != 0)
return ret;
return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
WM8400_DC1_SLEEP, 0);
WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP, 0);
default:
return -EINVAL;
}

View File

@ -74,6 +74,7 @@ enum max77686_regulators {
struct max77686_regulator_data {
int id;
struct regulator_init_data *initdata;
struct device_node *of_node;
};
enum max77686_opmode {

View File

@ -14,6 +14,7 @@
#define TPS6586X_SLEW_RATE_MASK 0x07
enum {
TPS6586X_ID_SYS,
TPS6586X_ID_SM_0,
TPS6586X_ID_SM_1,
TPS6586X_ID_SM_2,

View File

@ -177,6 +177,8 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode);
unsigned int regulator_get_mode(struct regulator *regulator);
int regulator_set_optimum_mode(struct regulator *regulator, int load_uA);
int regulator_allow_bypass(struct regulator *regulator, bool allow);
/* regulator notifier block */
int regulator_register_notifier(struct regulator *regulator,
struct notifier_block *nb);
@ -328,6 +330,12 @@ static inline int regulator_set_optimum_mode(struct regulator *regulator,
return REGULATOR_MODE_NORMAL;
}
static inline int regulator_allow_bypass(struct regulator *regulator,
bool allow)
{
return 0;
}
static inline int regulator_register_notifier(struct regulator *regulator,
struct notifier_block *nb)
{
@ -352,4 +360,11 @@ static inline void regulator_set_drvdata(struct regulator *regulator,
#endif
static inline int regulator_set_voltage_tol(struct regulator *regulator,
int new_uV, int tol_uV)
{
return regulator_set_voltage(regulator,
new_uV - tol_uV, new_uV + tol_uV);
}
#endif

View File

@ -32,6 +32,8 @@ enum regulator_status {
REGULATOR_STATUS_NORMAL,
REGULATOR_STATUS_IDLE,
REGULATOR_STATUS_STANDBY,
/* The regulator is enabled but not regulating */
REGULATOR_STATUS_BYPASS,
/* in case that any other status doesn't apply */
REGULATOR_STATUS_UNDEFINED,
};
@ -58,6 +60,7 @@ enum regulator_status {
* regulator_desc.n_voltages. Voltages may be reported in any order.
*
* @set_current_limit: Configure a limit for a current-limited regulator.
* The driver should select the current closest to max_uA.
* @get_current_limit: Get the configured limit for a current-limited regulator.
*
* @set_mode: Set the configured operating mode for the regulator.
@ -67,6 +70,9 @@ enum regulator_status {
* @get_optimum_mode: Get the most efficient operating mode for the regulator
* when running with the specified parameters.
*
* @set_bypass: Set the regulator in bypass mode.
* @get_bypass: Get the regulator bypass mode state.
*
* @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
@ -133,6 +139,10 @@ struct regulator_ops {
unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV,
int output_uV, int load_uA);
/* control and report on bypass mode */
int (*set_bypass)(struct regulator_dev *dev, bool enable);
int (*get_bypass)(struct regulator_dev *dev, bool *enable);
/* the operations below are for configuration of regulator state when
* its parent PMIC enters a global STANDBY/HIBERNATE state */
@ -205,6 +215,8 @@ struct regulator_desc {
unsigned int vsel_mask;
unsigned int enable_reg;
unsigned int enable_mask;
unsigned int bypass_reg;
unsigned int bypass_mask;
unsigned int enable_time;
};
@ -221,7 +233,8 @@ struct regulator_desc {
* @driver_data: private regulator data
* @of_node: OpenFirmware node to parse for device tree bindings (may be
* NULL).
* @regmap: regmap to use for core regmap helpers
* @regmap: regmap to use for core regmap helpers if dev_get_regulator() is
* insufficient.
* @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()
@ -253,6 +266,7 @@ struct regulator_dev {
int exclusive;
u32 use_count;
u32 open_count;
u32 bypass_count;
/* lists we belong to */
struct list_head list; /* list of all regulators */
@ -310,6 +324,8 @@ 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);
int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable);
int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable);
void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data);

View File

@ -0,0 +1,60 @@
/*
* fan53555.h - Fairchild Regulator FAN53555 Driver
*
* Copyright (C) 2012 Marvell Technology Ltd.
* Yunfan Zhang <yfzhang@marvell.com>
*
* This package 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 __FAN53555_H__
/* VSEL ID */
enum {
FAN53555_VSEL_ID_0 = 0,
FAN53555_VSEL_ID_1,
};
/* Transition slew rate limiting from a low to high voltage.
* -----------------------
* Bin |Slew Rate(mV/uS)
* ------|----------------
* 000 | 64.00
* ------|----------------
* 001 | 32.00
* ------|----------------
* 010 | 16.00
* ------|----------------
* 011 | 8.00
* ------|----------------
* 100 | 4.00
* ------|----------------
* 101 | 2.00
* ------|----------------
* 110 | 1.00
* ------|----------------
* 111 | 0.50
* -----------------------
*/
enum {
FAN53555_SLEW_RATE_64MV = 0,
FAN53555_SLEW_RATE_32MV,
FAN53555_SLEW_RATE_16MV,
FAN53555_SLEW_RATE_8MV,
FAN53555_SLEW_RATE_4MV,
FAN53555_SLEW_RATE_2MV,
FAN53555_SLEW_RATE_1MV,
FAN53555_SLEW_RATE_0_5MV,
};
struct fan53555_platform_data {
struct regulator_init_data *regulator;
unsigned int slew_rate;
/* Sleep VSEL ID */
unsigned int sleep_vsel_id;
};
#endif /* __FAN53555_H__ */

View File

@ -32,6 +32,7 @@ struct regulator;
* board/machine.
* STATUS: Regulator can be enabled and disabled.
* DRMS: Dynamic Regulator Mode Switching is enabled for this regulator.
* BYPASS: Regulator can be put into bypass mode
*/
#define REGULATOR_CHANGE_VOLTAGE 0x1
@ -39,6 +40,7 @@ struct regulator;
#define REGULATOR_CHANGE_MODE 0x4
#define REGULATOR_CHANGE_STATUS 0x8
#define REGULATOR_CHANGE_DRMS 0x10
#define REGULATOR_CHANGE_BYPASS 0x20
/**
* struct regulator_state - regulator state during low power system states