summaryrefslogtreecommitdiffstats
path: root/drivers/mfd/tps65910.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-28 13:56:35 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-28 13:56:35 -0700
commit30304e5a79d424eb2c8707b3ff0e9b8bf6ab3e8f (patch)
tree63968fb97b86861e31922515395feef8a110f884 /drivers/mfd/tps65910.c
parent750f77064a290beb162352077b52c61b04bcae0e (diff)
parentb8589e2a8065b8e7773742b60ae96b63b757bb69 (diff)
downloadop-kernel-dev-30304e5a79d424eb2c8707b3ff0e9b8bf6ab3e8f.zip
op-kernel-dev-30304e5a79d424eb2c8707b3ff0e9b8bf6ab3e8f.tar.gz
Merge tag 'mfd_3.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
Pull MFD changes from Samuel Ortiz: - 4 new drivers: Freescale i.MX on-chip Anatop, Ricoh's RC5T583 and TI's TPS65090 and TPS65217. - New variants support (8420, 8520 ab9540), cleanups and bug fixes for the abx500 and db8500 ST-E chipsets. - Some minor fixes and update for the wm8994 from Mark. - The beginning of a long term TWL cleanup effort coming from the TI folks. - Various fixes and cleanups for the s5m, TPS659xx, pm860x, and MAX8997 drivers. Fix up trivial conflicts due to duplicate patches and header file cleanups (<linux/device.h> removal etc). * tag 'mfd_3.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (97 commits) gpio/twl: Add DT support to gpio-twl4030 driver gpio/twl: Allocate irq_desc dynamically for SPARSE_IRQ support mfd: Detach twl6040 from the pmic mfd driver mfd: Replace twl-* pr_ macros by the dev_ equivalent and do various cleanups mfd: Micro-optimization on twl4030 IRQ handler mfd: Make twl4030 SIH SPARSE_IRQ capable mfd: Move twl-core IRQ allocation into twl[4030|6030]-irq files mfd: Remove references already defineid in header file from twl-core mfd: Remove unneeded header from twl-core mfd: Make twl-core not depend on pdata->irq_base/end ARM: OMAP2+: board-omap4-*: Do not use anymore TWL6030_IRQ_BASE in board files mfd: Return twl6030_mmc_card_detect IRQ for board setup Revert "mfd: Add platform data for MAX8997 haptic driver" mfd: Add support for TPS65090 mfd: Add some da9052-i2c section annotations mfd: Build rtc5t583 only if I2C config is selected to y. mfd: Add anatop mfd driver mfd: Fix compilation error in tps65910.h mfd: Add 8420 variant to db8500-prcmu mfd: Add 8520 PRCMU variant to db8500-prcmu ...
Diffstat (limited to 'drivers/mfd/tps65910.c')
-rw-r--r--drivers/mfd/tps65910.c123
1 files changed, 46 insertions, 77 deletions
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index 4392f6b..bf2b25e 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -16,10 +16,12 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
+#include <linux/err.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/mfd/core.h>
+#include <linux/regmap.h>
#include <linux/mfd/tps65910.h>
static struct mfd_cell tps65910s[] = {
@@ -38,99 +40,56 @@ static struct mfd_cell tps65910s[] = {
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;
+ return regmap_bulk_read(tps65910->regmap, reg, dest, bytes);
}
static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg,
- int bytes, void *src)
+ 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;
+ return regmap_bulk_write(tps65910->regmap, reg, src, bytes);
}
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;
+ return regmap_update_bits(tps65910->regmap, reg, mask, mask);
}
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;
+ return regmap_update_bits(tps65910->regmap, reg, mask, 0);
}
EXPORT_SYMBOL_GPL(tps65910_clear_bits);
+static bool is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ struct tps65910 *tps65910 = dev_get_drvdata(dev);
+
+ /*
+ * Caching all regulator registers.
+ * All regualator register address range is same for
+ * TPS65910 and TPS65911
+ */
+ if ((reg >= TPS65910_VIO) && (reg <= TPS65910_VDAC)) {
+ /* Check for non-existing register */
+ if (tps65910_chip_id(tps65910) == TPS65910)
+ if ((reg == TPS65911_VDDCTRL_OP) ||
+ (reg == TPS65911_VDDCTRL_SR))
+ return true;
+ return false;
+ }
+ return true;
+}
+
+static const struct regmap_config tps65910_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .volatile_reg = is_volatile_reg,
+ .max_register = TPS65910_MAX_REGISTER,
+ .num_reg_defaults_raw = TPS65910_MAX_REGISTER,
+ .cache_type = REGCACHE_RBTREE,
+};
+
static int tps65910_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -161,6 +120,13 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
tps65910->write = tps65910_i2c_write;
mutex_init(&tps65910->io_mutex);
+ tps65910->regmap = regmap_init_i2c(i2c, &tps65910_regmap_config);
+ if (IS_ERR(tps65910->regmap)) {
+ ret = PTR_ERR(tps65910->regmap);
+ dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret);
+ goto regmap_err;
+ }
+
ret = mfd_add_devices(tps65910->dev, -1,
tps65910s, ARRAY_SIZE(tps65910s),
NULL, 0);
@@ -178,6 +144,8 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
return ret;
err:
+ regmap_exit(tps65910->regmap);
+regmap_err:
kfree(tps65910);
kfree(init_data);
return ret;
@@ -189,6 +157,7 @@ static int tps65910_i2c_remove(struct i2c_client *i2c)
tps65910_irq_exit(tps65910);
mfd_remove_devices(tps65910->dev);
+ regmap_exit(tps65910->regmap);
kfree(tps65910);
return 0;
OpenPOWER on IntegriCloud