aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio/adc
diff options
context:
space:
mode:
authorSebastian Reichel <sre@debian.org>2014-03-15 21:43:31 -0400
committerLee Jones <lee.jones@linaro.org>2014-03-18 04:16:20 -0400
commitb2931b98cebfb30d940f248d2054b5268eae87a4 (patch)
treefcd1422ed3fc3aff3c04d60b84c89511eeae1f02 /drivers/iio/adc
parent1e1bce3956ab888d1627080eb85c5019f2adf955 (diff)
mfd: twl4030-madc: Move driver to drivers/iio/adc
This is a driver for an A/D converter, which belongs into drivers/iio/adc. Signed-off-by: Sebastian Reichel <sre@debian.org> Acked-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers/iio/adc')
-rw-r--r--drivers/iio/adc/Kconfig10
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/twl4030-madc.c896
3 files changed, 907 insertions, 0 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 2209f28441e9..427f75c4f69e 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -183,6 +183,16 @@ config TI_AM335X_ADC
183 Say yes here to build support for Texas Instruments ADC 183 Say yes here to build support for Texas Instruments ADC
184 driver which is also a MFD client. 184 driver which is also a MFD client.
185 185
186config TWL4030_MADC
187 tristate "TWL4030 MADC (Monitoring A/D Converter)"
188 depends on TWL4030_CORE
189 help
190 This driver provides support for Triton TWL4030-MADC. The
191 driver supports both RT and SW conversion methods.
192
193 This driver can also be built as a module. If so, the module will be
194 called twl4030-madc.
195
186config TWL6030_GPADC 196config TWL6030_GPADC
187 tristate "TWL6030 GPADC (General Purpose A/D Converter) Support" 197 tristate "TWL6030 GPADC (General Purpose A/D Converter) Support"
188 depends on TWL4030_CORE 198 depends on TWL4030_CORE
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index ba9a10a24cd0..9acf2df2c1a8 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -20,5 +20,6 @@ obj-$(CONFIG_MCP3422) += mcp3422.o
20obj-$(CONFIG_NAU7802) += nau7802.o 20obj-$(CONFIG_NAU7802) += nau7802.o
21obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o 21obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
22obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o 22obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
23obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
23obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o 24obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
24obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o 25obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c
new file mode 100644
index 000000000000..8a014fbb98bc
--- /dev/null
+++ b/drivers/iio/adc/twl4030-madc.c
@@ -0,0 +1,896 @@
1/*
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
50#include <linux/iio/iio.h>
51
52/**
53 * struct twl4030_madc_data - a container for madc info
54 * @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
60 */
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];
65 bool use_second_irq;
66 u8 imr;
67 u8 isr;
68};
69
70static 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
130static 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
158/* 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
168};
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
199/**
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.
205 */
206static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 reg)
207{
208 u16 val;
209 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 */
214 ret = twl_i2c_read_u16(TWL4030_MODULE_MADC, &val, reg);
215 if (ret) {
216 dev_err(madc->dev, "unable to read register 0x%X\n", reg);
217 return ret;
218 }
219
220 return (int)(val >> 6);
221}
222
223/*
224 * Return battery temperature in degrees Celsius
225 * 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;
233 /* Getting and calculating the supply current in micro amperes */
234 ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val,
235 REG_BCICTL2);
236 if (ret < 0)
237 return ret;
238
239 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--) {
244 int actual = twl4030_therm_tbl[temp];
245 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
257 ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val,
258 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}
266
267/*
268 * Function to read channel values
269 * @madc - pointer to twl4030_madc_data struct
270 * @reg_base - Base address of the first channel
271 * @Channels - 16 bit bitmap. If the bit is set, channel's value is read
272 * @buf - The channel values are stored here. if read fails error
273 * @raw - Return raw values without conversion
274 * 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
279 long channels, int *buf,
280 bool raw)
281{
282 int count = 0;
283 int i;
284 u8 reg;
285
286 for_each_set_bit(i, &channels, TWL4030_MADC_MAX_CHANNELS) {
287 reg = reg_base + (2 * i);
288 buf[i] = twl4030_madc_channel_raw_read(madc, reg);
289 if (buf[i] < 0) {
290 dev_err(madc->dev, "Unable to read register 0x%X\n",
291 reg);
292 return buf[i];
293 }
294 if (raw) {
295 count++;
296 continue;
297 }
298 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");
303 return buf[i];
304 } 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");
313 return buf[i];
314 } 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 }
334
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 }
357
358 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;
364 }
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)
426 dev_dbg(madc->dev, "Disable interrupt failed %d\n", i);
427 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,
437 r->channels, r->rbuf, r->raw);
438 /* 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,
463 r->channels, r->rbuf, r->raw);
464 /* 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;
508
509 if (conv_method != TWL4030_MADC_SW1 && conv_method != TWL4030_MADC_SW2)
510 return -ENOTSUPP;
511
512 method = &twl4030_conversion_methods[conv_method];
513 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;
519 }
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;
569 int ret;
570
571 if (!req || !twl4030_madc)
572 return -EINVAL;
573
574 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 }
584 method = &twl4030_conversion_methods[req->method];
585 /* Select channels to be converted */
586 ret = twl_i2c_write_u16(TWL4030_MODULE_MADC, req->channels, method->sel);
587 if (ret) {
588 dev_err(twl4030_madc->dev,
589 "unable to write sel register 0x%X\n", method->sel);
590 goto out;
591 }
592 /* Select averaging for all channels if do_avg is set */
593 if (req->do_avg) {
594 ret = twl_i2c_write_u16(TWL4030_MODULE_MADC, req->channels,
595 method->avg);
596 if (ret) {
597 dev_err(twl4030_madc->dev,
598 "unable to write avg register 0x%X\n",
599 method->avg);
600 goto out;
601 }
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,
630 req->channels, req->rbuf, req->raw);
631 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
640int 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
660/**
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 *
671 * Function to enable or disable bias current for
672 * main battery type reading or temperature sensing
673 */
674static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
675 int chan, int on)
676{
677 int ret;
678 int regmask;
679 u8 regval;
680
681 ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
682 &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 }
688
689 regmask = chan ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN;
690 if (on)
691 regval |= regmask;
692 else
693 regval &= ~regmask;
694
695 ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
696 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
709 * @on - Enable or disable MADC software power on bit.
710 * 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
717 ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
718 &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 */
741static int twl4030_madc_probe(struct platform_device *pdev)
742{
743 struct twl4030_madc_data *madc;
744 struct twl4030_madc_platform_data *pdata = dev_get_platdata(&pdev->dev);
745 struct device_node *np = pdev->dev.of_node;
746 int irq, ret;
747 u8 regval;
748 struct iio_dev *iio_dev = NULL;
749
750 if (!pdata && !np) {
751 dev_err(&pdev->dev, "neither platform data nor Device Tree node available\n");
752 return -EINVAL;
753 }
754
755 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);
762 madc->dev = &pdev->dev;
763
764 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
772 /*
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 */
777 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
788 ret = twl4030_madc_set_power(madc, 1);
789 if (ret < 0)
790 return ret;
791 ret = twl4030_madc_set_current_generator(madc, 0, 1);
792 if (ret < 0)
793 goto err_current_generator;
794
795 ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
796 &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;
803 ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
804 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 }
810
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
832 platform_set_drvdata(pdev, iio_dev);
833 mutex_init(&madc->lock);
834
835 irq = platform_get_irq(pdev, 0);
836 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
837 twl4030_madc_threaded_irq_handler,
838 IRQF_TRIGGER_RISING, "twl4030_madc", madc);
839 if (ret) {
840 dev_err(&pdev->dev, "could not request irq\n");
841 goto err_i2c;
842 }
843 twl4030_madc = madc;
844
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
851 return 0;
852
853err_i2c:
854 twl4030_madc_set_current_generator(madc, 0, 0);
855err_current_generator:
856 twl4030_madc_set_power(madc, 0);
857 return ret;
858}
859
860static int twl4030_madc_remove(struct platform_device *pdev)
861{
862 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);
866
867 twl4030_madc_set_current_generator(madc, 0, 0);
868 twl4030_madc_set_power(madc, 0);
869
870 return 0;
871}
872
873#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
881static struct platform_driver twl4030_madc_driver = {
882 .probe = twl4030_madc_probe,
883 .remove = twl4030_madc_remove,
884 .driver = {
885 .name = "twl4030_madc",
886 .owner = THIS_MODULE,
887 .of_match_table = of_match_ptr(twl_madc_of_match),
888 },
889};
890
891module_platform_driver(twl4030_madc_driver);
892
893MODULE_DESCRIPTION("TWL4030 ADC driver");
894MODULE_LICENSE("GPL");
895MODULE_AUTHOR("J Keerthy");
896MODULE_ALIAS("platform:twl4030_madc");