mirror of
https://github.com/fail0verflow/switch-linux.git
synced 2025-05-04 02:34:21 -04:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6: (32 commits) regulator: twl4030 VAUX3 supports 3.0V regulator: Support disabling of unused regulators by machines regulator: Don't increment use_count for boot_on regulators twl4030-regulator: expose VPLL2 regulator: refcount fixes regulator: Don't warn if we failed to get a regulator regulator: Allow boot_on regulators to be disabled by clients regulator: Implement list_voltage for WM835x LDOs and DCDCs twl4030-regulator: list more VAUX4 voltages regulator: Don't warn on omitted voltage constraints regulator: Implement list_voltage() for WM8400 DCDCs and LDOs MMC: regulator utilities regulator: twl4030 voltage enumeration (v2) regulator: twl4030 regulators regulator: get_status() grows kerneldoc regulator: enumerate voltages (v2) regulator: Fix get_mode() for WM835x DCDCs regulator: Allow regulators to set the initial operating mode regulator: Suggest use of datasheet supply or pin names for consumers regulator: email - update email address and regulator webpage. ...
This commit is contained in:
commit
18b34b9546
22 changed files with 1220 additions and 117 deletions
|
@ -4,8 +4,8 @@ KernelVersion: 2.6.26
|
||||||
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
|
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
|
||||||
Description:
|
Description:
|
||||||
Some regulator directories will contain a field called
|
Some regulator directories will contain a field called
|
||||||
state. This reports the regulator enable status, for
|
state. This reports the regulator enable control, for
|
||||||
regulators which can report that value.
|
regulators which can report that input value.
|
||||||
|
|
||||||
This will be one of the following strings:
|
This will be one of the following strings:
|
||||||
|
|
||||||
|
@ -14,16 +14,54 @@ Description:
|
||||||
'unknown'
|
'unknown'
|
||||||
|
|
||||||
'enabled' means the regulator output is ON and is supplying
|
'enabled' means the regulator output is ON and is supplying
|
||||||
power to the system.
|
power to the system (assuming no error prevents it).
|
||||||
|
|
||||||
'disabled' means the regulator output is OFF and is not
|
'disabled' means the regulator output is OFF and is not
|
||||||
supplying power to the system..
|
supplying power to the system (unless some non-Linux
|
||||||
|
control has enabled it).
|
||||||
|
|
||||||
'unknown' means software cannot determine the state, or
|
'unknown' means software cannot determine the state, or
|
||||||
the reported state is invalid.
|
the reported state is invalid.
|
||||||
|
|
||||||
NOTE: this field can be used in conjunction with microvolts
|
NOTE: this field can be used in conjunction with microvolts
|
||||||
and microamps to determine regulator output levels.
|
or microamps to determine configured regulator output levels.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../status
|
||||||
|
Description:
|
||||||
|
Some regulator directories will contain a field called
|
||||||
|
"status". This reports the current regulator status, for
|
||||||
|
regulators which can report that output value.
|
||||||
|
|
||||||
|
This will be one of the following strings:
|
||||||
|
|
||||||
|
off
|
||||||
|
on
|
||||||
|
error
|
||||||
|
fast
|
||||||
|
normal
|
||||||
|
idle
|
||||||
|
standby
|
||||||
|
|
||||||
|
"off" means the regulator is not supplying power to the
|
||||||
|
system.
|
||||||
|
|
||||||
|
"on" means the regulator is supplying power to the system,
|
||||||
|
and the regulator can't report a detailed operation mode.
|
||||||
|
|
||||||
|
"error" indicates an out-of-regulation status such as being
|
||||||
|
disabled due to thermal shutdown, or voltage being unstable
|
||||||
|
because of problems with the input power supply.
|
||||||
|
|
||||||
|
"fast", "normal", "idle", and "standby" are all detailed
|
||||||
|
regulator operation modes (described elsewhere). They
|
||||||
|
imply "on", but provide more detail.
|
||||||
|
|
||||||
|
Note that regulator status is a function of many inputs,
|
||||||
|
not limited to control inputs from Linux. For example,
|
||||||
|
the actual load presented may trigger "error" status; or
|
||||||
|
a regulator may be enabled by another user, even though
|
||||||
|
Linux did not enable it.
|
||||||
|
|
||||||
|
|
||||||
What: /sys/class/regulator/.../type
|
What: /sys/class/regulator/.../type
|
||||||
|
@ -58,7 +96,7 @@ Description:
|
||||||
Some regulator directories will contain a field called
|
Some regulator directories will contain a field called
|
||||||
microvolts. This holds the regulator output voltage setting
|
microvolts. This holds the regulator output voltage setting
|
||||||
measured in microvolts (i.e. E-6 Volts), for regulators
|
measured in microvolts (i.e. E-6 Volts), for regulators
|
||||||
which can report that voltage.
|
which can report the control input for voltage.
|
||||||
|
|
||||||
NOTE: This value should not be used to determine the regulator
|
NOTE: This value should not be used to determine the regulator
|
||||||
output voltage level as this value is the same regardless of
|
output voltage level as this value is the same regardless of
|
||||||
|
@ -73,7 +111,7 @@ Description:
|
||||||
Some regulator directories will contain a field called
|
Some regulator directories will contain a field called
|
||||||
microamps. This holds the regulator output current limit
|
microamps. This holds the regulator output current limit
|
||||||
setting measured in microamps (i.e. E-6 Amps), for regulators
|
setting measured in microamps (i.e. E-6 Amps), for regulators
|
||||||
which can report that current.
|
which can report the control input for a current limit.
|
||||||
|
|
||||||
NOTE: This value should not be used to determine the regulator
|
NOTE: This value should not be used to determine the regulator
|
||||||
output current level as this value is the same regardless of
|
output current level as this value is the same regardless of
|
||||||
|
@ -87,7 +125,7 @@ Contact: Liam Girdwood <lrg@slimlogic.co.uk>
|
||||||
Description:
|
Description:
|
||||||
Some regulator directories will contain a field called
|
Some regulator directories will contain a field called
|
||||||
opmode. This holds the current regulator operating mode,
|
opmode. This holds the current regulator operating mode,
|
||||||
for regulators which can report it.
|
for regulators which can report that control input value.
|
||||||
|
|
||||||
The opmode value can be one of the following strings:
|
The opmode value can be one of the following strings:
|
||||||
|
|
||||||
|
@ -101,7 +139,8 @@ Description:
|
||||||
|
|
||||||
NOTE: This value should not be used to determine the regulator
|
NOTE: This value should not be used to determine the regulator
|
||||||
output operating mode as this value is the same regardless of
|
output operating mode as this value is the same regardless of
|
||||||
whether the regulator is enabled or disabled.
|
whether the regulator is enabled or disabled. A "status"
|
||||||
|
attribute may be available to determine the actual mode.
|
||||||
|
|
||||||
|
|
||||||
What: /sys/class/regulator/.../min_microvolts
|
What: /sys/class/regulator/.../min_microvolts
|
||||||
|
|
|
@ -4847,7 +4847,7 @@ M: lrg@slimlogic.co.uk
|
||||||
P: Mark Brown
|
P: Mark Brown
|
||||||
M: broonie@opensource.wolfsonmicro.com
|
M: broonie@opensource.wolfsonmicro.com
|
||||||
W: http://opensource.wolfsonmicro.com/node/15
|
W: http://opensource.wolfsonmicro.com/node/15
|
||||||
W: http://www.slimlogic.co.uk/?page_id=5
|
W: http://www.slimlogic.co.uk/?p=48
|
||||||
T: git kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6.git
|
T: git kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6.git
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
||||||
|
|
|
@ -592,11 +592,9 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
|
||||||
|
|
||||||
/* maybe add LDOs that are omitted on cost-reduced parts */
|
/* maybe add LDOs that are omitted on cost-reduced parts */
|
||||||
if (twl_has_regulator() && !(features & TPS_SUBSET)) {
|
if (twl_has_regulator() && !(features & TPS_SUBSET)) {
|
||||||
/*
|
|
||||||
child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2);
|
child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2);
|
||||||
if (IS_ERR(child))
|
if (IS_ERR(child))
|
||||||
return PTR_ERR(child);
|
return PTR_ERR(child);
|
||||||
*/
|
|
||||||
|
|
||||||
child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2);
|
child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2);
|
||||||
if (IS_ERR(child))
|
if (IS_ERR(child))
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <linux/leds.h>
|
#include <linux/leds.h>
|
||||||
#include <linux/scatterlist.h>
|
#include <linux/scatterlist.h>
|
||||||
#include <linux/log2.h>
|
#include <linux/log2.h>
|
||||||
|
#include <linux/regulator/consumer.h>
|
||||||
|
|
||||||
#include <linux/mmc/card.h>
|
#include <linux/mmc/card.h>
|
||||||
#include <linux/mmc/host.h>
|
#include <linux/mmc/host.h>
|
||||||
|
@ -523,6 +524,105 @@ u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
|
EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
|
||||||
|
|
||||||
|
#ifdef CONFIG_REGULATOR
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mmc_regulator_get_ocrmask - return mask of supported voltages
|
||||||
|
* @supply: regulator to use
|
||||||
|
*
|
||||||
|
* This returns either a negative errno, or a mask of voltages that
|
||||||
|
* can be provided to MMC/SD/SDIO devices using the specified voltage
|
||||||
|
* regulator. This would normally be called before registering the
|
||||||
|
* MMC host adapter.
|
||||||
|
*/
|
||||||
|
int mmc_regulator_get_ocrmask(struct regulator *supply)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
int count;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
count = regulator_count_voltages(supply);
|
||||||
|
if (count < 0)
|
||||||
|
return count;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
int vdd_uV;
|
||||||
|
int vdd_mV;
|
||||||
|
|
||||||
|
vdd_uV = regulator_list_voltage(supply, i);
|
||||||
|
if (vdd_uV <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
vdd_mV = vdd_uV / 1000;
|
||||||
|
result |= mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mmc_regulator_get_ocrmask);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mmc_regulator_set_ocr - set regulator to match host->ios voltage
|
||||||
|
* @vdd_bit: zero for power off, else a bit number (host->ios.vdd)
|
||||||
|
* @supply: regulator to use
|
||||||
|
*
|
||||||
|
* Returns zero on success, else negative errno.
|
||||||
|
*
|
||||||
|
* MMC host drivers may use this to enable or disable a regulator using
|
||||||
|
* a particular supply voltage. This would normally be called from the
|
||||||
|
* set_ios() method.
|
||||||
|
*/
|
||||||
|
int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
int min_uV, max_uV;
|
||||||
|
int enabled;
|
||||||
|
|
||||||
|
enabled = regulator_is_enabled(supply);
|
||||||
|
if (enabled < 0)
|
||||||
|
return enabled;
|
||||||
|
|
||||||
|
if (vdd_bit) {
|
||||||
|
int tmp;
|
||||||
|
int voltage;
|
||||||
|
|
||||||
|
/* REVISIT mmc_vddrange_to_ocrmask() may have set some
|
||||||
|
* bits this regulator doesn't quite support ... don't
|
||||||
|
* be too picky, most cards and regulators are OK with
|
||||||
|
* a 0.1V range goof (it's a small error percentage).
|
||||||
|
*/
|
||||||
|
tmp = vdd_bit - ilog2(MMC_VDD_165_195);
|
||||||
|
if (tmp == 0) {
|
||||||
|
min_uV = 1650 * 1000;
|
||||||
|
max_uV = 1950 * 1000;
|
||||||
|
} else {
|
||||||
|
min_uV = 1900 * 1000 + tmp * 100 * 1000;
|
||||||
|
max_uV = min_uV + 100 * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* avoid needless changes to this voltage; the regulator
|
||||||
|
* might not allow this operation
|
||||||
|
*/
|
||||||
|
voltage = regulator_get_voltage(supply);
|
||||||
|
if (voltage < 0)
|
||||||
|
result = voltage;
|
||||||
|
else if (voltage < min_uV || voltage > max_uV)
|
||||||
|
result = regulator_set_voltage(supply, min_uV, max_uV);
|
||||||
|
else
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
if (result == 0 && !enabled)
|
||||||
|
result = regulator_enable(supply);
|
||||||
|
} else if (enabled) {
|
||||||
|
result = regulator_disable(supply);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mmc_regulator_set_ocr);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mask off any voltages we don't support and select
|
* Mask off any voltages we don't support and select
|
||||||
* the lowest voltage
|
* the lowest voltage
|
||||||
|
|
|
@ -29,8 +29,12 @@ config REGULATOR_DEBUG
|
||||||
Say yes here to enable debugging support.
|
Say yes here to enable debugging support.
|
||||||
|
|
||||||
config REGULATOR_FIXED_VOLTAGE
|
config REGULATOR_FIXED_VOLTAGE
|
||||||
tristate
|
tristate "Fixed voltage regulator support"
|
||||||
default n
|
default n
|
||||||
|
help
|
||||||
|
This driver provides support for fixed voltage regulators,
|
||||||
|
useful for systems which use a combination of software
|
||||||
|
managed regulators and simple non-configurable regulators.
|
||||||
|
|
||||||
config REGULATOR_VIRTUAL_CONSUMER
|
config REGULATOR_VIRTUAL_CONSUMER
|
||||||
tristate "Virtual regulator consumer support"
|
tristate "Virtual regulator consumer support"
|
||||||
|
@ -52,6 +56,13 @@ config REGULATOR_BQ24022
|
||||||
charging select between 100 mA and 500 mA charging current
|
charging select between 100 mA and 500 mA charging current
|
||||||
limit.
|
limit.
|
||||||
|
|
||||||
|
config REGULATOR_TWL4030
|
||||||
|
bool "TI TWL4030/TWL5030/TPS695x0 PMIC"
|
||||||
|
depends on TWL4030_CORE
|
||||||
|
help
|
||||||
|
This driver supports the voltage regulators provided by
|
||||||
|
this family of companion chips.
|
||||||
|
|
||||||
config REGULATOR_WM8350
|
config REGULATOR_WM8350
|
||||||
tristate "Wolfson Microelectroncis WM8350 AudioPlus PMIC"
|
tristate "Wolfson Microelectroncis WM8350 AudioPlus PMIC"
|
||||||
depends on MFD_WM8350
|
depends on MFD_WM8350
|
||||||
|
|
|
@ -8,6 +8,7 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
|
||||||
obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
|
obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
|
||||||
|
|
||||||
obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o
|
obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o
|
||||||
|
obj-$(CONFIG_REGULATOR_TWL4030) += twl4030-regulator.o
|
||||||
obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
|
obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
|
||||||
obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
|
obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
|
||||||
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
|
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
|
||||||
|
|
|
@ -105,7 +105,8 @@ static int __init bq24022_probe(struct platform_device *pdev)
|
||||||
ret = gpio_direction_output(pdata->gpio_iset2, 0);
|
ret = gpio_direction_output(pdata->gpio_iset2, 0);
|
||||||
ret = gpio_direction_output(pdata->gpio_nce, 1);
|
ret = gpio_direction_output(pdata->gpio_nce, 1);
|
||||||
|
|
||||||
bq24022 = regulator_register(&bq24022_desc, &pdev->dev, pdata);
|
bq24022 = regulator_register(&bq24022_desc, &pdev->dev,
|
||||||
|
pdata->init_data, pdata);
|
||||||
if (IS_ERR(bq24022)) {
|
if (IS_ERR(bq24022)) {
|
||||||
dev_dbg(&pdev->dev, "couldn't register regulator\n");
|
dev_dbg(&pdev->dev, "couldn't register regulator\n");
|
||||||
ret = PTR_ERR(bq24022);
|
ret = PTR_ERR(bq24022);
|
||||||
|
|
|
@ -28,33 +28,7 @@
|
||||||
static DEFINE_MUTEX(regulator_list_mutex);
|
static DEFINE_MUTEX(regulator_list_mutex);
|
||||||
static LIST_HEAD(regulator_list);
|
static LIST_HEAD(regulator_list);
|
||||||
static LIST_HEAD(regulator_map_list);
|
static LIST_HEAD(regulator_map_list);
|
||||||
|
static int has_full_constraints;
|
||||||
/*
|
|
||||||
* struct regulator_dev
|
|
||||||
*
|
|
||||||
* Voltage / Current regulator class device. One for each regulator.
|
|
||||||
*/
|
|
||||||
struct regulator_dev {
|
|
||||||
struct regulator_desc *desc;
|
|
||||||
int use_count;
|
|
||||||
|
|
||||||
/* lists we belong to */
|
|
||||||
struct list_head list; /* list of all regulators */
|
|
||||||
struct list_head slist; /* list of supplied regulators */
|
|
||||||
|
|
||||||
/* lists we own */
|
|
||||||
struct list_head consumer_list; /* consumers we supply */
|
|
||||||
struct list_head supply_list; /* regulators we supply */
|
|
||||||
|
|
||||||
struct blocking_notifier_head notifier;
|
|
||||||
struct mutex mutex; /* consumer lock */
|
|
||||||
struct module *owner;
|
|
||||||
struct device dev;
|
|
||||||
struct regulation_constraints *constraints;
|
|
||||||
struct regulator_dev *supply; /* for tree */
|
|
||||||
|
|
||||||
void *reg_data; /* regulator_dev data */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* struct regulator_map
|
* struct regulator_map
|
||||||
|
@ -79,7 +53,6 @@ struct regulator {
|
||||||
int uA_load;
|
int uA_load;
|
||||||
int min_uV;
|
int min_uV;
|
||||||
int max_uV;
|
int max_uV;
|
||||||
int enabled; /* count of client enables */
|
|
||||||
char *supply_name;
|
char *supply_name;
|
||||||
struct device_attribute dev_attr;
|
struct device_attribute dev_attr;
|
||||||
struct regulator_dev *rdev;
|
struct regulator_dev *rdev;
|
||||||
|
@ -312,6 +285,47 @@ static ssize_t regulator_state_show(struct device *dev,
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR(state, 0444, regulator_state_show, NULL);
|
static DEVICE_ATTR(state, 0444, regulator_state_show, NULL);
|
||||||
|
|
||||||
|
static ssize_t regulator_status_show(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct regulator_dev *rdev = dev_get_drvdata(dev);
|
||||||
|
int status;
|
||||||
|
char *label;
|
||||||
|
|
||||||
|
status = rdev->desc->ops->get_status(rdev);
|
||||||
|
if (status < 0)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case REGULATOR_STATUS_OFF:
|
||||||
|
label = "off";
|
||||||
|
break;
|
||||||
|
case REGULATOR_STATUS_ON:
|
||||||
|
label = "on";
|
||||||
|
break;
|
||||||
|
case REGULATOR_STATUS_ERROR:
|
||||||
|
label = "error";
|
||||||
|
break;
|
||||||
|
case REGULATOR_STATUS_FAST:
|
||||||
|
label = "fast";
|
||||||
|
break;
|
||||||
|
case REGULATOR_STATUS_NORMAL:
|
||||||
|
label = "normal";
|
||||||
|
break;
|
||||||
|
case REGULATOR_STATUS_IDLE:
|
||||||
|
label = "idle";
|
||||||
|
break;
|
||||||
|
case REGULATOR_STATUS_STANDBY:
|
||||||
|
label = "standby";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ERANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf(buf, "%s\n", label);
|
||||||
|
}
|
||||||
|
static DEVICE_ATTR(status, 0444, regulator_status_show, NULL);
|
||||||
|
|
||||||
static ssize_t regulator_min_uA_show(struct device *dev,
|
static ssize_t regulator_min_uA_show(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
|
@ -678,6 +692,73 @@ static int set_machine_constraints(struct regulator_dev *rdev,
|
||||||
else
|
else
|
||||||
name = "regulator";
|
name = "regulator";
|
||||||
|
|
||||||
|
/* constrain machine-level voltage specs to fit
|
||||||
|
* the actual range supported by this regulator.
|
||||||
|
*/
|
||||||
|
if (ops->list_voltage && rdev->desc->n_voltages) {
|
||||||
|
int count = rdev->desc->n_voltages;
|
||||||
|
int i;
|
||||||
|
int min_uV = INT_MAX;
|
||||||
|
int max_uV = INT_MIN;
|
||||||
|
int cmin = constraints->min_uV;
|
||||||
|
int cmax = constraints->max_uV;
|
||||||
|
|
||||||
|
/* it's safe to autoconfigure fixed-voltage supplies */
|
||||||
|
if (count == 1 && !cmin) {
|
||||||
|
cmin = INT_MIN;
|
||||||
|
cmax = INT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* voltage constraints are optional */
|
||||||
|
if ((cmin == 0) && (cmax == 0))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* else require explicit machine-level constraints */
|
||||||
|
if (cmin <= 0 || cmax <= 0 || cmax < cmin) {
|
||||||
|
pr_err("%s: %s '%s' voltage constraints\n",
|
||||||
|
__func__, "invalid", name);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initial: [cmin..cmax] valid, [min_uV..max_uV] not */
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
int value;
|
||||||
|
|
||||||
|
value = ops->list_voltage(rdev, i);
|
||||||
|
if (value <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* maybe adjust [min_uV..max_uV] */
|
||||||
|
if (value >= cmin && value < min_uV)
|
||||||
|
min_uV = value;
|
||||||
|
if (value <= cmax && value > max_uV)
|
||||||
|
max_uV = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* final: [min_uV..max_uV] valid iff constraints valid */
|
||||||
|
if (max_uV < min_uV) {
|
||||||
|
pr_err("%s: %s '%s' voltage constraints\n",
|
||||||
|
__func__, "unsupportable", name);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* use regulator's subset of machine constraints */
|
||||||
|
if (constraints->min_uV < min_uV) {
|
||||||
|
pr_debug("%s: override '%s' %s, %d -> %d\n",
|
||||||
|
__func__, name, "min_uV",
|
||||||
|
constraints->min_uV, min_uV);
|
||||||
|
constraints->min_uV = min_uV;
|
||||||
|
}
|
||||||
|
if (constraints->max_uV > max_uV) {
|
||||||
|
pr_debug("%s: override '%s' %s, %d -> %d\n",
|
||||||
|
__func__, name, "max_uV",
|
||||||
|
constraints->max_uV, max_uV);
|
||||||
|
constraints->max_uV = max_uV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rdev->constraints = constraints;
|
rdev->constraints = constraints;
|
||||||
|
|
||||||
/* do we need to apply the constraint voltage */
|
/* do we need to apply the constraint voltage */
|
||||||
|
@ -695,10 +776,6 @@ static int set_machine_constraints(struct regulator_dev *rdev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* are we enabled at boot time by firmware / bootloader */
|
|
||||||
if (rdev->constraints->boot_on)
|
|
||||||
rdev->use_count = 1;
|
|
||||||
|
|
||||||
/* do we need to setup our suspend state */
|
/* do we need to setup our suspend state */
|
||||||
if (constraints->initial_state) {
|
if (constraints->initial_state) {
|
||||||
ret = suspend_prepare(rdev, constraints->initial_state);
|
ret = suspend_prepare(rdev, constraints->initial_state);
|
||||||
|
@ -710,11 +787,27 @@ static int set_machine_constraints(struct regulator_dev *rdev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if always_on is set then turn the regulator on if it's not
|
if (constraints->initial_mode) {
|
||||||
* already on. */
|
if (!ops->set_mode) {
|
||||||
if (constraints->always_on && ops->enable &&
|
printk(KERN_ERR "%s: no set_mode operation for %s\n",
|
||||||
((ops->is_enabled && !ops->is_enabled(rdev)) ||
|
__func__, name);
|
||||||
(!ops->is_enabled && !constraints->boot_on))) {
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ops->set_mode(rdev, constraints->initial_mode);
|
||||||
|
if (ret < 0) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"%s: failed to set initial mode for %s: %d\n",
|
||||||
|
__func__, name, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the constraints say the regulator should be on at this point
|
||||||
|
* and we have control then make sure it is enabled.
|
||||||
|
*/
|
||||||
|
if ((constraints->always_on || constraints->boot_on) && ops->enable) {
|
||||||
ret = ops->enable(rdev);
|
ret = ops->enable(rdev);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printk(KERN_ERR "%s: failed to enable %s\n",
|
printk(KERN_ERR "%s: failed to enable %s\n",
|
||||||
|
@ -817,6 +910,19 @@ static void unset_consumer_device_supply(struct regulator_dev *rdev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void unset_regulator_supplies(struct regulator_dev *rdev)
|
||||||
|
{
|
||||||
|
struct regulator_map *node, *n;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(node, n, ®ulator_map_list, list) {
|
||||||
|
if (rdev == node->regulator) {
|
||||||
|
list_del(&node->list);
|
||||||
|
kfree(node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define REG_STR_SIZE 32
|
#define REG_STR_SIZE 32
|
||||||
|
|
||||||
static struct regulator *create_regulator(struct regulator_dev *rdev,
|
static struct regulator *create_regulator(struct regulator_dev *rdev,
|
||||||
|
@ -898,9 +1004,12 @@ overflow_err:
|
||||||
* @id: Supply name or regulator ID.
|
* @id: Supply name or regulator ID.
|
||||||
*
|
*
|
||||||
* Returns a struct regulator corresponding to the regulator producer,
|
* Returns a struct regulator corresponding to the regulator producer,
|
||||||
* or IS_ERR() condition containing errno. Use of supply names
|
* or IS_ERR() condition containing errno.
|
||||||
* configured via regulator_set_device_supply() is strongly
|
*
|
||||||
* encouraged.
|
* Use of supply names configured via regulator_set_device_supply() is
|
||||||
|
* strongly encouraged. It is recommended that the supply name used
|
||||||
|
* should match the name used for the supply and/or the relevant
|
||||||
|
* device pins in the datasheet.
|
||||||
*/
|
*/
|
||||||
struct regulator *regulator_get(struct device *dev, const char *id)
|
struct regulator *regulator_get(struct device *dev, const char *id)
|
||||||
{
|
{
|
||||||
|
@ -922,8 +1031,6 @@ struct regulator *regulator_get(struct device *dev, const char *id)
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printk(KERN_ERR "regulator: Unable to get requested regulator: %s\n",
|
|
||||||
id);
|
|
||||||
mutex_unlock(®ulator_list_mutex);
|
mutex_unlock(®ulator_list_mutex);
|
||||||
return regulator;
|
return regulator;
|
||||||
|
|
||||||
|
@ -961,10 +1068,6 @@ void regulator_put(struct regulator *regulator)
|
||||||
mutex_lock(®ulator_list_mutex);
|
mutex_lock(®ulator_list_mutex);
|
||||||
rdev = regulator->rdev;
|
rdev = regulator->rdev;
|
||||||
|
|
||||||
if (WARN(regulator->enabled, "Releasing supply %s while enabled\n",
|
|
||||||
regulator->supply_name))
|
|
||||||
_regulator_disable(rdev);
|
|
||||||
|
|
||||||
/* remove any sysfs entries */
|
/* remove any sysfs entries */
|
||||||
if (regulator->dev) {
|
if (regulator->dev) {
|
||||||
sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
|
sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
|
||||||
|
@ -1039,12 +1142,7 @@ int regulator_enable(struct regulator *regulator)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
mutex_lock(&rdev->mutex);
|
mutex_lock(&rdev->mutex);
|
||||||
if (regulator->enabled == 0)
|
|
||||||
ret = _regulator_enable(rdev);
|
ret = _regulator_enable(rdev);
|
||||||
else if (regulator->enabled < 0)
|
|
||||||
ret = -EIO;
|
|
||||||
if (ret == 0)
|
|
||||||
regulator->enabled++;
|
|
||||||
mutex_unlock(&rdev->mutex);
|
mutex_unlock(&rdev->mutex);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1055,6 +1153,11 @@ static int _regulator_disable(struct regulator_dev *rdev)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
if (WARN(rdev->use_count <= 0,
|
||||||
|
"unbalanced disables for %s\n",
|
||||||
|
rdev->desc->name))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
/* are we the last user and permitted to disable ? */
|
/* are we the last user and permitted to disable ? */
|
||||||
if (rdev->use_count == 1 && !rdev->constraints->always_on) {
|
if (rdev->use_count == 1 && !rdev->constraints->always_on) {
|
||||||
|
|
||||||
|
@ -1103,16 +1206,7 @@ int regulator_disable(struct regulator *regulator)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
mutex_lock(&rdev->mutex);
|
mutex_lock(&rdev->mutex);
|
||||||
if (regulator->enabled == 1) {
|
|
||||||
ret = _regulator_disable(rdev);
|
ret = _regulator_disable(rdev);
|
||||||
if (ret == 0)
|
|
||||||
regulator->uA_load = 0;
|
|
||||||
} else if (WARN(regulator->enabled <= 0,
|
|
||||||
"unbalanced disables for supply %s\n",
|
|
||||||
regulator->supply_name))
|
|
||||||
ret = -EIO;
|
|
||||||
if (ret == 0)
|
|
||||||
regulator->enabled--;
|
|
||||||
mutex_unlock(&rdev->mutex);
|
mutex_unlock(&rdev->mutex);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1159,7 +1253,6 @@ int regulator_force_disable(struct regulator *regulator)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mutex_lock(®ulator->rdev->mutex);
|
mutex_lock(®ulator->rdev->mutex);
|
||||||
regulator->enabled = 0;
|
|
||||||
regulator->uA_load = 0;
|
regulator->uA_load = 0;
|
||||||
ret = _regulator_force_disable(regulator->rdev);
|
ret = _regulator_force_disable(regulator->rdev);
|
||||||
mutex_unlock(®ulator->rdev->mutex);
|
mutex_unlock(®ulator->rdev->mutex);
|
||||||
|
@ -1203,6 +1296,56 @@ int regulator_is_enabled(struct regulator *regulator)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regulator_is_enabled);
|
EXPORT_SYMBOL_GPL(regulator_is_enabled);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* regulator_count_voltages - count regulator_list_voltage() selectors
|
||||||
|
* @regulator: regulator source
|
||||||
|
*
|
||||||
|
* Returns number of selectors, or negative errno. Selectors are
|
||||||
|
* numbered starting at zero, and typically correspond to bitfields
|
||||||
|
* in hardware registers.
|
||||||
|
*/
|
||||||
|
int regulator_count_voltages(struct regulator *regulator)
|
||||||
|
{
|
||||||
|
struct regulator_dev *rdev = regulator->rdev;
|
||||||
|
|
||||||
|
return rdev->desc->n_voltages ? : -EINVAL;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(regulator_count_voltages);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* regulator_list_voltage - enumerate supported voltages
|
||||||
|
* @regulator: regulator source
|
||||||
|
* @selector: identify voltage to list
|
||||||
|
* Context: can sleep
|
||||||
|
*
|
||||||
|
* Returns a voltage that can be passed to @regulator_set_voltage(),
|
||||||
|
* zero if this selector code can't be used on this sytem, or a
|
||||||
|
* negative errno.
|
||||||
|
*/
|
||||||
|
int regulator_list_voltage(struct regulator *regulator, unsigned selector)
|
||||||
|
{
|
||||||
|
struct regulator_dev *rdev = regulator->rdev;
|
||||||
|
struct regulator_ops *ops = rdev->desc->ops;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!ops->list_voltage || selector >= rdev->desc->n_voltages)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&rdev->mutex);
|
||||||
|
ret = ops->list_voltage(rdev, selector);
|
||||||
|
mutex_unlock(&rdev->mutex);
|
||||||
|
|
||||||
|
if (ret > 0) {
|
||||||
|
if (ret < rdev->constraints->min_uV)
|
||||||
|
ret = 0;
|
||||||
|
else if (ret > rdev->constraints->max_uV)
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(regulator_list_voltage);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* regulator_set_voltage - set regulator output voltage
|
* regulator_set_voltage - set regulator output voltage
|
||||||
* @regulator: regulator source
|
* @regulator: regulator source
|
||||||
|
@ -1243,6 +1386,7 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
|
||||||
ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV);
|
ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, NULL);
|
||||||
mutex_unlock(&rdev->mutex);
|
mutex_unlock(&rdev->mutex);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1543,20 +1687,23 @@ int regulator_unregister_notifier(struct regulator *regulator,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regulator_unregister_notifier);
|
EXPORT_SYMBOL_GPL(regulator_unregister_notifier);
|
||||||
|
|
||||||
/* notify regulator consumers and downstream regulator consumers */
|
/* notify regulator consumers and downstream regulator consumers.
|
||||||
|
* Note mutex must be held by caller.
|
||||||
|
*/
|
||||||
static void _notifier_call_chain(struct regulator_dev *rdev,
|
static void _notifier_call_chain(struct regulator_dev *rdev,
|
||||||
unsigned long event, void *data)
|
unsigned long event, void *data)
|
||||||
{
|
{
|
||||||
struct regulator_dev *_rdev;
|
struct regulator_dev *_rdev;
|
||||||
|
|
||||||
/* call rdev chain first */
|
/* call rdev chain first */
|
||||||
mutex_lock(&rdev->mutex);
|
|
||||||
blocking_notifier_call_chain(&rdev->notifier, event, NULL);
|
blocking_notifier_call_chain(&rdev->notifier, event, NULL);
|
||||||
mutex_unlock(&rdev->mutex);
|
|
||||||
|
|
||||||
/* now notify regulator we supply */
|
/* now notify regulator we supply */
|
||||||
list_for_each_entry(_rdev, &rdev->supply_list, slist)
|
list_for_each_entry(_rdev, &rdev->supply_list, slist) {
|
||||||
|
mutex_lock(&_rdev->mutex);
|
||||||
_notifier_call_chain(_rdev, event, data);
|
_notifier_call_chain(_rdev, event, data);
|
||||||
|
mutex_unlock(&_rdev->mutex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1703,6 +1850,7 @@ EXPORT_SYMBOL_GPL(regulator_bulk_free);
|
||||||
*
|
*
|
||||||
* Called by regulator drivers to notify clients a regulator event has
|
* Called by regulator drivers to notify clients a regulator event has
|
||||||
* occurred. We also notify regulator clients downstream.
|
* occurred. We also notify regulator clients downstream.
|
||||||
|
* Note lock must be held by caller.
|
||||||
*/
|
*/
|
||||||
int regulator_notifier_call_chain(struct regulator_dev *rdev,
|
int regulator_notifier_call_chain(struct regulator_dev *rdev,
|
||||||
unsigned long event, void *data)
|
unsigned long event, void *data)
|
||||||
|
@ -1744,6 +1892,11 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
if (ops->get_status) {
|
||||||
|
status = device_create_file(dev, &dev_attr_status);
|
||||||
|
if (status < 0)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
/* some attributes are type-specific */
|
/* some attributes are type-specific */
|
||||||
if (rdev->desc->type == REGULATOR_CURRENT) {
|
if (rdev->desc->type == REGULATOR_CURRENT) {
|
||||||
|
@ -1828,17 +1981,18 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
|
||||||
* regulator_register - register regulator
|
* regulator_register - register regulator
|
||||||
* @regulator_desc: regulator to register
|
* @regulator_desc: regulator to register
|
||||||
* @dev: struct device for the regulator
|
* @dev: struct device for the regulator
|
||||||
|
* @init_data: platform provided init data, passed through by driver
|
||||||
* @driver_data: private regulator data
|
* @driver_data: private regulator data
|
||||||
*
|
*
|
||||||
* Called by regulator drivers to register a regulator.
|
* Called by regulator drivers to register a regulator.
|
||||||
* Returns 0 on success.
|
* Returns 0 on success.
|
||||||
*/
|
*/
|
||||||
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
|
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
|
||||||
struct device *dev, void *driver_data)
|
struct device *dev, struct regulator_init_data *init_data,
|
||||||
|
void *driver_data)
|
||||||
{
|
{
|
||||||
static atomic_t regulator_no = ATOMIC_INIT(0);
|
static atomic_t regulator_no = ATOMIC_INIT(0);
|
||||||
struct regulator_dev *rdev;
|
struct regulator_dev *rdev;
|
||||||
struct regulator_init_data *init_data = dev->platform_data;
|
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
if (regulator_desc == NULL)
|
if (regulator_desc == NULL)
|
||||||
|
@ -1945,6 +2099,7 @@ void regulator_unregister(struct regulator_dev *rdev)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mutex_lock(®ulator_list_mutex);
|
mutex_lock(®ulator_list_mutex);
|
||||||
|
unset_regulator_supplies(rdev);
|
||||||
list_del(&rdev->list);
|
list_del(&rdev->list);
|
||||||
if (rdev->supply)
|
if (rdev->supply)
|
||||||
sysfs_remove_link(&rdev->dev.kobj, "supply");
|
sysfs_remove_link(&rdev->dev.kobj, "supply");
|
||||||
|
@ -1988,6 +2143,23 @@ out:
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regulator_suspend_prepare);
|
EXPORT_SYMBOL_GPL(regulator_suspend_prepare);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* regulator_has_full_constraints - the system has fully specified constraints
|
||||||
|
*
|
||||||
|
* Calling this function will cause the regulator API to disable all
|
||||||
|
* regulators which have a zero use count and don't have an always_on
|
||||||
|
* constraint in a late_initcall.
|
||||||
|
*
|
||||||
|
* The intention is that this will become the default behaviour in a
|
||||||
|
* future kernel release so users are encouraged to use this facility
|
||||||
|
* now.
|
||||||
|
*/
|
||||||
|
void regulator_has_full_constraints(void)
|
||||||
|
{
|
||||||
|
has_full_constraints = 1;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(regulator_has_full_constraints);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rdev_get_drvdata - get rdev regulator driver data
|
* rdev_get_drvdata - get rdev regulator driver data
|
||||||
* @rdev: regulator
|
* @rdev: regulator
|
||||||
|
@ -2055,3 +2227,77 @@ static int __init regulator_init(void)
|
||||||
|
|
||||||
/* init early to allow our consumers to complete system booting */
|
/* init early to allow our consumers to complete system booting */
|
||||||
core_initcall(regulator_init);
|
core_initcall(regulator_init);
|
||||||
|
|
||||||
|
static int __init regulator_init_complete(void)
|
||||||
|
{
|
||||||
|
struct regulator_dev *rdev;
|
||||||
|
struct regulator_ops *ops;
|
||||||
|
struct regulation_constraints *c;
|
||||||
|
int enabled, ret;
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
mutex_lock(®ulator_list_mutex);
|
||||||
|
|
||||||
|
/* If we have a full configuration then disable any regulators
|
||||||
|
* which are not in use or always_on. This will become the
|
||||||
|
* default behaviour in the future.
|
||||||
|
*/
|
||||||
|
list_for_each_entry(rdev, ®ulator_list, list) {
|
||||||
|
ops = rdev->desc->ops;
|
||||||
|
c = rdev->constraints;
|
||||||
|
|
||||||
|
if (c->name)
|
||||||
|
name = c->name;
|
||||||
|
else if (rdev->desc->name)
|
||||||
|
name = rdev->desc->name;
|
||||||
|
else
|
||||||
|
name = "regulator";
|
||||||
|
|
||||||
|
if (!ops->disable || c->always_on)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
mutex_lock(&rdev->mutex);
|
||||||
|
|
||||||
|
if (rdev->use_count)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
/* If we can't read the status assume it's on. */
|
||||||
|
if (ops->is_enabled)
|
||||||
|
enabled = ops->is_enabled(rdev);
|
||||||
|
else
|
||||||
|
enabled = 1;
|
||||||
|
|
||||||
|
if (!enabled)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
if (has_full_constraints) {
|
||||||
|
/* We log since this may kill the system if it
|
||||||
|
* goes wrong. */
|
||||||
|
printk(KERN_INFO "%s: disabling %s\n",
|
||||||
|
__func__, name);
|
||||||
|
ret = ops->disable(rdev);
|
||||||
|
if (ret != 0) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"%s: couldn't disable %s: %d\n",
|
||||||
|
__func__, name, ret);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* The intention is that in future we will
|
||||||
|
* assume that full constraints are provided
|
||||||
|
* so warn even if we aren't going to do
|
||||||
|
* anything here.
|
||||||
|
*/
|
||||||
|
printk(KERN_WARNING
|
||||||
|
"%s: incomplete constraints, leaving %s on\n",
|
||||||
|
__func__, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
mutex_unlock(&rdev->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(®ulator_list_mutex);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
late_initcall(regulator_init_complete);
|
||||||
|
|
|
@ -471,7 +471,8 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev)
|
||||||
if (ri->desc.id == DA9030_ID_LDO1 || ri->desc.id == DA9030_ID_LDO15)
|
if (ri->desc.id == DA9030_ID_LDO1 || ri->desc.id == DA9030_ID_LDO15)
|
||||||
ri->desc.ops = &da9030_regulator_ldo1_15_ops;
|
ri->desc.ops = &da9030_regulator_ldo1_15_ops;
|
||||||
|
|
||||||
rdev = regulator_register(&ri->desc, &pdev->dev, ri);
|
rdev = regulator_register(&ri->desc, &pdev->dev,
|
||||||
|
pdev->dev.platform_data, ri);
|
||||||
if (IS_ERR(rdev)) {
|
if (IS_ERR(rdev)) {
|
||||||
dev_err(&pdev->dev, "failed to register regulator %s\n",
|
dev_err(&pdev->dev, "failed to register regulator %s\n",
|
||||||
ri->desc.name);
|
ri->desc.name);
|
||||||
|
|
|
@ -73,7 +73,8 @@ static int regulator_fixed_voltage_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
drvdata->microvolts = config->microvolts;
|
drvdata->microvolts = config->microvolts;
|
||||||
|
|
||||||
drvdata->dev = regulator_register(&drvdata->desc, drvdata);
|
drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev,
|
||||||
|
config->init_data, drvdata);
|
||||||
if (IS_ERR(drvdata->dev)) {
|
if (IS_ERR(drvdata->dev)) {
|
||||||
ret = PTR_ERR(drvdata->dev);
|
ret = PTR_ERR(drvdata->dev);
|
||||||
goto err_name;
|
goto err_name;
|
||||||
|
|
|
@ -284,7 +284,8 @@ static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
|
||||||
/* Already set by core driver */
|
/* Already set by core driver */
|
||||||
pcf = platform_get_drvdata(pdev);
|
pcf = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
rdev = regulator_register(®ulators[pdev->id], &pdev->dev, pcf);
|
rdev = regulator_register(®ulators[pdev->id], &pdev->dev,
|
||||||
|
pdev->dev.platform_data, pcf);
|
||||||
if (IS_ERR(rdev))
|
if (IS_ERR(rdev))
|
||||||
return PTR_ERR(rdev);
|
return PTR_ERR(rdev);
|
||||||
|
|
||||||
|
|
500
drivers/regulator/twl4030-regulator.c
Normal file
500
drivers/regulator/twl4030-regulator.c
Normal file
|
@ -0,0 +1,500 @@
|
||||||
|
/*
|
||||||
|
* twl4030-regulator.c -- support regulators in twl4030 family chips
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 David Brownell
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/regulator/driver.h>
|
||||||
|
#include <linux/regulator/machine.h>
|
||||||
|
#include <linux/i2c/twl4030.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The TWL4030/TW5030/TPS659x0 family chips include power management, a
|
||||||
|
* USB OTG transceiver, an RTC, ADC, PWM, and lots more. Some versions
|
||||||
|
* include an audio codec, battery charger, and more voltage regulators.
|
||||||
|
* These chips are often used in OMAP-based systems.
|
||||||
|
*
|
||||||
|
* This driver implements software-based resource control for various
|
||||||
|
* voltage regulators. This is usually augmented with state machine
|
||||||
|
* based control.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct twlreg_info {
|
||||||
|
/* start of regulator's PM_RECEIVER control register bank */
|
||||||
|
u8 base;
|
||||||
|
|
||||||
|
/* twl4030 resource ID, for resource control state machine */
|
||||||
|
u8 id;
|
||||||
|
|
||||||
|
/* voltage in mV = table[VSEL]; table_len must be a power-of-two */
|
||||||
|
u8 table_len;
|
||||||
|
const u16 *table;
|
||||||
|
|
||||||
|
/* chip constraints on regulator behavior */
|
||||||
|
u16 min_mV;
|
||||||
|
|
||||||
|
/* used by regulator core */
|
||||||
|
struct regulator_desc desc;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* LDO control registers ... offset is from the base of its register bank.
|
||||||
|
* The first three registers of all power resource banks help hardware to
|
||||||
|
* manage the various resource groups.
|
||||||
|
*/
|
||||||
|
#define VREG_GRP 0
|
||||||
|
#define VREG_TYPE 1
|
||||||
|
#define VREG_REMAP 2
|
||||||
|
#define VREG_DEDICATED 3 /* LDO control */
|
||||||
|
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
twl4030reg_read(struct twlreg_info *info, unsigned offset)
|
||||||
|
{
|
||||||
|
u8 value;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER,
|
||||||
|
&value, info->base + offset);
|
||||||
|
return (status < 0) ? status : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
twl4030reg_write(struct twlreg_info *info, unsigned offset, u8 value)
|
||||||
|
{
|
||||||
|
return twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
|
||||||
|
value, info->base + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* generic power resource operations, which work on all regulators */
|
||||||
|
|
||||||
|
static int twl4030reg_grp(struct regulator_dev *rdev)
|
||||||
|
{
|
||||||
|
return twl4030reg_read(rdev_get_drvdata(rdev), VREG_GRP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable/disable regulators by joining/leaving the P1 (processor) group.
|
||||||
|
* We assume nobody else is updating the DEV_GRP registers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define P3_GRP BIT(7) /* "peripherals" */
|
||||||
|
#define P2_GRP BIT(6) /* secondary processor, modem, etc */
|
||||||
|
#define P1_GRP BIT(5) /* CPU/Linux */
|
||||||
|
|
||||||
|
static int twl4030reg_is_enabled(struct regulator_dev *rdev)
|
||||||
|
{
|
||||||
|
int state = twl4030reg_grp(rdev);
|
||||||
|
|
||||||
|
if (state < 0)
|
||||||
|
return state;
|
||||||
|
|
||||||
|
return (state & P1_GRP) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int twl4030reg_enable(struct regulator_dev *rdev)
|
||||||
|
{
|
||||||
|
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||||
|
int grp;
|
||||||
|
|
||||||
|
grp = twl4030reg_read(info, VREG_GRP);
|
||||||
|
if (grp < 0)
|
||||||
|
return grp;
|
||||||
|
|
||||||
|
grp |= P1_GRP;
|
||||||
|
return twl4030reg_write(info, VREG_GRP, grp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int twl4030reg_disable(struct regulator_dev *rdev)
|
||||||
|
{
|
||||||
|
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||||
|
int grp;
|
||||||
|
|
||||||
|
grp = twl4030reg_read(info, VREG_GRP);
|
||||||
|
if (grp < 0)
|
||||||
|
return grp;
|
||||||
|
|
||||||
|
grp &= ~P1_GRP;
|
||||||
|
return twl4030reg_write(info, VREG_GRP, grp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int twl4030reg_get_status(struct regulator_dev *rdev)
|
||||||
|
{
|
||||||
|
int state = twl4030reg_grp(rdev);
|
||||||
|
|
||||||
|
if (state < 0)
|
||||||
|
return state;
|
||||||
|
state &= 0x0f;
|
||||||
|
|
||||||
|
/* assume state != WARM_RESET; we'd not be running... */
|
||||||
|
if (!state)
|
||||||
|
return REGULATOR_STATUS_OFF;
|
||||||
|
return (state & BIT(3))
|
||||||
|
? REGULATOR_STATUS_NORMAL
|
||||||
|
: REGULATOR_STATUS_STANDBY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
|
||||||
|
{
|
||||||
|
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||||
|
unsigned message;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
/* We can only set the mode through state machine commands... */
|
||||||
|
switch (mode) {
|
||||||
|
case REGULATOR_MODE_NORMAL:
|
||||||
|
message = MSG_SINGULAR(DEV_GRP_P1, info->id, RES_STATE_ACTIVE);
|
||||||
|
break;
|
||||||
|
case REGULATOR_MODE_STANDBY:
|
||||||
|
message = MSG_SINGULAR(DEV_GRP_P1, info->id, RES_STATE_SLEEP);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure the resource is associated with some group */
|
||||||
|
status = twl4030reg_grp(rdev);
|
||||||
|
if (status < 0)
|
||||||
|
return status;
|
||||||
|
if (!(status & (P3_GRP | P2_GRP | P1_GRP)))
|
||||||
|
return -EACCES;
|
||||||
|
|
||||||
|
status = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
|
||||||
|
message >> 8, 0x15 /* PB_WORD_MSB */ );
|
||||||
|
if (status >= 0)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
return twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
|
||||||
|
message, 0x16 /* PB_WORD_LSB */ );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Support for adjustable-voltage LDOs uses a four bit (or less) voltage
|
||||||
|
* select field in its control register. We use tables indexed by VSEL
|
||||||
|
* to record voltages in milliVolts. (Accuracy is about three percent.)
|
||||||
|
*
|
||||||
|
* Note that VSEL values for VAUX2 changed in twl5030 and newer silicon;
|
||||||
|
* currently handled by listing two slightly different VAUX2 regulators,
|
||||||
|
* only one of which will be configured.
|
||||||
|
*
|
||||||
|
* VSEL values documented as "TI cannot support these values" are flagged
|
||||||
|
* in these tables as UNSUP() values; we normally won't assign them.
|
||||||
|
*
|
||||||
|
* VAUX3 at 3V is incorrectly listed in some TI manuals as unsupported.
|
||||||
|
* TI are revising the twl5030/tps659x0 specs to support that 3.0V setting.
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_TWL4030_ALLOW_UNSUPPORTED
|
||||||
|
#define UNSUP_MASK 0x0000
|
||||||
|
#else
|
||||||
|
#define UNSUP_MASK 0x8000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define UNSUP(x) (UNSUP_MASK | (x))
|
||||||
|
#define IS_UNSUP(x) (UNSUP_MASK & (x))
|
||||||
|
#define LDO_MV(x) (~UNSUP_MASK & (x))
|
||||||
|
|
||||||
|
|
||||||
|
static const u16 VAUX1_VSEL_table[] = {
|
||||||
|
UNSUP(1500), UNSUP(1800), 2500, 2800,
|
||||||
|
3000, 3000, 3000, 3000,
|
||||||
|
};
|
||||||
|
static const u16 VAUX2_4030_VSEL_table[] = {
|
||||||
|
UNSUP(1000), UNSUP(1000), UNSUP(1200), 1300,
|
||||||
|
1500, 1800, UNSUP(1850), 2500,
|
||||||
|
UNSUP(2600), 2800, UNSUP(2850), UNSUP(3000),
|
||||||
|
UNSUP(3150), UNSUP(3150), UNSUP(3150), UNSUP(3150),
|
||||||
|
};
|
||||||
|
static const u16 VAUX2_VSEL_table[] = {
|
||||||
|
1700, 1700, 1900, 1300,
|
||||||
|
1500, 1800, 2000, 2500,
|
||||||
|
2100, 2800, 2200, 2300,
|
||||||
|
2400, 2400, 2400, 2400,
|
||||||
|
};
|
||||||
|
static const u16 VAUX3_VSEL_table[] = {
|
||||||
|
1500, 1800, 2500, 2800,
|
||||||
|
3000, 3000, 3000, 3000,
|
||||||
|
};
|
||||||
|
static const u16 VAUX4_VSEL_table[] = {
|
||||||
|
700, 1000, 1200, UNSUP(1300),
|
||||||
|
1500, 1800, UNSUP(1850), 2500,
|
||||||
|
UNSUP(2600), 2800, UNSUP(2850), UNSUP(3000),
|
||||||
|
UNSUP(3150), UNSUP(3150), UNSUP(3150), UNSUP(3150),
|
||||||
|
};
|
||||||
|
static const u16 VMMC1_VSEL_table[] = {
|
||||||
|
1850, 2850, 3000, 3150,
|
||||||
|
};
|
||||||
|
static const u16 VMMC2_VSEL_table[] = {
|
||||||
|
UNSUP(1000), UNSUP(1000), UNSUP(1200), UNSUP(1300),
|
||||||
|
UNSUP(1500), UNSUP(1800), 1850, UNSUP(2500),
|
||||||
|
2600, 2800, 2850, 3000,
|
||||||
|
3150, 3150, 3150, 3150,
|
||||||
|
};
|
||||||
|
static const u16 VPLL1_VSEL_table[] = {
|
||||||
|
1000, 1200, 1300, 1800,
|
||||||
|
UNSUP(2800), UNSUP(3000), UNSUP(3000), UNSUP(3000),
|
||||||
|
};
|
||||||
|
static const u16 VPLL2_VSEL_table[] = {
|
||||||
|
700, 1000, 1200, 1300,
|
||||||
|
UNSUP(1500), 1800, UNSUP(1850), UNSUP(2500),
|
||||||
|
UNSUP(2600), UNSUP(2800), UNSUP(2850), UNSUP(3000),
|
||||||
|
UNSUP(3150), UNSUP(3150), UNSUP(3150), UNSUP(3150),
|
||||||
|
};
|
||||||
|
static const u16 VSIM_VSEL_table[] = {
|
||||||
|
UNSUP(1000), UNSUP(1200), UNSUP(1300), 1800,
|
||||||
|
2800, 3000, 3000, 3000,
|
||||||
|
};
|
||||||
|
static const u16 VDAC_VSEL_table[] = {
|
||||||
|
1200, 1300, 1800, 1800,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
|
||||||
|
{
|
||||||
|
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||||
|
int mV = info->table[index];
|
||||||
|
|
||||||
|
return IS_UNSUP(mV) ? 0 : (LDO_MV(mV) * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
|
||||||
|
{
|
||||||
|
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||||
|
int vsel;
|
||||||
|
|
||||||
|
for (vsel = 0; vsel < info->table_len; vsel++) {
|
||||||
|
int mV = info->table[vsel];
|
||||||
|
int uV;
|
||||||
|
|
||||||
|
if (IS_UNSUP(mV))
|
||||||
|
continue;
|
||||||
|
uV = LDO_MV(mV) * 1000;
|
||||||
|
|
||||||
|
/* REVISIT for VAUX2, first match may not be best/lowest */
|
||||||
|
|
||||||
|
/* use the first in-range value */
|
||||||
|
if (min_uV <= uV && uV <= max_uV)
|
||||||
|
return twl4030reg_write(info, VREG_DEDICATED, vsel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EDOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int twl4030ldo_get_voltage(struct regulator_dev *rdev)
|
||||||
|
{
|
||||||
|
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||||
|
int vsel = twl4030reg_read(info, VREG_DEDICATED);
|
||||||
|
|
||||||
|
if (vsel < 0)
|
||||||
|
return vsel;
|
||||||
|
|
||||||
|
vsel &= info->table_len - 1;
|
||||||
|
return LDO_MV(info->table[vsel]) * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct regulator_ops twl4030ldo_ops = {
|
||||||
|
.list_voltage = twl4030ldo_list_voltage,
|
||||||
|
|
||||||
|
.set_voltage = twl4030ldo_set_voltage,
|
||||||
|
.get_voltage = twl4030ldo_get_voltage,
|
||||||
|
|
||||||
|
.enable = twl4030reg_enable,
|
||||||
|
.disable = twl4030reg_disable,
|
||||||
|
.is_enabled = twl4030reg_is_enabled,
|
||||||
|
|
||||||
|
.set_mode = twl4030reg_set_mode,
|
||||||
|
|
||||||
|
.get_status = twl4030reg_get_status,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fixed voltage LDOs don't have a VSEL field to update.
|
||||||
|
*/
|
||||||
|
static int twl4030fixed_list_voltage(struct regulator_dev *rdev, unsigned index)
|
||||||
|
{
|
||||||
|
struct twlreg_info *info = rdev_get_drvdata(rdev);
|
||||||
|
|
||||||
|
return info->min_mV * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int twl4030fixed_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 = twl4030fixed_list_voltage,
|
||||||
|
|
||||||
|
.get_voltage = twl4030fixed_get_voltage,
|
||||||
|
|
||||||
|
.enable = twl4030reg_enable,
|
||||||
|
.disable = twl4030reg_disable,
|
||||||
|
.is_enabled = twl4030reg_is_enabled,
|
||||||
|
|
||||||
|
.set_mode = twl4030reg_set_mode,
|
||||||
|
|
||||||
|
.get_status = twl4030reg_get_status,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define TWL_ADJUSTABLE_LDO(label, offset, num) { \
|
||||||
|
.base = offset, \
|
||||||
|
.id = num, \
|
||||||
|
.table_len = ARRAY_SIZE(label##_VSEL_table), \
|
||||||
|
.table = label##_VSEL_table, \
|
||||||
|
.desc = { \
|
||||||
|
.name = #label, \
|
||||||
|
.id = TWL4030_REG_##label, \
|
||||||
|
.n_voltages = ARRAY_SIZE(label##_VSEL_table), \
|
||||||
|
.ops = &twl4030ldo_ops, \
|
||||||
|
.type = REGULATOR_VOLTAGE, \
|
||||||
|
.owner = THIS_MODULE, \
|
||||||
|
}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TWL_FIXED_LDO(label, offset, mVolts, num) { \
|
||||||
|
.base = offset, \
|
||||||
|
.id = num, \
|
||||||
|
.min_mV = mVolts, \
|
||||||
|
.desc = { \
|
||||||
|
.name = #label, \
|
||||||
|
.id = TWL4030_REG_##label, \
|
||||||
|
.n_voltages = 1, \
|
||||||
|
.ops = &twl4030fixed_ops, \
|
||||||
|
.type = REGULATOR_VOLTAGE, \
|
||||||
|
.owner = THIS_MODULE, \
|
||||||
|
}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We list regulators here if systems need some level of
|
||||||
|
* software control over them after boot.
|
||||||
|
*/
|
||||||
|
static struct twlreg_info twl4030_regs[] = {
|
||||||
|
TWL_ADJUSTABLE_LDO(VAUX1, 0x17, 1),
|
||||||
|
TWL_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2),
|
||||||
|
TWL_ADJUSTABLE_LDO(VAUX2, 0x1b, 2),
|
||||||
|
TWL_ADJUSTABLE_LDO(VAUX3, 0x1f, 3),
|
||||||
|
TWL_ADJUSTABLE_LDO(VAUX4, 0x23, 4),
|
||||||
|
TWL_ADJUSTABLE_LDO(VMMC1, 0x27, 5),
|
||||||
|
TWL_ADJUSTABLE_LDO(VMMC2, 0x2b, 6),
|
||||||
|
/*
|
||||||
|
TWL_ADJUSTABLE_LDO(VPLL1, 0x2f, 7),
|
||||||
|
*/
|
||||||
|
TWL_ADJUSTABLE_LDO(VPLL2, 0x33, 8),
|
||||||
|
TWL_ADJUSTABLE_LDO(VSIM, 0x37, 9),
|
||||||
|
TWL_ADJUSTABLE_LDO(VDAC, 0x3b, 10),
|
||||||
|
/*
|
||||||
|
TWL_ADJUSTABLE_LDO(VINTANA1, 0x3f, 11),
|
||||||
|
TWL_ADJUSTABLE_LDO(VINTANA2, 0x43, 12),
|
||||||
|
TWL_ADJUSTABLE_LDO(VINTDIG, 0x47, 13),
|
||||||
|
TWL_SMPS(VIO, 0x4b, 14),
|
||||||
|
TWL_SMPS(VDD1, 0x55, 15),
|
||||||
|
TWL_SMPS(VDD2, 0x63, 16),
|
||||||
|
*/
|
||||||
|
TWL_FIXED_LDO(VUSB1V5, 0x71, 1500, 17),
|
||||||
|
TWL_FIXED_LDO(VUSB1V8, 0x74, 1800, 18),
|
||||||
|
TWL_FIXED_LDO(VUSB3V1, 0x77, 3100, 19),
|
||||||
|
/* VUSBCP is managed *only* by the USB subchip */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int twl4030reg_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct twlreg_info *info;
|
||||||
|
struct regulator_init_data *initdata;
|
||||||
|
struct regulation_constraints *c;
|
||||||
|
struct regulator_dev *rdev;
|
||||||
|
|
||||||
|
for (i = 0, info = NULL; i < ARRAY_SIZE(twl4030_regs); i++) {
|
||||||
|
if (twl4030_regs[i].desc.id != pdev->id)
|
||||||
|
continue;
|
||||||
|
info = twl4030_regs + i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!info)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
initdata = pdev->dev.platform_data;
|
||||||
|
if (!initdata)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Constrain board-specific capabilities according to what
|
||||||
|
* this driver and the chip itself can actually do.
|
||||||
|
*/
|
||||||
|
c = &initdata->constraints;
|
||||||
|
c->valid_modes_mask &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY;
|
||||||
|
c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE
|
||||||
|
| REGULATOR_CHANGE_MODE
|
||||||
|
| REGULATOR_CHANGE_STATUS;
|
||||||
|
|
||||||
|
rdev = regulator_register(&info->desc, &pdev->dev, initdata, info);
|
||||||
|
if (IS_ERR(rdev)) {
|
||||||
|
dev_err(&pdev->dev, "can't register %s, %ld\n",
|
||||||
|
info->desc.name, PTR_ERR(rdev));
|
||||||
|
return PTR_ERR(rdev);
|
||||||
|
}
|
||||||
|
platform_set_drvdata(pdev, rdev);
|
||||||
|
|
||||||
|
/* NOTE: many regulators support short-circuit IRQs (presentable
|
||||||
|
* as REGULATOR_OVER_CURRENT notifications?) configured via:
|
||||||
|
* - SC_CONFIG
|
||||||
|
* - SC_DETECT1 (vintana2, vmmc1/2, vaux1/2/3/4)
|
||||||
|
* - SC_DETECT2 (vusb, vdac, vio, vdd1/2, vpll2)
|
||||||
|
* - IT_CONFIG
|
||||||
|
*/
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __devexit twl4030reg_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
regulator_unregister(platform_get_drvdata(pdev));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MODULE_ALIAS("platform:twl4030_reg");
|
||||||
|
|
||||||
|
static struct platform_driver twl4030reg_driver = {
|
||||||
|
.probe = twl4030reg_probe,
|
||||||
|
.remove = __devexit_p(twl4030reg_remove),
|
||||||
|
/* NOTE: short name, to work around driver model truncation of
|
||||||
|
* "twl4030_regulator.12" (and friends) to "twl4030_regulator.1".
|
||||||
|
*/
|
||||||
|
.driver.name = "twl4030_reg",
|
||||||
|
.driver.owner = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init twl4030reg_init(void)
|
||||||
|
{
|
||||||
|
return platform_driver_register(&twl4030reg_driver);
|
||||||
|
}
|
||||||
|
subsys_initcall(twl4030reg_init);
|
||||||
|
|
||||||
|
static void __exit twl4030reg_exit(void)
|
||||||
|
{
|
||||||
|
platform_driver_unregister(&twl4030reg_driver);
|
||||||
|
}
|
||||||
|
module_exit(twl4030reg_exit)
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("TWL4030 regulator driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
|
@ -226,13 +226,17 @@ static ssize_t set_mode(struct device *dev, struct device_attribute *attr,
|
||||||
unsigned int mode;
|
unsigned int mode;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (strncmp(buf, "fast", strlen("fast")) == 0)
|
/*
|
||||||
|
* sysfs_streq() doesn't need the \n's, but we add them so the strings
|
||||||
|
* will be shared with show_mode(), above.
|
||||||
|
*/
|
||||||
|
if (sysfs_streq(buf, "fast\n") == 0)
|
||||||
mode = REGULATOR_MODE_FAST;
|
mode = REGULATOR_MODE_FAST;
|
||||||
else if (strncmp(buf, "normal", strlen("normal")) == 0)
|
else if (sysfs_streq(buf, "normal\n") == 0)
|
||||||
mode = REGULATOR_MODE_NORMAL;
|
mode = REGULATOR_MODE_NORMAL;
|
||||||
else if (strncmp(buf, "idle", strlen("idle")) == 0)
|
else if (sysfs_streq(buf, "idle\n") == 0)
|
||||||
mode = REGULATOR_MODE_IDLE;
|
mode = REGULATOR_MODE_IDLE;
|
||||||
else if (strncmp(buf, "standby", strlen("standby")) == 0)
|
else if (sysfs_streq(buf, "standby\n") == 0)
|
||||||
mode = REGULATOR_MODE_STANDBY;
|
mode = REGULATOR_MODE_STANDBY;
|
||||||
else {
|
else {
|
||||||
dev_err(dev, "Configuring invalid mode\n");
|
dev_err(dev, "Configuring invalid mode\n");
|
||||||
|
@ -256,7 +260,7 @@ static DEVICE_ATTR(min_microamps, 0666, show_min_uA, set_min_uA);
|
||||||
static DEVICE_ATTR(max_microamps, 0666, show_max_uA, set_max_uA);
|
static DEVICE_ATTR(max_microamps, 0666, show_max_uA, set_max_uA);
|
||||||
static DEVICE_ATTR(mode, 0666, show_mode, set_mode);
|
static DEVICE_ATTR(mode, 0666, show_mode, set_mode);
|
||||||
|
|
||||||
struct device_attribute *attributes[] = {
|
static struct device_attribute *attributes[] = {
|
||||||
&dev_attr_min_microvolts,
|
&dev_attr_min_microvolts,
|
||||||
&dev_attr_max_microvolts,
|
&dev_attr_max_microvolts,
|
||||||
&dev_attr_min_microamps,
|
&dev_attr_min_microamps,
|
||||||
|
|
|
@ -24,6 +24,9 @@
|
||||||
#include <linux/regulator/driver.h>
|
#include <linux/regulator/driver.h>
|
||||||
#include <linux/regulator/machine.h>
|
#include <linux/regulator/machine.h>
|
||||||
|
|
||||||
|
/* Maximum value possible for VSEL */
|
||||||
|
#define WM8350_DCDC_MAX_VSEL 0x66
|
||||||
|
|
||||||
/* Microamps */
|
/* Microamps */
|
||||||
static const int isink_cur[] = {
|
static const int isink_cur[] = {
|
||||||
4,
|
4,
|
||||||
|
@ -385,6 +388,14 @@ static int wm8350_dcdc_get_voltage(struct regulator_dev *rdev)
|
||||||
return wm8350_dcdc_val_to_mvolts(val) * 1000;
|
return wm8350_dcdc_val_to_mvolts(val) * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int wm8350_dcdc_list_voltage(struct regulator_dev *rdev,
|
||||||
|
unsigned selector)
|
||||||
|
{
|
||||||
|
if (selector > WM8350_DCDC_MAX_VSEL)
|
||||||
|
return -EINVAL;
|
||||||
|
return wm8350_dcdc_val_to_mvolts(selector) * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV)
|
static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV)
|
||||||
{
|
{
|
||||||
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
|
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
|
||||||
|
@ -775,6 +786,14 @@ static int wm8350_ldo_get_voltage(struct regulator_dev *rdev)
|
||||||
return wm8350_ldo_val_to_mvolts(val) * 1000;
|
return wm8350_ldo_val_to_mvolts(val) * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int wm8350_ldo_list_voltage(struct regulator_dev *rdev,
|
||||||
|
unsigned selector)
|
||||||
|
{
|
||||||
|
if (selector > WM8350_LDO1_VSEL_MASK)
|
||||||
|
return -EINVAL;
|
||||||
|
return wm8350_ldo_val_to_mvolts(selector) * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
int wm8350_dcdc_set_slot(struct wm8350 *wm8350, int dcdc, u16 start,
|
int wm8350_dcdc_set_slot(struct wm8350 *wm8350, int dcdc, u16 start,
|
||||||
u16 stop, u16 fault)
|
u16 stop, u16 fault)
|
||||||
{
|
{
|
||||||
|
@ -1031,18 +1050,30 @@ static unsigned int wm8350_dcdc_get_mode(struct regulator_dev *rdev)
|
||||||
int dcdc = rdev_get_id(rdev);
|
int dcdc = rdev_get_id(rdev);
|
||||||
u16 mask, sleep, active, force;
|
u16 mask, sleep, active, force;
|
||||||
int mode = REGULATOR_MODE_NORMAL;
|
int mode = REGULATOR_MODE_NORMAL;
|
||||||
|
int reg;
|
||||||
|
|
||||||
if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
|
switch (dcdc) {
|
||||||
return -EINVAL;
|
case WM8350_DCDC_1:
|
||||||
|
reg = WM8350_DCDC1_FORCE_PWM;
|
||||||
if (dcdc == WM8350_DCDC_2 || dcdc == WM8350_DCDC_5)
|
break;
|
||||||
|
case WM8350_DCDC_3:
|
||||||
|
reg = WM8350_DCDC3_FORCE_PWM;
|
||||||
|
break;
|
||||||
|
case WM8350_DCDC_4:
|
||||||
|
reg = WM8350_DCDC4_FORCE_PWM;
|
||||||
|
break;
|
||||||
|
case WM8350_DCDC_6:
|
||||||
|
reg = WM8350_DCDC6_FORCE_PWM;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
mask = 1 << (dcdc - WM8350_DCDC_1);
|
mask = 1 << (dcdc - WM8350_DCDC_1);
|
||||||
active = wm8350_reg_read(wm8350, WM8350_DCDC_ACTIVE_OPTIONS) & mask;
|
active = wm8350_reg_read(wm8350, WM8350_DCDC_ACTIVE_OPTIONS) & mask;
|
||||||
|
force = wm8350_reg_read(wm8350, reg) & WM8350_DCDC1_FORCE_PWM_ENA;
|
||||||
sleep = wm8350_reg_read(wm8350, WM8350_DCDC_SLEEP_OPTIONS) & mask;
|
sleep = wm8350_reg_read(wm8350, WM8350_DCDC_SLEEP_OPTIONS) & mask;
|
||||||
force = wm8350_reg_read(wm8350, WM8350_DCDC1_FORCE_PWM)
|
|
||||||
& WM8350_DCDC1_FORCE_PWM_ENA;
|
|
||||||
dev_dbg(wm8350->dev, "mask %x active %x sleep %x force %x",
|
dev_dbg(wm8350->dev, "mask %x active %x sleep %x force %x",
|
||||||
mask, active, sleep, force);
|
mask, active, sleep, force);
|
||||||
|
|
||||||
|
@ -1150,6 +1181,7 @@ static int wm8350_ldo_is_enabled(struct regulator_dev *rdev)
|
||||||
static struct regulator_ops wm8350_dcdc_ops = {
|
static struct regulator_ops wm8350_dcdc_ops = {
|
||||||
.set_voltage = wm8350_dcdc_set_voltage,
|
.set_voltage = wm8350_dcdc_set_voltage,
|
||||||
.get_voltage = wm8350_dcdc_get_voltage,
|
.get_voltage = wm8350_dcdc_get_voltage,
|
||||||
|
.list_voltage = wm8350_dcdc_list_voltage,
|
||||||
.enable = wm8350_dcdc_enable,
|
.enable = wm8350_dcdc_enable,
|
||||||
.disable = wm8350_dcdc_disable,
|
.disable = wm8350_dcdc_disable,
|
||||||
.get_mode = wm8350_dcdc_get_mode,
|
.get_mode = wm8350_dcdc_get_mode,
|
||||||
|
@ -1173,6 +1205,7 @@ static struct regulator_ops wm8350_dcdc2_5_ops = {
|
||||||
static struct regulator_ops wm8350_ldo_ops = {
|
static struct regulator_ops wm8350_ldo_ops = {
|
||||||
.set_voltage = wm8350_ldo_set_voltage,
|
.set_voltage = wm8350_ldo_set_voltage,
|
||||||
.get_voltage = wm8350_ldo_get_voltage,
|
.get_voltage = wm8350_ldo_get_voltage,
|
||||||
|
.list_voltage = wm8350_ldo_list_voltage,
|
||||||
.enable = wm8350_ldo_enable,
|
.enable = wm8350_ldo_enable,
|
||||||
.disable = wm8350_ldo_disable,
|
.disable = wm8350_ldo_disable,
|
||||||
.is_enabled = wm8350_ldo_is_enabled,
|
.is_enabled = wm8350_ldo_is_enabled,
|
||||||
|
@ -1197,6 +1230,7 @@ static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||||
.ops = &wm8350_dcdc_ops,
|
.ops = &wm8350_dcdc_ops,
|
||||||
.irq = WM8350_IRQ_UV_DC1,
|
.irq = WM8350_IRQ_UV_DC1,
|
||||||
.type = REGULATOR_VOLTAGE,
|
.type = REGULATOR_VOLTAGE,
|
||||||
|
.n_voltages = WM8350_DCDC_MAX_VSEL + 1,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1213,6 +1247,7 @@ static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||||
.ops = &wm8350_dcdc_ops,
|
.ops = &wm8350_dcdc_ops,
|
||||||
.irq = WM8350_IRQ_UV_DC3,
|
.irq = WM8350_IRQ_UV_DC3,
|
||||||
.type = REGULATOR_VOLTAGE,
|
.type = REGULATOR_VOLTAGE,
|
||||||
|
.n_voltages = WM8350_DCDC_MAX_VSEL + 1,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1221,6 +1256,7 @@ static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||||
.ops = &wm8350_dcdc_ops,
|
.ops = &wm8350_dcdc_ops,
|
||||||
.irq = WM8350_IRQ_UV_DC4,
|
.irq = WM8350_IRQ_UV_DC4,
|
||||||
.type = REGULATOR_VOLTAGE,
|
.type = REGULATOR_VOLTAGE,
|
||||||
|
.n_voltages = WM8350_DCDC_MAX_VSEL + 1,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1237,6 +1273,7 @@ static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||||
.ops = &wm8350_dcdc_ops,
|
.ops = &wm8350_dcdc_ops,
|
||||||
.irq = WM8350_IRQ_UV_DC6,
|
.irq = WM8350_IRQ_UV_DC6,
|
||||||
.type = REGULATOR_VOLTAGE,
|
.type = REGULATOR_VOLTAGE,
|
||||||
|
.n_voltages = WM8350_DCDC_MAX_VSEL + 1,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1245,6 +1282,7 @@ static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||||
.ops = &wm8350_ldo_ops,
|
.ops = &wm8350_ldo_ops,
|
||||||
.irq = WM8350_IRQ_UV_LDO1,
|
.irq = WM8350_IRQ_UV_LDO1,
|
||||||
.type = REGULATOR_VOLTAGE,
|
.type = REGULATOR_VOLTAGE,
|
||||||
|
.n_voltages = WM8350_LDO1_VSEL_MASK + 1,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1253,6 +1291,7 @@ static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||||
.ops = &wm8350_ldo_ops,
|
.ops = &wm8350_ldo_ops,
|
||||||
.irq = WM8350_IRQ_UV_LDO2,
|
.irq = WM8350_IRQ_UV_LDO2,
|
||||||
.type = REGULATOR_VOLTAGE,
|
.type = REGULATOR_VOLTAGE,
|
||||||
|
.n_voltages = WM8350_LDO2_VSEL_MASK + 1,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1261,6 +1300,7 @@ static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||||
.ops = &wm8350_ldo_ops,
|
.ops = &wm8350_ldo_ops,
|
||||||
.irq = WM8350_IRQ_UV_LDO3,
|
.irq = WM8350_IRQ_UV_LDO3,
|
||||||
.type = REGULATOR_VOLTAGE,
|
.type = REGULATOR_VOLTAGE,
|
||||||
|
.n_voltages = WM8350_LDO3_VSEL_MASK + 1,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1269,6 +1309,7 @@ static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||||
.ops = &wm8350_ldo_ops,
|
.ops = &wm8350_ldo_ops,
|
||||||
.irq = WM8350_IRQ_UV_LDO4,
|
.irq = WM8350_IRQ_UV_LDO4,
|
||||||
.type = REGULATOR_VOLTAGE,
|
.type = REGULATOR_VOLTAGE,
|
||||||
|
.n_voltages = WM8350_LDO4_VSEL_MASK + 1,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1293,6 +1334,7 @@ static void pmic_uv_handler(struct wm8350 *wm8350, int irq, void *data)
|
||||||
{
|
{
|
||||||
struct regulator_dev *rdev = (struct regulator_dev *)data;
|
struct regulator_dev *rdev = (struct regulator_dev *)data;
|
||||||
|
|
||||||
|
mutex_lock(&rdev->mutex);
|
||||||
if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2)
|
if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2)
|
||||||
regulator_notifier_call_chain(rdev,
|
regulator_notifier_call_chain(rdev,
|
||||||
REGULATOR_EVENT_REGULATION_OUT,
|
REGULATOR_EVENT_REGULATION_OUT,
|
||||||
|
@ -1301,6 +1343,7 @@ static void pmic_uv_handler(struct wm8350 *wm8350, int irq, void *data)
|
||||||
regulator_notifier_call_chain(rdev,
|
regulator_notifier_call_chain(rdev,
|
||||||
REGULATOR_EVENT_UNDER_VOLTAGE,
|
REGULATOR_EVENT_UNDER_VOLTAGE,
|
||||||
wm8350);
|
wm8350);
|
||||||
|
mutex_unlock(&rdev->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wm8350_regulator_probe(struct platform_device *pdev)
|
static int wm8350_regulator_probe(struct platform_device *pdev)
|
||||||
|
@ -1333,9 +1376,9 @@ static int wm8350_regulator_probe(struct platform_device *pdev)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* register regulator */
|
/* register regulator */
|
||||||
rdev = regulator_register(&wm8350_reg[pdev->id], &pdev->dev,
|
rdev = regulator_register(&wm8350_reg[pdev->id], &pdev->dev,
|
||||||
|
pdev->dev.platform_data,
|
||||||
dev_get_drvdata(&pdev->dev));
|
dev_get_drvdata(&pdev->dev));
|
||||||
if (IS_ERR(rdev)) {
|
if (IS_ERR(rdev)) {
|
||||||
dev_err(&pdev->dev, "failed to register %s\n",
|
dev_err(&pdev->dev, "failed to register %s\n",
|
||||||
|
|
|
@ -43,6 +43,18 @@ static int wm8400_ldo_disable(struct regulator_dev *dev)
|
||||||
WM8400_LDO1_ENA, 0);
|
WM8400_LDO1_ENA, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int wm8400_ldo_list_voltage(struct regulator_dev *dev,
|
||||||
|
unsigned selector)
|
||||||
|
{
|
||||||
|
if (selector > WM8400_LDO1_VSEL_MASK)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (selector < 15)
|
||||||
|
return 900000 + (selector * 50000);
|
||||||
|
else
|
||||||
|
return 1600000 + ((selector - 14) * 100000);
|
||||||
|
}
|
||||||
|
|
||||||
static int wm8400_ldo_get_voltage(struct regulator_dev *dev)
|
static int wm8400_ldo_get_voltage(struct regulator_dev *dev)
|
||||||
{
|
{
|
||||||
struct wm8400 *wm8400 = rdev_get_drvdata(dev);
|
struct wm8400 *wm8400 = rdev_get_drvdata(dev);
|
||||||
|
@ -51,10 +63,7 @@ static int wm8400_ldo_get_voltage(struct regulator_dev *dev)
|
||||||
val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev));
|
val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev));
|
||||||
val &= WM8400_LDO1_VSEL_MASK;
|
val &= WM8400_LDO1_VSEL_MASK;
|
||||||
|
|
||||||
if (val < 15)
|
return wm8400_ldo_list_voltage(dev, val);
|
||||||
return 900000 + (val * 50000);
|
|
||||||
else
|
|
||||||
return 1600000 + ((val - 14) * 100000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wm8400_ldo_set_voltage(struct regulator_dev *dev,
|
static int wm8400_ldo_set_voltage(struct regulator_dev *dev,
|
||||||
|
@ -92,6 +101,7 @@ static struct regulator_ops wm8400_ldo_ops = {
|
||||||
.is_enabled = wm8400_ldo_is_enabled,
|
.is_enabled = wm8400_ldo_is_enabled,
|
||||||
.enable = wm8400_ldo_enable,
|
.enable = wm8400_ldo_enable,
|
||||||
.disable = wm8400_ldo_disable,
|
.disable = wm8400_ldo_disable,
|
||||||
|
.list_voltage = wm8400_ldo_list_voltage,
|
||||||
.get_voltage = wm8400_ldo_get_voltage,
|
.get_voltage = wm8400_ldo_get_voltage,
|
||||||
.set_voltage = wm8400_ldo_set_voltage,
|
.set_voltage = wm8400_ldo_set_voltage,
|
||||||
};
|
};
|
||||||
|
@ -124,6 +134,15 @@ static int wm8400_dcdc_disable(struct regulator_dev *dev)
|
||||||
WM8400_DC1_ENA, 0);
|
WM8400_DC1_ENA, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int wm8400_dcdc_list_voltage(struct regulator_dev *dev,
|
||||||
|
unsigned selector)
|
||||||
|
{
|
||||||
|
if (selector > WM8400_DC1_VSEL_MASK)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 850000 + (selector * 25000);
|
||||||
|
}
|
||||||
|
|
||||||
static int wm8400_dcdc_get_voltage(struct regulator_dev *dev)
|
static int wm8400_dcdc_get_voltage(struct regulator_dev *dev)
|
||||||
{
|
{
|
||||||
struct wm8400 *wm8400 = rdev_get_drvdata(dev);
|
struct wm8400 *wm8400 = rdev_get_drvdata(dev);
|
||||||
|
@ -237,6 +256,7 @@ static struct regulator_ops wm8400_dcdc_ops = {
|
||||||
.is_enabled = wm8400_dcdc_is_enabled,
|
.is_enabled = wm8400_dcdc_is_enabled,
|
||||||
.enable = wm8400_dcdc_enable,
|
.enable = wm8400_dcdc_enable,
|
||||||
.disable = wm8400_dcdc_disable,
|
.disable = wm8400_dcdc_disable,
|
||||||
|
.list_voltage = wm8400_dcdc_list_voltage,
|
||||||
.get_voltage = wm8400_dcdc_get_voltage,
|
.get_voltage = wm8400_dcdc_get_voltage,
|
||||||
.set_voltage = wm8400_dcdc_set_voltage,
|
.set_voltage = wm8400_dcdc_set_voltage,
|
||||||
.get_mode = wm8400_dcdc_get_mode,
|
.get_mode = wm8400_dcdc_get_mode,
|
||||||
|
@ -249,6 +269,7 @@ static struct regulator_desc regulators[] = {
|
||||||
.name = "LDO1",
|
.name = "LDO1",
|
||||||
.id = WM8400_LDO1,
|
.id = WM8400_LDO1,
|
||||||
.ops = &wm8400_ldo_ops,
|
.ops = &wm8400_ldo_ops,
|
||||||
|
.n_voltages = WM8400_LDO1_VSEL_MASK + 1,
|
||||||
.type = REGULATOR_VOLTAGE,
|
.type = REGULATOR_VOLTAGE,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
|
@ -256,6 +277,7 @@ static struct regulator_desc regulators[] = {
|
||||||
.name = "LDO2",
|
.name = "LDO2",
|
||||||
.id = WM8400_LDO2,
|
.id = WM8400_LDO2,
|
||||||
.ops = &wm8400_ldo_ops,
|
.ops = &wm8400_ldo_ops,
|
||||||
|
.n_voltages = WM8400_LDO2_VSEL_MASK + 1,
|
||||||
.type = REGULATOR_VOLTAGE,
|
.type = REGULATOR_VOLTAGE,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
|
@ -263,6 +285,7 @@ static struct regulator_desc regulators[] = {
|
||||||
.name = "LDO3",
|
.name = "LDO3",
|
||||||
.id = WM8400_LDO3,
|
.id = WM8400_LDO3,
|
||||||
.ops = &wm8400_ldo_ops,
|
.ops = &wm8400_ldo_ops,
|
||||||
|
.n_voltages = WM8400_LDO3_VSEL_MASK + 1,
|
||||||
.type = REGULATOR_VOLTAGE,
|
.type = REGULATOR_VOLTAGE,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
|
@ -270,6 +293,7 @@ static struct regulator_desc regulators[] = {
|
||||||
.name = "LDO4",
|
.name = "LDO4",
|
||||||
.id = WM8400_LDO4,
|
.id = WM8400_LDO4,
|
||||||
.ops = &wm8400_ldo_ops,
|
.ops = &wm8400_ldo_ops,
|
||||||
|
.n_voltages = WM8400_LDO4_VSEL_MASK + 1,
|
||||||
.type = REGULATOR_VOLTAGE,
|
.type = REGULATOR_VOLTAGE,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
|
@ -277,6 +301,7 @@ static struct regulator_desc regulators[] = {
|
||||||
.name = "DCDC1",
|
.name = "DCDC1",
|
||||||
.id = WM8400_DCDC1,
|
.id = WM8400_DCDC1,
|
||||||
.ops = &wm8400_dcdc_ops,
|
.ops = &wm8400_dcdc_ops,
|
||||||
|
.n_voltages = WM8400_DC1_VSEL_MASK + 1,
|
||||||
.type = REGULATOR_VOLTAGE,
|
.type = REGULATOR_VOLTAGE,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
|
@ -284,6 +309,7 @@ static struct regulator_desc regulators[] = {
|
||||||
.name = "DCDC2",
|
.name = "DCDC2",
|
||||||
.id = WM8400_DCDC2,
|
.id = WM8400_DCDC2,
|
||||||
.ops = &wm8400_dcdc_ops,
|
.ops = &wm8400_dcdc_ops,
|
||||||
|
.n_voltages = WM8400_DC2_VSEL_MASK + 1,
|
||||||
.type = REGULATOR_VOLTAGE,
|
.type = REGULATOR_VOLTAGE,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
|
@ -294,7 +320,7 @@ static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
|
||||||
struct regulator_dev *rdev;
|
struct regulator_dev *rdev;
|
||||||
|
|
||||||
rdev = regulator_register(®ulators[pdev->id], &pdev->dev,
|
rdev = regulator_register(®ulators[pdev->id], &pdev->dev,
|
||||||
pdev->dev.driver_data);
|
pdev->dev.platform_data, pdev->dev.driver_data);
|
||||||
|
|
||||||
if (IS_ERR(rdev))
|
if (IS_ERR(rdev))
|
||||||
return PTR_ERR(rdev);
|
return PTR_ERR(rdev);
|
||||||
|
|
|
@ -218,6 +218,53 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Power bus message definitions */
|
||||||
|
|
||||||
|
#define DEV_GRP_NULL 0x0
|
||||||
|
#define DEV_GRP_P1 0x1
|
||||||
|
#define DEV_GRP_P2 0x2
|
||||||
|
#define DEV_GRP_P3 0x4
|
||||||
|
|
||||||
|
#define RES_GRP_RES 0x0
|
||||||
|
#define RES_GRP_PP 0x1
|
||||||
|
#define RES_GRP_RC 0x2
|
||||||
|
#define RES_GRP_PP_RC 0x3
|
||||||
|
#define RES_GRP_PR 0x4
|
||||||
|
#define RES_GRP_PP_PR 0x5
|
||||||
|
#define RES_GRP_RC_PR 0x6
|
||||||
|
#define RES_GRP_ALL 0x7
|
||||||
|
|
||||||
|
#define RES_TYPE2_R0 0x0
|
||||||
|
|
||||||
|
#define RES_TYPE_ALL 0x7
|
||||||
|
|
||||||
|
#define RES_STATE_WRST 0xF
|
||||||
|
#define RES_STATE_ACTIVE 0xE
|
||||||
|
#define RES_STATE_SLEEP 0x8
|
||||||
|
#define RES_STATE_OFF 0x0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Power Bus Message Format ... these can be sent individually by Linux,
|
||||||
|
* but are usually part of downloaded scripts that are run when various
|
||||||
|
* power events are triggered.
|
||||||
|
*
|
||||||
|
* Broadcast Message (16 Bits):
|
||||||
|
* DEV_GRP[15:13] MT[12] RES_GRP[11:9] RES_TYPE2[8:7] RES_TYPE[6:4]
|
||||||
|
* RES_STATE[3:0]
|
||||||
|
*
|
||||||
|
* Singular Message (16 Bits):
|
||||||
|
* DEV_GRP[15:13] MT[12] RES_ID[11:4] RES_STATE[3:0]
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MSG_BROADCAST(devgrp, grp, type, type2, state) \
|
||||||
|
( (devgrp) << 13 | 1 << 12 | (grp) << 9 | (type2) << 7 \
|
||||||
|
| (type) << 4 | (state))
|
||||||
|
|
||||||
|
#define MSG_SINGULAR(devgrp, id, state) \
|
||||||
|
((devgrp) << 13 | 0 << 12 | (id) << 4 | (state))
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
struct twl4030_bci_platform_data {
|
struct twl4030_bci_platform_data {
|
||||||
int *battery_tmp_tbl;
|
int *battery_tmp_tbl;
|
||||||
unsigned int tblsize;
|
unsigned int tblsize;
|
||||||
|
|
|
@ -192,5 +192,10 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host)
|
||||||
wake_up_process(host->sdio_irq_thread);
|
wake_up_process(host->sdio_irq_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct regulator;
|
||||||
|
|
||||||
|
int mmc_regulator_get_ocrmask(struct regulator *supply);
|
||||||
|
int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct regulator_init_data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bq24022_mach_info - platform data for bq24022
|
* bq24022_mach_info - platform data for bq24022
|
||||||
* @gpio_nce: GPIO line connected to the nCE pin, used to enable / disable charging
|
* @gpio_nce: GPIO line connected to the nCE pin, used to enable / disable charging
|
||||||
|
@ -18,4 +20,5 @@
|
||||||
struct bq24022_mach_info {
|
struct bq24022_mach_info {
|
||||||
int gpio_nce;
|
int gpio_nce;
|
||||||
int gpio_iset2;
|
int gpio_iset2;
|
||||||
|
struct regulator_init_data *init_data;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007, 2008 Wolfson Microelectronics PLC.
|
* Copyright (C) 2007, 2008 Wolfson Microelectronics PLC.
|
||||||
*
|
*
|
||||||
* Author: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
* Author: Liam Girdwood <lrg@slimlogic.co.uk>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
@ -88,6 +88,7 @@
|
||||||
* FAIL Regulator output has failed.
|
* FAIL Regulator output has failed.
|
||||||
* OVER_TEMP Regulator over temp.
|
* OVER_TEMP Regulator over temp.
|
||||||
* FORCE_DISABLE Regulator shut down by software.
|
* FORCE_DISABLE Regulator shut down by software.
|
||||||
|
* VOLTAGE_CHANGE Regulator voltage changed.
|
||||||
*
|
*
|
||||||
* NOTE: These events can be OR'ed together when passed into handler.
|
* NOTE: These events can be OR'ed together when passed into handler.
|
||||||
*/
|
*/
|
||||||
|
@ -98,6 +99,7 @@
|
||||||
#define REGULATOR_EVENT_FAIL 0x08
|
#define REGULATOR_EVENT_FAIL 0x08
|
||||||
#define REGULATOR_EVENT_OVER_TEMP 0x10
|
#define REGULATOR_EVENT_OVER_TEMP 0x10
|
||||||
#define REGULATOR_EVENT_FORCE_DISABLE 0x20
|
#define REGULATOR_EVENT_FORCE_DISABLE 0x20
|
||||||
|
#define REGULATOR_EVENT_VOLTAGE_CHANGE 0x40
|
||||||
|
|
||||||
struct regulator;
|
struct regulator;
|
||||||
|
|
||||||
|
@ -140,6 +142,8 @@ int regulator_bulk_disable(int num_consumers,
|
||||||
void regulator_bulk_free(int num_consumers,
|
void regulator_bulk_free(int num_consumers,
|
||||||
struct regulator_bulk_data *consumers);
|
struct regulator_bulk_data *consumers);
|
||||||
|
|
||||||
|
int regulator_count_voltages(struct regulator *regulator);
|
||||||
|
int regulator_list_voltage(struct regulator *regulator, unsigned selector);
|
||||||
int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV);
|
int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV);
|
||||||
int regulator_get_voltage(struct regulator *regulator);
|
int regulator_get_voltage(struct regulator *regulator);
|
||||||
int regulator_set_current_limit(struct regulator *regulator,
|
int regulator_set_current_limit(struct regulator *regulator,
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007, 2008 Wolfson Microelectronics PLC.
|
* Copyright (C) 2007, 2008 Wolfson Microelectronics PLC.
|
||||||
*
|
*
|
||||||
* Author: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
* Author: Liam Girdwood <lrg@slimlogic.co.uk>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
@ -21,25 +21,38 @@
|
||||||
struct regulator_dev;
|
struct regulator_dev;
|
||||||
struct regulator_init_data;
|
struct regulator_init_data;
|
||||||
|
|
||||||
|
enum regulator_status {
|
||||||
|
REGULATOR_STATUS_OFF,
|
||||||
|
REGULATOR_STATUS_ON,
|
||||||
|
REGULATOR_STATUS_ERROR,
|
||||||
|
/* fast/normal/idle/standby are flavors of "on" */
|
||||||
|
REGULATOR_STATUS_FAST,
|
||||||
|
REGULATOR_STATUS_NORMAL,
|
||||||
|
REGULATOR_STATUS_IDLE,
|
||||||
|
REGULATOR_STATUS_STANDBY,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct regulator_ops - regulator operations.
|
* struct regulator_ops - regulator operations.
|
||||||
*
|
*
|
||||||
* This struct describes regulator operations which can be implemented by
|
* @enable: Configure the regulator as enabled.
|
||||||
* regulator chip drivers.
|
* @disable: Configure the regulator as disabled.
|
||||||
*
|
|
||||||
* @enable: Enable the regulator.
|
|
||||||
* @disable: Disable the regulator.
|
|
||||||
* @is_enabled: Return 1 if the regulator is enabled, 0 otherwise.
|
* @is_enabled: Return 1 if the regulator is enabled, 0 otherwise.
|
||||||
*
|
*
|
||||||
* @set_voltage: Set the voltage for the regulator within the range specified.
|
* @set_voltage: Set the voltage for the regulator within the range specified.
|
||||||
* The driver should select the voltage closest to min_uV.
|
* The driver should select the voltage closest to min_uV.
|
||||||
* @get_voltage: Return the currently configured voltage for the regulator.
|
* @get_voltage: Return the currently configured voltage for the regulator.
|
||||||
|
* @list_voltage: Return one of the supported voltages, in microvolts; zero
|
||||||
|
* if the selector indicates a voltage that is unusable on this system;
|
||||||
|
* or negative errno. Selectors range from zero to one less than
|
||||||
|
* regulator_desc.n_voltages. Voltages may be reported in any order.
|
||||||
*
|
*
|
||||||
* @set_current_limit: Configure a limit for a current-limited regulator.
|
* @set_current_limit: Configure a limit for a current-limited regulator.
|
||||||
* @get_current_limit: Get the limit for a current-limited regulator.
|
* @get_current_limit: Get the configured limit for a current-limited regulator.
|
||||||
*
|
*
|
||||||
* @set_mode: Set the operating mode for the regulator.
|
* @get_mode: Get the configured operating mode for the regulator.
|
||||||
* @get_mode: Get the current operating mode for the regulator.
|
* @get_status: Return actual (not as-configured) status of regulator, as a
|
||||||
|
* REGULATOR_STATUS value (or negative errno)
|
||||||
* @get_optimum_mode: Get the most efficient operating mode for the regulator
|
* @get_optimum_mode: Get the most efficient operating mode for the regulator
|
||||||
* when running with the specified parameters.
|
* when running with the specified parameters.
|
||||||
*
|
*
|
||||||
|
@ -51,9 +64,15 @@ struct regulator_init_data;
|
||||||
* suspended.
|
* suspended.
|
||||||
* @set_suspend_mode: Set the operating mode for the regulator when the
|
* @set_suspend_mode: Set the operating mode for the regulator when the
|
||||||
* system is suspended.
|
* system is suspended.
|
||||||
|
*
|
||||||
|
* This struct describes regulator operations which can be implemented by
|
||||||
|
* regulator chip drivers.
|
||||||
*/
|
*/
|
||||||
struct regulator_ops {
|
struct regulator_ops {
|
||||||
|
|
||||||
|
/* enumerate supported voltages */
|
||||||
|
int (*list_voltage) (struct regulator_dev *, unsigned selector);
|
||||||
|
|
||||||
/* get/set regulator voltage */
|
/* get/set regulator voltage */
|
||||||
int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV);
|
int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV);
|
||||||
int (*get_voltage) (struct regulator_dev *);
|
int (*get_voltage) (struct regulator_dev *);
|
||||||
|
@ -72,6 +91,13 @@ struct regulator_ops {
|
||||||
int (*set_mode) (struct regulator_dev *, unsigned int mode);
|
int (*set_mode) (struct regulator_dev *, unsigned int mode);
|
||||||
unsigned int (*get_mode) (struct regulator_dev *);
|
unsigned int (*get_mode) (struct regulator_dev *);
|
||||||
|
|
||||||
|
/* report regulator status ... most other accessors report
|
||||||
|
* control inputs, this reports results of combining inputs
|
||||||
|
* from Linux (and other sources) with the actual load.
|
||||||
|
* returns REGULATOR_STATUS_* or negative errno.
|
||||||
|
*/
|
||||||
|
int (*get_status)(struct regulator_dev *);
|
||||||
|
|
||||||
/* get most efficient regulator operating mode for load */
|
/* get most efficient regulator operating mode for load */
|
||||||
unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV,
|
unsigned int (*get_optimum_mode) (struct regulator_dev *, int input_uV,
|
||||||
int output_uV, int load_uA);
|
int output_uV, int load_uA);
|
||||||
|
@ -106,6 +132,7 @@ enum regulator_type {
|
||||||
*
|
*
|
||||||
* @name: Identifying name for the regulator.
|
* @name: Identifying name for the regulator.
|
||||||
* @id: Numerical identifier for the regulator.
|
* @id: Numerical identifier for the regulator.
|
||||||
|
* @n_voltages: Number of selectors available for ops.list_voltage().
|
||||||
* @ops: Regulator operations table.
|
* @ops: Regulator operations table.
|
||||||
* @irq: Interrupt number for the regulator.
|
* @irq: Interrupt number for the regulator.
|
||||||
* @type: Indicates if the regulator is a voltage or current regulator.
|
* @type: Indicates if the regulator is a voltage or current regulator.
|
||||||
|
@ -114,14 +141,48 @@ enum regulator_type {
|
||||||
struct regulator_desc {
|
struct regulator_desc {
|
||||||
const char *name;
|
const char *name;
|
||||||
int id;
|
int id;
|
||||||
|
unsigned n_voltages;
|
||||||
struct regulator_ops *ops;
|
struct regulator_ops *ops;
|
||||||
int irq;
|
int irq;
|
||||||
enum regulator_type type;
|
enum regulator_type type;
|
||||||
struct module *owner;
|
struct module *owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* struct regulator_dev
|
||||||
|
*
|
||||||
|
* Voltage / Current regulator class device. One for each
|
||||||
|
* regulator.
|
||||||
|
*
|
||||||
|
* This should *not* be used directly by anything except the regulator
|
||||||
|
* core and notification injection (which should take the mutex and do
|
||||||
|
* no other direct access).
|
||||||
|
*/
|
||||||
|
struct regulator_dev {
|
||||||
|
struct regulator_desc *desc;
|
||||||
|
int use_count;
|
||||||
|
|
||||||
|
/* lists we belong to */
|
||||||
|
struct list_head list; /* list of all regulators */
|
||||||
|
struct list_head slist; /* list of supplied regulators */
|
||||||
|
|
||||||
|
/* lists we own */
|
||||||
|
struct list_head consumer_list; /* consumers we supply */
|
||||||
|
struct list_head supply_list; /* regulators we supply */
|
||||||
|
|
||||||
|
struct blocking_notifier_head notifier;
|
||||||
|
struct mutex mutex; /* consumer lock */
|
||||||
|
struct module *owner;
|
||||||
|
struct device dev;
|
||||||
|
struct regulation_constraints *constraints;
|
||||||
|
struct regulator_dev *supply; /* for tree */
|
||||||
|
|
||||||
|
void *reg_data; /* regulator_dev data */
|
||||||
|
};
|
||||||
|
|
||||||
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
|
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
|
||||||
struct device *dev, void *driver_data);
|
struct device *dev, struct regulator_init_data *init_data,
|
||||||
|
void *driver_data);
|
||||||
void regulator_unregister(struct regulator_dev *rdev);
|
void regulator_unregister(struct regulator_dev *rdev);
|
||||||
|
|
||||||
int regulator_notifier_call_chain(struct regulator_dev *rdev,
|
int regulator_notifier_call_chain(struct regulator_dev *rdev,
|
||||||
|
|
|
@ -14,9 +14,12 @@
|
||||||
#ifndef __REGULATOR_FIXED_H
|
#ifndef __REGULATOR_FIXED_H
|
||||||
#define __REGULATOR_FIXED_H
|
#define __REGULATOR_FIXED_H
|
||||||
|
|
||||||
|
struct regulator_init_data;
|
||||||
|
|
||||||
struct fixed_voltage_config {
|
struct fixed_voltage_config {
|
||||||
const char *supply_name;
|
const char *supply_name;
|
||||||
int microvolts;
|
int microvolts;
|
||||||
|
struct regulator_init_data *init_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007, 2008 Wolfson Microelectronics PLC.
|
* Copyright (C) 2007, 2008 Wolfson Microelectronics PLC.
|
||||||
*
|
*
|
||||||
* Author: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
* Author: Liam Girdwood <lrg@slimlogic.co.uk>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
@ -73,7 +73,9 @@ struct regulator_state {
|
||||||
*
|
*
|
||||||
* @always_on: Set if the regulator should never be disabled.
|
* @always_on: Set if the regulator should never be disabled.
|
||||||
* @boot_on: Set if the regulator is enabled when the system is initially
|
* @boot_on: Set if the regulator is enabled when the system is initially
|
||||||
* started.
|
* started. If the regulator is not enabled by the hardware or
|
||||||
|
* bootloader then it will be enabled when the constraints are
|
||||||
|
* applied.
|
||||||
* @apply_uV: Apply the voltage constraint when initialising.
|
* @apply_uV: Apply the voltage constraint when initialising.
|
||||||
*
|
*
|
||||||
* @input_uV: Input voltage for regulator when supplied by another regulator.
|
* @input_uV: Input voltage for regulator when supplied by another regulator.
|
||||||
|
@ -83,6 +85,7 @@ struct regulator_state {
|
||||||
* @state_standby: State for regulator when system is suspended in standby
|
* @state_standby: State for regulator when system is suspended in standby
|
||||||
* mode.
|
* mode.
|
||||||
* @initial_state: Suspend state to set by default.
|
* @initial_state: Suspend state to set by default.
|
||||||
|
* @initial_mode: Mode to set at startup.
|
||||||
*/
|
*/
|
||||||
struct regulation_constraints {
|
struct regulation_constraints {
|
||||||
|
|
||||||
|
@ -111,6 +114,9 @@ struct regulation_constraints {
|
||||||
struct regulator_state state_standby;
|
struct regulator_state state_standby;
|
||||||
suspend_state_t initial_state; /* suspend state to set at init */
|
suspend_state_t initial_state; /* suspend state to set at init */
|
||||||
|
|
||||||
|
/* mode to set on startup */
|
||||||
|
unsigned int initial_mode;
|
||||||
|
|
||||||
/* constriant flags */
|
/* constriant flags */
|
||||||
unsigned always_on:1; /* regulator never off when system is on */
|
unsigned always_on:1; /* regulator never off when system is on */
|
||||||
unsigned boot_on:1; /* bootloader/firmware enabled regulator */
|
unsigned boot_on:1; /* bootloader/firmware enabled regulator */
|
||||||
|
@ -160,4 +166,6 @@ struct regulator_init_data {
|
||||||
|
|
||||||
int regulator_suspend_prepare(suspend_state_t state);
|
int regulator_suspend_prepare(suspend_state_t state);
|
||||||
|
|
||||||
|
void regulator_has_full_constraints(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue