x86, mrst: use a temporary variable for SFI irq
[linux-btrfs-devel.git] / drivers / mfd / twl4030-madc.c
blob7cbf2aa9e64f2fb744dbf717ce90057e08a8eaf2
1 /*
3 * TWL4030 MADC module driver-This driver monitors the real time
4 * conversion of analog signals like battery temperature,
5 * battery type, battery level etc.
7 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
8 * J Keerthy <j-keerthy@ti.com>
10 * Based on twl4030-madc.c
11 * Copyright (C) 2008 Nokia Corporation
12 * Mikko Ylinen <mikko.k.ylinen@nokia.com>
14 * Amit Kucheria <amit.kucheria@canonical.com>
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * version 2 as published by the Free Software Foundation.
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
28 * 02110-1301 USA
32 #include <linux/init.h>
33 #include <linux/device.h>
34 #include <linux/interrupt.h>
35 #include <linux/kernel.h>
36 #include <linux/delay.h>
37 #include <linux/platform_device.h>
38 #include <linux/slab.h>
39 #include <linux/i2c/twl.h>
40 #include <linux/i2c/twl4030-madc.h>
41 #include <linux/module.h>
42 #include <linux/stddef.h>
43 #include <linux/mutex.h>
44 #include <linux/bitops.h>
45 #include <linux/jiffies.h>
46 #include <linux/types.h>
47 #include <linux/gfp.h>
48 #include <linux/err.h>
51 * struct twl4030_madc_data - a container for madc info
52 * @dev - pointer to device structure for madc
53 * @lock - mutex protecting this data structure
54 * @requests - Array of request struct corresponding to SW1, SW2 and RT
55 * @imr - Interrupt mask register of MADC
56 * @isr - Interrupt status register of MADC
58 struct twl4030_madc_data {
59 struct device *dev;
60 struct mutex lock; /* mutex protecting this data structure */
61 struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
62 int imr;
63 int isr;
66 static struct twl4030_madc_data *twl4030_madc;
68 struct twl4030_prescale_divider_ratios {
69 s16 numerator;
70 s16 denominator;
73 static const struct twl4030_prescale_divider_ratios
74 twl4030_divider_ratios[16] = {
75 {1, 1}, /* CHANNEL 0 No Prescaler */
76 {1, 1}, /* CHANNEL 1 No Prescaler */
77 {6, 10}, /* CHANNEL 2 */
78 {6, 10}, /* CHANNEL 3 */
79 {6, 10}, /* CHANNEL 4 */
80 {6, 10}, /* CHANNEL 5 */
81 {6, 10}, /* CHANNEL 6 */
82 {6, 10}, /* CHANNEL 7 */
83 {3, 14}, /* CHANNEL 8 */
84 {1, 3}, /* CHANNEL 9 */
85 {1, 1}, /* CHANNEL 10 No Prescaler */
86 {15, 100}, /* CHANNEL 11 */
87 {1, 4}, /* CHANNEL 12 */
88 {1, 1}, /* CHANNEL 13 Reserved channels */
89 {1, 1}, /* CHANNEL 14 Reseved channels */
90 {5, 11}, /* CHANNEL 15 */
95 * Conversion table from -3 to 55 degree Celcius
97 static int therm_tbl[] = {
98 30800, 29500, 28300, 27100,
99 26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900,
100 17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100,
101 11600, 11200, 10800, 10400, 10000, 9630, 9280, 8950, 8620, 8310,
102 8020, 7730, 7460, 7200, 6950, 6710, 6470, 6250, 6040, 5830,
103 5640, 5450, 5260, 5090, 4920, 4760, 4600, 4450, 4310, 4170,
104 4040, 3910, 3790, 3670, 3550
108 * Structure containing the registers
109 * of different conversion methods supported by MADC.
110 * Hardware or RT real time conversion request initiated by external host
111 * processor for RT Signal conversions.
112 * External host processors can also request for non RT conversions
113 * SW1 and SW2 software conversions also called asynchronous or GPC request.
115 static
116 const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = {
117 [TWL4030_MADC_RT] = {
118 .sel = TWL4030_MADC_RTSELECT_LSB,
119 .avg = TWL4030_MADC_RTAVERAGE_LSB,
120 .rbase = TWL4030_MADC_RTCH0_LSB,
122 [TWL4030_MADC_SW1] = {
123 .sel = TWL4030_MADC_SW1SELECT_LSB,
124 .avg = TWL4030_MADC_SW1AVERAGE_LSB,
125 .rbase = TWL4030_MADC_GPCH0_LSB,
126 .ctrl = TWL4030_MADC_CTRL_SW1,
128 [TWL4030_MADC_SW2] = {
129 .sel = TWL4030_MADC_SW2SELECT_LSB,
130 .avg = TWL4030_MADC_SW2AVERAGE_LSB,
131 .rbase = TWL4030_MADC_GPCH0_LSB,
132 .ctrl = TWL4030_MADC_CTRL_SW2,
137 * Function to read a particular channel value.
138 * @madc - pointer to struct twl4030_madc_data
139 * @reg - lsb of ADC Channel
140 * If the i2c read fails it returns an error else returns 0.
142 static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 reg)
144 u8 msb, lsb;
145 int ret;
147 * For each ADC channel, we have MSB and LSB register pair. MSB address
148 * is always LSB address+1. reg parameter is the address of LSB register
150 ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &msb, reg + 1);
151 if (ret) {
152 dev_err(madc->dev, "unable to read MSB register 0x%X\n",
153 reg + 1);
154 return ret;
156 ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &lsb, reg);
157 if (ret) {
158 dev_err(madc->dev, "unable to read LSB register 0x%X\n", reg);
159 return ret;
162 return (int)(((msb << 8) | lsb) >> 6);
166 * Return battery temperature
167 * Or < 0 on failure.
169 static int twl4030battery_temperature(int raw_volt)
171 u8 val;
172 int temp, curr, volt, res, ret;
174 volt = (raw_volt * TEMP_STEP_SIZE) / TEMP_PSR_R;
175 /* Getting and calculating the supply current in micro ampers */
176 ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
177 REG_BCICTL2);
178 if (ret < 0)
179 return ret;
180 curr = ((val & TWL4030_BCI_ITHEN) + 1) * 10;
181 /* Getting and calculating the thermistor resistance in ohms */
182 res = volt * 1000 / curr;
183 /* calculating temperature */
184 for (temp = 58; temp >= 0; temp--) {
185 int actual = therm_tbl[temp];
187 if ((actual - res) >= 0)
188 break;
191 return temp + 1;
194 static int twl4030battery_current(int raw_volt)
196 int ret;
197 u8 val;
199 ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
200 TWL4030_BCI_BCICTL1);
201 if (ret)
202 return ret;
203 if (val & TWL4030_BCI_CGAIN) /* slope of 0.44 mV/mA */
204 return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R1;
205 else /* slope of 0.88 mV/mA */
206 return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R2;
209 * Function to read channel values
210 * @madc - pointer to twl4030_madc_data struct
211 * @reg_base - Base address of the first channel
212 * @Channels - 16 bit bitmap. If the bit is set, channel value is read
213 * @buf - The channel values are stored here. if read fails error
214 * value is stored
215 * Returns the number of successfully read channels.
217 static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
218 u8 reg_base, unsigned
219 long channels, int *buf)
221 int count = 0, count_req = 0, i;
222 u8 reg;
224 for_each_set_bit(i, &channels, TWL4030_MADC_MAX_CHANNELS) {
225 reg = reg_base + 2 * i;
226 buf[i] = twl4030_madc_channel_raw_read(madc, reg);
227 if (buf[i] < 0) {
228 dev_err(madc->dev,
229 "Unable to read register 0x%X\n", reg);
230 count_req++;
231 continue;
233 switch (i) {
234 case 10:
235 buf[i] = twl4030battery_current(buf[i]);
236 if (buf[i] < 0) {
237 dev_err(madc->dev, "err reading current\n");
238 count_req++;
239 } else {
240 count++;
241 buf[i] = buf[i] - 750;
243 break;
244 case 1:
245 buf[i] = twl4030battery_temperature(buf[i]);
246 if (buf[i] < 0) {
247 dev_err(madc->dev, "err reading temperature\n");
248 count_req++;
249 } else {
250 buf[i] -= 3;
251 count++;
253 break;
254 default:
255 count++;
256 /* Analog Input (V) = conv_result * step_size / R
257 * conv_result = decimal value of 10-bit conversion
258 * result
259 * step size = 1.5 / (2 ^ 10 -1)
260 * R = Prescaler ratio for input channels.
261 * Result given in mV hence multiplied by 1000.
263 buf[i] = (buf[i] * 3 * 1000 *
264 twl4030_divider_ratios[i].denominator)
265 / (2 * 1023 *
266 twl4030_divider_ratios[i].numerator);
269 if (count_req)
270 dev_err(madc->dev, "%d channel conversion failed\n", count_req);
272 return count;
276 * Enables irq.
277 * @madc - pointer to twl4030_madc_data struct
278 * @id - irq number to be enabled
279 * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
280 * corresponding to RT, SW1, SW2 conversion requests.
281 * If the i2c read fails it returns an error else returns 0.
283 static int twl4030_madc_enable_irq(struct twl4030_madc_data *madc, u8 id)
285 u8 val;
286 int ret;
288 ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
289 if (ret) {
290 dev_err(madc->dev, "unable to read imr register 0x%X\n",
291 madc->imr);
292 return ret;
294 val &= ~(1 << id);
295 ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
296 if (ret) {
297 dev_err(madc->dev,
298 "unable to write imr register 0x%X\n", madc->imr);
299 return ret;
303 return 0;
307 * Disables irq.
308 * @madc - pointer to twl4030_madc_data struct
309 * @id - irq number to be disabled
310 * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
311 * corresponding to RT, SW1, SW2 conversion requests.
312 * Returns error if i2c read/write fails.
314 static int twl4030_madc_disable_irq(struct twl4030_madc_data *madc, u8 id)
316 u8 val;
317 int ret;
319 ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
320 if (ret) {
321 dev_err(madc->dev, "unable to read imr register 0x%X\n",
322 madc->imr);
323 return ret;
325 val |= (1 << id);
326 ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
327 if (ret) {
328 dev_err(madc->dev,
329 "unable to write imr register 0x%X\n", madc->imr);
330 return ret;
333 return 0;
336 static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
338 struct twl4030_madc_data *madc = _madc;
339 const struct twl4030_madc_conversion_method *method;
340 u8 isr_val, imr_val;
341 int i, len, ret;
342 struct twl4030_madc_request *r;
344 mutex_lock(&madc->lock);
345 ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &isr_val, madc->isr);
346 if (ret) {
347 dev_err(madc->dev, "unable to read isr register 0x%X\n",
348 madc->isr);
349 goto err_i2c;
351 ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &imr_val, madc->imr);
352 if (ret) {
353 dev_err(madc->dev, "unable to read imr register 0x%X\n",
354 madc->imr);
355 goto err_i2c;
357 isr_val &= ~imr_val;
358 for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
359 if (!(isr_val & (1 << i)))
360 continue;
361 ret = twl4030_madc_disable_irq(madc, i);
362 if (ret < 0)
363 dev_dbg(madc->dev, "Disable interrupt failed%d\n", i);
364 madc->requests[i].result_pending = 1;
366 for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
367 r = &madc->requests[i];
368 /* No pending results for this method, move to next one */
369 if (!r->result_pending)
370 continue;
371 method = &twl4030_conversion_methods[r->method];
372 /* Read results */
373 len = twl4030_madc_read_channels(madc, method->rbase,
374 r->channels, r->rbuf);
375 /* Return results to caller */
376 if (r->func_cb != NULL) {
377 r->func_cb(len, r->channels, r->rbuf);
378 r->func_cb = NULL;
380 /* Free request */
381 r->result_pending = 0;
382 r->active = 0;
384 mutex_unlock(&madc->lock);
386 return IRQ_HANDLED;
388 err_i2c:
390 * In case of error check whichever request is active
391 * and service the same.
393 for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
394 r = &madc->requests[i];
395 if (r->active == 0)
396 continue;
397 method = &twl4030_conversion_methods[r->method];
398 /* Read results */
399 len = twl4030_madc_read_channels(madc, method->rbase,
400 r->channels, r->rbuf);
401 /* Return results to caller */
402 if (r->func_cb != NULL) {
403 r->func_cb(len, r->channels, r->rbuf);
404 r->func_cb = NULL;
406 /* Free request */
407 r->result_pending = 0;
408 r->active = 0;
410 mutex_unlock(&madc->lock);
412 return IRQ_HANDLED;
415 static int twl4030_madc_set_irq(struct twl4030_madc_data *madc,
416 struct twl4030_madc_request *req)
418 struct twl4030_madc_request *p;
419 int ret;
421 p = &madc->requests[req->method];
422 memcpy(p, req, sizeof(*req));
423 ret = twl4030_madc_enable_irq(madc, req->method);
424 if (ret < 0) {
425 dev_err(madc->dev, "enable irq failed!!\n");
426 return ret;
429 return 0;
433 * Function which enables the madc conversion
434 * by writing to the control register.
435 * @madc - pointer to twl4030_madc_data struct
436 * @conv_method - can be TWL4030_MADC_RT, TWL4030_MADC_SW2, TWL4030_MADC_SW1
437 * corresponding to RT SW1 or SW2 conversion methods.
438 * Returns 0 if succeeds else a negative error value
440 static int twl4030_madc_start_conversion(struct twl4030_madc_data *madc,
441 int conv_method)
443 const struct twl4030_madc_conversion_method *method;
444 int ret = 0;
445 method = &twl4030_conversion_methods[conv_method];
446 switch (conv_method) {
447 case TWL4030_MADC_SW1:
448 case TWL4030_MADC_SW2:
449 ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
450 TWL4030_MADC_SW_START, method->ctrl);
451 if (ret) {
452 dev_err(madc->dev,
453 "unable to write ctrl register 0x%X\n",
454 method->ctrl);
455 return ret;
457 break;
458 default:
459 break;
462 return 0;
466 * Function that waits for conversion to be ready
467 * @madc - pointer to twl4030_madc_data struct
468 * @timeout_ms - timeout value in milliseconds
469 * @status_reg - ctrl register
470 * returns 0 if succeeds else a negative error value
472 static int twl4030_madc_wait_conversion_ready(struct twl4030_madc_data *madc,
473 unsigned int timeout_ms,
474 u8 status_reg)
476 unsigned long timeout;
477 int ret;
479 timeout = jiffies + msecs_to_jiffies(timeout_ms);
480 do {
481 u8 reg;
483 ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &reg, status_reg);
484 if (ret) {
485 dev_err(madc->dev,
486 "unable to read status register 0x%X\n",
487 status_reg);
488 return ret;
490 if (!(reg & TWL4030_MADC_BUSY) && (reg & TWL4030_MADC_EOC_SW))
491 return 0;
492 usleep_range(500, 2000);
493 } while (!time_after(jiffies, timeout));
494 dev_err(madc->dev, "conversion timeout!\n");
496 return -EAGAIN;
500 * An exported function which can be called from other kernel drivers.
501 * @req twl4030_madc_request structure
502 * req->rbuf will be filled with read values of channels based on the
503 * channel index. If a particular channel reading fails there will
504 * be a negative error value in the corresponding array element.
505 * returns 0 if succeeds else error value
507 int twl4030_madc_conversion(struct twl4030_madc_request *req)
509 const struct twl4030_madc_conversion_method *method;
510 u8 ch_msb, ch_lsb;
511 int ret;
513 if (!req || !twl4030_madc)
514 return -EINVAL;
516 mutex_lock(&twl4030_madc->lock);
517 if (req->method < TWL4030_MADC_RT || req->method > TWL4030_MADC_SW2) {
518 ret = -EINVAL;
519 goto out;
521 /* Do we have a conversion request ongoing */
522 if (twl4030_madc->requests[req->method].active) {
523 ret = -EBUSY;
524 goto out;
526 ch_msb = (req->channels >> 8) & 0xff;
527 ch_lsb = req->channels & 0xff;
528 method = &twl4030_conversion_methods[req->method];
529 /* Select channels to be converted */
530 ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_msb, method->sel + 1);
531 if (ret) {
532 dev_err(twl4030_madc->dev,
533 "unable to write sel register 0x%X\n", method->sel + 1);
534 goto out;
536 ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_lsb, method->sel);
537 if (ret) {
538 dev_err(twl4030_madc->dev,
539 "unable to write sel register 0x%X\n", method->sel + 1);
540 goto out;
542 /* Select averaging for all channels if do_avg is set */
543 if (req->do_avg) {
544 ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
545 ch_msb, method->avg + 1);
546 if (ret) {
547 dev_err(twl4030_madc->dev,
548 "unable to write avg register 0x%X\n",
549 method->avg + 1);
550 goto out;
552 ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
553 ch_lsb, method->avg);
554 if (ret) {
555 dev_err(twl4030_madc->dev,
556 "unable to write sel reg 0x%X\n",
557 method->sel + 1);
558 goto out;
561 if (req->type == TWL4030_MADC_IRQ_ONESHOT && req->func_cb != NULL) {
562 ret = twl4030_madc_set_irq(twl4030_madc, req);
563 if (ret < 0)
564 goto out;
565 ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
566 if (ret < 0)
567 goto out;
568 twl4030_madc->requests[req->method].active = 1;
569 ret = 0;
570 goto out;
572 /* With RT method we should not be here anymore */
573 if (req->method == TWL4030_MADC_RT) {
574 ret = -EINVAL;
575 goto out;
577 ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
578 if (ret < 0)
579 goto out;
580 twl4030_madc->requests[req->method].active = 1;
581 /* Wait until conversion is ready (ctrl register returns EOC) */
582 ret = twl4030_madc_wait_conversion_ready(twl4030_madc, 5, method->ctrl);
583 if (ret) {
584 twl4030_madc->requests[req->method].active = 0;
585 goto out;
587 ret = twl4030_madc_read_channels(twl4030_madc, method->rbase,
588 req->channels, req->rbuf);
589 twl4030_madc->requests[req->method].active = 0;
591 out:
592 mutex_unlock(&twl4030_madc->lock);
594 return ret;
596 EXPORT_SYMBOL_GPL(twl4030_madc_conversion);
599 * Return channel value
600 * Or < 0 on failure.
602 int twl4030_get_madc_conversion(int channel_no)
604 struct twl4030_madc_request req;
605 int temp = 0;
606 int ret;
608 req.channels = (1 << channel_no);
609 req.method = TWL4030_MADC_SW2;
610 req.active = 0;
611 req.func_cb = NULL;
612 ret = twl4030_madc_conversion(&req);
613 if (ret < 0)
614 return ret;
615 if (req.rbuf[channel_no] > 0)
616 temp = req.rbuf[channel_no];
618 return temp;
620 EXPORT_SYMBOL_GPL(twl4030_get_madc_conversion);
623 * Function to enable or disable bias current for
624 * main battery type reading or temperature sensing
625 * @madc - pointer to twl4030_madc_data struct
626 * @chan - can be one of the two values
627 * TWL4030_BCI_ITHEN - Enables bias current for main battery type reading
628 * TWL4030_BCI_TYPEN - Enables bias current for main battery temperature
629 * sensing
630 * @on - enable or disable chan.
632 static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
633 int chan, int on)
635 int ret;
636 u8 regval;
638 ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
639 &regval, TWL4030_BCI_BCICTL1);
640 if (ret) {
641 dev_err(madc->dev, "unable to read BCICTL1 reg 0x%X",
642 TWL4030_BCI_BCICTL1);
643 return ret;
645 if (on)
646 regval |= chan ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN;
647 else
648 regval &= chan ? ~TWL4030_BCI_ITHEN : ~TWL4030_BCI_TYPEN;
649 ret = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
650 regval, TWL4030_BCI_BCICTL1);
651 if (ret) {
652 dev_err(madc->dev, "unable to write BCICTL1 reg 0x%X\n",
653 TWL4030_BCI_BCICTL1);
654 return ret;
657 return 0;
661 * Function that sets MADC software power on bit to enable MADC
662 * @madc - pointer to twl4030_madc_data struct
663 * @on - Enable or disable MADC software powen on bit.
664 * returns error if i2c read/write fails else 0
666 static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
668 u8 regval;
669 int ret;
671 ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
672 &regval, TWL4030_MADC_CTRL1);
673 if (ret) {
674 dev_err(madc->dev, "unable to read madc ctrl1 reg 0x%X\n",
675 TWL4030_MADC_CTRL1);
676 return ret;
678 if (on)
679 regval |= TWL4030_MADC_MADCON;
680 else
681 regval &= ~TWL4030_MADC_MADCON;
682 ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, regval, TWL4030_MADC_CTRL1);
683 if (ret) {
684 dev_err(madc->dev, "unable to write madc ctrl1 reg 0x%X\n",
685 TWL4030_MADC_CTRL1);
686 return ret;
689 return 0;
693 * Initialize MADC and request for threaded irq
695 static int __devinit twl4030_madc_probe(struct platform_device *pdev)
697 struct twl4030_madc_data *madc;
698 struct twl4030_madc_platform_data *pdata = pdev->dev.platform_data;
699 int ret;
700 u8 regval;
702 if (!pdata) {
703 dev_err(&pdev->dev, "platform_data not available\n");
704 return -EINVAL;
706 madc = kzalloc(sizeof(*madc), GFP_KERNEL);
707 if (!madc)
708 return -ENOMEM;
710 madc->dev = &pdev->dev;
713 * Phoenix provides 2 interrupt lines. The first one is connected to
714 * the OMAP. The other one can be connected to the other processor such
715 * as modem. Hence two separate ISR and IMR registers.
717 madc->imr = (pdata->irq_line == 1) ?
718 TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2;
719 madc->isr = (pdata->irq_line == 1) ?
720 TWL4030_MADC_ISR1 : TWL4030_MADC_ISR2;
721 ret = twl4030_madc_set_power(madc, 1);
722 if (ret < 0)
723 goto err_power;
724 ret = twl4030_madc_set_current_generator(madc, 0, 1);
725 if (ret < 0)
726 goto err_current_generator;
728 ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
729 &regval, TWL4030_BCI_BCICTL1);
730 if (ret) {
731 dev_err(&pdev->dev, "unable to read reg BCI CTL1 0x%X\n",
732 TWL4030_BCI_BCICTL1);
733 goto err_i2c;
735 regval |= TWL4030_BCI_MESBAT;
736 ret = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
737 regval, TWL4030_BCI_BCICTL1);
738 if (ret) {
739 dev_err(&pdev->dev, "unable to write reg BCI Ctl1 0x%X\n",
740 TWL4030_BCI_BCICTL1);
741 goto err_i2c;
743 platform_set_drvdata(pdev, madc);
744 mutex_init(&madc->lock);
745 ret = request_threaded_irq(platform_get_irq(pdev, 0), NULL,
746 twl4030_madc_threaded_irq_handler,
747 IRQF_TRIGGER_RISING, "twl4030_madc", madc);
748 if (ret) {
749 dev_dbg(&pdev->dev, "could not request irq\n");
750 goto err_irq;
752 twl4030_madc = madc;
753 return 0;
754 err_irq:
755 platform_set_drvdata(pdev, NULL);
756 err_i2c:
757 twl4030_madc_set_current_generator(madc, 0, 0);
758 err_current_generator:
759 twl4030_madc_set_power(madc, 0);
760 err_power:
761 kfree(madc);
763 return ret;
766 static int __devexit twl4030_madc_remove(struct platform_device *pdev)
768 struct twl4030_madc_data *madc = platform_get_drvdata(pdev);
770 free_irq(platform_get_irq(pdev, 0), madc);
771 platform_set_drvdata(pdev, NULL);
772 twl4030_madc_set_current_generator(madc, 0, 0);
773 twl4030_madc_set_power(madc, 0);
774 kfree(madc);
776 return 0;
779 static struct platform_driver twl4030_madc_driver = {
780 .probe = twl4030_madc_probe,
781 .remove = __exit_p(twl4030_madc_remove),
782 .driver = {
783 .name = "twl4030_madc",
784 .owner = THIS_MODULE,
788 static int __init twl4030_madc_init(void)
790 return platform_driver_register(&twl4030_madc_driver);
793 module_init(twl4030_madc_init);
795 static void __exit twl4030_madc_exit(void)
797 platform_driver_unregister(&twl4030_madc_driver);
800 module_exit(twl4030_madc_exit);
802 MODULE_DESCRIPTION("TWL4030 ADC driver");
803 MODULE_LICENSE("GPL");
804 MODULE_AUTHOR("J Keerthy");
805 MODULE_ALIAS("platform:twl4030_madc");