blob: 7de1c4c87942326bbf11e7519ddfa17d29f263f9 [file] [log] [blame]
Keerthyf99c1d42011-03-01 19:12:26 +05301/*
2 *
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.
6 *
7 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
8 * J Keerthy <j-keerthy@ti.com>
9 *
10 * Based on twl4030-madc.c
11 * Copyright (C) 2008 Nokia Corporation
12 * Mikko Ylinen <mikko.k.ylinen@nokia.com>
13 *
14 * Amit Kucheria <amit.kucheria@canonical.com>
15 *
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.
19 *
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.
24 *
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
29 *
30 */
31
Keerthyf99c1d42011-03-01 19:12:26 +053032#include <linux/device.h>
33#include <linux/interrupt.h>
34#include <linux/kernel.h>
35#include <linux/delay.h>
36#include <linux/platform_device.h>
37#include <linux/slab.h>
38#include <linux/i2c/twl.h>
39#include <linux/i2c/twl4030-madc.h>
40#include <linux/module.h>
41#include <linux/stddef.h>
42#include <linux/mutex.h>
43#include <linux/bitops.h>
44#include <linux/jiffies.h>
45#include <linux/types.h>
46#include <linux/gfp.h>
47#include <linux/err.h>
48
Sebastian Reichel2f39b702014-03-16 02:43:26 +010049#include <linux/iio/iio.h>
50
Sebastian Reichel99be0242014-03-16 02:43:27 +010051/**
Keerthyf99c1d42011-03-01 19:12:26 +053052 * struct twl4030_madc_data - a container for madc info
Sebastian Reichel99be0242014-03-16 02:43:27 +010053 * @dev: Pointer to device structure for madc
54 * @lock: Mutex protecting this data structure
55 * @requests: Array of request struct corresponding to SW1, SW2 and RT
56 * @use_second_irq: IRQ selection (main or co-processor)
57 * @imr: Interrupt mask register of MADC
58 * @isr: Interrupt status register of MADC
Keerthyf99c1d42011-03-01 19:12:26 +053059 */
60struct twl4030_madc_data {
61 struct device *dev;
62 struct mutex lock; /* mutex protecting this data structure */
63 struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
Sebastian Reichel2f39b702014-03-16 02:43:26 +010064 bool use_second_irq;
Sebastian Reichel99be0242014-03-16 02:43:27 +010065 u8 imr;
66 u8 isr;
Keerthyf99c1d42011-03-01 19:12:26 +053067};
68
Sebastian Reichel2f39b702014-03-16 02:43:26 +010069static int twl4030_madc_read(struct iio_dev *iio_dev,
70 const struct iio_chan_spec *chan,
71 int *val, int *val2, long mask)
72{
73 struct twl4030_madc_data *madc = iio_priv(iio_dev);
74 struct twl4030_madc_request req;
75 int ret;
76
77 req.method = madc->use_second_irq ? TWL4030_MADC_SW2 : TWL4030_MADC_SW1;
78
79 req.channels = BIT(chan->channel);
80 req.active = false;
81 req.func_cb = NULL;
82 req.type = TWL4030_MADC_WAIT;
83 req.raw = !(mask == IIO_CHAN_INFO_PROCESSED);
84 req.do_avg = (mask == IIO_CHAN_INFO_AVERAGE_RAW);
85
86 ret = twl4030_madc_conversion(&req);
87 if (ret < 0)
88 return ret;
89
90 *val = req.rbuf[chan->channel];
91
92 return IIO_VAL_INT;
93}
94
95static const struct iio_info twl4030_madc_iio_info = {
96 .read_raw = &twl4030_madc_read,
97 .driver_module = THIS_MODULE,
98};
99
100#define TWL4030_ADC_CHANNEL(_channel, _type, _name) { \
101 .type = _type, \
102 .channel = _channel, \
103 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
104 BIT(IIO_CHAN_INFO_AVERAGE_RAW) | \
105 BIT(IIO_CHAN_INFO_PROCESSED), \
106 .datasheet_name = _name, \
107 .indexed = 1, \
108}
109
110static const struct iio_chan_spec twl4030_madc_iio_channels[] = {
111 TWL4030_ADC_CHANNEL(0, IIO_VOLTAGE, "ADCIN0"),
112 TWL4030_ADC_CHANNEL(1, IIO_TEMP, "ADCIN1"),
113 TWL4030_ADC_CHANNEL(2, IIO_VOLTAGE, "ADCIN2"),
114 TWL4030_ADC_CHANNEL(3, IIO_VOLTAGE, "ADCIN3"),
115 TWL4030_ADC_CHANNEL(4, IIO_VOLTAGE, "ADCIN4"),
116 TWL4030_ADC_CHANNEL(5, IIO_VOLTAGE, "ADCIN5"),
117 TWL4030_ADC_CHANNEL(6, IIO_VOLTAGE, "ADCIN6"),
118 TWL4030_ADC_CHANNEL(7, IIO_VOLTAGE, "ADCIN7"),
119 TWL4030_ADC_CHANNEL(8, IIO_VOLTAGE, "ADCIN8"),
120 TWL4030_ADC_CHANNEL(9, IIO_VOLTAGE, "ADCIN9"),
121 TWL4030_ADC_CHANNEL(10, IIO_CURRENT, "ADCIN10"),
122 TWL4030_ADC_CHANNEL(11, IIO_VOLTAGE, "ADCIN11"),
123 TWL4030_ADC_CHANNEL(12, IIO_VOLTAGE, "ADCIN12"),
124 TWL4030_ADC_CHANNEL(13, IIO_VOLTAGE, "ADCIN13"),
125 TWL4030_ADC_CHANNEL(14, IIO_VOLTAGE, "ADCIN14"),
126 TWL4030_ADC_CHANNEL(15, IIO_VOLTAGE, "ADCIN15"),
127};
128
Keerthyf99c1d42011-03-01 19:12:26 +0530129static struct twl4030_madc_data *twl4030_madc;
130
131struct twl4030_prescale_divider_ratios {
132 s16 numerator;
133 s16 denominator;
134};
135
136static const struct twl4030_prescale_divider_ratios
137twl4030_divider_ratios[16] = {
138 {1, 1}, /* CHANNEL 0 No Prescaler */
139 {1, 1}, /* CHANNEL 1 No Prescaler */
140 {6, 10}, /* CHANNEL 2 */
141 {6, 10}, /* CHANNEL 3 */
142 {6, 10}, /* CHANNEL 4 */
143 {6, 10}, /* CHANNEL 5 */
144 {6, 10}, /* CHANNEL 6 */
145 {6, 10}, /* CHANNEL 7 */
146 {3, 14}, /* CHANNEL 8 */
147 {1, 3}, /* CHANNEL 9 */
148 {1, 1}, /* CHANNEL 10 No Prescaler */
149 {15, 100}, /* CHANNEL 11 */
150 {1, 4}, /* CHANNEL 12 */
151 {1, 1}, /* CHANNEL 13 Reserved channels */
152 {1, 1}, /* CHANNEL 14 Reseved channels */
153 {5, 11}, /* CHANNEL 15 */
154};
155
156
Sebastian Reichel99be0242014-03-16 02:43:27 +0100157/* Conversion table from -3 to 55 degrees Celcius */
158static int twl4030_therm_tbl[] = {
159 30800, 29500, 28300, 27100,
160 26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700,
161 17900, 17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100,
162 12600, 12100, 11600, 11200, 10800, 10400, 10000, 9630, 9280,
163 8950, 8620, 8310, 8020, 7730, 7460, 7200, 6950, 6710,
164 6470, 6250, 6040, 5830, 5640, 5450, 5260, 5090, 4920,
165 4760, 4600, 4450, 4310, 4170, 4040, 3910, 3790, 3670,
166 3550
Keerthyf99c1d42011-03-01 19:12:26 +0530167};
168
169/*
170 * Structure containing the registers
171 * of different conversion methods supported by MADC.
172 * Hardware or RT real time conversion request initiated by external host
173 * processor for RT Signal conversions.
174 * External host processors can also request for non RT conversions
175 * SW1 and SW2 software conversions also called asynchronous or GPC request.
176 */
177static
178const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = {
179 [TWL4030_MADC_RT] = {
180 .sel = TWL4030_MADC_RTSELECT_LSB,
181 .avg = TWL4030_MADC_RTAVERAGE_LSB,
182 .rbase = TWL4030_MADC_RTCH0_LSB,
183 },
184 [TWL4030_MADC_SW1] = {
185 .sel = TWL4030_MADC_SW1SELECT_LSB,
186 .avg = TWL4030_MADC_SW1AVERAGE_LSB,
187 .rbase = TWL4030_MADC_GPCH0_LSB,
188 .ctrl = TWL4030_MADC_CTRL_SW1,
189 },
190 [TWL4030_MADC_SW2] = {
191 .sel = TWL4030_MADC_SW2SELECT_LSB,
192 .avg = TWL4030_MADC_SW2AVERAGE_LSB,
193 .rbase = TWL4030_MADC_GPCH0_LSB,
194 .ctrl = TWL4030_MADC_CTRL_SW2,
195 },
196};
197
Sebastian Reichel99be0242014-03-16 02:43:27 +0100198/**
199 * twl4030_madc_channel_raw_read() - Function to read a particular channel value
200 * @madc: pointer to struct twl4030_madc_data
201 * @reg: lsb of ADC Channel
202 *
203 * Return: 0 on success, an error code otherwise.
Keerthyf99c1d42011-03-01 19:12:26 +0530204 */
205static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 reg)
206{
Sebastian Reichel168ae302014-03-16 02:43:29 +0100207 u16 val;
Keerthyf99c1d42011-03-01 19:12:26 +0530208 int ret;
209 /*
210 * For each ADC channel, we have MSB and LSB register pair. MSB address
211 * is always LSB address+1. reg parameter is the address of LSB register
212 */
Sebastian Reichel168ae302014-03-16 02:43:29 +0100213 ret = twl_i2c_read_u16(TWL4030_MODULE_MADC, &val, reg);
Keerthyf99c1d42011-03-01 19:12:26 +0530214 if (ret) {
Sebastian Reichel168ae302014-03-16 02:43:29 +0100215 dev_err(madc->dev, "unable to read register 0x%X\n", reg);
Keerthyf99c1d42011-03-01 19:12:26 +0530216 return ret;
217 }
218
Sebastian Reichel168ae302014-03-16 02:43:29 +0100219 return (int)(val >> 6);
Keerthyf99c1d42011-03-01 19:12:26 +0530220}
221
222/*
Sebastian Reichel99be0242014-03-16 02:43:27 +0100223 * Return battery temperature in degrees Celsius
Keerthyf99c1d42011-03-01 19:12:26 +0530224 * Or < 0 on failure.
225 */
226static int twl4030battery_temperature(int raw_volt)
227{
228 u8 val;
229 int temp, curr, volt, res, ret;
230
231 volt = (raw_volt * TEMP_STEP_SIZE) / TEMP_PSR_R;
Sebastian Reichel99be0242014-03-16 02:43:27 +0100232 /* Getting and calculating the supply current in micro amperes */
Peter Ujfalusie45342f2012-11-13 09:28:51 +0100233 ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val,
Keerthyf99c1d42011-03-01 19:12:26 +0530234 REG_BCICTL2);
235 if (ret < 0)
236 return ret;
Sebastian Reichel99be0242014-03-16 02:43:27 +0100237
Keerthyf99c1d42011-03-01 19:12:26 +0530238 curr = ((val & TWL4030_BCI_ITHEN) + 1) * 10;
239 /* Getting and calculating the thermistor resistance in ohms */
240 res = volt * 1000 / curr;
241 /* calculating temperature */
242 for (temp = 58; temp >= 0; temp--) {
Sebastian Reichel99be0242014-03-16 02:43:27 +0100243 int actual = twl4030_therm_tbl[temp];
Keerthyf99c1d42011-03-01 19:12:26 +0530244 if ((actual - res) >= 0)
245 break;
246 }
247
248 return temp + 1;
249}
250
251static int twl4030battery_current(int raw_volt)
252{
253 int ret;
254 u8 val;
255
Peter Ujfalusie45342f2012-11-13 09:28:51 +0100256 ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val,
Keerthyf99c1d42011-03-01 19:12:26 +0530257 TWL4030_BCI_BCICTL1);
258 if (ret)
259 return ret;
260 if (val & TWL4030_BCI_CGAIN) /* slope of 0.44 mV/mA */
261 return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R1;
262 else /* slope of 0.88 mV/mA */
263 return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R2;
264}
Sebastian Reichel99be0242014-03-16 02:43:27 +0100265
Keerthyf99c1d42011-03-01 19:12:26 +0530266/*
267 * Function to read channel values
268 * @madc - pointer to twl4030_madc_data struct
269 * @reg_base - Base address of the first channel
Sebastian Reichel99be0242014-03-16 02:43:27 +0100270 * @Channels - 16 bit bitmap. If the bit is set, channel's value is read
Keerthyf99c1d42011-03-01 19:12:26 +0530271 * @buf - The channel values are stored here. if read fails error
Pali Rohára5055d52013-02-15 23:56:49 +0100272 * @raw - Return raw values without conversion
Keerthyf99c1d42011-03-01 19:12:26 +0530273 * value is stored
274 * Returns the number of successfully read channels.
275 */
276static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
277 u8 reg_base, unsigned
Pali Rohára5055d52013-02-15 23:56:49 +0100278 long channels, int *buf,
279 bool raw)
Keerthyf99c1d42011-03-01 19:12:26 +0530280{
Sebastian Reichel99be0242014-03-16 02:43:27 +0100281 int count = 0;
282 int i;
Keerthyf99c1d42011-03-01 19:12:26 +0530283 u8 reg;
284
285 for_each_set_bit(i, &channels, TWL4030_MADC_MAX_CHANNELS) {
Sebastian Reichel99be0242014-03-16 02:43:27 +0100286 reg = reg_base + (2 * i);
Keerthyf99c1d42011-03-01 19:12:26 +0530287 buf[i] = twl4030_madc_channel_raw_read(madc, reg);
288 if (buf[i] < 0) {
Sebastian Reichel99be0242014-03-16 02:43:27 +0100289 dev_err(madc->dev, "Unable to read register 0x%X\n",
290 reg);
291 return buf[i];
Keerthyf99c1d42011-03-01 19:12:26 +0530292 }
Pali Rohára5055d52013-02-15 23:56:49 +0100293 if (raw) {
294 count++;
295 continue;
296 }
Keerthyf99c1d42011-03-01 19:12:26 +0530297 switch (i) {
298 case 10:
299 buf[i] = twl4030battery_current(buf[i]);
300 if (buf[i] < 0) {
301 dev_err(madc->dev, "err reading current\n");
Sebastian Reichel99be0242014-03-16 02:43:27 +0100302 return buf[i];
Keerthyf99c1d42011-03-01 19:12:26 +0530303 } else {
304 count++;
305 buf[i] = buf[i] - 750;
306 }
307 break;
308 case 1:
309 buf[i] = twl4030battery_temperature(buf[i]);
310 if (buf[i] < 0) {
311 dev_err(madc->dev, "err reading temperature\n");
Sebastian Reichel99be0242014-03-16 02:43:27 +0100312 return buf[i];
Keerthyf99c1d42011-03-01 19:12:26 +0530313 } else {
314 buf[i] -= 3;
315 count++;
316 }
317 break;
318 default:
319 count++;
320 /* Analog Input (V) = conv_result * step_size / R
321 * conv_result = decimal value of 10-bit conversion
322 * result
323 * step size = 1.5 / (2 ^ 10 -1)
324 * R = Prescaler ratio for input channels.
325 * Result given in mV hence multiplied by 1000.
326 */
327 buf[i] = (buf[i] * 3 * 1000 *
328 twl4030_divider_ratios[i].denominator)
329 / (2 * 1023 *
330 twl4030_divider_ratios[i].numerator);
331 }
332 }
Keerthyf99c1d42011-03-01 19:12:26 +0530333
334 return count;
335}
336
337/*
338 * Enables irq.
339 * @madc - pointer to twl4030_madc_data struct
340 * @id - irq number to be enabled
341 * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
342 * corresponding to RT, SW1, SW2 conversion requests.
343 * If the i2c read fails it returns an error else returns 0.
344 */
345static int twl4030_madc_enable_irq(struct twl4030_madc_data *madc, u8 id)
346{
347 u8 val;
348 int ret;
349
350 ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
351 if (ret) {
352 dev_err(madc->dev, "unable to read imr register 0x%X\n",
353 madc->imr);
354 return ret;
355 }
Sebastian Reichel99be0242014-03-16 02:43:27 +0100356
Keerthyf99c1d42011-03-01 19:12:26 +0530357 val &= ~(1 << id);
358 ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
359 if (ret) {
360 dev_err(madc->dev,
361 "unable to write imr register 0x%X\n", madc->imr);
362 return ret;
Keerthyf99c1d42011-03-01 19:12:26 +0530363 }
364
365 return 0;
366}
367
368/*
369 * Disables irq.
370 * @madc - pointer to twl4030_madc_data struct
371 * @id - irq number to be disabled
372 * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
373 * corresponding to RT, SW1, SW2 conversion requests.
374 * Returns error if i2c read/write fails.
375 */
376static int twl4030_madc_disable_irq(struct twl4030_madc_data *madc, u8 id)
377{
378 u8 val;
379 int ret;
380
381 ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
382 if (ret) {
383 dev_err(madc->dev, "unable to read imr register 0x%X\n",
384 madc->imr);
385 return ret;
386 }
387 val |= (1 << id);
388 ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
389 if (ret) {
390 dev_err(madc->dev,
391 "unable to write imr register 0x%X\n", madc->imr);
392 return ret;
393 }
394
395 return 0;
396}
397
398static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
399{
400 struct twl4030_madc_data *madc = _madc;
401 const struct twl4030_madc_conversion_method *method;
402 u8 isr_val, imr_val;
403 int i, len, ret;
404 struct twl4030_madc_request *r;
405
406 mutex_lock(&madc->lock);
407 ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &isr_val, madc->isr);
408 if (ret) {
409 dev_err(madc->dev, "unable to read isr register 0x%X\n",
410 madc->isr);
411 goto err_i2c;
412 }
413 ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &imr_val, madc->imr);
414 if (ret) {
415 dev_err(madc->dev, "unable to read imr register 0x%X\n",
416 madc->imr);
417 goto err_i2c;
418 }
419 isr_val &= ~imr_val;
420 for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
421 if (!(isr_val & (1 << i)))
422 continue;
423 ret = twl4030_madc_disable_irq(madc, i);
424 if (ret < 0)
Sebastian Reichel99be0242014-03-16 02:43:27 +0100425 dev_dbg(madc->dev, "Disable interrupt failed %d\n", i);
Keerthyf99c1d42011-03-01 19:12:26 +0530426 madc->requests[i].result_pending = 1;
427 }
428 for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
429 r = &madc->requests[i];
430 /* No pending results for this method, move to next one */
431 if (!r->result_pending)
432 continue;
433 method = &twl4030_conversion_methods[r->method];
434 /* Read results */
435 len = twl4030_madc_read_channels(madc, method->rbase,
Pali Rohára5055d52013-02-15 23:56:49 +0100436 r->channels, r->rbuf, r->raw);
Keerthyf99c1d42011-03-01 19:12:26 +0530437 /* Return results to caller */
438 if (r->func_cb != NULL) {
439 r->func_cb(len, r->channels, r->rbuf);
440 r->func_cb = NULL;
441 }
442 /* Free request */
443 r->result_pending = 0;
444 r->active = 0;
445 }
446 mutex_unlock(&madc->lock);
447
448 return IRQ_HANDLED;
449
450err_i2c:
451 /*
452 * In case of error check whichever request is active
453 * and service the same.
454 */
455 for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
456 r = &madc->requests[i];
457 if (r->active == 0)
458 continue;
459 method = &twl4030_conversion_methods[r->method];
460 /* Read results */
461 len = twl4030_madc_read_channels(madc, method->rbase,
Pali Rohára5055d52013-02-15 23:56:49 +0100462 r->channels, r->rbuf, r->raw);
Keerthyf99c1d42011-03-01 19:12:26 +0530463 /* Return results to caller */
464 if (r->func_cb != NULL) {
465 r->func_cb(len, r->channels, r->rbuf);
466 r->func_cb = NULL;
467 }
468 /* Free request */
469 r->result_pending = 0;
470 r->active = 0;
471 }
472 mutex_unlock(&madc->lock);
473
474 return IRQ_HANDLED;
475}
476
477static int twl4030_madc_set_irq(struct twl4030_madc_data *madc,
478 struct twl4030_madc_request *req)
479{
480 struct twl4030_madc_request *p;
481 int ret;
482
483 p = &madc->requests[req->method];
484 memcpy(p, req, sizeof(*req));
485 ret = twl4030_madc_enable_irq(madc, req->method);
486 if (ret < 0) {
487 dev_err(madc->dev, "enable irq failed!!\n");
488 return ret;
489 }
490
491 return 0;
492}
493
494/*
495 * Function which enables the madc conversion
496 * by writing to the control register.
497 * @madc - pointer to twl4030_madc_data struct
498 * @conv_method - can be TWL4030_MADC_RT, TWL4030_MADC_SW2, TWL4030_MADC_SW1
499 * corresponding to RT SW1 or SW2 conversion methods.
500 * Returns 0 if succeeds else a negative error value
501 */
502static int twl4030_madc_start_conversion(struct twl4030_madc_data *madc,
503 int conv_method)
504{
505 const struct twl4030_madc_conversion_method *method;
506 int ret = 0;
Sebastian Reichel99be0242014-03-16 02:43:27 +0100507
508 if (conv_method != TWL4030_MADC_SW1 && conv_method != TWL4030_MADC_SW2)
509 return -ENOTSUPP;
510
Keerthyf99c1d42011-03-01 19:12:26 +0530511 method = &twl4030_conversion_methods[conv_method];
Sebastian Reichel99be0242014-03-16 02:43:27 +0100512 ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, TWL4030_MADC_SW_START,
513 method->ctrl);
514 if (ret) {
515 dev_err(madc->dev, "unable to write ctrl register 0x%X\n",
516 method->ctrl);
517 return ret;
Keerthyf99c1d42011-03-01 19:12:26 +0530518 }
519
520 return 0;
521}
522
523/*
524 * Function that waits for conversion to be ready
525 * @madc - pointer to twl4030_madc_data struct
526 * @timeout_ms - timeout value in milliseconds
527 * @status_reg - ctrl register
528 * returns 0 if succeeds else a negative error value
529 */
530static int twl4030_madc_wait_conversion_ready(struct twl4030_madc_data *madc,
531 unsigned int timeout_ms,
532 u8 status_reg)
533{
534 unsigned long timeout;
535 int ret;
536
537 timeout = jiffies + msecs_to_jiffies(timeout_ms);
538 do {
539 u8 reg;
540
541 ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &reg, status_reg);
542 if (ret) {
543 dev_err(madc->dev,
544 "unable to read status register 0x%X\n",
545 status_reg);
546 return ret;
547 }
548 if (!(reg & TWL4030_MADC_BUSY) && (reg & TWL4030_MADC_EOC_SW))
549 return 0;
550 usleep_range(500, 2000);
551 } while (!time_after(jiffies, timeout));
552 dev_err(madc->dev, "conversion timeout!\n");
553
554 return -EAGAIN;
555}
556
557/*
558 * An exported function which can be called from other kernel drivers.
559 * @req twl4030_madc_request structure
560 * req->rbuf will be filled with read values of channels based on the
561 * channel index. If a particular channel reading fails there will
562 * be a negative error value in the corresponding array element.
563 * returns 0 if succeeds else error value
564 */
565int twl4030_madc_conversion(struct twl4030_madc_request *req)
566{
567 const struct twl4030_madc_conversion_method *method;
Keerthyf99c1d42011-03-01 19:12:26 +0530568 int ret;
569
Kyle Mannad0e84ca2011-08-11 22:33:14 -0500570 if (!req || !twl4030_madc)
Keerthyf99c1d42011-03-01 19:12:26 +0530571 return -EINVAL;
Kyle Mannad0e84ca2011-08-11 22:33:14 -0500572
Keerthyf99c1d42011-03-01 19:12:26 +0530573 mutex_lock(&twl4030_madc->lock);
574 if (req->method < TWL4030_MADC_RT || req->method > TWL4030_MADC_SW2) {
575 ret = -EINVAL;
576 goto out;
577 }
578 /* Do we have a conversion request ongoing */
579 if (twl4030_madc->requests[req->method].active) {
580 ret = -EBUSY;
581 goto out;
582 }
Keerthyf99c1d42011-03-01 19:12:26 +0530583 method = &twl4030_conversion_methods[req->method];
584 /* Select channels to be converted */
Sebastian Reichel168ae302014-03-16 02:43:29 +0100585 ret = twl_i2c_write_u16(TWL4030_MODULE_MADC, req->channels, method->sel);
Keerthyf99c1d42011-03-01 19:12:26 +0530586 if (ret) {
587 dev_err(twl4030_madc->dev,
Sebastian Reichel168ae302014-03-16 02:43:29 +0100588 "unable to write sel register 0x%X\n", method->sel);
Sanjeev Premie178ccb2011-07-11 20:50:31 +0530589 goto out;
Keerthyf99c1d42011-03-01 19:12:26 +0530590 }
591 /* Select averaging for all channels if do_avg is set */
592 if (req->do_avg) {
Sebastian Reichel168ae302014-03-16 02:43:29 +0100593 ret = twl_i2c_write_u16(TWL4030_MODULE_MADC, req->channels,
594 method->avg);
Keerthyf99c1d42011-03-01 19:12:26 +0530595 if (ret) {
596 dev_err(twl4030_madc->dev,
597 "unable to write avg register 0x%X\n",
Sebastian Reichel99be0242014-03-16 02:43:27 +0100598 method->avg);
Sanjeev Premie178ccb2011-07-11 20:50:31 +0530599 goto out;
Keerthyf99c1d42011-03-01 19:12:26 +0530600 }
601 }
602 if (req->type == TWL4030_MADC_IRQ_ONESHOT && req->func_cb != NULL) {
603 ret = twl4030_madc_set_irq(twl4030_madc, req);
604 if (ret < 0)
605 goto out;
606 ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
607 if (ret < 0)
608 goto out;
609 twl4030_madc->requests[req->method].active = 1;
610 ret = 0;
611 goto out;
612 }
613 /* With RT method we should not be here anymore */
614 if (req->method == TWL4030_MADC_RT) {
615 ret = -EINVAL;
616 goto out;
617 }
618 ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
619 if (ret < 0)
620 goto out;
621 twl4030_madc->requests[req->method].active = 1;
622 /* Wait until conversion is ready (ctrl register returns EOC) */
623 ret = twl4030_madc_wait_conversion_ready(twl4030_madc, 5, method->ctrl);
624 if (ret) {
625 twl4030_madc->requests[req->method].active = 0;
626 goto out;
627 }
628 ret = twl4030_madc_read_channels(twl4030_madc, method->rbase,
Pali Rohára5055d52013-02-15 23:56:49 +0100629 req->channels, req->rbuf, req->raw);
Keerthyf99c1d42011-03-01 19:12:26 +0530630 twl4030_madc->requests[req->method].active = 0;
631
632out:
633 mutex_unlock(&twl4030_madc->lock);
634
635 return ret;
636}
637EXPORT_SYMBOL_GPL(twl4030_madc_conversion);
638
Keerthyf99c1d42011-03-01 19:12:26 +0530639int twl4030_get_madc_conversion(int channel_no)
640{
641 struct twl4030_madc_request req;
642 int temp = 0;
643 int ret;
644
645 req.channels = (1 << channel_no);
646 req.method = TWL4030_MADC_SW2;
647 req.active = 0;
648 req.func_cb = NULL;
649 ret = twl4030_madc_conversion(&req);
650 if (ret < 0)
651 return ret;
652 if (req.rbuf[channel_no] > 0)
653 temp = req.rbuf[channel_no];
654
655 return temp;
656}
657EXPORT_SYMBOL_GPL(twl4030_get_madc_conversion);
658
Sebastian Reichel99be0242014-03-16 02:43:27 +0100659/**
660 * twl4030_madc_set_current_generator() - setup bias current
661 *
662 * @madc: pointer to twl4030_madc_data struct
663 * @chan: can be one of the two values:
664 * TWL4030_BCI_ITHEN
665 * Enables bias current for main battery type reading
666 * TWL4030_BCI_TYPEN
667 * Enables bias current for main battery temperature sensing
668 * @on: enable or disable chan.
669 *
Keerthyf99c1d42011-03-01 19:12:26 +0530670 * Function to enable or disable bias current for
671 * main battery type reading or temperature sensing
Keerthyf99c1d42011-03-01 19:12:26 +0530672 */
673static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
674 int chan, int on)
675{
676 int ret;
Sebastian Reichel99be0242014-03-16 02:43:27 +0100677 int regmask;
Keerthyf99c1d42011-03-01 19:12:26 +0530678 u8 regval;
679
Peter Ujfalusie45342f2012-11-13 09:28:51 +0100680 ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
Keerthyf99c1d42011-03-01 19:12:26 +0530681 &regval, TWL4030_BCI_BCICTL1);
682 if (ret) {
683 dev_err(madc->dev, "unable to read BCICTL1 reg 0x%X",
684 TWL4030_BCI_BCICTL1);
685 return ret;
686 }
Sebastian Reichel99be0242014-03-16 02:43:27 +0100687
688 regmask = chan ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN;
Keerthyf99c1d42011-03-01 19:12:26 +0530689 if (on)
Sebastian Reichel99be0242014-03-16 02:43:27 +0100690 regval |= regmask;
Keerthyf99c1d42011-03-01 19:12:26 +0530691 else
Sebastian Reichel99be0242014-03-16 02:43:27 +0100692 regval &= ~regmask;
693
Peter Ujfalusie45342f2012-11-13 09:28:51 +0100694 ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
Keerthyf99c1d42011-03-01 19:12:26 +0530695 regval, TWL4030_BCI_BCICTL1);
696 if (ret) {
697 dev_err(madc->dev, "unable to write BCICTL1 reg 0x%X\n",
698 TWL4030_BCI_BCICTL1);
699 return ret;
700 }
701
702 return 0;
703}
704
705/*
706 * Function that sets MADC software power on bit to enable MADC
707 * @madc - pointer to twl4030_madc_data struct
Sebastian Reichel99be0242014-03-16 02:43:27 +0100708 * @on - Enable or disable MADC software power on bit.
Keerthyf99c1d42011-03-01 19:12:26 +0530709 * returns error if i2c read/write fails else 0
710 */
711static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
712{
713 u8 regval;
714 int ret;
715
Peter Ujfalusie45342f2012-11-13 09:28:51 +0100716 ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
Keerthyf99c1d42011-03-01 19:12:26 +0530717 &regval, TWL4030_MADC_CTRL1);
718 if (ret) {
719 dev_err(madc->dev, "unable to read madc ctrl1 reg 0x%X\n",
720 TWL4030_MADC_CTRL1);
721 return ret;
722 }
723 if (on)
724 regval |= TWL4030_MADC_MADCON;
725 else
726 regval &= ~TWL4030_MADC_MADCON;
727 ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, regval, TWL4030_MADC_CTRL1);
728 if (ret) {
729 dev_err(madc->dev, "unable to write madc ctrl1 reg 0x%X\n",
730 TWL4030_MADC_CTRL1);
731 return ret;
732 }
733
734 return 0;
735}
736
737/*
738 * Initialize MADC and request for threaded irq
739 */
Bill Pembertonf791be42012-11-19 13:23:04 -0500740static int twl4030_madc_probe(struct platform_device *pdev)
Keerthyf99c1d42011-03-01 19:12:26 +0530741{
742 struct twl4030_madc_data *madc;
Jingoo Han334a41c2013-07-30 17:10:05 +0900743 struct twl4030_madc_platform_data *pdata = dev_get_platdata(&pdev->dev);
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100744 struct device_node *np = pdev->dev.of_node;
Sebastian Reichele7f22b72014-03-16 02:43:25 +0100745 int irq, ret;
Keerthyf99c1d42011-03-01 19:12:26 +0530746 u8 regval;
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100747 struct iio_dev *iio_dev = NULL;
Keerthyf99c1d42011-03-01 19:12:26 +0530748
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100749 if (!pdata && !np) {
750 dev_err(&pdev->dev, "neither platform data nor Device Tree node available\n");
Keerthyf99c1d42011-03-01 19:12:26 +0530751 return -EINVAL;
752 }
Keerthyf99c1d42011-03-01 19:12:26 +0530753
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100754 iio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*madc));
755 if (!iio_dev) {
756 dev_err(&pdev->dev, "failed allocating iio device\n");
757 return -ENOMEM;
758 }
759
760 madc = iio_priv(iio_dev);
Kyle Manna66cc5b82011-08-11 22:33:12 -0500761 madc->dev = &pdev->dev;
762
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100763 iio_dev->name = dev_name(&pdev->dev);
764 iio_dev->dev.parent = &pdev->dev;
765 iio_dev->dev.of_node = pdev->dev.of_node;
766 iio_dev->info = &twl4030_madc_iio_info;
767 iio_dev->modes = INDIO_DIRECT_MODE;
768 iio_dev->channels = twl4030_madc_iio_channels;
769 iio_dev->num_channels = ARRAY_SIZE(twl4030_madc_iio_channels);
770
Keerthyf99c1d42011-03-01 19:12:26 +0530771 /*
772 * Phoenix provides 2 interrupt lines. The first one is connected to
773 * the OMAP. The other one can be connected to the other processor such
774 * as modem. Hence two separate ISR and IMR registers.
775 */
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100776 if (pdata)
777 madc->use_second_irq = (pdata->irq_line != 1);
778 else
779 madc->use_second_irq = of_property_read_bool(np,
780 "ti,system-uses-second-madc-irq");
781
782 madc->imr = madc->use_second_irq ? TWL4030_MADC_IMR2 :
783 TWL4030_MADC_IMR1;
784 madc->isr = madc->use_second_irq ? TWL4030_MADC_ISR2 :
785 TWL4030_MADC_ISR1;
786
Keerthyf99c1d42011-03-01 19:12:26 +0530787 ret = twl4030_madc_set_power(madc, 1);
788 if (ret < 0)
Sebastian Reichele7f22b72014-03-16 02:43:25 +0100789 return ret;
Keerthyf99c1d42011-03-01 19:12:26 +0530790 ret = twl4030_madc_set_current_generator(madc, 0, 1);
791 if (ret < 0)
792 goto err_current_generator;
793
Peter Ujfalusie45342f2012-11-13 09:28:51 +0100794 ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
Keerthyf99c1d42011-03-01 19:12:26 +0530795 &regval, TWL4030_BCI_BCICTL1);
796 if (ret) {
797 dev_err(&pdev->dev, "unable to read reg BCI CTL1 0x%X\n",
798 TWL4030_BCI_BCICTL1);
799 goto err_i2c;
800 }
801 regval |= TWL4030_BCI_MESBAT;
Peter Ujfalusie45342f2012-11-13 09:28:51 +0100802 ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
Keerthyf99c1d42011-03-01 19:12:26 +0530803 regval, TWL4030_BCI_BCICTL1);
804 if (ret) {
805 dev_err(&pdev->dev, "unable to write reg BCI Ctl1 0x%X\n",
806 TWL4030_BCI_BCICTL1);
807 goto err_i2c;
808 }
Kyle Manna3d6271f2011-08-11 22:33:13 -0500809
810 /* Check that MADC clock is on */
811 ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &regval, TWL4030_REG_GPBR1);
812 if (ret) {
813 dev_err(&pdev->dev, "unable to read reg GPBR1 0x%X\n",
814 TWL4030_REG_GPBR1);
815 goto err_i2c;
816 }
817
818 /* If MADC clk is not on, turn it on */
819 if (!(regval & TWL4030_GPBR1_MADC_HFCLK_EN)) {
820 dev_info(&pdev->dev, "clk disabled, enabling\n");
821 regval |= TWL4030_GPBR1_MADC_HFCLK_EN;
822 ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, regval,
823 TWL4030_REG_GPBR1);
824 if (ret) {
825 dev_err(&pdev->dev, "unable to write reg GPBR1 0x%X\n",
826 TWL4030_REG_GPBR1);
827 goto err_i2c;
828 }
829 }
830
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100831 platform_set_drvdata(pdev, iio_dev);
Keerthyf99c1d42011-03-01 19:12:26 +0530832 mutex_init(&madc->lock);
Sebastian Reichele7f22b72014-03-16 02:43:25 +0100833
834 irq = platform_get_irq(pdev, 0);
835 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
Keerthyf99c1d42011-03-01 19:12:26 +0530836 twl4030_madc_threaded_irq_handler,
837 IRQF_TRIGGER_RISING, "twl4030_madc", madc);
838 if (ret) {
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100839 dev_err(&pdev->dev, "could not request irq\n");
Jingoo Hanc3d6a0a2013-05-06 13:08:08 +0900840 goto err_i2c;
Keerthyf99c1d42011-03-01 19:12:26 +0530841 }
842 twl4030_madc = madc;
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100843
844 ret = iio_device_register(iio_dev);
845 if (ret) {
846 dev_err(&pdev->dev, "could not register iio device\n");
847 goto err_i2c;
848 }
849
Keerthyf99c1d42011-03-01 19:12:26 +0530850 return 0;
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100851
Keerthyf99c1d42011-03-01 19:12:26 +0530852err_i2c:
853 twl4030_madc_set_current_generator(madc, 0, 0);
854err_current_generator:
855 twl4030_madc_set_power(madc, 0);
Keerthyf99c1d42011-03-01 19:12:26 +0530856 return ret;
857}
858
Bill Pemberton4740f732012-11-19 13:26:01 -0500859static int twl4030_madc_remove(struct platform_device *pdev)
Keerthyf99c1d42011-03-01 19:12:26 +0530860{
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100861 struct iio_dev *iio_dev = platform_get_drvdata(pdev);
862 struct twl4030_madc_data *madc = iio_priv(iio_dev);
863
864 iio_device_unregister(iio_dev);
Keerthyf99c1d42011-03-01 19:12:26 +0530865
Keerthyf99c1d42011-03-01 19:12:26 +0530866 twl4030_madc_set_current_generator(madc, 0, 0);
867 twl4030_madc_set_power(madc, 0);
Keerthyf99c1d42011-03-01 19:12:26 +0530868
869 return 0;
870}
871
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100872#ifdef CONFIG_OF
873static const struct of_device_id twl_madc_of_match[] = {
874 { .compatible = "ti,twl4030-madc", },
875 { },
876};
877MODULE_DEVICE_TABLE(of, twl_madc_of_match);
878#endif
879
Keerthyf99c1d42011-03-01 19:12:26 +0530880static struct platform_driver twl4030_madc_driver = {
881 .probe = twl4030_madc_probe,
Arnd Bergmann03715412013-03-14 22:56:38 +0100882 .remove = twl4030_madc_remove,
Keerthyf99c1d42011-03-01 19:12:26 +0530883 .driver = {
884 .name = "twl4030_madc",
885 .owner = THIS_MODULE,
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100886 .of_match_table = of_match_ptr(twl_madc_of_match),
Sebastian Reichel99be0242014-03-16 02:43:27 +0100887 },
Keerthyf99c1d42011-03-01 19:12:26 +0530888};
889
Mark Brown65349d62011-11-23 22:58:34 +0000890module_platform_driver(twl4030_madc_driver);
Keerthyf99c1d42011-03-01 19:12:26 +0530891
892MODULE_DESCRIPTION("TWL4030 ADC driver");
893MODULE_LICENSE("GPL");
894MODULE_AUTHOR("J Keerthy");
Axel Lin0ea3e832011-03-07 11:02:29 +0800895MODULE_ALIAS("platform:twl4030_madc");