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
  ...
This commit is contained in:
Linus Torvalds 2011-05-27 10:13:01 -07:00
commit f7fc06e3a4
27 changed files with 3162 additions and 151 deletions

View File

@ -53,11 +53,11 @@ static struct regulator_init_data regulator1_data = {
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
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:-
static struct regulator_init_data regulator2_data = {
.supply_regulator_dev = &platform_regulator1_device.dev,
.supply_regulator = "regulator_name",
.constraints = {
.min_uV = 1800000,
.max_uV = 2000000,

View File

@ -424,4 +424,11 @@ config AB8500_GPIO
depends on AB8500_CORE && BROKEN
help
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

View File

@ -40,3 +40,4 @@ obj-$(CONFIG_GPIO_SX150X) += sx150x.o
obj-$(CONFIG_GPIO_VX855) += vx855_gpio.o
obj-$(CONFIG_GPIO_ML_IOH) += ml_ioh_gpio.o
obj-$(CONFIG_AB8500_GPIO) += ab8500-gpio.o
obj-$(CONFIG_GPIO_TPS65910) += tps65910-gpio.o

View File

@ -0,0 +1,100 @@
/*
* 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);
}

View File

@ -719,6 +719,15 @@ config MFD_PM8XXX_IRQ
This is required to use certain other PM 8xxx features, such as GPIO
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
menu "Multimedia Capabilities Port drivers"

View File

@ -93,3 +93,4 @@ obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o
obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o
obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o
obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o
obj-$(CONFIG_MFD_TPS65910) += tps65910.o tps65910-irq.o

218
drivers/mfd/tps65910-irq.c Normal file
View File

@ -0,0 +1,218 @@
/*
* 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;
}

229
drivers/mfd/tps65910.c Normal file
View File

@ -0,0 +1,229 @@
/*
* 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");

View File

@ -0,0 +1,188 @@
/*
* 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");

View File

@ -297,5 +297,11 @@ config REGULATOR_TPS6524X
serial interface currently supported on the sequencer serial
port controller.
config REGULATOR_TPS65910
tristate "TI TPS65910 Power Regulator"
depends on MFD_TPS65910
help
This driver supports TPS65910 voltage regulator chips.
endif

View File

@ -42,5 +42,6 @@ obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG

View File

@ -158,6 +158,13 @@ static int regulator_check_consumers(struct regulator_dev *rdev,
struct regulator *regulator;
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)
*max_uV = regulator->max_uV;
if (*min_uV < regulator->min_uV)
@ -197,9 +204,9 @@ static int regulator_check_current_limit(struct regulator_dev *rdev,
}
/* 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_NORMAL:
case REGULATOR_MODE_IDLE:
@ -217,11 +224,17 @@ static int regulator_check_mode(struct regulator_dev *rdev, int mode)
rdev_err(rdev, "operation not allowed\n");
return -EPERM;
}
if (!(rdev->constraints->valid_modes_mask & mode)) {
rdev_err(rdev, "invalid mode %x\n", mode);
return -EINVAL;
/* The modes are bitmasks, the most power hungry modes having
* 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 */
@ -612,7 +625,7 @@ static void drms_uA_update(struct regulator_dev *rdev)
output_uV, current_uA);
/* check the new mode is allowed */
err = regulator_check_mode(rdev, mode);
err = regulator_mode_constrain(rdev, &mode);
if (err == 0)
rdev->desc->ops->set_mode(rdev, mode);
}
@ -718,6 +731,10 @@ static void print_constraints(struct regulator_dev *rdev)
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)
count += sprintf(buf + count, "%d mA ",
@ -1498,13 +1515,14 @@ static int _regulator_force_disable(struct regulator_dev *rdev,
*/
int regulator_force_disable(struct regulator *regulator)
{
struct regulator_dev *rdev = regulator->rdev;
struct regulator_dev *supply_rdev = NULL;
int ret;
mutex_lock(&regulator->rdev->mutex);
mutex_lock(&rdev->mutex);
regulator->uA_load = 0;
ret = _regulator_force_disable(regulator->rdev, &supply_rdev);
mutex_unlock(&regulator->rdev->mutex);
ret = _regulator_force_disable(rdev, &supply_rdev);
mutex_unlock(&rdev->mutex);
if (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,
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) {
ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV,
&selector);
@ -1858,18 +1879,22 @@ EXPORT_SYMBOL_GPL(regulator_sync_voltage);
static int _regulator_get_voltage(struct regulator_dev *rdev)
{
int sel;
int sel, ret;
if (rdev->desc->ops->get_voltage_sel) {
sel = rdev->desc->ops->get_voltage_sel(rdev);
if (sel < 0)
return sel;
return rdev->desc->ops->list_voltage(rdev, sel);
}
if (rdev->desc->ops->get_voltage)
return rdev->desc->ops->get_voltage(rdev);
else
ret = rdev->desc->ops->list_voltage(rdev, sel);
} else if (rdev->desc->ops->get_voltage) {
ret = rdev->desc->ops->get_voltage(rdev);
} else {
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)
}
/* constraints check */
ret = regulator_check_mode(rdev, mode);
ret = regulator_mode_constrain(rdev, &mode);
if (ret < 0)
goto out;
@ -2081,16 +2106,26 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
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;
ret = regulator_check_drms(rdev);
if (ret < 0)
if (ret < 0) {
ret = 0;
goto out;
ret = -EINVAL;
}
/* sanity check */
if (!rdev->desc->ops->get_optimum_mode)
goto out;
/*
* we can actually do this so any errors are indicators of
* potential real failure.
*/
ret = -EINVAL;
/* get output voltage */
output_uV = _regulator_get_voltage(rdev);
if (output_uV <= 0) {
@ -2116,7 +2151,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
mode = rdev->desc->ops->get_optimum_mode(rdev,
input_uV, output_uV,
total_uA_load);
ret = regulator_check_mode(rdev, mode);
ret = regulator_mode_constrain(rdev, &mode);
if (ret < 0) {
rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n",
total_uA_load, input_uV, output_uV);
@ -2589,14 +2624,6 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
if (ret < 0)
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) {
struct regulator_dev *r;
int found = 0;
@ -2621,14 +2648,6 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
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 */
for (i = 0; i < init_data->num_consumer_supplies; i++) {
ret = set_consumer_device_supply(rdev,

View File

@ -267,7 +267,6 @@ static int max8997_get_enable_register(struct regulator_dev *rdev,
default:
/* Not controllable or not exists */
return -EINVAL;
break;
}
return 0;
@ -1033,11 +1032,11 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
/* For the safety, set max voltage before setting up */
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);
max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS(i + 1),
max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
max_buck2, 0x3f);
max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS(i + 1),
max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
max_buck5, 0x3f);
}
@ -1114,13 +1113,13 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
/* Initialize all the DVS related BUCK registers */
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],
0x3f);
max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS(i + 1),
max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
max8997->buck2_vol[i],
0x3f);
max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS(i + 1),
max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
max8997->buck5_vol[i],
0x3f);
}

View File

@ -732,13 +732,15 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
if (!pdata->buck1_set1) {
printk(KERN_ERR "MAX8998 SET1 GPIO defined as 0 !\n");
WARN_ON(!pdata->buck1_set1);
return -EIO;
ret = -EIO;
goto err_free_mem;
}
/* Check if SET2 is not equal to 0 */
if (!pdata->buck1_set2) {
printk(KERN_ERR "MAX8998 SET2 GPIO defined as 0 !\n");
WARN_ON(!pdata->buck1_set2);
return -EIO;
ret = -EIO;
goto err_free_mem;
}
gpio_request(pdata->buck1_set1, "MAX8998 BUCK1_SET1");
@ -758,7 +760,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck1_vol[0] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i);
if (ret)
return ret;
goto err_free_mem;
/* Set predefined value for BUCK1 register 2 */
i = 0;
@ -770,7 +772,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck1_vol[1] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE2, i);
if (ret)
return ret;
goto err_free_mem;
/* Set predefined value for BUCK1 register 3 */
i = 0;
@ -782,7 +784,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck1_vol[2] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE3, i);
if (ret)
return ret;
goto err_free_mem;
/* Set predefined value for BUCK1 register 4 */
i = 0;
@ -794,7 +796,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck1_vol[3] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE4, i);
if (ret)
return ret;
goto err_free_mem;
}
@ -803,7 +805,8 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
if (!pdata->buck2_set3) {
printk(KERN_ERR "MAX8998 SET3 GPIO defined as 0 !\n");
WARN_ON(!pdata->buck2_set3);
return -EIO;
ret = -EIO;
goto err_free_mem;
}
gpio_request(pdata->buck2_set3, "MAX8998 BUCK2_SET3");
gpio_direction_output(pdata->buck2_set3,
@ -818,7 +821,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck2_vol[0] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i);
if (ret)
return ret;
goto err_free_mem;
/* BUCK2 register 2 */
i = 0;
@ -830,7 +833,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
max8998->buck2_vol[1] = i;
ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i);
if (ret)
return ret;
goto err_free_mem;
}
for (i = 0; i < pdata->num_regulators; i++) {
@ -860,6 +863,7 @@ err:
if (rdev[i])
regulator_unregister(rdev[i]);
err_free_mem:
kfree(max8998->rdev);
kfree(max8998);

View File

@ -431,7 +431,8 @@ static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV, unsigned *selector)
{
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;
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,
mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_read(priv->mc13xxx,
mc13892_regulators[id].vsel_reg, &val);
mc13892_regulators[id].vsel_reg, &valread);
if (ret)
goto err;
hi = val & MC13892_SWITCHERS0_SWxHI;
if (value > 1375)
if (value > 1375000)
hi = 1;
if (value < 1100)
else if (value < 1100000)
hi = 0;
else
hi = valread & MC13892_SWITCHERS0_SWxHI;
if (hi) {
value = (value - 1100000) / 25000;
@ -464,8 +466,10 @@ static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev,
value = (value - 600000) / 25000;
mask = mc13892_regulators[id].vsel_mask | MC13892_SWITCHERS0_SWxHI;
ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].vsel_reg,
mask, value << mc13892_regulators[id].vsel_shift);
valread = (valread & ~mask) |
(value << mc13892_regulators[id].vsel_shift);
ret = mc13xxx_reg_write(priv->mc13xxx, mc13892_regulators[id].vsel_reg,
valread);
err:
mc13xxx_unlock(priv->mc13xxx);

View File

@ -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);
BUG_ON(val > mc13xxx_regulators[id].desc.n_voltages);
BUG_ON(val >= mc13xxx_regulators[id].desc.n_voltages);
return mc13xxx_regulators[id].voltages[val];
}

View File

@ -158,6 +158,7 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
"failed to register regulator\n");
return ret;
}
platform_set_drvdata(pdev, tps6105x);
return 0;
}

View File

@ -466,7 +466,6 @@ static struct regulator_ops tps65023_ldo_ops = {
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;
struct regulator_init_data *init_data;
struct regulator_dev *rdev;
@ -499,7 +498,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
tps->info[i] = info;
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].ops = (i > TPS65023_DCDC_3 ?
&tps65023_ldo_ops : &tps65023_dcdc_ops);

View File

@ -553,7 +553,6 @@ static __devinit
int tps6507x_pmic_probe(struct platform_device *pdev)
{
struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
static int desc_id;
struct tps_info *info = &tps6507x_pmic_regs[0];
struct regulator_init_data *init_data;
struct regulator_dev *rdev;
@ -598,7 +597,7 @@ int tps6507x_pmic_probe(struct platform_device *pdev)
}
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].ops = (i > TPS6507X_DCDC_3 ?
&tps6507x_pmic_ldo_ops : &tps6507x_pmic_dcdc_ops);

View File

@ -0,0 +1,993 @@
/*
* tps65910.c -- TI tps65910
*
* 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/err.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/mfd/tps65910.h>
#define TPS65910_REG_VRTC 0
#define TPS65910_REG_VIO 1
#define TPS65910_REG_VDD1 2
#define TPS65910_REG_VDD2 3
#define TPS65910_REG_VDD3 4
#define TPS65910_REG_VDIG1 5
#define TPS65910_REG_VDIG2 6
#define TPS65910_REG_VPLL 7
#define TPS65910_REG_VDAC 8
#define TPS65910_REG_VAUX1 9
#define TPS65910_REG_VAUX2 10
#define TPS65910_REG_VAUX33 11
#define TPS65910_REG_VMMC 12
#define TPS65911_REG_VDDCTRL 4
#define TPS65911_REG_LDO1 5
#define TPS65911_REG_LDO2 6
#define TPS65911_REG_LDO3 7
#define TPS65911_REG_LDO4 8
#define TPS65911_REG_LDO5 9
#define TPS65911_REG_LDO6 10
#define TPS65911_REG_LDO7 11
#define TPS65911_REG_LDO8 12
#define TPS65910_NUM_REGULATOR 13
#define TPS65910_SUPPLY_STATE_ENABLED 0x1
/* supported VIO voltages in milivolts */
static const u16 VIO_VSEL_table[] = {
1500, 1800, 2500, 3300,
};
/* VSEL tables for TPS65910 specific LDOs and dcdc's */
/* supported VDD3 voltages in milivolts */
static const u16 VDD3_VSEL_table[] = {
5000,
};
/* supported VDIG1 voltages in milivolts */
static const u16 VDIG1_VSEL_table[] = {
1200, 1500, 1800, 2700,
};
/* supported VDIG2 voltages in milivolts */
static const u16 VDIG2_VSEL_table[] = {
1000, 1100, 1200, 1800,
};
/* supported VPLL voltages in milivolts */
static const u16 VPLL_VSEL_table[] = {
1000, 1100, 1800, 2500,
};
/* supported VDAC voltages in milivolts */
static const u16 VDAC_VSEL_table[] = {
1800, 2600, 2800, 2850,
};
/* supported VAUX1 voltages in milivolts */
static const u16 VAUX1_VSEL_table[] = {
1800, 2500, 2800, 2850,
};
/* supported VAUX2 voltages in milivolts */
static const u16 VAUX2_VSEL_table[] = {
1800, 2800, 2900, 3300,
};
/* supported VAUX33 voltages in milivolts */
static const u16 VAUX33_VSEL_table[] = {
1800, 2000, 2800, 3300,
};
/* supported VMMC voltages in milivolts */
static const u16 VMMC_VSEL_table[] = {
1800, 2800, 3000, 3300,
};
struct tps_info {
const char *name;
unsigned min_uV;
unsigned max_uV;
u8 table_len;
const u16 *table;
};
static struct tps_info tps65910_regs[] = {
{
.name = "VRTC",
},
{
.name = "VIO",
.min_uV = 1500000,
.max_uV = 3300000,
.table_len = ARRAY_SIZE(VIO_VSEL_table),
.table = VIO_VSEL_table,
},
{
.name = "VDD1",
.min_uV = 600000,
.max_uV = 4500000,
},
{
.name = "VDD2",
.min_uV = 600000,
.max_uV = 4500000,
},
{
.name = "VDD3",
.min_uV = 5000000,
.max_uV = 5000000,
.table_len = ARRAY_SIZE(VDD3_VSEL_table),
.table = VDD3_VSEL_table,
},
{
.name = "VDIG1",
.min_uV = 1200000,
.max_uV = 2700000,
.table_len = ARRAY_SIZE(VDIG1_VSEL_table),
.table = VDIG1_VSEL_table,
},
{
.name = "VDIG2",
.min_uV = 1000000,
.max_uV = 1800000,
.table_len = ARRAY_SIZE(VDIG2_VSEL_table),
.table = VDIG2_VSEL_table,
},
{
.name = "VPLL",
.min_uV = 1000000,
.max_uV = 2500000,
.table_len = ARRAY_SIZE(VPLL_VSEL_table),
.table = VPLL_VSEL_table,
},
{
.name = "VDAC",
.min_uV = 1800000,
.max_uV = 2850000,
.table_len = ARRAY_SIZE(VDAC_VSEL_table),
.table = VDAC_VSEL_table,
},
{
.name = "VAUX1",
.min_uV = 1800000,
.max_uV = 2850000,
.table_len = ARRAY_SIZE(VAUX1_VSEL_table),
.table = VAUX1_VSEL_table,
},
{
.name = "VAUX2",
.min_uV = 1800000,
.max_uV = 3300000,
.table_len = ARRAY_SIZE(VAUX2_VSEL_table),
.table = VAUX2_VSEL_table,
},
{
.name = "VAUX33",
.min_uV = 1800000,
.max_uV = 3300000,
.table_len = ARRAY_SIZE(VAUX33_VSEL_table),
.table = VAUX33_VSEL_table,
},
{
.name = "VMMC",
.min_uV = 1800000,
.max_uV = 3300000,
.table_len = ARRAY_SIZE(VMMC_VSEL_table),
.table = VMMC_VSEL_table,
},
};
static struct tps_info tps65911_regs[] = {
{
.name = "VIO",
.min_uV = 1500000,
.max_uV = 3300000,
.table_len = ARRAY_SIZE(VIO_VSEL_table),
.table = VIO_VSEL_table,
},
{
.name = "VDD1",
.min_uV = 600000,
.max_uV = 4500000,
},
{
.name = "VDD2",
.min_uV = 600000,
.max_uV = 4500000,
},
{
.name = "VDDCTRL",
.min_uV = 600000,
.max_uV = 1400000,
},
{
.name = "LDO1",
.min_uV = 1000000,
.max_uV = 3300000,
},
{
.name = "LDO2",
.min_uV = 1000000,
.max_uV = 3300000,
},
{
.name = "LDO3",
.min_uV = 1000000,
.max_uV = 3300000,
},
{
.name = "LDO4",
.min_uV = 1000000,
.max_uV = 3300000,
},
{
.name = "LDO5",
.min_uV = 1000000,
.max_uV = 3300000,
},
{
.name = "LDO6",
.min_uV = 1000000,
.max_uV = 3300000,
},
{
.name = "LDO7",
.min_uV = 1000000,
.max_uV = 3300000,
},
{
.name = "LDO8",
.min_uV = 1000000,
.max_uV = 3300000,
},
};
struct tps65910_reg {
struct regulator_desc desc[TPS65910_NUM_REGULATOR];
struct tps65910 *mfd;
struct regulator_dev *rdev[TPS65910_NUM_REGULATOR];
struct tps_info *info[TPS65910_NUM_REGULATOR];
struct mutex mutex;
int mode;
int (*get_ctrl_reg)(int);
};
static inline int tps65910_read(struct tps65910_reg *pmic, u8 reg)
{
u8 val;
int err;
err = pmic->mfd->read(pmic->mfd, reg, 1, &val);
if (err)
return err;
return val;
}
static inline int tps65910_write(struct tps65910_reg *pmic, u8 reg, u8 val)
{
return pmic->mfd->write(pmic->mfd, reg, 1, &val);
}
static int tps65910_modify_bits(struct tps65910_reg *pmic, u8 reg,
u8 set_mask, u8 clear_mask)
{
int err, data;
mutex_lock(&pmic->mutex);
data = tps65910_read(pmic, reg);
if (data < 0) {
dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg);
err = data;
goto out;
}
data &= ~clear_mask;
data |= set_mask;
err = tps65910_write(pmic, reg, data);
if (err)
dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg);
out:
mutex_unlock(&pmic->mutex);
return err;
}
static int tps65910_reg_read(struct tps65910_reg *pmic, u8 reg)
{
int data;
mutex_lock(&pmic->mutex);
data = tps65910_read(pmic, reg);
if (data < 0)
dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg);
mutex_unlock(&pmic->mutex);
return data;
}
static int tps65910_reg_write(struct tps65910_reg *pmic, u8 reg, u8 val)
{
int err;
mutex_lock(&pmic->mutex);
err = tps65910_write(pmic, reg, val);
if (err < 0)
dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg);
mutex_unlock(&pmic->mutex);
return err;
}
static int tps65910_get_ctrl_register(int id)
{
switch (id) {
case TPS65910_REG_VRTC:
return TPS65910_VRTC;
case TPS65910_REG_VIO:
return TPS65910_VIO;
case TPS65910_REG_VDD1:
return TPS65910_VDD1;
case TPS65910_REG_VDD2:
return TPS65910_VDD2;
case TPS65910_REG_VDD3:
return TPS65910_VDD3;
case TPS65910_REG_VDIG1:
return TPS65910_VDIG1;
case TPS65910_REG_VDIG2:
return TPS65910_VDIG2;
case TPS65910_REG_VPLL:
return TPS65910_VPLL;
case TPS65910_REG_VDAC:
return TPS65910_VDAC;
case TPS65910_REG_VAUX1:
return TPS65910_VAUX1;
case TPS65910_REG_VAUX2:
return TPS65910_VAUX2;
case TPS65910_REG_VAUX33:
return TPS65910_VAUX33;
case TPS65910_REG_VMMC:
return TPS65910_VMMC;
default:
return -EINVAL;
}
}
static int tps65911_get_ctrl_register(int id)
{
switch (id) {
case TPS65910_REG_VRTC:
return TPS65910_VRTC;
case TPS65910_REG_VIO:
return TPS65910_VIO;
case TPS65910_REG_VDD1:
return TPS65910_VDD1;
case TPS65910_REG_VDD2:
return TPS65910_VDD2;
case TPS65911_REG_VDDCTRL:
return TPS65911_VDDCTRL;
case TPS65911_REG_LDO1:
return TPS65911_LDO1;
case TPS65911_REG_LDO2:
return TPS65911_LDO2;
case TPS65911_REG_LDO3:
return TPS65911_LDO3;
case TPS65911_REG_LDO4:
return TPS65911_LDO4;
case TPS65911_REG_LDO5:
return TPS65911_LDO5;
case TPS65911_REG_LDO6:
return TPS65911_LDO6;
case TPS65911_REG_LDO7:
return TPS65911_LDO7;
case TPS65911_REG_LDO8:
return TPS65911_LDO8;
default:
return -EINVAL;
}
}
static int tps65910_is_enabled(struct regulator_dev *dev)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
int reg, value, id = rdev_get_id(dev);
reg = pmic->get_ctrl_reg(id);
if (reg < 0)
return reg;
value = tps65910_reg_read(pmic, reg);
if (value < 0)
return value;
return value & TPS65910_SUPPLY_STATE_ENABLED;
}
static int tps65910_enable(struct regulator_dev *dev)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
struct tps65910 *mfd = pmic->mfd;
int reg, id = rdev_get_id(dev);
reg = pmic->get_ctrl_reg(id);
if (reg < 0)
return reg;
return tps65910_set_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED);
}
static int tps65910_disable(struct regulator_dev *dev)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
struct tps65910 *mfd = pmic->mfd;
int reg, id = rdev_get_id(dev);
reg = pmic->get_ctrl_reg(id);
if (reg < 0)
return reg;
return tps65910_clear_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED);
}
static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
struct tps65910 *mfd = pmic->mfd;
int reg, value, id = rdev_get_id(dev);
reg = pmic->get_ctrl_reg(id);
if (reg < 0)
return reg;
switch (mode) {
case REGULATOR_MODE_NORMAL:
return tps65910_modify_bits(pmic, reg, LDO_ST_ON_BIT,
LDO_ST_MODE_BIT);
case REGULATOR_MODE_IDLE:
value = LDO_ST_ON_BIT | LDO_ST_MODE_BIT;
return tps65910_set_bits(mfd, reg, value);
case REGULATOR_MODE_STANDBY:
return tps65910_clear_bits(mfd, reg, LDO_ST_ON_BIT);
}
return -EINVAL;
}
static unsigned int tps65910_get_mode(struct regulator_dev *dev)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
int reg, value, id = rdev_get_id(dev);
reg = pmic->get_ctrl_reg(id);
if (reg < 0)
return reg;
value = tps65910_reg_read(pmic, reg);
if (value < 0)
return value;
if (value & LDO_ST_ON_BIT)
return REGULATOR_MODE_STANDBY;
else if (value & LDO_ST_MODE_BIT)
return REGULATOR_MODE_IDLE;
else
return REGULATOR_MODE_NORMAL;
}
static int tps65910_get_voltage_dcdc(struct regulator_dev *dev)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
int id = rdev_get_id(dev), voltage = 0;
int opvsel = 0, srvsel = 0, vselmax = 0, mult = 0, sr = 0;
switch (id) {
case TPS65910_REG_VDD1:
opvsel = tps65910_reg_read(pmic, TPS65910_VDD1_OP);
mult = tps65910_reg_read(pmic, TPS65910_VDD1);
mult = (mult & VDD1_VGAIN_SEL_MASK) >> VDD1_VGAIN_SEL_SHIFT;
srvsel = tps65910_reg_read(pmic, TPS65910_VDD1_SR);
sr = opvsel & VDD1_OP_CMD_MASK;
opvsel &= VDD1_OP_SEL_MASK;
srvsel &= VDD1_SR_SEL_MASK;
vselmax = 75;
break;
case TPS65910_REG_VDD2:
opvsel = tps65910_reg_read(pmic, TPS65910_VDD2_OP);
mult = tps65910_reg_read(pmic, TPS65910_VDD2);
mult = (mult & VDD2_VGAIN_SEL_MASK) >> VDD2_VGAIN_SEL_SHIFT;
srvsel = tps65910_reg_read(pmic, TPS65910_VDD2_SR);
sr = opvsel & VDD2_OP_CMD_MASK;
opvsel &= VDD2_OP_SEL_MASK;
srvsel &= VDD2_SR_SEL_MASK;
vselmax = 75;
break;
case TPS65911_REG_VDDCTRL:
opvsel = tps65910_reg_read(pmic, TPS65911_VDDCTRL_OP);
srvsel = tps65910_reg_read(pmic, TPS65911_VDDCTRL_SR);
sr = opvsel & VDDCTRL_OP_CMD_MASK;
opvsel &= VDDCTRL_OP_SEL_MASK;
srvsel &= VDDCTRL_SR_SEL_MASK;
vselmax = 64;
break;
}
/* multiplier 0 == 1 but 2,3 normal */
if (!mult)
mult=1;
if (sr) {
/* normalise to valid range */
if (srvsel < 3)
srvsel = 3;
if (srvsel > vselmax)
srvsel = vselmax;
srvsel -= 3;
voltage = (srvsel * VDD1_2_OFFSET + VDD1_2_MIN_VOLT) * 100;
} else {
/* normalise to valid range*/
if (opvsel < 3)
opvsel = 3;
if (opvsel > vselmax)
opvsel = vselmax;
opvsel -= 3;
voltage = (opvsel * VDD1_2_OFFSET + VDD1_2_MIN_VOLT) * 100;
}
voltage *= mult;
return voltage;
}
static int tps65910_get_voltage(struct regulator_dev *dev)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
int reg, value, id = rdev_get_id(dev), voltage = 0;
reg = pmic->get_ctrl_reg(id);
if (reg < 0)
return reg;
value = tps65910_reg_read(pmic, reg);
if (value < 0)
return value;
switch (id) {
case TPS65910_REG_VIO:
case TPS65910_REG_VDIG1:
case TPS65910_REG_VDIG2:
case TPS65910_REG_VPLL:
case TPS65910_REG_VDAC:
case TPS65910_REG_VAUX1:
case TPS65910_REG_VAUX2:
case TPS65910_REG_VAUX33:
case TPS65910_REG_VMMC:
value &= LDO_SEL_MASK;
value >>= LDO_SEL_SHIFT;
break;
default:
return -EINVAL;
}
voltage = pmic->info[id]->table[value] * 1000;
return voltage;
}
static int tps65910_get_voltage_vdd3(struct regulator_dev *dev)
{
return 5 * 1000 * 1000;
}
static int tps65911_get_voltage(struct regulator_dev *dev)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
int step_mv, id = rdev_get_id(dev);
u8 value, reg;
reg = pmic->get_ctrl_reg(id);
value = tps65910_reg_read(pmic, reg);
switch (id) {
case TPS65911_REG_LDO1:
case TPS65911_REG_LDO2:
case TPS65911_REG_LDO4:
value &= LDO1_SEL_MASK;
value >>= LDO_SEL_SHIFT;
/* The first 5 values of the selector correspond to 1V */
if (value < 5)
value = 0;
else
value -= 4;
step_mv = 50;
break;
case TPS65911_REG_LDO3:
case TPS65911_REG_LDO5:
case TPS65911_REG_LDO6:
case TPS65911_REG_LDO7:
case TPS65911_REG_LDO8:
value &= LDO3_SEL_MASK;
value >>= LDO_SEL_SHIFT;
/* The first 3 values of the selector correspond to 1V */
if (value < 3)
value = 0;
else
value -= 2;
step_mv = 100;
break;
case TPS65910_REG_VIO:
return pmic->info[id]->table[value] * 1000;
break;
default:
return -EINVAL;
}
return (LDO_MIN_VOLT + value * step_mv) * 1000;
}
static int tps65910_set_voltage_dcdc(struct regulator_dev *dev,
unsigned selector)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
int id = rdev_get_id(dev), vsel;
int dcdc_mult = 0;
switch (id) {
case TPS65910_REG_VDD1:
dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1;
if (dcdc_mult == 1)
dcdc_mult--;
vsel = (selector % VDD1_2_NUM_VOLTS) + 3;
tps65910_modify_bits(pmic, TPS65910_VDD1,
(dcdc_mult << VDD1_VGAIN_SEL_SHIFT),
VDD1_VGAIN_SEL_MASK);
tps65910_reg_write(pmic, TPS65910_VDD1_OP, vsel);
break;
case TPS65910_REG_VDD2:
dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1;
if (dcdc_mult == 1)
dcdc_mult--;
vsel = (selector % VDD1_2_NUM_VOLTS) + 3;
tps65910_modify_bits(pmic, TPS65910_VDD2,
(dcdc_mult << VDD2_VGAIN_SEL_SHIFT),
VDD1_VGAIN_SEL_MASK);
tps65910_reg_write(pmic, TPS65910_VDD2_OP, vsel);
break;
case TPS65911_REG_VDDCTRL:
vsel = selector;
tps65910_reg_write(pmic, TPS65911_VDDCTRL_OP, vsel);
}
return 0;
}
static int tps65910_set_voltage(struct regulator_dev *dev, unsigned selector)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
int reg, id = rdev_get_id(dev);
reg = pmic->get_ctrl_reg(id);
if (reg < 0)
return reg;
switch (id) {
case TPS65910_REG_VIO:
case TPS65910_REG_VDIG1:
case TPS65910_REG_VDIG2:
case TPS65910_REG_VPLL:
case TPS65910_REG_VDAC:
case TPS65910_REG_VAUX1:
case TPS65910_REG_VAUX2:
case TPS65910_REG_VAUX33:
case TPS65910_REG_VMMC:
return tps65910_modify_bits(pmic, reg,
(selector << LDO_SEL_SHIFT), LDO_SEL_MASK);
}
return -EINVAL;
}
static int tps65911_set_voltage(struct regulator_dev *dev, unsigned selector)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
int reg, id = rdev_get_id(dev);
reg = pmic->get_ctrl_reg(id);
if (reg < 0)
return reg;
switch (id) {
case TPS65911_REG_LDO1:
case TPS65911_REG_LDO2:
case TPS65911_REG_LDO4:
return tps65910_modify_bits(pmic, reg,
(selector << LDO_SEL_SHIFT), LDO1_SEL_MASK);
case TPS65911_REG_LDO3:
case TPS65911_REG_LDO5:
case TPS65911_REG_LDO6:
case TPS65911_REG_LDO7:
case TPS65911_REG_LDO8:
case TPS65910_REG_VIO:
return tps65910_modify_bits(pmic, reg,
(selector << LDO_SEL_SHIFT), LDO3_SEL_MASK);
}
return -EINVAL;
}
static int tps65910_list_voltage_dcdc(struct regulator_dev *dev,
unsigned selector)
{
int volt, mult = 1, id = rdev_get_id(dev);
switch (id) {
case TPS65910_REG_VDD1:
case TPS65910_REG_VDD2:
mult = (selector / VDD1_2_NUM_VOLTS) + 1;
volt = VDD1_2_MIN_VOLT +
(selector % VDD1_2_NUM_VOLTS) * VDD1_2_OFFSET;
case TPS65911_REG_VDDCTRL:
volt = VDDCTRL_MIN_VOLT + (selector * VDDCTRL_OFFSET);
}
return volt * 100 * mult;
}
static int tps65910_list_voltage(struct regulator_dev *dev,
unsigned selector)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
int id = rdev_get_id(dev), voltage;
if (id < TPS65910_REG_VIO || id > TPS65910_REG_VMMC)
return -EINVAL;
if (selector >= pmic->info[id]->table_len)
return -EINVAL;
else
voltage = pmic->info[id]->table[selector] * 1000;
return voltage;
}
static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector)
{
struct tps65910_reg *pmic = rdev_get_drvdata(dev);
int step_mv = 0, id = rdev_get_id(dev);
switch(id) {
case TPS65911_REG_LDO1:
case TPS65911_REG_LDO2:
case TPS65911_REG_LDO4:
/* The first 5 values of the selector correspond to 1V */
if (selector < 5)
selector = 0;
else
selector -= 4;
step_mv = 50;
break;
case TPS65911_REG_LDO3:
case TPS65911_REG_LDO5:
case TPS65911_REG_LDO6:
case TPS65911_REG_LDO7:
case TPS65911_REG_LDO8:
/* The first 3 values of the selector correspond to 1V */
if (selector < 3)
selector = 0;
else
selector -= 2;
step_mv = 100;
break;
case TPS65910_REG_VIO:
return pmic->info[id]->table[selector] * 1000;
default:
return -EINVAL;
}
return (LDO_MIN_VOLT + selector * step_mv) * 1000;
}
/* Regulator ops (except VRTC) */
static struct regulator_ops tps65910_ops_dcdc = {
.is_enabled = tps65910_is_enabled,
.enable = tps65910_enable,
.disable = tps65910_disable,
.set_mode = tps65910_set_mode,
.get_mode = tps65910_get_mode,
.get_voltage = tps65910_get_voltage_dcdc,
.set_voltage_sel = tps65910_set_voltage_dcdc,
.list_voltage = tps65910_list_voltage_dcdc,
};
static struct regulator_ops tps65910_ops_vdd3 = {
.is_enabled = tps65910_is_enabled,
.enable = tps65910_enable,
.disable = tps65910_disable,
.set_mode = tps65910_set_mode,
.get_mode = tps65910_get_mode,
.get_voltage = tps65910_get_voltage_vdd3,
.list_voltage = tps65910_list_voltage,
};
static struct regulator_ops tps65910_ops = {
.is_enabled = tps65910_is_enabled,
.enable = tps65910_enable,
.disable = tps65910_disable,
.set_mode = tps65910_set_mode,
.get_mode = tps65910_get_mode,
.get_voltage = tps65910_get_voltage,
.set_voltage_sel = tps65910_set_voltage,
.list_voltage = tps65910_list_voltage,
};
static struct regulator_ops tps65911_ops = {
.is_enabled = tps65910_is_enabled,
.enable = tps65910_enable,
.disable = tps65910_disable,
.set_mode = tps65910_set_mode,
.get_mode = tps65910_get_mode,
.get_voltage = tps65911_get_voltage,
.set_voltage_sel = tps65911_set_voltage,
.list_voltage = tps65911_list_voltage,
};
static __devinit int tps65910_probe(struct platform_device *pdev)
{
struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
struct tps_info *info;
struct regulator_init_data *reg_data;
struct regulator_dev *rdev;
struct tps65910_reg *pmic;
struct tps65910_board *pmic_plat_data;
int i, err;
pmic_plat_data = dev_get_platdata(tps65910->dev);
if (!pmic_plat_data)
return -EINVAL;
reg_data = pmic_plat_data->tps65910_pmic_init_data;
pmic = kzalloc(sizeof(*pmic), GFP_KERNEL);
if (!pmic)
return -ENOMEM;
mutex_init(&pmic->mutex);
pmic->mfd = tps65910;
platform_set_drvdata(pdev, pmic);
/* Give control of all register to control port */
tps65910_set_bits(pmic->mfd, TPS65910_DEVCTRL,
DEVCTRL_SR_CTL_I2C_SEL_MASK);
switch(tps65910_chip_id(tps65910)) {
case TPS65910:
pmic->get_ctrl_reg = &tps65910_get_ctrl_register;
info = tps65910_regs;
case TPS65911:
pmic->get_ctrl_reg = &tps65911_get_ctrl_register;
info = tps65911_regs;
default:
pr_err("Invalid tps chip version\n");
return -ENODEV;
}
for (i = 0; i < TPS65910_NUM_REGULATOR; i++, info++, reg_data++) {
/* Register the regulators */
pmic->info[i] = info;
pmic->desc[i].name = info->name;
pmic->desc[i].id = i;
pmic->desc[i].n_voltages = info->table_len;
if (i == TPS65910_REG_VDD1 || i == TPS65910_REG_VDD2) {
pmic->desc[i].ops = &tps65910_ops_dcdc;
} else if (i == TPS65910_REG_VDD3) {
if (tps65910_chip_id(tps65910) == TPS65910)
pmic->desc[i].ops = &tps65910_ops_vdd3;
else
pmic->desc[i].ops = &tps65910_ops_dcdc;
} else {
if (tps65910_chip_id(tps65910) == TPS65910)
pmic->desc[i].ops = &tps65910_ops;
else
pmic->desc[i].ops = &tps65911_ops;
}
pmic->desc[i].type = REGULATOR_VOLTAGE;
pmic->desc[i].owner = THIS_MODULE;
rdev = regulator_register(&pmic->desc[i],
tps65910->dev, reg_data, pmic);
if (IS_ERR(rdev)) {
dev_err(tps65910->dev,
"failed to register %s regulator\n",
pdev->name);
err = PTR_ERR(rdev);
goto err;
}
/* Save regulator for cleanup */
pmic->rdev[i] = rdev;
}
return 0;
err:
while (--i >= 0)
regulator_unregister(pmic->rdev[i]);
kfree(pmic);
return err;
}
static int __devexit tps65910_remove(struct platform_device *pdev)
{
struct tps65910_reg *tps65910_reg = platform_get_drvdata(pdev);
int i;
for (i = 0; i < TPS65910_NUM_REGULATOR; i++)
regulator_unregister(tps65910_reg->rdev[i]);
kfree(tps65910_reg);
return 0;
}
static struct platform_driver tps65910_driver = {
.driver = {
.name = "tps65910-pmic",
.owner = THIS_MODULE,
},
.probe = tps65910_probe,
.remove = __devexit_p(tps65910_remove),
};
static int __init tps65910_init(void)
{
return platform_driver_register(&tps65910_driver);
}
subsys_initcall(tps65910_init);
static void __exit tps65910_cleanup(void)
{
platform_driver_unregister(&tps65910_driver);
}
module_exit(tps65910_cleanup);
MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
MODULE_DESCRIPTION("TPS6507x voltage regulator driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:tps65910-pmic");

View File

@ -51,8 +51,13 @@ struct twlreg_info {
u16 min_mV;
u16 max_mV;
u8 flags;
/* used by regulator core */
struct regulator_desc desc;
/* chip specific features */
unsigned long features;
};
@ -70,12 +75,35 @@ struct twlreg_info {
#define VREG_TRANS 1
#define VREG_STATE 2
#define VREG_VOLTAGE 3
#define VREG_VOLTAGE_SMPS 4
/* TWL6030 Misc register offsets */
#define VREG_BC_ALL 1
#define VREG_BC_REF 2
#define VREG_BC_PROC 3
#define VREG_BC_CLK_RST 4
/* TWL6030 LDO register values for CFG_STATE */
#define TWL6030_CFG_STATE_OFF 0x00
#define TWL6030_CFG_STATE_ON 0x01
#define TWL6030_CFG_STATE_OFF2 0x02
#define TWL6030_CFG_STATE_SLEEP 0x03
#define TWL6030_CFG_STATE_GRP_SHIFT 5
#define TWL6030_CFG_STATE_APP_SHIFT 2
#define TWL6030_CFG_STATE_APP_MASK (0x03 << TWL6030_CFG_STATE_APP_SHIFT)
#define TWL6030_CFG_STATE_APP(v) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\
TWL6030_CFG_STATE_APP_SHIFT)
/* Flags for SMPS Voltage reading */
#define SMPS_OFFSET_EN BIT(0)
#define SMPS_EXTENDED_EN BIT(1)
/* twl6025 SMPS EPROM values */
#define TWL6030_SMPS_OFFSET 0xB0
#define TWL6030_SMPS_MULT 0xB3
#define SMPS_MULTOFFSET_SMPS4 BIT(0)
#define SMPS_MULTOFFSET_VIO BIT(1)
#define SMPS_MULTOFFSET_SMPS3 BIT(6)
static inline int
twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset)
{
@ -118,21 +146,38 @@ static int twlreg_grp(struct regulator_dev *rdev)
#define P2_GRP_6030 BIT(1) /* "peripherals" */
#define P1_GRP_6030 BIT(0) /* CPU/Linux */
static int twlreg_is_enabled(struct regulator_dev *rdev)
static int twl4030reg_is_enabled(struct regulator_dev *rdev)
{
int state = twlreg_grp(rdev);
if (state < 0)
return state;
if (twl_class_is_4030())
state &= P1_GRP_4030;
else
state &= P1_GRP_6030;
return state;
return state & P1_GRP_4030;
}
static int twlreg_enable(struct regulator_dev *rdev)
static int twl6030reg_is_enabled(struct regulator_dev *rdev)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
int grp = 0, val;
if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
if (grp < 0)
return grp;
if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
grp &= P1_GRP_6030;
else
grp = 1;
val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
val = TWL6030_CFG_STATE_APP(val);
return grp && (val == TWL6030_CFG_STATE_ON);
}
static int twl4030reg_enable(struct regulator_dev *rdev)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
int grp;
@ -142,10 +187,7 @@ static int twlreg_enable(struct regulator_dev *rdev)
if (grp < 0)
return grp;
if (twl_class_is_4030())
grp |= P1_GRP_4030;
else
grp |= P1_GRP_6030;
grp |= P1_GRP_4030;
ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp);
@ -154,30 +196,64 @@ static int twlreg_enable(struct regulator_dev *rdev)
return ret;
}
static int twlreg_disable(struct regulator_dev *rdev)
static int twl6030reg_enable(struct regulator_dev *rdev)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
int grp = 0;
int ret;
if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
if (grp < 0)
return grp;
ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE,
grp << TWL6030_CFG_STATE_GRP_SHIFT |
TWL6030_CFG_STATE_ON);
udelay(info->delay);
return ret;
}
static int twl4030reg_disable(struct regulator_dev *rdev)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
int grp;
int ret;
grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
if (grp < 0)
return grp;
if (twl_class_is_4030())
grp &= ~(P1_GRP_4030 | P2_GRP_4030 | P3_GRP_4030);
else
grp &= ~(P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030);
grp &= ~(P1_GRP_4030 | P2_GRP_4030 | P3_GRP_4030);
return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp);
ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp);
return ret;
}
static int twlreg_get_status(struct regulator_dev *rdev)
static int twl6030reg_disable(struct regulator_dev *rdev)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
int grp = 0;
int ret;
if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
grp = P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030;
/* For 6030, set the off state for all grps enabled */
ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE,
(grp) << TWL6030_CFG_STATE_GRP_SHIFT |
TWL6030_CFG_STATE_OFF);
return ret;
}
static int twl4030reg_get_status(struct regulator_dev *rdev)
{
int state = twlreg_grp(rdev);
if (twl_class_is_6030())
return 0; /* FIXME return for 6030 regulator */
if (state < 0)
return state;
state &= 0x0f;
@ -190,15 +266,39 @@ static int twlreg_get_status(struct regulator_dev *rdev)
: REGULATOR_STATUS_STANDBY;
}
static int twlreg_set_mode(struct regulator_dev *rdev, unsigned mode)
static int twl6030reg_get_status(struct regulator_dev *rdev)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
int val;
val = twlreg_grp(rdev);
if (val < 0)
return val;
val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
switch (TWL6030_CFG_STATE_APP(val)) {
case TWL6030_CFG_STATE_ON:
return REGULATOR_STATUS_NORMAL;
case TWL6030_CFG_STATE_SLEEP:
return REGULATOR_STATUS_STANDBY;
case TWL6030_CFG_STATE_OFF:
case TWL6030_CFG_STATE_OFF2:
default:
break;
}
return REGULATOR_STATUS_OFF;
}
static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
unsigned message;
int status;
if (twl_class_is_6030())
return 0; /* FIXME return for 6030 regulator */
/* We can only set the mode through state machine commands... */
switch (mode) {
case REGULATOR_MODE_NORMAL:
@ -227,6 +327,36 @@ static int twlreg_set_mode(struct regulator_dev *rdev, unsigned mode)
message & 0xff, TWL4030_PM_MASTER_PB_WORD_LSB);
}
static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
int grp = 0;
int val;
if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
if (grp < 0)
return grp;
/* Compose the state register settings */
val = grp << TWL6030_CFG_STATE_GRP_SHIFT;
/* We can only set the mode through state machine commands... */
switch (mode) {
case REGULATOR_MODE_NORMAL:
val |= TWL6030_CFG_STATE_ON;
break;
case REGULATOR_MODE_STANDBY:
val |= TWL6030_CFG_STATE_SLEEP;
break;
default:
return -EINVAL;
}
return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, val);
}
/*----------------------------------------------------------------------*/
/*
@ -375,13 +505,13 @@ static struct regulator_ops twl4030ldo_ops = {
.set_voltage = twl4030ldo_set_voltage,
.get_voltage = twl4030ldo_get_voltage,
.enable = twlreg_enable,
.disable = twlreg_disable,
.is_enabled = twlreg_is_enabled,
.enable = twl4030reg_enable,
.disable = twl4030reg_disable,
.is_enabled = twl4030reg_is_enabled,
.set_mode = twlreg_set_mode,
.set_mode = twl4030reg_set_mode,
.get_status = twlreg_get_status,
.get_status = twl4030reg_get_status,
};
static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
@ -433,13 +563,13 @@ static struct regulator_ops twl6030ldo_ops = {
.set_voltage = twl6030ldo_set_voltage,
.get_voltage = twl6030ldo_get_voltage,
.enable = twlreg_enable,
.disable = twlreg_disable,
.is_enabled = twlreg_is_enabled,
.enable = twl6030reg_enable,
.disable = twl6030reg_disable,
.is_enabled = twl6030reg_is_enabled,
.set_mode = twlreg_set_mode,
.set_mode = twl6030reg_set_mode,
.get_status = twlreg_get_status,
.get_status = twl6030reg_get_status,
};
/*----------------------------------------------------------------------*/
@ -461,25 +591,242 @@ static int twlfixed_get_voltage(struct regulator_dev *rdev)
return info->min_mV * 1000;
}
static struct regulator_ops twlfixed_ops = {
static struct regulator_ops twl4030fixed_ops = {
.list_voltage = twlfixed_list_voltage,
.get_voltage = twlfixed_get_voltage,
.enable = twlreg_enable,
.disable = twlreg_disable,
.is_enabled = twlreg_is_enabled,
.enable = twl4030reg_enable,
.disable = twl4030reg_disable,
.is_enabled = twl4030reg_is_enabled,
.set_mode = twlreg_set_mode,
.set_mode = twl4030reg_set_mode,
.get_status = twlreg_get_status,
.get_status = twl4030reg_get_status,
};
static struct regulator_ops twl6030fixed_ops = {
.list_voltage = twlfixed_list_voltage,
.get_voltage = twlfixed_get_voltage,
.enable = twl6030reg_enable,
.disable = twl6030reg_disable,
.is_enabled = twl6030reg_is_enabled,
.set_mode = twl6030reg_set_mode,
.get_status = twl6030reg_get_status,
};
static struct regulator_ops twl6030_fixed_resource = {
.enable = twlreg_enable,
.disable = twlreg_disable,
.is_enabled = twlreg_is_enabled,
.get_status = twlreg_get_status,
.enable = twl6030reg_enable,
.disable = twl6030reg_disable,
.is_enabled = twl6030reg_is_enabled,
.get_status = twl6030reg_get_status,
};
/*
* SMPS status and control
*/
static int twl6030smps_list_voltage(struct regulator_dev *rdev, unsigned index)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
int voltage = 0;
switch (info->flags) {
case SMPS_OFFSET_EN:
voltage = 100000;
/* fall through */
case 0:
switch (index) {
case 0:
voltage = 0;
break;
case 58:
voltage = 1350 * 1000;
break;
case 59:
voltage = 1500 * 1000;
break;
case 60:
voltage = 1800 * 1000;
break;
case 61:
voltage = 1900 * 1000;
break;
case 62:
voltage = 2100 * 1000;
break;
default:
voltage += (600000 + (12500 * (index - 1)));
}
break;
case SMPS_EXTENDED_EN:
switch (index) {
case 0:
voltage = 0;
break;
case 58:
voltage = 2084 * 1000;
break;
case 59:
voltage = 2315 * 1000;
break;
case 60:
voltage = 2778 * 1000;
break;
case 61:
voltage = 2932 * 1000;
break;
case 62:
voltage = 3241 * 1000;
break;
default:
voltage = (1852000 + (38600 * (index - 1)));
}
break;
case SMPS_OFFSET_EN | SMPS_EXTENDED_EN:
switch (index) {
case 0:
voltage = 0;
break;
case 58:
voltage = 4167 * 1000;
break;
case 59:
voltage = 2315 * 1000;
break;
case 60:
voltage = 2778 * 1000;
break;
case 61:
voltage = 2932 * 1000;
break;
case 62:
voltage = 3241 * 1000;
break;
default:
voltage = (2161000 + (38600 * (index - 1)));
}
break;
}
return voltage;
}
static int
twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
unsigned int *selector)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
int vsel = 0;
switch (info->flags) {
case 0:
if (min_uV == 0)
vsel = 0;
else if ((min_uV >= 600000) && (max_uV <= 1300000)) {
vsel = (min_uV - 600000) / 125;
if (vsel % 100)
vsel += 100;
vsel /= 100;
vsel++;
}
/* Values 1..57 for vsel are linear and can be calculated
* values 58..62 are non linear.
*/
else if ((min_uV > 1900000) && (max_uV >= 2100000))
vsel = 62;
else if ((min_uV > 1800000) && (max_uV >= 1900000))
vsel = 61;
else if ((min_uV > 1500000) && (max_uV >= 1800000))
vsel = 60;
else if ((min_uV > 1350000) && (max_uV >= 1500000))
vsel = 59;
else if ((min_uV > 1300000) && (max_uV >= 1350000))
vsel = 58;
else
return -EINVAL;
break;
case SMPS_OFFSET_EN:
if (min_uV == 0)
vsel = 0;
else if ((min_uV >= 700000) && (max_uV <= 1420000)) {
vsel = (min_uV - 700000) / 125;
if (vsel % 100)
vsel += 100;
vsel /= 100;
vsel++;
}
/* Values 1..57 for vsel are linear and can be calculated
* values 58..62 are non linear.
*/
else if ((min_uV > 1900000) && (max_uV >= 2100000))
vsel = 62;
else if ((min_uV > 1800000) && (max_uV >= 1900000))
vsel = 61;
else if ((min_uV > 1350000) && (max_uV >= 1800000))
vsel = 60;
else if ((min_uV > 1350000) && (max_uV >= 1500000))
vsel = 59;
else if ((min_uV > 1300000) && (max_uV >= 1350000))
vsel = 58;
else
return -EINVAL;
break;
case SMPS_EXTENDED_EN:
if (min_uV == 0)
vsel = 0;
else if ((min_uV >= 1852000) && (max_uV <= 4013600)) {
vsel = (min_uV - 1852000) / 386;
if (vsel % 100)
vsel += 100;
vsel /= 100;
vsel++;
}
break;
case SMPS_OFFSET_EN|SMPS_EXTENDED_EN:
if (min_uV == 0)
vsel = 0;
else if ((min_uV >= 2161000) && (max_uV <= 4321000)) {
vsel = (min_uV - 1852000) / 386;
if (vsel % 100)
vsel += 100;
vsel /= 100;
vsel++;
}
break;
}
*selector = vsel;
return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS,
vsel);
}
static int twl6030smps_get_voltage_sel(struct regulator_dev *rdev)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
return twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS);
}
static struct regulator_ops twlsmps_ops = {
.list_voltage = twl6030smps_list_voltage,
.set_voltage = twl6030smps_set_voltage,
.get_voltage_sel = twl6030smps_get_voltage_sel,
.enable = twl6030reg_enable,
.disable = twl6030reg_disable,
.is_enabled = twl6030reg_is_enabled,
.set_mode = twl6030reg_set_mode,
.get_status = twl6030reg_get_status,
};
/*----------------------------------------------------------------------*/
@ -487,11 +834,10 @@ static struct regulator_ops twl6030_fixed_resource = {
#define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
remap_conf) \
TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
remap_conf, TWL4030)
#define TWL6030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
remap_conf) \
remap_conf, TWL4030, twl4030fixed_ops)
#define TWL6030_FIXED_LDO(label, offset, mVolts, num, turnon_delay) \
TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
remap_conf, TWL6030)
0x0, TWL6030, twl6030fixed_ops)
#define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) { \
.base = offset, \
@ -510,13 +856,11 @@ static struct regulator_ops twl6030_fixed_resource = {
}, \
}
#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num, \
remap_conf) { \
#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \
.base = offset, \
.id = num, \
.min_mV = min_mVolts, \
.max_mV = max_mVolts, \
.remap = remap_conf, \
.desc = { \
.name = #label, \
.id = TWL6030_REG_##label, \
@ -527,9 +871,23 @@ static struct regulator_ops twl6030_fixed_resource = {
}, \
}
#define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \
.base = offset, \
.id = num, \
.min_mV = min_mVolts, \
.max_mV = max_mVolts, \
.desc = { \
.name = #label, \
.id = TWL6025_REG_##label, \
.n_voltages = ((max_mVolts - min_mVolts)/100) + 1, \
.ops = &twl6030ldo_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}, \
}
#define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \
family) { \
family, operations) { \
.base = offset, \
.id = num, \
.min_mV = mVolts, \
@ -539,17 +897,16 @@ static struct regulator_ops twl6030_fixed_resource = {
.name = #label, \
.id = family##_REG_##label, \
.n_voltages = 1, \
.ops = &twlfixed_ops, \
.ops = &operations, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}, \
}
#define TWL6030_FIXED_RESOURCE(label, offset, num, turnon_delay, remap_conf) { \
#define TWL6030_FIXED_RESOURCE(label, offset, num, turnon_delay) { \
.base = offset, \
.id = num, \
.delay = turnon_delay, \
.remap = remap_conf, \
.desc = { \
.name = #label, \
.id = TWL6030_REG_##label, \
@ -559,6 +916,21 @@ static struct regulator_ops twl6030_fixed_resource = {
}, \
}
#define TWL6025_ADJUSTABLE_SMPS(label, offset, num) { \
.base = offset, \
.id = num, \
.min_mV = 600, \
.max_mV = 2100, \
.desc = { \
.name = #label, \
.id = TWL6025_REG_##label, \
.n_voltages = 63, \
.ops = &twlsmps_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}, \
}
/*
* We list regulators here if systems need some level of
* software control over them after boot.
@ -589,19 +961,52 @@ 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, 1000, 3300, 1, 0x21),
TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300, 2, 0x21),
TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300, 3, 0x21),
TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300, 4, 0x21),
TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300, 5, 0x21),
TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300, 7, 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),
TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 48, 0, 0x21),
TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300, 1),
TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300, 2),
TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300, 3),
TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300, 4),
TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300, 5),
TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300, 7),
TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0),
TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0),
TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0),
TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0),
TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 48, 0),
/* 6025 are renamed compared to 6030 versions */
TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300, 1),
TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300, 2),
TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300, 3),
TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300, 4),
TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300, 5),
TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300, 7),
TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300, 16),
TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300, 17),
TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300, 18),
TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34, 1),
TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10, 2),
TWL6025_ADJUSTABLE_SMPS(VIO, 0x16, 3),
};
static u8 twl_get_smps_offset(void)
{
u8 value;
twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &value,
TWL6030_SMPS_OFFSET);
return value;
}
static u8 twl_get_smps_mult(void)
{
u8 value;
twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &value,
TWL6030_SMPS_MULT);
return value;
}
static int __devinit twlreg_probe(struct platform_device *pdev)
{
int i;
@ -623,6 +1028,9 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
if (!initdata)
return -EINVAL;
/* copy the features into regulator data */
info->features = (unsigned long)initdata->driver_data;
/* Constrain board-specific capabilities according to what
* this driver and the chip itself can actually do.
*/
@ -645,6 +1053,27 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
break;
}
switch (pdev->id) {
case TWL6025_REG_SMPS3:
if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3)
info->flags |= SMPS_EXTENDED_EN;
if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS3)
info->flags |= SMPS_OFFSET_EN;
break;
case TWL6025_REG_SMPS4:
if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS4)
info->flags |= SMPS_EXTENDED_EN;
if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS4)
info->flags |= SMPS_OFFSET_EN;
break;
case TWL6025_REG_VIO:
if (twl_get_smps_mult() & SMPS_MULTOFFSET_VIO)
info->flags |= SMPS_EXTENDED_EN;
if (twl_get_smps_offset() & SMPS_MULTOFFSET_VIO)
info->flags |= SMPS_OFFSET_EN;
break;
}
rdev = regulator_register(&info->desc, &pdev->dev, initdata, info);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "can't register %s, %ld\n",
@ -653,7 +1082,8 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, rdev);
twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP,
if (twl_class_is_4030())
twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP,
info->remap);
/* NOTE: many regulators support short-circuit IRQs (presentable

View File

@ -600,7 +600,6 @@ err:
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);
@ -776,7 +775,6 @@ err:
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);

View File

@ -55,7 +55,7 @@ static int wm8400_ldo_list_voltage(struct regulator_dev *dev,
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);
u16 val;
@ -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_LDO1_VSEL_MASK;
return wm8400_ldo_list_voltage(dev, val);
return val;
}
static int wm8400_ldo_set_voltage(struct regulator_dev *dev,
@ -104,7 +104,7 @@ static struct regulator_ops wm8400_ldo_ops = {
.enable = wm8400_ldo_enable,
.disable = wm8400_ldo_disable,
.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,
};
@ -145,7 +145,7 @@ static int wm8400_dcdc_list_voltage(struct regulator_dev *dev,
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);
u16 val;
@ -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_DC1_VSEL_MASK;
return 850000 + (25000 * val);
return val;
}
static int wm8400_dcdc_set_voltage(struct regulator_dev *dev,
@ -261,7 +261,7 @@ static struct regulator_ops wm8400_dcdc_ops = {
.enable = wm8400_dcdc_enable,
.disable = wm8400_dcdc_disable,
.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,
.get_mode = wm8400_dcdc_get_mode,
.set_mode = wm8400_dcdc_set_mode,

View File

@ -100,6 +100,7 @@ struct twl6030_usb {
u8 linkstat;
u8 asleep;
bool irq_enabled;
unsigned long features;
};
#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)
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 */
twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG);
@ -214,7 +221,7 @@ static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
/* Program MISC2 register and set bit VUSB_IN_VBAT */
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))
return -ENODEV;
@ -409,6 +416,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
twl->dev = &pdev->dev;
twl->irq1 = platform_get_irq(pdev, 0);
twl->irq2 = platform_get_irq(pdev, 1);
twl->features = pdata->features;
twl->otg.dev = twl->dev;
twl->otg.label = "twl6030";
twl->otg.set_host = twl6030_set_host;

View File

@ -311,10 +311,6 @@ enum max8997_irq {
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
struct max8997_dev {
struct device *dev;

View File

@ -0,0 +1,800 @@
/*
* tps65910.h -- TI TPS6591x
*
* Copyright 2010-2011 Texas Instruments Inc.
*
* Author: Graeme Gregory <gg@slimlogic.co.uk>
* Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>
* Author: Arnaud Deconinck <a-deconinck@ti.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.
*
*/
#ifndef __LINUX_MFD_TPS65910_H
#define __LINUX_MFD_TPS65910_H
/* TPS chip id list */
#define TPS65910 0
#define TPS65911 1
/* TPS regulator type list */
#define REGULATOR_LDO 0
#define REGULATOR_DCDC 1
/*
* List of registers for component TPS65910
*
*/
#define TPS65910_SECONDS 0x0
#define TPS65910_MINUTES 0x1
#define TPS65910_HOURS 0x2
#define TPS65910_DAYS 0x3
#define TPS65910_MONTHS 0x4
#define TPS65910_YEARS 0x5
#define TPS65910_WEEKS 0x6
#define TPS65910_ALARM_SECONDS 0x8
#define TPS65910_ALARM_MINUTES 0x9
#define TPS65910_ALARM_HOURS 0xA
#define TPS65910_ALARM_DAYS 0xB
#define TPS65910_ALARM_MONTHS 0xC
#define TPS65910_ALARM_YEARS 0xD
#define TPS65910_RTC_CTRL 0x10
#define TPS65910_RTC_STATUS 0x11
#define TPS65910_RTC_INTERRUPTS 0x12
#define TPS65910_RTC_COMP_LSB 0x13
#define TPS65910_RTC_COMP_MSB 0x14
#define TPS65910_RTC_RES_PROG 0x15
#define TPS65910_RTC_RESET_STATUS 0x16
#define TPS65910_BCK1 0x17
#define TPS65910_BCK2 0x18
#define TPS65910_BCK3 0x19
#define TPS65910_BCK4 0x1A
#define TPS65910_BCK5 0x1B
#define TPS65910_PUADEN 0x1C
#define TPS65910_REF 0x1D
#define TPS65910_VRTC 0x1E
#define TPS65910_VIO 0x20
#define TPS65910_VDD1 0x21
#define TPS65910_VDD1_OP 0x22
#define TPS65910_VDD1_SR 0x23
#define TPS65910_VDD2 0x24
#define TPS65910_VDD2_OP 0x25
#define TPS65910_VDD2_SR 0x26
#define TPS65910_VDD3 0x27
#define TPS65910_VDIG1 0x30
#define TPS65910_VDIG2 0x31
#define TPS65910_VAUX1 0x32
#define TPS65910_VAUX2 0x33
#define TPS65910_VAUX33 0x34
#define TPS65910_VMMC 0x35
#define TPS65910_VPLL 0x36
#define TPS65910_VDAC 0x37
#define TPS65910_THERM 0x38
#define TPS65910_BBCH 0x39
#define TPS65910_DCDCCTRL 0x3E
#define TPS65910_DEVCTRL 0x3F
#define TPS65910_DEVCTRL2 0x40
#define TPS65910_SLEEP_KEEP_LDO_ON 0x41
#define TPS65910_SLEEP_KEEP_RES_ON 0x42
#define TPS65910_SLEEP_SET_LDO_OFF 0x43
#define TPS65910_SLEEP_SET_RES_OFF 0x44
#define TPS65910_EN1_LDO_ASS 0x45
#define TPS65910_EN1_SMPS_ASS 0x46
#define TPS65910_EN2_LDO_ASS 0x47
#define TPS65910_EN2_SMPS_ASS 0x48
#define TPS65910_EN3_LDO_ASS 0x49
#define TPS65910_SPARE 0x4A
#define TPS65910_INT_STS 0x50
#define TPS65910_INT_MSK 0x51
#define TPS65910_INT_STS2 0x52
#define TPS65910_INT_MSK2 0x53
#define TPS65910_INT_STS3 0x54
#define TPS65910_INT_MSK3 0x55
#define TPS65910_GPIO0 0x60
#define TPS65910_GPIO1 0x61
#define TPS65910_GPIO2 0x62
#define TPS65910_GPIO3 0x63
#define TPS65910_GPIO4 0x64
#define TPS65910_GPIO5 0x65
#define TPS65910_GPIO6 0x66
#define TPS65910_GPIO7 0x67
#define TPS65910_GPIO8 0x68
#define TPS65910_JTAGVERNUM 0x80
#define TPS65910_MAX_REGISTER 0x80
/*
* List of registers specific to TPS65911
*/
#define TPS65911_VDDCTRL 0x27
#define TPS65911_VDDCTRL_OP 0x28
#define TPS65911_VDDCTRL_SR 0x29
#define TPS65911_LDO1 0x30
#define TPS65911_LDO2 0x31
#define TPS65911_LDO5 0x32
#define TPS65911_LDO8 0x33
#define TPS65911_LDO7 0x34
#define TPS65911_LDO6 0x35
#define TPS65911_LDO4 0x36
#define TPS65911_LDO3 0x37
#define TPS65911_VMBCH 0x6A
#define TPS65911_VMBCH2 0x6B
/*
* List of register bitfields for component TPS65910
*
*/
/*Register BCK1 (0x80) register.RegisterDescription */
#define BCK1_BCKUP_MASK 0xFF
#define BCK1_BCKUP_SHIFT 0
/*Register BCK2 (0x80) register.RegisterDescription */
#define BCK2_BCKUP_MASK 0xFF
#define BCK2_BCKUP_SHIFT 0
/*Register BCK3 (0x80) register.RegisterDescription */
#define BCK3_BCKUP_MASK 0xFF
#define BCK3_BCKUP_SHIFT 0
/*Register BCK4 (0x80) register.RegisterDescription */
#define BCK4_BCKUP_MASK 0xFF
#define BCK4_BCKUP_SHIFT 0
/*Register BCK5 (0x80) register.RegisterDescription */
#define BCK5_BCKUP_MASK 0xFF
#define BCK5_BCKUP_SHIFT 0
/*Register PUADEN (0x80) register.RegisterDescription */
#define PUADEN_EN3P_MASK 0x80
#define PUADEN_EN3P_SHIFT 7
#define PUADEN_I2CCTLP_MASK 0x40
#define PUADEN_I2CCTLP_SHIFT 6
#define PUADEN_I2CSRP_MASK 0x20
#define PUADEN_I2CSRP_SHIFT 5
#define PUADEN_PWRONP_MASK 0x10
#define PUADEN_PWRONP_SHIFT 4
#define PUADEN_SLEEPP_MASK 0x08
#define PUADEN_SLEEPP_SHIFT 3
#define PUADEN_PWRHOLDP_MASK 0x04
#define PUADEN_PWRHOLDP_SHIFT 2
#define PUADEN_BOOT1P_MASK 0x02
#define PUADEN_BOOT1P_SHIFT 1
#define PUADEN_BOOT0P_MASK 0x01
#define PUADEN_BOOT0P_SHIFT 0
/*Register REF (0x80) register.RegisterDescription */
#define REF_VMBCH_SEL_MASK 0x0C
#define REF_VMBCH_SEL_SHIFT 2
#define REF_ST_MASK 0x03
#define REF_ST_SHIFT 0
/*Register VRTC (0x80) register.RegisterDescription */
#define VRTC_VRTC_OFFMASK_MASK 0x08
#define VRTC_VRTC_OFFMASK_SHIFT 3
#define VRTC_ST_MASK 0x03
#define VRTC_ST_SHIFT 0
/*Register VIO (0x80) register.RegisterDescription */
#define VIO_ILMAX_MASK 0xC0
#define VIO_ILMAX_SHIFT 6
#define VIO_SEL_MASK 0x0C
#define VIO_SEL_SHIFT 2
#define VIO_ST_MASK 0x03
#define VIO_ST_SHIFT 0
/*Register VDD1 (0x80) register.RegisterDescription */
#define VDD1_VGAIN_SEL_MASK 0xC0
#define VDD1_VGAIN_SEL_SHIFT 6
#define VDD1_ILMAX_MASK 0x20
#define VDD1_ILMAX_SHIFT 5
#define VDD1_TSTEP_MASK 0x1C
#define VDD1_TSTEP_SHIFT 2
#define VDD1_ST_MASK 0x03
#define VDD1_ST_SHIFT 0
/*Register VDD1_OP (0x80) register.RegisterDescription */
#define VDD1_OP_CMD_MASK 0x80
#define VDD1_OP_CMD_SHIFT 7
#define VDD1_OP_SEL_MASK 0x7F
#define VDD1_OP_SEL_SHIFT 0
/*Register VDD1_SR (0x80) register.RegisterDescription */
#define VDD1_SR_SEL_MASK 0x7F
#define VDD1_SR_SEL_SHIFT 0
/*Register VDD2 (0x80) register.RegisterDescription */
#define VDD2_VGAIN_SEL_MASK 0xC0
#define VDD2_VGAIN_SEL_SHIFT 6
#define VDD2_ILMAX_MASK 0x20
#define VDD2_ILMAX_SHIFT 5
#define VDD2_TSTEP_MASK 0x1C
#define VDD2_TSTEP_SHIFT 2
#define VDD2_ST_MASK 0x03
#define VDD2_ST_SHIFT 0
/*Register VDD2_OP (0x80) register.RegisterDescription */
#define VDD2_OP_CMD_MASK 0x80
#define VDD2_OP_CMD_SHIFT 7
#define VDD2_OP_SEL_MASK 0x7F
#define VDD2_OP_SEL_SHIFT 0
/*Register VDD2_SR (0x80) register.RegisterDescription */
#define VDD2_SR_SEL_MASK 0x7F
#define VDD2_SR_SEL_SHIFT 0
/*Registers VDD1, VDD2 voltage values definitions */
#define VDD1_2_NUM_VOLTS 73
#define VDD1_2_MIN_VOLT 6000
#define VDD1_2_OFFSET 125
/*Register VDD3 (0x80) register.RegisterDescription */
#define VDD3_CKINEN_MASK 0x04
#define VDD3_CKINEN_SHIFT 2
#define VDD3_ST_MASK 0x03
#define VDD3_ST_SHIFT 0
#define VDDCTRL_MIN_VOLT 6000
#define VDDCTRL_OFFSET 125
/*Registers VDIG (0x80) to VDAC register.RegisterDescription */
#define LDO_SEL_MASK 0x0C
#define LDO_SEL_SHIFT 2
#define LDO_ST_MASK 0x03
#define LDO_ST_SHIFT 0
#define LDO_ST_ON_BIT 0x01
#define LDO_ST_MODE_BIT 0x02
/* Registers LDO1 to LDO8 in tps65910 */
#define LDO1_SEL_MASK 0xFC
#define LDO3_SEL_MASK 0x7C
#define LDO_MIN_VOLT 1000
#define LDO_MAX_VOLT 3300;
/*Register VDIG1 (0x80) register.RegisterDescription */
#define VDIG1_SEL_MASK 0x0C
#define VDIG1_SEL_SHIFT 2
#define VDIG1_ST_MASK 0x03
#define VDIG1_ST_SHIFT 0
/*Register VDIG2 (0x80) register.RegisterDescription */
#define VDIG2_SEL_MASK 0x0C
#define VDIG2_SEL_SHIFT 2
#define VDIG2_ST_MASK 0x03
#define VDIG2_ST_SHIFT 0
/*Register VAUX1 (0x80) register.RegisterDescription */
#define VAUX1_SEL_MASK 0x0C
#define VAUX1_SEL_SHIFT 2
#define VAUX1_ST_MASK 0x03
#define VAUX1_ST_SHIFT 0
/*Register VAUX2 (0x80) register.RegisterDescription */
#define VAUX2_SEL_MASK 0x0C
#define VAUX2_SEL_SHIFT 2
#define VAUX2_ST_MASK 0x03
#define VAUX2_ST_SHIFT 0
/*Register VAUX33 (0x80) register.RegisterDescription */
#define VAUX33_SEL_MASK 0x0C
#define VAUX33_SEL_SHIFT 2
#define VAUX33_ST_MASK 0x03
#define VAUX33_ST_SHIFT 0
/*Register VMMC (0x80) register.RegisterDescription */
#define VMMC_SEL_MASK 0x0C
#define VMMC_SEL_SHIFT 2
#define VMMC_ST_MASK 0x03
#define VMMC_ST_SHIFT 0
/*Register VPLL (0x80) register.RegisterDescription */
#define VPLL_SEL_MASK 0x0C
#define VPLL_SEL_SHIFT 2
#define VPLL_ST_MASK 0x03
#define VPLL_ST_SHIFT 0
/*Register VDAC (0x80) register.RegisterDescription */
#define VDAC_SEL_MASK 0x0C
#define VDAC_SEL_SHIFT 2
#define VDAC_ST_MASK 0x03
#define VDAC_ST_SHIFT 0
/*Register THERM (0x80) register.RegisterDescription */
#define THERM_THERM_HD_MASK 0x20
#define THERM_THERM_HD_SHIFT 5
#define THERM_THERM_TS_MASK 0x10
#define THERM_THERM_TS_SHIFT 4
#define THERM_THERM_HDSEL_MASK 0x0C
#define THERM_THERM_HDSEL_SHIFT 2
#define THERM_RSVD1_MASK 0x02
#define THERM_RSVD1_SHIFT 1
#define THERM_THERM_STATE_MASK 0x01
#define THERM_THERM_STATE_SHIFT 0
/*Register BBCH (0x80) register.RegisterDescription */
#define BBCH_BBSEL_MASK 0x06
#define BBCH_BBSEL_SHIFT 1
#define BBCH_BBCHEN_MASK 0x01
#define BBCH_BBCHEN_SHIFT 0
/*Register DCDCCTRL (0x80) register.RegisterDescription */
#define DCDCCTRL_VDD2_PSKIP_MASK 0x20
#define DCDCCTRL_VDD2_PSKIP_SHIFT 5
#define DCDCCTRL_VDD1_PSKIP_MASK 0x10
#define DCDCCTRL_VDD1_PSKIP_SHIFT 4
#define DCDCCTRL_VIO_PSKIP_MASK 0x08
#define DCDCCTRL_VIO_PSKIP_SHIFT 3
#define DCDCCTRL_DCDCCKEXT_MASK 0x04
#define DCDCCTRL_DCDCCKEXT_SHIFT 2
#define DCDCCTRL_DCDCCKSYNC_MASK 0x03
#define DCDCCTRL_DCDCCKSYNC_SHIFT 0
/*Register DEVCTRL (0x80) register.RegisterDescription */
#define DEVCTRL_RTC_PWDN_MASK 0x40
#define DEVCTRL_RTC_PWDN_SHIFT 6
#define DEVCTRL_CK32K_CTRL_MASK 0x20
#define DEVCTRL_CK32K_CTRL_SHIFT 5
#define DEVCTRL_SR_CTL_I2C_SEL_MASK 0x10
#define DEVCTRL_SR_CTL_I2C_SEL_SHIFT 4
#define DEVCTRL_DEV_OFF_RST_MASK 0x08
#define DEVCTRL_DEV_OFF_RST_SHIFT 3
#define DEVCTRL_DEV_ON_MASK 0x04
#define DEVCTRL_DEV_ON_SHIFT 2
#define DEVCTRL_DEV_SLP_MASK 0x02
#define DEVCTRL_DEV_SLP_SHIFT 1
#define DEVCTRL_DEV_OFF_MASK 0x01
#define DEVCTRL_DEV_OFF_SHIFT 0
/*Register DEVCTRL2 (0x80) register.RegisterDescription */
#define DEVCTRL2_TSLOT_LENGTH_MASK 0x30
#define DEVCTRL2_TSLOT_LENGTH_SHIFT 4
#define DEVCTRL2_SLEEPSIG_POL_MASK 0x08
#define DEVCTRL2_SLEEPSIG_POL_SHIFT 3
#define DEVCTRL2_PWON_LP_OFF_MASK 0x04
#define DEVCTRL2_PWON_LP_OFF_SHIFT 2
#define DEVCTRL2_PWON_LP_RST_MASK 0x02
#define DEVCTRL2_PWON_LP_RST_SHIFT 1
#define DEVCTRL2_IT_POL_MASK 0x01
#define DEVCTRL2_IT_POL_SHIFT 0
/*Register SLEEP_KEEP_LDO_ON (0x80) register.RegisterDescription */
#define SLEEP_KEEP_LDO_ON_VDAC_KEEPON_MASK 0x80
#define SLEEP_KEEP_LDO_ON_VDAC_KEEPON_SHIFT 7
#define SLEEP_KEEP_LDO_ON_VPLL_KEEPON_MASK 0x40
#define SLEEP_KEEP_LDO_ON_VPLL_KEEPON_SHIFT 6
#define SLEEP_KEEP_LDO_ON_VAUX33_KEEPON_MASK 0x20
#define SLEEP_KEEP_LDO_ON_VAUX33_KEEPON_SHIFT 5
#define SLEEP_KEEP_LDO_ON_VAUX2_KEEPON_MASK 0x10
#define SLEEP_KEEP_LDO_ON_VAUX2_KEEPON_SHIFT 4
#define SLEEP_KEEP_LDO_ON_VAUX1_KEEPON_MASK 0x08
#define SLEEP_KEEP_LDO_ON_VAUX1_KEEPON_SHIFT 3
#define SLEEP_KEEP_LDO_ON_VDIG2_KEEPON_MASK 0x04
#define SLEEP_KEEP_LDO_ON_VDIG2_KEEPON_SHIFT 2
#define SLEEP_KEEP_LDO_ON_VDIG1_KEEPON_MASK 0x02
#define SLEEP_KEEP_LDO_ON_VDIG1_KEEPON_SHIFT 1
#define SLEEP_KEEP_LDO_ON_VMMC_KEEPON_MASK 0x01
#define SLEEP_KEEP_LDO_ON_VMMC_KEEPON_SHIFT 0
/*Register SLEEP_KEEP_RES_ON (0x80) register.RegisterDescription */
#define SLEEP_KEEP_RES_ON_THERM_KEEPON_MASK 0x80
#define SLEEP_KEEP_RES_ON_THERM_KEEPON_SHIFT 7
#define SLEEP_KEEP_RES_ON_CLKOUT32K_KEEPON_MASK 0x40
#define SLEEP_KEEP_RES_ON_CLKOUT32K_KEEPON_SHIFT 6
#define SLEEP_KEEP_RES_ON_VRTC_KEEPON_MASK 0x20
#define SLEEP_KEEP_RES_ON_VRTC_KEEPON_SHIFT 5
#define SLEEP_KEEP_RES_ON_I2CHS_KEEPON_MASK 0x10
#define SLEEP_KEEP_RES_ON_I2CHS_KEEPON_SHIFT 4
#define SLEEP_KEEP_RES_ON_VDD3_KEEPON_MASK 0x08
#define SLEEP_KEEP_RES_ON_VDD3_KEEPON_SHIFT 3
#define SLEEP_KEEP_RES_ON_VDD2_KEEPON_MASK 0x04
#define SLEEP_KEEP_RES_ON_VDD2_KEEPON_SHIFT 2
#define SLEEP_KEEP_RES_ON_VDD1_KEEPON_MASK 0x02
#define SLEEP_KEEP_RES_ON_VDD1_KEEPON_SHIFT 1
#define SLEEP_KEEP_RES_ON_VIO_KEEPON_MASK 0x01
#define SLEEP_KEEP_RES_ON_VIO_KEEPON_SHIFT 0
/*Register SLEEP_SET_LDO_OFF (0x80) register.RegisterDescription */
#define SLEEP_SET_LDO_OFF_VDAC_SETOFF_MASK 0x80
#define SLEEP_SET_LDO_OFF_VDAC_SETOFF_SHIFT 7
#define SLEEP_SET_LDO_OFF_VPLL_SETOFF_MASK 0x40
#define SLEEP_SET_LDO_OFF_VPLL_SETOFF_SHIFT 6
#define SLEEP_SET_LDO_OFF_VAUX33_SETOFF_MASK 0x20
#define SLEEP_SET_LDO_OFF_VAUX33_SETOFF_SHIFT 5
#define SLEEP_SET_LDO_OFF_VAUX2_SETOFF_MASK 0x10
#define SLEEP_SET_LDO_OFF_VAUX2_SETOFF_SHIFT 4
#define SLEEP_SET_LDO_OFF_VAUX1_SETOFF_MASK 0x08
#define SLEEP_SET_LDO_OFF_VAUX1_SETOFF_SHIFT 3
#define SLEEP_SET_LDO_OFF_VDIG2_SETOFF_MASK 0x04
#define SLEEP_SET_LDO_OFF_VDIG2_SETOFF_SHIFT 2
#define SLEEP_SET_LDO_OFF_VDIG1_SETOFF_MASK 0x02
#define SLEEP_SET_LDO_OFF_VDIG1_SETOFF_SHIFT 1
#define SLEEP_SET_LDO_OFF_VMMC_SETOFF_MASK 0x01
#define SLEEP_SET_LDO_OFF_VMMC_SETOFF_SHIFT 0
/*Register SLEEP_SET_RES_OFF (0x80) register.RegisterDescription */
#define SLEEP_SET_RES_OFF_DEFAULT_VOLT_MASK 0x80
#define SLEEP_SET_RES_OFF_DEFAULT_VOLT_SHIFT 7
#define SLEEP_SET_RES_OFF_RSVD_MASK 0x60
#define SLEEP_SET_RES_OFF_RSVD_SHIFT 5
#define SLEEP_SET_RES_OFF_SPARE_SETOFF_MASK 0x10
#define SLEEP_SET_RES_OFF_SPARE_SETOFF_SHIFT 4
#define SLEEP_SET_RES_OFF_VDD3_SETOFF_MASK 0x08
#define SLEEP_SET_RES_OFF_VDD3_SETOFF_SHIFT 3
#define SLEEP_SET_RES_OFF_VDD2_SETOFF_MASK 0x04
#define SLEEP_SET_RES_OFF_VDD2_SETOFF_SHIFT 2
#define SLEEP_SET_RES_OFF_VDD1_SETOFF_MASK 0x02
#define SLEEP_SET_RES_OFF_VDD1_SETOFF_SHIFT 1
#define SLEEP_SET_RES_OFF_VIO_SETOFF_MASK 0x01
#define SLEEP_SET_RES_OFF_VIO_SETOFF_SHIFT 0
/*Register EN1_LDO_ASS (0x80) register.RegisterDescription */
#define EN1_LDO_ASS_VDAC_EN1_MASK 0x80
#define EN1_LDO_ASS_VDAC_EN1_SHIFT 7
#define EN1_LDO_ASS_VPLL_EN1_MASK 0x40
#define EN1_LDO_ASS_VPLL_EN1_SHIFT 6
#define EN1_LDO_ASS_VAUX33_EN1_MASK 0x20
#define EN1_LDO_ASS_VAUX33_EN1_SHIFT 5
#define EN1_LDO_ASS_VAUX2_EN1_MASK 0x10
#define EN1_LDO_ASS_VAUX2_EN1_SHIFT 4
#define EN1_LDO_ASS_VAUX1_EN1_MASK 0x08
#define EN1_LDO_ASS_VAUX1_EN1_SHIFT 3
#define EN1_LDO_ASS_VDIG2_EN1_MASK 0x04
#define EN1_LDO_ASS_VDIG2_EN1_SHIFT 2
#define EN1_LDO_ASS_VDIG1_EN1_MASK 0x02
#define EN1_LDO_ASS_VDIG1_EN1_SHIFT 1
#define EN1_LDO_ASS_VMMC_EN1_MASK 0x01
#define EN1_LDO_ASS_VMMC_EN1_SHIFT 0
/*Register EN1_SMPS_ASS (0x80) register.RegisterDescription */
#define EN1_SMPS_ASS_RSVD_MASK 0xE0
#define EN1_SMPS_ASS_RSVD_SHIFT 5
#define EN1_SMPS_ASS_SPARE_EN1_MASK 0x10
#define EN1_SMPS_ASS_SPARE_EN1_SHIFT 4
#define EN1_SMPS_ASS_VDD3_EN1_MASK 0x08
#define EN1_SMPS_ASS_VDD3_EN1_SHIFT 3
#define EN1_SMPS_ASS_VDD2_EN1_MASK 0x04
#define EN1_SMPS_ASS_VDD2_EN1_SHIFT 2
#define EN1_SMPS_ASS_VDD1_EN1_MASK 0x02
#define EN1_SMPS_ASS_VDD1_EN1_SHIFT 1
#define EN1_SMPS_ASS_VIO_EN1_MASK 0x01
#define EN1_SMPS_ASS_VIO_EN1_SHIFT 0
/*Register EN2_LDO_ASS (0x80) register.RegisterDescription */
#define EN2_LDO_ASS_VDAC_EN2_MASK 0x80
#define EN2_LDO_ASS_VDAC_EN2_SHIFT 7
#define EN2_LDO_ASS_VPLL_EN2_MASK 0x40
#define EN2_LDO_ASS_VPLL_EN2_SHIFT 6
#define EN2_LDO_ASS_VAUX33_EN2_MASK 0x20
#define EN2_LDO_ASS_VAUX33_EN2_SHIFT 5
#define EN2_LDO_ASS_VAUX2_EN2_MASK 0x10
#define EN2_LDO_ASS_VAUX2_EN2_SHIFT 4
#define EN2_LDO_ASS_VAUX1_EN2_MASK 0x08
#define EN2_LDO_ASS_VAUX1_EN2_SHIFT 3
#define EN2_LDO_ASS_VDIG2_EN2_MASK 0x04
#define EN2_LDO_ASS_VDIG2_EN2_SHIFT 2
#define EN2_LDO_ASS_VDIG1_EN2_MASK 0x02
#define EN2_LDO_ASS_VDIG1_EN2_SHIFT 1
#define EN2_LDO_ASS_VMMC_EN2_MASK 0x01
#define EN2_LDO_ASS_VMMC_EN2_SHIFT 0
/*Register EN2_SMPS_ASS (0x80) register.RegisterDescription */
#define EN2_SMPS_ASS_RSVD_MASK 0xE0
#define EN2_SMPS_ASS_RSVD_SHIFT 5
#define EN2_SMPS_ASS_SPARE_EN2_MASK 0x10
#define EN2_SMPS_ASS_SPARE_EN2_SHIFT 4
#define EN2_SMPS_ASS_VDD3_EN2_MASK 0x08
#define EN2_SMPS_ASS_VDD3_EN2_SHIFT 3
#define EN2_SMPS_ASS_VDD2_EN2_MASK 0x04
#define EN2_SMPS_ASS_VDD2_EN2_SHIFT 2
#define EN2_SMPS_ASS_VDD1_EN2_MASK 0x02
#define EN2_SMPS_ASS_VDD1_EN2_SHIFT 1
#define EN2_SMPS_ASS_VIO_EN2_MASK 0x01
#define EN2_SMPS_ASS_VIO_EN2_SHIFT 0
/*Register EN3_LDO_ASS (0x80) register.RegisterDescription */
#define EN3_LDO_ASS_VDAC_EN3_MASK 0x80
#define EN3_LDO_ASS_VDAC_EN3_SHIFT 7
#define EN3_LDO_ASS_VPLL_EN3_MASK 0x40
#define EN3_LDO_ASS_VPLL_EN3_SHIFT 6
#define EN3_LDO_ASS_VAUX33_EN3_MASK 0x20
#define EN3_LDO_ASS_VAUX33_EN3_SHIFT 5
#define EN3_LDO_ASS_VAUX2_EN3_MASK 0x10
#define EN3_LDO_ASS_VAUX2_EN3_SHIFT 4
#define EN3_LDO_ASS_VAUX1_EN3_MASK 0x08
#define EN3_LDO_ASS_VAUX1_EN3_SHIFT 3
#define EN3_LDO_ASS_VDIG2_EN3_MASK 0x04
#define EN3_LDO_ASS_VDIG2_EN3_SHIFT 2
#define EN3_LDO_ASS_VDIG1_EN3_MASK 0x02
#define EN3_LDO_ASS_VDIG1_EN3_SHIFT 1
#define EN3_LDO_ASS_VMMC_EN3_MASK 0x01
#define EN3_LDO_ASS_VMMC_EN3_SHIFT 0
/*Register SPARE (0x80) register.RegisterDescription */
#define SPARE_SPARE_MASK 0xFF
#define SPARE_SPARE_SHIFT 0
/*Register INT_STS (0x80) register.RegisterDescription */
#define INT_STS_RTC_PERIOD_IT_MASK 0x80
#define INT_STS_RTC_PERIOD_IT_SHIFT 7
#define INT_STS_RTC_ALARM_IT_MASK 0x40
#define INT_STS_RTC_ALARM_IT_SHIFT 6
#define INT_STS_HOTDIE_IT_MASK 0x20
#define INT_STS_HOTDIE_IT_SHIFT 5
#define INT_STS_PWRHOLD_IT_MASK 0x10
#define INT_STS_PWRHOLD_IT_SHIFT 4
#define INT_STS_PWRON_LP_IT_MASK 0x08
#define INT_STS_PWRON_LP_IT_SHIFT 3
#define INT_STS_PWRON_IT_MASK 0x04
#define INT_STS_PWRON_IT_SHIFT 2
#define INT_STS_VMBHI_IT_MASK 0x02
#define INT_STS_VMBHI_IT_SHIFT 1
#define INT_STS_VMBDCH_IT_MASK 0x01
#define INT_STS_VMBDCH_IT_SHIFT 0
/*Register INT_MSK (0x80) register.RegisterDescription */
#define INT_MSK_RTC_PERIOD_IT_MSK_MASK 0x80
#define INT_MSK_RTC_PERIOD_IT_MSK_SHIFT 7
#define INT_MSK_RTC_ALARM_IT_MSK_MASK 0x40
#define INT_MSK_RTC_ALARM_IT_MSK_SHIFT 6
#define INT_MSK_HOTDIE_IT_MSK_MASK 0x20
#define INT_MSK_HOTDIE_IT_MSK_SHIFT 5
#define INT_MSK_PWRHOLD_IT_MSK_MASK 0x10
#define INT_MSK_PWRHOLD_IT_MSK_SHIFT 4
#define INT_MSK_PWRON_LP_IT_MSK_MASK 0x08
#define INT_MSK_PWRON_LP_IT_MSK_SHIFT 3
#define INT_MSK_PWRON_IT_MSK_MASK 0x04
#define INT_MSK_PWRON_IT_MSK_SHIFT 2
#define INT_MSK_VMBHI_IT_MSK_MASK 0x02
#define INT_MSK_VMBHI_IT_MSK_SHIFT 1
#define INT_MSK_VMBDCH_IT_MSK_MASK 0x01
#define INT_MSK_VMBDCH_IT_MSK_SHIFT 0
/*Register INT_STS2 (0x80) register.RegisterDescription */
#define INT_STS2_GPIO3_F_IT_MASK 0x80
#define INT_STS2_GPIO3_F_IT_SHIFT 7
#define INT_STS2_GPIO3_R_IT_MASK 0x40
#define INT_STS2_GPIO3_R_IT_SHIFT 6
#define INT_STS2_GPIO2_F_IT_MASK 0x20
#define INT_STS2_GPIO2_F_IT_SHIFT 5
#define INT_STS2_GPIO2_R_IT_MASK 0x10
#define INT_STS2_GPIO2_R_IT_SHIFT 4
#define INT_STS2_GPIO1_F_IT_MASK 0x08
#define INT_STS2_GPIO1_F_IT_SHIFT 3
#define INT_STS2_GPIO1_R_IT_MASK 0x04
#define INT_STS2_GPIO1_R_IT_SHIFT 2
#define INT_STS2_GPIO0_F_IT_MASK 0x02
#define INT_STS2_GPIO0_F_IT_SHIFT 1
#define INT_STS2_GPIO0_R_IT_MASK 0x01
#define INT_STS2_GPIO0_R_IT_SHIFT 0
/*Register INT_MSK2 (0x80) register.RegisterDescription */
#define INT_MSK2_GPIO3_F_IT_MSK_MASK 0x80
#define INT_MSK2_GPIO3_F_IT_MSK_SHIFT 7
#define INT_MSK2_GPIO3_R_IT_MSK_MASK 0x40
#define INT_MSK2_GPIO3_R_IT_MSK_SHIFT 6
#define INT_MSK2_GPIO2_F_IT_MSK_MASK 0x20
#define INT_MSK2_GPIO2_F_IT_MSK_SHIFT 5
#define INT_MSK2_GPIO2_R_IT_MSK_MASK 0x10
#define INT_MSK2_GPIO2_R_IT_MSK_SHIFT 4
#define INT_MSK2_GPIO1_F_IT_MSK_MASK 0x08
#define INT_MSK2_GPIO1_F_IT_MSK_SHIFT 3
#define INT_MSK2_GPIO1_R_IT_MSK_MASK 0x04
#define INT_MSK2_GPIO1_R_IT_MSK_SHIFT 2
#define INT_MSK2_GPIO0_F_IT_MSK_MASK 0x02
#define INT_MSK2_GPIO0_F_IT_MSK_SHIFT 1
#define INT_MSK2_GPIO0_R_IT_MSK_MASK 0x01
#define INT_MSK2_GPIO0_R_IT_MSK_SHIFT 0
/*Register INT_STS3 (0x80) register.RegisterDescription */
#define INT_STS3_GPIO5_F_IT_MASK 0x08
#define INT_STS3_GPIO5_F_IT_SHIFT 3
#define INT_STS3_GPIO5_R_IT_MASK 0x04
#define INT_STS3_GPIO5_R_IT_SHIFT 2
#define INT_STS3_GPIO4_F_IT_MASK 0x02
#define INT_STS3_GPIO4_F_IT_SHIFT 1
#define INT_STS3_GPIO4_R_IT_MASK 0x01
#define INT_STS3_GPIO4_R_IT_SHIFT 0
/*Register INT_MSK3 (0x80) register.RegisterDescription */
#define INT_MSK3_GPIO5_F_IT_MSK_MASK 0x08
#define INT_MSK3_GPIO5_F_IT_MSK_SHIFT 3
#define INT_MSK3_GPIO5_R_IT_MSK_MASK 0x04
#define INT_MSK3_GPIO5_R_IT_MSK_SHIFT 2
#define INT_MSK3_GPIO4_F_IT_MSK_MASK 0x02
#define INT_MSK3_GPIO4_F_IT_MSK_SHIFT 1
#define INT_MSK3_GPIO4_R_IT_MSK_MASK 0x01
#define INT_MSK3_GPIO4_R_IT_MSK_SHIFT 0
/*Register GPIO (0x80) register.RegisterDescription */
#define GPIO_DEB_MASK 0x10
#define GPIO_DEB_SHIFT 4
#define GPIO_PUEN_MASK 0x08
#define GPIO_PUEN_SHIFT 3
#define GPIO_CFG_MASK 0x04
#define GPIO_CFG_SHIFT 2
#define GPIO_STS_MASK 0x02
#define GPIO_STS_SHIFT 1
#define GPIO_SET_MASK 0x01
#define GPIO_SET_SHIFT 0
/*Register JTAGVERNUM (0x80) register.RegisterDescription */
#define JTAGVERNUM_VERNUM_MASK 0x0F
#define JTAGVERNUM_VERNUM_SHIFT 0
/* Register VDDCTRL (0x27) bit definitions */
#define VDDCTRL_ST_MASK 0x03
#define VDDCTRL_ST_SHIFT 0
/*Register VDDCTRL_OP (0x28) bit definitios */
#define VDDCTRL_OP_CMD_MASK 0x80
#define VDDCTRL_OP_CMD_SHIFT 7
#define VDDCTRL_OP_SEL_MASK 0x7F
#define VDDCTRL_OP_SEL_SHIFT 0
/*Register VDDCTRL_SR (0x29) bit definitions */
#define VDDCTRL_SR_SEL_MASK 0x7F
#define VDDCTRL_SR_SEL_SHIFT 0
/* IRQ Definitions */
#define TPS65910_IRQ_VBAT_VMBDCH 0
#define TPS65910_IRQ_VBAT_VMHI 1
#define TPS65910_IRQ_PWRON 2
#define TPS65910_IRQ_PWRON_LP 3
#define TPS65910_IRQ_PWRHOLD 4
#define TPS65910_IRQ_HOTDIE 5
#define TPS65910_IRQ_RTC_ALARM 6
#define TPS65910_IRQ_RTC_PERIOD 7
#define TPS65910_IRQ_GPIO_R 8
#define TPS65910_IRQ_GPIO_F 9
#define TPS65910_NUM_IRQ 10
#define TPS65911_IRQ_VBAT_VMBDCH 0
#define TPS65911_IRQ_VBAT_VMBDCH2L 1
#define TPS65911_IRQ_VBAT_VMBDCH2H 2
#define TPS65911_IRQ_VBAT_VMHI 3
#define TPS65911_IRQ_PWRON 4
#define TPS65911_IRQ_PWRON_LP 5
#define TPS65911_IRQ_PWRHOLD_F 6
#define TPS65911_IRQ_PWRHOLD_R 7
#define TPS65911_IRQ_HOTDIE 8
#define TPS65911_IRQ_RTC_ALARM 9
#define TPS65911_IRQ_RTC_PERIOD 10
#define TPS65911_IRQ_GPIO0_R 11
#define TPS65911_IRQ_GPIO0_F 12
#define TPS65911_IRQ_GPIO1_R 13
#define TPS65911_IRQ_GPIO1_F 14
#define TPS65911_IRQ_GPIO2_R 15
#define TPS65911_IRQ_GPIO2_F 16
#define TPS65911_IRQ_GPIO3_R 17
#define TPS65911_IRQ_GPIO3_F 18
#define TPS65911_IRQ_GPIO4_R 19
#define TPS65911_IRQ_GPIO4_F 20
#define TPS65911_IRQ_GPIO5_R 21
#define TPS65911_IRQ_GPIO5_F 22
#define TPS65911_IRQ_WTCHDG 23
#define TPS65911_IRQ_PWRDN 24
#define TPS65911_NUM_IRQ 25
/* GPIO Register Definitions */
#define TPS65910_GPIO_DEB BIT(2)
#define TPS65910_GPIO_PUEN BIT(3)
#define TPS65910_GPIO_CFG BIT(2)
#define TPS65910_GPIO_STS BIT(1)
#define TPS65910_GPIO_SET BIT(0)
/**
* struct tps65910_board
* Board platform data may be used to initialize regulators.
*/
struct tps65910_board {
int gpio_base;
int irq;
int irq_base;
int vmbch_threshold;
int vmbch2_threshold;
struct regulator_init_data *tps65910_pmic_init_data;
};
/**
* struct tps65910 - tps65910 sub-driver chip access routines
*/
struct tps65910 {
struct device *dev;
struct i2c_client *i2c_client;
struct mutex io_mutex;
unsigned int id;
int (*read)(struct tps65910 *tps65910, u8 reg, int size, void *dest);
int (*write)(struct tps65910 *tps65910, u8 reg, int size, void *src);
/* Client devices */
struct tps65910_pmic *pmic;
struct tps65910_rtc *rtc;
struct tps65910_power *power;
/* GPIO Handling */
struct gpio_chip gpio;
/* IRQ Handling */
struct mutex irq_lock;
int chip_irq;
int irq_base;
int irq_num;
u32 irq_mask;
};
struct tps65910_platform_data {
int irq;
int irq_base;
};
int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask);
int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask);
void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base);
int tps65910_irq_init(struct tps65910 *tps65910, int irq,
struct tps65910_platform_data *pdata);
static inline int tps65910_chip_id(struct tps65910 *tps65910)
{
return tps65910->id;
}
#endif /* __LINUX_MFD_TPS65910_H */

View File

@ -68,6 +68,8 @@ struct regulator_state {
*
* @min_uV: Smallest 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.
* @max_uA: Largest current consumers may set.
@ -99,6 +101,8 @@ struct regulation_constraints {
int min_uV;
int max_uV;
int uV_offset;
/* current output range (inclusive) - for current control */
int min_uA;
int max_uA;
@ -160,8 +164,6 @@ struct regulator_consumer_supply {
* @supply_regulator: Parent regulator. Specified using the regulator name
* as it appears in the name field in sysfs, which can
* 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
* be usable.
@ -173,7 +175,6 @@ struct regulator_consumer_supply {
*/
struct regulator_init_data {
const char *supply_regulator; /* or NULL for system supply */
struct device *supply_regulator_dev; /* or NULL for system supply */
struct regulation_constraints constraints;