aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/tps6586x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/tps6586x.c')
-rw-r--r--drivers/mfd/tps6586x.c107
1 files changed, 21 insertions, 86 deletions
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index d59bfb77326b..353c34812120 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -22,7 +22,6 @@
22#include <linux/mutex.h> 22#include <linux/mutex.h>
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/err.h> 24#include <linux/err.h>
25#include <linux/gpio.h>
26#include <linux/i2c.h> 25#include <linux/i2c.h>
27#include <linux/regmap.h> 26#include <linux/regmap.h>
28#include <linux/regulator/of_regulator.h> 27#include <linux/regulator/of_regulator.h>
@@ -30,10 +29,6 @@
30#include <linux/mfd/core.h> 29#include <linux/mfd/core.h>
31#include <linux/mfd/tps6586x.h> 30#include <linux/mfd/tps6586x.h>
32 31
33/* GPIO control registers */
34#define TPS6586X_GPIOSET1 0x5d
35#define TPS6586X_GPIOSET2 0x5e
36
37/* interrupt control registers */ 32/* interrupt control registers */
38#define TPS6586X_INT_ACK1 0xb5 33#define TPS6586X_INT_ACK1 0xb5
39#define TPS6586X_INT_ACK2 0xb6 34#define TPS6586X_INT_ACK2 0xb6
@@ -94,12 +89,23 @@ static const struct tps6586x_irq_data tps6586x_irqs[] = {
94 [TPS6586X_INT_RTC_ALM2] = TPS6586X_IRQ(TPS6586X_INT_MASK4, 1 << 1), 89 [TPS6586X_INT_RTC_ALM2] = TPS6586X_IRQ(TPS6586X_INT_MASK4, 1 << 1),
95}; 90};
96 91
92static struct mfd_cell tps6586x_cell[] = {
93 {
94 .name = "tps6586x-gpio",
95 },
96 {
97 .name = "tps6586x-rtc",
98 },
99 {
100 .name = "tps6586x-onkey",
101 },
102};
103
97struct tps6586x { 104struct tps6586x {
98 struct device *dev; 105 struct device *dev;
99 struct i2c_client *client; 106 struct i2c_client *client;
100 struct regmap *regmap; 107 struct regmap *regmap;
101 108
102 struct gpio_chip gpio;
103 struct irq_chip irq_chip; 109 struct irq_chip irq_chip;
104 struct mutex irq_lock; 110 struct mutex irq_lock;
105 int irq_base; 111 int irq_base;
@@ -173,63 +179,6 @@ int tps6586x_update(struct device *dev, int reg, uint8_t val, uint8_t mask)
173} 179}
174EXPORT_SYMBOL_GPL(tps6586x_update); 180EXPORT_SYMBOL_GPL(tps6586x_update);
175 181
176static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset)
177{
178 struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio);
179 uint8_t val;
180 int ret;
181
182 ret = tps6586x_read(tps6586x->dev, TPS6586X_GPIOSET2, &val);
183 if (ret)
184 return ret;
185
186 return !!(val & (1 << offset));
187}
188
189
190static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset,
191 int value)
192{
193 struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio);
194
195 tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET2,
196 value << offset, 1 << offset);
197}
198
199static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset,
200 int value)
201{
202 struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio);
203 uint8_t val, mask;
204
205 tps6586x_gpio_set(gc, offset, value);
206
207 val = 0x1 << (offset * 2);
208 mask = 0x3 << (offset * 2);
209
210 return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask);
211}
212
213static int tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base)
214{
215 if (!gpio_base)
216 return 0;
217
218 tps6586x->gpio.owner = THIS_MODULE;
219 tps6586x->gpio.label = tps6586x->client->name;
220 tps6586x->gpio.dev = tps6586x->dev;
221 tps6586x->gpio.base = gpio_base;
222 tps6586x->gpio.ngpio = 4;
223 tps6586x->gpio.can_sleep = 1;
224
225 /* FIXME: add handling of GPIOs as dedicated inputs */
226 tps6586x->gpio.direction_output = tps6586x_gpio_output;
227 tps6586x->gpio.set = tps6586x_gpio_set;
228 tps6586x->gpio.get = tps6586x_gpio_get;
229
230 return gpiochip_add(&tps6586x->gpio);
231}
232
233static int __remove_subdev(struct device *dev, void *unused) 182static int __remove_subdev(struct device *dev, void *unused)
234{ 183{
235 platform_device_unregister(to_platform_device(dev)); 184 platform_device_unregister(to_platform_device(dev));
@@ -543,10 +492,11 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
543 } 492 }
544 } 493 }
545 494
546 ret = tps6586x_gpio_init(tps6586x, pdata->gpio_base); 495 ret = mfd_add_devices(tps6586x->dev, -1,
547 if (ret) { 496 tps6586x_cell, ARRAY_SIZE(tps6586x_cell), NULL, 0);
548 dev_err(&client->dev, "GPIO registration failed: %d\n", ret); 497 if (ret < 0) {
549 goto err_gpio_init; 498 dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret);
499 goto err_mfd_add;
550 } 500 }
551 501
552 ret = tps6586x_add_subdevs(tps6586x, pdata); 502 ret = tps6586x_add_subdevs(tps6586x, pdata);
@@ -558,36 +508,21 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
558 return 0; 508 return 0;
559 509
560err_add_devs: 510err_add_devs:
561 if (pdata->gpio_base) { 511 mfd_remove_devices(tps6586x->dev);
562 ret = gpiochip_remove(&tps6586x->gpio); 512err_mfd_add:
563 if (ret)
564 dev_err(&client->dev, "Can't remove gpio chip: %d\n",
565 ret);
566 }
567err_gpio_init:
568 if (client->irq) 513 if (client->irq)
569 free_irq(client->irq, tps6586x); 514 free_irq(client->irq, tps6586x);
570
571 return ret; 515 return ret;
572} 516}
573 517
574static int __devexit tps6586x_i2c_remove(struct i2c_client *client) 518static int __devexit tps6586x_i2c_remove(struct i2c_client *client)
575{ 519{
576 struct tps6586x *tps6586x = i2c_get_clientdata(client); 520 struct tps6586x *tps6586x = i2c_get_clientdata(client);
577 struct tps6586x_platform_data *pdata = client->dev.platform_data;
578 int ret;
579 521
522 tps6586x_remove_subdevs(tps6586x);
523 mfd_remove_devices(tps6586x->dev);
580 if (client->irq) 524 if (client->irq)
581 free_irq(client->irq, tps6586x); 525 free_irq(client->irq, tps6586x);
582
583 if (pdata->gpio_base) {
584 ret = gpiochip_remove(&tps6586x->gpio);
585 if (ret)
586 dev_err(&client->dev, "Can't remove gpio chip: %d\n",
587 ret);
588 }
589
590 tps6586x_remove_subdevs(tps6586x);
591 return 0; 526 return 0;
592} 527}
593 528