twl4030-madc: adjust for twl4030 -> twl api changes
[beagleboard-validation:linux.git] / drivers / mfd / twl4030-madc.c
1 /*
2  * TWL4030 MADC module driver
3  *
4  * Copyright (C) 2008 Nokia Corporation
5  * Mikko Ylinen <mikko.k.ylinen@nokia.com>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19  * 02110-1301 USA
20  *
21  */
22
23 #include <linux/init.h>
24 #include <linux/interrupt.h>
25 #include <linux/kernel.h>
26 #include <linux/types.h>
27 #include <linux/module.h>
28 #include <linux/delay.h>
29 #include <linux/fs.h>
30 #include <linux/platform_device.h>
31 #include <linux/miscdevice.h>
32 #include <linux/i2c/twl.h>
33 #include <linux/i2c/twl4030-madc.h>
34
35 #include <asm/uaccess.h>
36
37 #define TWL4030_MADC_PFX        "twl4030-madc: "
38
39 struct twl4030_madc_data {
40         struct device           *dev;
41         struct mutex            lock;
42         struct work_struct      ws;
43         struct twl4030_madc_request     requests[TWL4030_MADC_NUM_METHODS];
44         int imr;
45         int isr;
46 };
47
48 static struct twl4030_madc_data *the_madc;
49
50 static
51 const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = {
52         [TWL4030_MADC_RT] = {
53                 .sel    = TWL4030_MADC_RTSELECT_LSB,
54                 .avg    = TWL4030_MADC_RTAVERAGE_LSB,
55                 .rbase  = TWL4030_MADC_RTCH0_LSB,
56         },
57         [TWL4030_MADC_SW1] = {
58                 .sel    = TWL4030_MADC_SW1SELECT_LSB,
59                 .avg    = TWL4030_MADC_SW1AVERAGE_LSB,
60                 .rbase  = TWL4030_MADC_GPCH0_LSB,
61                 .ctrl   = TWL4030_MADC_CTRL_SW1,
62         },
63         [TWL4030_MADC_SW2] = {
64                 .sel    = TWL4030_MADC_SW2SELECT_LSB,
65                 .avg    = TWL4030_MADC_SW2AVERAGE_LSB,
66                 .rbase  = TWL4030_MADC_GPCH0_LSB,
67                 .ctrl   = TWL4030_MADC_CTRL_SW2,
68         },
69 };
70
71 static int twl4030_madc_read(struct twl4030_madc_data *madc, u8 reg)
72 {
73         int ret;
74         u8 val;
75
76         ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, reg);
77         if (ret) {
78                 dev_dbg(madc->dev, "unable to read register 0x%X\n", reg);
79                 return ret;
80         }
81
82         return val;
83 }
84
85 static void twl4030_madc_write(struct twl4030_madc_data *madc, u8 reg, u8 val)
86 {
87         int ret;
88
89         ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, reg);
90         if (ret)
91                 dev_err(madc->dev, "unable to write register 0x%X\n", reg);
92 }
93
94 static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 reg)
95 {
96         u8 msb, lsb;
97
98         /* For each ADC channel, we have MSB and LSB register pair. MSB address
99          * is always LSB address+1. reg parameter is the addr of LSB register */
100         msb = twl4030_madc_read(madc, reg + 1);
101         lsb = twl4030_madc_read(madc, reg);
102
103         return (int)(((msb << 8) | lsb) >> 6);
104 }
105
106 static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
107                 u8 reg_base, u16 channels, int *buf)
108 {
109         int count = 0;
110         u8 reg, i;
111
112         if (unlikely(!buf))
113                 return 0;
114
115         for (i = 0; i < TWL4030_MADC_MAX_CHANNELS; i++) {
116                 if (channels & (1<<i)) {
117                         reg = reg_base + 2*i;
118                         buf[i] = twl4030_madc_channel_raw_read(madc, reg);
119                         count++;
120                 }
121         }
122         return count;
123 }
124
125 static void twl4030_madc_enable_irq(struct twl4030_madc_data *madc, int id)
126 {
127         u8 val;
128
129         val = twl4030_madc_read(madc, madc->imr);
130         val &= ~(1 << id);
131         twl4030_madc_write(madc, madc->imr, val);
132 }
133
134 static void twl4030_madc_disable_irq(struct twl4030_madc_data *madc, int id)
135 {
136         u8 val;
137
138         val = twl4030_madc_read(madc, madc->imr);
139         val |= (1 << id);
140         twl4030_madc_write(madc, madc->imr, val);
141 }
142
143 static irqreturn_t twl4030_madc_irq_handler(int irq, void *_madc)
144 {
145         struct twl4030_madc_data *madc = _madc;
146         u8 isr_val, imr_val;
147         int i;
148
149 #ifdef CONFIG_LOCKDEP
150         /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
151          * we don't want and can't tolerate.  Although it might be
152          * friendlier not to borrow this thread context...
153          */
154         local_irq_enable();
155 #endif
156
157         /* Use COR to ack interrupts since we have no shared IRQs in ISRx */
158         isr_val = twl4030_madc_read(madc, madc->isr);
159         imr_val = twl4030_madc_read(madc, madc->imr);
160
161         isr_val &= ~imr_val;
162
163         for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
164
165                 if (!(isr_val & (1<<i)))
166                         continue;
167
168                 twl4030_madc_disable_irq(madc, i);
169                 madc->requests[i].result_pending = 1;
170         }
171
172         schedule_work(&madc->ws);
173
174         return IRQ_HANDLED;
175 }
176
177 static void twl4030_madc_work(struct work_struct *ws)
178 {
179         const struct twl4030_madc_conversion_method *method;
180         struct twl4030_madc_data *madc;
181         struct twl4030_madc_request *r;
182         int len, i;
183
184         madc = container_of(ws, struct twl4030_madc_data, ws);
185         mutex_lock(&madc->lock);
186
187         for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
188
189                 r = &madc->requests[i];
190
191                 /* No pending results for this method, move to next one */
192                 if (!r->result_pending)
193                         continue;
194
195                 method = &twl4030_conversion_methods[r->method];
196
197                 /* Read results */
198                 len = twl4030_madc_read_channels(madc, method->rbase,
199                                                  r->channels, r->rbuf);
200
201                 /* Return results to caller */
202                 if (r->func_cb != NULL) {
203                         r->func_cb(len, r->channels, r->rbuf);
204                         r->func_cb = NULL;
205                 }
206
207                 /* Free request */
208                 r->result_pending = 0;
209                 r->active         = 0;
210         }
211
212         mutex_unlock(&madc->lock);
213 }
214
215 static int twl4030_madc_set_irq(struct twl4030_madc_data *madc,
216                 struct twl4030_madc_request *req)
217 {
218         struct twl4030_madc_request *p;
219
220         p = &madc->requests[req->method];
221
222         memcpy(p, req, sizeof *req);
223
224         twl4030_madc_enable_irq(madc, req->method);
225
226         return 0;
227 }
228
229 static inline void twl4030_madc_start_conversion(struct twl4030_madc_data *madc,
230                 int conv_method)
231 {
232         const struct twl4030_madc_conversion_method *method;
233
234         method = &twl4030_conversion_methods[conv_method];
235
236         switch (conv_method) {
237         case TWL4030_MADC_SW1:
238         case TWL4030_MADC_SW2:
239                 twl4030_madc_write(madc, method->ctrl, TWL4030_MADC_SW_START);
240                 break;
241         case TWL4030_MADC_RT:
242         default:
243                 break;
244         }
245 }
246
247 static int twl4030_madc_wait_conversion_ready(
248                 struct twl4030_madc_data *madc,
249                 unsigned int timeout_ms, u8 status_reg)
250 {
251         unsigned long timeout;
252
253         timeout = jiffies + msecs_to_jiffies(timeout_ms);
254         do {
255                 u8 reg;
256
257                 reg = twl4030_madc_read(madc, status_reg);
258                 if (!(reg & TWL4030_MADC_BUSY) && (reg & TWL4030_MADC_EOC_SW))
259                         return 0;
260         } while (!time_after(jiffies, timeout));
261
262         return -EAGAIN;
263 }
264
265 int twl4030_madc_conversion(struct twl4030_madc_request *req)
266 {
267         const struct twl4030_madc_conversion_method *method;
268         u8 ch_msb, ch_lsb;
269         int ret;
270
271         if (unlikely(!req))
272                 return -EINVAL;
273
274         mutex_lock(&the_madc->lock);
275
276         /* Do we have a conversion request ongoing */
277         if (the_madc->requests[req->method].active) {
278                 ret = -EBUSY;
279                 goto out;
280         }
281
282         ch_msb = (req->channels >> 8) & 0xff;
283         ch_lsb = req->channels & 0xff;
284
285         method = &twl4030_conversion_methods[req->method];
286
287         /* Select channels to be converted */
288         twl4030_madc_write(the_madc, method->sel + 1, ch_msb);
289         twl4030_madc_write(the_madc, method->sel, ch_lsb);
290
291         /* Select averaging for all channels if do_avg is set */
292         if (req->do_avg) {
293                 twl4030_madc_write(the_madc, method->avg + 1, ch_msb);
294                 twl4030_madc_write(the_madc, method->avg, ch_lsb);
295         }
296
297         if ((req->type == TWL4030_MADC_IRQ_ONESHOT) && (req->func_cb != NULL)) {
298                 twl4030_madc_set_irq(the_madc, req);
299                 twl4030_madc_start_conversion(the_madc, req->method);
300                 the_madc->requests[req->method].active = 1;
301                 ret = 0;
302                 goto out;
303         }
304
305         /* With RT method we should not be here anymore */
306         if (req->method == TWL4030_MADC_RT) {
307                 ret = -EINVAL;
308                 goto out;
309         }
310
311         twl4030_madc_start_conversion(the_madc, req->method);
312         the_madc->requests[req->method].active = 1;
313
314         /* Wait until conversion is ready (ctrl register returns EOC) */
315         ret = twl4030_madc_wait_conversion_ready(the_madc, 5, method->ctrl);
316         if (ret) {
317                 dev_dbg(the_madc->dev, "conversion timeout!\n");
318                 the_madc->requests[req->method].active = 0;
319                 goto out;
320         }
321
322         ret = twl4030_madc_read_channels(the_madc, method->rbase, req->channels,
323                                          req->rbuf);
324
325         the_madc->requests[req->method].active = 0;
326
327 out:
328         mutex_unlock(&the_madc->lock);
329
330         return ret;
331 }
332 EXPORT_SYMBOL(twl4030_madc_conversion);
333
334 static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
335                 int chan, int on)
336 {
337         int ret;
338         u8 regval;
339
340         /* Current generator is only available for ADCIN0 and ADCIN1. NB:
341          * ADCIN1 current generator only works when AC or VBUS is present */
342         if (chan > 1)
343                 return EINVAL;
344
345         ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
346                                   &regval, TWL4030_BCI_BCICTL1);
347         if (on)
348                 regval |= (chan) ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN;
349         else
350                 regval &= (chan) ? ~TWL4030_BCI_ITHEN : ~TWL4030_BCI_TYPEN;
351         ret = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
352                                    regval, TWL4030_BCI_BCICTL1);
353
354         return ret;
355 }
356
357 static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
358 {
359         u8 regval;
360
361         regval = twl4030_madc_read(madc, TWL4030_MADC_CTRL1);
362         if (on)
363                 regval |= TWL4030_MADC_MADCON;
364         else
365                 regval &= ~TWL4030_MADC_MADCON;
366         twl4030_madc_write(madc, TWL4030_MADC_CTRL1, regval);
367
368         return 0;
369 }
370
371 static long twl4030_madc_ioctl(struct file *filp, unsigned int cmd,
372                                unsigned long arg)
373 {
374         struct twl4030_madc_user_parms par;
375         int val, ret;
376
377         ret = copy_from_user(&par, (void __user *) arg, sizeof(par));
378         if (ret) {
379                 dev_dbg(the_madc->dev, "copy_from_user: %d\n", ret);
380                 return -EACCES;
381         }
382
383         switch (cmd) {
384         case TWL4030_MADC_IOCX_ADC_RAW_READ: {
385                 struct twl4030_madc_request req;
386                 if (par.channel >= TWL4030_MADC_MAX_CHANNELS)
387                         return -EINVAL;
388
389                 req.channels = (1 << par.channel);
390                 req.do_avg      = par.average;
391                 req.method      = TWL4030_MADC_SW1;
392                 req.func_cb     = NULL;
393
394                 val = twl4030_madc_conversion(&req);
395                 if (val <= 0) {
396                         par.status = -1;
397                 } else {
398                         par.status = 0;
399                         par.result = (u16)req.rbuf[par.channel];
400                 }
401                 break;
402                                              }
403         default:
404                 return -EINVAL;
405         }
406
407         ret = copy_to_user((void __user *) arg, &par, sizeof(par));
408         if (ret) {
409                 dev_dbg(the_madc->dev, "copy_to_user: %d\n", ret);
410                 return -EACCES;
411         }
412
413         return 0;
414 }
415
416 static struct file_operations twl4030_madc_fileops = {
417         .owner = THIS_MODULE,
418         .unlocked_ioctl = twl4030_madc_ioctl
419 };
420
421 static struct miscdevice twl4030_madc_device = {
422         .minor = MISC_DYNAMIC_MINOR,
423         .name = "twl4030-madc",
424         .fops = &twl4030_madc_fileops
425 };
426
427 static int __init twl4030_madc_probe(struct platform_device *pdev)
428 {
429         struct twl4030_madc_data *madc;
430         struct twl4030_madc_platform_data *pdata = pdev->dev.platform_data;
431         int ret;
432         u8 regval;
433
434         madc = kzalloc(sizeof *madc, GFP_KERNEL);
435         if (!madc)
436                 return -ENOMEM;
437
438         if (!pdata) {
439                 dev_dbg(&pdev->dev, "platform_data not available\n");
440                 ret = -EINVAL;
441                 goto err_pdata;
442         }
443
444         madc->imr = (pdata->irq_line == 1) ? TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2;
445         madc->isr = (pdata->irq_line == 1) ? TWL4030_MADC_ISR1 : TWL4030_MADC_ISR2;
446
447         ret = misc_register(&twl4030_madc_device);
448         if (ret) {
449                 dev_dbg(&pdev->dev, "could not register misc_device\n");
450                 goto err_misc;
451         }
452         twl4030_madc_set_power(madc, 1);
453         twl4030_madc_set_current_generator(madc, 0, 1);
454
455         /* Enable ADCIN3 through 6 */
456         ret = twl_i2c_read_u8(TWL4030_MODULE_USB,
457                                   &regval, TWL4030_USB_CARKIT_ANA_CTRL);
458
459         regval |= TWL4030_USB_SEL_MADC_MCPC;
460
461         ret = twl_i2c_write_u8(TWL4030_MODULE_USB,
462                                 regval, TWL4030_USB_CARKIT_ANA_CTRL);
463
464
465         ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
466                                   &regval, TWL4030_BCI_BCICTL1);
467
468         regval |= TWL4030_BCI_MESBAT;
469
470         ret = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
471                                    regval, TWL4030_BCI_BCICTL1);
472
473         ret = request_irq(platform_get_irq(pdev, 0), twl4030_madc_irq_handler,
474                           0, "twl4030_madc", madc);
475         if (ret) {
476                 dev_dbg(&pdev->dev, "could not request irq\n");
477                 goto err_irq;
478         }
479
480         platform_set_drvdata(pdev, madc);
481         mutex_init(&madc->lock);
482         INIT_WORK(&madc->ws, twl4030_madc_work);
483
484         the_madc = madc;
485
486         return 0;
487
488 err_irq:
489         misc_deregister(&twl4030_madc_device);
490
491 err_misc:
492 err_pdata:
493         kfree(madc);
494
495         return ret;
496 }
497
498 static int __exit twl4030_madc_remove(struct platform_device *pdev)
499 {
500         struct twl4030_madc_data *madc = platform_get_drvdata(pdev);
501
502         twl4030_madc_set_power(madc, 0);
503         twl4030_madc_set_current_generator(madc, 0, 0);
504         free_irq(platform_get_irq(pdev, 0), madc);
505         cancel_work_sync(&madc->ws);
506         misc_deregister(&twl4030_madc_device);
507
508         return 0;
509 }
510
511 static struct platform_driver twl4030_madc_driver = {
512         .probe          = twl4030_madc_probe,
513         .remove         = __exit_p(twl4030_madc_remove),
514         .driver         = {
515                 .name   = "twl4030_madc",
516                 .owner  = THIS_MODULE,
517         },
518 };
519
520 static int __init twl4030_madc_init(void)
521 {
522         return platform_driver_register(&twl4030_madc_driver);
523 }
524 module_init(twl4030_madc_init);
525
526 static void __exit twl4030_madc_exit(void)
527 {
528         platform_driver_unregister(&twl4030_madc_driver);
529 }
530 module_exit(twl4030_madc_exit);
531
532 MODULE_ALIAS("platform:twl4030-madc");
533 MODULE_AUTHOR("Nokia Corporation");
534 MODULE_DESCRIPTION("twl4030 ADC driver");
535 MODULE_LICENSE("GPL");
536