提交 65b65559 编写于 作者: A Andrew F. Davis 提交者: Lee Jones

mfd: tps65912: Remove old driver in preparation for new driver

The old tps65912 driver is being replaced, delete old driver.
Signed-off-by: NAndrew F. Davis <afd@ti.com>
Acked-by: NMark Brown <broonie@kernel.org>
Acked-by: NLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: NLee Jones <lee.jones@linaro.org>
上级 c5cdf1d2
...@@ -858,12 +858,6 @@ config GPIO_TPS65910 ...@@ -858,12 +858,6 @@ config GPIO_TPS65910
Select this option to enable GPIO driver for the TPS65910 Select this option to enable GPIO driver for the TPS65910
chip family. chip family.
config GPIO_TPS65912
tristate "TI TPS65912 GPIO"
depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI)
help
This driver supports TPS65912 gpio chip
config GPIO_TWL4030 config GPIO_TWL4030
tristate "TWL4030, TWL5030, and TPS659x0 GPIOs" tristate "TWL4030, TWL5030, and TPS659x0 GPIOs"
depends on TWL4030_CORE depends on TWL4030_CORE
......
...@@ -97,7 +97,6 @@ obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o ...@@ -97,7 +97,6 @@ obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o
obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o
obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o
obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o
obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o
obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o
obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o
obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o
......
/*
* Copyright 2011 Texas Instruments Inc.
*
* Author: Margarita Olaya <magi@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.
*
* This driver is based on wm8350 implementation.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/mfd/core.h>
#include <linux/platform_device.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/mfd/tps65912.h>
struct tps65912_gpio_data {
struct tps65912 *tps65912;
struct gpio_chip gpio_chip;
};
static int tps65912_gpio_get(struct gpio_chip *gc, unsigned offset)
{
struct tps65912_gpio_data *tps65912_gpio = gpiochip_get_data(gc);
struct tps65912 *tps65912 = tps65912_gpio->tps65912;
int val;
val = tps65912_reg_read(tps65912, TPS65912_GPIO1 + offset);
if (val & GPIO_STS_MASK)
return 1;
return 0;
}
static void tps65912_gpio_set(struct gpio_chip *gc, unsigned offset,
int value)
{
struct tps65912_gpio_data *tps65912_gpio = gpiochip_get_data(gc);
struct tps65912 *tps65912 = tps65912_gpio->tps65912;
if (value)
tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset,
GPIO_SET_MASK);
else
tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset,
GPIO_SET_MASK);
}
static int tps65912_gpio_output(struct gpio_chip *gc, unsigned offset,
int value)
{
struct tps65912_gpio_data *tps65912_gpio = gpiochip_get_data(gc);
struct tps65912 *tps65912 = tps65912_gpio->tps65912;
/* Set the initial value */
tps65912_gpio_set(gc, offset, value);
return tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset,
GPIO_CFG_MASK);
}
static int tps65912_gpio_input(struct gpio_chip *gc, unsigned offset)
{
struct tps65912_gpio_data *tps65912_gpio = gpiochip_get_data(gc);
struct tps65912 *tps65912 = tps65912_gpio->tps65912;
return tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset,
GPIO_CFG_MASK);
}
static struct gpio_chip template_chip = {
.label = "tps65912",
.owner = THIS_MODULE,
.direction_input = tps65912_gpio_input,
.direction_output = tps65912_gpio_output,
.get = tps65912_gpio_get,
.set = tps65912_gpio_set,
.can_sleep = true,
.ngpio = 5,
.base = -1,
};
static int tps65912_gpio_probe(struct platform_device *pdev)
{
struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
struct tps65912_board *pdata = dev_get_platdata(tps65912->dev);
struct tps65912_gpio_data *tps65912_gpio;
int ret;
tps65912_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps65912_gpio),
GFP_KERNEL);
if (tps65912_gpio == NULL)
return -ENOMEM;
tps65912_gpio->tps65912 = tps65912;
tps65912_gpio->gpio_chip = template_chip;
tps65912_gpio->gpio_chip.parent = &pdev->dev;
if (pdata && pdata->gpio_base)
tps65912_gpio->gpio_chip.base = pdata->gpio_base;
ret = gpiochip_add_data(&tps65912_gpio->gpio_chip, tps65912_gpio);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register gpiochip, %d\n", ret);
return ret;
}
platform_set_drvdata(pdev, tps65912_gpio);
return ret;
}
static int tps65912_gpio_remove(struct platform_device *pdev)
{
struct tps65912_gpio_data *tps65912_gpio = platform_get_drvdata(pdev);
gpiochip_remove(&tps65912_gpio->gpio_chip);
return 0;
}
static struct platform_driver tps65912_gpio_driver = {
.driver = {
.name = "tps65912-gpio",
},
.probe = tps65912_gpio_probe,
.remove = tps65912_gpio_remove,
};
static int __init tps65912_gpio_init(void)
{
return platform_driver_register(&tps65912_gpio_driver);
}
subsys_initcall(tps65912_gpio_init);
static void __exit tps65912_gpio_exit(void)
{
platform_driver_unregister(&tps65912_gpio_driver);
}
module_exit(tps65912_gpio_exit);
MODULE_AUTHOR("Margarita Olaya Cabrera <magi@slimlogic.co.uk>");
MODULE_DESCRIPTION("GPIO interface for TPS65912 PMICs");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:tps65912-gpio");
...@@ -1180,32 +1180,6 @@ config MFD_TPS65910 ...@@ -1180,32 +1180,6 @@ config MFD_TPS65910
if you say yes here you get support for the TPS65910 series of if you say yes here you get support for the TPS65910 series of
Power Management chips. Power Management chips.
config MFD_TPS65912
bool "TI TPS65912 Power Management chip"
depends on GPIOLIB
select MFD_CORE
help
If you say yes here you get support for the TPS65912 series of
PM chips.
config MFD_TPS65912_I2C
bool "TI TPS65912 Power Management chip with I2C"
select MFD_CORE
select MFD_TPS65912
depends on I2C=y && GPIOLIB
help
If you say yes here you get support for the TPS65912 series of
PM chips with I2C interface.
config MFD_TPS65912_SPI
bool "TI TPS65912 Power Management chip with SPI"
select MFD_CORE
select MFD_TPS65912
depends on SPI_MASTER && GPIOLIB
help
If you say yes here you get support for the TPS65912 series of
PM chips with SPI interface.
config MFD_TPS80031 config MFD_TPS80031
bool "TI TPS80031/TPS80032 Power Management chips" bool "TI TPS80031/TPS80032 Power Management chips"
depends on I2C=y depends on I2C=y
......
...@@ -73,10 +73,6 @@ obj-$(CONFIG_TPS6507X) += tps6507x.o ...@@ -73,10 +73,6 @@ obj-$(CONFIG_TPS6507X) += tps6507x.o
obj-$(CONFIG_MFD_TPS65217) += tps65217.o obj-$(CONFIG_MFD_TPS65217) += tps65217.o
obj-$(CONFIG_MFD_TPS65218) += tps65218.o obj-$(CONFIG_MFD_TPS65218) += tps65218.o
obj-$(CONFIG_MFD_TPS65910) += tps65910.o obj-$(CONFIG_MFD_TPS65910) += tps65910.o
tps65912-objs := tps65912-core.o tps65912-irq.o
obj-$(CONFIG_MFD_TPS65912) += tps65912.o
obj-$(CONFIG_MFD_TPS65912_I2C) += tps65912-i2c.o
obj-$(CONFIG_MFD_TPS65912_SPI) += tps65912-spi.o
obj-$(CONFIG_MFD_TPS80031) += tps80031.o obj-$(CONFIG_MFD_TPS80031) += tps80031.o
obj-$(CONFIG_MENELAUS) += menelaus.o obj-$(CONFIG_MENELAUS) += menelaus.o
......
/*
* tps65912-core.c -- TI TPS65912x
*
* Copyright 2011 Texas Instruments Inc.
*
* Author: Margarita Olaya Cabrera <magi@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.
*
* This driver is based on wm8350 implementation.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps65912.h>
static const struct mfd_cell tps65912s[] = {
{
.name = "tps65912-pmic",
},
};
int tps65912_set_bits(struct tps65912 *tps65912, u8 reg, u8 mask)
{
u8 data;
int err;
mutex_lock(&tps65912->io_mutex);
err = tps65912->read(tps65912, reg, 1, &data);
if (err) {
dev_err(tps65912->dev, "Read from reg 0x%x failed\n", reg);
goto out;
}
data |= mask;
err = tps65912->write(tps65912, reg, 1, &data);
if (err)
dev_err(tps65912->dev, "Write to reg 0x%x failed\n", reg);
out:
mutex_unlock(&tps65912->io_mutex);
return err;
}
EXPORT_SYMBOL_GPL(tps65912_set_bits);
int tps65912_clear_bits(struct tps65912 *tps65912, u8 reg, u8 mask)
{
u8 data;
int err;
mutex_lock(&tps65912->io_mutex);
err = tps65912->read(tps65912, reg, 1, &data);
if (err) {
dev_err(tps65912->dev, "Read from reg 0x%x failed\n", reg);
goto out;
}
data &= ~mask;
err = tps65912->write(tps65912, reg, 1, &data);
if (err)
dev_err(tps65912->dev, "Write to reg 0x%x failed\n", reg);
out:
mutex_unlock(&tps65912->io_mutex);
return err;
}
EXPORT_SYMBOL_GPL(tps65912_clear_bits);
static inline int tps65912_read(struct tps65912 *tps65912, u8 reg)
{
u8 val;
int err;
err = tps65912->read(tps65912, reg, 1, &val);
if (err < 0)
return err;
return val;
}
static inline int tps65912_write(struct tps65912 *tps65912, u8 reg, u8 val)
{
return tps65912->write(tps65912, reg, 1, &val);
}
int tps65912_reg_read(struct tps65912 *tps65912, u8 reg)
{
int data;
mutex_lock(&tps65912->io_mutex);
data = tps65912_read(tps65912, reg);
if (data < 0)
dev_err(tps65912->dev, "Read from reg 0x%x failed\n", reg);
mutex_unlock(&tps65912->io_mutex);
return data;
}
EXPORT_SYMBOL_GPL(tps65912_reg_read);
int tps65912_reg_write(struct tps65912 *tps65912, u8 reg, u8 val)
{
int err;
mutex_lock(&tps65912->io_mutex);
err = tps65912_write(tps65912, reg, val);
if (err < 0)
dev_err(tps65912->dev, "Write for reg 0x%x failed\n", reg);
mutex_unlock(&tps65912->io_mutex);
return err;
}
EXPORT_SYMBOL_GPL(tps65912_reg_write);
int tps65912_device_init(struct tps65912 *tps65912)
{
struct tps65912_board *pmic_plat_data = dev_get_platdata(tps65912->dev);
struct tps65912_platform_data *init_data;
int ret, dcdc_avs, value;
init_data = kzalloc(sizeof(struct tps65912_platform_data), GFP_KERNEL);
if (init_data == NULL)
return -ENOMEM;
mutex_init(&tps65912->io_mutex);
dev_set_drvdata(tps65912->dev, tps65912);
dcdc_avs = (pmic_plat_data->is_dcdc1_avs << 0 |
pmic_plat_data->is_dcdc2_avs << 1 |
pmic_plat_data->is_dcdc3_avs << 2 |
pmic_plat_data->is_dcdc4_avs << 3);
if (dcdc_avs) {
tps65912->read(tps65912, TPS65912_I2C_SPI_CFG, 1, &value);
dcdc_avs |= value;
tps65912->write(tps65912, TPS65912_I2C_SPI_CFG, 1, &dcdc_avs);
}
ret = mfd_add_devices(tps65912->dev, -1,
tps65912s, ARRAY_SIZE(tps65912s),
NULL, 0, NULL);
if (ret < 0)
goto err;
init_data->irq = pmic_plat_data->irq;
init_data->irq_base = pmic_plat_data->irq_base;
ret = tps65912_irq_init(tps65912, init_data->irq, init_data);
if (ret < 0)
goto err;
kfree(init_data);
return ret;
err:
kfree(init_data);
mfd_remove_devices(tps65912->dev);
return ret;
}
void tps65912_device_exit(struct tps65912 *tps65912)
{
mfd_remove_devices(tps65912->dev);
tps65912_irq_exit(tps65912);
}
MODULE_AUTHOR("Margarita Olaya <magi@slimlogic.co.uk>");
MODULE_DESCRIPTION("TPS65912x chip family multi-function driver");
MODULE_LICENSE("GPL");
/*
* tps65912-i2c.c -- I2C access for TI TPS65912x PMIC
*
* Copyright 2011 Texas Instruments Inc.
*
* Author: Margarita Olaya Cabrera <magi@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.
*
* This driver is based on wm8350 implementation.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps65912.h>
static int tps65912_i2c_read(struct tps65912 *tps65912, u8 reg,
int bytes, void *dest)
{
struct i2c_client *i2c = tps65912->control_data;
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 tps65912_i2c_write(struct tps65912 *tps65912, u8 reg,
int bytes, void *src)
{
struct i2c_client *i2c = tps65912->control_data;
/* we add 1 byte for device register */
u8 msg[TPS6591X_MAX_REGISTER + 1];
int ret;
if (bytes > TPS6591X_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;
}
static int tps65912_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct tps65912 *tps65912;
tps65912 = devm_kzalloc(&i2c->dev,
sizeof(struct tps65912), GFP_KERNEL);
if (tps65912 == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, tps65912);
tps65912->dev = &i2c->dev;
tps65912->control_data = i2c;
tps65912->read = tps65912_i2c_read;
tps65912->write = tps65912_i2c_write;
return tps65912_device_init(tps65912);
}
static int tps65912_i2c_remove(struct i2c_client *i2c)
{
struct tps65912 *tps65912 = i2c_get_clientdata(i2c);
tps65912_device_exit(tps65912);
return 0;
}
static const struct i2c_device_id tps65912_i2c_id[] = {
{"tps65912", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tps65912_i2c_id);
static struct i2c_driver tps65912_i2c_driver = {
.driver = {
.name = "tps65912",
},
.probe = tps65912_i2c_probe,
.remove = tps65912_i2c_remove,
.id_table = tps65912_i2c_id,
};
static int __init tps65912_i2c_init(void)
{
int ret;
ret = i2c_add_driver(&tps65912_i2c_driver);
if (ret != 0)
pr_err("Failed to register TPS65912 I2C driver: %d\n", ret);
return ret;
}
/* init early so consumer devices can complete system boot */
subsys_initcall(tps65912_i2c_init);
static void __exit tps65912_i2c_exit(void)
{
i2c_del_driver(&tps65912_i2c_driver);
}
module_exit(tps65912_i2c_exit);
MODULE_AUTHOR("Margarita Olaya <magi@slimlogic.co.uk>");
MODULE_DESCRIPTION("TPS6591x chip family multi-function driver");
MODULE_LICENSE("GPL");
/*
* tps65912-irq.c -- TI TPS6591x
*
* Copyright 2011 Texas Instruments Inc.
*
* Author: Margarita Olaya <magi@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.
*
* This driver is based on wm8350 implementation.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/bug.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/mfd/tps65912.h>
static inline int irq_to_tps65912_irq(struct tps65912 *tps65912,
int irq)
{
return irq - tps65912->irq_base;
}
/*
* This is a threaded IRQ handler so can access I2C/SPI. Since the
* IRQ handler explicitly clears the IRQ it handles 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 tps65912_irq(int irq, void *irq_data)
{
struct tps65912 *tps65912 = irq_data;
u32 irq_sts;
u32 irq_mask;
u8 reg;
int i;
tps65912->read(tps65912, TPS65912_INT_STS, 1, &reg);
irq_sts = reg;
tps65912->read(tps65912, TPS65912_INT_STS2, 1, &reg);
irq_sts |= reg << 8;
tps65912->read(tps65912, TPS65912_INT_STS3, 1, &reg);
irq_sts |= reg << 16;
tps65912->read(tps65912, TPS65912_INT_STS4, 1, &reg);
irq_sts |= reg << 24;
tps65912->read(tps65912, TPS65912_INT_MSK, 1, &reg);
irq_mask = reg;
tps65912->read(tps65912, TPS65912_INT_MSK2, 1, &reg);
irq_mask |= reg << 8;
tps65912->read(tps65912, TPS65912_INT_MSK3, 1, &reg);
irq_mask |= reg << 16;
tps65912->read(tps65912, TPS65912_INT_MSK4, 1, &reg);
irq_mask |= reg << 24;
irq_sts &= ~irq_mask;
if (!irq_sts)
return IRQ_NONE;
for (i = 0; i < tps65912->irq_num; i++) {
if (!(irq_sts & (1 << i)))
continue;
handle_nested_irq(tps65912->irq_base + i);
}
/* Write the STS register back to clear IRQs we handled */
reg = irq_sts & 0xFF;
irq_sts >>= 8;
if (reg)
tps65912->write(tps65912, TPS65912_INT_STS, 1, &reg);
reg = irq_sts & 0xFF;
irq_sts >>= 8;
if (reg)
tps65912->write(tps65912, TPS65912_INT_STS2, 1, &reg);
reg = irq_sts & 0xFF;
irq_sts >>= 8;
if (reg)
tps65912->write(tps65912, TPS65912_INT_STS3, 1, &reg);
reg = irq_sts & 0xFF;
if (reg)
tps65912->write(tps65912, TPS65912_INT_STS4, 1, &reg);
return IRQ_HANDLED;
}
static void tps65912_irq_lock(struct irq_data *data)
{
struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data);
mutex_lock(&tps65912->irq_lock);
}
static void tps65912_irq_sync_unlock(struct irq_data *data)
{
struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data);
u32 reg_mask;
u8 reg;
tps65912->read(tps65912, TPS65912_INT_MSK, 1, &reg);
reg_mask = reg;
tps65912->read(tps65912, TPS65912_INT_MSK2, 1, &reg);
reg_mask |= reg << 8;
tps65912->read(tps65912, TPS65912_INT_MSK3, 1, &reg);
reg_mask |= reg << 16;
tps65912->read(tps65912, TPS65912_INT_MSK4, 1, &reg);
reg_mask |= reg << 24;
if (tps65912->irq_mask != reg_mask) {
reg = tps65912->irq_mask & 0xFF;
tps65912->write(tps65912, TPS65912_INT_MSK, 1, &reg);
reg = tps65912->irq_mask >> 8 & 0xFF;
tps65912->write(tps65912, TPS65912_INT_MSK2, 1, &reg);
reg = tps65912->irq_mask >> 16 & 0xFF;
tps65912->write(tps65912, TPS65912_INT_MSK3, 1, &reg);
reg = tps65912->irq_mask >> 24 & 0xFF;
tps65912->write(tps65912, TPS65912_INT_MSK4, 1, &reg);
}
mutex_unlock(&tps65912->irq_lock);
}
static void tps65912_irq_enable(struct irq_data *data)
{
struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data);
tps65912->irq_mask &= ~(1 << irq_to_tps65912_irq(tps65912, data->irq));
}
static void tps65912_irq_disable(struct irq_data *data)
{
struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data);
tps65912->irq_mask |= (1 << irq_to_tps65912_irq(tps65912, data->irq));
}
static struct irq_chip tps65912_irq_chip = {
.name = "tps65912",
.irq_bus_lock = tps65912_irq_lock,
.irq_bus_sync_unlock = tps65912_irq_sync_unlock,
.irq_disable = tps65912_irq_disable,
.irq_enable = tps65912_irq_enable,
};
int tps65912_irq_init(struct tps65912 *tps65912, int irq,
struct tps65912_platform_data *pdata)
{
int ret, cur_irq;
int flags = IRQF_ONESHOT;
u8 reg;
if (!irq) {
dev_warn(tps65912->dev, "No interrupt support, no core IRQ\n");
return 0;
}
if (!pdata || !pdata->irq_base) {
dev_warn(tps65912->dev, "No interrupt support, no IRQ base\n");
return 0;
}
/* Clear unattended interrupts */
tps65912->read(tps65912, TPS65912_INT_STS, 1, &reg);
tps65912->write(tps65912, TPS65912_INT_STS, 1, &reg);
tps65912->read(tps65912, TPS65912_INT_STS2, 1, &reg);
tps65912->write(tps65912, TPS65912_INT_STS2, 1, &reg);
tps65912->read(tps65912, TPS65912_INT_STS3, 1, &reg);
tps65912->write(tps65912, TPS65912_INT_STS3, 1, &reg);
tps65912->read(tps65912, TPS65912_INT_STS4, 1, &reg);
tps65912->write(tps65912, TPS65912_INT_STS4, 1, &reg);
/* Mask top level interrupts */
tps65912->irq_mask = 0xFFFFFFFF;
mutex_init(&tps65912->irq_lock);
tps65912->chip_irq = irq;
tps65912->irq_base = pdata->irq_base;
tps65912->irq_num = TPS65912_NUM_IRQ;
/* Register with genirq */
for (cur_irq = tps65912->irq_base;
cur_irq < tps65912->irq_num + tps65912->irq_base;
cur_irq++) {
irq_set_chip_data(cur_irq, tps65912);
irq_set_chip_and_handler(cur_irq, &tps65912_irq_chip,
handle_edge_irq);
irq_set_nested_thread(cur_irq, 1);
irq_clear_status_flags(cur_irq, IRQ_NOREQUEST | IRQ_NOPROBE);
}
ret = request_threaded_irq(irq, NULL, tps65912_irq, flags,
"tps65912", tps65912);
irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
if (ret != 0)
dev_err(tps65912->dev, "Failed to request IRQ: %d\n", ret);
return ret;
}
int tps65912_irq_exit(struct tps65912 *tps65912)
{
free_irq(tps65912->chip_irq, tps65912);
return 0;
}
/*
* tps65912-spi.c -- SPI access for TI TPS65912x PMIC
*
* Copyright 2011 Texas Instruments Inc.
*
* Author: Margarita Olaya Cabrera <magi@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.
*
* This driver is based on wm8350 implementation.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps65912.h>
static int tps65912_spi_write(struct tps65912 *tps65912, u8 addr,
int bytes, void *src)
{
struct spi_device *spi = tps65912->control_data;
u8 *data = (u8 *) src;
int ret;
/* bit 23 is the read/write bit */
unsigned long spi_data = 1 << 23 | addr << 15 | *data;
struct spi_transfer xfer;
struct spi_message msg;
u32 tx_buf;
tx_buf = spi_data;
xfer.tx_buf = &tx_buf;
xfer.rx_buf = NULL;
xfer.len = sizeof(unsigned long);
xfer.bits_per_word = 24;
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(spi, &msg);
return ret;
}
static int tps65912_spi_read(struct tps65912 *tps65912, u8 addr,
int bytes, void *dest)
{
struct spi_device *spi = tps65912->control_data;
/* bit 23 is the read/write bit */
unsigned long spi_data = 0 << 23 | addr << 15;
struct spi_transfer xfer;
struct spi_message msg;
int ret;
u8 *data = (u8 *) dest;
u32 tx_buf, rx_buf;
tx_buf = spi_data;
rx_buf = 0;
xfer.tx_buf = &tx_buf;
xfer.rx_buf = &rx_buf;
xfer.len = sizeof(unsigned long);
xfer.bits_per_word = 24;
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
if (spi == NULL)
return 0;
ret = spi_sync(spi, &msg);
if (ret == 0)
*data = (u8) (rx_buf & 0xFF);
return ret;
}
static int tps65912_spi_probe(struct spi_device *spi)
{
struct tps65912 *tps65912;
tps65912 = devm_kzalloc(&spi->dev,
sizeof(struct tps65912), GFP_KERNEL);
if (tps65912 == NULL)
return -ENOMEM;
tps65912->dev = &spi->dev;
tps65912->control_data = spi;
tps65912->read = tps65912_spi_read;
tps65912->write = tps65912_spi_write;
spi_set_drvdata(spi, tps65912);
return tps65912_device_init(tps65912);
}
static int tps65912_spi_remove(struct spi_device *spi)
{
struct tps65912 *tps65912 = spi_get_drvdata(spi);
tps65912_device_exit(tps65912);
return 0;
}
static struct spi_driver tps65912_spi_driver = {
.driver = {
.name = "tps65912",
},
.probe = tps65912_spi_probe,
.remove = tps65912_spi_remove,
};
static int __init tps65912_spi_init(void)
{
int ret;
ret = spi_register_driver(&tps65912_spi_driver);
if (ret != 0)
pr_err("Failed to register TPS65912 SPI driver: %d\n", ret);
return 0;
}
/* init early so consumer devices can complete system boot */
subsys_initcall(tps65912_spi_init);
static void __exit tps65912_spi_exit(void)
{
spi_unregister_driver(&tps65912_spi_driver);
}
module_exit(tps65912_spi_exit);
MODULE_AUTHOR("Margarita Olaya <magi@slimlogic.co.uk>");
MODULE_DESCRIPTION("SPI support for TPS65912 chip family mfd");
MODULE_LICENSE("GPL");
...@@ -760,12 +760,6 @@ config REGULATOR_TPS65910 ...@@ -760,12 +760,6 @@ config REGULATOR_TPS65910
help help
This driver supports TPS65910/TPS65911 voltage regulator chips. This driver supports TPS65910/TPS65911 voltage regulator chips.
config REGULATOR_TPS65912
tristate "TI TPS65912 Power regulator"
depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI)
help
This driver supports TPS65912 voltage regulator chip.
config REGULATOR_TPS80031 config REGULATOR_TPS80031
tristate "TI TPS80031/TPS80032 power regualtor driver" tristate "TI TPS80031/TPS80032 power regualtor driver"
depends on MFD_TPS80031 depends on MFD_TPS80031
......
...@@ -95,7 +95,6 @@ obj-$(CONFIG_REGULATOR_TPS65218) += tps65218-regulator.o ...@@ -95,7 +95,6 @@ obj-$(CONFIG_REGULATOR_TPS65218) += tps65218-regulator.o
obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o
obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o
......
/*
* tps65912.c -- TI tps65912
*
* Copyright 2011 Texas Instruments Inc.
*
* Author: Margarita Olaya Cabrera <magi@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.
*
* This driver is based on wm8350 implementation.
*/
#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/slab.h>
#include <linux/gpio.h>
#include <linux/mfd/tps65912.h>
/* DCDC's */
#define TPS65912_REG_DCDC1 0
#define TPS65912_REG_DCDC2 1
#define TPS65912_REG_DCDC3 2
#define TPS65912_REG_DCDC4 3
/* LDOs */
#define TPS65912_REG_LDO1 4
#define TPS65912_REG_LDO2 5
#define TPS65912_REG_LDO3 6
#define TPS65912_REG_LDO4 7
#define TPS65912_REG_LDO5 8
#define TPS65912_REG_LDO6 9
#define TPS65912_REG_LDO7 10
#define TPS65912_REG_LDO8 11
#define TPS65912_REG_LDO9 12
#define TPS65912_REG_LDO10 13
/* Number of step-down converters available */
#define TPS65912_NUM_DCDC 4
/* Number of LDO voltage regulators available */
#define TPS65912_NUM_LDO 10
/* Number of total regulators available */
#define TPS65912_NUM_REGULATOR (TPS65912_NUM_DCDC + TPS65912_NUM_LDO)
#define TPS65912_REG_ENABLED 0x80
#define OP_SELREG_MASK 0x40
#define OP_SELREG_SHIFT 6
struct tps_info {
const char *name;
};
static struct tps_info tps65912_regs[] = {
{
.name = "DCDC1",
},
{
.name = "DCDC2",
},
{
.name = "DCDC3",
},
{
.name = "DCDC4",
},
{
.name = "LDO1",
},
{
.name = "LDO2",
},
{
.name = "LDO3",
},
{
.name = "LDO4",
},
{
.name = "LDO5",
},
{
.name = "LDO6",
},
{
.name = "LDO7",
},
{
.name = "LDO8",
},
{
.name = "LDO9",
},
{
.name = "LDO10",
},
};
struct tps65912_reg {
struct regulator_desc desc[TPS65912_NUM_REGULATOR];
struct tps65912 *mfd;
struct regulator_dev *rdev[TPS65912_NUM_REGULATOR];
struct tps_info *info[TPS65912_NUM_REGULATOR];
/* for read/write access */
struct mutex io_lock;
int mode;
int (*get_ctrl_reg)(int);
int dcdc_range[TPS65912_NUM_DCDC];
int pwm_mode_reg;
int eco_reg;
};
static const struct regulator_linear_range tps65912_ldo_ranges[] = {
REGULATOR_LINEAR_RANGE(800000, 0, 32, 25000),
REGULATOR_LINEAR_RANGE(1650000, 33, 60, 50000),
REGULATOR_LINEAR_RANGE(3100000, 61, 63, 100000),
};
static int tps65912_get_range(struct tps65912_reg *pmic, int id)
{
struct tps65912 *mfd = pmic->mfd;
int range;
switch (id) {
case TPS65912_REG_DCDC1:
range = tps65912_reg_read(mfd, TPS65912_DCDC1_LIMIT);
break;
case TPS65912_REG_DCDC2:
range = tps65912_reg_read(mfd, TPS65912_DCDC2_LIMIT);
break;
case TPS65912_REG_DCDC3:
range = tps65912_reg_read(mfd, TPS65912_DCDC3_LIMIT);
break;
case TPS65912_REG_DCDC4:
range = tps65912_reg_read(mfd, TPS65912_DCDC4_LIMIT);
break;
default:
return 0;
}
if (range >= 0)
range = (range & DCDC_LIMIT_RANGE_MASK)
>> DCDC_LIMIT_RANGE_SHIFT;
pmic->dcdc_range[id] = range;
return range;
}
static unsigned long tps65912_vsel_to_uv_range0(u8 vsel)
{
unsigned long uv;
uv = ((vsel * 12500) + 500000);
return uv;
}
static unsigned long tps65912_vsel_to_uv_range1(u8 vsel)
{
unsigned long uv;
uv = ((vsel * 12500) + 700000);
return uv;
}
static unsigned long tps65912_vsel_to_uv_range2(u8 vsel)
{
unsigned long uv;
uv = ((vsel * 25000) + 500000);
return uv;
}
static unsigned long tps65912_vsel_to_uv_range3(u8 vsel)
{
unsigned long uv;
if (vsel == 0x3f)
uv = 3800000;
else
uv = ((vsel * 50000) + 500000);
return uv;
}
static int tps65912_get_ctrl_register(int id)
{
if (id >= TPS65912_REG_DCDC1 && id <= TPS65912_REG_LDO4)
return id * 3 + TPS65912_DCDC1_AVS;
else if (id >= TPS65912_REG_LDO5 && id <= TPS65912_REG_LDO10)
return id - TPS65912_REG_LDO5 + TPS65912_LDO5;
else
return -EINVAL;
}
static int tps65912_get_sel_register(struct tps65912_reg *pmic, int id)
{
struct tps65912 *mfd = pmic->mfd;
int opvsel;
u8 reg = 0;
if (id >= TPS65912_REG_DCDC1 && id <= TPS65912_REG_LDO4) {
opvsel = tps65912_reg_read(mfd, id * 3 + TPS65912_DCDC1_OP);
if (opvsel & OP_SELREG_MASK)
reg = id * 3 + TPS65912_DCDC1_AVS;
else
reg = id * 3 + TPS65912_DCDC1_OP;
} else if (id >= TPS65912_REG_LDO5 && id <= TPS65912_REG_LDO10) {
reg = id - TPS65912_REG_LDO5 + TPS65912_LDO5;
} else {
return -EINVAL;
}
return reg;
}
static int tps65912_get_mode_regiters(struct tps65912_reg *pmic, int id)
{
switch (id) {
case TPS65912_REG_DCDC1:
pmic->pwm_mode_reg = TPS65912_DCDC1_CTRL;
pmic->eco_reg = TPS65912_DCDC1_AVS;
break;
case TPS65912_REG_DCDC2:
pmic->pwm_mode_reg = TPS65912_DCDC2_CTRL;
pmic->eco_reg = TPS65912_DCDC2_AVS;
break;
case TPS65912_REG_DCDC3:
pmic->pwm_mode_reg = TPS65912_DCDC3_CTRL;
pmic->eco_reg = TPS65912_DCDC3_AVS;
break;
case TPS65912_REG_DCDC4:
pmic->pwm_mode_reg = TPS65912_DCDC4_CTRL;
pmic->eco_reg = TPS65912_DCDC4_AVS;
break;
default:
return -EINVAL;
}
return 0;
}
static int tps65912_reg_is_enabled(struct regulator_dev *dev)
{
struct tps65912_reg *pmic = rdev_get_drvdata(dev);
struct tps65912 *mfd = pmic->mfd;
int reg, value, id = rdev_get_id(dev);
if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_LDO10)
return -EINVAL;
reg = pmic->get_ctrl_reg(id);
if (reg < 0)
return reg;
value = tps65912_reg_read(mfd, reg);
if (value < 0)
return value;
return value & TPS65912_REG_ENABLED;
}
static int tps65912_reg_enable(struct regulator_dev *dev)
{
struct tps65912_reg *pmic = rdev_get_drvdata(dev);
struct tps65912 *mfd = pmic->mfd;
int id = rdev_get_id(dev);
int reg;
if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_LDO10)
return -EINVAL;
reg = pmic->get_ctrl_reg(id);
if (reg < 0)
return reg;
return tps65912_set_bits(mfd, reg, TPS65912_REG_ENABLED);
}
static int tps65912_reg_disable(struct regulator_dev *dev)
{
struct tps65912_reg *pmic = rdev_get_drvdata(dev);
struct tps65912 *mfd = pmic->mfd;
int id = rdev_get_id(dev), reg;
reg = pmic->get_ctrl_reg(id);
if (reg < 0)
return reg;
return tps65912_clear_bits(mfd, reg, TPS65912_REG_ENABLED);
}
static int tps65912_set_mode(struct regulator_dev *dev, unsigned int mode)
{
struct tps65912_reg *pmic = rdev_get_drvdata(dev);
struct tps65912 *mfd = pmic->mfd;
int pwm_mode, eco, id = rdev_get_id(dev);
tps65912_get_mode_regiters(pmic, id);
pwm_mode = tps65912_reg_read(mfd, pmic->pwm_mode_reg);
eco = tps65912_reg_read(mfd, pmic->eco_reg);
pwm_mode &= DCDCCTRL_DCDC_MODE_MASK;
eco &= DCDC_AVS_ECO_MASK;
switch (mode) {
case REGULATOR_MODE_FAST:
/* Verify if mode alredy set */
if (pwm_mode && !eco)
break;
tps65912_set_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK);
tps65912_clear_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK);
break;
case REGULATOR_MODE_NORMAL:
case REGULATOR_MODE_IDLE:
if (!pwm_mode && !eco)
break;
tps65912_clear_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK);
tps65912_clear_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK);
break;
case REGULATOR_MODE_STANDBY:
if (!pwm_mode && eco)
break;
tps65912_clear_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK);
tps65912_set_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK);
break;
default:
return -EINVAL;
}
return 0;
}
static unsigned int tps65912_get_mode(struct regulator_dev *dev)
{
struct tps65912_reg *pmic = rdev_get_drvdata(dev);
struct tps65912 *mfd = pmic->mfd;
int pwm_mode, eco, mode = 0, id = rdev_get_id(dev);
tps65912_get_mode_regiters(pmic, id);
pwm_mode = tps65912_reg_read(mfd, pmic->pwm_mode_reg);
eco = tps65912_reg_read(mfd, pmic->eco_reg);
pwm_mode &= DCDCCTRL_DCDC_MODE_MASK;
eco &= DCDC_AVS_ECO_MASK;
if (pwm_mode && !eco)
mode = REGULATOR_MODE_FAST;
else if (!pwm_mode && !eco)
mode = REGULATOR_MODE_NORMAL;
else if (!pwm_mode && eco)
mode = REGULATOR_MODE_STANDBY;
return mode;
}
static int tps65912_list_voltage(struct regulator_dev *dev, unsigned selector)
{
struct tps65912_reg *pmic = rdev_get_drvdata(dev);
int range, voltage = 0, id = rdev_get_id(dev);
if (id > TPS65912_REG_DCDC4)
return -EINVAL;
range = pmic->dcdc_range[id];
switch (range) {
case 0:
/* 0.5 - 1.2875V in 12.5mV steps */
voltage = tps65912_vsel_to_uv_range0(selector);
break;
case 1:
/* 0.7 - 1.4875V in 12.5mV steps */
voltage = tps65912_vsel_to_uv_range1(selector);
break;
case 2:
/* 0.5 - 2.075V in 25mV steps */
voltage = tps65912_vsel_to_uv_range2(selector);
break;
case 3:
/* 0.5 - 3.8V in 50mV steps */
voltage = tps65912_vsel_to_uv_range3(selector);
break;
}
return voltage;
}
static int tps65912_get_voltage_sel(struct regulator_dev *dev)
{
struct tps65912_reg *pmic = rdev_get_drvdata(dev);
struct tps65912 *mfd = pmic->mfd;
int id = rdev_get_id(dev);
int reg, vsel;
reg = tps65912_get_sel_register(pmic, id);
if (reg < 0)
return reg;
vsel = tps65912_reg_read(mfd, reg);
vsel &= 0x3F;
return vsel;
}
static int tps65912_set_voltage_sel(struct regulator_dev *dev,
unsigned selector)
{
struct tps65912_reg *pmic = rdev_get_drvdata(dev);
struct tps65912 *mfd = pmic->mfd;
int id = rdev_get_id(dev);
int value;
u8 reg;
reg = tps65912_get_sel_register(pmic, id);
value = tps65912_reg_read(mfd, reg);
value &= 0xC0;
return tps65912_reg_write(mfd, reg, selector | value);
}
/* Operations permitted on DCDCx */
static struct regulator_ops tps65912_ops_dcdc = {
.is_enabled = tps65912_reg_is_enabled,
.enable = tps65912_reg_enable,
.disable = tps65912_reg_disable,
.set_mode = tps65912_set_mode,
.get_mode = tps65912_get_mode,
.get_voltage_sel = tps65912_get_voltage_sel,
.set_voltage_sel = tps65912_set_voltage_sel,
.list_voltage = tps65912_list_voltage,
};
/* Operations permitted on LDOx */
static struct regulator_ops tps65912_ops_ldo = {
.is_enabled = tps65912_reg_is_enabled,
.enable = tps65912_reg_enable,
.disable = tps65912_reg_disable,
.get_voltage_sel = tps65912_get_voltage_sel,
.set_voltage_sel = tps65912_set_voltage_sel,
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
};
static int tps65912_probe(struct platform_device *pdev)
{
struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = { };
struct tps_info *info;
struct regulator_init_data *reg_data;
struct regulator_dev *rdev;
struct tps65912_reg *pmic;
struct tps65912_board *pmic_plat_data;
int i;
pmic_plat_data = dev_get_platdata(tps65912->dev);
if (!pmic_plat_data)
return -EINVAL;
reg_data = pmic_plat_data->tps65912_pmic_init_data;
pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
if (!pmic)
return -ENOMEM;
mutex_init(&pmic->io_lock);
pmic->mfd = tps65912;
platform_set_drvdata(pdev, pmic);
pmic->get_ctrl_reg = &tps65912_get_ctrl_register;
info = tps65912_regs;
for (i = 0; i < TPS65912_NUM_REGULATOR; i++, info++, reg_data++) {
int range = 0;
/* Register the regulators */
pmic->info[i] = info;
pmic->desc[i].name = info->name;
pmic->desc[i].id = i;
pmic->desc[i].n_voltages = 64;
if (i > TPS65912_REG_DCDC4) {
pmic->desc[i].ops = &tps65912_ops_ldo;
pmic->desc[i].linear_ranges = tps65912_ldo_ranges;
pmic->desc[i].n_linear_ranges =
ARRAY_SIZE(tps65912_ldo_ranges);
} else {
pmic->desc[i].ops = &tps65912_ops_dcdc;
}
pmic->desc[i].type = REGULATOR_VOLTAGE;
pmic->desc[i].owner = THIS_MODULE;
range = tps65912_get_range(pmic, i);
config.dev = tps65912->dev;
config.init_data = reg_data;
config.driver_data = pmic;
rdev = devm_regulator_register(&pdev->dev, &pmic->desc[i],
&config);
if (IS_ERR(rdev)) {
dev_err(tps65912->dev,
"failed to register %s regulator\n",
pdev->name);
return PTR_ERR(rdev);
}
/* Save regulator for cleanup */
pmic->rdev[i] = rdev;
}
return 0;
}
static struct platform_driver tps65912_driver = {
.driver = {
.name = "tps65912-pmic",
},
.probe = tps65912_probe,
};
static int __init tps65912_init(void)
{
return platform_driver_register(&tps65912_driver);
}
subsys_initcall(tps65912_init);
static void __exit tps65912_cleanup(void)
{
platform_driver_unregister(&tps65912_driver);
}
module_exit(tps65912_cleanup);
MODULE_AUTHOR("Margarita Olaya Cabrera <magi@slimlogic.co.uk>");
MODULE_DESCRIPTION("TPS65912 voltage regulator driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:tps65912-pmic");
/*
* tps65912.h -- TI TPS6591x
*
* Copyright 2011 Texas Instruments Inc.
*
* Author: Margarita Olaya <magi@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.
*
*/
#ifndef __LINUX_MFD_TPS65912_H
#define __LINUX_MFD_TPS65912_H
/* TPS regulator type list */
#define REGULATOR_LDO 0
#define REGULATOR_DCDC 1
/*
* List of registers for TPS65912
*/
#define TPS65912_DCDC1_CTRL 0x00
#define TPS65912_DCDC2_CTRL 0x01
#define TPS65912_DCDC3_CTRL 0x02
#define TPS65912_DCDC4_CTRL 0x03
#define TPS65912_DCDC1_OP 0x04
#define TPS65912_DCDC1_AVS 0x05
#define TPS65912_DCDC1_LIMIT 0x06
#define TPS65912_DCDC2_OP 0x07
#define TPS65912_DCDC2_AVS 0x08
#define TPS65912_DCDC2_LIMIT 0x09
#define TPS65912_DCDC3_OP 0x0A
#define TPS65912_DCDC3_AVS 0x0B
#define TPS65912_DCDC3_LIMIT 0x0C
#define TPS65912_DCDC4_OP 0x0D
#define TPS65912_DCDC4_AVS 0x0E
#define TPS65912_DCDC4_LIMIT 0x0F
#define TPS65912_LDO1_OP 0x10
#define TPS65912_LDO1_AVS 0x11
#define TPS65912_LDO1_LIMIT 0x12
#define TPS65912_LDO2_OP 0x13
#define TPS65912_LDO2_AVS 0x14
#define TPS65912_LDO2_LIMIT 0x15
#define TPS65912_LDO3_OP 0x16
#define TPS65912_LDO3_AVS 0x17
#define TPS65912_LDO3_LIMIT 0x18
#define TPS65912_LDO4_OP 0x19
#define TPS65912_LDO4_AVS 0x1A
#define TPS65912_LDO4_LIMIT 0x1B
#define TPS65912_LDO5 0x1C
#define TPS65912_LDO6 0x1D
#define TPS65912_LDO7 0x1E
#define TPS65912_LDO8 0x1F
#define TPS65912_LDO9 0x20
#define TPS65912_LDO10 0x21
#define TPS65912_THRM 0x22
#define TPS65912_CLK32OUT 0x23
#define TPS65912_DEVCTRL 0x24
#define TPS65912_DEVCTRL2 0x25
#define TPS65912_I2C_SPI_CFG 0x26
#define TPS65912_KEEP_ON 0x27
#define TPS65912_KEEP_ON2 0x28
#define TPS65912_SET_OFF1 0x29
#define TPS65912_SET_OFF2 0x2A
#define TPS65912_DEF_VOLT 0x2B
#define TPS65912_DEF_VOLT_MAPPING 0x2C
#define TPS65912_DISCHARGE 0x2D
#define TPS65912_DISCHARGE2 0x2E
#define TPS65912_EN1_SET1 0x2F
#define TPS65912_EN1_SET2 0x30
#define TPS65912_EN2_SET1 0x31
#define TPS65912_EN2_SET2 0x32
#define TPS65912_EN3_SET1 0x33
#define TPS65912_EN3_SET2 0x34
#define TPS65912_EN4_SET1 0x35
#define TPS65912_EN4_SET2 0x36
#define TPS65912_PGOOD 0x37
#define TPS65912_PGOOD2 0x38
#define TPS65912_INT_STS 0x39
#define TPS65912_INT_MSK 0x3A
#define TPS65912_INT_STS2 0x3B
#define TPS65912_INT_MSK2 0x3C
#define TPS65912_INT_STS3 0x3D
#define TPS65912_INT_MSK3 0x3E
#define TPS65912_INT_STS4 0x3F
#define TPS65912_INT_MSK4 0x40
#define TPS65912_GPIO1 0x41
#define TPS65912_GPIO2 0x42
#define TPS65912_GPIO3 0x43
#define TPS65912_GPIO4 0x44
#define TPS65912_GPIO5 0x45
#define TPS65912_VMON 0x46
#define TPS65912_LEDA_CTRL1 0x47
#define TPS65912_LEDA_CTRL2 0x48
#define TPS65912_LEDA_CTRL3 0x49
#define TPS65912_LEDA_CTRL4 0x4A
#define TPS65912_LEDA_CTRL5 0x4B
#define TPS65912_LEDA_CTRL6 0x4C
#define TPS65912_LEDA_CTRL7 0x4D
#define TPS65912_LEDA_CTRL8 0x4E
#define TPS65912_LEDB_CTRL1 0x4F
#define TPS65912_LEDB_CTRL2 0x50
#define TPS65912_LEDB_CTRL3 0x51
#define TPS65912_LEDB_CTRL4 0x52
#define TPS65912_LEDB_CTRL5 0x53
#define TPS65912_LEDB_CTRL6 0x54
#define TPS65912_LEDB_CTRL7 0x55
#define TPS65912_LEDB_CTRL8 0x56
#define TPS65912_LEDC_CTRL1 0x57
#define TPS65912_LEDC_CTRL2 0x58
#define TPS65912_LEDC_CTRL3 0x59
#define TPS65912_LEDC_CTRL4 0x5A
#define TPS65912_LEDC_CTRL5 0x5B
#define TPS65912_LEDC_CTRL6 0x5C
#define TPS65912_LEDC_CTRL7 0x5D
#define TPS65912_LEDC_CTRL8 0x5E
#define TPS65912_LED_RAMP_UP_TIME 0x5F
#define TPS65912_LED_RAMP_DOWN_TIME 0x60
#define TPS65912_LED_SEQ_EN 0x61
#define TPS65912_LOADSWITCH 0x62
#define TPS65912_SPARE 0x63
#define TPS65912_VERNUM 0x64
#define TPS6591X_MAX_REGISTER 0x64
/* IRQ Definitions */
#define TPS65912_IRQ_PWRHOLD_F 0
#define TPS65912_IRQ_VMON 1
#define TPS65912_IRQ_PWRON 2
#define TPS65912_IRQ_PWRON_LP 3
#define TPS65912_IRQ_PWRHOLD_R 4
#define TPS65912_IRQ_HOTDIE 5
#define TPS65912_IRQ_GPIO1_R 6
#define TPS65912_IRQ_GPIO1_F 7
#define TPS65912_IRQ_GPIO2_R 8
#define TPS65912_IRQ_GPIO2_F 9
#define TPS65912_IRQ_GPIO3_R 10
#define TPS65912_IRQ_GPIO3_F 11
#define TPS65912_IRQ_GPIO4_R 12
#define TPS65912_IRQ_GPIO4_F 13
#define TPS65912_IRQ_GPIO5_R 14
#define TPS65912_IRQ_GPIO5_F 15
#define TPS65912_IRQ_PGOOD_DCDC1 16
#define TPS65912_IRQ_PGOOD_DCDC2 17
#define TPS65912_IRQ_PGOOD_DCDC3 18
#define TPS65912_IRQ_PGOOD_DCDC4 19
#define TPS65912_IRQ_PGOOD_LDO1 20
#define TPS65912_IRQ_PGOOD_LDO2 21
#define TPS65912_IRQ_PGOOD_LDO3 22
#define TPS65912_IRQ_PGOOD_LDO4 23
#define TPS65912_IRQ_PGOOD_LDO5 24
#define TPS65912_IRQ_PGOOD_LDO6 25
#define TPS65912_IRQ_PGOOD_LDO7 26
#define TPS65912_IRQ_PGOOD_LD08 27
#define TPS65912_IRQ_PGOOD_LDO9 28
#define TPS65912_IRQ_PGOOD_LDO10 29
#define TPS65912_NUM_IRQ 30
/* GPIO 1 and 2 Register Definitions */
#define GPIO_SLEEP_MASK 0x80
#define GPIO_SLEEP_SHIFT 7
#define GPIO_DEB_MASK 0x10
#define GPIO_DEB_SHIFT 4
#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
/* GPIO 3 Register Definitions */
#define GPIO3_SLEEP_MASK 0x80
#define GPIO3_SLEEP_SHIFT 7
#define GPIO3_SEL_MASK 0x40
#define GPIO3_SEL_SHIFT 6
#define GPIO3_ODEN_MASK 0x20
#define GPIO3_ODEN_SHIFT 5
#define GPIO3_DEB_MASK 0x10
#define GPIO3_DEB_SHIFT 4
#define GPIO3_PDEN_MASK 0x08
#define GPIO3_PDEN_SHIFT 3
#define GPIO3_CFG_MASK 0x04
#define GPIO3_CFG_SHIFT 2
#define GPIO3_STS_MASK 0x02
#define GPIO3_STS_SHIFT 1
#define GPIO3_SET_MASK 0x01
#define GPIO3_SET_SHIFT 0
/* GPIO 4 Register Definitions */
#define GPIO4_SLEEP_MASK 0x80
#define GPIO4_SLEEP_SHIFT 7
#define GPIO4_SEL_MASK 0x40
#define GPIO4_SEL_SHIFT 6
#define GPIO4_ODEN_MASK 0x20
#define GPIO4_ODEN_SHIFT 5
#define GPIO4_DEB_MASK 0x10
#define GPIO4_DEB_SHIFT 4
#define GPIO4_PDEN_MASK 0x08
#define GPIO4_PDEN_SHIFT 3
#define GPIO4_CFG_MASK 0x04
#define GPIO4_CFG_SHIFT 2
#define GPIO4_STS_MASK 0x02
#define GPIO4_STS_SHIFT 1
#define GPIO4_SET_MASK 0x01
#define GPIO4_SET_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 DCDCCTRL1 register.RegisterDescription */
#define DCDCCTRL_VCON_ENABLE_MASK 0x80
#define DCDCCTRL_VCON_ENABLE_SHIFT 7
#define DCDCCTRL_VCON_RANGE1_MASK 0x40
#define DCDCCTRL_VCON_RANGE1_SHIFT 6
#define DCDCCTRL_VCON_RANGE0_MASK 0x20
#define DCDCCTRL_VCON_RANGE0_SHIFT 5
#define DCDCCTRL_TSTEP2_MASK 0x10
#define DCDCCTRL_TSTEP2_SHIFT 4
#define DCDCCTRL_TSTEP1_MASK 0x08
#define DCDCCTRL_TSTEP1_SHIFT 3
#define DCDCCTRL_TSTEP0_MASK 0x04
#define DCDCCTRL_TSTEP0_SHIFT 2
#define DCDCCTRL_DCDC1_MODE_MASK 0x02
#define DCDCCTRL_DCDC1_MODE_SHIFT 1
/* Register DCDCCTRL2 and DCDCCTRL3 register.RegisterDescription */
#define DCDCCTRL_TSTEP2_MASK 0x10
#define DCDCCTRL_TSTEP2_SHIFT 4
#define DCDCCTRL_TSTEP1_MASK 0x08
#define DCDCCTRL_TSTEP1_SHIFT 3
#define DCDCCTRL_TSTEP0_MASK 0x04
#define DCDCCTRL_TSTEP0_SHIFT 2
#define DCDCCTRL_DCDC_MODE_MASK 0x02
#define DCDCCTRL_DCDC_MODE_SHIFT 1
#define DCDCCTRL_RSVD0_MASK 0x01
#define DCDCCTRL_RSVD0_SHIFT 0
/* Register DCDCCTRL4 register.RegisterDescription */
#define DCDCCTRL_RAMP_TIME_MASK 0x01
#define DCDCCTRL_RAMP_TIME_SHIFT 0
/* Register DCDCx_AVS */
#define DCDC_AVS_ENABLE_MASK 0x80
#define DCDC_AVS_ENABLE_SHIFT 7
#define DCDC_AVS_ECO_MASK 0x40
#define DCDC_AVS_ECO_SHIFT 6
/* Register DCDCx_LIMIT */
#define DCDC_LIMIT_RANGE_MASK 0xC0
#define DCDC_LIMIT_RANGE_SHIFT 6
#define DCDC_LIMIT_MAX_SEL_MASK 0x3F
#define DCDC_LIMIT_MAX_SEL_SHIFT 0
/**
* struct tps65912_board
* Board platform dat may be used to initialize regulators.
*/
struct tps65912_board {
int is_dcdc1_avs;
int is_dcdc2_avs;
int is_dcdc3_avs;
int is_dcdc4_avs;
int irq;
int irq_base;
int gpio_base;
struct regulator_init_data *tps65912_pmic_init_data;
};
/**
* struct tps65912 - tps65912 sub-driver chip access routines
*/
struct tps65912 {
struct device *dev;
/* for read/write acces */
struct mutex io_mutex;
/* For device IO interfaces: I2C or SPI */
void *control_data;
int (*read)(struct tps65912 *tps65912, u8 reg, int size, void *dest);
int (*write)(struct tps65912 *tps65912, u8 reg, int size, void *src);
/* Client devices */
struct tps65912_pmic *pmic;
/* 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 tps65912_platform_data {
int irq;
int irq_base;
};
unsigned int tps_chip(void);
int tps65912_set_bits(struct tps65912 *tps65912, u8 reg, u8 mask);
int tps65912_clear_bits(struct tps65912 *tps65912, u8 reg, u8 mask);
int tps65912_reg_read(struct tps65912 *tps65912, u8 reg);
int tps65912_reg_write(struct tps65912 *tps65912, u8 reg, u8 val);
int tps65912_device_init(struct tps65912 *tps65912);
void tps65912_device_exit(struct tps65912 *tps65912);
int tps65912_irq_init(struct tps65912 *tps65912, int irq,
struct tps65912_platform_data *pdata);
int tps65912_irq_exit(struct tps65912 *tps65912);
#endif /* __LINUX_MFD_TPS65912_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册