aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/tps65910.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-28 16:56:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-28 16:56:35 -0400
commit30304e5a79d424eb2c8707b3ff0e9b8bf6ab3e8f (patch)
tree63968fb97b86861e31922515395feef8a110f884 /drivers/mfd/tps65910.c
parent750f77064a290beb162352077b52c61b04bcae0e (diff)
parentb8589e2a8065b8e7773742b60ae96b63b757bb69 (diff)
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 4392f6bca156..bf2b25ebf2ca 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -16,10 +16,12 @@
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/moduleparam.h> 17#include <linux/moduleparam.h>
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/err.h>
19#include <linux/slab.h> 20#include <linux/slab.h>
20#include <linux/i2c.h> 21#include <linux/i2c.h>
21#include <linux/gpio.h> 22#include <linux/gpio.h>
22#include <linux/mfd/core.h> 23#include <linux/mfd/core.h>
24#include <linux/regmap.h>
23#include <linux/mfd/tps65910.h> 25#include <linux/mfd/tps65910.h>
24 26
25static struct mfd_cell tps65910s[] = { 27static struct mfd_cell tps65910s[] = {
@@ -38,99 +40,56 @@ static struct mfd_cell tps65910s[] = {
38static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg, 40static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg,
39 int bytes, void *dest) 41 int bytes, void *dest)
40{ 42{
41 struct i2c_client *i2c = tps65910->i2c_client; 43 return regmap_bulk_read(tps65910->regmap, reg, dest, bytes);
42 struct i2c_msg xfer[2];
43 int ret;
44
45 /* Write register */
46 xfer[0].addr = i2c->addr;
47 xfer[0].flags = 0;
48 xfer[0].len = 1;
49 xfer[0].buf = &reg;
50
51 /* Read data */
52 xfer[1].addr = i2c->addr;
53 xfer[1].flags = I2C_M_RD;
54 xfer[1].len = bytes;
55 xfer[1].buf = dest;
56
57 ret = i2c_transfer(i2c->adapter, xfer, 2);
58 if (ret == 2)
59 ret = 0;
60 else if (ret >= 0)
61 ret = -EIO;
62
63 return ret;
64} 44}
65 45
66static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg, 46static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg,
67 int bytes, void *src) 47 int bytes, void *src)
68{ 48{
69 struct i2c_client *i2c = tps65910->i2c_client; 49 return regmap_bulk_write(tps65910->regmap, reg, src, bytes);
70 /* we add 1 byte for device register */
71 u8 msg[TPS65910_MAX_REGISTER + 1];
72 int ret;
73
74 if (bytes > TPS65910_MAX_REGISTER)
75 return -EINVAL;
76
77 msg[0] = reg;
78 memcpy(&msg[1], src, bytes);
79
80 ret = i2c_master_send(i2c, msg, bytes + 1);
81 if (ret < 0)
82 return ret;
83 if (ret != bytes + 1)
84 return -EIO;
85 return 0;
86} 50}
87 51
88int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask) 52int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask)
89{ 53{
90 u8 data; 54 return regmap_update_bits(tps65910->regmap, reg, mask, mask);
91 int err;
92
93 mutex_lock(&tps65910->io_mutex);
94 err = tps65910_i2c_read(tps65910, reg, 1, &data);
95 if (err) {
96 dev_err(tps65910->dev, "read from reg %x failed\n", reg);
97 goto out;
98 }
99
100 data |= mask;
101 err = tps65910_i2c_write(tps65910, reg, 1, &data);
102 if (err)
103 dev_err(tps65910->dev, "write to reg %x failed\n", reg);
104
105out:
106 mutex_unlock(&tps65910->io_mutex);
107 return err;
108} 55}
109EXPORT_SYMBOL_GPL(tps65910_set_bits); 56EXPORT_SYMBOL_GPL(tps65910_set_bits);
110 57
111int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask) 58int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask)
112{ 59{
113 u8 data; 60 return regmap_update_bits(tps65910->regmap, reg, mask, 0);
114 int err;
115
116 mutex_lock(&tps65910->io_mutex);
117 err = tps65910_i2c_read(tps65910, reg, 1, &data);
118 if (err) {
119 dev_err(tps65910->dev, "read from reg %x failed\n", reg);
120 goto out;
121 }
122
123 data &= ~mask;
124 err = tps65910_i2c_write(tps65910, reg, 1, &data);
125 if (err)
126 dev_err(tps65910->dev, "write to reg %x failed\n", reg);
127
128out:
129 mutex_unlock(&tps65910->io_mutex);
130 return err;
131} 61}
132EXPORT_SYMBOL_GPL(tps65910_clear_bits); 62EXPORT_SYMBOL_GPL(tps65910_clear_bits);
133 63
64static bool is_volatile_reg(struct device *dev, unsigned int reg)
65{
66 struct tps65910 *tps65910 = dev_get_drvdata(dev);
67
68 /*
69 * Caching all regulator registers.
70 * All regualator register address range is same for
71 * TPS65910 and TPS65911
72 */
73 if ((reg >= TPS65910_VIO) && (reg <= TPS65910_VDAC)) {
74 /* Check for non-existing register */
75 if (tps65910_chip_id(tps65910) == TPS65910)
76 if ((reg == TPS65911_VDDCTRL_OP) ||
77 (reg == TPS65911_VDDCTRL_SR))
78 return true;
79 return false;
80 }
81 return true;
82}
83
84static const struct regmap_config tps65910_regmap_config = {
85 .reg_bits = 8,
86 .val_bits = 8,
87 .volatile_reg = is_volatile_reg,
88 .max_register = TPS65910_MAX_REGISTER,
89 .num_reg_defaults_raw = TPS65910_MAX_REGISTER,
90 .cache_type = REGCACHE_RBTREE,
91};
92
134static int tps65910_i2c_probe(struct i2c_client *i2c, 93static int tps65910_i2c_probe(struct i2c_client *i2c,
135 const struct i2c_device_id *id) 94 const struct i2c_device_id *id)
136{ 95{
@@ -161,6 +120,13 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
161 tps65910->write = tps65910_i2c_write; 120 tps65910->write = tps65910_i2c_write;
162 mutex_init(&tps65910->io_mutex); 121 mutex_init(&tps65910->io_mutex);
163 122
123 tps65910->regmap = regmap_init_i2c(i2c, &tps65910_regmap_config);
124 if (IS_ERR(tps65910->regmap)) {
125 ret = PTR_ERR(tps65910->regmap);
126 dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret);
127 goto regmap_err;
128 }
129
164 ret = mfd_add_devices(tps65910->dev, -1, 130 ret = mfd_add_devices(tps65910->dev, -1,
165 tps65910s, ARRAY_SIZE(tps65910s), 131 tps65910s, ARRAY_SIZE(tps65910s),
166 NULL, 0); 132 NULL, 0);
@@ -178,6 +144,8 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
178 return ret; 144 return ret;
179 145
180err: 146err:
147 regmap_exit(tps65910->regmap);
148regmap_err:
181 kfree(tps65910); 149 kfree(tps65910);
182 kfree(init_data); 150 kfree(init_data);
183 return ret; 151 return ret;
@@ -189,6 +157,7 @@ static int tps65910_i2c_remove(struct i2c_client *i2c)
189 157
190 tps65910_irq_exit(tps65910); 158 tps65910_irq_exit(tps65910);
191 mfd_remove_devices(tps65910->dev); 159 mfd_remove_devices(tps65910->dev);
160 regmap_exit(tps65910->regmap);
192 kfree(tps65910); 161 kfree(tps65910);
193 162
194 return 0; 163 return 0;