Commit | Line | Data |
---|---|---|
5e53a69b PR |
1 | /* |
2 | * TI ADC MFD driver | |
3 | * | |
4 | * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation version 2. | |
9 | * | |
10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | |
11 | * kind, whether express or implied; without even the implied warranty | |
12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | */ | |
15 | ||
16 | #include <linux/init.h> | |
17 | #include <linux/kernel.h> | |
18 | #include <linux/err.h> | |
19 | #include <linux/module.h> | |
20 | #include <linux/slab.h> | |
21 | #include <linux/interrupt.h> | |
22 | #include <linux/platform_device.h> | |
23 | #include <linux/io.h> | |
24 | #include <linux/iio/iio.h> | |
6f39ac4e PR |
25 | #include <linux/of.h> |
26 | #include <linux/of_device.h> | |
c80df483 PA |
27 | #include <linux/iio/machine.h> |
28 | #include <linux/iio/driver.h> | |
5e53a69b PR |
29 | |
30 | #include <linux/mfd/ti_am335x_tscadc.h> | |
ca9a5638 ZL |
31 | #include <linux/iio/buffer.h> |
32 | #include <linux/iio/kfifo_buf.h> | |
5e53a69b PR |
33 | |
34 | struct tiadc_device { | |
35 | struct ti_tscadc_dev *mfd_tscadc; | |
36 | int channels; | |
18926ede SAS |
37 | u8 channel_line[8]; |
38 | u8 channel_step[8]; | |
ca9a5638 | 39 | int buffer_en_ch_steps; |
ca9a5638 | 40 | u16 data[8]; |
5e53a69b PR |
41 | }; |
42 | ||
43 | static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg) | |
44 | { | |
45 | return readl(adc->mfd_tscadc->tscadc_base + reg); | |
46 | } | |
47 | ||
48 | static void tiadc_writel(struct tiadc_device *adc, unsigned int reg, | |
49 | unsigned int val) | |
50 | { | |
51 | writel(val, adc->mfd_tscadc->tscadc_base + reg); | |
52 | } | |
53 | ||
abeccee4 PR |
54 | static u32 get_adc_step_mask(struct tiadc_device *adc_dev) |
55 | { | |
56 | u32 step_en; | |
57 | ||
58 | step_en = ((1 << adc_dev->channels) - 1); | |
59 | step_en <<= TOTAL_STEPS - adc_dev->channels + 1; | |
60 | return step_en; | |
61 | } | |
62 | ||
ca9a5638 | 63 | static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan) |
5e53a69b | 64 | { |
ca9a5638 ZL |
65 | return 1 << adc_dev->channel_step[chan]; |
66 | } | |
67 | ||
68 | static void tiadc_step_config(struct iio_dev *indio_dev) | |
69 | { | |
70 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
5e53a69b | 71 | unsigned int stepconfig; |
18926ede | 72 | int i, steps; |
5e53a69b PR |
73 | |
74 | /* | |
75 | * There are 16 configurable steps and 8 analog input | |
76 | * lines available which are shared between Touchscreen and ADC. | |
77 | * | |
78 | * Steps backwards i.e. from 16 towards 0 are used by ADC | |
79 | * depending on number of input lines needed. | |
80 | * Channel would represent which analog input | |
81 | * needs to be given to ADC to digitalize data. | |
82 | */ | |
83 | ||
84 | steps = TOTAL_STEPS - adc_dev->channels; | |
ca9a5638 ZL |
85 | if (iio_buffer_enabled(indio_dev)) |
86 | stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1 | |
87 | | STEPCONFIG_MODE_SWCNT; | |
88 | else | |
89 | stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1; | |
5e53a69b | 90 | |
18926ede SAS |
91 | for (i = 0; i < adc_dev->channels; i++) { |
92 | int chan; | |
93 | ||
94 | chan = adc_dev->channel_line[i]; | |
95 | tiadc_writel(adc_dev, REG_STEPCONFIG(steps), | |
96 | stepconfig | STEPCONFIG_INP(chan)); | |
97 | tiadc_writel(adc_dev, REG_STEPDELAY(steps), | |
5e53a69b | 98 | STEPCONFIG_OPENDLY); |
18926ede SAS |
99 | adc_dev->channel_step[i] = steps; |
100 | steps++; | |
5e53a69b | 101 | } |
ca9a5638 ZL |
102 | } |
103 | ||
104 | static irqreturn_t tiadc_irq_h(int irq, void *private) | |
105 | { | |
106 | struct iio_dev *indio_dev = private; | |
107 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
108 | unsigned int status, config; | |
109 | status = tiadc_readl(adc_dev, REG_IRQSTATUS); | |
110 | ||
111 | /* | |
112 | * ADC and touchscreen share the IRQ line. | |
113 | * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only | |
114 | */ | |
115 | if (status & IRQENB_FIFO1OVRRUN) { | |
116 | /* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */ | |
117 | config = tiadc_readl(adc_dev, REG_CTRL); | |
118 | config &= ~(CNTRLREG_TSCSSENB); | |
119 | tiadc_writel(adc_dev, REG_CTRL, config); | |
120 | tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN | |
121 | | IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES); | |
122 | tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB)); | |
123 | return IRQ_HANDLED; | |
124 | } else if (status & IRQENB_FIFO1THRES) { | |
125 | /* Disable irq and wake worker thread */ | |
126 | tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES); | |
127 | return IRQ_WAKE_THREAD; | |
128 | } | |
129 | ||
130 | return IRQ_NONE; | |
131 | } | |
132 | ||
133 | static irqreturn_t tiadc_worker_h(int irq, void *private) | |
134 | { | |
135 | struct iio_dev *indio_dev = private; | |
136 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
137 | int i, k, fifo1count, read; | |
138 | u16 *data = adc_dev->data; | |
139 | ||
140 | fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); | |
141 | for (k = 0; k < fifo1count; k = k + i) { | |
142 | for (i = 0; i < (indio_dev->scan_bytes)/2; i++) { | |
143 | read = tiadc_readl(adc_dev, REG_FIFO1); | |
144 | data[i] = read & FIFOREAD_DATA_MASK; | |
145 | } | |
146 | iio_push_to_buffers(indio_dev, (u8 *) data); | |
147 | } | |
148 | ||
149 | tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES); | |
150 | tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES); | |
151 | ||
152 | return IRQ_HANDLED; | |
153 | } | |
154 | ||
155 | static int tiadc_buffer_preenable(struct iio_dev *indio_dev) | |
156 | { | |
157 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
158 | int i, fifo1count, read; | |
159 | ||
160 | tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES | | |
161 | IRQENB_FIFO1OVRRUN | | |
162 | IRQENB_FIFO1UNDRFLW)); | |
163 | ||
164 | /* Flush FIFO. Needed in corner cases in simultaneous tsc/adc use */ | |
165 | fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); | |
166 | for (i = 0; i < fifo1count; i++) | |
167 | read = tiadc_readl(adc_dev, REG_FIFO1); | |
168 | ||
169 | return iio_sw_buffer_preenable(indio_dev); | |
170 | } | |
171 | ||
172 | static int tiadc_buffer_postenable(struct iio_dev *indio_dev) | |
173 | { | |
174 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
175 | struct iio_buffer *buffer = indio_dev->buffer; | |
176 | unsigned int enb = 0; | |
177 | u8 bit; | |
178 | ||
179 | tiadc_step_config(indio_dev); | |
180 | for_each_set_bit(bit, buffer->scan_mask, adc_dev->channels) | |
181 | enb |= (get_adc_step_bit(adc_dev, bit) << 1); | |
182 | adc_dev->buffer_en_ch_steps = enb; | |
183 | ||
184 | am335x_tsc_se_set(adc_dev->mfd_tscadc, enb); | |
185 | ||
186 | tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES | |
187 | | IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW); | |
188 | tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES | |
189 | | IRQENB_FIFO1OVRRUN); | |
190 | ||
191 | return 0; | |
192 | } | |
193 | ||
194 | static int tiadc_buffer_predisable(struct iio_dev *indio_dev) | |
195 | { | |
196 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
197 | int fifo1count, i, read; | |
198 | ||
199 | tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES | | |
200 | IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW)); | |
201 | am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps); | |
b1451e54 | 202 | |
ca9a5638 ZL |
203 | /* Flush FIFO of leftover data in the time it takes to disable adc */ |
204 | fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); | |
205 | for (i = 0; i < fifo1count; i++) | |
206 | read = tiadc_readl(adc_dev, REG_FIFO1); | |
207 | ||
208 | return 0; | |
5e53a69b PR |
209 | } |
210 | ||
ca9a5638 ZL |
211 | static int tiadc_buffer_postdisable(struct iio_dev *indio_dev) |
212 | { | |
213 | tiadc_step_config(indio_dev); | |
214 | ||
215 | return 0; | |
216 | } | |
217 | ||
218 | static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = { | |
219 | .preenable = &tiadc_buffer_preenable, | |
220 | .postenable = &tiadc_buffer_postenable, | |
221 | .predisable = &tiadc_buffer_predisable, | |
222 | .postdisable = &tiadc_buffer_postdisable, | |
223 | }; | |
224 | ||
98c08cf4 | 225 | static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev, |
ca9a5638 ZL |
226 | irqreturn_t (*pollfunc_bh)(int irq, void *p), |
227 | irqreturn_t (*pollfunc_th)(int irq, void *p), | |
228 | int irq, | |
229 | unsigned long flags, | |
230 | const struct iio_buffer_setup_ops *setup_ops) | |
231 | { | |
232 | int ret; | |
233 | ||
234 | indio_dev->buffer = iio_kfifo_allocate(indio_dev); | |
235 | if (!indio_dev->buffer) | |
236 | return -ENOMEM; | |
237 | ||
238 | ret = request_threaded_irq(irq, pollfunc_th, pollfunc_bh, | |
239 | flags, indio_dev->name, indio_dev); | |
240 | if (ret) | |
241 | goto error_kfifo_free; | |
242 | ||
243 | indio_dev->setup_ops = setup_ops; | |
244 | indio_dev->modes |= INDIO_BUFFER_HARDWARE; | |
245 | ||
246 | ret = iio_buffer_register(indio_dev, | |
247 | indio_dev->channels, | |
248 | indio_dev->num_channels); | |
249 | if (ret) | |
250 | goto error_free_irq; | |
251 | ||
252 | return 0; | |
253 | ||
254 | error_free_irq: | |
255 | free_irq(irq, indio_dev); | |
256 | error_kfifo_free: | |
257 | iio_kfifo_free(indio_dev->buffer); | |
258 | return ret; | |
259 | } | |
260 | ||
261 | static void tiadc_iio_buffered_hardware_remove(struct iio_dev *indio_dev) | |
262 | { | |
263 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
264 | ||
265 | free_irq(adc_dev->mfd_tscadc->irq, indio_dev); | |
266 | iio_kfifo_free(indio_dev->buffer); | |
267 | iio_buffer_unregister(indio_dev); | |
268 | } | |
269 | ||
270 | ||
c80df483 PA |
271 | static const char * const chan_name_ain[] = { |
272 | "AIN0", | |
273 | "AIN1", | |
274 | "AIN2", | |
275 | "AIN3", | |
276 | "AIN4", | |
277 | "AIN5", | |
278 | "AIN6", | |
279 | "AIN7", | |
280 | }; | |
281 | ||
5e53a69b PR |
282 | static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) |
283 | { | |
c80df483 | 284 | struct tiadc_device *adc_dev = iio_priv(indio_dev); |
5e53a69b | 285 | struct iio_chan_spec *chan_array; |
c80df483 | 286 | struct iio_chan_spec *chan; |
5e53a69b PR |
287 | int i; |
288 | ||
289 | indio_dev->num_channels = channels; | |
c80df483 | 290 | chan_array = kcalloc(channels, |
5e53a69b | 291 | sizeof(struct iio_chan_spec), GFP_KERNEL); |
5e53a69b PR |
292 | if (chan_array == NULL) |
293 | return -ENOMEM; | |
294 | ||
c80df483 PA |
295 | chan = chan_array; |
296 | for (i = 0; i < channels; i++, chan++) { | |
297 | ||
5e53a69b PR |
298 | chan->type = IIO_VOLTAGE; |
299 | chan->indexed = 1; | |
18926ede | 300 | chan->channel = adc_dev->channel_line[i]; |
6c572522 | 301 | chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); |
18926ede | 302 | chan->datasheet_name = chan_name_ain[chan->channel]; |
ca9a5638 | 303 | chan->scan_index = i; |
c80df483 PA |
304 | chan->scan_type.sign = 'u'; |
305 | chan->scan_type.realbits = 12; | |
0f6fc7d5 | 306 | chan->scan_type.storagebits = 16; |
5e53a69b PR |
307 | } |
308 | ||
309 | indio_dev->channels = chan_array; | |
310 | ||
c80df483 | 311 | return 0; |
5e53a69b PR |
312 | } |
313 | ||
314 | static void tiadc_channels_remove(struct iio_dev *indio_dev) | |
315 | { | |
316 | kfree(indio_dev->channels); | |
317 | } | |
318 | ||
319 | static int tiadc_read_raw(struct iio_dev *indio_dev, | |
320 | struct iio_chan_spec const *chan, | |
321 | int *val, int *val2, long mask) | |
322 | { | |
323 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
b1451e54 PR |
324 | int i, map_val; |
325 | unsigned int fifo1count, read, stepid; | |
18926ede | 326 | u32 step = UINT_MAX; |
1460c152 | 327 | bool found = false; |
b1451e54 PR |
328 | u32 step_en; |
329 | unsigned long timeout = jiffies + usecs_to_jiffies | |
330 | (IDLE_TIMEOUT * adc_dev->channels); | |
ca9a5638 ZL |
331 | |
332 | if (iio_buffer_enabled(indio_dev)) | |
333 | return -EBUSY; | |
334 | ||
b1451e54 PR |
335 | step_en = get_adc_step_mask(adc_dev); |
336 | am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en); | |
337 | ||
338 | /* Wait for ADC sequencer to complete sampling */ | |
339 | while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) { | |
340 | if (time_after(jiffies, timeout)) | |
341 | return -EAGAIN; | |
342 | } | |
343 | map_val = chan->channel + TOTAL_CHANNELS; | |
5e53a69b PR |
344 | |
345 | /* | |
346 | * When the sub-system is first enabled, | |
347 | * the sequencer will always start with the | |
348 | * lowest step (1) and continue until step (16). | |
349 | * For ex: If we have enabled 4 ADC channels and | |
350 | * currently use only 1 out of them, the | |
351 | * sequencer still configures all the 4 steps, | |
352 | * leading to 3 unwanted data. | |
353 | * Hence we need to flush out this data. | |
354 | */ | |
355 | ||
18926ede SAS |
356 | for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) { |
357 | if (chan->channel == adc_dev->channel_line[i]) { | |
358 | step = adc_dev->channel_step[i]; | |
359 | break; | |
360 | } | |
361 | } | |
362 | if (WARN_ON_ONCE(step == UINT_MAX)) | |
363 | return -EINVAL; | |
364 | ||
5e53a69b PR |
365 | fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); |
366 | for (i = 0; i < fifo1count; i++) { | |
18926ede | 367 | read = tiadc_readl(adc_dev, REG_FIFO1); |
b1451e54 PR |
368 | stepid = read & FIFOREAD_CHNLID_MASK; |
369 | stepid = stepid >> 0x10; | |
370 | ||
371 | if (stepid == map_val) { | |
372 | read = read & FIFOREAD_DATA_MASK; | |
1460c152 | 373 | found = true; |
0f6fc7d5 | 374 | *val = (u16) read; |
1460c152 | 375 | } |
5e53a69b | 376 | } |
b1451e54 | 377 | |
1460c152 SAS |
378 | if (found == false) |
379 | return -EBUSY; | |
5e53a69b PR |
380 | return IIO_VAL_INT; |
381 | } | |
382 | ||
383 | static const struct iio_info tiadc_info = { | |
384 | .read_raw = &tiadc_read_raw, | |
bc93aa76 | 385 | .driver_module = THIS_MODULE, |
5e53a69b PR |
386 | }; |
387 | ||
fc52692c | 388 | static int tiadc_probe(struct platform_device *pdev) |
5e53a69b PR |
389 | { |
390 | struct iio_dev *indio_dev; | |
391 | struct tiadc_device *adc_dev; | |
6f39ac4e | 392 | struct device_node *node = pdev->dev.of_node; |
18926ede SAS |
393 | struct property *prop; |
394 | const __be32 *cur; | |
5e53a69b | 395 | int err; |
18926ede SAS |
396 | u32 val; |
397 | int channels = 0; | |
5e53a69b | 398 | |
0ead4fb2 SAS |
399 | if (!node) { |
400 | dev_err(&pdev->dev, "Could not find valid DT data.\n"); | |
5e53a69b PR |
401 | return -EINVAL; |
402 | } | |
403 | ||
a0648130 SK |
404 | indio_dev = devm_iio_device_alloc(&pdev->dev, |
405 | sizeof(struct tiadc_device)); | |
5e53a69b PR |
406 | if (indio_dev == NULL) { |
407 | dev_err(&pdev->dev, "failed to allocate iio device\n"); | |
a0648130 | 408 | return -ENOMEM; |
5e53a69b PR |
409 | } |
410 | adc_dev = iio_priv(indio_dev); | |
411 | ||
6f39ac4e PR |
412 | adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev); |
413 | ||
18926ede SAS |
414 | of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) { |
415 | adc_dev->channel_line[channels] = val; | |
416 | channels++; | |
417 | } | |
418 | adc_dev->channels = channels; | |
5e53a69b PR |
419 | |
420 | indio_dev->dev.parent = &pdev->dev; | |
421 | indio_dev->name = dev_name(&pdev->dev); | |
422 | indio_dev->modes = INDIO_DIRECT_MODE; | |
423 | indio_dev->info = &tiadc_info; | |
424 | ||
ca9a5638 ZL |
425 | tiadc_step_config(indio_dev); |
426 | tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD); | |
5e53a69b PR |
427 | |
428 | err = tiadc_channel_init(indio_dev, adc_dev->channels); | |
429 | if (err < 0) | |
a0648130 | 430 | return err; |
5e53a69b | 431 | |
ca9a5638 ZL |
432 | err = tiadc_iio_buffered_hardware_setup(indio_dev, |
433 | &tiadc_worker_h, | |
434 | &tiadc_irq_h, | |
435 | adc_dev->mfd_tscadc->irq, | |
436 | IRQF_SHARED, | |
437 | &tiadc_buffer_setup_ops); | |
438 | ||
5e53a69b PR |
439 | if (err) |
440 | goto err_free_channels; | |
441 | ||
ca9a5638 ZL |
442 | err = iio_device_register(indio_dev); |
443 | if (err) | |
444 | goto err_buffer_unregister; | |
445 | ||
5e53a69b PR |
446 | platform_set_drvdata(pdev, indio_dev); |
447 | ||
448 | return 0; | |
449 | ||
ca9a5638 ZL |
450 | err_buffer_unregister: |
451 | tiadc_iio_buffered_hardware_remove(indio_dev); | |
5e53a69b PR |
452 | err_free_channels: |
453 | tiadc_channels_remove(indio_dev); | |
5e53a69b PR |
454 | return err; |
455 | } | |
456 | ||
fc52692c | 457 | static int tiadc_remove(struct platform_device *pdev) |
5e53a69b PR |
458 | { |
459 | struct iio_dev *indio_dev = platform_get_drvdata(pdev); | |
abeccee4 PR |
460 | struct tiadc_device *adc_dev = iio_priv(indio_dev); |
461 | u32 step_en; | |
5e53a69b PR |
462 | |
463 | iio_device_unregister(indio_dev); | |
ca9a5638 | 464 | tiadc_iio_buffered_hardware_remove(indio_dev); |
5e53a69b PR |
465 | tiadc_channels_remove(indio_dev); |
466 | ||
abeccee4 PR |
467 | step_en = get_adc_step_mask(adc_dev); |
468 | am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en); | |
469 | ||
5e53a69b PR |
470 | return 0; |
471 | } | |
472 | ||
473 | #ifdef CONFIG_PM | |
474 | static int tiadc_suspend(struct device *dev) | |
475 | { | |
476 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
477 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
a9bce1b0 | 478 | struct ti_tscadc_dev *tscadc_dev; |
5e53a69b PR |
479 | unsigned int idle; |
480 | ||
a9bce1b0 | 481 | tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); |
5e53a69b PR |
482 | if (!device_may_wakeup(tscadc_dev->dev)) { |
483 | idle = tiadc_readl(adc_dev, REG_CTRL); | |
484 | idle &= ~(CNTRLREG_TSCSSENB); | |
485 | tiadc_writel(adc_dev, REG_CTRL, (idle | | |
486 | CNTRLREG_POWERDOWN)); | |
487 | } | |
488 | ||
489 | return 0; | |
490 | } | |
491 | ||
492 | static int tiadc_resume(struct device *dev) | |
493 | { | |
494 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
495 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
496 | unsigned int restore; | |
497 | ||
498 | /* Make sure ADC is powered up */ | |
499 | restore = tiadc_readl(adc_dev, REG_CTRL); | |
500 | restore &= ~(CNTRLREG_POWERDOWN); | |
501 | tiadc_writel(adc_dev, REG_CTRL, restore); | |
502 | ||
ca9a5638 | 503 | tiadc_step_config(indio_dev); |
5e53a69b PR |
504 | |
505 | return 0; | |
506 | } | |
507 | ||
508 | static const struct dev_pm_ops tiadc_pm_ops = { | |
509 | .suspend = tiadc_suspend, | |
510 | .resume = tiadc_resume, | |
511 | }; | |
512 | #define TIADC_PM_OPS (&tiadc_pm_ops) | |
513 | #else | |
514 | #define TIADC_PM_OPS NULL | |
515 | #endif | |
516 | ||
6f39ac4e PR |
517 | static const struct of_device_id ti_adc_dt_ids[] = { |
518 | { .compatible = "ti,am3359-adc", }, | |
519 | { } | |
520 | }; | |
521 | MODULE_DEVICE_TABLE(of, ti_adc_dt_ids); | |
522 | ||
5e53a69b PR |
523 | static struct platform_driver tiadc_driver = { |
524 | .driver = { | |
9f99928f | 525 | .name = "TI-am335x-adc", |
5e53a69b PR |
526 | .owner = THIS_MODULE, |
527 | .pm = TIADC_PM_OPS, | |
6f39ac4e | 528 | .of_match_table = of_match_ptr(ti_adc_dt_ids), |
5e53a69b PR |
529 | }, |
530 | .probe = tiadc_probe, | |
fc52692c | 531 | .remove = tiadc_remove, |
5e53a69b | 532 | }; |
5e53a69b PR |
533 | module_platform_driver(tiadc_driver); |
534 | ||
535 | MODULE_DESCRIPTION("TI ADC controller driver"); | |
536 | MODULE_AUTHOR("Rachna Patil <rachna@ti.com>"); | |
537 | MODULE_LICENSE("GPL"); |