blob: 66d27c638d8370adb30d04b52c765190f44e8749 [file] [log] [blame]
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +00001/*
2 * exynos_adc.c - Support for ADC in EXYNOS SoCs
3 *
4 * 8 ~ 10 channel, 10/12-bit ADC
5 *
6 * Copyright (C) 2013 Naveen Krishna Chatradhi <ch.naveen@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/interrupt.h>
26#include <linux/delay.h>
27#include <linux/kernel.h>
28#include <linux/slab.h>
29#include <linux/io.h>
30#include <linux/clk.h>
31#include <linux/completion.h>
32#include <linux/of.h>
33#include <linux/of_irq.h>
34#include <linux/regulator/consumer.h>
35#include <linux/of_platform.h>
Sachin Kamatebeb0212013-07-22 12:02:00 +010036#include <linux/err.h>
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +000037
38#include <linux/iio/iio.h>
39#include <linux/iio/machine.h>
40#include <linux/iio/driver.h>
41
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +000042/* EXYNOS4412/5250 ADC_V1 registers definitions */
43#define ADC_V1_CON(x) ((x) + 0x00)
44#define ADC_V1_DLY(x) ((x) + 0x08)
45#define ADC_V1_DATX(x) ((x) + 0x0C)
46#define ADC_V1_INTCLR(x) ((x) + 0x18)
47#define ADC_V1_MUX(x) ((x) + 0x1c)
48
49/* Future ADC_V2 registers definitions */
50#define ADC_V2_CON1(x) ((x) + 0x00)
51#define ADC_V2_CON2(x) ((x) + 0x04)
52#define ADC_V2_STAT(x) ((x) + 0x08)
53#define ADC_V2_INT_EN(x) ((x) + 0x10)
54#define ADC_V2_INT_ST(x) ((x) + 0x14)
55#define ADC_V2_VER(x) ((x) + 0x20)
56
57/* Bit definitions for ADC_V1 */
58#define ADC_V1_CON_RES (1u << 16)
59#define ADC_V1_CON_PRSCEN (1u << 14)
60#define ADC_V1_CON_PRSCLV(x) (((x) & 0xFF) << 6)
61#define ADC_V1_CON_STANDBY (1u << 2)
62
63/* Bit definitions for ADC_V2 */
64#define ADC_V2_CON1_SOFT_RESET (1u << 2)
65
66#define ADC_V2_CON2_OSEL (1u << 10)
67#define ADC_V2_CON2_ESEL (1u << 9)
68#define ADC_V2_CON2_HIGHF (1u << 8)
69#define ADC_V2_CON2_C_TIME(x) (((x) & 7) << 4)
70#define ADC_V2_CON2_ACH_SEL(x) (((x) & 0xF) << 0)
71#define ADC_V2_CON2_ACH_MASK 0xF
72
73#define MAX_ADC_V2_CHANNELS 10
74#define MAX_ADC_V1_CHANNELS 8
75
76/* Bit definitions common for ADC_V1 and ADC_V2 */
77#define ADC_CON_EN_START (1u << 0)
78#define ADC_DATX_MASK 0xFFF
79
Naveen Krishna Chatradhic780a8c2014-04-30 10:26:00 +010080#define EXYNOS_ADC_TIMEOUT (msecs_to_jiffies(100))
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +000081
82struct exynos_adc {
Chanwoo Choie49d99e2014-07-22 03:04:00 +010083 struct exynos_adc_data *data;
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +000084 void __iomem *regs;
Doug Andersonbb916eb2013-03-13 20:40:00 +000085 void __iomem *enable_reg;
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +000086 struct clk *clk;
87 unsigned int irq;
88 struct regulator *vdd;
89
90 struct completion completion;
91
92 u32 value;
93 unsigned int version;
94};
95
Chanwoo Choie49d99e2014-07-22 03:04:00 +010096struct exynos_adc_data {
97 int num_channels;
98
99 void (*init_hw)(struct exynos_adc *info);
100 void (*exit_hw)(struct exynos_adc *info);
101 void (*clear_irq)(struct exynos_adc *info);
102 void (*start_conv)(struct exynos_adc *info, unsigned long addr);
103};
104
105static void exynos_adc_v1_init_hw(struct exynos_adc *info)
106{
107 u32 con1;
108
109 writel(1, info->enable_reg);
110
111 /* set default prescaler values and Enable prescaler */
112 con1 = ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
113
114 /* Enable 12-bit ADC resolution */
115 con1 |= ADC_V1_CON_RES;
116 writel(con1, ADC_V1_CON(info->regs));
117}
118
119static void exynos_adc_v1_exit_hw(struct exynos_adc *info)
120{
121 u32 con;
122
123 writel(0, info->enable_reg);
124
125 con = readl(ADC_V1_CON(info->regs));
126 con |= ADC_V1_CON_STANDBY;
127 writel(con, ADC_V1_CON(info->regs));
128}
129
130static void exynos_adc_v1_clear_irq(struct exynos_adc *info)
131{
132 writel(1, ADC_V1_INTCLR(info->regs));
133}
134
135static void exynos_adc_v1_start_conv(struct exynos_adc *info,
136 unsigned long addr)
137{
138 u32 con1;
139
140 writel(addr, ADC_V1_MUX(info->regs));
141
142 con1 = readl(ADC_V1_CON(info->regs));
143 writel(con1 | ADC_CON_EN_START, ADC_V1_CON(info->regs));
144}
145
146static const struct exynos_adc_data exynos_adc_v1_data = {
147 .num_channels = MAX_ADC_V1_CHANNELS,
148
149 .init_hw = exynos_adc_v1_init_hw,
150 .exit_hw = exynos_adc_v1_exit_hw,
151 .clear_irq = exynos_adc_v1_clear_irq,
152 .start_conv = exynos_adc_v1_start_conv,
153};
154
155static void exynos_adc_v2_init_hw(struct exynos_adc *info)
156{
157 u32 con1, con2;
158
159 writel(1, info->enable_reg);
160
161 con1 = ADC_V2_CON1_SOFT_RESET;
162 writel(con1, ADC_V2_CON1(info->regs));
163
164 con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
165 ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
166 writel(con2, ADC_V2_CON2(info->regs));
167
168 /* Enable interrupts */
169 writel(1, ADC_V2_INT_EN(info->regs));
170}
171
172static void exynos_adc_v2_exit_hw(struct exynos_adc *info)
173{
174 u32 con;
175
176 writel(0, info->enable_reg);
177
178 con = readl(ADC_V2_CON1(info->regs));
179 con &= ~ADC_CON_EN_START;
180 writel(con, ADC_V2_CON1(info->regs));
181}
182
183static void exynos_adc_v2_clear_irq(struct exynos_adc *info)
184{
185 writel(1, ADC_V2_INT_ST(info->regs));
186}
187
188static void exynos_adc_v2_start_conv(struct exynos_adc *info,
189 unsigned long addr)
190{
191 u32 con1, con2;
192
193 con2 = readl(ADC_V2_CON2(info->regs));
194 con2 &= ~ADC_V2_CON2_ACH_MASK;
195 con2 |= ADC_V2_CON2_ACH_SEL(addr);
196 writel(con2, ADC_V2_CON2(info->regs));
197
198 con1 = readl(ADC_V2_CON1(info->regs));
199 writel(con1 | ADC_CON_EN_START, ADC_V2_CON1(info->regs));
200}
201
202static const struct exynos_adc_data exynos_adc_v2_data = {
203 .num_channels = MAX_ADC_V2_CHANNELS,
204
205 .init_hw = exynos_adc_v2_init_hw,
206 .exit_hw = exynos_adc_v2_exit_hw,
207 .clear_irq = exynos_adc_v2_clear_irq,
208 .start_conv = exynos_adc_v2_start_conv,
209};
210
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000211static const struct of_device_id exynos_adc_match[] = {
Chanwoo Choie49d99e2014-07-22 03:04:00 +0100212 {
213 .compatible = "samsung,exynos-adc-v1",
214 .data = &exynos_adc_v1_data,
215 }, {
216 .compatible = "samsung,exynos-adc-v2",
217 .data = &exynos_adc_v2_data,
218 },
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000219 {},
220};
221MODULE_DEVICE_TABLE(of, exynos_adc_match);
222
Chanwoo Choie49d99e2014-07-22 03:04:00 +0100223static struct exynos_adc_data *exynos_adc_get_data(struct platform_device *pdev)
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000224{
225 const struct of_device_id *match;
226
227 match = of_match_node(exynos_adc_match, pdev->dev.of_node);
Chanwoo Choie49d99e2014-07-22 03:04:00 +0100228 return (struct exynos_adc_data *)match->data;
Naveen Krishna Chatradhidd2723f2014-04-30 10:26:00 +0100229}
230
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000231static int exynos_read_raw(struct iio_dev *indio_dev,
232 struct iio_chan_spec const *chan,
233 int *val,
234 int *val2,
235 long mask)
236{
237 struct exynos_adc *info = iio_priv(indio_dev);
238 unsigned long timeout;
Naveen Krishna Chatradhic780a8c2014-04-30 10:26:00 +0100239 int ret;
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000240
241 if (mask != IIO_CHAN_INFO_RAW)
242 return -EINVAL;
243
244 mutex_lock(&indio_dev->mlock);
Naveen Krishna Chatradhi6442d942014-04-30 10:26:00 +0100245 reinit_completion(&info->completion);
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000246
247 /* Select the channel to be used and Trigger conversion */
Chanwoo Choie49d99e2014-07-22 03:04:00 +0100248 if (info->data->start_conv)
249 info->data->start_conv(info, chan->address);
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000250
Naveen Krishna Chatradhic780a8c2014-04-30 10:26:00 +0100251 timeout = wait_for_completion_timeout
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000252 (&info->completion, EXYNOS_ADC_TIMEOUT);
Naveen Krishna Chatradhic780a8c2014-04-30 10:26:00 +0100253 if (timeout == 0) {
Naveen Krishna Chatradhidd2723f2014-04-30 10:26:00 +0100254 dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n");
Chanwoo Choie49d99e2014-07-22 03:04:00 +0100255 if (info->data->init_hw)
256 info->data->init_hw(info);
Naveen Krishna Chatradhic780a8c2014-04-30 10:26:00 +0100257 ret = -ETIMEDOUT;
258 } else {
259 *val = info->value;
260 *val2 = 0;
261 ret = IIO_VAL_INT;
262 }
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000263
264 mutex_unlock(&indio_dev->mlock);
265
Naveen Krishna Chatradhic780a8c2014-04-30 10:26:00 +0100266 return ret;
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000267}
268
269static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
270{
271 struct exynos_adc *info = (struct exynos_adc *)dev_id;
272
273 /* Read value */
Chanwoo Choie49d99e2014-07-22 03:04:00 +0100274 info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK;
275
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000276 /* clear irq */
Chanwoo Choie49d99e2014-07-22 03:04:00 +0100277 if (info->data->clear_irq)
278 info->data->clear_irq(info);
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000279
280 complete(&info->completion);
281
282 return IRQ_HANDLED;
283}
284
285static int exynos_adc_reg_access(struct iio_dev *indio_dev,
286 unsigned reg, unsigned writeval,
287 unsigned *readval)
288{
289 struct exynos_adc *info = iio_priv(indio_dev);
290
291 if (readval == NULL)
292 return -EINVAL;
293
294 *readval = readl(info->regs + reg);
295
296 return 0;
297}
298
299static const struct iio_info exynos_adc_iio_info = {
300 .read_raw = &exynos_read_raw,
301 .debugfs_reg_access = &exynos_adc_reg_access,
302 .driver_module = THIS_MODULE,
303};
304
305#define ADC_CHANNEL(_index, _id) { \
306 .type = IIO_VOLTAGE, \
307 .indexed = 1, \
308 .channel = _index, \
309 .address = _index, \
Jonathan Cameron0d23d322013-03-03 12:25:30 +0000310 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000311 .datasheet_name = _id, \
312}
313
314static const struct iio_chan_spec exynos_adc_iio_channels[] = {
315 ADC_CHANNEL(0, "adc0"),
316 ADC_CHANNEL(1, "adc1"),
317 ADC_CHANNEL(2, "adc2"),
318 ADC_CHANNEL(3, "adc3"),
319 ADC_CHANNEL(4, "adc4"),
320 ADC_CHANNEL(5, "adc5"),
321 ADC_CHANNEL(6, "adc6"),
322 ADC_CHANNEL(7, "adc7"),
323 ADC_CHANNEL(8, "adc8"),
324 ADC_CHANNEL(9, "adc9"),
325};
326
327static int exynos_adc_remove_devices(struct device *dev, void *c)
328{
329 struct platform_device *pdev = to_platform_device(dev);
330
331 platform_device_unregister(pdev);
332
333 return 0;
334}
335
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000336static int exynos_adc_probe(struct platform_device *pdev)
337{
338 struct exynos_adc *info = NULL;
339 struct device_node *np = pdev->dev.of_node;
340 struct iio_dev *indio_dev = NULL;
341 struct resource *mem;
342 int ret = -ENODEV;
343 int irq;
344
345 if (!np)
346 return ret;
347
Sachin Kamatebeb0212013-07-22 12:02:00 +0100348 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct exynos_adc));
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000349 if (!indio_dev) {
350 dev_err(&pdev->dev, "failed allocating iio device\n");
351 return -ENOMEM;
352 }
353
354 info = iio_priv(indio_dev);
355
Chanwoo Choie49d99e2014-07-22 03:04:00 +0100356 info->data = exynos_adc_get_data(pdev);
357 if (!info->data) {
358 dev_err(&pdev->dev, "failed getting exynos_adc_data\n");
359 return -EINVAL;
360 }
361
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000362 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Sachin Kamatc6196532013-04-03 07:23:00 +0100363 info->regs = devm_ioremap_resource(&pdev->dev, mem);
Sachin Kamatebeb0212013-07-22 12:02:00 +0100364 if (IS_ERR(info->regs))
365 return PTR_ERR(info->regs);
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000366
Doug Andersonbb916eb2013-03-13 20:40:00 +0000367 mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
Sachin Kamatc6196532013-04-03 07:23:00 +0100368 info->enable_reg = devm_ioremap_resource(&pdev->dev, mem);
Sachin Kamatebeb0212013-07-22 12:02:00 +0100369 if (IS_ERR(info->enable_reg))
370 return PTR_ERR(info->enable_reg);
Doug Andersonbb916eb2013-03-13 20:40:00 +0000371
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000372 irq = platform_get_irq(pdev, 0);
373 if (irq < 0) {
374 dev_err(&pdev->dev, "no irq resource?\n");
Sachin Kamatebeb0212013-07-22 12:02:00 +0100375 return irq;
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000376 }
377
378 info->irq = irq;
379
380 init_completion(&info->completion);
381
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000382 info->clk = devm_clk_get(&pdev->dev, "adc");
383 if (IS_ERR(info->clk)) {
384 dev_err(&pdev->dev, "failed getting clock, err = %ld\n",
385 PTR_ERR(info->clk));
Naveen Krishna Ch2bbc7242014-04-30 10:26:00 +0100386 return PTR_ERR(info->clk);
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000387 }
388
389 info->vdd = devm_regulator_get(&pdev->dev, "vdd");
390 if (IS_ERR(info->vdd)) {
391 dev_err(&pdev->dev, "failed getting regulator, err = %ld\n",
392 PTR_ERR(info->vdd));
Naveen Krishna Ch2bbc7242014-04-30 10:26:00 +0100393 return PTR_ERR(info->vdd);
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000394 }
395
Naveen Krishna Ch2bbc7242014-04-30 10:26:00 +0100396 ret = regulator_enable(info->vdd);
397 if (ret)
398 return ret;
399
400 ret = clk_prepare_enable(info->clk);
401 if (ret)
402 goto err_disable_reg;
403
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000404 platform_set_drvdata(pdev, indio_dev);
405
406 indio_dev->name = dev_name(&pdev->dev);
407 indio_dev->dev.parent = &pdev->dev;
408 indio_dev->dev.of_node = pdev->dev.of_node;
409 indio_dev->info = &exynos_adc_iio_info;
410 indio_dev->modes = INDIO_DIRECT_MODE;
411 indio_dev->channels = exynos_adc_iio_channels;
Chanwoo Choie49d99e2014-07-22 03:04:00 +0100412 indio_dev->num_channels = info->data->num_channels;
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000413
Naveen Krishna Ch2bbc7242014-04-30 10:26:00 +0100414 ret = request_irq(info->irq, exynos_adc_isr,
415 0, dev_name(&pdev->dev), info);
416 if (ret < 0) {
417 dev_err(&pdev->dev, "failed requesting irq, irq = %d\n",
418 info->irq);
419 goto err_disable_clk;
420 }
421
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000422 ret = iio_device_register(indio_dev);
423 if (ret)
424 goto err_irq;
425
Chanwoo Choie49d99e2014-07-22 03:04:00 +0100426 if (info->data->init_hw)
427 info->data->init_hw(info);
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000428
Naveen Krishna Ch3d821a12014-04-25 11:14:00 +0100429 ret = of_platform_populate(np, exynos_adc_match, NULL, &indio_dev->dev);
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000430 if (ret < 0) {
431 dev_err(&pdev->dev, "failed adding child nodes\n");
432 goto err_of_populate;
433 }
434
435 return 0;
436
437err_of_populate:
Naveen Krishna Ch3d821a12014-04-25 11:14:00 +0100438 device_for_each_child(&indio_dev->dev, NULL,
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000439 exynos_adc_remove_devices);
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000440 iio_device_unregister(indio_dev);
441err_irq:
442 free_irq(info->irq, info);
Naveen Krishna Ch2bbc7242014-04-30 10:26:00 +0100443err_disable_clk:
Chanwoo Choie49d99e2014-07-22 03:04:00 +0100444 if (info->data->exit_hw)
445 info->data->exit_hw(info);
Naveen Krishna Ch2bbc7242014-04-30 10:26:00 +0100446 clk_disable_unprepare(info->clk);
447err_disable_reg:
448 regulator_disable(info->vdd);
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000449 return ret;
450}
451
452static int exynos_adc_remove(struct platform_device *pdev)
453{
454 struct iio_dev *indio_dev = platform_get_drvdata(pdev);
455 struct exynos_adc *info = iio_priv(indio_dev);
456
Naveen Krishna Ch3d821a12014-04-25 11:14:00 +0100457 device_for_each_child(&indio_dev->dev, NULL,
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000458 exynos_adc_remove_devices);
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000459 iio_device_unregister(indio_dev);
460 free_irq(info->irq, info);
Chanwoo Choie49d99e2014-07-22 03:04:00 +0100461 if (info->data->exit_hw)
462 info->data->exit_hw(info);
Naveen Krishna Ch2bbc7242014-04-30 10:26:00 +0100463 clk_disable_unprepare(info->clk);
464 regulator_disable(info->vdd);
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000465
466 return 0;
467}
468
469#ifdef CONFIG_PM_SLEEP
470static int exynos_adc_suspend(struct device *dev)
471{
Naveen Krishna Chatradhi927b4dc2013-05-20 07:34:00 +0100472 struct iio_dev *indio_dev = dev_get_drvdata(dev);
473 struct exynos_adc *info = iio_priv(indio_dev);
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000474
Chanwoo Choie49d99e2014-07-22 03:04:00 +0100475 if (info->data->exit_hw)
476 info->data->exit_hw(info);
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000477
Naveen Krishna Ch2bbc7242014-04-30 10:26:00 +0100478 clk_disable_unprepare(info->clk);
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000479 regulator_disable(info->vdd);
480
481 return 0;
482}
483
484static int exynos_adc_resume(struct device *dev)
485{
Naveen Krishna Chatradhi927b4dc2013-05-20 07:34:00 +0100486 struct iio_dev *indio_dev = dev_get_drvdata(dev);
487 struct exynos_adc *info = iio_priv(indio_dev);
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000488 int ret;
489
490 ret = regulator_enable(info->vdd);
491 if (ret)
492 return ret;
493
Naveen Krishna Ch2bbc7242014-04-30 10:26:00 +0100494 ret = clk_prepare_enable(info->clk);
495 if (ret)
496 return ret;
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000497
Chanwoo Choie49d99e2014-07-22 03:04:00 +0100498 if (info->data->init_hw)
499 info->data->init_hw(info);
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000500
501 return 0;
502}
503#endif
504
505static SIMPLE_DEV_PM_OPS(exynos_adc_pm_ops,
506 exynos_adc_suspend,
507 exynos_adc_resume);
508
509static struct platform_driver exynos_adc_driver = {
510 .probe = exynos_adc_probe,
511 .remove = exynos_adc_remove,
512 .driver = {
513 .name = "exynos-adc",
514 .owner = THIS_MODULE,
Sachin Kamat1ba06862013-03-26 09:42:00 +0000515 .of_match_table = exynos_adc_match,
Naveen Krishna Chatradhi10f5b142013-02-15 06:56:00 +0000516 .pm = &exynos_adc_pm_ops,
517 },
518};
519
520module_platform_driver(exynos_adc_driver);
521
522MODULE_AUTHOR("Naveen Krishna Chatradhi <ch.naveen@samsung.com>");
523MODULE_DESCRIPTION("Samsung EXYNOS5 ADC driver");
524MODULE_LICENSE("GPL v2");