提交 f7fc06e3 编写于 作者: L 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: (42 commits)
  regulator: Fix _regulator_get_voltage if get_voltage callback is NULL
  USB: TWL6025 allow different regulator name
  REGULATOR: TWL6025: add support to twl-regulator
  regulator: twl6030: do not write to _GRP for regulator disable
  regulator: twl6030: do not write to _GRP for regulator enable
  TPS65911: Comparator: Add comparator driver
  TPS65911: Add support for added GPIO lines
  GPIO: TPS65910: Move driver to drivers/gpio/
  TPS65911: Add new irq definitions
  regulator: tps65911: Add new chip version
  MFD: TPS65910: Add support for TPS65911 device
  regulator: Fix off-by-one value range checking for mc13xxx_regulator_get_voltage
  regulator: mc13892: Fix voltage unit in test case.
  regulator: Remove MAX8997_REG_BUCK1DVS/MAX8997_REG_BUCK2DVS/MAX8997_REG_BUCK5DVS macros
  mfd: Fix off-by-one value range checking for tps65910_i2c_write
  regulator: Only apply voltage constraints from consumers that set them
  regulator: If we can't configure optimum mode we're always in the best one
  regulator: max8997: remove useless code
  regulator: Fix memory leak in max8998_pmic_probe failure path
  regulator: Fix desc_id for tps65023/6507x/65910
  ...
...@@ -53,11 +53,11 @@ static struct regulator_init_data regulator1_data = { ...@@ -53,11 +53,11 @@ static struct regulator_init_data regulator1_data = {
Regulator-1 supplies power to Regulator-2. This relationship must be registered Regulator-1 supplies power to Regulator-2. This relationship must be registered
with the core so that Regulator-1 is also enabled when Consumer A enables its with the core so that Regulator-1 is also enabled when Consumer A enables its
supply (Regulator-2). The supply regulator is set by the supply_regulator_dev supply (Regulator-2). The supply regulator is set by the supply_regulator
field below:- field below:-
static struct regulator_init_data regulator2_data = { static struct regulator_init_data regulator2_data = {
.supply_regulator_dev = &platform_regulator1_device.dev, .supply_regulator = "regulator_name",
.constraints = { .constraints = {
.min_uV = 1800000, .min_uV = 1800000,
.max_uV = 2000000, .max_uV = 2000000,
......
...@@ -424,4 +424,11 @@ config AB8500_GPIO ...@@ -424,4 +424,11 @@ config AB8500_GPIO
depends on AB8500_CORE && BROKEN depends on AB8500_CORE && BROKEN
help help
Select this to enable the AB8500 IC GPIO driver Select this to enable the AB8500 IC GPIO driver
config GPIO_TPS65910
bool "TPS65910 GPIO"
depends on MFD_TPS65910
help
Select this option to enable GPIO driver for the TPS65910
chip family.
endif endif
...@@ -40,3 +40,4 @@ obj-$(CONFIG_GPIO_SX150X) += sx150x.o ...@@ -40,3 +40,4 @@ obj-$(CONFIG_GPIO_SX150X) += sx150x.o
obj-$(CONFIG_GPIO_VX855) += vx855_gpio.o obj-$(CONFIG_GPIO_VX855) += vx855_gpio.o
obj-$(CONFIG_GPIO_ML_IOH) += ml_ioh_gpio.o obj-$(CONFIG_GPIO_ML_IOH) += ml_ioh_gpio.o
obj-$(CONFIG_AB8500_GPIO) += ab8500-gpio.o obj-$(CONFIG_AB8500_GPIO) += ab8500-gpio.o
obj-$(CONFIG_GPIO_TPS65910) += tps65910-gpio.o
/*
* tps65910-gpio.c -- TI TPS6591x
*
* Copyright 2010 Texas Instruments Inc.
*
* Author: Graeme Gregory <gg@slimlogic.co.uk>
* Author: Jorge Eduardo Candelaria jedu@slimlogic.co.uk>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/mfd/tps65910.h>
static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset)
{
struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
uint8_t val;
tps65910->read(tps65910, TPS65910_GPIO0 + offset, 1, &val);
if (val & GPIO_STS_MASK)
return 1;
return 0;
}
static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset,
int value)
{
struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
if (value)
tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
GPIO_SET_MASK);
else
tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
GPIO_SET_MASK);
}
static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset,
int value)
{
struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
/* Set the initial value */
tps65910_gpio_set(gc, 0, value);
return tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
GPIO_CFG_MASK);
}
static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset)
{
struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
return tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
GPIO_CFG_MASK);
}
void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
{
int ret;
if (!gpio_base)
return;
tps65910->gpio.owner = THIS_MODULE;
tps65910->gpio.label = tps65910->i2c_client->name;
tps65910->gpio.dev = tps65910->dev;
tps65910->gpio.base = gpio_base;
switch(tps65910_chip_id(tps65910)) {
case TPS65910:
tps65910->gpio.ngpio = 6;
case TPS65911:
tps65910->gpio.ngpio = 9;
default:
return;
}
tps65910->gpio.can_sleep = 1;
tps65910->gpio.direction_input = tps65910_gpio_input;
tps65910->gpio.direction_output = tps65910_gpio_output;
tps65910->gpio.set = tps65910_gpio_set;
tps65910->gpio.get = tps65910_gpio_get;
ret = gpiochip_add(&tps65910->gpio);
if (ret)
dev_warn(tps65910->dev, "GPIO registration failed: %d\n", ret);
}
...@@ -719,6 +719,15 @@ config MFD_PM8XXX_IRQ ...@@ -719,6 +719,15 @@ config MFD_PM8XXX_IRQ
This is required to use certain other PM 8xxx features, such as GPIO This is required to use certain other PM 8xxx features, such as GPIO
and MPP. and MPP.
config MFD_TPS65910
bool "TPS65910 Power Management chip"
depends on I2C=y
select MFD_CORE
select GPIO_TPS65910
help
if you say yes here you get support for the TPS65910 series of
Power Management chips.
endif # MFD_SUPPORT endif # MFD_SUPPORT
menu "Multimedia Capabilities Port drivers" menu "Multimedia Capabilities Port drivers"
......
...@@ -93,3 +93,4 @@ obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o ...@@ -93,3 +93,4 @@ obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o
obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o
obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o
obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o
obj-$(CONFIG_MFD_TPS65910) += tps65910.o tps65910-irq.o
/*
* tps65910-irq.c -- TI TPS6591x
*
* Copyright 2010 Texas Instruments Inc.
*
* Author: Graeme Gregory <gg@slimlogic.co.uk>
* Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/bug.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/mfd/tps65910.h>
static inline int irq_to_tps65910_irq(struct tps65910 *tps65910,
int irq)
{
return (irq - tps65910->irq_base);
}
/*
* This is a threaded IRQ handler so can access I2C/SPI. Since all
* interrupts are clear on read the IRQ line will be reasserted and
* the physical IRQ will be handled again if another interrupt is
* asserted while we run - in the normal course of events this is a
* rare occurrence so we save I2C/SPI reads. We're also assuming that
* it's rare to get lots of interrupts firing simultaneously so try to
* minimise I/O.
*/
static irqreturn_t tps65910_irq(int irq, void *irq_data)
{
struct tps65910 *tps65910 = irq_data;
u32 irq_sts;
u32 irq_mask;
u8 reg;
int i;
tps65910->read(tps65910, TPS65910_INT_STS, 1, &reg);
irq_sts = reg;
tps65910->read(tps65910, TPS65910_INT_STS2, 1, &reg);
irq_sts |= reg << 8;
switch (tps65910_chip_id(tps65910)) {
case TPS65911:
tps65910->read(tps65910, TPS65910_INT_STS3, 1, &reg);
irq_sts |= reg << 16;
}
tps65910->read(tps65910, TPS65910_INT_MSK, 1, &reg);
irq_mask = reg;
tps65910->read(tps65910, TPS65910_INT_MSK2, 1, &reg);
irq_mask |= reg << 8;
switch (tps65910_chip_id(tps65910)) {
case TPS65911:
tps65910->read(tps65910, TPS65910_INT_MSK3, 1, &reg);
irq_mask |= reg << 16;
}
irq_sts &= ~irq_mask;
if (!irq_sts)
return IRQ_NONE;
for (i = 0; i < tps65910->irq_num; i++) {
if (!(irq_sts & (1 << i)))
continue;
handle_nested_irq(tps65910->irq_base + i);
}
/* Write the STS register back to clear IRQs we handled */
reg = irq_sts & 0xFF;
irq_sts >>= 8;
tps65910->write(tps65910, TPS65910_INT_STS, 1, &reg);
reg = irq_sts & 0xFF;
tps65910->write(tps65910, TPS65910_INT_STS2, 1, &reg);
switch (tps65910_chip_id(tps65910)) {
case TPS65911:
reg = irq_sts >> 8;
tps65910->write(tps65910, TPS65910_INT_STS3, 1, &reg);
}
return IRQ_HANDLED;
}
static void tps65910_irq_lock(struct irq_data *data)
{
struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
mutex_lock(&tps65910->irq_lock);
}
static void tps65910_irq_sync_unlock(struct irq_data *data)
{
struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
u32 reg_mask;
u8 reg;
tps65910->read(tps65910, TPS65910_INT_MSK, 1, &reg);
reg_mask = reg;
tps65910->read(tps65910, TPS65910_INT_MSK2, 1, &reg);
reg_mask |= reg << 8;
switch (tps65910_chip_id(tps65910)) {
case TPS65911:
tps65910->read(tps65910, TPS65910_INT_MSK3, 1, &reg);
reg_mask |= reg << 16;
}
if (tps65910->irq_mask != reg_mask) {
reg = tps65910->irq_mask & 0xFF;
tps65910->write(tps65910, TPS65910_INT_MSK, 1, &reg);
reg = tps65910->irq_mask >> 8 & 0xFF;
tps65910->write(tps65910, TPS65910_INT_MSK2, 1, &reg);
switch (tps65910_chip_id(tps65910)) {
case TPS65911:
reg = tps65910->irq_mask >> 16;
tps65910->write(tps65910, TPS65910_INT_MSK3, 1, &reg);
}
}
mutex_unlock(&tps65910->irq_lock);
}
static void tps65910_irq_enable(struct irq_data *data)
{
struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
tps65910->irq_mask &= ~( 1 << irq_to_tps65910_irq(tps65910, data->irq));
}
static void tps65910_irq_disable(struct irq_data *data)
{
struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
tps65910->irq_mask |= ( 1 << irq_to_tps65910_irq(tps65910, data->irq));
}
static struct irq_chip tps65910_irq_chip = {
.name = "tps65910",
.irq_bus_lock = tps65910_irq_lock,
.irq_bus_sync_unlock = tps65910_irq_sync_unlock,
.irq_disable = tps65910_irq_disable,
.irq_enable = tps65910_irq_enable,
};
int tps65910_irq_init(struct tps65910 *tps65910, int irq,
struct tps65910_platform_data *pdata)
{
int ret, cur_irq;
int flags = IRQF_ONESHOT;
if (!irq) {
dev_warn(tps65910->dev, "No interrupt support, no core IRQ\n");
return -EINVAL;
}
if (!pdata || !pdata->irq_base) {
dev_warn(tps65910->dev, "No interrupt support, no IRQ base\n");
return -EINVAL;
}
tps65910->irq_mask = 0xFFFFFF;
mutex_init(&tps65910->irq_lock);
tps65910->chip_irq = irq;
tps65910->irq_base = pdata->irq_base;
switch (tps65910_chip_id(tps65910)) {
case TPS65910:
tps65910->irq_num = TPS65910_NUM_IRQ;
case TPS65911:
tps65910->irq_num = TPS65911_NUM_IRQ;
}
/* Register with genirq */
for (cur_irq = tps65910->irq_base;
cur_irq < tps65910->irq_num + tps65910->irq_base;
cur_irq++) {
irq_set_chip_data(cur_irq, tps65910);
irq_set_chip_and_handler(cur_irq, &tps65910_irq_chip,
handle_edge_irq);
irq_set_nested_thread(cur_irq, 1);
/* ARM needs us to explicitly flag the IRQ as valid
* and will set them noprobe when we do so. */
#ifdef CONFIG_ARM
set_irq_flags(cur_irq, IRQF_VALID);
#else
irq_set_noprobe(cur_irq);
#endif
}
ret = request_threaded_irq(irq, NULL, tps65910_irq, flags,
"tps65910", tps65910);
irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
if (ret != 0)
dev_err(tps65910->dev, "Failed to request IRQ: %d\n", ret);
return ret;
}
int tps65910_irq_exit(struct tps65910 *tps65910)
{
free_irq(tps65910->chip_irq, tps65910);
return 0;
}
/*
* tps65910.c -- TI TPS6591x
*
* Copyright 2010 Texas Instruments Inc.
*
* Author: Graeme Gregory <gg@slimlogic.co.uk>
* Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License 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/slab.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps65910.h>
static struct mfd_cell tps65910s[] = {
{
.name = "tps65910-pmic",
},
{
.name = "tps65910-rtc",
},
{
.name = "tps65910-power",
},
};
static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg,
int bytes, void *dest)
{
struct i2c_client *i2c = tps65910->i2c_client;
struct i2c_msg xfer[2];
int ret;
/* Write register */
xfer[0].addr = i2c->addr;
xfer[0].flags = 0;
xfer[0].len = 1;
xfer[0].buf = &reg;
/* Read data */
xfer[1].addr = i2c->addr;
xfer[1].flags = I2C_M_RD;
xfer[1].len = bytes;
xfer[1].buf = dest;
ret = i2c_transfer(i2c->adapter, xfer, 2);
if (ret == 2)
ret = 0;
else if (ret >= 0)
ret = -EIO;
return ret;
}
static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg,
int bytes, void *src)
{
struct i2c_client *i2c = tps65910->i2c_client;
/* we add 1 byte for device register */
u8 msg[TPS65910_MAX_REGISTER + 1];
int ret;
if (bytes > TPS65910_MAX_REGISTER)
return -EINVAL;
msg[0] = reg;
memcpy(&msg[1], src, bytes);
ret = i2c_master_send(i2c, msg, bytes + 1);
if (ret < 0)
return ret;
if (ret != bytes + 1)
return -EIO;
return 0;
}
int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask)
{
u8 data;
int err;
mutex_lock(&tps65910->io_mutex);
err = tps65910_i2c_read(tps65910, reg, 1, &data);
if (err) {
dev_err(tps65910->dev, "read from reg %x failed\n", reg);
goto out;
}
data |= mask;
err = tps65910_i2c_write(tps65910, reg, 1, &data);
if (err)
dev_err(tps65910->dev, "write to reg %x failed\n", reg);
out:
mutex_unlock(&tps65910->io_mutex);
return err;
}
EXPORT_SYMBOL_GPL(tps65910_set_bits);
int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask)
{
u8 data;
int err;
mutex_lock(&tps65910->io_mutex);
err = tps65910_i2c_read(tps65910, reg, 1, &data);
if (err) {
dev_err(tps65910->dev, "read from reg %x failed\n", reg);
goto out;
}
data &= mask;
err = tps65910_i2c_write(tps65910, reg, 1, &data);
if (err)
dev_err(tps65910->dev, "write to reg %x failed\n", reg);
out:
mutex_unlock(&tps65910->io_mutex);
return err;
}
EXPORT_SYMBOL_GPL(tps65910_clear_bits);
static int tps65910_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct tps65910 *tps65910;
struct tps65910_board *pmic_plat_data;
struct tps65910_platform_data *init_data;
int ret = 0;
pmic_plat_data = dev_get_platdata(&i2c->dev);
if (!pmic_plat_data)
return -EINVAL;
init_data = kzalloc(sizeof(struct tps65910_platform_data), GFP_KERNEL);
if (init_data == NULL)
return -ENOMEM;
init_data->irq = pmic_plat_data->irq;
init_data->irq_base = pmic_plat_data->irq;
tps65910 = kzalloc(sizeof(struct tps65910), GFP_KERNEL);
if (tps65910 == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, tps65910);
tps65910->dev = &i2c->dev;
tps65910->i2c_client = i2c;
tps65910->id = id->driver_data;
tps65910->read = tps65910_i2c_read;
tps65910->write = tps65910_i2c_write;
mutex_init(&tps65910->io_mutex);
ret = mfd_add_devices(tps65910->dev, -1,
tps65910s, ARRAY_SIZE(tps65910s),
NULL, 0);
if (ret < 0)
goto err;
tps65910_gpio_init(tps65910, pmic_plat_data->gpio_base);
ret = tps65910_irq_init(tps65910, init_data->irq, init_data);
if (ret < 0)
goto err;
return ret;
err:
mfd_remove_devices(tps65910->dev);
kfree(tps65910);
return ret;
}
static int tps65910_i2c_remove(struct i2c_client *i2c)
{
struct tps65910 *tps65910 = i2c_get_clientdata(i2c);
mfd_remove_devices(tps65910->dev);
kfree(tps65910);
return 0;
}
static const struct i2c_device_id tps65910_i2c_id[] = {
{ "tps65910", TPS65910 },
{ "tps65911", TPS65911 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tps65910_i2c_id);
static struct i2c_driver tps65910_i2c_driver = {
.driver = {
.name = "tps65910",
.owner = THIS_MODULE,
},
.probe = tps65910_i2c_probe,
.remove = tps65910_i2c_remove,
.id_table = tps65910_i2c_id,
};
static int __init tps65910_i2c_init(void)
{
return i2c_add_driver(&tps65910_i2c_driver);
}
/* init early so consumer devices can complete system boot */
subsys_initcall(tps65910_i2c_init);
static void __exit tps65910_i2c_exit(void)
{
i2c_del_driver(&tps65910_i2c_driver);
}
module_exit(tps65910_i2c_exit);
MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
MODULE_AUTHOR("Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>");
MODULE_DESCRIPTION("TPS6591x chip family multi-function driver");
MODULE_LICENSE("GPL");
/*
* tps65910.c -- TI TPS6591x
*
* Copyright 2010 Texas Instruments Inc.
*
* Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/debugfs.h>
#include <linux/gpio.h>
#include <linux/mfd/tps65910.h>
#define COMP 0
#define COMP1 1
#define COMP2 2
/* Comparator 1 voltage selection table in milivolts */
static const u16 COMP_VSEL_TABLE[] = {
0, 2500, 2500, 2500, 2500, 2550, 2600, 2650,
2700, 2750, 2800, 2850, 2900, 2950, 3000, 3050,
3100, 3150, 3200, 3250, 3300, 3350, 3400, 3450,
3500,
};
struct comparator {
const char *name;
int reg;
int uV_max;
const u16 *vsel_table;
};
static struct comparator tps_comparators[] = {
{
.name = "COMP1",
.reg = TPS65911_VMBCH,
.uV_max = 3500,
.vsel_table = COMP_VSEL_TABLE,
},
{
.name = "COMP2",
.reg = TPS65911_VMBCH2,
.uV_max = 3500,
.vsel_table = COMP_VSEL_TABLE,
},
};
static int comp_threshold_set(struct tps65910 *tps65910, int id, int voltage)
{
struct comparator tps_comp = tps_comparators[id];
int curr_voltage = 0;
int ret;
u8 index = 0, val;
if (id == COMP)
return 0;
while (curr_voltage < tps_comp.uV_max) {
curr_voltage = tps_comp.vsel_table[index];
if (curr_voltage >= voltage)
break;
else if (curr_voltage < voltage)
index ++;
}
if (curr_voltage > tps_comp.uV_max)
return -EINVAL;
val = index << 1;
ret = tps65910->write(tps65910, tps_comp.reg, 1, &val);
return ret;
}
static int comp_threshold_get(struct tps65910 *tps65910, int id)
{
struct comparator tps_comp = tps_comparators[id];
int ret;
u8 val;
if (id == COMP)
return 0;
ret = tps65910->read(tps65910, tps_comp.reg, 1, &val);
if (ret < 0)
return ret;
val >>= 1;
return tps_comp.vsel_table[val];
}
static ssize_t comp_threshold_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct tps65910 *tps65910 = dev_get_drvdata(dev->parent);
struct attribute comp_attr = attr->attr;
int id, uVolt;
if (!strcmp(comp_attr.name, "comp1_threshold"))
id = COMP1;
else if (!strcmp(comp_attr.name, "comp2_threshold"))
id = COMP2;
else
return -EINVAL;
uVolt = comp_threshold_get(tps65910, id);
return sprintf(buf, "%d\n", uVolt);
}
static DEVICE_ATTR(comp1_threshold, S_IRUGO, comp_threshold_show, NULL);
static DEVICE_ATTR(comp2_threshold, S_IRUGO, comp_threshold_show, NULL);
static __devinit int tps65911_comparator_probe(struct platform_device *pdev)
{
struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
struct tps65910_platform_data *pdata = dev_get_platdata(tps65910->dev);
int ret;
ret = comp_threshold_set(tps65910, COMP1, pdata->vmbch_threshold);
if (ret < 0) {
dev_err(&pdev->dev, "cannot set COMP1 threshold\n");
return ret;
}
ret = comp_threshold_set(tps65910, COMP2, pdata->vmbch2_threshold);
if (ret < 0) {
dev_err(&pdev->dev, "cannot set COMP2 theshold\n");
return ret;
}
/* Create sysfs entry */
ret = device_create_file(&pdev->dev, &dev_attr_comp1_threshold);
if (ret < 0)
dev_err(&pdev->dev, "failed to add COMP1 sysfs file\n");
ret = device_create_file(&pdev->dev, &dev_attr_comp2_threshold);
if (ret < 0)
dev_err(&pdev->dev, "failed to add COMP2 sysfs file\n");
return ret;
}
static __devexit int tps65911_comparator_remove(struct platform_device *pdev)
{
struct tps65910 *tps65910;
tps65910 = dev_get_drvdata(pdev->dev.parent);
return 0;
}
static struct platform_driver tps65911_comparator_driver = {
.driver = {
.name = "tps65911-comparator",
.owner = THIS_MODULE,
},
.probe = tps65911_comparator_probe,
.remove = __devexit_p(tps65911_comparator_remove),
};
static int __init tps65911_comparator_init(void)
{
return platform_driver_register(&tps65911_comparator_driver);
}
subsys_initcall(tps65911_comparator_init);
static void __exit tps65911_comparator_exit(void)
{
platform_driver_unregister(&tps65911_comparator_driver);
}
module_exit(tps65911_comparator_exit);
MODULE_AUTHOR("Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>");
MODULE_DESCRIPTION("TPS65911 comparator driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:tps65911-comparator");
...@@ -297,5 +297,11 @@ config REGULATOR_TPS6524X ...@@ -297,5 +297,11 @@ config REGULATOR_TPS6524X
serial interface currently supported on the sequencer serial serial interface currently supported on the sequencer serial
port controller. port controller.
config REGULATOR_TPS65910
tristate "TI TPS65910 Power Regulator"
depends on MFD_TPS65910
help
This driver supports TPS65910 voltage regulator chips.
endif endif
...@@ -42,5 +42,6 @@ obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o ...@@ -42,5 +42,6 @@ obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
...@@ -158,6 +158,13 @@ static int regulator_check_consumers(struct regulator_dev *rdev, ...@@ -158,6 +158,13 @@ static int regulator_check_consumers(struct regulator_dev *rdev,
struct regulator *regulator; struct regulator *regulator;
list_for_each_entry(regulator, &rdev->consumer_list, list) { list_for_each_entry(regulator, &rdev->consumer_list, list) {
/*
* Assume consumers that didn't say anything are OK
* with anything in the constraint range.
*/
if (!regulator->min_uV && !regulator->max_uV)
continue;
if (*max_uV > regulator->max_uV) if (*max_uV > regulator->max_uV)
*max_uV = regulator->max_uV; *max_uV = regulator->max_uV;
if (*min_uV < regulator->min_uV) if (*min_uV < regulator->min_uV)
...@@ -197,9 +204,9 @@ static int regulator_check_current_limit(struct regulator_dev *rdev, ...@@ -197,9 +204,9 @@ static int regulator_check_current_limit(struct regulator_dev *rdev,
} }
/* operating mode constraint check */ /* operating mode constraint check */
static int regulator_check_mode(struct regulator_dev *rdev, int mode) static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode)
{ {
switch (mode) { switch (*mode) {
case REGULATOR_MODE_FAST: case REGULATOR_MODE_FAST:
case REGULATOR_MODE_NORMAL: case REGULATOR_MODE_NORMAL:
case REGULATOR_MODE_IDLE: case REGULATOR_MODE_IDLE:
...@@ -217,11 +224,17 @@ static int regulator_check_mode(struct regulator_dev *rdev, int mode) ...@@ -217,11 +224,17 @@ static int regulator_check_mode(struct regulator_dev *rdev, int mode)
rdev_err(rdev, "operation not allowed\n"); rdev_err(rdev, "operation not allowed\n");
return -EPERM; return -EPERM;
} }
if (!(rdev->constraints->valid_modes_mask & mode)) {
rdev_err(rdev, "invalid mode %x\n", mode); /* The modes are bitmasks, the most power hungry modes having
return -EINVAL; * the lowest values. If the requested mode isn't supported
* try higher modes. */
while (*mode) {
if (rdev->constraints->valid_modes_mask & *mode)
return 0;
*mode /= 2;
} }
return 0;
return -EINVAL;
} }
/* dynamic regulator mode switching constraint check */ /* dynamic regulator mode switching constraint check */
...@@ -612,7 +625,7 @@ static void drms_uA_update(struct regulator_dev *rdev) ...@@ -612,7 +625,7 @@ static void drms_uA_update(struct regulator_dev *rdev)
output_uV, current_uA); output_uV, current_uA);
/* check the new mode is allowed */ /* check the new mode is allowed */
err = regulator_check_mode(rdev, mode); err = regulator_mode_constrain(rdev, &mode);
if (err == 0) if (err == 0)
rdev->desc->ops->set_mode(rdev, mode); rdev->desc->ops->set_mode(rdev, mode);
} }
...@@ -718,6 +731,10 @@ static void print_constraints(struct regulator_dev *rdev) ...@@ -718,6 +731,10 @@ static void print_constraints(struct regulator_dev *rdev)
count += sprintf(buf + count, "at %d mV ", ret / 1000); count += sprintf(buf + count, "at %d mV ", ret / 1000);
} }
if (constraints->uV_offset)
count += sprintf(buf, "%dmV offset ",
constraints->uV_offset / 1000);
if (constraints->min_uA && constraints->max_uA) { if (constraints->min_uA && constraints->max_uA) {
if (constraints->min_uA == constraints->max_uA) if (constraints->min_uA == constraints->max_uA)
count += sprintf(buf + count, "%d mA ", count += sprintf(buf + count, "%d mA ",
...@@ -1498,13 +1515,14 @@ static int _regulator_force_disable(struct regulator_dev *rdev, ...@@ -1498,13 +1515,14 @@ static int _regulator_force_disable(struct regulator_dev *rdev,
*/ */
int regulator_force_disable(struct regulator *regulator) int regulator_force_disable(struct regulator *regulator)
{ {
struct regulator_dev *rdev = regulator->rdev;
struct regulator_dev *supply_rdev = NULL; struct regulator_dev *supply_rdev = NULL;
int ret; int ret;
mutex_lock(&regulator->rdev->mutex); mutex_lock(&rdev->mutex);
regulator->uA_load = 0; regulator->uA_load = 0;
ret = _regulator_force_disable(regulator->rdev, &supply_rdev); ret = _regulator_force_disable(rdev, &supply_rdev);
mutex_unlock(&regulator->rdev->mutex); mutex_unlock(&rdev->mutex);
if (supply_rdev) if (supply_rdev)
regulator_disable(get_device_regulator(rdev_get_dev(supply_rdev))); regulator_disable(get_device_regulator(rdev_get_dev(supply_rdev)));
...@@ -1634,6 +1652,9 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, ...@@ -1634,6 +1652,9 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
min_uV += rdev->constraints->uV_offset;
max_uV += rdev->constraints->uV_offset;
if (rdev->desc->ops->set_voltage) { if (rdev->desc->ops->set_voltage) {
ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV,
&selector); &selector);
...@@ -1858,18 +1879,22 @@ EXPORT_SYMBOL_GPL(regulator_sync_voltage); ...@@ -1858,18 +1879,22 @@ EXPORT_SYMBOL_GPL(regulator_sync_voltage);
static int _regulator_get_voltage(struct regulator_dev *rdev) static int _regulator_get_voltage(struct regulator_dev *rdev)
{ {
int sel; int sel, ret;
if (rdev->desc->ops->get_voltage_sel) { if (rdev->desc->ops->get_voltage_sel) {
sel = rdev->desc->ops->get_voltage_sel(rdev); sel = rdev->desc->ops->get_voltage_sel(rdev);
if (sel < 0) if (sel < 0)
return sel; return sel;
return rdev->desc->ops->list_voltage(rdev, sel); ret = rdev->desc->ops->list_voltage(rdev, sel);
} } else if (rdev->desc->ops->get_voltage) {
if (rdev->desc->ops->get_voltage) ret = rdev->desc->ops->get_voltage(rdev);
return rdev->desc->ops->get_voltage(rdev); } else {
else
return -EINVAL; return -EINVAL;
}
if (ret < 0)
return ret;
return ret - rdev->constraints->uV_offset;
} }
/** /**
...@@ -2005,7 +2030,7 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode) ...@@ -2005,7 +2030,7 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode)
} }
/* constraints check */ /* constraints check */
ret = regulator_check_mode(rdev, mode); ret = regulator_mode_constrain(rdev, &mode);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -2081,16 +2106,26 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) ...@@ -2081,16 +2106,26 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
mutex_lock(&rdev->mutex); mutex_lock(&rdev->mutex);
/*
* first check to see if we can set modes at all, otherwise just
* tell the consumer everything is OK.
*/
regulator->uA_load = uA_load; regulator->uA_load = uA_load;
ret = regulator_check_drms(rdev); ret = regulator_check_drms(rdev);
if (ret < 0) if (ret < 0) {
ret = 0;
goto out; goto out;
ret = -EINVAL; }
/* sanity check */
if (!rdev->desc->ops->get_optimum_mode) if (!rdev->desc->ops->get_optimum_mode)
goto out; goto out;
/*
* we can actually do this so any errors are indicators of
* potential real failure.
*/
ret = -EINVAL;
/* get output voltage */ /* get output voltage */
output_uV = _regulator_get_voltage(rdev); output_uV = _regulator_get_voltage(rdev);
if (output_uV <= 0) { if (output_uV <= 0) {
...@@ -2116,7 +2151,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) ...@@ -2116,7 +2151,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
mode = rdev->desc->ops->get_optimum_mode(rdev, mode = rdev->desc->ops->get_optimum_mode(rdev,
input_uV, output_uV, input_uV, output_uV,
total_uA_load); total_uA_load);
ret = regulator_check_mode(rdev, mode); ret = regulator_mode_constrain(rdev, &mode);
if (ret < 0) { if (ret < 0) {
rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n",
total_uA_load, input_uV, output_uV); total_uA_load, input_uV, output_uV);
...@@ -2589,14 +2624,6 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, ...@@ -2589,14 +2624,6 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
if (ret < 0) if (ret < 0)
goto scrub; goto scrub;
/* set supply regulator if it exists */
if (init_data->supply_regulator && init_data->supply_regulator_dev) {
dev_err(dev,
"Supply regulator specified by both name and dev\n");
ret = -EINVAL;
goto scrub;
}
if (init_data->supply_regulator) { if (init_data->supply_regulator) {
struct regulator_dev *r; struct regulator_dev *r;
int found = 0; int found = 0;
...@@ -2621,14 +2648,6 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, ...@@ -2621,14 +2648,6 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
goto scrub; goto scrub;
} }
if (init_data->supply_regulator_dev) {
dev_warn(dev, "Uses supply_regulator_dev instead of regulator_supply\n");
ret = set_supply(rdev,
dev_get_drvdata(init_data->supply_regulator_dev));
if (ret < 0)
goto scrub;
}
/* add consumers devices */ /* add consumers devices */
for (i = 0; i < init_data->num_consumer_supplies; i++) { for (i = 0; i < init_data->num_consumer_supplies; i++) {
ret = set_consumer_device_supply(rdev, ret = set_consumer_device_supply(rdev,
......
...@@ -267,7 +267,6 @@ static int max8997_get_enable_register(struct regulator_dev *rdev, ...@@ -267,7 +267,6 @@ static int max8997_get_enable_register(struct regulator_dev *rdev,
default: default:
/* Not controllable or not exists */ /* Not controllable or not exists */
return -EINVAL; return -EINVAL;
break;
} }
return 0; return 0;
...@@ -1033,11 +1032,11 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) ...@@ -1033,11 +1032,11 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
/* For the safety, set max voltage before setting up */ /* For the safety, set max voltage before setting up */
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS(i + 1), max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
max_buck1, 0x3f); max_buck1, 0x3f);
max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS(i + 1), max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
max_buck2, 0x3f); max_buck2, 0x3f);
max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS(i + 1), max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
max_buck5, 0x3f); max_buck5, 0x3f);
} }
...@@ -1114,13 +1113,13 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) ...@@ -1114,13 +1113,13 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
/* Initialize all the DVS related BUCK registers */ /* Initialize all the DVS related BUCK registers */
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS(i + 1), max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
max8997->buck1_vol[i], max8997->buck1_vol[i],
0x3f); 0x3f);
max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS(i + 1), max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
max8997->buck2_vol[i], max8997->buck2_vol[i],
0x3f); 0x3f);
max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS(i + 1), max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
max8997->buck5_vol[i], max8997->buck5_vol[i],
0x3f); 0x3f);
} }
......
...@@ -732,13 +732,15 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) ...@@ -732,13 +732,15 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
if (!pdata->buck1_set1) { if (!pdata->buck1_set1) {
printk(KERN_ERR "MAX8998 SET1 GPIO defined as 0 !\n"); printk(KERN_ERR "MAX8998 SET1 GPIO defined as 0 !\n");
WARN_ON(!pdata->buck1_set1); WARN_ON(!pdata->buck1_set1);
return -EIO; ret = -EIO;
goto err_free_mem;
} }
/* Check if SET2 is not equal to 0 */ /* Check if SET2 is not equal to 0 */
if (!pdata->buck1_set2) { if (!pdata->buck1_set2) {
printk(KERN_ERR "MAX8998 SET2 GPIO defined as 0 !\n"); printk(KERN_ERR "MAX8998 SET2 GPIO defined as 0 !\n");
WARN_ON(!pdata->buck1_set2); WARN_ON(!pdata->buck1_set2);
return -EIO; ret = -EIO;
goto err_free_mem;
} }
gpio_request(pdata->buck1_set1, "MAX8998 BUCK1_SET1"); gpio_request(pdata->buck1_set1, "MAX8998 BUCK1_SET1");
...@@ -758,7 +760,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) ...@@ -758,7 +760,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck1_vol[0] = i; max8998->buck1_vol[0] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i);
if (ret) if (ret)
return ret; goto err_free_mem;
/* Set predefined value for BUCK1 register 2 */ /* Set predefined value for BUCK1 register 2 */
i = 0; i = 0;
...@@ -770,7 +772,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) ...@@ -770,7 +772,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck1_vol[1] = i; max8998->buck1_vol[1] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE2, i); ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE2, i);
if (ret) if (ret)
return ret; goto err_free_mem;
/* Set predefined value for BUCK1 register 3 */ /* Set predefined value for BUCK1 register 3 */
i = 0; i = 0;
...@@ -782,7 +784,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) ...@@ -782,7 +784,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck1_vol[2] = i; max8998->buck1_vol[2] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE3, i); ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE3, i);
if (ret) if (ret)
return ret; goto err_free_mem;
/* Set predefined value for BUCK1 register 4 */ /* Set predefined value for BUCK1 register 4 */
i = 0; i = 0;
...@@ -794,7 +796,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) ...@@ -794,7 +796,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck1_vol[3] = i; max8998->buck1_vol[3] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE4, i); ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE4, i);
if (ret) if (ret)
return ret; goto err_free_mem;
} }
...@@ -803,7 +805,8 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) ...@@ -803,7 +805,8 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
if (!pdata->buck2_set3) { if (!pdata->buck2_set3) {
printk(KERN_ERR "MAX8998 SET3 GPIO defined as 0 !\n"); printk(KERN_ERR "MAX8998 SET3 GPIO defined as 0 !\n");
WARN_ON(!pdata->buck2_set3); WARN_ON(!pdata->buck2_set3);
return -EIO; ret = -EIO;
goto err_free_mem;
} }
gpio_request(pdata->buck2_set3, "MAX8998 BUCK2_SET3"); gpio_request(pdata->buck2_set3, "MAX8998 BUCK2_SET3");
gpio_direction_output(pdata->buck2_set3, gpio_direction_output(pdata->buck2_set3,
...@@ -818,7 +821,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) ...@@ -818,7 +821,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck2_vol[0] = i; max8998->buck2_vol[0] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i);
if (ret) if (ret)
return ret; goto err_free_mem;
/* BUCK2 register 2 */ /* BUCK2 register 2 */
i = 0; i = 0;
...@@ -830,7 +833,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) ...@@ -830,7 +833,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck2_vol[1] = i; max8998->buck2_vol[1] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i); ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i);
if (ret) if (ret)
return ret; goto err_free_mem;
} }
for (i = 0; i < pdata->num_regulators; i++) { for (i = 0; i < pdata->num_regulators; i++) {
...@@ -860,6 +863,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) ...@@ -860,6 +863,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
if (rdev[i]) if (rdev[i])
regulator_unregister(rdev[i]); regulator_unregister(rdev[i]);
err_free_mem:
kfree(max8998->rdev); kfree(max8998->rdev);
kfree(max8998); kfree(max8998);
......
...@@ -431,7 +431,8 @@ static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev, ...@@ -431,7 +431,8 @@ static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV, unsigned *selector) int min_uV, int max_uV, unsigned *selector)
{ {
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
int hi, value, val, mask, id = rdev_get_id(rdev); int hi, value, mask, id = rdev_get_id(rdev);
u32 valread;
int ret; int ret;
dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
...@@ -447,15 +448,16 @@ static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev, ...@@ -447,15 +448,16 @@ static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev,
mc13xxx_lock(priv->mc13xxx); mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_read(priv->mc13xxx, ret = mc13xxx_reg_read(priv->mc13xxx,
mc13892_regulators[id].vsel_reg, &val); mc13892_regulators[id].vsel_reg, &valread);
if (ret) if (ret)
goto err; goto err;
hi = val & MC13892_SWITCHERS0_SWxHI; if (value > 1375000)
if (value > 1375)
hi = 1; hi = 1;
if (value < 1100) else if (value < 1100000)
hi = 0; hi = 0;
else
hi = valread & MC13892_SWITCHERS0_SWxHI;
if (hi) { if (hi) {
value = (value - 1100000) / 25000; value = (value - 1100000) / 25000;
...@@ -464,8 +466,10 @@ static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev, ...@@ -464,8 +466,10 @@ static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev,
value = (value - 600000) / 25000; value = (value - 600000) / 25000;
mask = mc13892_regulators[id].vsel_mask | MC13892_SWITCHERS0_SWxHI; mask = mc13892_regulators[id].vsel_mask | MC13892_SWITCHERS0_SWxHI;
ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].vsel_reg, valread = (valread & ~mask) |
mask, value << mc13892_regulators[id].vsel_shift); (value << mc13892_regulators[id].vsel_shift);
ret = mc13xxx_reg_write(priv->mc13xxx, mc13892_regulators[id].vsel_reg,
valread);
err: err:
mc13xxx_unlock(priv->mc13xxx); mc13xxx_unlock(priv->mc13xxx);
......
...@@ -174,7 +174,7 @@ static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev) ...@@ -174,7 +174,7 @@ static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev)
dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val); dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val);
BUG_ON(val > mc13xxx_regulators[id].desc.n_voltages); BUG_ON(val >= mc13xxx_regulators[id].desc.n_voltages);
return mc13xxx_regulators[id].voltages[val]; return mc13xxx_regulators[id].voltages[val];
} }
......
...@@ -158,6 +158,7 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev) ...@@ -158,6 +158,7 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
"failed to register regulator\n"); "failed to register regulator\n");
return ret; return ret;
} }
platform_set_drvdata(pdev, tps6105x);
return 0; return 0;
} }
......
...@@ -466,7 +466,6 @@ static struct regulator_ops tps65023_ldo_ops = { ...@@ -466,7 +466,6 @@ static struct regulator_ops tps65023_ldo_ops = {
static int __devinit tps_65023_probe(struct i2c_client *client, static int __devinit tps_65023_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
static int desc_id;
const struct tps_info *info = (void *)id->driver_data; const struct tps_info *info = (void *)id->driver_data;
struct regulator_init_data *init_data; struct regulator_init_data *init_data;
struct regulator_dev *rdev; struct regulator_dev *rdev;
...@@ -499,7 +498,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client, ...@@ -499,7 +498,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
tps->info[i] = info; tps->info[i] = info;
tps->desc[i].name = info->name; tps->desc[i].name = info->name;
tps->desc[i].id = desc_id++; tps->desc[i].id = i;
tps->desc[i].n_voltages = num_voltages[i]; tps->desc[i].n_voltages = num_voltages[i];
tps->desc[i].ops = (i > TPS65023_DCDC_3 ? tps->desc[i].ops = (i > TPS65023_DCDC_3 ?
&tps65023_ldo_ops : &tps65023_dcdc_ops); &tps65023_ldo_ops : &tps65023_dcdc_ops);
......
...@@ -553,7 +553,6 @@ static __devinit ...@@ -553,7 +553,6 @@ static __devinit
int tps6507x_pmic_probe(struct platform_device *pdev) int tps6507x_pmic_probe(struct platform_device *pdev)
{ {
struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
static int desc_id;
struct tps_info *info = &tps6507x_pmic_regs[0]; struct tps_info *info = &tps6507x_pmic_regs[0];
struct regulator_init_data *init_data; struct regulator_init_data *init_data;
struct regulator_dev *rdev; struct regulator_dev *rdev;
...@@ -598,7 +597,7 @@ int tps6507x_pmic_probe(struct platform_device *pdev) ...@@ -598,7 +597,7 @@ int tps6507x_pmic_probe(struct platform_device *pdev)
} }
tps->desc[i].name = info->name; tps->desc[i].name = info->name;
tps->desc[i].id = desc_id++; tps->desc[i].id = i;
tps->desc[i].n_voltages = num_voltages[i]; tps->desc[i].n_voltages = num_voltages[i];
tps->desc[i].ops = (i > TPS6507X_DCDC_3 ? tps->desc[i].ops = (i > TPS6507X_DCDC_3 ?
&tps6507x_pmic_ldo_ops : &tps6507x_pmic_dcdc_ops); &tps6507x_pmic_ldo_ops : &tps6507x_pmic_dcdc_ops);
......
此差异已折叠。
此差异已折叠。
...@@ -600,7 +600,6 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) ...@@ -600,7 +600,6 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
static __devexit int wm831x_buckv_remove(struct platform_device *pdev) static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
{ {
struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
struct wm831x *wm831x = dcdc->wm831x;
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
...@@ -776,7 +775,6 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) ...@@ -776,7 +775,6 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
static __devexit int wm831x_buckp_remove(struct platform_device *pdev) static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
{ {
struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
struct wm831x *wm831x = dcdc->wm831x;
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
......
...@@ -55,7 +55,7 @@ static int wm8400_ldo_list_voltage(struct regulator_dev *dev, ...@@ -55,7 +55,7 @@ static int wm8400_ldo_list_voltage(struct regulator_dev *dev,
return 1600000 + ((selector - 14) * 100000); return 1600000 + ((selector - 14) * 100000);
} }
static int wm8400_ldo_get_voltage(struct regulator_dev *dev) static int wm8400_ldo_get_voltage_sel(struct regulator_dev *dev)
{ {
struct wm8400 *wm8400 = rdev_get_drvdata(dev); struct wm8400 *wm8400 = rdev_get_drvdata(dev);
u16 val; u16 val;
...@@ -63,7 +63,7 @@ static int wm8400_ldo_get_voltage(struct regulator_dev *dev) ...@@ -63,7 +63,7 @@ static int wm8400_ldo_get_voltage(struct regulator_dev *dev)
val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev)); val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev));
val &= WM8400_LDO1_VSEL_MASK; val &= WM8400_LDO1_VSEL_MASK;
return wm8400_ldo_list_voltage(dev, val); return val;
} }
static int wm8400_ldo_set_voltage(struct regulator_dev *dev, static int wm8400_ldo_set_voltage(struct regulator_dev *dev,
...@@ -104,7 +104,7 @@ static struct regulator_ops wm8400_ldo_ops = { ...@@ -104,7 +104,7 @@ static struct regulator_ops wm8400_ldo_ops = {
.enable = wm8400_ldo_enable, .enable = wm8400_ldo_enable,
.disable = wm8400_ldo_disable, .disable = wm8400_ldo_disable,
.list_voltage = wm8400_ldo_list_voltage, .list_voltage = wm8400_ldo_list_voltage,
.get_voltage = wm8400_ldo_get_voltage, .get_voltage_sel = wm8400_ldo_get_voltage_sel,
.set_voltage = wm8400_ldo_set_voltage, .set_voltage = wm8400_ldo_set_voltage,
}; };
...@@ -145,7 +145,7 @@ static int wm8400_dcdc_list_voltage(struct regulator_dev *dev, ...@@ -145,7 +145,7 @@ static int wm8400_dcdc_list_voltage(struct regulator_dev *dev,
return 850000 + (selector * 25000); return 850000 + (selector * 25000);
} }
static int wm8400_dcdc_get_voltage(struct regulator_dev *dev) static int wm8400_dcdc_get_voltage_sel(struct regulator_dev *dev)
{ {
struct wm8400 *wm8400 = rdev_get_drvdata(dev); struct wm8400 *wm8400 = rdev_get_drvdata(dev);
u16 val; u16 val;
...@@ -154,7 +154,7 @@ static int wm8400_dcdc_get_voltage(struct regulator_dev *dev) ...@@ -154,7 +154,7 @@ static int wm8400_dcdc_get_voltage(struct regulator_dev *dev)
val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset); val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset);
val &= WM8400_DC1_VSEL_MASK; val &= WM8400_DC1_VSEL_MASK;
return 850000 + (25000 * val); return val;
} }
static int wm8400_dcdc_set_voltage(struct regulator_dev *dev, static int wm8400_dcdc_set_voltage(struct regulator_dev *dev,
...@@ -261,7 +261,7 @@ static struct regulator_ops wm8400_dcdc_ops = { ...@@ -261,7 +261,7 @@ static struct regulator_ops wm8400_dcdc_ops = {
.enable = wm8400_dcdc_enable, .enable = wm8400_dcdc_enable,
.disable = wm8400_dcdc_disable, .disable = wm8400_dcdc_disable,
.list_voltage = wm8400_dcdc_list_voltage, .list_voltage = wm8400_dcdc_list_voltage,
.get_voltage = wm8400_dcdc_get_voltage, .get_voltage_sel = wm8400_dcdc_get_voltage_sel,
.set_voltage = wm8400_dcdc_set_voltage, .set_voltage = wm8400_dcdc_set_voltage,
.get_mode = wm8400_dcdc_get_mode, .get_mode = wm8400_dcdc_get_mode,
.set_mode = wm8400_dcdc_set_mode, .set_mode = wm8400_dcdc_set_mode,
......
...@@ -100,6 +100,7 @@ struct twl6030_usb { ...@@ -100,6 +100,7 @@ struct twl6030_usb {
u8 linkstat; u8 linkstat;
u8 asleep; u8 asleep;
bool irq_enabled; bool irq_enabled;
unsigned long features;
}; };
#define xceiv_to_twl(x) container_of((x), struct twl6030_usb, otg) #define xceiv_to_twl(x) container_of((x), struct twl6030_usb, otg)
...@@ -204,6 +205,12 @@ static int twl6030_start_srp(struct otg_transceiver *x) ...@@ -204,6 +205,12 @@ static int twl6030_start_srp(struct otg_transceiver *x)
static int twl6030_usb_ldo_init(struct twl6030_usb *twl) static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
{ {
char *regulator_name;
if (twl->features & TWL6025_SUBCLASS)
regulator_name = "ldousb";
else
regulator_name = "vusb";
/* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */ /* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */
twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG); twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);
...@@ -214,7 +221,7 @@ static int twl6030_usb_ldo_init(struct twl6030_usb *twl) ...@@ -214,7 +221,7 @@ static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
/* Program MISC2 register and set bit VUSB_IN_VBAT */ /* Program MISC2 register and set bit VUSB_IN_VBAT */
twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2); twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2);
twl->usb3v3 = regulator_get(twl->dev, "vusb"); twl->usb3v3 = regulator_get(twl->dev, regulator_name);
if (IS_ERR(twl->usb3v3)) if (IS_ERR(twl->usb3v3))
return -ENODEV; return -ENODEV;
...@@ -409,6 +416,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) ...@@ -409,6 +416,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
twl->dev = &pdev->dev; twl->dev = &pdev->dev;
twl->irq1 = platform_get_irq(pdev, 0); twl->irq1 = platform_get_irq(pdev, 0);
twl->irq2 = platform_get_irq(pdev, 1); twl->irq2 = platform_get_irq(pdev, 1);
twl->features = pdata->features;
twl->otg.dev = twl->dev; twl->otg.dev = twl->dev;
twl->otg.label = "twl6030"; twl->otg.label = "twl6030";
twl->otg.set_host = twl6030_set_host; twl->otg.set_host = twl6030_set_host;
......
...@@ -311,10 +311,6 @@ enum max8997_irq { ...@@ -311,10 +311,6 @@ enum max8997_irq {
MAX8997_IRQ_NR, MAX8997_IRQ_NR,
}; };
#define MAX8997_REG_BUCK1DVS(x) (MAX8997_REG_BUCK1DVS1 + (x) - 1)
#define MAX8997_REG_BUCK2DVS(x) (MAX8997_REG_BUCK2DVS1 + (x) - 1)
#define MAX8997_REG_BUCK5DVS(x) (MAX8997_REG_BUCK5DVS1 + (x) - 1)
#define MAX8997_NUM_GPIO 12 #define MAX8997_NUM_GPIO 12
struct max8997_dev { struct max8997_dev {
struct device *dev; struct device *dev;
......
此差异已折叠。
...@@ -68,6 +68,8 @@ struct regulator_state { ...@@ -68,6 +68,8 @@ struct regulator_state {
* *
* @min_uV: Smallest voltage consumers may set. * @min_uV: Smallest voltage consumers may set.
* @max_uV: Largest voltage consumers may set. * @max_uV: Largest voltage consumers may set.
* @uV_offset: Offset applied to voltages from consumer to compensate for
* voltage drops.
* *
* @min_uA: Smallest consumers consumers may set. * @min_uA: Smallest consumers consumers may set.
* @max_uA: Largest current consumers may set. * @max_uA: Largest current consumers may set.
...@@ -99,6 +101,8 @@ struct regulation_constraints { ...@@ -99,6 +101,8 @@ struct regulation_constraints {
int min_uV; int min_uV;
int max_uV; int max_uV;
int uV_offset;
/* current output range (inclusive) - for current control */ /* current output range (inclusive) - for current control */
int min_uA; int min_uA;
int max_uA; int max_uA;
...@@ -160,8 +164,6 @@ struct regulator_consumer_supply { ...@@ -160,8 +164,6 @@ struct regulator_consumer_supply {
* @supply_regulator: Parent regulator. Specified using the regulator name * @supply_regulator: Parent regulator. Specified using the regulator name
* as it appears in the name field in sysfs, which can * as it appears in the name field in sysfs, which can
* be explicitly set using the constraints field 'name'. * be explicitly set using the constraints field 'name'.
* @supply_regulator_dev: Parent regulator (if any) - DEPRECATED in favour
* of supply_regulator.
* *
* @constraints: Constraints. These must be specified for the regulator to * @constraints: Constraints. These must be specified for the regulator to
* be usable. * be usable.
...@@ -173,7 +175,6 @@ struct regulator_consumer_supply { ...@@ -173,7 +175,6 @@ struct regulator_consumer_supply {
*/ */
struct regulator_init_data { struct regulator_init_data {
const char *supply_regulator; /* or NULL for system supply */ const char *supply_regulator; /* or NULL for system supply */
struct device *supply_regulator_dev; /* or NULL for system supply */
struct regulation_constraints constraints; struct regulation_constraints constraints;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册