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: (27 commits) Regulators: wm8400 - cleanup platform driver data handling Regulators: wm8994 - clean up driver data after removal Regulators: wm831x-xxx - clean up driver data after removal Regulators: pcap-regulator - clean up driver data after removal Regulators: max8660 - annotate probe and remove methods Regulators: max1586 - annotate probe and remove methods Regulators: lp3971 - fail if platform data was not supplied Regulators: tps6507x-regulator - mark probe method as __devinit Regulators: tps65023-regulator - mark probe method as __devinit Regulators: twl-regulator - mark probe function as __devinit Regulators: fixed - annotate probe and remove methods Regulators: ab3100 - fix probe and remove annotations Regulators: virtual - use sysfs attribute groups twl6030: regulator: Configure STATE register instead of REMAP regulator: Provide optional dummy regulator for consumers regulator: Assume regulators are enabled if they don't report anything regulator: Convert fixed voltage regulator to use enable_time() regulator: Add WM8994 regulator support regulator: enable max8649 regulator driver regulator: trivial: fix typos in user-visible Kconfig text ...
This commit is contained in:
commit
c8bf9fec47
28 changed files with 1622 additions and 184 deletions
|
@ -27,6 +27,17 @@ config REGULATOR_DEBUG
|
|||
help
|
||||
Say yes here to enable debugging support.
|
||||
|
||||
config REGULATOR_DUMMY
|
||||
bool "Provide a dummy regulator if regulator lookups fail"
|
||||
help
|
||||
If this option is enabled then when a regulator lookup fails
|
||||
and the board has not specified that it has provided full
|
||||
constraints then the regulator core will provide an always
|
||||
enabled dummy regulator will be provided, allowing consumer
|
||||
drivers to continue.
|
||||
|
||||
A warning will be generated when this substitution is done.
|
||||
|
||||
config REGULATOR_FIXED_VOLTAGE
|
||||
tristate "Fixed voltage regulator support"
|
||||
help
|
||||
|
@ -69,6 +80,13 @@ config REGULATOR_MAX1586
|
|||
regulator via I2C bus. The provided regulator is suitable
|
||||
for PXA27x chips to control VCC_CORE and VCC_USIM voltages.
|
||||
|
||||
config REGULATOR_MAX8649
|
||||
tristate "Maxim 8649 voltage regulator"
|
||||
depends on I2C
|
||||
help
|
||||
This driver controls a Maxim 8649 voltage output regulator via
|
||||
I2C bus.
|
||||
|
||||
config REGULATOR_MAX8660
|
||||
tristate "Maxim 8660/8661 voltage regulator"
|
||||
depends on I2C
|
||||
|
@ -91,19 +109,26 @@ config REGULATOR_WM831X
|
|||
of PMIC devices.
|
||||
|
||||
config REGULATOR_WM8350
|
||||
tristate "Wolfson Microelectroncis WM8350 AudioPlus PMIC"
|
||||
tristate "Wolfson Microelectronics WM8350 AudioPlus PMIC"
|
||||
depends on MFD_WM8350
|
||||
help
|
||||
This driver provides support for the voltage and current regulators
|
||||
of the WM8350 AudioPlus PMIC.
|
||||
|
||||
config REGULATOR_WM8400
|
||||
tristate "Wolfson Microelectroncis WM8400 AudioPlus PMIC"
|
||||
tristate "Wolfson Microelectronics WM8400 AudioPlus PMIC"
|
||||
depends on MFD_WM8400
|
||||
help
|
||||
This driver provides support for the voltage regulators of the
|
||||
WM8400 AudioPlus PMIC.
|
||||
|
||||
config REGULATOR_WM8994
|
||||
tristate "Wolfson Microelectronics WM8994 CODEC"
|
||||
depends on MFD_WM8994
|
||||
help
|
||||
This driver provides support for the voltage regulators on the
|
||||
WM8994 CODEC.
|
||||
|
||||
config REGULATOR_DA903X
|
||||
tristate "Support regulators on Dialog Semiconductor DA9030/DA9034 PMIC"
|
||||
depends on PMIC_DA903X
|
||||
|
|
|
@ -9,15 +9,18 @@ obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
|
|||
obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
|
||||
|
||||
obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o
|
||||
obj-$(CONFIG_REGULATOR_DUMMY) += dummy.o
|
||||
obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
|
||||
obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
|
||||
obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o
|
||||
obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
|
||||
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
|
||||
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
|
||||
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
|
||||
obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
|
||||
obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
|
||||
|
|
|
@ -561,7 +561,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
|
|||
* for all the different regulators.
|
||||
*/
|
||||
|
||||
static int __init ab3100_regulators_probe(struct platform_device *pdev)
|
||||
static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
|
||||
struct ab3100 *ab3100 = platform_get_drvdata(pdev);
|
||||
|
@ -641,7 +641,7 @@ static int __init ab3100_regulators_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __exit ab3100_regulators_remove(struct platform_device *pdev)
|
||||
static int __devexit ab3100_regulators_remove(struct platform_device *pdev)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -659,7 +659,7 @@ static struct platform_driver ab3100_regulators_driver = {
|
|||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ab3100_regulators_probe,
|
||||
.remove = __exit_p(ab3100_regulators_remove),
|
||||
.remove = __devexit_p(ab3100_regulators_remove),
|
||||
};
|
||||
|
||||
static __init int ab3100_regulators_init(void)
|
||||
|
|
|
@ -19,10 +19,13 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
#include "dummy.h"
|
||||
|
||||
#define REGULATOR_VERSION "0.5"
|
||||
|
||||
static DEFINE_MUTEX(regulator_list_mutex);
|
||||
|
@ -1084,6 +1087,13 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int _regulator_get_enable_time(struct regulator_dev *rdev)
|
||||
{
|
||||
if (!rdev->desc->ops->enable_time)
|
||||
return 0;
|
||||
return rdev->desc->ops->enable_time(rdev);
|
||||
}
|
||||
|
||||
/* Internal regulator request function */
|
||||
static struct regulator *_regulator_get(struct device *dev, const char *id,
|
||||
int exclusive)
|
||||
|
@ -1115,6 +1125,22 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
|
|||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_REGULATOR_DUMMY
|
||||
if (!devname)
|
||||
devname = "deviceless";
|
||||
|
||||
/* If the board didn't flag that it was fully constrained then
|
||||
* substitute in a dummy regulator so consumers can continue.
|
||||
*/
|
||||
if (!has_full_constraints) {
|
||||
pr_warning("%s supply %s not found, using dummy regulator\n",
|
||||
devname, id);
|
||||
rdev = dummy_regulator_rdev;
|
||||
goto found;
|
||||
}
|
||||
#endif
|
||||
|
||||
mutex_unlock(®ulator_list_mutex);
|
||||
return regulator;
|
||||
|
||||
|
@ -1251,7 +1277,7 @@ static int _regulator_can_change_status(struct regulator_dev *rdev)
|
|||
/* locks held by regulator_enable() */
|
||||
static int _regulator_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
int ret;
|
||||
int ret, delay;
|
||||
|
||||
/* do we need to enable the supply regulator first */
|
||||
if (rdev->supply) {
|
||||
|
@ -1275,13 +1301,34 @@ static int _regulator_enable(struct regulator_dev *rdev)
|
|||
if (!_regulator_can_change_status(rdev))
|
||||
return -EPERM;
|
||||
|
||||
if (rdev->desc->ops->enable) {
|
||||
ret = rdev->desc->ops->enable(rdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
if (!rdev->desc->ops->enable)
|
||||
return -EINVAL;
|
||||
|
||||
/* Query before enabling in case configuration
|
||||
* dependant. */
|
||||
ret = _regulator_get_enable_time(rdev);
|
||||
if (ret >= 0) {
|
||||
delay = ret;
|
||||
} else {
|
||||
printk(KERN_WARNING
|
||||
"%s: enable_time() failed for %s: %d\n",
|
||||
__func__, rdev_get_name(rdev),
|
||||
ret);
|
||||
delay = 0;
|
||||
}
|
||||
|
||||
/* Allow the regulator to ramp; it would be useful
|
||||
* to extend this for bulk operations so that the
|
||||
* regulators can ramp together. */
|
||||
ret = rdev->desc->ops->enable(rdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (delay >= 1000)
|
||||
mdelay(delay / 1000);
|
||||
else if (delay)
|
||||
udelay(delay);
|
||||
|
||||
} else if (ret < 0) {
|
||||
printk(KERN_ERR "%s: is_enabled() failed for %s: %d\n",
|
||||
__func__, rdev_get_name(rdev), ret);
|
||||
|
@ -1341,6 +1388,9 @@ static int _regulator_disable(struct regulator_dev *rdev)
|
|||
__func__, rdev_get_name(rdev));
|
||||
return ret;
|
||||
}
|
||||
|
||||
_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* decrease our supplies ref count and disable if required */
|
||||
|
@ -1399,8 +1449,8 @@ static int _regulator_force_disable(struct regulator_dev *rdev)
|
|||
return ret;
|
||||
}
|
||||
/* notify other consumers that power has been forced off */
|
||||
_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE,
|
||||
NULL);
|
||||
_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
|
||||
REGULATOR_EVENT_DISABLE, NULL);
|
||||
}
|
||||
|
||||
/* decrease our supplies ref count and disable if required */
|
||||
|
@ -1434,9 +1484,9 @@ EXPORT_SYMBOL_GPL(regulator_force_disable);
|
|||
|
||||
static int _regulator_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
/* sanity check */
|
||||
/* If we don't know then assume that the regulator is always on */
|
||||
if (!rdev->desc->ops->is_enabled)
|
||||
return -EINVAL;
|
||||
return 1;
|
||||
|
||||
return rdev->desc->ops->is_enabled(rdev);
|
||||
}
|
||||
|
@ -2451,8 +2501,15 @@ EXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
|
|||
|
||||
static int __init regulator_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printk(KERN_INFO "regulator: core version %s\n", REGULATOR_VERSION);
|
||||
return class_register(®ulator_class);
|
||||
|
||||
ret = class_register(®ulator_class);
|
||||
|
||||
regulator_dummy_init();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* init early to allow our consumers to complete system booting */
|
||||
|
|
66
drivers/regulator/dummy.c
Normal file
66
drivers/regulator/dummy.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* dummy.c
|
||||
*
|
||||
* Copyright 2010 Wolfson Microelectronics PLC.
|
||||
*
|
||||
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This is useful for systems with mixed controllable and
|
||||
* non-controllable regulators, as well as for allowing testing on
|
||||
* systems with no controllable regulators.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
#include "dummy.h"
|
||||
|
||||
struct regulator_dev *dummy_regulator_rdev;
|
||||
|
||||
static struct regulator_init_data dummy_initdata;
|
||||
|
||||
static struct regulator_ops dummy_ops;
|
||||
|
||||
static struct regulator_desc dummy_desc = {
|
||||
.name = "dummy",
|
||||
.id = -1,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.ops = &dummy_ops,
|
||||
};
|
||||
|
||||
static struct platform_device *dummy_pdev;
|
||||
|
||||
void __init regulator_dummy_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dummy_pdev = platform_device_alloc("reg-dummy", -1);
|
||||
if (!dummy_pdev) {
|
||||
pr_err("Failed to allocate dummy regulator device\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = platform_device_add(dummy_pdev);
|
||||
if (ret != 0) {
|
||||
pr_err("Failed to register dummy regulator device: %d\n", ret);
|
||||
platform_device_put(dummy_pdev);
|
||||
return;
|
||||
}
|
||||
|
||||
dummy_regulator_rdev = regulator_register(&dummy_desc, NULL,
|
||||
&dummy_initdata, NULL);
|
||||
if (IS_ERR(dummy_regulator_rdev)) {
|
||||
ret = PTR_ERR(dummy_regulator_rdev);
|
||||
pr_err("Failed to register regulator: %d\n", ret);
|
||||
platform_device_unregister(dummy_pdev);
|
||||
return;
|
||||
}
|
||||
}
|
31
drivers/regulator/dummy.h
Normal file
31
drivers/regulator/dummy.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* dummy.h
|
||||
*
|
||||
* Copyright 2010 Wolfson Microelectronics PLC.
|
||||
*
|
||||
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This is useful for systems with mixed controllable and
|
||||
* non-controllable regulators, as well as for allowing testing on
|
||||
* systems with no controllable regulators.
|
||||
*/
|
||||
|
||||
#ifndef _DUMMY_H
|
||||
#define _DUMMY_H
|
||||
|
||||
struct regulator_dev;
|
||||
|
||||
extern struct regulator_dev *dummy_regulator_rdev;
|
||||
|
||||
#ifdef CONFIG_REGULATOR_DUMMY
|
||||
void __init regulator_dummy_init(void);
|
||||
#else
|
||||
static inline void regulator_dummy_init(void) { }
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -24,14 +24,16 @@
|
|||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/fixed.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
struct fixed_voltage_data {
|
||||
struct regulator_desc desc;
|
||||
struct regulator_dev *dev;
|
||||
int microvolts;
|
||||
int gpio;
|
||||
unsigned enable_high:1;
|
||||
unsigned is_enabled:1;
|
||||
unsigned startup_delay;
|
||||
bool enable_high;
|
||||
bool is_enabled;
|
||||
};
|
||||
|
||||
static int fixed_voltage_is_enabled(struct regulator_dev *dev)
|
||||
|
@ -47,7 +49,7 @@ static int fixed_voltage_enable(struct regulator_dev *dev)
|
|||
|
||||
if (gpio_is_valid(data->gpio)) {
|
||||
gpio_set_value_cansleep(data->gpio, data->enable_high);
|
||||
data->is_enabled = 1;
|
||||
data->is_enabled = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -59,12 +61,19 @@ static int fixed_voltage_disable(struct regulator_dev *dev)
|
|||
|
||||
if (gpio_is_valid(data->gpio)) {
|
||||
gpio_set_value_cansleep(data->gpio, !data->enable_high);
|
||||
data->is_enabled = 0;
|
||||
data->is_enabled = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fixed_voltage_enable_time(struct regulator_dev *dev)
|
||||
{
|
||||
struct fixed_voltage_data *data = rdev_get_drvdata(dev);
|
||||
|
||||
return data->startup_delay;
|
||||
}
|
||||
|
||||
static int fixed_voltage_get_voltage(struct regulator_dev *dev)
|
||||
{
|
||||
struct fixed_voltage_data *data = rdev_get_drvdata(dev);
|
||||
|
@ -87,11 +96,12 @@ static struct regulator_ops fixed_voltage_ops = {
|
|||
.is_enabled = fixed_voltage_is_enabled,
|
||||
.enable = fixed_voltage_enable,
|
||||
.disable = fixed_voltage_disable,
|
||||
.enable_time = fixed_voltage_enable_time,
|
||||
.get_voltage = fixed_voltage_get_voltage,
|
||||
.list_voltage = fixed_voltage_list_voltage,
|
||||
};
|
||||
|
||||
static int regulator_fixed_voltage_probe(struct platform_device *pdev)
|
||||
static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct fixed_voltage_config *config = pdev->dev.platform_data;
|
||||
struct fixed_voltage_data *drvdata;
|
||||
|
@ -117,6 +127,7 @@ static int regulator_fixed_voltage_probe(struct platform_device *pdev)
|
|||
|
||||
drvdata->microvolts = config->microvolts;
|
||||
drvdata->gpio = config->gpio;
|
||||
drvdata->startup_delay = config->startup_delay;
|
||||
|
||||
if (gpio_is_valid(config->gpio)) {
|
||||
drvdata->enable_high = config->enable_high;
|
||||
|
@ -163,7 +174,7 @@ static int regulator_fixed_voltage_probe(struct platform_device *pdev)
|
|||
/* Regulator without GPIO control is considered
|
||||
* always enabled
|
||||
*/
|
||||
drvdata->is_enabled = 1;
|
||||
drvdata->is_enabled = true;
|
||||
}
|
||||
|
||||
drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev,
|
||||
|
@ -191,7 +202,7 @@ static int regulator_fixed_voltage_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int regulator_fixed_voltage_remove(struct platform_device *pdev)
|
||||
static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev);
|
||||
|
||||
|
@ -205,10 +216,11 @@ static int regulator_fixed_voltage_remove(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
static struct platform_driver regulator_fixed_voltage_driver = {
|
||||
.probe = regulator_fixed_voltage_probe,
|
||||
.remove = regulator_fixed_voltage_remove,
|
||||
.probe = reg_fixed_voltage_probe,
|
||||
.remove = __devexit_p(reg_fixed_voltage_remove),
|
||||
.driver = {
|
||||
.name = "reg-fixed-voltage",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val);
|
|||
#define LP3971_BUCK2_BASE 0x29
|
||||
#define LP3971_BUCK3_BASE 0x32
|
||||
|
||||
const static int buck_base_addr[] = {
|
||||
static const int buck_base_addr[] = {
|
||||
LP3971_BUCK1_BASE,
|
||||
LP3971_BUCK2_BASE,
|
||||
LP3971_BUCK3_BASE,
|
||||
|
@ -63,7 +63,7 @@ const static int buck_base_addr[] = {
|
|||
#define LP3971_BUCK_TARGET_VOL1_REG(x) (buck_base_addr[x])
|
||||
#define LP3971_BUCK_TARGET_VOL2_REG(x) (buck_base_addr[x]+1)
|
||||
|
||||
const static int buck_voltage_map[] = {
|
||||
static const int buck_voltage_map[] = {
|
||||
0, 800, 850, 900, 950, 1000, 1050, 1100,
|
||||
1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500,
|
||||
1550, 1600, 1650, 1700, 1800, 1900, 2500, 2800,
|
||||
|
@ -96,17 +96,17 @@ const static int buck_voltage_map[] = {
|
|||
#define LDO_VOL_CONTR_SHIFT(x) ((x & 1) << 2)
|
||||
#define LDO_VOL_CONTR_MASK 0x0f
|
||||
|
||||
const static int ldo45_voltage_map[] = {
|
||||
static const int ldo45_voltage_map[] = {
|
||||
1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350,
|
||||
1400, 1500, 1800, 1900, 2500, 2800, 3000, 3300,
|
||||
};
|
||||
|
||||
const static int ldo123_voltage_map[] = {
|
||||
static const int ldo123_voltage_map[] = {
|
||||
1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500,
|
||||
2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300,
|
||||
};
|
||||
|
||||
const static int *ldo_voltage_map[] = {
|
||||
static const int *ldo_voltage_map[] = {
|
||||
ldo123_voltage_map, /* LDO1 */
|
||||
ldo123_voltage_map, /* LDO2 */
|
||||
ldo123_voltage_map, /* LDO3 */
|
||||
|
@ -431,20 +431,20 @@ static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int setup_regulators(struct lp3971 *lp3971,
|
||||
struct lp3971_platform_data *pdata)
|
||||
static int __devinit setup_regulators(struct lp3971 *lp3971,
|
||||
struct lp3971_platform_data *pdata)
|
||||
{
|
||||
int i, err;
|
||||
int num_regulators = pdata->num_regulators;
|
||||
lp3971->num_regulators = num_regulators;
|
||||
lp3971->rdev = kzalloc(sizeof(struct regulator_dev *) * num_regulators,
|
||||
GFP_KERNEL);
|
||||
|
||||
lp3971->num_regulators = pdata->num_regulators;
|
||||
lp3971->rdev = kcalloc(pdata->num_regulators,
|
||||
sizeof(struct regulator_dev *), GFP_KERNEL);
|
||||
|
||||
/* Instantiate the regulators */
|
||||
for (i = 0; i < num_regulators; i++) {
|
||||
int id = pdata->regulators[i].id;
|
||||
lp3971->rdev[i] = regulator_register(®ulators[id],
|
||||
lp3971->dev, pdata->regulators[i].initdata, lp3971);
|
||||
for (i = 0; i < pdata->num_regulators; i++) {
|
||||
struct lp3971_regulator_subdev *reg = &pdata->regulators[i];
|
||||
lp3971->rdev[i] = regulator_register(®ulators[reg->id],
|
||||
lp3971->dev, reg->initdata, lp3971);
|
||||
|
||||
if (IS_ERR(lp3971->rdev[i])) {
|
||||
err = PTR_ERR(lp3971->rdev[i]);
|
||||
|
@ -455,10 +455,10 @@ static int setup_regulators(struct lp3971 *lp3971,
|
|||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
for (i = 0; i < num_regulators; i++)
|
||||
if (lp3971->rdev[i])
|
||||
regulator_unregister(lp3971->rdev[i]);
|
||||
while (--i >= 0)
|
||||
regulator_unregister(lp3971->rdev[i]);
|
||||
kfree(lp3971->rdev);
|
||||
lp3971->rdev = NULL;
|
||||
return err;
|
||||
|
@ -472,15 +472,17 @@ static int __devinit lp3971_i2c_probe(struct i2c_client *i2c,
|
|||
int ret;
|
||||
u16 val;
|
||||
|
||||
lp3971 = kzalloc(sizeof(struct lp3971), GFP_KERNEL);
|
||||
if (lp3971 == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
if (!pdata) {
|
||||
dev_dbg(&i2c->dev, "No platform init data supplied\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
lp3971 = kzalloc(sizeof(struct lp3971), GFP_KERNEL);
|
||||
if (lp3971 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
lp3971->i2c = i2c;
|
||||
lp3971->dev = &i2c->dev;
|
||||
i2c_set_clientdata(i2c, lp3971);
|
||||
|
||||
mutex_init(&lp3971->io_lock);
|
||||
|
||||
|
@ -493,19 +495,15 @@ static int __devinit lp3971_i2c_probe(struct i2c_client *i2c,
|
|||
goto err_detect;
|
||||
}
|
||||
|
||||
if (pdata) {
|
||||
ret = setup_regulators(lp3971, pdata);
|
||||
if (ret < 0)
|
||||
goto err_detect;
|
||||
} else
|
||||
dev_warn(lp3971->dev, "No platform init data supplied\n");
|
||||
ret = setup_regulators(lp3971, pdata);
|
||||
if (ret < 0)
|
||||
goto err_detect;
|
||||
|
||||
i2c_set_clientdata(i2c, lp3971);
|
||||
return 0;
|
||||
|
||||
err_detect:
|
||||
i2c_set_clientdata(i2c, NULL);
|
||||
kfree(lp3971);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -513,11 +511,13 @@ static int __devexit lp3971_i2c_remove(struct i2c_client *i2c)
|
|||
{
|
||||
struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
|
||||
int i;
|
||||
for (i = 0; i < lp3971->num_regulators; i++)
|
||||
if (lp3971->rdev[i])
|
||||
regulator_unregister(lp3971->rdev[i]);
|
||||
kfree(lp3971->rdev);
|
||||
|
||||
i2c_set_clientdata(i2c, NULL);
|
||||
|
||||
for (i = 0; i < lp3971->num_regulators; i++)
|
||||
regulator_unregister(lp3971->rdev[i]);
|
||||
|
||||
kfree(lp3971->rdev);
|
||||
kfree(lp3971);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -179,8 +179,8 @@ static struct regulator_desc max1586_reg[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static int max1586_pmic_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *i2c_id)
|
||||
static int __devinit max1586_pmic_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *i2c_id)
|
||||
{
|
||||
struct regulator_dev **rdev;
|
||||
struct max1586_platform_data *pdata = client->dev.platform_data;
|
||||
|
@ -235,7 +235,7 @@ static int max1586_pmic_probe(struct i2c_client *client,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int max1586_pmic_remove(struct i2c_client *client)
|
||||
static int __devexit max1586_pmic_remove(struct i2c_client *client)
|
||||
{
|
||||
struct regulator_dev **rdev = i2c_get_clientdata(client);
|
||||
int i;
|
||||
|
@ -257,9 +257,10 @@ MODULE_DEVICE_TABLE(i2c, max1586_id);
|
|||
|
||||
static struct i2c_driver max1586_pmic_driver = {
|
||||
.probe = max1586_pmic_probe,
|
||||
.remove = max1586_pmic_remove,
|
||||
.remove = __devexit_p(max1586_pmic_remove),
|
||||
.driver = {
|
||||
.name = "max1586",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.id_table = max1586_id,
|
||||
};
|
||||
|
|
408
drivers/regulator/max8649.c
Normal file
408
drivers/regulator/max8649.c
Normal file
|
@ -0,0 +1,408 @@
|
|||
/*
|
||||
* Regulators driver for Maxim max8649
|
||||
*
|
||||
* Copyright (C) 2009-2010 Marvell International Ltd.
|
||||
* Haojian Zhuang <haojian.zhuang@marvell.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/max8649.h>
|
||||
|
||||
#define MAX8649_DCDC_VMIN 750000 /* uV */
|
||||
#define MAX8649_DCDC_VMAX 1380000 /* uV */
|
||||
#define MAX8649_DCDC_STEP 10000 /* uV */
|
||||
#define MAX8649_VOL_MASK 0x3f
|
||||
|
||||
/* Registers */
|
||||
#define MAX8649_MODE0 0x00
|
||||
#define MAX8649_MODE1 0x01
|
||||
#define MAX8649_MODE2 0x02
|
||||
#define MAX8649_MODE3 0x03
|
||||
#define MAX8649_CONTROL 0x04
|
||||
#define MAX8649_SYNC 0x05
|
||||
#define MAX8649_RAMP 0x06
|
||||
#define MAX8649_CHIP_ID1 0x08
|
||||
#define MAX8649_CHIP_ID2 0x09
|
||||
|
||||
/* Bits */
|
||||
#define MAX8649_EN_PD (1 << 7)
|
||||
#define MAX8649_VID0_PD (1 << 6)
|
||||
#define MAX8649_VID1_PD (1 << 5)
|
||||
#define MAX8649_VID_MASK (3 << 5)
|
||||
|
||||
#define MAX8649_FORCE_PWM (1 << 7)
|
||||
#define MAX8649_SYNC_EXTCLK (1 << 6)
|
||||
|
||||
#define MAX8649_EXT_MASK (3 << 6)
|
||||
|
||||
#define MAX8649_RAMP_MASK (7 << 5)
|
||||
#define MAX8649_RAMP_DOWN (1 << 1)
|
||||
|
||||
struct max8649_regulator_info {
|
||||
struct regulator_dev *regulator;
|
||||
struct i2c_client *i2c;
|
||||
struct device *dev;
|
||||
struct mutex io_lock;
|
||||
|
||||
int vol_reg;
|
||||
unsigned mode:2; /* bit[1:0] = VID1, VID0 */
|
||||
unsigned extclk_freq:2;
|
||||
unsigned extclk:1;
|
||||
unsigned ramp_timing:3;
|
||||
unsigned ramp_down:1;
|
||||
};
|
||||
|
||||
/* I2C operations */
|
||||
|
||||
static inline int max8649_read_device(struct i2c_client *i2c,
|
||||
int reg, int bytes, void *dest)
|
||||
{
|
||||
unsigned char data;
|
||||
int ret;
|
||||
|
||||
data = (unsigned char)reg;
|
||||
ret = i2c_master_send(i2c, &data, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = i2c_master_recv(i2c, dest, bytes);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int max8649_write_device(struct i2c_client *i2c,
|
||||
int reg, int bytes, void *src)
|
||||
{
|
||||
unsigned char buf[bytes + 1];
|
||||
int ret;
|
||||
|
||||
buf[0] = (unsigned char)reg;
|
||||
memcpy(&buf[1], src, bytes);
|
||||
|
||||
ret = i2c_master_send(i2c, buf, bytes + 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max8649_reg_read(struct i2c_client *i2c, int reg)
|
||||
{
|
||||
struct max8649_regulator_info *info = i2c_get_clientdata(i2c);
|
||||
unsigned char data;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&info->io_lock);
|
||||
ret = max8649_read_device(i2c, reg, 1, &data);
|
||||
mutex_unlock(&info->io_lock);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return (int)data;
|
||||
}
|
||||
|
||||
static int max8649_set_bits(struct i2c_client *i2c, int reg,
|
||||
unsigned char mask, unsigned char data)
|
||||
{
|
||||
struct max8649_regulator_info *info = i2c_get_clientdata(i2c);
|
||||
unsigned char value;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&info->io_lock);
|
||||
ret = max8649_read_device(i2c, reg, 1, &value);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
value &= ~mask;
|
||||
value |= data;
|
||||
ret = max8649_write_device(i2c, reg, 1, &value);
|
||||
out:
|
||||
mutex_unlock(&info->io_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int check_range(int min_uV, int max_uV)
|
||||
{
|
||||
if ((min_uV < MAX8649_DCDC_VMIN) || (max_uV > MAX8649_DCDC_VMAX)
|
||||
|| (min_uV > max_uV))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max8649_list_voltage(struct regulator_dev *rdev, unsigned index)
|
||||
{
|
||||
return (MAX8649_DCDC_VMIN + index * MAX8649_DCDC_STEP);
|
||||
}
|
||||
|
||||
static int max8649_get_voltage(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
unsigned char data;
|
||||
int ret;
|
||||
|
||||
ret = max8649_reg_read(info->i2c, info->vol_reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
data = (unsigned char)ret & MAX8649_VOL_MASK;
|
||||
return max8649_list_voltage(rdev, data);
|
||||
}
|
||||
|
||||
static int max8649_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
unsigned char data, mask;
|
||||
|
||||
if (check_range(min_uV, max_uV)) {
|
||||
dev_err(info->dev, "invalid voltage range (%d, %d) uV\n",
|
||||
min_uV, max_uV);
|
||||
return -EINVAL;
|
||||
}
|
||||
data = (min_uV - MAX8649_DCDC_VMIN + MAX8649_DCDC_STEP - 1)
|
||||
/ MAX8649_DCDC_STEP;
|
||||
mask = MAX8649_VOL_MASK;
|
||||
|
||||
return max8649_set_bits(info->i2c, info->vol_reg, mask, data);
|
||||
}
|
||||
|
||||
/* EN_PD means pulldown on EN input */
|
||||
static int max8649_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
return max8649_set_bits(info->i2c, MAX8649_CONTROL, MAX8649_EN_PD, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Applied internal pulldown resistor on EN input pin.
|
||||
* If pulldown EN pin outside, it would be better.
|
||||
*/
|
||||
static int max8649_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
return max8649_set_bits(info->i2c, MAX8649_CONTROL, MAX8649_EN_PD,
|
||||
MAX8649_EN_PD);
|
||||
}
|
||||
|
||||
static int max8649_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
ret = max8649_reg_read(info->i2c, MAX8649_CONTROL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return !((unsigned char)ret & MAX8649_EN_PD);
|
||||
}
|
||||
|
||||
static int max8649_enable_time(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
int voltage, rate, ret;
|
||||
|
||||
/* get voltage */
|
||||
ret = max8649_reg_read(info->i2c, info->vol_reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret &= MAX8649_VOL_MASK;
|
||||
voltage = max8649_list_voltage(rdev, (unsigned char)ret); /* uV */
|
||||
|
||||
/* get rate */
|
||||
ret = max8649_reg_read(info->i2c, MAX8649_RAMP);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = (ret & MAX8649_RAMP_MASK) >> 5;
|
||||
rate = (32 * 1000) >> ret; /* uV/uS */
|
||||
|
||||
return (voltage / rate);
|
||||
}
|
||||
|
||||
static int max8649_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
{
|
||||
struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_FAST:
|
||||
max8649_set_bits(info->i2c, info->vol_reg, MAX8649_FORCE_PWM,
|
||||
MAX8649_FORCE_PWM);
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
max8649_set_bits(info->i2c, info->vol_reg,
|
||||
MAX8649_FORCE_PWM, 0);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int max8649_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
ret = max8649_reg_read(info->i2c, info->vol_reg);
|
||||
if (ret & MAX8649_FORCE_PWM)
|
||||
return REGULATOR_MODE_FAST;
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static struct regulator_ops max8649_dcdc_ops = {
|
||||
.set_voltage = max8649_set_voltage,
|
||||
.get_voltage = max8649_get_voltage,
|
||||
.list_voltage = max8649_list_voltage,
|
||||
.enable = max8649_enable,
|
||||
.disable = max8649_disable,
|
||||
.is_enabled = max8649_is_enabled,
|
||||
.enable_time = max8649_enable_time,
|
||||
.set_mode = max8649_set_mode,
|
||||
.get_mode = max8649_get_mode,
|
||||
|
||||
};
|
||||
|
||||
static struct regulator_desc dcdc_desc = {
|
||||
.name = "max8649",
|
||||
.ops = &max8649_dcdc_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = 1 << 6,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __devinit max8649_regulator_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct max8649_platform_data *pdata = client->dev.platform_data;
|
||||
struct max8649_regulator_info *info = NULL;
|
||||
unsigned char data;
|
||||
int ret;
|
||||
|
||||
info = kzalloc(sizeof(struct max8649_regulator_info), GFP_KERNEL);
|
||||
if (!info) {
|
||||
dev_err(&client->dev, "No enough memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
info->i2c = client;
|
||||
info->dev = &client->dev;
|
||||
mutex_init(&info->io_lock);
|
||||
i2c_set_clientdata(client, info);
|
||||
|
||||
info->mode = pdata->mode;
|
||||
switch (info->mode) {
|
||||
case 0:
|
||||
info->vol_reg = MAX8649_MODE0;
|
||||
break;
|
||||
case 1:
|
||||
info->vol_reg = MAX8649_MODE1;
|
||||
break;
|
||||
case 2:
|
||||
info->vol_reg = MAX8649_MODE2;
|
||||
break;
|
||||
case 3:
|
||||
info->vol_reg = MAX8649_MODE3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = max8649_reg_read(info->i2c, MAX8649_CHIP_ID1);
|
||||
if (ret < 0) {
|
||||
dev_err(info->dev, "Failed to detect ID of MAX8649:%d\n",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
dev_info(info->dev, "Detected MAX8649 (ID:%x)\n", ret);
|
||||
|
||||
/* enable VID0 & VID1 */
|
||||
max8649_set_bits(info->i2c, MAX8649_CONTROL, MAX8649_VID_MASK, 0);
|
||||
|
||||
/* enable/disable external clock synchronization */
|
||||
info->extclk = pdata->extclk;
|
||||
data = (info->extclk) ? MAX8649_SYNC_EXTCLK : 0;
|
||||
max8649_set_bits(info->i2c, info->vol_reg, MAX8649_SYNC_EXTCLK, data);
|
||||
if (info->extclk) {
|
||||
/* set external clock frequency */
|
||||
info->extclk_freq = pdata->extclk_freq;
|
||||
max8649_set_bits(info->i2c, MAX8649_SYNC, MAX8649_EXT_MASK,
|
||||
info->extclk_freq);
|
||||
}
|
||||
|
||||
if (pdata->ramp_timing) {
|
||||
info->ramp_timing = pdata->ramp_timing;
|
||||
max8649_set_bits(info->i2c, MAX8649_RAMP, MAX8649_RAMP_MASK,
|
||||
info->ramp_timing << 5);
|
||||
}
|
||||
|
||||
info->ramp_down = pdata->ramp_down;
|
||||
if (info->ramp_down) {
|
||||
max8649_set_bits(info->i2c, MAX8649_RAMP, MAX8649_RAMP_DOWN,
|
||||
MAX8649_RAMP_DOWN);
|
||||
}
|
||||
|
||||
info->regulator = regulator_register(&dcdc_desc, &client->dev,
|
||||
pdata->regulator, info);
|
||||
if (IS_ERR(info->regulator)) {
|
||||
dev_err(info->dev, "failed to register regulator %s\n",
|
||||
dcdc_desc.name);
|
||||
ret = PTR_ERR(info->regulator);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_info(info->dev, "Max8649 regulator device is detected.\n");
|
||||
return 0;
|
||||
out:
|
||||
kfree(info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit max8649_regulator_remove(struct i2c_client *client)
|
||||
{
|
||||
struct max8649_regulator_info *info = i2c_get_clientdata(client);
|
||||
|
||||
if (info) {
|
||||
if (info->regulator)
|
||||
regulator_unregister(info->regulator);
|
||||
kfree(info);
|
||||
}
|
||||
i2c_set_clientdata(client, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id max8649_id[] = {
|
||||
{ "max8649", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, max8649_id);
|
||||
|
||||
static struct i2c_driver max8649_driver = {
|
||||
.probe = max8649_regulator_probe,
|
||||
.remove = __devexit_p(max8649_regulator_remove),
|
||||
.driver = {
|
||||
.name = "max8649",
|
||||
},
|
||||
.id_table = max8649_id,
|
||||
};
|
||||
|
||||
static int __init max8649_init(void)
|
||||
{
|
||||
return i2c_add_driver(&max8649_driver);
|
||||
}
|
||||
subsys_initcall(max8649_init);
|
||||
|
||||
static void __exit max8649_exit(void)
|
||||
{
|
||||
i2c_del_driver(&max8649_driver);
|
||||
}
|
||||
module_exit(max8649_exit);
|
||||
|
||||
/* Module information */
|
||||
MODULE_DESCRIPTION("MAXIM 8649 voltage regulator driver");
|
||||
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -345,8 +345,8 @@ static struct regulator_desc max8660_reg[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static int max8660_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *i2c_id)
|
||||
static int __devinit max8660_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *i2c_id)
|
||||
{
|
||||
struct regulator_dev **rdev;
|
||||
struct max8660_platform_data *pdata = client->dev.platform_data;
|
||||
|
@ -354,7 +354,7 @@ static int max8660_probe(struct i2c_client *client,
|
|||
int boot_on, i, id, ret = -EINVAL;
|
||||
|
||||
if (pdata->num_subdevs > MAX8660_V_END) {
|
||||
dev_err(&client->dev, "Too much regulators found!\n");
|
||||
dev_err(&client->dev, "Too many regulators found!\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -462,7 +462,7 @@ static int max8660_probe(struct i2c_client *client,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int max8660_remove(struct i2c_client *client)
|
||||
static int __devexit max8660_remove(struct i2c_client *client)
|
||||
{
|
||||
struct regulator_dev **rdev = i2c_get_clientdata(client);
|
||||
int i;
|
||||
|
@ -485,9 +485,10 @@ MODULE_DEVICE_TABLE(i2c, max8660_id);
|
|||
|
||||
static struct i2c_driver max8660_driver = {
|
||||
.probe = max8660_probe,
|
||||
.remove = max8660_remove,
|
||||
.remove = __devexit_p(max8660_remove),
|
||||
.driver = {
|
||||
.name = "max8660",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.id_table = max8660_id,
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* Regulator Driver for Freescale MC13783 PMIC
|
||||
*
|
||||
* Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
|
||||
* Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
@ -16,11 +17,44 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#define MC13783_REG_SWITCHERS4 28
|
||||
#define MC13783_REG_SWITCHERS4_PLLEN (1 << 18)
|
||||
|
||||
#define MC13783_REG_SWITCHERS5 29
|
||||
#define MC13783_REG_SWITCHERS5_SW3EN (1 << 20)
|
||||
#define MC13783_REG_SWITCHERS5_SW3VSEL 18
|
||||
#define MC13783_REG_SWITCHERS5_SW3VSEL_M (3 << 18)
|
||||
|
||||
#define MC13783_REG_REGULATORSETTING0 30
|
||||
#define MC13783_REG_REGULATORSETTING0_VIOLOVSEL 2
|
||||
#define MC13783_REG_REGULATORSETTING0_VDIGVSEL 4
|
||||
#define MC13783_REG_REGULATORSETTING0_VGENVSEL 6
|
||||
#define MC13783_REG_REGULATORSETTING0_VRFDIGVSEL 9
|
||||
#define MC13783_REG_REGULATORSETTING0_VRFREFVSEL 11
|
||||
#define MC13783_REG_REGULATORSETTING0_VRFCPVSEL 13
|
||||
#define MC13783_REG_REGULATORSETTING0_VSIMVSEL 14
|
||||
#define MC13783_REG_REGULATORSETTING0_VESIMVSEL 15
|
||||
#define MC13783_REG_REGULATORSETTING0_VCAMVSEL 16
|
||||
|
||||
#define MC13783_REG_REGULATORSETTING0_VIOLOVSEL_M (3 << 2)
|
||||
#define MC13783_REG_REGULATORSETTING0_VDIGVSEL_M (3 << 4)
|
||||
#define MC13783_REG_REGULATORSETTING0_VGENVSEL_M (7 << 6)
|
||||
#define MC13783_REG_REGULATORSETTING0_VRFDIGVSEL_M (3 << 9)
|
||||
#define MC13783_REG_REGULATORSETTING0_VRFREFVSEL_M (3 << 11)
|
||||
#define MC13783_REG_REGULATORSETTING0_VRFCPVSEL_M (1 << 13)
|
||||
#define MC13783_REG_REGULATORSETTING0_VSIMVSEL_M (1 << 14)
|
||||
#define MC13783_REG_REGULATORSETTING0_VESIMVSEL_M (1 << 15)
|
||||
#define MC13783_REG_REGULATORSETTING0_VCAMVSEL_M (7 << 16)
|
||||
|
||||
#define MC13783_REG_REGULATORSETTING1 31
|
||||
#define MC13783_REG_REGULATORSETTING1_VVIBVSEL 0
|
||||
#define MC13783_REG_REGULATORSETTING1_VRF1VSEL 2
|
||||
#define MC13783_REG_REGULATORSETTING1_VRF2VSEL 4
|
||||
#define MC13783_REG_REGULATORSETTING1_VMMC1VSEL 6
|
||||
#define MC13783_REG_REGULATORSETTING1_VMMC2VSEL 9
|
||||
|
||||
#define MC13783_REG_REGULATORSETTING1_VVIBVSEL_M (3 << 0)
|
||||
#define MC13783_REG_REGULATORSETTING1_VRF1VSEL_M (3 << 2)
|
||||
#define MC13783_REG_REGULATORSETTING1_VRF2VSEL_M (3 << 4)
|
||||
#define MC13783_REG_REGULATORSETTING1_VMMC1VSEL_M (7 << 6)
|
||||
#define MC13783_REG_REGULATORSETTING1_VMMC2VSEL_M (7 << 9)
|
||||
|
||||
#define MC13783_REG_REGULATORMODE0 32
|
||||
#define MC13783_REG_REGULATORMODE0_VAUDIOEN (1 << 0)
|
||||
|
@ -48,19 +82,107 @@
|
|||
#define MC13783_REG_POWERMISC_GPO2EN (1 << 8)
|
||||
#define MC13783_REG_POWERMISC_GPO3EN (1 << 10)
|
||||
#define MC13783_REG_POWERMISC_GPO4EN (1 << 12)
|
||||
#define MC13783_REG_POWERMISC_PWGT1SPIEN (1 << 15)
|
||||
#define MC13783_REG_POWERMISC_PWGT2SPIEN (1 << 16)
|
||||
|
||||
#define MC13783_REG_POWERMISC_PWGTSPI_M (3 << 15)
|
||||
|
||||
|
||||
struct mc13783_regulator {
|
||||
struct regulator_desc desc;
|
||||
int reg;
|
||||
int enable_bit;
|
||||
int vsel_reg;
|
||||
int vsel_shift;
|
||||
int vsel_mask;
|
||||
int const *voltages;
|
||||
};
|
||||
|
||||
/* Voltage Values */
|
||||
static const int const mc13783_sw3_val[] = {
|
||||
5000000, 5000000, 5000000, 5500000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vaudio_val[] = {
|
||||
2775000,
|
||||
};
|
||||
|
||||
static const int const mc13783_viohi_val[] = {
|
||||
2775000,
|
||||
};
|
||||
|
||||
static const int const mc13783_violo_val[] = {
|
||||
1200000, 1300000, 1500000, 1800000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vdig_val[] = {
|
||||
1200000, 1300000, 1500000, 1800000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vgen_val[] = {
|
||||
1200000, 1300000, 1500000, 1800000,
|
||||
1100000, 2000000, 2775000, 2400000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vrfdig_val[] = {
|
||||
1200000, 1500000, 1800000, 1875000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vrfref_val[] = {
|
||||
2475000, 2600000, 2700000, 2775000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vrfcp_val[] = {
|
||||
2700000, 2775000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vsim_val[] = {
|
||||
1800000, 2900000, 3000000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vesim_val[] = {
|
||||
1800000, 2900000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vcam_val[] = {
|
||||
1500000, 1800000, 2500000, 2550000,
|
||||
2600000, 2750000, 2800000, 3000000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vrfbg_val[] = {
|
||||
1250000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vvib_val[] = {
|
||||
1300000, 1800000, 2000000, 3000000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vmmc_val[] = {
|
||||
1600000, 1800000, 2000000, 2600000,
|
||||
2700000, 2800000, 2900000, 3000000,
|
||||
};
|
||||
|
||||
static const int const mc13783_vrf_val[] = {
|
||||
1500000, 1875000, 2700000, 2775000,
|
||||
};
|
||||
|
||||
static const int const mc13783_gpo_val[] = {
|
||||
3100000,
|
||||
};
|
||||
|
||||
static const int const mc13783_pwgtdrv_val[] = {
|
||||
5500000,
|
||||
};
|
||||
|
||||
static struct regulator_ops mc13783_regulator_ops;
|
||||
static struct regulator_ops mc13783_fixed_regulator_ops;
|
||||
static struct regulator_ops mc13783_gpo_regulator_ops;
|
||||
|
||||
#define MC13783_DEFINE(prefix, _name, _reg) \
|
||||
#define MC13783_DEFINE(prefix, _name, _reg, _vsel_reg, _voltages) \
|
||||
[MC13783_ ## prefix ## _ ## _name] = { \
|
||||
.desc = { \
|
||||
.name = #prefix "_" #_name, \
|
||||
.n_voltages = ARRAY_SIZE(_voltages), \
|
||||
.ops = &mc13783_regulator_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = MC13783_ ## prefix ## _ ## _name, \
|
||||
|
@ -68,40 +190,92 @@ static struct regulator_ops mc13783_regulator_ops;
|
|||
}, \
|
||||
.reg = MC13783_REG_ ## _reg, \
|
||||
.enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN, \
|
||||
.vsel_reg = MC13783_REG_ ## _vsel_reg, \
|
||||
.vsel_shift = MC13783_REG_ ## _vsel_reg ## _ ## _name ## VSEL,\
|
||||
.vsel_mask = MC13783_REG_ ## _vsel_reg ## _ ## _name ## VSEL_M,\
|
||||
.voltages = _voltages, \
|
||||
}
|
||||
|
||||
#define MC13783_DEFINE_SW(_name, _reg) MC13783_DEFINE(SW, _name, _reg)
|
||||
#define MC13783_DEFINE_REGU(_name, _reg) MC13783_DEFINE(REGU, _name, _reg)
|
||||
#define MC13783_FIXED_DEFINE(prefix, _name, _reg, _voltages) \
|
||||
[MC13783_ ## prefix ## _ ## _name] = { \
|
||||
.desc = { \
|
||||
.name = #prefix "_" #_name, \
|
||||
.n_voltages = ARRAY_SIZE(_voltages), \
|
||||
.ops = &mc13783_fixed_regulator_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = MC13783_ ## prefix ## _ ## _name, \
|
||||
.owner = THIS_MODULE, \
|
||||
}, \
|
||||
.reg = MC13783_REG_ ## _reg, \
|
||||
.enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN, \
|
||||
.voltages = _voltages, \
|
||||
}
|
||||
|
||||
#define MC13783_GPO_DEFINE(prefix, _name, _reg, _voltages) \
|
||||
[MC13783_ ## prefix ## _ ## _name] = { \
|
||||
.desc = { \
|
||||
.name = #prefix "_" #_name, \
|
||||
.n_voltages = ARRAY_SIZE(_voltages), \
|
||||
.ops = &mc13783_gpo_regulator_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = MC13783_ ## prefix ## _ ## _name, \
|
||||
.owner = THIS_MODULE, \
|
||||
}, \
|
||||
.reg = MC13783_REG_ ## _reg, \
|
||||
.enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN, \
|
||||
.voltages = _voltages, \
|
||||
}
|
||||
|
||||
#define MC13783_DEFINE_SW(_name, _reg, _vsel_reg, _voltages) \
|
||||
MC13783_DEFINE(SW, _name, _reg, _vsel_reg, _voltages)
|
||||
#define MC13783_DEFINE_REGU(_name, _reg, _vsel_reg, _voltages) \
|
||||
MC13783_DEFINE(REGU, _name, _reg, _vsel_reg, _voltages)
|
||||
|
||||
static struct mc13783_regulator mc13783_regulators[] = {
|
||||
MC13783_DEFINE_SW(SW3, SWITCHERS5),
|
||||
MC13783_DEFINE_SW(PLL, SWITCHERS4),
|
||||
MC13783_DEFINE_SW(SW3, SWITCHERS5, SWITCHERS5, mc13783_sw3_val),
|
||||
|
||||
MC13783_DEFINE_REGU(VAUDIO, REGULATORMODE0),
|
||||
MC13783_DEFINE_REGU(VIOHI, REGULATORMODE0),
|
||||
MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0),
|
||||
MC13783_DEFINE_REGU(VDIG, REGULATORMODE0),
|
||||
MC13783_DEFINE_REGU(VGEN, REGULATORMODE0),
|
||||
MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0),
|
||||
MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0),
|
||||
MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0),
|
||||
MC13783_DEFINE_REGU(VSIM, REGULATORMODE1),
|
||||
MC13783_DEFINE_REGU(VESIM, REGULATORMODE1),
|
||||
MC13783_DEFINE_REGU(VCAM, REGULATORMODE1),
|
||||
MC13783_DEFINE_REGU(VRFBG, REGULATORMODE1),
|
||||
MC13783_DEFINE_REGU(VVIB, REGULATORMODE1),
|
||||
MC13783_DEFINE_REGU(VRF1, REGULATORMODE1),
|
||||
MC13783_DEFINE_REGU(VRF2, REGULATORMODE1),
|
||||
MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1),
|
||||
MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1),
|
||||
MC13783_DEFINE_REGU(GPO1, POWERMISC),
|
||||
MC13783_DEFINE_REGU(GPO2, POWERMISC),
|
||||
MC13783_DEFINE_REGU(GPO3, POWERMISC),
|
||||
MC13783_DEFINE_REGU(GPO4, POWERMISC),
|
||||
MC13783_FIXED_DEFINE(REGU, VAUDIO, REGULATORMODE0, mc13783_vaudio_val),
|
||||
MC13783_FIXED_DEFINE(REGU, VIOHI, REGULATORMODE0, mc13783_viohi_val),
|
||||
MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0, \
|
||||
mc13783_violo_val),
|
||||
MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0, \
|
||||
mc13783_vdig_val),
|
||||
MC13783_DEFINE_REGU(VGEN, REGULATORMODE0, REGULATORSETTING0, \
|
||||
mc13783_vgen_val),
|
||||
MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0, REGULATORSETTING0, \
|
||||
mc13783_vrfdig_val),
|
||||
MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0, REGULATORSETTING0, \
|
||||
mc13783_vrfref_val),
|
||||
MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0, REGULATORSETTING0, \
|
||||
mc13783_vrfcp_val),
|
||||
MC13783_DEFINE_REGU(VSIM, REGULATORMODE1, REGULATORSETTING0, \
|
||||
mc13783_vsim_val),
|
||||
MC13783_DEFINE_REGU(VESIM, REGULATORMODE1, REGULATORSETTING0, \
|
||||
mc13783_vesim_val),
|
||||
MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0, \
|
||||
mc13783_vcam_val),
|
||||
MC13783_FIXED_DEFINE(REGU, VRFBG, REGULATORMODE1, mc13783_vrfbg_val),
|
||||
MC13783_DEFINE_REGU(VVIB, REGULATORMODE1, REGULATORSETTING1, \
|
||||
mc13783_vvib_val),
|
||||
MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1, \
|
||||
mc13783_vrf_val),
|
||||
MC13783_DEFINE_REGU(VRF2, REGULATORMODE1, REGULATORSETTING1, \
|
||||
mc13783_vrf_val),
|
||||
MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1, REGULATORSETTING1, \
|
||||
mc13783_vmmc_val),
|
||||
MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1, \
|
||||
mc13783_vmmc_val),
|
||||
MC13783_GPO_DEFINE(REGU, GPO1, POWERMISC, mc13783_gpo_val),
|
||||
MC13783_GPO_DEFINE(REGU, GPO2, POWERMISC, mc13783_gpo_val),
|
||||
MC13783_GPO_DEFINE(REGU, GPO3, POWERMISC, mc13783_gpo_val),
|
||||
MC13783_GPO_DEFINE(REGU, GPO4, POWERMISC, mc13783_gpo_val),
|
||||
MC13783_GPO_DEFINE(REGU, PWGT1SPI, POWERMISC, mc13783_pwgtdrv_val),
|
||||
MC13783_GPO_DEFINE(REGU, PWGT2SPI, POWERMISC, mc13783_pwgtdrv_val),
|
||||
};
|
||||
|
||||
struct mc13783_regulator_priv {
|
||||
struct mc13783 *mc13783;
|
||||
u32 powermisc_pwgt_state;
|
||||
struct regulator_dev *regulators[];
|
||||
};
|
||||
|
||||
|
@ -154,10 +328,241 @@ static int mc13783_regulator_is_enabled(struct regulator_dev *rdev)
|
|||
return (val & mc13783_regulators[id].enable_bit) != 0;
|
||||
}
|
||||
|
||||
static int mc13783_regulator_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
int id = rdev_get_id(rdev);
|
||||
|
||||
if (selector >= mc13783_regulators[id].desc.n_voltages)
|
||||
return -EINVAL;
|
||||
|
||||
return mc13783_regulators[id].voltages[selector];
|
||||
}
|
||||
|
||||
static int mc13783_get_best_voltage_index(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
int reg_id = rdev_get_id(rdev);
|
||||
int i;
|
||||
int bestmatch;
|
||||
int bestindex;
|
||||
|
||||
/*
|
||||
* Locate the minimum voltage fitting the criteria on
|
||||
* this regulator. The switchable voltages are not
|
||||
* in strict falling order so we need to check them
|
||||
* all for the best match.
|
||||
*/
|
||||
bestmatch = INT_MAX;
|
||||
bestindex = -1;
|
||||
for (i = 0; i < mc13783_regulators[reg_id].desc.n_voltages; i++) {
|
||||
if (mc13783_regulators[reg_id].voltages[i] >= min_uV &&
|
||||
mc13783_regulators[reg_id].voltages[i] < bestmatch) {
|
||||
bestmatch = mc13783_regulators[reg_id].voltages[i];
|
||||
bestindex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestindex < 0 || bestmatch > max_uV) {
|
||||
dev_warn(&rdev->dev, "no possible value for %d<=x<=%d uV\n",
|
||||
min_uV, max_uV);
|
||||
return -EINVAL;
|
||||
}
|
||||
return bestindex;
|
||||
}
|
||||
|
||||
static int mc13783_regulator_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
|
||||
int value, id = rdev_get_id(rdev);
|
||||
int ret;
|
||||
|
||||
dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
|
||||
__func__, id, min_uV, max_uV);
|
||||
|
||||
/* Find the best index */
|
||||
value = mc13783_get_best_voltage_index(rdev, min_uV, max_uV);
|
||||
dev_dbg(rdev_get_dev(rdev), "%s best value: %d \n", __func__, value);
|
||||
if (value < 0)
|
||||
return value;
|
||||
|
||||
mc13783_lock(priv->mc13783);
|
||||
ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].vsel_reg,
|
||||
mc13783_regulators[id].vsel_mask,
|
||||
value << mc13783_regulators[id].vsel_shift);
|
||||
mc13783_unlock(priv->mc13783);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mc13783_regulator_get_voltage(struct regulator_dev *rdev)
|
||||
{
|
||||
struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
|
||||
int ret, id = rdev_get_id(rdev);
|
||||
unsigned int val;
|
||||
|
||||
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
|
||||
|
||||
mc13783_lock(priv->mc13783);
|
||||
ret = mc13783_reg_read(priv->mc13783,
|
||||
mc13783_regulators[id].vsel_reg, &val);
|
||||
mc13783_unlock(priv->mc13783);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = (val & mc13783_regulators[id].vsel_mask)
|
||||
>> mc13783_regulators[id].vsel_shift;
|
||||
|
||||
dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val);
|
||||
|
||||
BUG_ON(val < 0 || val > mc13783_regulators[id].desc.n_voltages);
|
||||
|
||||
return mc13783_regulators[id].voltages[val];
|
||||
}
|
||||
|
||||
static struct regulator_ops mc13783_regulator_ops = {
|
||||
.enable = mc13783_regulator_enable,
|
||||
.disable = mc13783_regulator_disable,
|
||||
.is_enabled = mc13783_regulator_is_enabled,
|
||||
.list_voltage = mc13783_regulator_list_voltage,
|
||||
.set_voltage = mc13783_regulator_set_voltage,
|
||||
.get_voltage = mc13783_regulator_get_voltage,
|
||||
};
|
||||
|
||||
static int mc13783_fixed_regulator_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
int id = rdev_get_id(rdev);
|
||||
|
||||
dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
|
||||
__func__, id, min_uV, max_uV);
|
||||
|
||||
if (min_uV > mc13783_regulators[id].voltages[0] &&
|
||||
max_uV < mc13783_regulators[id].voltages[0])
|
||||
return 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int mc13783_fixed_regulator_get_voltage(struct regulator_dev *rdev)
|
||||
{
|
||||
int id = rdev_get_id(rdev);
|
||||
|
||||
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
|
||||
|
||||
return mc13783_regulators[id].voltages[0];
|
||||
}
|
||||
|
||||
static struct regulator_ops mc13783_fixed_regulator_ops = {
|
||||
.enable = mc13783_regulator_enable,
|
||||
.disable = mc13783_regulator_disable,
|
||||
.is_enabled = mc13783_regulator_is_enabled,
|
||||
.list_voltage = mc13783_regulator_list_voltage,
|
||||
.set_voltage = mc13783_fixed_regulator_set_voltage,
|
||||
.get_voltage = mc13783_fixed_regulator_get_voltage,
|
||||
};
|
||||
|
||||
int mc13783_powermisc_rmw(struct mc13783_regulator_priv *priv, u32 mask,
|
||||
u32 val)
|
||||
{
|
||||
struct mc13783 *mc13783 = priv->mc13783;
|
||||
int ret;
|
||||
u32 valread;
|
||||
|
||||
BUG_ON(val & ~mask);
|
||||
|
||||
ret = mc13783_reg_read(mc13783, MC13783_REG_POWERMISC, &valread);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Update the stored state for Power Gates. */
|
||||
priv->powermisc_pwgt_state =
|
||||
(priv->powermisc_pwgt_state & ~mask) | val;
|
||||
priv->powermisc_pwgt_state &= MC13783_REG_POWERMISC_PWGTSPI_M;
|
||||
|
||||
/* Construct the new register value */
|
||||
valread = (valread & ~mask) | val;
|
||||
/* Overwrite the PWGTxEN with the stored version */
|
||||
valread = (valread & ~MC13783_REG_POWERMISC_PWGTSPI_M) |
|
||||
priv->powermisc_pwgt_state;
|
||||
|
||||
return mc13783_reg_write(mc13783, MC13783_REG_POWERMISC, valread);
|
||||
}
|
||||
|
||||
static int mc13783_gpo_regulator_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
|
||||
int id = rdev_get_id(rdev);
|
||||
int ret;
|
||||
u32 en_val = mc13783_regulators[id].enable_bit;
|
||||
|
||||
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
|
||||
|
||||
/* Power Gate enable value is 0 */
|
||||
if (id == MC13783_REGU_PWGT1SPI ||
|
||||
id == MC13783_REGU_PWGT2SPI)
|
||||
en_val = 0;
|
||||
|
||||
mc13783_lock(priv->mc13783);
|
||||
ret = mc13783_powermisc_rmw(priv, mc13783_regulators[id].enable_bit,
|
||||
en_val);
|
||||
mc13783_unlock(priv->mc13783);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mc13783_gpo_regulator_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
|
||||
int id = rdev_get_id(rdev);
|
||||
int ret;
|
||||
u32 dis_val = 0;
|
||||
|
||||
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
|
||||
|
||||
/* Power Gate disable value is 1 */
|
||||
if (id == MC13783_REGU_PWGT1SPI ||
|
||||
id == MC13783_REGU_PWGT2SPI)
|
||||
dis_val = mc13783_regulators[id].enable_bit;
|
||||
|
||||
mc13783_lock(priv->mc13783);
|
||||
ret = mc13783_powermisc_rmw(priv, mc13783_regulators[id].enable_bit,
|
||||
dis_val);
|
||||
mc13783_unlock(priv->mc13783);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mc13783_gpo_regulator_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
|
||||
int ret, id = rdev_get_id(rdev);
|
||||
unsigned int val;
|
||||
|
||||
mc13783_lock(priv->mc13783);
|
||||
ret = mc13783_reg_read(priv->mc13783, mc13783_regulators[id].reg, &val);
|
||||
mc13783_unlock(priv->mc13783);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Power Gates state is stored in powermisc_pwgt_state
|
||||
* where the meaning of bits is negated */
|
||||
val = (val & ~MC13783_REG_POWERMISC_PWGTSPI_M) |
|
||||
(priv->powermisc_pwgt_state ^ MC13783_REG_POWERMISC_PWGTSPI_M);
|
||||
|
||||
return (val & mc13783_regulators[id].enable_bit) != 0;
|
||||
}
|
||||
|
||||
static struct regulator_ops mc13783_gpo_regulator_ops = {
|
||||
.enable = mc13783_gpo_regulator_enable,
|
||||
.disable = mc13783_gpo_regulator_disable,
|
||||
.is_enabled = mc13783_gpo_regulator_is_enabled,
|
||||
.list_voltage = mc13783_regulator_list_voltage,
|
||||
.set_voltage = mc13783_fixed_regulator_set_voltage,
|
||||
.get_voltage = mc13783_fixed_regulator_get_voltage,
|
||||
};
|
||||
|
||||
static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
|
||||
|
|
|
@ -288,16 +288,18 @@ static int __devexit pcap_regulator_remove(struct platform_device *pdev)
|
|||
struct regulator_dev *rdev = platform_get_drvdata(pdev);
|
||||
|
||||
regulator_unregister(rdev);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver pcap_regulator_driver = {
|
||||
.driver = {
|
||||
.name = "pcap-regulator",
|
||||
.name = "pcap-regulator",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = pcap_regulator_probe,
|
||||
.remove = __devexit_p(pcap_regulator_remove),
|
||||
.probe = pcap_regulator_probe,
|
||||
.remove = __devexit_p(pcap_regulator_remove),
|
||||
};
|
||||
|
||||
static int __init pcap_regulator_init(void)
|
||||
|
|
|
@ -457,8 +457,8 @@ static struct regulator_ops tps65023_ldo_ops = {
|
|||
.list_voltage = tps65023_ldo_list_voltage,
|
||||
};
|
||||
|
||||
static
|
||||
int tps_65023_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
static int __devinit tps_65023_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
static int desc_id;
|
||||
const struct tps_info *info = (void *)id->driver_data;
|
||||
|
@ -466,6 +466,7 @@ int tps_65023_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
struct regulator_dev *rdev;
|
||||
struct tps_pmic *tps;
|
||||
int i;
|
||||
int error;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
return -EIO;
|
||||
|
@ -475,7 +476,6 @@ int tps_65023_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
* coming from the board-evm file.
|
||||
*/
|
||||
init_data = client->dev.platform_data;
|
||||
|
||||
if (!init_data)
|
||||
return -EIO;
|
||||
|
||||
|
@ -502,21 +502,12 @@ int tps_65023_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
|
||||
/* Register the regulators */
|
||||
rdev = regulator_register(&tps->desc[i], &client->dev,
|
||||
init_data, tps);
|
||||
init_data, tps);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&client->dev, "failed to register %s\n",
|
||||
id->name);
|
||||
|
||||
/* Unregister */
|
||||
while (i)
|
||||
regulator_unregister(tps->rdev[--i]);
|
||||
|
||||
tps->client = NULL;
|
||||
|
||||
/* clear the client data in i2c */
|
||||
i2c_set_clientdata(client, NULL);
|
||||
kfree(tps);
|
||||
return PTR_ERR(rdev);
|
||||
error = PTR_ERR(rdev);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Save regulator for cleanup */
|
||||
|
@ -526,6 +517,13 @@ int tps_65023_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
i2c_set_clientdata(client, tps);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
while (--i >= 0)
|
||||
regulator_unregister(tps->rdev[i]);
|
||||
|
||||
kfree(tps);
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -539,13 +537,12 @@ static int __devexit tps_65023_remove(struct i2c_client *client)
|
|||
struct tps_pmic *tps = i2c_get_clientdata(client);
|
||||
int i;
|
||||
|
||||
/* clear the client data in i2c */
|
||||
i2c_set_clientdata(client, NULL);
|
||||
|
||||
for (i = 0; i < TPS65023_NUM_REGULATOR; i++)
|
||||
regulator_unregister(tps->rdev[i]);
|
||||
|
||||
tps->client = NULL;
|
||||
|
||||
/* clear the client data in i2c */
|
||||
i2c_set_clientdata(client, NULL);
|
||||
kfree(tps);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -538,8 +538,8 @@ static struct regulator_ops tps6507x_ldo_ops = {
|
|||
.list_voltage = tps6507x_ldo_list_voltage,
|
||||
};
|
||||
|
||||
static
|
||||
int tps_6507x_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
static int __devinit tps_6507x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
static int desc_id;
|
||||
const struct tps_info *info = (void *)id->driver_data;
|
||||
|
@ -547,6 +547,7 @@ int tps_6507x_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
struct regulator_dev *rdev;
|
||||
struct tps_pmic *tps;
|
||||
int i;
|
||||
int error;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
|
@ -557,7 +558,6 @@ int tps_6507x_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
* coming from the board-evm file.
|
||||
*/
|
||||
init_data = client->dev.platform_data;
|
||||
|
||||
if (!init_data)
|
||||
return -EIO;
|
||||
|
||||
|
@ -586,18 +586,8 @@ int tps_6507x_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
if (IS_ERR(rdev)) {
|
||||
dev_err(&client->dev, "failed to register %s\n",
|
||||
id->name);
|
||||
|
||||
/* Unregister */
|
||||
while (i)
|
||||
regulator_unregister(tps->rdev[--i]);
|
||||
|
||||
tps->client = NULL;
|
||||
|
||||
/* clear the client data in i2c */
|
||||
i2c_set_clientdata(client, NULL);
|
||||
|
||||
kfree(tps);
|
||||
return PTR_ERR(rdev);
|
||||
error = PTR_ERR(rdev);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Save regulator for cleanup */
|
||||
|
@ -607,6 +597,13 @@ int tps_6507x_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
i2c_set_clientdata(client, tps);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
while (--i >= 0)
|
||||
regulator_unregister(tps->rdev[i]);
|
||||
|
||||
kfree(tps);
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -620,13 +617,12 @@ static int __devexit tps_6507x_remove(struct i2c_client *client)
|
|||
struct tps_pmic *tps = i2c_get_clientdata(client);
|
||||
int i;
|
||||
|
||||
/* clear the client data in i2c */
|
||||
i2c_set_clientdata(client, NULL);
|
||||
|
||||
for (i = 0; i < TPS6507X_NUM_REGULATOR; i++)
|
||||
regulator_unregister(tps->rdev[i]);
|
||||
|
||||
tps->client = NULL;
|
||||
|
||||
/* clear the client data in i2c */
|
||||
i2c_set_clientdata(client, NULL);
|
||||
kfree(tps);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -519,19 +519,19 @@ static struct twlreg_info twl_regs[] = {
|
|||
/* 6030 REG with base as PMC Slave Misc : 0x0030 */
|
||||
/* Turnon-delay and remap configuration values for 6030 are not
|
||||
verified since the specification is not public */
|
||||
TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1, 0, 0x08),
|
||||
TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 2, 0, 0x08),
|
||||
TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 3, 0, 0x08),
|
||||
TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 4, 0, 0x08),
|
||||
TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 5, 0, 0x08),
|
||||
TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 7, 0, 0x08),
|
||||
TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0, 0x08),
|
||||
TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0, 0x08),
|
||||
TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0, 0x08),
|
||||
TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0, 0x08)
|
||||
TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1, 0, 0x21),
|
||||
TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 2, 0, 0x21),
|
||||
TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 3, 0, 0x21),
|
||||
TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 4, 0, 0x21),
|
||||
TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 5, 0, 0x21),
|
||||
TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 7, 0, 0x21),
|
||||
TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0, 0x21),
|
||||
TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0, 0x21),
|
||||
TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0, 0x21),
|
||||
TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0, 0x21)
|
||||
};
|
||||
|
||||
static int twlreg_probe(struct platform_device *pdev)
|
||||
static int __devinit twlreg_probe(struct platform_device *pdev)
|
||||
{
|
||||
int i;
|
||||
struct twlreg_info *info;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
struct virtual_consumer_data {
|
||||
struct mutex lock;
|
||||
struct regulator *regulator;
|
||||
int enabled;
|
||||
bool enabled;
|
||||
int min_uV;
|
||||
int max_uV;
|
||||
int min_uA;
|
||||
|
@ -49,7 +49,7 @@ static void update_voltage_constraints(struct device *dev,
|
|||
dev_dbg(dev, "Enabling regulator\n");
|
||||
ret = regulator_enable(data->regulator);
|
||||
if (ret == 0)
|
||||
data->enabled = 1;
|
||||
data->enabled = true;
|
||||
else
|
||||
dev_err(dev, "regulator_enable() failed: %d\n",
|
||||
ret);
|
||||
|
@ -59,7 +59,7 @@ static void update_voltage_constraints(struct device *dev,
|
|||
dev_dbg(dev, "Disabling regulator\n");
|
||||
ret = regulator_disable(data->regulator);
|
||||
if (ret == 0)
|
||||
data->enabled = 0;
|
||||
data->enabled = false;
|
||||
else
|
||||
dev_err(dev, "regulator_disable() failed: %d\n",
|
||||
ret);
|
||||
|
@ -89,7 +89,7 @@ static void update_current_limit_constraints(struct device *dev,
|
|||
dev_dbg(dev, "Enabling regulator\n");
|
||||
ret = regulator_enable(data->regulator);
|
||||
if (ret == 0)
|
||||
data->enabled = 1;
|
||||
data->enabled = true;
|
||||
else
|
||||
dev_err(dev, "regulator_enable() failed: %d\n",
|
||||
ret);
|
||||
|
@ -99,7 +99,7 @@ static void update_current_limit_constraints(struct device *dev,
|
|||
dev_dbg(dev, "Disabling regulator\n");
|
||||
ret = regulator_disable(data->regulator);
|
||||
if (ret == 0)
|
||||
data->enabled = 0;
|
||||
data->enabled = false;
|
||||
else
|
||||
dev_err(dev, "regulator_disable() failed: %d\n",
|
||||
ret);
|
||||
|
@ -270,24 +270,28 @@ 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(mode, 0666, show_mode, set_mode);
|
||||
|
||||
static struct device_attribute *attributes[] = {
|
||||
&dev_attr_min_microvolts,
|
||||
&dev_attr_max_microvolts,
|
||||
&dev_attr_min_microamps,
|
||||
&dev_attr_max_microamps,
|
||||
&dev_attr_mode,
|
||||
static struct attribute *regulator_virtual_attributes[] = {
|
||||
&dev_attr_min_microvolts.attr,
|
||||
&dev_attr_max_microvolts.attr,
|
||||
&dev_attr_min_microamps.attr,
|
||||
&dev_attr_max_microamps.attr,
|
||||
&dev_attr_mode.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int regulator_virtual_consumer_probe(struct platform_device *pdev)
|
||||
static const struct attribute_group regulator_virtual_attr_group = {
|
||||
.attrs = regulator_virtual_attributes,
|
||||
};
|
||||
|
||||
static int __devinit regulator_virtual_probe(struct platform_device *pdev)
|
||||
{
|
||||
char *reg_id = pdev->dev.platform_data;
|
||||
struct virtual_consumer_data *drvdata;
|
||||
int ret, i;
|
||||
int ret;
|
||||
|
||||
drvdata = kzalloc(sizeof(struct virtual_consumer_data), GFP_KERNEL);
|
||||
if (drvdata == NULL) {
|
||||
if (drvdata == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mutex_init(&drvdata->lock);
|
||||
|
||||
|
@ -299,13 +303,12 @@ static int regulator_virtual_consumer_probe(struct platform_device *pdev)
|
|||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(attributes); i++) {
|
||||
ret = device_create_file(&pdev->dev, attributes[i]);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "Failed to create attr %d: %d\n",
|
||||
i, ret);
|
||||
goto err_regulator;
|
||||
}
|
||||
ret = sysfs_create_group(&pdev->dev.kobj,
|
||||
®ulator_virtual_attr_group);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to create attribute group: %d\n", ret);
|
||||
goto err_regulator;
|
||||
}
|
||||
|
||||
drvdata->mode = regulator_get_mode(drvdata->regulator);
|
||||
|
@ -317,37 +320,36 @@ static int regulator_virtual_consumer_probe(struct platform_device *pdev)
|
|||
err_regulator:
|
||||
regulator_put(drvdata->regulator);
|
||||
err:
|
||||
for (i = 0; i < ARRAY_SIZE(attributes); i++)
|
||||
device_remove_file(&pdev->dev, attributes[i]);
|
||||
kfree(drvdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int regulator_virtual_consumer_remove(struct platform_device *pdev)
|
||||
static int __devexit regulator_virtual_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct virtual_consumer_data *drvdata = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(attributes); i++)
|
||||
device_remove_file(&pdev->dev, attributes[i]);
|
||||
sysfs_remove_group(&pdev->dev.kobj, ®ulator_virtual_attr_group);
|
||||
|
||||
if (drvdata->enabled)
|
||||
regulator_disable(drvdata->regulator);
|
||||
regulator_put(drvdata->regulator);
|
||||
|
||||
kfree(drvdata);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver regulator_virtual_consumer_driver = {
|
||||
.probe = regulator_virtual_consumer_probe,
|
||||
.remove = regulator_virtual_consumer_remove,
|
||||
.probe = regulator_virtual_probe,
|
||||
.remove = __devexit_p(regulator_virtual_remove),
|
||||
.driver = {
|
||||
.name = "reg-virt-consumer",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
static int __init regulator_virtual_consumer_init(void)
|
||||
{
|
||||
return platform_driver_register(®ulator_virtual_consumer_driver);
|
||||
|
|
|
@ -600,6 +600,8 @@ static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
|
|||
struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
|
||||
struct wm831x *wm831x = dcdc->wm831x;
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "HC"), dcdc);
|
||||
wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc);
|
||||
regulator_unregister(dcdc->regulator);
|
||||
|
@ -615,6 +617,7 @@ static struct platform_driver wm831x_buckv_driver = {
|
|||
.remove = __devexit_p(wm831x_buckv_remove),
|
||||
.driver = {
|
||||
.name = "wm831x-buckv",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -769,6 +772,8 @@ static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
|
|||
struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
|
||||
struct wm831x *wm831x = dcdc->wm831x;
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc);
|
||||
regulator_unregister(dcdc->regulator);
|
||||
kfree(dcdc);
|
||||
|
@ -781,6 +786,7 @@ static struct platform_driver wm831x_buckp_driver = {
|
|||
.remove = __devexit_p(wm831x_buckp_remove),
|
||||
.driver = {
|
||||
.name = "wm831x-buckp",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -895,6 +901,8 @@ static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
|
|||
struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
|
||||
struct wm831x *wm831x = dcdc->wm831x;
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc);
|
||||
regulator_unregister(dcdc->regulator);
|
||||
kfree(dcdc);
|
||||
|
@ -907,6 +915,7 @@ static struct platform_driver wm831x_boostp_driver = {
|
|||
.remove = __devexit_p(wm831x_boostp_remove),
|
||||
.driver = {
|
||||
.name = "wm831x-boostp",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -979,6 +988,8 @@ static __devexit int wm831x_epe_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
regulator_unregister(dcdc->regulator);
|
||||
kfree(dcdc);
|
||||
|
||||
|
@ -990,6 +1001,7 @@ static struct platform_driver wm831x_epe_driver = {
|
|||
.remove = __devexit_p(wm831x_epe_remove),
|
||||
.driver = {
|
||||
.name = "wm831x-epe",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -222,6 +222,8 @@ static __devexit int wm831x_isink_remove(struct platform_device *pdev)
|
|||
struct wm831x_isink *isink = platform_get_drvdata(pdev);
|
||||
struct wm831x *wm831x = isink->wm831x;
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
wm831x_free_irq(wm831x, platform_get_irq(pdev, 0), isink);
|
||||
|
||||
regulator_unregister(isink->regulator);
|
||||
|
@ -235,6 +237,7 @@ static struct platform_driver wm831x_isink_driver = {
|
|||
.remove = __devexit_p(wm831x_isink_remove),
|
||||
.driver = {
|
||||
.name = "wm831x-isink",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -371,6 +371,8 @@ static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
|
|||
struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
|
||||
struct wm831x *wm831x = ldo->wm831x;
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), ldo);
|
||||
regulator_unregister(ldo->regulator);
|
||||
kfree(ldo);
|
||||
|
@ -383,6 +385,7 @@ static struct platform_driver wm831x_gp_ldo_driver = {
|
|||
.remove = __devexit_p(wm831x_gp_ldo_remove),
|
||||
.driver = {
|
||||
.name = "wm831x-ldo",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -640,6 +643,7 @@ static struct platform_driver wm831x_aldo_driver = {
|
|||
.remove = __devexit_p(wm831x_aldo_remove),
|
||||
.driver = {
|
||||
.name = "wm831x-aldo",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -811,6 +815,7 @@ static struct platform_driver wm831x_alive_ldo_driver = {
|
|||
.remove = __devexit_p(wm831x_alive_ldo_remove),
|
||||
.driver = {
|
||||
.name = "wm831x-alive-ldo",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -290,6 +290,51 @@ static int wm8350_isink_is_enabled(struct regulator_dev *rdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int wm8350_isink_enable_time(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
|
||||
int isink = rdev_get_id(rdev);
|
||||
int reg;
|
||||
|
||||
switch (isink) {
|
||||
case WM8350_ISINK_A:
|
||||
reg = wm8350_reg_read(wm8350, WM8350_CSA_FLASH_CONTROL);
|
||||
break;
|
||||
case WM8350_ISINK_B:
|
||||
reg = wm8350_reg_read(wm8350, WM8350_CSB_FLASH_CONTROL);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (reg & WM8350_CS1_FLASH_MODE) {
|
||||
switch (reg & WM8350_CS1_ON_RAMP_MASK) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return 1950;
|
||||
case 2:
|
||||
return 3910;
|
||||
case 3:
|
||||
return 7800;
|
||||
}
|
||||
} else {
|
||||
switch (reg & WM8350_CS1_ON_RAMP_MASK) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return 250000;
|
||||
case 2:
|
||||
return 500000;
|
||||
case 3:
|
||||
return 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode,
|
||||
u16 trigger, u16 duration, u16 on_ramp, u16 off_ramp,
|
||||
u16 drive)
|
||||
|
@ -1221,6 +1266,7 @@ static struct regulator_ops wm8350_isink_ops = {
|
|||
.enable = wm8350_isink_enable,
|
||||
.disable = wm8350_isink_disable,
|
||||
.is_enabled = wm8350_isink_is_enabled,
|
||||
.enable_time = wm8350_isink_enable_time,
|
||||
};
|
||||
|
||||
static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
|
||||
|
|
|
@ -317,14 +317,17 @@ static struct regulator_desc regulators[] = {
|
|||
|
||||
static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wm8400 *wm8400 = container_of(pdev, struct wm8400, regulators[pdev->id]);
|
||||
struct regulator_dev *rdev;
|
||||
|
||||
rdev = regulator_register(®ulators[pdev->id], &pdev->dev,
|
||||
pdev->dev.platform_data, dev_get_drvdata(&pdev->dev));
|
||||
pdev->dev.platform_data, wm8400);
|
||||
|
||||
if (IS_ERR(rdev))
|
||||
return PTR_ERR(rdev);
|
||||
|
||||
platform_set_drvdata(pdev, rdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -332,6 +335,7 @@ static int __devexit wm8400_regulator_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct regulator_dev *rdev = platform_get_drvdata(pdev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
regulator_unregister(rdev);
|
||||
|
||||
return 0;
|
||||
|
@ -370,7 +374,6 @@ int wm8400_register_regulator(struct device *dev, int reg,
|
|||
wm8400->regulators[reg].id = reg;
|
||||
wm8400->regulators[reg].dev.parent = dev;
|
||||
wm8400->regulators[reg].dev.platform_data = initdata;
|
||||
dev_set_drvdata(&wm8400->regulators[reg].dev, wm8400);
|
||||
|
||||
return platform_device_register(&wm8400->regulators[reg]);
|
||||
}
|
||||
|
|
307
drivers/regulator/wm8994-regulator.c
Normal file
307
drivers/regulator/wm8994-regulator.c
Normal file
|
@ -0,0 +1,307 @@
|
|||
/*
|
||||
* wm8994-regulator.c -- Regulator driver for the WM8994
|
||||
*
|
||||
* Copyright 2009 Wolfson Microelectronics PLC.
|
||||
*
|
||||
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <linux/mfd/wm8994/core.h>
|
||||
#include <linux/mfd/wm8994/registers.h>
|
||||
#include <linux/mfd/wm8994/pdata.h>
|
||||
|
||||
struct wm8994_ldo {
|
||||
int enable;
|
||||
bool is_enabled;
|
||||
struct regulator_dev *regulator;
|
||||
struct wm8994 *wm8994;
|
||||
};
|
||||
|
||||
#define WM8994_LDO1_MAX_SELECTOR 0x7
|
||||
#define WM8994_LDO2_MAX_SELECTOR 0x3
|
||||
|
||||
static int wm8994_ldo_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
|
||||
/* If we have no soft control assume that the LDO is always enabled. */
|
||||
if (!ldo->enable)
|
||||
return 0;
|
||||
|
||||
gpio_set_value(ldo->enable, 1);
|
||||
ldo->is_enabled = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8994_ldo_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
|
||||
/* If we have no soft control assume that the LDO is always enabled. */
|
||||
if (!ldo->enable)
|
||||
return -EINVAL;
|
||||
|
||||
gpio_set_value(ldo->enable, 0);
|
||||
ldo->is_enabled = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm8994_ldo_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
|
||||
return ldo->is_enabled;
|
||||
}
|
||||
|
||||
static int wm8994_ldo_enable_time(struct regulator_dev *rdev)
|
||||
{
|
||||
/* 3ms is fairly conservative but this shouldn't be too performance
|
||||
* critical; can be tweaked per-system if required. */
|
||||
return 3000;
|
||||
}
|
||||
|
||||
static int wm8994_ldo1_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned int selector)
|
||||
{
|
||||
if (selector > WM8994_LDO1_MAX_SELECTOR)
|
||||
return -EINVAL;
|
||||
|
||||
return (selector * 100000) + 2400000;
|
||||
}
|
||||
|
||||
static int wm8994_ldo1_get_voltage(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
int val;
|
||||
|
||||
val = wm8994_reg_read(ldo->wm8994, WM8994_LDO_1);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
val = (val & WM8994_LDO1_VSEL_MASK) >> WM8994_LDO1_VSEL_SHIFT;
|
||||
|
||||
return wm8994_ldo1_list_voltage(rdev, val);
|
||||
}
|
||||
|
||||
static int wm8994_ldo1_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
int selector, v;
|
||||
|
||||
selector = (min_uV - 2400000) / 100000;
|
||||
v = wm8994_ldo1_list_voltage(rdev, selector);
|
||||
if (v < 0 || v > max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
selector <<= WM8994_LDO1_VSEL_SHIFT;
|
||||
|
||||
return wm8994_set_bits(ldo->wm8994, WM8994_LDO_1,
|
||||
WM8994_LDO1_VSEL_MASK, selector);
|
||||
}
|
||||
|
||||
static struct regulator_ops wm8994_ldo1_ops = {
|
||||
.enable = wm8994_ldo_enable,
|
||||
.disable = wm8994_ldo_disable,
|
||||
.is_enabled = wm8994_ldo_is_enabled,
|
||||
.enable_time = wm8994_ldo_enable_time,
|
||||
|
||||
.list_voltage = wm8994_ldo1_list_voltage,
|
||||
.get_voltage = wm8994_ldo1_get_voltage,
|
||||
.set_voltage = wm8994_ldo1_set_voltage,
|
||||
};
|
||||
|
||||
static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned int selector)
|
||||
{
|
||||
if (selector > WM8994_LDO2_MAX_SELECTOR)
|
||||
return -EINVAL;
|
||||
|
||||
return (selector * 100000) + 900000;
|
||||
}
|
||||
|
||||
static int wm8994_ldo2_get_voltage(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
int val;
|
||||
|
||||
val = wm8994_reg_read(ldo->wm8994, WM8994_LDO_2);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
val = (val & WM8994_LDO2_VSEL_MASK) >> WM8994_LDO2_VSEL_SHIFT;
|
||||
|
||||
return wm8994_ldo2_list_voltage(rdev, val);
|
||||
}
|
||||
|
||||
static int wm8994_ldo2_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
int selector, v;
|
||||
|
||||
selector = (min_uV - 900000) / 100000;
|
||||
v = wm8994_ldo2_list_voltage(rdev, selector);
|
||||
if (v < 0 || v > max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
selector <<= WM8994_LDO2_VSEL_SHIFT;
|
||||
|
||||
return wm8994_set_bits(ldo->wm8994, WM8994_LDO_2,
|
||||
WM8994_LDO2_VSEL_MASK, selector);
|
||||
}
|
||||
|
||||
static struct regulator_ops wm8994_ldo2_ops = {
|
||||
.enable = wm8994_ldo_enable,
|
||||
.disable = wm8994_ldo_disable,
|
||||
.is_enabled = wm8994_ldo_is_enabled,
|
||||
.enable_time = wm8994_ldo_enable_time,
|
||||
|
||||
.list_voltage = wm8994_ldo2_list_voltage,
|
||||
.get_voltage = wm8994_ldo2_get_voltage,
|
||||
.set_voltage = wm8994_ldo2_set_voltage,
|
||||
};
|
||||
|
||||
static struct regulator_desc wm8994_ldo_desc[] = {
|
||||
{
|
||||
.name = "LDO1",
|
||||
.id = 1,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = WM8994_LDO1_MAX_SELECTOR + 1,
|
||||
.ops = &wm8994_ldo1_ops,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
.name = "LDO2",
|
||||
.id = 2,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = WM8994_LDO2_MAX_SELECTOR + 1,
|
||||
.ops = &wm8994_ldo2_ops,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static __devinit int wm8994_ldo_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct wm8994_pdata *pdata = wm8994->dev->platform_data;
|
||||
int id = pdev->id % ARRAY_SIZE(pdata->ldo);
|
||||
struct wm8994_ldo *ldo;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
|
||||
|
||||
if (!pdata)
|
||||
return -ENODEV;
|
||||
|
||||
ldo = kzalloc(sizeof(struct wm8994_ldo), GFP_KERNEL);
|
||||
if (ldo == NULL) {
|
||||
dev_err(&pdev->dev, "Unable to allocate private data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ldo->wm8994 = wm8994;
|
||||
|
||||
ldo->is_enabled = true;
|
||||
|
||||
if (pdata->ldo[id].enable && gpio_is_valid(pdata->ldo[id].enable)) {
|
||||
ldo->enable = pdata->ldo[id].enable;
|
||||
|
||||
ret = gpio_request(ldo->enable, "WM8994 LDO enable");
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to get enable GPIO: %d\n",
|
||||
ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = gpio_direction_output(ldo->enable, ldo->is_enabled);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to set GPIO up: %d\n",
|
||||
ret);
|
||||
goto err_gpio;
|
||||
}
|
||||
}
|
||||
|
||||
ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &pdev->dev,
|
||||
pdata->ldo[id].init_data, ldo);
|
||||
if (IS_ERR(ldo->regulator)) {
|
||||
ret = PTR_ERR(ldo->regulator);
|
||||
dev_err(wm8994->dev, "Failed to register LDO%d: %d\n",
|
||||
id + 1, ret);
|
||||
goto err_gpio;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, ldo);
|
||||
|
||||
return 0;
|
||||
|
||||
err_gpio:
|
||||
if (gpio_is_valid(ldo->enable))
|
||||
gpio_free(ldo->enable);
|
||||
err:
|
||||
kfree(ldo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct wm8994_ldo *ldo = platform_get_drvdata(pdev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
regulator_unregister(ldo->regulator);
|
||||
if (gpio_is_valid(ldo->enable))
|
||||
gpio_free(ldo->enable);
|
||||
kfree(ldo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver wm8994_ldo_driver = {
|
||||
.probe = wm8994_ldo_probe,
|
||||
.remove = __devexit_p(wm8994_ldo_remove),
|
||||
.driver = {
|
||||
.name = "wm8994-ldo",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init wm8994_ldo_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&wm8994_ldo_driver);
|
||||
if (ret != 0)
|
||||
pr_err("Failed to register Wm8994 GP LDO driver: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
subsys_initcall(wm8994_ldo_init);
|
||||
|
||||
static void __exit wm8994_ldo_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&wm8994_ldo_driver);
|
||||
}
|
||||
module_exit(wm8994_ldo_exit);
|
||||
|
||||
/* Module information */
|
||||
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
|
||||
MODULE_DESCRIPTION("WM8994 LDO driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:wm8994-ldo");
|
|
@ -108,6 +108,8 @@ int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode,
|
|||
#define MC13783_REGU_V2 28
|
||||
#define MC13783_REGU_V3 29
|
||||
#define MC13783_REGU_V4 30
|
||||
#define MC13783_REGU_PWGT1SPI 31
|
||||
#define MC13783_REGU_PWGT2SPI 32
|
||||
|
||||
#define MC13783_IRQ_ADCDONE 0
|
||||
#define MC13783_IRQ_ADCBISDONE 1
|
||||
|
|
|
@ -89,8 +89,9 @@
|
|||
* REGULATION_OUT Regulator output is out of regulation.
|
||||
* FAIL Regulator output has failed.
|
||||
* OVER_TEMP Regulator over temp.
|
||||
* FORCE_DISABLE Regulator shut down by software.
|
||||
* FORCE_DISABLE Regulator forcibly shut down by software.
|
||||
* VOLTAGE_CHANGE Regulator voltage changed.
|
||||
* DISABLE Regulator was disabled.
|
||||
*
|
||||
* NOTE: These events can be OR'ed together when passed into handler.
|
||||
*/
|
||||
|
@ -102,6 +103,7 @@
|
|||
#define REGULATOR_EVENT_OVER_TEMP 0x10
|
||||
#define REGULATOR_EVENT_FORCE_DISABLE 0x20
|
||||
#define REGULATOR_EVENT_VOLTAGE_CHANGE 0x40
|
||||
#define REGULATOR_EVENT_DISABLE 0x80
|
||||
|
||||
struct regulator;
|
||||
|
||||
|
|
|
@ -58,6 +58,9 @@ enum regulator_status {
|
|||
* @get_optimum_mode: Get the most efficient operating mode for the regulator
|
||||
* when running with the specified parameters.
|
||||
*
|
||||
* @enable_time: Time taken for the regulator voltage output voltage to
|
||||
* stabalise after being enabled, in microseconds.
|
||||
*
|
||||
* @set_suspend_voltage: Set the voltage for the regulator when the system
|
||||
* is suspended.
|
||||
* @set_suspend_enable: Mark the regulator as enabled when the system is
|
||||
|
@ -93,6 +96,9 @@ struct regulator_ops {
|
|||
int (*set_mode) (struct regulator_dev *, unsigned int mode);
|
||||
unsigned int (*get_mode) (struct regulator_dev *);
|
||||
|
||||
/* Time taken to enable the regulator */
|
||||
int (*enable_time) (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.
|
||||
|
|
|
@ -25,6 +25,7 @@ struct regulator_init_data;
|
|||
* @microvolts: Output voltage of regulator
|
||||
* @gpio: GPIO to use for enable control
|
||||
* set to -EINVAL if not used
|
||||
* @startup_delay: Start-up time in microseconds
|
||||
* @enable_high: Polarity of enable GPIO
|
||||
* 1 = Active high, 0 = Active low
|
||||
* @enabled_at_boot: Whether regulator has been enabled at
|
||||
|
@ -41,6 +42,7 @@ struct fixed_voltage_config {
|
|||
const char *supply_name;
|
||||
int microvolts;
|
||||
int gpio;
|
||||
unsigned startup_delay;
|
||||
unsigned enable_high:1;
|
||||
unsigned enabled_at_boot:1;
|
||||
struct regulator_init_data *init_data;
|
||||
|
|
44
include/linux/regulator/max8649.h
Normal file
44
include/linux/regulator/max8649.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Interface of Maxim max8649
|
||||
*
|
||||
* Copyright (C) 2009-2010 Marvell International Ltd.
|
||||
* Haojian Zhuang <haojian.zhuang@marvell.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_REGULATOR_MAX8649_H
|
||||
#define __LINUX_REGULATOR_MAX8649_H
|
||||
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
enum {
|
||||
MAX8649_EXTCLK_26MHZ = 0,
|
||||
MAX8649_EXTCLK_13MHZ,
|
||||
MAX8649_EXTCLK_19MHZ, /* 19.2MHz */
|
||||
};
|
||||
|
||||
enum {
|
||||
MAX8649_RAMP_32MV = 0,
|
||||
MAX8649_RAMP_16MV,
|
||||
MAX8649_RAMP_8MV,
|
||||
MAX8649_RAMP_4MV,
|
||||
MAX8649_RAMP_2MV,
|
||||
MAX8649_RAMP_1MV,
|
||||
MAX8649_RAMP_0_5MV,
|
||||
MAX8649_RAMP_0_25MV,
|
||||
};
|
||||
|
||||
struct max8649_platform_data {
|
||||
struct regulator_init_data *regulator;
|
||||
|
||||
unsigned mode:2; /* bit[1:0] = VID1,VID0 */
|
||||
unsigned extclk_freq:2;
|
||||
unsigned extclk:1;
|
||||
unsigned ramp_timing:3;
|
||||
unsigned ramp_down:1;
|
||||
};
|
||||
|
||||
#endif /* __LINUX_REGULATOR_MAX8649_H */
|
Loading…
Reference in a new issue