blob: 8a014fbb98bcf50279bed245412fe86e68caffdb [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
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>
49
Sebastian Reichel2f39b702014-03-16 02:43:26 +010050#include <linux/iio/iio.h>
51
Sebastian Reichel99be0242014-03-16 02:43:27 +010052/**
Keerthyf99c1d42011-03-01 19:12:26 +053053 * struct twl4030_madc_data - a container for madc info
Sebastian Reichel99be0242014-03-16 02:43:27 +010054 * @dev: Pointer to device structure for madc
55 * @lock: Mutex protecting this data structure
56 * @requests: Array of request struct corresponding to SW1, SW2 and RT
57 * @use_second_irq: IRQ selection (main or co-processor)
58 * @imr: Interrupt mask register of MADC
59 * @isr: Interrupt status register of MADC
Keerthyf99c1d42011-03-01 19:12:26 +053060 */
61struct twl4030_madc_data {
62 struct device *dev;
63 struct mutex lock; /* mutex protecting this data structure */
64 struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
Sebastian Reichel2f39b702014-03-16 02:43:26 +010065 bool use_second_irq;
Sebastian Reichel99be0242014-03-16 02:43:27 +010066 u8 imr;
67 u8 isr;
Keerthyf99c1d42011-03-01 19:12:26 +053068};
69
Sebastian Reichel2f39b702014-03-16 02:43:26 +010070static int twl4030_madc_read(struct iio_dev *iio_dev,
71 const struct iio_chan_spec *chan,
72 int *val, int *val2, long mask)
73{
74 struct twl4030_madc_data *madc = iio_priv(iio_dev);
75 struct twl4030_madc_request req;
76 int ret;
77
78 req.method = madc->use_second_irq ? TWL4030_MADC_SW2 : TWL4030_MADC_SW1;
79
80 req.channels = BIT(chan->channel);
81 req.active = false;
82 req.func_cb = NULL;
83 req.type = TWL4030_MADC_WAIT;
84 req.raw = !(mask == IIO_CHAN_INFO_PROCESSED);
85 req.do_avg = (mask == IIO_CHAN_INFO_AVERAGE_RAW);
86
87 ret = twl4030_madc_conversion(&req);
88 if (ret < 0)
89 return ret;
90
91 *val = req.rbuf[chan->channel];
92
93 return IIO_VAL_INT;
94}
95
96static const struct iio_info twl4030_madc_iio_info = {
97 .read_raw = &twl4030_madc_read,
98 .driver_module = THIS_MODULE,
99};
100
101#define TWL4030_ADC_CHANNEL(_channel, _type, _name) { \
102 .type = _type, \
103 .channel = _channel, \
104 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
105 BIT(IIO_CHAN_INFO_AVERAGE_RAW) | \
106 BIT(IIO_CHAN_INFO_PROCESSED), \
107 .datasheet_name = _name, \
108 .indexed = 1, \
109}
110
111static const struct iio_chan_spec twl4030_madc_iio_channels[] = {
112 TWL4030_ADC_CHANNEL(0, IIO_VOLTAGE, "ADCIN0"),
113 TWL4030_ADC_CHANNEL(1, IIO_TEMP, "ADCIN1"),
114 TWL4030_ADC_CHANNEL(2, IIO_VOLTAGE, "ADCIN2"),
115 TWL4030_ADC_CHANNEL(3, IIO_VOLTAGE, "ADCIN3"),
116 TWL4030_ADC_CHANNEL(4, IIO_VOLTAGE, "ADCIN4"),
117 TWL4030_ADC_CHANNEL(5, IIO_VOLTAGE, "ADCIN5"),
118 TWL4030_ADC_CHANNEL(6, IIO_VOLTAGE, "ADCIN6"),
119 TWL4030_ADC_CHANNEL(7, IIO_VOLTAGE, "ADCIN7"),
120 TWL4030_ADC_CHANNEL(8, IIO_VOLTAGE, "ADCIN8"),
121 TWL4030_ADC_CHANNEL(9, IIO_VOLTAGE, "ADCIN9"),
122 TWL4030_ADC_CHANNEL(10, IIO_CURRENT, "ADCIN10"),
123 TWL4030_ADC_CHANNEL(11, IIO_VOLTAGE, "ADCIN11"),
124 TWL4030_ADC_CHANNEL(12, IIO_VOLTAGE, "ADCIN12"),
125 TWL4030_ADC_CHANNEL(13, IIO_VOLTAGE, "ADCIN13"),
126 TWL4030_ADC_CHANNEL(14, IIO_VOLTAGE, "ADCIN14"),
127 TWL4030_ADC_CHANNEL(15, IIO_VOLTAGE, "ADCIN15"),
128};
129
Keerthyf99c1d42011-03-01 19:12:26 +0530130static struct twl4030_madc_data *twl4030_madc;
131
132struct twl4030_prescale_divider_ratios {
133 s16 numerator;
134 s16 denominator;
135};
136
137static const struct twl4030_prescale_divider_ratios
138twl4030_divider_ratios[16] = {
139 {1, 1}, /* CHANNEL 0 No Prescaler */
140 {1, 1}, /* CHANNEL 1 No Prescaler */
141 {6, 10}, /* CHANNEL 2 */
142 {6, 10}, /* CHANNEL 3 */
143 {6, 10}, /* CHANNEL 4 */
144 {6, 10}, /* CHANNEL 5 */
145 {6, 10}, /* CHANNEL 6 */
146 {6, 10}, /* CHANNEL 7 */
147 {3, 14}, /* CHANNEL 8 */
148 {1, 3}, /* CHANNEL 9 */
149 {1, 1}, /* CHANNEL 10 No Prescaler */
150 {15, 100}, /* CHANNEL 11 */
151 {1, 4}, /* CHANNEL 12 */
152 {1, 1}, /* CHANNEL 13 Reserved channels */
153 {1, 1}, /* CHANNEL 14 Reseved channels */
154 {5, 11}, /* CHANNEL 15 */
155};
156
157
Sebastian Reichel99be0242014-03-16 02:43:27 +0100158/* Conversion table from -3 to 55 degrees Celcius */
159static int twl4030_therm_tbl[] = {
160 30800, 29500, 28300, 27100,
161 26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700,
162 17900, 17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100,
163 12600, 12100, 11600, 11200, 10800, 10400, 10000, 9630, 9280,
164 8950, 8620, 8310, 8020, 7730, 7460, 7200, 6950, 6710,
165 6470, 6250, 6040, 5830, 5640, 5450, 5260, 5090, 4920,
166 4760, 4600, 4450, 4310, 4170, 4040, 3910, 3790, 3670,
167 3550
Keerthyf99c1d42011-03-01 19:12:26 +0530168};
169
170/*
171 * Structure containing the registers
172 * of different conversion methods supported by MADC.
173 * Hardware or RT real time conversion request initiated by external host
174 * processor for RT Signal conversions.
175 * External host processors can also request for non RT conversions
176 * SW1 and SW2 software conversions also called asynchronous or GPC request.
177 */
178static
179const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = {
180 [TWL4030_MADC_RT] = {
181 .sel = TWL4030_MADC_RTSELECT_LSB,
182 .avg = TWL4030_MADC_RTAVERAGE_LSB,
183 .rbase = TWL4030_MADC_RTCH0_LSB,
184 },
185 [TWL4030_MADC_SW1] = {
186 .sel = TWL4030_MADC_SW1SELECT_LSB,
187 .avg = TWL4030_MADC_SW1AVERAGE_LSB,
188 .rbase = TWL4030_MADC_GPCH0_LSB,
189 .ctrl = TWL4030_MADC_CTRL_SW1,
190 },
191 [TWL4030_MADC_SW2] = {
192 .sel = TWL4030_MADC_SW2SELECT_LSB,
193 .avg = TWL4030_MADC_SW2AVERAGE_LSB,
194 .rbase = TWL4030_MADC_GPCH0_LSB,
195 .ctrl = TWL4030_MADC_CTRL_SW2,
196 },
197};
198
Sebastian Reichel99be0242014-03-16 02:43:27 +0100199/**
200 * twl4030_madc_channel_raw_read() - Function to read a particular channel value
201 * @madc: pointer to struct twl4030_madc_data
202 * @reg: lsb of ADC Channel
203 *
204 * Return: 0 on success, an error code otherwise.
Keerthyf99c1d42011-03-01 19:12:26 +0530205 */
206static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 reg)
207{
Sebastian Reichel168ae302014-03-16 02:43:29 +0100208 u16 val;
Keerthyf99c1d42011-03-01 19:12:26 +0530209 int ret;
210 /*
211 * For each ADC channel, we have MSB and LSB register pair. MSB address
212 * is always LSB address+1. reg parameter is the address of LSB register
213 */
Sebastian Reichel168ae302014-03-16 02:43:29 +0100214 ret = twl_i2c_read_u16(TWL4030_MODULE_MADC, &val, reg);
Keerthyf99c1d42011-03-01 19:12:26 +0530215 if (ret) {
Sebastian Reichel168ae302014-03-16 02:43:29 +0100216 dev_err(madc->dev, "unable to read register 0x%X\n", reg);
Keerthyf99c1d42011-03-01 19:12:26 +0530217 return ret;
218 }
219
Sebastian Reichel168ae302014-03-16 02:43:29 +0100220 return (int)(val >> 6);
Keerthyf99c1d42011-03-01 19:12:26 +0530221}
222
223/*
Sebastian Reichel99be0242014-03-16 02:43:27 +0100224 * Return battery temperature in degrees Celsius
Keerthyf99c1d42011-03-01 19:12:26 +0530225 * Or < 0 on failure.
226 */
227static int twl4030battery_temperature(int raw_volt)
228{
229 u8 val;
230 int temp, curr, volt, res, ret;
231
232 volt = (raw_volt * TEMP_STEP_SIZE) / TEMP_PSR_R;
Sebastian Reichel99be0242014-03-16 02:43:27 +0100233 /* Getting and calculating the supply current in micro amperes */
Peter Ujfalusie45342f2012-11-13 09:28:51 +0100234 ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val,
Keerthyf99c1d42011-03-01 19:12:26 +0530235 REG_BCICTL2);
236 if (ret < 0)
237 return ret;
Sebastian Reichel99be0242014-03-16 02:43:27 +0100238
Keerthyf99c1d42011-03-01 19:12:26 +0530239 curr = ((val & TWL4030_BCI_ITHEN) + 1) * 10;
240 /* Getting and calculating the thermistor resistance in ohms */
241 res = volt * 1000 / curr;
242 /* calculating temperature */
243 for (temp = 58; temp >= 0; temp--) {
Sebastian Reichel99be0242014-03-16 02:43:27 +0100244 int actual = twl4030_therm_tbl[temp];
Keerthyf99c1d42011-03-01 19:12:26 +0530245 if ((actual - res) >= 0)
246 break;
247 }
248
249 return temp + 1;
250}
251
252static int twl4030battery_current(int raw_volt)
253{
254 int ret;
255 u8 val;
256
Peter Ujfalusie45342f2012-11-13 09:28:51 +0100257 ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val,
Keerthyf99c1d42011-03-01 19:12:26 +0530258 TWL4030_BCI_BCICTL1);
259 if (ret)
260 return ret;
261 if (val & TWL4030_BCI_CGAIN) /* slope of 0.44 mV/mA */
262 return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R1;
263 else /* slope of 0.88 mV/mA */
264 return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R2;
265}
Sebastian Reichel99be0242014-03-16 02:43:27 +0100266
Keerthyf99c1d42011-03-01 19:12:26 +0530267/*
268 * Function to read channel values
269 * @madc - pointer to twl4030_madc_data struct
270 * @reg_base - Base address of the first channel
Sebastian Reichel99be0242014-03-16 02:43:27 +0100271 * @Channels - 16 bit bitmap. If the bit is set, channel's value is read
Keerthyf99c1d42011-03-01 19:12:26 +0530272 * @buf - The channel values are stored here. if read fails error
Pali Rohára5055d52013-02-15 23:56:49 +0100273 * @raw - Return raw values without conversion
Keerthyf99c1d42011-03-01 19:12:26 +0530274 * value is stored
275 * Returns the number of successfully read channels.
276 */
277static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
278 u8 reg_base, unsigned
Pali Rohára5055d52013-02-15 23:56:49 +0100279 long channels, int *buf,
280 bool raw)
Keerthyf99c1d42011-03-01 19:12:26 +0530281{
Sebastian Reichel99be0242014-03-16 02:43:27 +0100282 int count = 0;
283 int i;
Keerthyf99c1d42011-03-01 19:12:26 +0530284 u8 reg;
285
286 for_each_set_bit(i, &channels, TWL4030_MADC_MAX_CHANNELS) {
Sebastian Reichel99be0242014-03-16 02:43:27 +0100287 reg = reg_base + (2 * i);
Keerthyf99c1d42011-03-01 19:12:26 +0530288 buf[i] = twl4030_madc_channel_raw_read(madc, reg);
289 if (buf[i] < 0) {
Sebastian Reichel99be0242014-03-16 02:43:27 +0100290 dev_err(madc->dev, "Unable to read register 0x%X\n",
291 reg);
292 return buf[i];
Keerthyf99c1d42011-03-01 19:12:26 +0530293 }
Pali Rohára5055d52013-02-15 23:56:49 +0100294 if (raw) {
295 count++;
296 continue;
297 }
Keerthyf99c1d42011-03-01 19:12:26 +0530298 switch (i) {
299 case 10:
300 buf[i] = twl4030battery_current(buf[i]);
301 if (buf[i] < 0) {
302 dev_err(madc->dev, "err reading current\n");
Sebastian Reichel99be0242014-03-16 02:43:27 +0100303 return buf[i];
Keerthyf99c1d42011-03-01 19:12:26 +0530304 } else {
305 count++;
306 buf[i] = buf[i] - 750;
307 }
308 break;
309 case 1:
310 buf[i] = twl4030battery_temperature(buf[i]);
311 if (buf[i] < 0) {
312 dev_err(madc->dev, "err reading temperature\n");
Sebastian Reichel99be0242014-03-16 02:43:27 +0100313 return buf[i];
Keerthyf99c1d42011-03-01 19:12:26 +0530314 } else {
315 buf[i] -= 3;
316 count++;
317 }
318 break;
319 default:
320 count++;
321 /* Analog Input (V) = conv_result * step_size / R
322 * conv_result = decimal value of 10-bit conversion
323 * result
324 * step size = 1.5 / (2 ^ 10 -1)
325 * R = Prescaler ratio for input channels.
326 * Result given in mV hence multiplied by 1000.
327 */
328 buf[i] = (buf[i] * 3 * 1000 *
329 twl4030_divider_ratios[i].denominator)
330 / (2 * 1023 *
331 twl4030_divider_ratios[i].numerator);
332 }
333 }
Keerthyf99c1d42011-03-01 19:12:26 +0530334
335 return count;
336}
337
338/*
339 * Enables irq.
340 * @madc - pointer to twl4030_madc_data struct
341 * @id - irq number to be enabled
342 * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
343 * corresponding to RT, SW1, SW2 conversion requests.
344 * If the i2c read fails it returns an error else returns 0.
345 */
346static int twl4030_madc_enable_irq(struct twl4030_madc_data *madc, u8 id)
347{
348 u8 val;
349 int ret;
350
351 ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
352 if (ret) {
353 dev_err(madc->dev, "unable to read imr register 0x%X\n",
354 madc->imr);
355 return ret;
356 }
Sebastian Reichel99be0242014-03-16 02:43:27 +0100357
Keerthyf99c1d42011-03-01 19:12:26 +0530358 val &= ~(1 << id);
359 ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
360 if (ret) {
361 dev_err(madc->dev,
362 "unable to write imr register 0x%X\n", madc->imr);
363 return ret;
Keerthyf99c1d42011-03-01 19:12:26 +0530364 }
365
366 return 0;
367}
368
369/*
370 * Disables irq.
371 * @madc - pointer to twl4030_madc_data struct
372 * @id - irq number to be disabled
373 * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
374 * corresponding to RT, SW1, SW2 conversion requests.
375 * Returns error if i2c read/write fails.
376 */
377static int twl4030_madc_disable_irq(struct twl4030_madc_data *madc, u8 id)
378{
379 u8 val;
380 int ret;
381
382 ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
383 if (ret) {
384 dev_err(madc->dev, "unable to read imr register 0x%X\n",
385 madc->imr);
386 return ret;
387 }
388 val |= (1 << id);
389 ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
390 if (ret) {
391 dev_err(madc->dev,
392 "unable to write imr register 0x%X\n", madc->imr);
393 return ret;
394 }
395
396 return 0;
397}
398
399static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
400{
401 struct twl4030_madc_data *madc = _madc;
402 const struct twl4030_madc_conversion_method *method;
403 u8 isr_val, imr_val;
404 int i, len, ret;
405 struct twl4030_madc_request *r;
406
407 mutex_lock(&madc->lock);
408 ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &isr_val, madc->isr);
409 if (ret) {
410 dev_err(madc->dev, "unable to read isr register 0x%X\n",
411 madc->isr);
412 goto err_i2c;
413 }
414 ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &imr_val, madc->imr);
415 if (ret) {
416 dev_err(madc->dev, "unable to read imr register 0x%X\n",
417 madc->imr);
418 goto err_i2c;
419 }
420 isr_val &= ~imr_val;
421 for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
422 if (!(isr_val & (1 << i)))
423 continue;
424 ret = twl4030_madc_disable_irq(madc, i);
425 if (ret < 0)
Sebastian Reichel99be0242014-03-16 02:43:27 +0100426 dev_dbg(madc->dev, "Disable interrupt failed %d\n", i);
Keerthyf99c1d42011-03-01 19:12:26 +0530427 madc->requests[i].result_pending = 1;
428 }
429 for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
430 r = &madc->requests[i];
431 /* No pending results for this method, move to next one */
432 if (!r->result_pending)
433 continue;
434 method = &twl4030_conversion_methods[r->method];
435 /* Read results */
436 len = twl4030_madc_read_channels(madc, method->rbase,
Pali Rohára5055d52013-02-15 23:56:49 +0100437 r->channels, r->rbuf, r->raw);
Keerthyf99c1d42011-03-01 19:12:26 +0530438 /* Return results to caller */
439 if (r->func_cb != NULL) {
440 r->func_cb(len, r->channels, r->rbuf);
441 r->func_cb = NULL;
442 }
443 /* Free request */
444 r->result_pending = 0;
445 r->active = 0;
446 }
447 mutex_unlock(&madc->lock);
448
449 return IRQ_HANDLED;
450
451err_i2c:
452 /*
453 * In case of error check whichever request is active
454 * and service the same.
455 */
456 for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
457 r = &madc->requests[i];
458 if (r->active == 0)
459 continue;
460 method = &twl4030_conversion_methods[r->method];
461 /* Read results */
462 len = twl4030_madc_read_channels(madc, method->rbase,
Pali Rohára5055d52013-02-15 23:56:49 +0100463 r->channels, r->rbuf, r->raw);
Keerthyf99c1d42011-03-01 19:12:26 +0530464 /* Return results to caller */
465 if (r->func_cb != NULL) {
466 r->func_cb(len, r->channels, r->rbuf);
467 r->func_cb = NULL;
468 }
469 /* Free request */
470 r->result_pending = 0;
471 r->active = 0;
472 }
473 mutex_unlock(&madc->lock);
474
475 return IRQ_HANDLED;
476}
477
478static int twl4030_madc_set_irq(struct twl4030_madc_data *madc,
479 struct twl4030_madc_request *req)
480{
481 struct twl4030_madc_request *p;
482 int ret;
483
484 p = &madc->requests[req->method];
485 memcpy(p, req, sizeof(*req));
486 ret = twl4030_madc_enable_irq(madc, req->method);
487 if (ret < 0) {
488 dev_err(madc->dev, "enable irq failed!!\n");
489 return ret;
490 }
491
492 return 0;
493}
494
495/*
496 * Function which enables the madc conversion
497 * by writing to the control register.
498 * @madc - pointer to twl4030_madc_data struct
499 * @conv_method - can be TWL4030_MADC_RT, TWL4030_MADC_SW2, TWL4030_MADC_SW1
500 * corresponding to RT SW1 or SW2 conversion methods.
501 * Returns 0 if succeeds else a negative error value
502 */
503static int twl4030_madc_start_conversion(struct twl4030_madc_data *madc,
504 int conv_method)
505{
506 const struct twl4030_madc_conversion_method *method;
507 int ret = 0;
Sebastian Reichel99be0242014-03-16 02:43:27 +0100508
509 if (conv_method != TWL4030_MADC_SW1 && conv_method != TWL4030_MADC_SW2)
510 return -ENOTSUPP;
511
Keerthyf99c1d42011-03-01 19:12:26 +0530512 method = &twl4030_conversion_methods[conv_method];
Sebastian Reichel99be0242014-03-16 02:43:27 +0100513 ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, TWL4030_MADC_SW_START,
514 method->ctrl);
515 if (ret) {
516 dev_err(madc->dev, "unable to write ctrl register 0x%X\n",
517 method->ctrl);
518 return ret;
Keerthyf99c1d42011-03-01 19:12:26 +0530519 }
520
521 return 0;
522}
523
524/*
525 * Function that waits for conversion to be ready
526 * @madc - pointer to twl4030_madc_data struct
527 * @timeout_ms - timeout value in milliseconds
528 * @status_reg - ctrl register
529 * returns 0 if succeeds else a negative error value
530 */
531static int twl4030_madc_wait_conversion_ready(struct twl4030_madc_data *madc,
532 unsigned int timeout_ms,
533 u8 status_reg)
534{
535 unsigned long timeout;
536 int ret;
537
538 timeout = jiffies + msecs_to_jiffies(timeout_ms);
539 do {
540 u8 reg;
541
542 ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &reg, status_reg);
543 if (ret) {
544 dev_err(madc->dev,
545 "unable to read status register 0x%X\n",
546 status_reg);
547 return ret;
548 }
549 if (!(reg & TWL4030_MADC_BUSY) && (reg & TWL4030_MADC_EOC_SW))
550 return 0;
551 usleep_range(500, 2000);
552 } while (!time_after(jiffies, timeout));
553 dev_err(madc->dev, "conversion timeout!\n");
554
555 return -EAGAIN;
556}
557
558/*
559 * An exported function which can be called from other kernel drivers.
560 * @req twl4030_madc_request structure
561 * req->rbuf will be filled with read values of channels based on the
562 * channel index. If a particular channel reading fails there will
563 * be a negative error value in the corresponding array element.
564 * returns 0 if succeeds else error value
565 */
566int twl4030_madc_conversion(struct twl4030_madc_request *req)
567{
568 const struct twl4030_madc_conversion_method *method;
Keerthyf99c1d42011-03-01 19:12:26 +0530569 int ret;
570
Kyle Mannad0e84ca2011-08-11 22:33:14 -0500571 if (!req || !twl4030_madc)
Keerthyf99c1d42011-03-01 19:12:26 +0530572 return -EINVAL;
Kyle Mannad0e84ca2011-08-11 22:33:14 -0500573
Keerthyf99c1d42011-03-01 19:12:26 +0530574 mutex_lock(&twl4030_madc->lock);
575 if (req->method < TWL4030_MADC_RT || req->method > TWL4030_MADC_SW2) {
576 ret = -EINVAL;
577 goto out;
578 }
579 /* Do we have a conversion request ongoing */
580 if (twl4030_madc->requests[req->method].active) {
581 ret = -EBUSY;
582 goto out;
583 }
Keerthyf99c1d42011-03-01 19:12:26 +0530584 method = &twl4030_conversion_methods[req->method];
585 /* Select channels to be converted */
Sebastian Reichel168ae302014-03-16 02:43:29 +0100586 ret = twl_i2c_write_u16(TWL4030_MODULE_MADC, req->channels, method->sel);
Keerthyf99c1d42011-03-01 19:12:26 +0530587 if (ret) {
588 dev_err(twl4030_madc->dev,
Sebastian Reichel168ae302014-03-16 02:43:29 +0100589 "unable to write sel register 0x%X\n", method->sel);
Sanjeev Premie178ccb2011-07-11 20:50:31 +0530590 goto out;
Keerthyf99c1d42011-03-01 19:12:26 +0530591 }
592 /* Select averaging for all channels if do_avg is set */
593 if (req->do_avg) {
Sebastian Reichel168ae302014-03-16 02:43:29 +0100594 ret = twl_i2c_write_u16(TWL4030_MODULE_MADC, req->channels,
595 method->avg);
Keerthyf99c1d42011-03-01 19:12:26 +0530596 if (ret) {
597 dev_err(twl4030_madc->dev,
598 "unable to write avg register 0x%X\n",
Sebastian Reichel99be0242014-03-16 02:43:27 +0100599 method->avg);
Sanjeev Premie178ccb2011-07-11 20:50:31 +0530600 goto out;
Keerthyf99c1d42011-03-01 19:12:26 +0530601 }
602 }
603 if (req->type == TWL4030_MADC_IRQ_ONESHOT && req->func_cb != NULL) {
604 ret = twl4030_madc_set_irq(twl4030_madc, req);
605 if (ret < 0)
606 goto out;
607 ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
608 if (ret < 0)
609 goto out;
610 twl4030_madc->requests[req->method].active = 1;
611 ret = 0;
612 goto out;
613 }
614 /* With RT method we should not be here anymore */
615 if (req->method == TWL4030_MADC_RT) {
616 ret = -EINVAL;
617 goto out;
618 }
619 ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
620 if (ret < 0)
621 goto out;
622 twl4030_madc->requests[req->method].active = 1;
623 /* Wait until conversion is ready (ctrl register returns EOC) */
624 ret = twl4030_madc_wait_conversion_ready(twl4030_madc, 5, method->ctrl);
625 if (ret) {
626 twl4030_madc->requests[req->method].active = 0;
627 goto out;
628 }
629 ret = twl4030_madc_read_channels(twl4030_madc, method->rbase,
Pali Rohára5055d52013-02-15 23:56:49 +0100630 req->channels, req->rbuf, req->raw);
Keerthyf99c1d42011-03-01 19:12:26 +0530631 twl4030_madc->requests[req->method].active = 0;
632
633out:
634 mutex_unlock(&twl4030_madc->lock);
635
636 return ret;
637}
638EXPORT_SYMBOL_GPL(twl4030_madc_conversion);
639
Keerthyf99c1d42011-03-01 19:12:26 +0530640int twl4030_get_madc_conversion(int channel_no)
641{
642 struct twl4030_madc_request req;
643 int temp = 0;
644 int ret;
645
646 req.channels = (1 << channel_no);
647 req.method = TWL4030_MADC_SW2;
648 req.active = 0;
649 req.func_cb = NULL;
650 ret = twl4030_madc_conversion(&req);
651 if (ret < 0)
652 return ret;
653 if (req.rbuf[channel_no] > 0)
654 temp = req.rbuf[channel_no];
655
656 return temp;
657}
658EXPORT_SYMBOL_GPL(twl4030_get_madc_conversion);
659
Sebastian Reichel99be0242014-03-16 02:43:27 +0100660/**
661 * twl4030_madc_set_current_generator() - setup bias current
662 *
663 * @madc: pointer to twl4030_madc_data struct
664 * @chan: can be one of the two values:
665 * TWL4030_BCI_ITHEN
666 * Enables bias current for main battery type reading
667 * TWL4030_BCI_TYPEN
668 * Enables bias current for main battery temperature sensing
669 * @on: enable or disable chan.
670 *
Keerthyf99c1d42011-03-01 19:12:26 +0530671 * Function to enable or disable bias current for
672 * main battery type reading or temperature sensing
Keerthyf99c1d42011-03-01 19:12:26 +0530673 */
674static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
675 int chan, int on)
676{
677 int ret;
Sebastian Reichel99be0242014-03-16 02:43:27 +0100678 int regmask;
Keerthyf99c1d42011-03-01 19:12:26 +0530679 u8 regval;
680
Peter Ujfalusie45342f2012-11-13 09:28:51 +0100681 ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
Keerthyf99c1d42011-03-01 19:12:26 +0530682 &regval, TWL4030_BCI_BCICTL1);
683 if (ret) {
684 dev_err(madc->dev, "unable to read BCICTL1 reg 0x%X",
685 TWL4030_BCI_BCICTL1);
686 return ret;
687 }
Sebastian Reichel99be0242014-03-16 02:43:27 +0100688
689 regmask = chan ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN;
Keerthyf99c1d42011-03-01 19:12:26 +0530690 if (on)
Sebastian Reichel99be0242014-03-16 02:43:27 +0100691 regval |= regmask;
Keerthyf99c1d42011-03-01 19:12:26 +0530692 else
Sebastian Reichel99be0242014-03-16 02:43:27 +0100693 regval &= ~regmask;
694
Peter Ujfalusie45342f2012-11-13 09:28:51 +0100695 ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
Keerthyf99c1d42011-03-01 19:12:26 +0530696 regval, TWL4030_BCI_BCICTL1);
697 if (ret) {
698 dev_err(madc->dev, "unable to write BCICTL1 reg 0x%X\n",
699 TWL4030_BCI_BCICTL1);
700 return ret;
701 }
702
703 return 0;
704}
705
706/*
707 * Function that sets MADC software power on bit to enable MADC
708 * @madc - pointer to twl4030_madc_data struct
Sebastian Reichel99be0242014-03-16 02:43:27 +0100709 * @on - Enable or disable MADC software power on bit.
Keerthyf99c1d42011-03-01 19:12:26 +0530710 * returns error if i2c read/write fails else 0
711 */
712static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
713{
714 u8 regval;
715 int ret;
716
Peter Ujfalusie45342f2012-11-13 09:28:51 +0100717 ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
Keerthyf99c1d42011-03-01 19:12:26 +0530718 &regval, TWL4030_MADC_CTRL1);
719 if (ret) {
720 dev_err(madc->dev, "unable to read madc ctrl1 reg 0x%X\n",
721 TWL4030_MADC_CTRL1);
722 return ret;
723 }
724 if (on)
725 regval |= TWL4030_MADC_MADCON;
726 else
727 regval &= ~TWL4030_MADC_MADCON;
728 ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, regval, TWL4030_MADC_CTRL1);
729 if (ret) {
730 dev_err(madc->dev, "unable to write madc ctrl1 reg 0x%X\n",
731 TWL4030_MADC_CTRL1);
732 return ret;
733 }
734
735 return 0;
736}
737
738/*
739 * Initialize MADC and request for threaded irq
740 */
Bill Pembertonf791be42012-11-19 13:23:04 -0500741static int twl4030_madc_probe(struct platform_device *pdev)
Keerthyf99c1d42011-03-01 19:12:26 +0530742{
743 struct twl4030_madc_data *madc;
Jingoo Han334a41c2013-07-30 17:10:05 +0900744 struct twl4030_madc_platform_data *pdata = dev_get_platdata(&pdev->dev);
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100745 struct device_node *np = pdev->dev.of_node;
Sebastian Reichele7f22b72014-03-16 02:43:25 +0100746 int irq, ret;
Keerthyf99c1d42011-03-01 19:12:26 +0530747 u8 regval;
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100748 struct iio_dev *iio_dev = NULL;
Keerthyf99c1d42011-03-01 19:12:26 +0530749
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100750 if (!pdata && !np) {
751 dev_err(&pdev->dev, "neither platform data nor Device Tree node available\n");
Keerthyf99c1d42011-03-01 19:12:26 +0530752 return -EINVAL;
753 }
Keerthyf99c1d42011-03-01 19:12:26 +0530754
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100755 iio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*madc));
756 if (!iio_dev) {
757 dev_err(&pdev->dev, "failed allocating iio device\n");
758 return -ENOMEM;
759 }
760
761 madc = iio_priv(iio_dev);
Kyle Manna66cc5b82011-08-11 22:33:12 -0500762 madc->dev = &pdev->dev;
763
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100764 iio_dev->name = dev_name(&pdev->dev);
765 iio_dev->dev.parent = &pdev->dev;
766 iio_dev->dev.of_node = pdev->dev.of_node;
767 iio_dev->info = &twl4030_madc_iio_info;
768 iio_dev->modes = INDIO_DIRECT_MODE;
769 iio_dev->channels = twl4030_madc_iio_channels;
770 iio_dev->num_channels = ARRAY_SIZE(twl4030_madc_iio_channels);
771
Keerthyf99c1d42011-03-01 19:12:26 +0530772 /*
773 * Phoenix provides 2 interrupt lines. The first one is connected to
774 * the OMAP. The other one can be connected to the other processor such
775 * as modem. Hence two separate ISR and IMR registers.
776 */
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100777 if (pdata)
778 madc->use_second_irq = (pdata->irq_line != 1);
779 else
780 madc->use_second_irq = of_property_read_bool(np,
781 "ti,system-uses-second-madc-irq");
782
783 madc->imr = madc->use_second_irq ? TWL4030_MADC_IMR2 :
784 TWL4030_MADC_IMR1;
785 madc->isr = madc->use_second_irq ? TWL4030_MADC_ISR2 :
786 TWL4030_MADC_ISR1;
787
Keerthyf99c1d42011-03-01 19:12:26 +0530788 ret = twl4030_madc_set_power(madc, 1);
789 if (ret < 0)
Sebastian Reichele7f22b72014-03-16 02:43:25 +0100790 return ret;
Keerthyf99c1d42011-03-01 19:12:26 +0530791 ret = twl4030_madc_set_current_generator(madc, 0, 1);
792 if (ret < 0)
793 goto err_current_generator;
794
Peter Ujfalusie45342f2012-11-13 09:28:51 +0100795 ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
Keerthyf99c1d42011-03-01 19:12:26 +0530796 &regval, TWL4030_BCI_BCICTL1);
797 if (ret) {
798 dev_err(&pdev->dev, "unable to read reg BCI CTL1 0x%X\n",
799 TWL4030_BCI_BCICTL1);
800 goto err_i2c;
801 }
802 regval |= TWL4030_BCI_MESBAT;
Peter Ujfalusie45342f2012-11-13 09:28:51 +0100803 ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
Keerthyf99c1d42011-03-01 19:12:26 +0530804 regval, TWL4030_BCI_BCICTL1);
805 if (ret) {
806 dev_err(&pdev->dev, "unable to write reg BCI Ctl1 0x%X\n",
807 TWL4030_BCI_BCICTL1);
808 goto err_i2c;
809 }
Kyle Manna3d6271f2011-08-11 22:33:13 -0500810
811 /* Check that MADC clock is on */
812 ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &regval, TWL4030_REG_GPBR1);
813 if (ret) {
814 dev_err(&pdev->dev, "unable to read reg GPBR1 0x%X\n",
815 TWL4030_REG_GPBR1);
816 goto err_i2c;
817 }
818
819 /* If MADC clk is not on, turn it on */
820 if (!(regval & TWL4030_GPBR1_MADC_HFCLK_EN)) {
821 dev_info(&pdev->dev, "clk disabled, enabling\n");
822 regval |= TWL4030_GPBR1_MADC_HFCLK_EN;
823 ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, regval,
824 TWL4030_REG_GPBR1);
825 if (ret) {
826 dev_err(&pdev->dev, "unable to write reg GPBR1 0x%X\n",
827 TWL4030_REG_GPBR1);
828 goto err_i2c;
829 }
830 }
831
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100832 platform_set_drvdata(pdev, iio_dev);
Keerthyf99c1d42011-03-01 19:12:26 +0530833 mutex_init(&madc->lock);
Sebastian Reichele7f22b72014-03-16 02:43:25 +0100834
835 irq = platform_get_irq(pdev, 0);
836 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
Keerthyf99c1d42011-03-01 19:12:26 +0530837 twl4030_madc_threaded_irq_handler,
838 IRQF_TRIGGER_RISING, "twl4030_madc", madc);
839 if (ret) {
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100840 dev_err(&pdev->dev, "could not request irq\n");
Jingoo Hanc3d6a0a2013-05-06 13:08:08 +0900841 goto err_i2c;
Keerthyf99c1d42011-03-01 19:12:26 +0530842 }
843 twl4030_madc = madc;
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100844
845 ret = iio_device_register(iio_dev);
846 if (ret) {
847 dev_err(&pdev->dev, "could not register iio device\n");
848 goto err_i2c;
849 }
850
Keerthyf99c1d42011-03-01 19:12:26 +0530851 return 0;
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100852
Keerthyf99c1d42011-03-01 19:12:26 +0530853err_i2c:
854 twl4030_madc_set_current_generator(madc, 0, 0);
855err_current_generator:
856 twl4030_madc_set_power(madc, 0);
Keerthyf99c1d42011-03-01 19:12:26 +0530857 return ret;
858}
859
Bill Pemberton4740f732012-11-19 13:26:01 -0500860static int twl4030_madc_remove(struct platform_device *pdev)
Keerthyf99c1d42011-03-01 19:12:26 +0530861{
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100862 struct iio_dev *iio_dev = platform_get_drvdata(pdev);
863 struct twl4030_madc_data *madc = iio_priv(iio_dev);
864
865 iio_device_unregister(iio_dev);
Keerthyf99c1d42011-03-01 19:12:26 +0530866
Keerthyf99c1d42011-03-01 19:12:26 +0530867 twl4030_madc_set_current_generator(madc, 0, 0);
868 twl4030_madc_set_power(madc, 0);
Keerthyf99c1d42011-03-01 19:12:26 +0530869
870 return 0;
871}
872
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100873#ifdef CONFIG_OF
874static const struct of_device_id twl_madc_of_match[] = {
875 { .compatible = "ti,twl4030-madc", },
876 { },
877};
878MODULE_DEVICE_TABLE(of, twl_madc_of_match);
879#endif
880
Keerthyf99c1d42011-03-01 19:12:26 +0530881static struct platform_driver twl4030_madc_driver = {
882 .probe = twl4030_madc_probe,
Arnd Bergmann03715412013-03-14 22:56:38 +0100883 .remove = twl4030_madc_remove,
Keerthyf99c1d42011-03-01 19:12:26 +0530884 .driver = {
885 .name = "twl4030_madc",
886 .owner = THIS_MODULE,
Sebastian Reichel2f39b702014-03-16 02:43:26 +0100887 .of_match_table = of_match_ptr(twl_madc_of_match),
Sebastian Reichel99be0242014-03-16 02:43:27 +0100888 },
Keerthyf99c1d42011-03-01 19:12:26 +0530889};
890
Mark Brown65349d62011-11-23 22:58:34 +0000891module_platform_driver(twl4030_madc_driver);
Keerthyf99c1d42011-03-01 19:12:26 +0530892
893MODULE_DESCRIPTION("TWL4030 ADC driver");
894MODULE_LICENSE("GPL");
895MODULE_AUTHOR("J Keerthy");
Axel Lin0ea3e832011-03-07 11:02:29 +0800896MODULE_ALIAS("platform:twl4030_madc");