Skip to content

Commit

Permalink
mfd: Add TPS6507x support
Browse files Browse the repository at this point in the history
TPS6507x are multi function (PM, touchscreen) chipsets from TI.
This commit also changes the corresponding regulator driver from being
standalone to an MFD subdevice.

Signed-off-by: Todd Fischer <[email protected]>
Acked-by: Mark Brown <[email protected]>
Signed-off-by: Liam Girdwood <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
  • Loading branch information
fischer authored and Samuel Ortiz committed May 27, 2010
1 parent 4ce5ba5 commit 31dd6a2
Show file tree
Hide file tree
Showing 5 changed files with 265 additions and 79 deletions.
12 changes: 12 additions & 0 deletions drivers/mfd/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,18 @@ config TPS65010
This driver can also be built as a module. If so, the module
will be called tps65010.

config TPS6507X
tristate "TPS6507x Power Management / Touch Screen chips"
select MFD_CORE
depends on I2C
help
If you say yes here you get support for the TPS6507x series of
Power Management / Touch Screen chips. These include voltage
regulators, lithium ion/polymer battery charging, touch screen
and other features that are often used in portable devices.
This driver can also be built as a module. If so, the module
will be called tps6507x.

config MENELAUS
bool "Texas Instruments TWL92330/Menelaus PM chip"
depends on I2C=y && ARCH_OMAP2
Expand Down
1 change: 1 addition & 0 deletions drivers/mfd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o

obj-$(CONFIG_TPS65010) += tps65010.o
obj-$(CONFIG_TPS6507X) += tps6507x.o
obj-$(CONFIG_MENELAUS) += menelaus.o

obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o
Expand Down
156 changes: 156 additions & 0 deletions drivers/mfd/tps6507x.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/*
* tps6507x.c -- TPS6507x chip family multi-function driver
*
* Copyright (c) 2010 RidgeRun ([email protected])
*
* Author: Todd Fischer
* [email protected]
*
* Credits:
*
* Using code from wm831x-*.c, wm8400-core, Wolfson Microelectronics PLC.
*
* For licencing details see kernel-base/COPYING
*
*/

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps6507x.h>

static struct mfd_cell tps6507x_devs[] = {
{
.name = "tps6507x-pmic",
},
};


static int tps6507x_i2c_read_device(struct tps6507x_dev *tps6507x, char reg,
int bytes, void *dest)
{
struct i2c_client *i2c = tps6507x->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 tps6507x_i2c_write_device(struct tps6507x_dev *tps6507x, char reg,
int bytes, void *src)
{
struct i2c_client *i2c = tps6507x->i2c_client;
/* we add 1 byte for device register */
u8 msg[TPS6507X_MAX_REGISTER + 1];
int ret;

if (bytes > (TPS6507X_MAX_REGISTER + 1))
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 tps6507x_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct tps6507x_dev *tps6507x;
int ret = 0;

tps6507x = kzalloc(sizeof(struct tps6507x_dev), GFP_KERNEL);
if (tps6507x == NULL) {
kfree(i2c);
return -ENOMEM;
}

i2c_set_clientdata(i2c, tps6507x);
tps6507x->dev = &i2c->dev;
tps6507x->i2c_client = i2c;
tps6507x->read_dev = tps6507x_i2c_read_device;
tps6507x->write_dev = tps6507x_i2c_write_device;

ret = mfd_add_devices(tps6507x->dev, -1,
tps6507x_devs, ARRAY_SIZE(tps6507x_devs),
NULL, 0);

if (ret < 0)
goto err;

return ret;

err:
mfd_remove_devices(tps6507x->dev);
kfree(tps6507x);
return ret;
}

static int tps6507x_i2c_remove(struct i2c_client *i2c)
{
struct tps6507x_dev *tps6507x = i2c_get_clientdata(i2c);

mfd_remove_devices(tps6507x->dev);
kfree(tps6507x);

return 0;
}

static const struct i2c_device_id tps6507x_i2c_id[] = {
{ "tps6507x", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tps6507x_i2c_id);


static struct i2c_driver tps6507x_i2c_driver = {
.driver = {
.name = "tps6507x",
.owner = THIS_MODULE,
},
.probe = tps6507x_i2c_probe,
.remove = tps6507x_i2c_remove,
.id_table = tps6507x_i2c_id,
};

static int __init tps6507x_i2c_init(void)
{
return i2c_add_driver(&tps6507x_i2c_driver);
}
/* init early so consumer devices can complete system boot */
subsys_initcall(tps6507x_i2c_init);

static void __exit tps6507x_i2c_exit(void)
{
i2c_del_driver(&tps6507x_i2c_driver);
}
module_exit(tps6507x_i2c_exit);

MODULE_DESCRIPTION("TPS6507x chip family multi-function driver");
MODULE_LICENSE("GPL");
Loading

0 comments on commit 31dd6a2

Please sign in to comment.