mfd: Fix tps6586x_add_subdevs error path
[pandora-kernel.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                 if (!pdev) {
277                         ret = -ENOMEM;
278                         goto failed;
279                 }
280
281                 pdev->dev.parent = tps6586x->dev;
282                 pdev->dev.platform_data = subdev->platform_data;
283
284                 ret = platform_device_add(pdev);
285                 if (ret) {
286                         platform_device_put(pdev);
287                         goto failed;
288                 }
289         }
290         return 0;
291
292 failed:
293         tps6586x_remove_subdevs(tps6586x);
294         return ret;
295 }
296
297 static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
298                                         const struct i2c_device_id *id)
299 {
300         struct tps6586x_platform_data *pdata = client->dev.platform_data;
301         struct tps6586x *tps6586x;
302         int ret;
303
304         if (!pdata) {
305                 dev_err(&client->dev, "tps6586x requires platform data\n");
306                 return -ENOTSUPP;
307         }
308
309         ret = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC);
310         if (ret < 0) {
311                 dev_err(&client->dev, "Chip ID read failed: %d\n", ret);
312                 return -EIO;
313         }
314
315         if (ret != TPS658621A_VERSIONCRC) {
316                 dev_err(&client->dev, "Unsupported chip ID: %x\n", ret);
317                 return -ENODEV;
318         }
319
320         tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL);
321         if (tps6586x == NULL)
322                 return -ENOMEM;
323
324         tps6586x->client = client;
325         tps6586x->dev = &client->dev;
326         i2c_set_clientdata(client, tps6586x);
327
328         mutex_init(&tps6586x->lock);
329
330         ret = tps6586x_add_subdevs(tps6586x, pdata);
331         if (ret) {
332                 dev_err(&client->dev, "add devices failed: %d\n", ret);
333                 goto err_add_devs;
334         }
335
336         tps6586x_gpio_init(tps6586x, pdata->gpio_base);
337
338         return 0;
339
340 err_add_devs:
341         kfree(tps6586x);
342         return ret;
343 }
344
345 static int __devexit tps6586x_i2c_remove(struct i2c_client *client)
346 {
347         struct tps6586x *tps6586x = i2c_get_clientdata(client);
348         struct tps6586x_platform_data *pdata = client->dev.platform_data;
349         int ret;
350
351         if (pdata->gpio_base) {
352                 ret = gpiochip_remove(&tps6586x->gpio);
353                 if (ret)
354                         dev_err(&client->dev, "Can't remove gpio chip: %d\n",
355                                 ret);
356         }
357
358         tps6586x_remove_subdevs(tps6586x);
359         kfree(tps6586x);
360         return 0;
361 }
362
363 static const struct i2c_device_id tps6586x_id_table[] = {
364         { "tps6586x", 0 },
365         { },
366 };
367 MODULE_DEVICE_TABLE(i2c, tps6586x_id_table);
368
369 static struct i2c_driver tps6586x_driver = {
370         .driver = {
371                 .name   = "tps6586x",
372                 .owner  = THIS_MODULE,
373         },
374         .probe          = tps6586x_i2c_probe,
375         .remove         = __devexit_p(tps6586x_i2c_remove),
376         .id_table       = tps6586x_id_table,
377 };
378
379 static int __init tps6586x_init(void)
380 {
381         return i2c_add_driver(&tps6586x_driver);
382 }
383 subsys_initcall(tps6586x_init);
384
385 static void __exit tps6586x_exit(void)
386 {
387         i2c_del_driver(&tps6586x_driver);
388 }
389 module_exit(tps6586x_exit);
390
391 MODULE_DESCRIPTION("TPS6586X core driver");
392 MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
393 MODULE_LICENSE("GPL");
394