aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio
diff options
context:
space:
mode:
authorIvan T. Ivanov <iivanov@mm-sol.com>2014-10-22 10:13:33 -0400
committerJonathan Cameron <jic23@kernel.org>2014-10-25 16:03:22 -0400
commitce0694841ea61607afcbdb5a67bb0b00328357ef (patch)
tree773bf4513d4a036fe63b90c4452eca316c1b3874 /drivers/iio
parente0922e5e3ccb78aa0152e93dfbd1755ac39c8582 (diff)
iio: iadc: Qualcomm SPMI PMIC current ADC driver
The current ADC is peripheral of Qualcomm SPMI PMIC chips. It has 16 bits resolution and register space inside PMIC accessible across SPMI bus. The driver registers itself through IIO interface. Signed-off-by: Ivan T. Ivanov <iivanov@mm-sol.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r--drivers/iio/adc/Kconfig14
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/qcom-spmi-iadc.c595
3 files changed, 610 insertions, 0 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 88bdc8f612e2..d0924f3cfa25 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -206,6 +206,20 @@ config NAU7802
206 To compile this driver as a module, choose M here: the 206 To compile this driver as a module, choose M here: the
207 module will be called nau7802. 207 module will be called nau7802.
208 208
209config QCOM_SPMI_IADC
210 tristate "Qualcomm SPMI PMIC current ADC"
211 depends on SPMI
212 select REGMAP_SPMI
213 help
214 This is the IIO Current ADC driver for Qualcomm QPNP IADC Chip.
215
216 The driver supports single mode operation to read from one of two
217 channels (external or internal). Hardware have additional
218 channels internally used for gain and offset calibration.
219
220 To compile this driver as a module, choose M here: the module will
221 be called qcom-spmi-iadc.
222
209config ROCKCHIP_SARADC 223config ROCKCHIP_SARADC
210 tristate "Rockchip SARADC driver" 224 tristate "Rockchip SARADC driver"
211 depends on ARCH_ROCKCHIP || (ARM && COMPILE_TEST) 225 depends on ARCH_ROCKCHIP || (ARM && COMPILE_TEST)
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index cb88a6a23b8f..c06718b9d8ce 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o
22obj-$(CONFIG_MCP3422) += mcp3422.o 22obj-$(CONFIG_MCP3422) += mcp3422.o
23obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o 23obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
24obj-$(CONFIG_NAU7802) += nau7802.o 24obj-$(CONFIG_NAU7802) += nau7802.o
25obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
25obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o 26obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
26obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o 27obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
27obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o 28obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o
diff --git a/drivers/iio/adc/qcom-spmi-iadc.c b/drivers/iio/adc/qcom-spmi-iadc.c
new file mode 100644
index 000000000000..b9666f2f5e51
--- /dev/null
+++ b/drivers/iio/adc/qcom-spmi-iadc.c
@@ -0,0 +1,595 @@
1/*
2 * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/bitops.h>
15#include <linux/completion.h>
16#include <linux/delay.h>
17#include <linux/err.h>
18#include <linux/iio/iio.h>
19#include <linux/interrupt.h>
20#include <linux/kernel.h>
21#include <linux/mutex.h>
22#include <linux/module.h>
23#include <linux/of.h>
24#include <linux/of_device.h>
25#include <linux/platform_device.h>
26#include <linux/regmap.h>
27#include <linux/slab.h>
28
29/* IADC register and bit definition */
30#define IADC_REVISION2 0x1
31#define IADC_REVISION2_SUPPORTED_IADC 1
32
33#define IADC_PERPH_TYPE 0x4
34#define IADC_PERPH_TYPE_ADC 8
35
36#define IADC_PERPH_SUBTYPE 0x5
37#define IADC_PERPH_SUBTYPE_IADC 3
38
39#define IADC_STATUS1 0x8
40#define IADC_STATUS1_OP_MODE 4
41#define IADC_STATUS1_REQ_STS BIT(1)
42#define IADC_STATUS1_EOC BIT(0)
43#define IADC_STATUS1_REQ_STS_EOC_MASK 0x3
44
45#define IADC_MODE_CTL 0x40
46#define IADC_OP_MODE_SHIFT 3
47#define IADC_OP_MODE_NORMAL 0
48#define IADC_TRIM_EN BIT(0)
49
50#define IADC_EN_CTL1 0x46
51#define IADC_EN_CTL1_SET BIT(7)
52
53#define IADC_CH_SEL_CTL 0x48
54
55#define IADC_DIG_PARAM 0x50
56#define IADC_DIG_DEC_RATIO_SEL_SHIFT 2
57
58#define IADC_HW_SETTLE_DELAY 0x51
59
60#define IADC_CONV_REQ 0x52
61#define IADC_CONV_REQ_SET BIT(7)
62
63#define IADC_FAST_AVG_CTL 0x5a
64#define IADC_FAST_AVG_EN 0x5b
65#define IADC_FAST_AVG_EN_SET BIT(7)
66
67#define IADC_PERH_RESET_CTL3 0xda
68#define IADC_FOLLOW_WARM_RB BIT(2)
69
70#define IADC_DATA 0x60 /* 16 bits */
71
72#define IADC_SEC_ACCESS 0xd0
73#define IADC_SEC_ACCESS_DATA 0xa5
74
75#define IADC_NOMINAL_RSENSE 0xf4
76#define IADC_NOMINAL_RSENSE_SIGN_MASK BIT(7)
77
78#define IADC_REF_GAIN_MICRO_VOLTS 17857
79
80#define IADC_INT_RSENSE_DEVIATION 15625 /* nano Ohms per bit */
81
82#define IADC_INT_RSENSE_IDEAL_VALUE 10000 /* micro Ohms */
83#define IADC_INT_RSENSE_DEFAULT_VALUE 7800 /* micro Ohms */
84#define IADC_INT_RSENSE_DEFAULT_GF 9000 /* micro Ohms */
85#define IADC_INT_RSENSE_DEFAULT_SMIC 9700 /* micro Ohms */
86
87#define IADC_CONV_TIME_MIN_US 2000
88#define IADC_CONV_TIME_MAX_US 2100
89
90#define IADC_DEF_PRESCALING 0 /* 1:1 */
91#define IADC_DEF_DECIMATION 0 /* 512 */
92#define IADC_DEF_HW_SETTLE_TIME 0 /* 0 us */
93#define IADC_DEF_AVG_SAMPLES 0 /* 1 sample */
94
95/* IADC channel list */
96#define IADC_INT_RSENSE 0
97#define IADC_EXT_RSENSE 1
98#define IADC_GAIN_17P857MV 3
99#define IADC_EXT_OFFSET_CSP_CSN 5
100#define IADC_INT_OFFSET_CSP2_CSN2 6
101
102/**
103 * struct iadc_chip - IADC Current ADC device structure.
104 * @regmap: regmap for register read/write.
105 * @dev: This device pointer.
106 * @base: base offset for the ADC peripheral.
107 * @rsense: Values of the internal and external sense resister in micro Ohms.
108 * @poll_eoc: Poll for end of conversion instead of waiting for IRQ.
109 * @offset: Raw offset values for the internal and external channels.
110 * @gain: Raw gain of the channels.
111 * @lock: ADC lock for access to the peripheral.
112 * @complete: ADC notification after end of conversion interrupt is received.
113 */
114struct iadc_chip {
115 struct regmap *regmap;
116 struct device *dev;
117 u16 base;
118 bool poll_eoc;
119 u32 rsense[2];
120 u16 offset[2];
121 u16 gain;
122 struct mutex lock;
123 struct completion complete;
124};
125
126static int iadc_read(struct iadc_chip *iadc, u16 offset, u8 *data)
127{
128 unsigned int val;
129 int ret;
130
131 ret = regmap_read(iadc->regmap, iadc->base + offset, &val);
132 if (ret < 0)
133 return ret;
134
135 *data = val;
136 return 0;
137}
138
139static int iadc_write(struct iadc_chip *iadc, u16 offset, u8 data)
140{
141 return regmap_write(iadc->regmap, iadc->base + offset, data);
142}
143
144static int iadc_reset(struct iadc_chip *iadc)
145{
146 u8 data;
147 int ret;
148
149 ret = iadc_write(iadc, IADC_SEC_ACCESS, IADC_SEC_ACCESS_DATA);
150 if (ret < 0)
151 return ret;
152
153 ret = iadc_read(iadc, IADC_PERH_RESET_CTL3, &data);
154 if (ret < 0)
155 return ret;
156
157 ret = iadc_write(iadc, IADC_SEC_ACCESS, IADC_SEC_ACCESS_DATA);
158 if (ret < 0)
159 return ret;
160
161 data |= IADC_FOLLOW_WARM_RB;
162
163 return iadc_write(iadc, IADC_PERH_RESET_CTL3, data);
164}
165
166static int iadc_set_state(struct iadc_chip *iadc, bool state)
167{
168 return iadc_write(iadc, IADC_EN_CTL1, state ? IADC_EN_CTL1_SET : 0);
169}
170
171static void iadc_status_show(struct iadc_chip *iadc)
172{
173 u8 mode, sta1, chan, dig, en, req;
174 int ret;
175
176 ret = iadc_read(iadc, IADC_MODE_CTL, &mode);
177 if (ret < 0)
178 return;
179
180 ret = iadc_read(iadc, IADC_DIG_PARAM, &dig);
181 if (ret < 0)
182 return;
183
184 ret = iadc_read(iadc, IADC_CH_SEL_CTL, &chan);
185 if (ret < 0)
186 return;
187
188 ret = iadc_read(iadc, IADC_CONV_REQ, &req);
189 if (ret < 0)
190 return;
191
192 ret = iadc_read(iadc, IADC_STATUS1, &sta1);
193 if (ret < 0)
194 return;
195
196 ret = iadc_read(iadc, IADC_EN_CTL1, &en);
197 if (ret < 0)
198 return;
199
200 dev_err(iadc->dev,
201 "mode:%02x en:%02x chan:%02x dig:%02x req:%02x sta1:%02x\n",
202 mode, en, chan, dig, req, sta1);
203}
204
205static int iadc_configure(struct iadc_chip *iadc, int channel)
206{
207 u8 decim, mode;
208 int ret;
209
210 /* Mode selection */
211 mode = (IADC_OP_MODE_NORMAL << IADC_OP_MODE_SHIFT) | IADC_TRIM_EN;
212 ret = iadc_write(iadc, IADC_MODE_CTL, mode);
213 if (ret < 0)
214 return ret;
215
216 /* Channel selection */
217 ret = iadc_write(iadc, IADC_CH_SEL_CTL, channel);
218 if (ret < 0)
219 return ret;
220
221 /* Digital parameter setup */
222 decim = IADC_DEF_DECIMATION << IADC_DIG_DEC_RATIO_SEL_SHIFT;
223 ret = iadc_write(iadc, IADC_DIG_PARAM, decim);
224 if (ret < 0)
225 return ret;
226
227 /* HW settle time delay */
228 ret = iadc_write(iadc, IADC_HW_SETTLE_DELAY, IADC_DEF_HW_SETTLE_TIME);
229 if (ret < 0)
230 return ret;
231
232 ret = iadc_write(iadc, IADC_FAST_AVG_CTL, IADC_DEF_AVG_SAMPLES);
233 if (ret < 0)
234 return ret;
235
236 if (IADC_DEF_AVG_SAMPLES)
237 ret = iadc_write(iadc, IADC_FAST_AVG_EN, IADC_FAST_AVG_EN_SET);
238 else
239 ret = iadc_write(iadc, IADC_FAST_AVG_EN, 0);
240
241 if (ret < 0)
242 return ret;
243
244 if (!iadc->poll_eoc)
245 reinit_completion(&iadc->complete);
246
247 ret = iadc_set_state(iadc, true);
248 if (ret < 0)
249 return ret;
250
251 /* Request conversion */
252 return iadc_write(iadc, IADC_CONV_REQ, IADC_CONV_REQ_SET);
253}
254
255static int iadc_poll_wait_eoc(struct iadc_chip *iadc, unsigned int interval_us)
256{
257 unsigned int count, retry;
258 int ret;
259 u8 sta1;
260
261 retry = interval_us / IADC_CONV_TIME_MIN_US;
262
263 for (count = 0; count < retry; count++) {
264 ret = iadc_read(iadc, IADC_STATUS1, &sta1);
265 if (ret < 0)
266 return ret;
267
268 sta1 &= IADC_STATUS1_REQ_STS_EOC_MASK;
269 if (sta1 == IADC_STATUS1_EOC)
270 return 0;
271
272 usleep_range(IADC_CONV_TIME_MIN_US, IADC_CONV_TIME_MAX_US);
273 }
274
275 iadc_status_show(iadc);
276
277 return -ETIMEDOUT;
278}
279
280static int iadc_read_result(struct iadc_chip *iadc, u16 *data)
281{
282 return regmap_bulk_read(iadc->regmap, iadc->base + IADC_DATA, data, 2);
283}
284
285static int iadc_do_conversion(struct iadc_chip *iadc, int chan, u16 *data)
286{
287 unsigned int wait;
288 int ret;
289
290 ret = iadc_configure(iadc, chan);
291 if (ret < 0)
292 goto exit;
293
294 wait = BIT(IADC_DEF_AVG_SAMPLES) * IADC_CONV_TIME_MIN_US * 2;
295
296 if (iadc->poll_eoc) {
297 ret = iadc_poll_wait_eoc(iadc, wait);
298 } else {
299 ret = wait_for_completion_timeout(&iadc->complete, wait);
300 if (!ret)
301 ret = -ETIMEDOUT;
302 else
303 /* double check conversion status */
304 ret = iadc_poll_wait_eoc(iadc, IADC_CONV_TIME_MIN_US);
305 }
306
307 if (!ret)
308 ret = iadc_read_result(iadc, data);
309exit:
310 iadc_set_state(iadc, false);
311 if (ret < 0)
312 dev_err(iadc->dev, "conversion failed\n");
313
314 return ret;
315}
316
317static int iadc_read_raw(struct iio_dev *indio_dev,
318 struct iio_chan_spec const *chan,
319 int *val, int *val2, long mask)
320{
321 struct iadc_chip *iadc = iio_priv(indio_dev);
322 s32 isense_ua, vsense_uv;
323 u16 adc_raw, vsense_raw;
324 int ret;
325
326 switch (mask) {
327 case IIO_CHAN_INFO_RAW:
328 mutex_lock(&iadc->lock);
329 ret = iadc_do_conversion(iadc, chan->channel, &adc_raw);
330 mutex_unlock(&iadc->lock);
331 if (ret < 0)
332 return ret;
333
334 vsense_raw = adc_raw - iadc->offset[chan->channel];
335
336 vsense_uv = vsense_raw * IADC_REF_GAIN_MICRO_VOLTS;
337 vsense_uv /= (s32)iadc->gain - iadc->offset[chan->channel];
338
339 isense_ua = vsense_uv / iadc->rsense[chan->channel];
340
341 dev_dbg(iadc->dev, "off %d gain %d adc %d %duV I %duA\n",
342 iadc->offset[chan->channel], iadc->gain,
343 adc_raw, vsense_uv, isense_ua);
344
345 *val = isense_ua;
346 return IIO_VAL_INT;
347 case IIO_CHAN_INFO_SCALE:
348 *val = 0;
349 *val2 = 1000;
350 return IIO_VAL_INT_PLUS_MICRO;
351 }
352
353 return -EINVAL;
354}
355
356static const struct iio_info iadc_info = {
357 .read_raw = iadc_read_raw,
358 .driver_module = THIS_MODULE,
359};
360
361static irqreturn_t iadc_isr(int irq, void *dev_id)
362{
363 struct iadc_chip *iadc = dev_id;
364
365 complete(&iadc->complete);
366
367 return IRQ_HANDLED;
368}
369
370static int iadc_update_offset(struct iadc_chip *iadc)
371{
372 int ret;
373
374 ret = iadc_do_conversion(iadc, IADC_GAIN_17P857MV, &iadc->gain);
375 if (ret < 0)
376 return ret;
377
378 ret = iadc_do_conversion(iadc, IADC_INT_OFFSET_CSP2_CSN2,
379 &iadc->offset[IADC_INT_RSENSE]);
380 if (ret < 0)
381 return ret;
382
383 if (iadc->gain == iadc->offset[IADC_INT_RSENSE]) {
384 dev_err(iadc->dev, "error: internal offset == gain %d\n",
385 iadc->gain);
386 return -EINVAL;
387 }
388
389 ret = iadc_do_conversion(iadc, IADC_EXT_OFFSET_CSP_CSN,
390 &iadc->offset[IADC_EXT_RSENSE]);
391 if (ret < 0)
392 return ret;
393
394 if (iadc->gain == iadc->offset[IADC_EXT_RSENSE]) {
395 dev_err(iadc->dev, "error: external offset == gain %d\n",
396 iadc->gain);
397 return -EINVAL;
398 }
399
400 return 0;
401}
402
403static int iadc_version_check(struct iadc_chip *iadc)
404{
405 u8 val;
406 int ret;
407
408 ret = iadc_read(iadc, IADC_PERPH_TYPE, &val);
409 if (ret < 0)
410 return ret;
411
412 if (val < IADC_PERPH_TYPE_ADC) {
413 dev_err(iadc->dev, "%d is not ADC\n", val);
414 return -EINVAL;
415 }
416
417 ret = iadc_read(iadc, IADC_PERPH_SUBTYPE, &val);
418 if (ret < 0)
419 return ret;
420
421 if (val < IADC_PERPH_SUBTYPE_IADC) {
422 dev_err(iadc->dev, "%d is not IADC\n", val);
423 return -EINVAL;
424 }
425
426 ret = iadc_read(iadc, IADC_REVISION2, &val);
427 if (ret < 0)
428 return ret;
429
430 if (val < IADC_REVISION2_SUPPORTED_IADC) {
431 dev_err(iadc->dev, "revision %d not supported\n", val);
432 return -EINVAL;
433 }
434
435 return 0;
436}
437
438static int iadc_rsense_read(struct iadc_chip *iadc, struct device_node *node)
439{
440 int ret, sign, int_sense;
441 u8 deviation;
442
443 ret = of_property_read_u32(node, "qcom,external-resistor-micro-ohms",
444 &iadc->rsense[IADC_EXT_RSENSE]);
445 if (ret < 0)
446 iadc->rsense[IADC_EXT_RSENSE] = IADC_INT_RSENSE_IDEAL_VALUE;
447
448 if (!iadc->rsense[IADC_EXT_RSENSE]) {
449 dev_err(iadc->dev, "external resistor can't be zero Ohms");
450 return -EINVAL;
451 }
452
453 ret = iadc_read(iadc, IADC_NOMINAL_RSENSE, &deviation);
454 if (ret < 0)
455 return ret;
456
457 /*
458 * Deviation value stored is an offset from 10 mili Ohms, bit 7 is
459 * the sign, the remaining bits have an LSB of 15625 nano Ohms.
460 */
461 sign = (deviation & IADC_NOMINAL_RSENSE_SIGN_MASK) ? -1 : 1;
462
463 deviation &= ~IADC_NOMINAL_RSENSE_SIGN_MASK;
464
465 /* Scale it to nono Ohms */
466 int_sense = IADC_INT_RSENSE_IDEAL_VALUE * 1000;
467 int_sense += sign * deviation * IADC_INT_RSENSE_DEVIATION;
468 int_sense /= 1000; /* micro Ohms */
469
470 iadc->rsense[IADC_INT_RSENSE] = int_sense;
471 return 0;
472}
473
474static const struct iio_chan_spec iadc_channels[] = {
475 {
476 .type = IIO_CURRENT,
477 .datasheet_name = "INTERNAL_RSENSE",
478 .channel = 0,
479 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
480 BIT(IIO_CHAN_INFO_SCALE),
481 .indexed = 1,
482 },
483 {
484 .type = IIO_CURRENT,
485 .datasheet_name = "EXTERNAL_RSENSE",
486 .channel = 1,
487 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
488 BIT(IIO_CHAN_INFO_SCALE),
489 .indexed = 1,
490 },
491};
492
493static int iadc_probe(struct platform_device *pdev)
494{
495 struct device_node *node = pdev->dev.of_node;
496 struct device *dev = &pdev->dev;
497 struct iio_dev *indio_dev;
498 struct iadc_chip *iadc;
499 int ret, irq_eoc;
500 u32 res;
501
502 indio_dev = devm_iio_device_alloc(dev, sizeof(*iadc));
503 if (!indio_dev)
504 return -ENOMEM;
505
506 iadc = iio_priv(indio_dev);
507 iadc->dev = dev;
508
509 iadc->regmap = dev_get_regmap(dev->parent, NULL);
510 if (!iadc->regmap)
511 return -ENODEV;
512
513 init_completion(&iadc->complete);
514 mutex_init(&iadc->lock);
515
516 ret = of_property_read_u32(node, "reg", &res);
517 if (ret < 0)
518 return -ENODEV;
519
520 iadc->base = res;
521
522 ret = iadc_version_check(iadc);
523 if (ret < 0)
524 return -ENODEV;
525
526 ret = iadc_rsense_read(iadc, node);
527 if (ret < 0)
528 return -ENODEV;
529
530 dev_dbg(iadc->dev, "sense resistors %d and %d micro Ohm\n",
531 iadc->rsense[IADC_INT_RSENSE],
532 iadc->rsense[IADC_EXT_RSENSE]);
533
534 irq_eoc = platform_get_irq(pdev, 0);
535 if (irq_eoc == -EPROBE_DEFER)
536 return irq_eoc;
537
538 if (irq_eoc < 0)
539 iadc->poll_eoc = true;
540
541 ret = iadc_reset(iadc);
542 if (ret < 0) {
543 dev_err(dev, "reset failed\n");
544 return ret;
545 }
546
547 if (!iadc->poll_eoc) {
548 ret = devm_request_irq(dev, irq_eoc, iadc_isr, 0,
549 "spmi-iadc", iadc);
550 if (!ret)
551 enable_irq_wake(irq_eoc);
552 else
553 return ret;
554 } else {
555 device_init_wakeup(iadc->dev, 1);
556 }
557
558 ret = iadc_update_offset(iadc);
559 if (ret < 0) {
560 dev_err(dev, "failed offset calibration\n");
561 return ret;
562 }
563
564 indio_dev->dev.parent = dev;
565 indio_dev->dev.of_node = node;
566 indio_dev->name = pdev->name;
567 indio_dev->modes = INDIO_DIRECT_MODE;
568 indio_dev->info = &iadc_info;
569 indio_dev->channels = iadc_channels;
570 indio_dev->num_channels = ARRAY_SIZE(iadc_channels);
571
572 return devm_iio_device_register(dev, indio_dev);
573}
574
575static const struct of_device_id iadc_match_table[] = {
576 { .compatible = "qcom,spmi-iadc" },
577 { }
578};
579
580MODULE_DEVICE_TABLE(of, iadc_match_table);
581
582static struct platform_driver iadc_driver = {
583 .driver = {
584 .name = "qcom-spmi-iadc",
585 .of_match_table = iadc_match_table,
586 },
587 .probe = iadc_probe,
588};
589
590module_platform_driver(iadc_driver);
591
592MODULE_ALIAS("platform:qcom-spmi-iadc");
593MODULE_DESCRIPTION("Qualcomm SPMI PMIC current ADC driver");
594MODULE_LICENSE("GPL v2");
595MODULE_AUTHOR("Ivan T. Ivanov <iivanov@mm-sol.com>");