mfd: Add TPS6586x driver
[linux-2.6.git] / drivers / mfd / tps6586x.c
1 /*
2  * Core driver for TI TPS6586x PMIC family
3  *
4  * Copyright (c) 2010 CompuLab Ltd.
5  * Mike Rapoport <mike@compulab.co.il>
6  *
7  * Based on da903x.c.
8  * Copyright (C) 2008 Compulab, Ltd.
9  * Mike Rapoport <mike@compulab.co.il>
10  * Copyright (C) 2006-2008 Marvell International Ltd.
11  * Eric Miao <eric.miao@marvell.com>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License version 2 as
15  * published by the Free Software Foundation.
16  */
17
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/mutex.h>
21 #include <linux/slab.h>
22 #include <linux/gpio.h>
23 #include <linux/i2c.h>
24
25 #include <linux/mfd/core.h>
26 #include <linux/mfd/tps6586x.h>
27
28 /* GPIO control registers */
29 #define TPS6586X_GPIOSET1       0x5d
30 #define TPS6586X_GPIOSET2       0x5e
31
32 /* device id */
33 #define TPS6586X_VERSIONCRC     0xcd
34 #define TPS658621A_VERSIONCRC   0x15
35
36 struct tps6586x {
37         struct mutex            lock;
38         struct device           *dev;
39         struct i2c_client       *client;
40
41         struct gpio_chip        gpio;
42 };
43
44 static inline int __tps6586x_read(struct i2c_client *client,
45                                   int reg, uint8_t *val)
46 {
47         int ret;
48
49         ret = i2c_smbus_read_byte_data(client, reg);
50         if (ret < 0) {
51                 dev_err(&client->dev, "failed reading at 0x%02x\n", reg);
52                 return ret;
53         }
54
55         *val = (uint8_t)ret;
56
57         return 0;
58 }
59
60 static inline int __tps6586x_reads(struct i2c_client *client, int reg,
61                                    int len, uint8_t *val)
62 {
63         int ret;
64
65         ret = i2c_smbus_read_i2c_block_data(client, reg, len, val);
66         if (ret < 0) {
67                 dev_err(&client->dev, "failed reading from 0x%02x\n", reg);
68                 return ret;
69         }
70
71         return 0;
72 }
73
74 static inline int __tps6586x_write(struct i2c_client *client,
75                                  int reg, uint8_t val)
76 {
77         int ret;
78
79         ret = i2c_smbus_write_byte_data(client, reg, val);
80         if (ret < 0) {
81                 dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n",
82                                 val, reg);
83                 return ret;
84         }
85
86         return 0;
87 }
88
89 static inline int __tps6586x_writes(struct i2c_client *client, int reg,
90                                   int len, uint8_t *val)
91 {
92         int ret;
93
94         ret = i2c_smbus_write_i2c_block_data(client, reg, len, val);
95         if (ret < 0) {
96                 dev_err(&client->dev, "failed writings to 0x%02x\n", reg);
97                 return ret;
98         }
99
100         return 0;
101 }
102
103 int tps6586x_write(struct device *dev, int reg, uint8_t val)
104 {
105         return __tps6586x_write(to_i2c_client(dev), reg, val);
106 }
107 EXPORT_SYMBOL_GPL(tps6586x_write);
108
109 int tps6586x_writes(struct device *dev, int reg, int len, uint8_t *val)
110 {
111         return __tps6586x_writes(to_i2c_client(dev), reg, len, val);
112 }
113 EXPORT_SYMBOL_GPL(tps6586x_writes);
114
115 int tps6586x_read(struct device *dev, int reg, uint8_t *val)
116 {
117         return __tps6586x_read(to_i2c_client(dev), reg, val);
118 }
119 EXPORT_SYMBOL_GPL(tps6586x_read);
120
121 int tps6586x_reads(struct device *dev, int reg, int len, uint8_t *val)
122 {
123         return __tps6586x_reads(to_i2c_client(dev), reg, len, val);
124 }
125 EXPORT_SYMBOL_GPL(tps6586x_reads);
126
127 int tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask)
128 {
129         struct tps6586x *tps6586x = dev_get_drvdata(dev);
130         uint8_t reg_val;
131         int ret = 0;
132
133         mutex_lock(&tps6586x->lock);
134
135         ret = __tps6586x_read(to_i2c_client(dev), reg, &reg_val);
136         if (ret)
137                 goto out;
138
139         if ((reg_val & bit_mask) == 0) {
140                 reg_val |= bit_mask;
141                 ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val);
142         }
143 out:
144         mutex_unlock(&tps6586x->lock);
145         return ret;
146 }
147 EXPORT_SYMBOL_GPL(tps6586x_set_bits);
148
149 int tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask)
150 {
151         struct tps6586x *tps6586x = dev_get_drvdata(dev);
152         uint8_t reg_val;
153         int ret = 0;
154
155         mutex_lock(&tps6586x->lock);
156
157         ret = __tps6586x_read(to_i2c_client(dev), reg, &reg_val);
158         if (ret)
159                 goto out;
160
161         if (reg_val & bit_mask) {
162                 reg_val &= ~bit_mask;
163                 ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val);
164         }
165 out:
166         mutex_unlock(&tps6586x->lock);
167         return ret;
168 }
169 EXPORT_SYMBOL_GPL(tps6586x_clr_bits);
170
171 int tps6586x_update(struct device *dev, int reg, uint8_t val, uint8_t mask)
172 {
173         struct tps6586x *tps6586x = dev_get_drvdata(dev);
174         uint8_t reg_val;
175         int ret = 0;
176
177         mutex_lock(&tps6586x->lock);
178
179         ret = __tps6586x_read(tps6586x->client, reg, &reg_val);
180         if (ret)
181                 goto out;
182
183         if ((reg_val & mask) != val) {
184                 reg_val = (reg_val & ~mask) | val;
185                 ret = __tps6586x_write(tps6586x->client, reg, reg_val);
186         }
187 out:
188         mutex_unlock(&tps6586x->lock);
189         return ret;
190 }
191 EXPORT_SYMBOL_GPL(tps6586x_update);
192
193 static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset)
194 {
195         struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio);
196         uint8_t val;
197         int ret;
198
199         ret = __tps6586x_read(tps6586x->client, TPS6586X_GPIOSET2, &val);
200         if (ret)
201                 return ret;
202
203         return !!(val & (1 << offset));
204 }
205
206
207 static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset,
208                               int value)
209 {
210         struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio);
211
212         __tps6586x_write(tps6586x->client, TPS6586X_GPIOSET2,
213                          value << offset);
214 }
215
216 static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset,
217                                 int value)
218 {
219         struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio);
220         uint8_t val, mask;
221
222         tps6586x_gpio_set(gc, offset, value);
223
224         val = 0x1 << (offset * 2);
225         mask = 0x3 << (offset * 2);
226
227         return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask);
228 }
229
230 static void tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base)
231 {
232         int ret;
233
234         if (!gpio_base)
235                 return;
236
237         tps6586x->gpio.owner            = THIS_MODULE;
238         tps6586x->gpio.label            = tps6586x->client->name;
239         tps6586x->gpio.dev              = tps6586x->dev;
240         tps6586x->gpio.base             = gpio_base;
241         tps6586x->gpio.ngpio            = 4;
242         tps6586x->gpio.can_sleep        = 1;
243
244         /* FIXME: add handling of GPIOs as dedicated inputs */
245         tps6586x->gpio.direction_output = tps6586x_gpio_output;
246         tps6586x->gpio.set              = tps6586x_gpio_set;
247         tps6586x->gpio.get              = tps6586x_gpio_get;
248
249         ret = gpiochip_add(&tps6586x->gpio);
250         if (ret)
251                 dev_warn(tps6586x->dev, "GPIO registration failed: %d\n", ret);
252 }
253
254 static int __remove_subdev(struct device *dev, void *unused)
255 {
256         platform_device_unregister(to_platform_device(dev));
257         return 0;
258 }
259
260 static int tps6586x_remove_subdevs(struct tps6586x *tps6586x)
261 {
262         return device_for_each_child(tps6586x->dev, NULL, __remove_subdev);
263 }
264
265 static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x,
266                                           struct tps6586x_platform_data *pdata)
267 {
268         struct tps6586x_subdev_info *subdev;
269         struct platform_device *pdev;
270         int i, ret = 0;
271
272         for (i = 0; i < pdata->num_subdevs; i++) {
273                 subdev = &pdata->subdevs[i];
274
275                 pdev = platform_device_alloc(subdev->name, subdev->id);
276
277                 pdev->dev.parent = tps6586x->dev;
278                 pdev->dev.platform_data = subdev->platform_data;
279
280                 ret = platform_device_add(pdev);
281                 if (ret)
282                         goto failed;
283         }
284         return 0;
285
286 failed:
287         tps6586x_remove_subdevs(tps6586x);
288         return ret;
289 }
290
291 static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
292                                         const struct i2c_device_id *id)
293 {
294         struct tps6586x_platform_data *pdata = client->dev.platform_data;
295         struct tps6586x *tps6586x;
296         int ret;
297
298         if (!pdata) {
299                 dev_err(&client->dev, "tps6586x requires platform data\n");
300                 return -ENOTSUPP;
301         }
302
303         ret = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC);
304         if (ret < 0) {
305                 dev_err(&client->dev, "Chip ID read failed: %d\n", ret);
306                 return -EIO;
307         }
308
309         if (ret != TPS658621A_VERSIONCRC) {
310                 dev_err(&client->dev, "Unsupported chip ID: %x\n", ret);
311                 return -ENODEV;
312         }
313
314         tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL);
315         if (tps6586x == NULL)
316                 return -ENOMEM;
317
318         tps6586x->client = client;
319         tps6586x->dev = &client->dev;
320         i2c_set_clientdata(client, tps6586x);
321
322         mutex_init(&tps6586x->lock);
323
324         ret = tps6586x_add_subdevs(tps6586x, pdata);
325         if (ret) {
326                 dev_err(&client->dev, "add devices failed: %d\n", ret);
327                 goto err_add_devs;
328         }
329
330         tps6586x_gpio_init(tps6586x, pdata->gpio_base);
331
332         return 0;
333
334 err_add_devs:
335         kfree(tps6586x);
336         return ret;
337 }
338
339 static int __devexit tps6586x_i2c_remove(struct i2c_client *client)
340 {
341         return 0;
342 }
343
344 static const struct i2c_device_id tps6586x_id_table[] = {
345         { "tps6586x", 0 },
346         { },
347 };
348 MODULE_DEVICE_TABLE(i2c, tps6586x_id_table);
349
350 static struct i2c_driver tps6586x_driver = {
351         .driver = {
352                 .name   = "tps6586x",
353                 .owner  = THIS_MODULE,
354         },
355         .probe          = tps6586x_i2c_probe,
356         .remove         = __devexit_p(tps6586x_i2c_remove),
357         .id_table       = tps6586x_id_table,
358 };
359
360 static int __init tps6586x_init(void)
361 {
362         return i2c_add_driver(&tps6586x_driver);
363 }
364 subsys_initcall(tps6586x_init);
365
366 static void __exit tps6586x_exit(void)
367 {
368         i2c_del_driver(&tps6586x_driver);
369 }
370 module_exit(tps6586x_exit);
371
372 MODULE_DESCRIPTION("TPS6586X core driver");
373 MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
374 MODULE_LICENSE("GPL");
375