aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio
diff options
context:
space:
mode:
authorFugang Duan <B38611@freescale.com>2014-01-26 00:39:00 -0500
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:57:35 -0400
commit06f4baa24df97830b21c86c677d8043eff9f5362 (patch)
tree9d511b9101c23b3d56e22e4c620a7d629737303e /drivers/iio
parentd472828dac9afbe09139a8a9aa0805719bec3e89 (diff)
iio:adc:imx: add Freescale Vybrid vf610 adc driver
Add Freescale Vybrid vf610 adc driver. The driver only support ADC software trigger. VF610 ADC device documentation is available at below reference manual (chapter 37): http://cache.freescale.com/files/32bit/doc/ref_manual/VYBRIDRM.pdf? fpsp=1&WT_TYPE=Reference%20Manuals&WT_VENDOR=FREESCALE&WT_FILE_FORMAT =pdf&WT_ASSET=Documentation CC: Shawn Guo <shawn.guo@linaro.org> CC: Jonathan Cameron <jic23@kernel.org> CC: Mark Rutland <mark.rutland@arm.com> CC: Otavio Salvador <otavio@ossystems.com.br> CC: Peter Meerwald <pmeerw@pmeerw.net> CC: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Fugang Duan <B38611@freescale.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r--drivers/iio/adc/Kconfig10
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/vf610_adc.c711
3 files changed, 722 insertions, 0 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index ab0767e6727e..31d971bd06b7 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -150,6 +150,16 @@ config TI_AM335X_ADC
150 Say yes here to build support for Texas Instruments ADC 150 Say yes here to build support for Texas Instruments ADC
151 driver which is also a MFD client. 151 driver which is also a MFD client.
152 152
153config VF610_ADC
154 tristate "Freescale vf610 ADC driver"
155 depends on OF
156 help
157 Say yes here to support for Vybrid board analog-to-digital converter.
158 Since the IP is used for i.MX6SLX, the driver also support i.MX6SLX.
159
160 This driver can also be built as a module. If so, the module will be
161 called vf610_adc.
162
153config VIPERBOARD_ADC 163config VIPERBOARD_ADC
154 tristate "Viperboard ADC support" 164 tristate "Viperboard ADC support"
155 depends on MFD_VIPERBOARD && USB 165 depends on MFD_VIPERBOARD && USB
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 0a825bed43f6..7eae32d40972 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -16,4 +16,5 @@ obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
16obj-$(CONFIG_MAX1363) += max1363.o 16obj-$(CONFIG_MAX1363) += max1363.o
17obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o 17obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
18obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o 18obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
19obj-$(CONFIG_VF610_ADC) += vf610_adc.o
19obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o 20obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
new file mode 100644
index 000000000000..37f542e8233c
--- /dev/null
+++ b/drivers/iio/adc/vf610_adc.c
@@ -0,0 +1,711 @@
1/*
2 * Freescale Vybrid vf610 ADC driver
3 *
4 * Copyright 2013 Freescale Semiconductor, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#include <linux/module.h>
22#include <linux/platform_device.h>
23#include <linux/interrupt.h>
24#include <linux/delay.h>
25#include <linux/kernel.h>
26#include <linux/slab.h>
27#include <linux/io.h>
28#include <linux/clk.h>
29#include <linux/completion.h>
30#include <linux/of.h>
31#include <linux/of_irq.h>
32#include <linux/regulator/consumer.h>
33#include <linux/of_platform.h>
34#include <linux/err.h>
35
36#include <linux/iio/iio.h>
37#include <linux/iio/sysfs.h>
38#include <linux/iio/driver.h>
39
40/* This will be the driver name the kernel reports */
41#define DRIVER_NAME "vf610-adc"
42
43/* Vybrid/IMX ADC registers */
44#define VF610_REG_ADC_HC0 0x00
45#define VF610_REG_ADC_HC1 0x04
46#define VF610_REG_ADC_HS 0x08
47#define VF610_REG_ADC_R0 0x0c
48#define VF610_REG_ADC_R1 0x10
49#define VF610_REG_ADC_CFG 0x14
50#define VF610_REG_ADC_GC 0x18
51#define VF610_REG_ADC_GS 0x1c
52#define VF610_REG_ADC_CV 0x20
53#define VF610_REG_ADC_OFS 0x24
54#define VF610_REG_ADC_CAL 0x28
55#define VF610_REG_ADC_PCTL 0x30
56
57/* Configuration register field define */
58#define VF610_ADC_MODE_BIT8 0x00
59#define VF610_ADC_MODE_BIT10 0x04
60#define VF610_ADC_MODE_BIT12 0x08
61#define VF610_ADC_MODE_MASK 0x0c
62#define VF610_ADC_BUSCLK2_SEL 0x01
63#define VF610_ADC_ALTCLK_SEL 0x02
64#define VF610_ADC_ADACK_SEL 0x03
65#define VF610_ADC_ADCCLK_MASK 0x03
66#define VF610_ADC_CLK_DIV2 0x20
67#define VF610_ADC_CLK_DIV4 0x40
68#define VF610_ADC_CLK_DIV8 0x60
69#define VF610_ADC_CLK_MASK 0x60
70#define VF610_ADC_ADLSMP_LONG 0x10
71#define VF610_ADC_ADSTS_MASK 0x300
72#define VF610_ADC_ADLPC_EN 0x80
73#define VF610_ADC_ADHSC_EN 0x400
74#define VF610_ADC_REFSEL_VALT 0x100
75#define VF610_ADC_REFSEL_VBG 0x1000
76#define VF610_ADC_ADTRG_HARD 0x2000
77#define VF610_ADC_AVGS_8 0x4000
78#define VF610_ADC_AVGS_16 0x8000
79#define VF610_ADC_AVGS_32 0xC000
80#define VF610_ADC_AVGS_MASK 0xC000
81#define VF610_ADC_OVWREN 0x10000
82
83/* General control register field define */
84#define VF610_ADC_ADACKEN 0x1
85#define VF610_ADC_DMAEN 0x2
86#define VF610_ADC_ACREN 0x4
87#define VF610_ADC_ACFGT 0x8
88#define VF610_ADC_ACFE 0x10
89#define VF610_ADC_AVGEN 0x20
90#define VF610_ADC_ADCON 0x40
91#define VF610_ADC_CAL 0x80
92
93/* Other field define */
94#define VF610_ADC_ADCHC(x) ((x) & 0xF)
95#define VF610_ADC_AIEN (0x1 << 7)
96#define VF610_ADC_CONV_DISABLE 0x1F
97#define VF610_ADC_HS_COCO0 0x1
98#define VF610_ADC_CALF 0x2
99#define VF610_ADC_TIMEOUT msecs_to_jiffies(100)
100
101enum clk_sel {
102 VF610_ADCIOC_BUSCLK_SET,
103 VF610_ADCIOC_ALTCLK_SET,
104 VF610_ADCIOC_ADACK_SET,
105};
106
107enum vol_ref {
108 VF610_ADCIOC_VR_VREF_SET,
109 VF610_ADCIOC_VR_VALT_SET,
110 VF610_ADCIOC_VR_VBG_SET,
111};
112
113enum average_sel {
114 VF610_ADC_SAMPLE_1,
115 VF610_ADC_SAMPLE_4,
116 VF610_ADC_SAMPLE_8,
117 VF610_ADC_SAMPLE_16,
118 VF610_ADC_SAMPLE_32,
119};
120
121struct vf610_adc_feature {
122 enum clk_sel clk_sel;
123 enum vol_ref vol_ref;
124
125 int clk_div;
126 int sample_rate;
127 int res_mode;
128
129 bool lpm;
130 bool calibration;
131 bool ovwren;
132};
133
134struct vf610_adc {
135 struct device *dev;
136 void __iomem *regs;
137 struct clk *clk;
138
139 u32 vref_uv;
140 u32 value;
141 struct regulator *vref;
142 struct vf610_adc_feature adc_feature;
143
144 struct completion completion;
145};
146
147#define VF610_ADC_CHAN(_idx, _chan_type) { \
148 .type = (_chan_type), \
149 .indexed = 1, \
150 .channel = (_idx), \
151 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
152 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
153 BIT(IIO_CHAN_INFO_SAMP_FREQ), \
154}
155
156static const struct iio_chan_spec vf610_adc_iio_channels[] = {
157 VF610_ADC_CHAN(0, IIO_VOLTAGE),
158 VF610_ADC_CHAN(1, IIO_VOLTAGE),
159 VF610_ADC_CHAN(2, IIO_VOLTAGE),
160 VF610_ADC_CHAN(3, IIO_VOLTAGE),
161 VF610_ADC_CHAN(4, IIO_VOLTAGE),
162 VF610_ADC_CHAN(5, IIO_VOLTAGE),
163 VF610_ADC_CHAN(6, IIO_VOLTAGE),
164 VF610_ADC_CHAN(7, IIO_VOLTAGE),
165 VF610_ADC_CHAN(8, IIO_VOLTAGE),
166 VF610_ADC_CHAN(9, IIO_VOLTAGE),
167 VF610_ADC_CHAN(10, IIO_VOLTAGE),
168 VF610_ADC_CHAN(11, IIO_VOLTAGE),
169 VF610_ADC_CHAN(12, IIO_VOLTAGE),
170 VF610_ADC_CHAN(13, IIO_VOLTAGE),
171 VF610_ADC_CHAN(14, IIO_VOLTAGE),
172 VF610_ADC_CHAN(15, IIO_VOLTAGE),
173 /* sentinel */
174};
175
176/*
177 * ADC sample frequency, unit is ADCK cycles.
178 * ADC clk source is ipg clock, which is the same as bus clock.
179 *
180 * ADC conversion time = SFCAdder + AverageNum x (BCT + LSTAdder)
181 * SFCAdder: fixed to 6 ADCK cycles
182 * AverageNum: 1, 4, 8, 16, 32 samples for hardware average.
183 * BCT (Base Conversion Time): fixed to 25 ADCK cycles for 12 bit mode
184 * LSTAdder(Long Sample Time): fixed to 3 ADCK cycles
185 *
186 * By default, enable 12 bit resolution mode, clock source
187 * set to ipg clock, So get below frequency group:
188 */
189static const u32 vf610_sample_freq_avail[5] =
190{1941176, 559332, 286957, 145374, 73171};
191
192static inline void vf610_adc_cfg_init(struct vf610_adc *info)
193{
194 /* set default Configuration for ADC controller */
195 info->adc_feature.clk_sel = VF610_ADCIOC_BUSCLK_SET;
196 info->adc_feature.vol_ref = VF610_ADCIOC_VR_VREF_SET;
197
198 info->adc_feature.calibration = true;
199 info->adc_feature.ovwren = true;
200
201 info->adc_feature.clk_div = 1;
202 info->adc_feature.res_mode = 12;
203 info->adc_feature.sample_rate = 1;
204 info->adc_feature.lpm = true;
205}
206
207static void vf610_adc_cfg_post_set(struct vf610_adc *info)
208{
209 struct vf610_adc_feature *adc_feature = &info->adc_feature;
210 int cfg_data = 0;
211 int gc_data = 0;
212
213 switch (adc_feature->clk_sel) {
214 case VF610_ADCIOC_ALTCLK_SET:
215 cfg_data |= VF610_ADC_ALTCLK_SEL;
216 break;
217 case VF610_ADCIOC_ADACK_SET:
218 cfg_data |= VF610_ADC_ADACK_SEL;
219 break;
220 default:
221 break;
222 }
223
224 /* low power set for calibration */
225 cfg_data |= VF610_ADC_ADLPC_EN;
226
227 /* enable high speed for calibration */
228 cfg_data |= VF610_ADC_ADHSC_EN;
229
230 /* voltage reference */
231 switch (adc_feature->vol_ref) {
232 case VF610_ADCIOC_VR_VREF_SET:
233 break;
234 case VF610_ADCIOC_VR_VALT_SET:
235 cfg_data |= VF610_ADC_REFSEL_VALT;
236 break;
237 case VF610_ADCIOC_VR_VBG_SET:
238 cfg_data |= VF610_ADC_REFSEL_VBG;
239 break;
240 default:
241 dev_err(info->dev, "error voltage reference\n");
242 }
243
244 /* data overwrite enable */
245 if (adc_feature->ovwren)
246 cfg_data |= VF610_ADC_OVWREN;
247
248 writel(cfg_data, info->regs + VF610_REG_ADC_CFG);
249 writel(gc_data, info->regs + VF610_REG_ADC_GC);
250}
251
252static void vf610_adc_calibration(struct vf610_adc *info)
253{
254 int adc_gc, hc_cfg;
255 int timeout;
256
257 if (!info->adc_feature.calibration)
258 return;
259
260 /* enable calibration interrupt */
261 hc_cfg = VF610_ADC_AIEN | VF610_ADC_CONV_DISABLE;
262 writel(hc_cfg, info->regs + VF610_REG_ADC_HC0);
263
264 adc_gc = readl(info->regs + VF610_REG_ADC_GC);
265 writel(adc_gc | VF610_ADC_CAL, info->regs + VF610_REG_ADC_GC);
266
267 timeout = wait_for_completion_timeout
268 (&info->completion, VF610_ADC_TIMEOUT);
269 if (timeout == 0)
270 dev_err(info->dev, "Timeout for adc calibration\n");
271
272 adc_gc = readl(info->regs + VF610_REG_ADC_GS);
273 if (adc_gc & VF610_ADC_CALF)
274 dev_err(info->dev, "ADC calibration failed\n");
275
276 info->adc_feature.calibration = false;
277}
278
279static void vf610_adc_cfg_set(struct vf610_adc *info)
280{
281 struct vf610_adc_feature *adc_feature = &(info->adc_feature);
282 int cfg_data;
283
284 cfg_data = readl(info->regs + VF610_REG_ADC_CFG);
285
286 /* low power configuration */
287 cfg_data &= ~VF610_ADC_ADLPC_EN;
288 if (adc_feature->lpm)
289 cfg_data |= VF610_ADC_ADLPC_EN;
290
291 /* disable high speed */
292 cfg_data &= ~VF610_ADC_ADHSC_EN;
293
294 writel(cfg_data, info->regs + VF610_REG_ADC_CFG);
295}
296
297static void vf610_adc_sample_set(struct vf610_adc *info)
298{
299 struct vf610_adc_feature *adc_feature = &(info->adc_feature);
300 int cfg_data, gc_data;
301
302 cfg_data = readl(info->regs + VF610_REG_ADC_CFG);
303 gc_data = readl(info->regs + VF610_REG_ADC_GC);
304
305 /* resolution mode */
306 cfg_data &= ~VF610_ADC_MODE_MASK;
307 switch (adc_feature->res_mode) {
308 case 8:
309 cfg_data |= VF610_ADC_MODE_BIT8;
310 break;
311 case 10:
312 cfg_data |= VF610_ADC_MODE_BIT10;
313 break;
314 case 12:
315 cfg_data |= VF610_ADC_MODE_BIT12;
316 break;
317 default:
318 dev_err(info->dev, "error resolution mode\n");
319 break;
320 }
321
322 /* clock select and clock divider */
323 cfg_data &= ~(VF610_ADC_CLK_MASK | VF610_ADC_ADCCLK_MASK);
324 switch (adc_feature->clk_div) {
325 case 1:
326 break;
327 case 2:
328 cfg_data |= VF610_ADC_CLK_DIV2;
329 break;
330 case 4:
331 cfg_data |= VF610_ADC_CLK_DIV4;
332 break;
333 case 8:
334 cfg_data |= VF610_ADC_CLK_DIV8;
335 break;
336 case 16:
337 switch (adc_feature->clk_sel) {
338 case VF610_ADCIOC_BUSCLK_SET:
339 cfg_data |= VF610_ADC_BUSCLK2_SEL | VF610_ADC_CLK_DIV8;
340 break;
341 default:
342 dev_err(info->dev, "error clk divider\n");
343 break;
344 }
345 break;
346 }
347
348 /* Use the short sample mode */
349 cfg_data &= ~(VF610_ADC_ADLSMP_LONG | VF610_ADC_ADSTS_MASK);
350
351 /* update hardware average selection */
352 cfg_data &= ~VF610_ADC_AVGS_MASK;
353 gc_data &= ~VF610_ADC_AVGEN;
354 switch (adc_feature->sample_rate) {
355 case VF610_ADC_SAMPLE_1:
356 break;
357 case VF610_ADC_SAMPLE_4:
358 gc_data |= VF610_ADC_AVGEN;
359 break;
360 case VF610_ADC_SAMPLE_8:
361 gc_data |= VF610_ADC_AVGEN;
362 cfg_data |= VF610_ADC_AVGS_8;
363 break;
364 case VF610_ADC_SAMPLE_16:
365 gc_data |= VF610_ADC_AVGEN;
366 cfg_data |= VF610_ADC_AVGS_16;
367 break;
368 case VF610_ADC_SAMPLE_32:
369 gc_data |= VF610_ADC_AVGEN;
370 cfg_data |= VF610_ADC_AVGS_32;
371 break;
372 default:
373 dev_err(info->dev,
374 "error hardware sample average select\n");
375 }
376
377 writel(cfg_data, info->regs + VF610_REG_ADC_CFG);
378 writel(gc_data, info->regs + VF610_REG_ADC_GC);
379}
380
381static void vf610_adc_hw_init(struct vf610_adc *info)
382{
383 /* CFG: Feature set */
384 vf610_adc_cfg_post_set(info);
385 vf610_adc_sample_set(info);
386
387 /* adc calibration */
388 vf610_adc_calibration(info);
389
390 /* CFG: power and speed set */
391 vf610_adc_cfg_set(info);
392}
393
394static int vf610_adc_read_data(struct vf610_adc *info)
395{
396 int result;
397
398 result = readl(info->regs + VF610_REG_ADC_R0);
399
400 switch (info->adc_feature.res_mode) {
401 case 8:
402 result &= 0xFF;
403 break;
404 case 10:
405 result &= 0x3FF;
406 break;
407 case 12:
408 result &= 0xFFF;
409 break;
410 default:
411 break;
412 }
413
414 return result;
415}
416
417static irqreturn_t vf610_adc_isr(int irq, void *dev_id)
418{
419 struct vf610_adc *info = (struct vf610_adc *)dev_id;
420 int coco;
421
422 coco = readl(info->regs + VF610_REG_ADC_HS);
423 if (coco & VF610_ADC_HS_COCO0) {
424 info->value = vf610_adc_read_data(info);
425 complete(&info->completion);
426 }
427
428 return IRQ_HANDLED;
429}
430
431static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("1941176, 559332, 286957, 145374, 73171");
432
433static struct attribute *vf610_attributes[] = {
434 &iio_const_attr_sampling_frequency_available.dev_attr.attr,
435 NULL
436};
437
438static const struct attribute_group vf610_attribute_group = {
439 .attrs = vf610_attributes,
440};
441
442static int vf610_read_raw(struct iio_dev *indio_dev,
443 struct iio_chan_spec const *chan,
444 int *val,
445 int *val2,
446 long mask)
447{
448 struct vf610_adc *info = iio_priv(indio_dev);
449 unsigned int hc_cfg;
450 unsigned long ret;
451
452 switch (mask) {
453 case IIO_CHAN_INFO_RAW:
454 mutex_lock(&indio_dev->mlock);
455 reinit_completion(&info->completion);
456
457 hc_cfg = VF610_ADC_ADCHC(chan->channel);
458 hc_cfg |= VF610_ADC_AIEN;
459 writel(hc_cfg, info->regs + VF610_REG_ADC_HC0);
460 ret = wait_for_completion_interruptible_timeout
461 (&info->completion, VF610_ADC_TIMEOUT);
462 if (ret == 0) {
463 mutex_unlock(&indio_dev->mlock);
464 return -ETIMEDOUT;
465 }
466 if (ret < 0) {
467 mutex_unlock(&indio_dev->mlock);
468 return ret;
469 }
470
471 *val = info->value;
472 mutex_unlock(&indio_dev->mlock);
473 return IIO_VAL_INT;
474
475 case IIO_CHAN_INFO_SCALE:
476 *val = info->vref_uv / 1000;
477 *val2 = info->adc_feature.res_mode;
478 return IIO_VAL_FRACTIONAL_LOG2;
479
480 case IIO_CHAN_INFO_SAMP_FREQ:
481 *val = vf610_sample_freq_avail[info->adc_feature.sample_rate];
482 *val2 = 0;
483 return IIO_VAL_INT;
484
485 default:
486 break;
487 }
488
489 return -EINVAL;
490}
491
492static int vf610_write_raw(struct iio_dev *indio_dev,
493 struct iio_chan_spec const *chan,
494 int val,
495 int val2,
496 long mask)
497{
498 struct vf610_adc *info = iio_priv(indio_dev);
499 int i;
500
501 switch (mask) {
502 case IIO_CHAN_INFO_SAMP_FREQ:
503 for (i = 0;
504 i < ARRAY_SIZE(vf610_sample_freq_avail);
505 i++)
506 if (val == vf610_sample_freq_avail[i]) {
507 info->adc_feature.sample_rate = i;
508 vf610_adc_sample_set(info);
509 return 0;
510 }
511 break;
512
513 default:
514 break;
515 }
516
517 return -EINVAL;
518}
519
520static int vf610_adc_reg_access(struct iio_dev *indio_dev,
521 unsigned reg, unsigned writeval,
522 unsigned *readval)
523{
524 struct vf610_adc *info = iio_priv(indio_dev);
525
526 if ((readval == NULL) ||
527 (!(reg % 4) || (reg > VF610_REG_ADC_PCTL)))
528 return -EINVAL;
529
530 *readval = readl(info->regs + reg);
531
532 return 0;
533}
534
535static const struct iio_info vf610_adc_iio_info = {
536 .driver_module = THIS_MODULE,
537 .read_raw = &vf610_read_raw,
538 .write_raw = &vf610_write_raw,
539 .debugfs_reg_access = &vf610_adc_reg_access,
540 .attrs = &vf610_attribute_group,
541};
542
543static const struct of_device_id vf610_adc_match[] = {
544 { .compatible = "fsl,vf610-adc", },
545 { /* sentinel */ }
546};
547MODULE_DEVICE_TABLE(of, vf610_adc_match);
548
549static int vf610_adc_probe(struct platform_device *pdev)
550{
551 struct vf610_adc *info;
552 struct iio_dev *indio_dev;
553 struct resource *mem;
554 int irq;
555 int ret;
556
557 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct vf610_adc));
558 if (!indio_dev) {
559 dev_err(&pdev->dev, "Failed allocating iio device\n");
560 return -ENOMEM;
561 }
562
563 info = iio_priv(indio_dev);
564 info->dev = &pdev->dev;
565
566 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
567 info->regs = devm_ioremap_resource(&pdev->dev, mem);
568 if (IS_ERR(info->regs))
569 return PTR_ERR(info->regs);
570
571 irq = platform_get_irq(pdev, 0);
572 if (irq <= 0) {
573 dev_err(&pdev->dev, "no irq resource?\n");
574 return -EINVAL;
575 }
576
577 ret = devm_request_irq(info->dev, irq,
578 vf610_adc_isr, 0,
579 dev_name(&pdev->dev), info);
580 if (ret < 0) {
581 dev_err(&pdev->dev, "failed requesting irq, irq = %d\n", irq);
582 return ret;
583 }
584
585 info->clk = devm_clk_get(&pdev->dev, "adc");
586 if (IS_ERR(info->clk)) {
587 dev_err(&pdev->dev, "failed getting clock, err = %ld\n",
588 PTR_ERR(info->clk));
589 ret = PTR_ERR(info->clk);
590 return ret;
591 }
592
593 info->vref = devm_regulator_get(&pdev->dev, "vref");
594 if (IS_ERR(info->vref))
595 return PTR_ERR(info->vref);
596
597 ret = regulator_enable(info->vref);
598 if (ret)
599 return ret;
600
601 info->vref_uv = regulator_get_voltage(info->vref);
602
603 platform_set_drvdata(pdev, indio_dev);
604
605 init_completion(&info->completion);
606
607 indio_dev->name = dev_name(&pdev->dev);
608 indio_dev->dev.parent = &pdev->dev;
609 indio_dev->dev.of_node = pdev->dev.of_node;
610 indio_dev->info = &vf610_adc_iio_info;
611 indio_dev->modes = INDIO_DIRECT_MODE;
612 indio_dev->channels = vf610_adc_iio_channels;
613 indio_dev->num_channels = ARRAY_SIZE(vf610_adc_iio_channels);
614
615 ret = clk_prepare_enable(info->clk);
616 if (ret) {
617 dev_err(&pdev->dev,
618 "Could not prepare or enable the clock.\n");
619 goto error_adc_clk_enable;
620 }
621
622 vf610_adc_cfg_init(info);
623 vf610_adc_hw_init(info);
624
625 ret = iio_device_register(indio_dev);
626 if (ret) {
627 dev_err(&pdev->dev, "Couldn't register the device.\n");
628 goto error_iio_device_register;
629 }
630
631 return 0;
632
633
634error_iio_device_register:
635 clk_disable_unprepare(info->clk);
636error_adc_clk_enable:
637 regulator_disable(info->vref);
638
639 return ret;
640}
641
642static int vf610_adc_remove(struct platform_device *pdev)
643{
644 struct iio_dev *indio_dev = platform_get_drvdata(pdev);
645 struct vf610_adc *info = iio_priv(indio_dev);
646
647 iio_device_unregister(indio_dev);
648 regulator_disable(info->vref);
649 clk_disable_unprepare(info->clk);
650
651 return 0;
652}
653
654#ifdef CONFIG_PM_SLEEP
655static int vf610_adc_suspend(struct device *dev)
656{
657 struct iio_dev *indio_dev = dev_get_drvdata(dev);
658 struct vf610_adc *info = iio_priv(indio_dev);
659 int hc_cfg;
660
661 /* ADC controller enters to stop mode */
662 hc_cfg = readl(info->regs + VF610_REG_ADC_HC0);
663 hc_cfg |= VF610_ADC_CONV_DISABLE;
664 writel(hc_cfg, info->regs + VF610_REG_ADC_HC0);
665
666 clk_disable_unprepare(info->clk);
667 regulator_disable(info->vref);
668
669 return 0;
670}
671
672static int vf610_adc_resume(struct device *dev)
673{
674 struct iio_dev *indio_dev = dev_get_drvdata(dev);
675 struct vf610_adc *info = iio_priv(indio_dev);
676 int ret;
677
678 ret = regulator_enable(info->vref);
679 if (ret)
680 return ret;
681
682 ret = clk_prepare_enable(info->clk);
683 if (ret)
684 return ret;
685
686 vf610_adc_hw_init(info);
687
688 return 0;
689}
690#endif
691
692static SIMPLE_DEV_PM_OPS(vf610_adc_pm_ops,
693 vf610_adc_suspend,
694 vf610_adc_resume);
695
696static struct platform_driver vf610_adc_driver = {
697 .probe = vf610_adc_probe,
698 .remove = vf610_adc_remove,
699 .driver = {
700 .name = DRIVER_NAME,
701 .owner = THIS_MODULE,
702 .of_match_table = vf610_adc_match,
703 .pm = &vf610_adc_pm_ops,
704 },
705};
706
707module_platform_driver(vf610_adc_driver);
708
709MODULE_AUTHOR("Fugang Duan <B38611@freescale.com>");
710MODULE_DESCRIPTION("Freescale VF610 ADC driver");
711MODULE_LICENSE("GPL v2");