Commit c8bf9fec authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents a2e28fc1 1ad02bbc
......@@ -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 @@ overflow_err:
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(&regulator_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(&regulator_class);
ret = class_register(&regulator_class);
regulator_dummy_init();
return ret;
}
/* init early to allow our consumers to complete system booting */
......
/*
* 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;
}
}
/*
* 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 @@ err:
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(&regulators[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(&regulators[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;
i2c_set_clientdata(i2c, NULL);
for (i = 0; i < lp3971->num_regulators; i++)
if (lp3971->rdev[i])
regulator_unregister(lp3971->rdev[i]);
regulator_unregister(lp3971->rdev[i]);
kfree(lp3971->rdev);
i2c_set_clientdata(i2c, NULL);
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 @@ out:
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,
};
......
This diff is collapsed.
......@@ -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 @@ out:
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,
};
......
This diff is collapsed.
......@@ -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,
&regulator_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, &regulator_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(&regulator_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(&regulators[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]);
}
......
/*
* 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;
......
/*
* 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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment