2 * drivers/i2c/chips/twl4030-madc.c
4 * TWL4030 MADC module driver
6 * Copyright (C) 2008 Nokia Corporation
7 * Mikko Ylinen <mikko.k.ylinen@nokia.com>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25 #include <linux/init.h>
26 #include <linux/interrupt.h>
27 #include <linux/kernel.h>
28 #include <linux/types.h>
29 #include <linux/module.h>
30 #include <linux/delay.h>
32 #include <linux/platform_device.h>
33 #include <linux/miscdevice.h>
34 #include <linux/i2c/twl4030.h>
35 #include <linux/i2c/twl4030-madc.h>
37 #include <asm/uaccess.h>
39 #define TWL4030_MADC_PFX "twl4030-madc: "
41 struct twl4030_madc_data {
44 struct work_struct ws;
45 struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
50 static struct twl4030_madc_data *the_madc;
53 const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = {
55 .sel = TWL4030_MADC_RTSELECT_LSB,
56 .avg = TWL4030_MADC_RTAVERAGE_LSB,
57 .rbase = TWL4030_MADC_RTCH0_LSB,
59 [TWL4030_MADC_SW1] = {
60 .sel = TWL4030_MADC_SW1SELECT_LSB,
61 .avg = TWL4030_MADC_SW1AVERAGE_LSB,
62 .rbase = TWL4030_MADC_GPCH0_LSB,
63 .ctrl = TWL4030_MADC_CTRL_SW1,
65 [TWL4030_MADC_SW2] = {
66 .sel = TWL4030_MADC_SW2SELECT_LSB,
67 .avg = TWL4030_MADC_SW2AVERAGE_LSB,
68 .rbase = TWL4030_MADC_GPCH0_LSB,
69 .ctrl = TWL4030_MADC_CTRL_SW2,
73 static int twl4030_madc_read(struct twl4030_madc_data *madc, u8 reg)
78 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MADC, &val, reg);
80 dev_dbg(madc->dev, "unable to read register 0x%X\n", reg);
87 static void twl4030_madc_write(struct twl4030_madc_data *madc, u8 reg, u8 val)
91 ret = twl4030_i2c_write_u8(TWL4030_MODULE_MADC, val, reg);
93 dev_err(madc->dev, "unable to write register 0x%X\n", reg);
96 static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 reg)
100 /* For each ADC channel, we have MSB and LSB register pair. MSB address
101 * is always LSB address+1. reg parameter is the addr of LSB register */
102 msb = twl4030_madc_read(madc, reg + 1);
103 lsb = twl4030_madc_read(madc, reg);
105 return (int)(((msb << 8) | lsb) >> 6);
108 static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
109 u8 reg_base, u16 channels, int *buf)
117 for (i = 0; i < TWL4030_MADC_MAX_CHANNELS; i++) {
118 if (channels & (1<<i)) {
119 reg = reg_base + 2*i;
120 buf[i] = twl4030_madc_channel_raw_read(madc, reg);
127 static void twl4030_madc_enable_irq(struct twl4030_madc_data *madc, int id)
131 val = twl4030_madc_read(madc, madc->imr);
133 twl4030_madc_write(madc, madc->imr, val);
136 static void twl4030_madc_disable_irq(struct twl4030_madc_data *madc, int id)
140 val = twl4030_madc_read(madc, madc->imr);
142 twl4030_madc_write(madc, madc->imr, val);
145 static irqreturn_t twl4030_madc_irq_handler(int irq, void *_madc)
147 struct twl4030_madc_data *madc = _madc;
151 #ifdef CONFIG_LOCKDEP
152 /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
153 * we don't want and can't tolerate. Although it might be
154 * friendlier not to borrow this thread context...
159 /* Use COR to ack interrupts since we have no shared IRQs in ISRx */
160 isr_val = twl4030_madc_read(madc, madc->isr);
161 imr_val = twl4030_madc_read(madc, madc->imr);
165 for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
167 if (!(isr_val & (1<<i)))
170 twl4030_madc_disable_irq(madc, i);
171 madc->requests[i].result_pending = 1;
174 schedule_work(&madc->ws);
179 static void twl4030_madc_work(struct work_struct *ws)
181 const struct twl4030_madc_conversion_method *method;
182 struct twl4030_madc_data *madc;
183 struct twl4030_madc_request *r;
186 madc = container_of(ws, struct twl4030_madc_data, ws);
187 mutex_lock(&madc->lock);
189 for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
191 r = &madc->requests[i];
193 /* No pending results for this method, move to next one */
194 if (!r->result_pending)
197 method = &twl4030_conversion_methods[r->method];
200 len = twl4030_madc_read_channels(madc, method->rbase,
201 r->channels, r->rbuf);
203 /* Return results to caller */
204 if (r->func_cb != NULL) {
205 r->func_cb(len, r->channels, r->rbuf);
210 r->result_pending = 0;
214 mutex_unlock(&madc->lock);
217 static int twl4030_madc_set_irq(struct twl4030_madc_data *madc,
218 struct twl4030_madc_request *req)
220 struct twl4030_madc_request *p;
222 p = &madc->requests[req->method];
224 memcpy(p, req, sizeof *req);
226 twl4030_madc_enable_irq(madc, req->method);
231 static inline void twl4030_madc_start_conversion(struct twl4030_madc_data *madc,
234 const struct twl4030_madc_conversion_method *method;
236 method = &twl4030_conversion_methods[conv_method];
238 switch (conv_method) {
239 case TWL4030_MADC_SW1:
240 case TWL4030_MADC_SW2:
241 twl4030_madc_write(madc, method->ctrl, TWL4030_MADC_SW_START);
243 case TWL4030_MADC_RT:
249 static int twl4030_madc_wait_conversion_ready(
250 struct twl4030_madc_data *madc,
251 unsigned int timeout_ms, u8 status_reg)
253 unsigned long timeout;
255 timeout = jiffies + msecs_to_jiffies(timeout_ms);
259 reg = twl4030_madc_read(madc, status_reg);
260 if (!(reg & TWL4030_MADC_BUSY) && (reg & TWL4030_MADC_EOC_SW))
262 } while (!time_after(jiffies, timeout));
267 int twl4030_madc_conversion(struct twl4030_madc_request *req)
269 const struct twl4030_madc_conversion_method *method;
276 mutex_lock(&the_madc->lock);
278 /* Do we have a conversion request ongoing */
279 if (the_madc->requests[req->method].active) {
284 ch_msb = (req->channels >> 8) & 0xff;
285 ch_lsb = req->channels & 0xff;
287 method = &twl4030_conversion_methods[req->method];
289 /* Select channels to be converted */
290 twl4030_madc_write(the_madc, method->sel + 1, ch_msb);
291 twl4030_madc_write(the_madc, method->sel, ch_lsb);
293 /* Select averaging for all channels if do_avg is set */
295 twl4030_madc_write(the_madc, method->avg + 1, ch_msb);
296 twl4030_madc_write(the_madc, method->avg, ch_lsb);
299 if ((req->type == TWL4030_MADC_IRQ_ONESHOT) && (req->func_cb != NULL)) {
300 twl4030_madc_set_irq(the_madc, req);
301 twl4030_madc_start_conversion(the_madc, req->method);
302 the_madc->requests[req->method].active = 1;
307 /* With RT method we should not be here anymore */
308 if (req->method == TWL4030_MADC_RT) {
313 twl4030_madc_start_conversion(the_madc, req->method);
314 the_madc->requests[req->method].active = 1;
316 /* Wait until conversion is ready (ctrl register returns EOC) */
317 ret = twl4030_madc_wait_conversion_ready(the_madc, 5, method->ctrl);
319 dev_dbg(the_madc->dev, "conversion timeout!\n");
320 the_madc->requests[req->method].active = 0;
324 ret = twl4030_madc_read_channels(the_madc, method->rbase, req->channels,
327 the_madc->requests[req->method].active = 0;
330 mutex_unlock(&the_madc->lock);
334 EXPORT_SYMBOL(twl4030_madc_conversion);
336 static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
342 /* Current generator is only available for ADCIN0 and ADCIN1. NB:
343 * ADCIN1 current generator only works when AC or VBUS is present */
347 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
348 ®val, TWL4030_BCI_BCICTL1);
350 regval |= (chan) ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN;
352 regval &= (chan) ? ~TWL4030_BCI_ITHEN : ~TWL4030_BCI_TYPEN;
353 ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
354 regval, TWL4030_BCI_BCICTL1);
359 static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
363 regval = twl4030_madc_read(madc, TWL4030_MADC_CTRL1);
365 regval |= TWL4030_MADC_MADCON;
367 regval &= ~TWL4030_MADC_MADCON;
368 twl4030_madc_write(madc, TWL4030_MADC_CTRL1, regval);
373 static long twl4030_madc_ioctl(struct file *filp, unsigned int cmd,
376 struct twl4030_madc_user_parms par;
379 ret = copy_from_user(&par, (void __user *) arg, sizeof(par));
381 dev_dbg(the_madc->dev, "copy_from_user: %d\n", ret);
386 case TWL4030_MADC_IOCX_ADC_RAW_READ: {
387 struct twl4030_madc_request req;
388 if (par.channel >= TWL4030_MADC_MAX_CHANNELS)
391 req.channels = (1 << par.channel);
392 req.do_avg = par.average;
393 req.method = TWL4030_MADC_SW1;
396 val = twl4030_madc_conversion(&req);
401 par.result = (u16)req.rbuf[par.channel];
409 ret = copy_to_user((void __user *) arg, &par, sizeof(par));
411 dev_dbg(the_madc->dev, "copy_to_user: %d\n", ret);
418 static struct file_operations twl4030_madc_fileops = {
419 .owner = THIS_MODULE,
420 .unlocked_ioctl = twl4030_madc_ioctl
423 static struct miscdevice twl4030_madc_device = {
424 .minor = MISC_DYNAMIC_MINOR,
425 .name = "twl4030-madc",
426 .fops = &twl4030_madc_fileops
429 static int __init twl4030_madc_probe(struct platform_device *pdev)
431 struct twl4030_madc_data *madc;
432 struct twl4030_madc_platform_data *pdata = pdev->dev.platform_data;
436 madc = kzalloc(sizeof *madc, GFP_KERNEL);
441 dev_dbg(&pdev->dev, "platform_data not available\n");
446 madc->imr = (pdata->irq_line == 1) ? TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2;
447 madc->isr = (pdata->irq_line == 1) ? TWL4030_MADC_ISR1 : TWL4030_MADC_ISR2;
449 ret = misc_register(&twl4030_madc_device);
451 dev_dbg(&pdev->dev, "could not register misc_device\n");
454 twl4030_madc_set_power(madc, 1);
455 twl4030_madc_set_current_generator(madc, 0, 1);
457 ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
458 ®val, TWL4030_BCI_BCICTL1);
460 regval |= TWL4030_BCI_MESBAT;
462 ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
463 regval, TWL4030_BCI_BCICTL1);
465 ret = request_irq(platform_get_irq(pdev, 0), twl4030_madc_irq_handler,
466 0, "twl4030_madc", madc);
468 dev_dbg(&pdev->dev, "could not request irq\n");
472 platform_set_drvdata(pdev, madc);
473 mutex_init(&madc->lock);
474 INIT_WORK(&madc->ws, twl4030_madc_work);
481 misc_deregister(&twl4030_madc_device);
490 static int __exit twl4030_madc_remove(struct platform_device *pdev)
492 struct twl4030_madc_data *madc = platform_get_drvdata(pdev);
494 twl4030_madc_set_power(madc, 0);
495 twl4030_madc_set_current_generator(madc, 0, 0);
496 free_irq(platform_get_irq(pdev, 0), madc);
497 cancel_work_sync(&madc->ws);
498 misc_deregister(&twl4030_madc_device);
503 static struct platform_driver twl4030_madc_driver = {
504 .probe = twl4030_madc_probe,
505 .remove = __exit_p(twl4030_madc_remove),
507 .name = "twl4030_madc",
508 .owner = THIS_MODULE,
512 static int __init twl4030_madc_init(void)
514 return platform_driver_register(&twl4030_madc_driver);
516 module_init(twl4030_madc_init);
518 static void __exit twl4030_madc_exit(void)
520 platform_driver_unregister(&twl4030_madc_driver);
522 module_exit(twl4030_madc_exit);
524 MODULE_ALIAS("platform:twl4030-madc");
525 MODULE_AUTHOR("Nokia Corporation");
526 MODULE_DESCRIPTION("twl4030 ADC driver");
527 MODULE_LICENSE("GPL");