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 | ||
5e53a69b PR |
16 | #include <linux/kernel.h> |
17 | #include <linux/err.h> | |
18 | #include <linux/module.h> | |
19 | #include <linux/slab.h> | |
20 | #include <linux/interrupt.h> | |
21 | #include <linux/platform_device.h> | |
22 | #include <linux/io.h> | |
23 | #include <linux/iio/iio.h> | |
6f39ac4e PR |
24 | #include <linux/of.h> |
25 | #include <linux/of_device.h> | |
c80df483 PA |
26 | #include <linux/iio/machine.h> |
27 | #include <linux/iio/driver.h> | |
5e53a69b PR |
28 | |
29 | #include <linux/mfd/ti_am335x_tscadc.h> | |
ca9a5638 ZL |
30 | #include <linux/iio/buffer.h> |
31 | #include <linux/iio/kfifo_buf.h> | |
5e53a69b PR |
32 | |
33 | struct tiadc_device { | |
34 | struct ti_tscadc_dev *mfd_tscadc; | |
35 | int channels; | |
18926ede SAS |
36 | u8 channel_line[8]; |
37 | u8 channel_step[8]; | |
ca9a5638 | 38 | int buffer_en_ch_steps; |
ca9a5638 | 39 | u16 data[8]; |
5dc11e81 | 40 | u32 open_delay[8], sample_delay[8], step_avg[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 | ||
7ca6740c SAS |
63 | static u32 get_adc_chan_step_mask(struct tiadc_device *adc_dev, |
64 | struct iio_chan_spec const *chan) | |
65 | { | |
66 | int i; | |
67 | ||
68 | for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) { | |
69 | if (chan->channel == adc_dev->channel_line[i]) { | |
70 | u32 step; | |
71 | ||
72 | step = adc_dev->channel_step[i]; | |
73 | /* +1 for the charger */ | |
74 | return 1 << (step + 1); | |
75 | } | |
76 | } | |
77 | WARN_ON(1); | |
78 | return 0; | |
79 | } | |
80 | ||
ca9a5638 | 81 | static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan) |
5e53a69b | 82 | { |
ca9a5638 ZL |
83 | return 1 << adc_dev->channel_step[chan]; |
84 | } | |
85 | ||
86 | static void tiadc_step_config(struct iio_dev *indio_dev) | |
87 | { | |
88 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
5dc11e81 | 89 | struct device *dev = adc_dev->mfd_tscadc->dev; |
5e53a69b | 90 | unsigned int stepconfig; |
3a59684c | 91 | int i, steps = 0; |
5e53a69b PR |
92 | |
93 | /* | |
94 | * There are 16 configurable steps and 8 analog input | |
95 | * lines available which are shared between Touchscreen and ADC. | |
96 | * | |
3a59684c | 97 | * Steps forwards i.e. from 0 towards 16 are used by ADC |
5e53a69b PR |
98 | * depending on number of input lines needed. |
99 | * Channel would represent which analog input | |
100 | * needs to be given to ADC to digitalize data. | |
101 | */ | |
102 | ||
5e53a69b | 103 | |
18926ede SAS |
104 | for (i = 0; i < adc_dev->channels; i++) { |
105 | int chan; | |
106 | ||
107 | chan = adc_dev->channel_line[i]; | |
5dc11e81 V |
108 | |
109 | if (adc_dev->step_avg[i] > STEPCONFIG_AVG_16) { | |
110 | dev_warn(dev, "chan %d step_avg truncating to %d\n", | |
111 | chan, STEPCONFIG_AVG_16); | |
112 | adc_dev->step_avg[i] = STEPCONFIG_AVG_16; | |
113 | } | |
114 | ||
115 | if (adc_dev->step_avg[i]) | |
116 | stepconfig = | |
117 | STEPCONFIG_AVG(ffs(adc_dev->step_avg[i]) - 1) | | |
118 | STEPCONFIG_FIFO1; | |
119 | else | |
120 | stepconfig = STEPCONFIG_FIFO1; | |
121 | ||
122 | if (iio_buffer_enabled(indio_dev)) | |
123 | stepconfig |= STEPCONFIG_MODE_SWCNT; | |
124 | ||
18926ede SAS |
125 | tiadc_writel(adc_dev, REG_STEPCONFIG(steps), |
126 | stepconfig | STEPCONFIG_INP(chan)); | |
5dc11e81 V |
127 | |
128 | if (adc_dev->open_delay[i] > STEPDELAY_OPEN_MASK) { | |
129 | dev_warn(dev, "chan %d open delay truncating to 0x3FFFF\n", | |
130 | chan); | |
131 | adc_dev->open_delay[i] = STEPDELAY_OPEN_MASK; | |
132 | } | |
133 | ||
134 | if (adc_dev->sample_delay[i] > 0xFF) { | |
135 | dev_warn(dev, "chan %d sample delay truncating to 0xFF\n", | |
136 | chan); | |
137 | adc_dev->sample_delay[i] = 0xFF; | |
138 | } | |
139 | ||
18926ede | 140 | tiadc_writel(adc_dev, REG_STEPDELAY(steps), |
5dc11e81 V |
141 | STEPDELAY_OPEN(adc_dev->open_delay[i]) | |
142 | STEPDELAY_SAMPLE(adc_dev->sample_delay[i])); | |
143 | ||
18926ede SAS |
144 | adc_dev->channel_step[i] = steps; |
145 | steps++; | |
5e53a69b | 146 | } |
ca9a5638 ZL |
147 | } |
148 | ||
149 | static irqreturn_t tiadc_irq_h(int irq, void *private) | |
150 | { | |
151 | struct iio_dev *indio_dev = private; | |
152 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
153 | unsigned int status, config; | |
154 | status = tiadc_readl(adc_dev, REG_IRQSTATUS); | |
155 | ||
156 | /* | |
157 | * ADC and touchscreen share the IRQ line. | |
158 | * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only | |
159 | */ | |
160 | if (status & IRQENB_FIFO1OVRRUN) { | |
161 | /* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */ | |
162 | config = tiadc_readl(adc_dev, REG_CTRL); | |
163 | config &= ~(CNTRLREG_TSCSSENB); | |
164 | tiadc_writel(adc_dev, REG_CTRL, config); | |
165 | tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN | |
166 | | IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES); | |
167 | tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB)); | |
168 | return IRQ_HANDLED; | |
169 | } else if (status & IRQENB_FIFO1THRES) { | |
170 | /* Disable irq and wake worker thread */ | |
171 | tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES); | |
172 | return IRQ_WAKE_THREAD; | |
173 | } | |
174 | ||
175 | return IRQ_NONE; | |
176 | } | |
177 | ||
178 | static irqreturn_t tiadc_worker_h(int irq, void *private) | |
179 | { | |
180 | struct iio_dev *indio_dev = private; | |
181 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
182 | int i, k, fifo1count, read; | |
183 | u16 *data = adc_dev->data; | |
184 | ||
185 | fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); | |
186 | for (k = 0; k < fifo1count; k = k + i) { | |
187 | for (i = 0; i < (indio_dev->scan_bytes)/2; i++) { | |
188 | read = tiadc_readl(adc_dev, REG_FIFO1); | |
189 | data[i] = read & FIFOREAD_DATA_MASK; | |
190 | } | |
191 | iio_push_to_buffers(indio_dev, (u8 *) data); | |
192 | } | |
193 | ||
194 | tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES); | |
195 | tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES); | |
196 | ||
197 | return IRQ_HANDLED; | |
198 | } | |
199 | ||
200 | static int tiadc_buffer_preenable(struct iio_dev *indio_dev) | |
201 | { | |
202 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
203 | int i, fifo1count, read; | |
204 | ||
205 | tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES | | |
206 | IRQENB_FIFO1OVRRUN | | |
207 | IRQENB_FIFO1UNDRFLW)); | |
208 | ||
209 | /* Flush FIFO. Needed in corner cases in simultaneous tsc/adc use */ | |
210 | fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); | |
211 | for (i = 0; i < fifo1count; i++) | |
212 | read = tiadc_readl(adc_dev, REG_FIFO1); | |
213 | ||
24adaf79 | 214 | return 0; |
ca9a5638 ZL |
215 | } |
216 | ||
217 | static int tiadc_buffer_postenable(struct iio_dev *indio_dev) | |
218 | { | |
219 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
ca9a5638 ZL |
220 | unsigned int enb = 0; |
221 | u8 bit; | |
222 | ||
223 | tiadc_step_config(indio_dev); | |
70dddeee | 224 | for_each_set_bit(bit, indio_dev->active_scan_mask, adc_dev->channels) |
ca9a5638 ZL |
225 | enb |= (get_adc_step_bit(adc_dev, bit) << 1); |
226 | adc_dev->buffer_en_ch_steps = enb; | |
227 | ||
7e170c6e | 228 | am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, enb); |
ca9a5638 ZL |
229 | |
230 | tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES | |
231 | | IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW); | |
232 | tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES | |
233 | | IRQENB_FIFO1OVRRUN); | |
234 | ||
235 | return 0; | |
236 | } | |
237 | ||
238 | static int tiadc_buffer_predisable(struct iio_dev *indio_dev) | |
239 | { | |
240 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
241 | int fifo1count, i, read; | |
242 | ||
243 | tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES | | |
244 | IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW)); | |
245 | am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps); | |
3954b7bf | 246 | adc_dev->buffer_en_ch_steps = 0; |
b1451e54 | 247 | |
ca9a5638 ZL |
248 | /* Flush FIFO of leftover data in the time it takes to disable adc */ |
249 | fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); | |
250 | for (i = 0; i < fifo1count; i++) | |
251 | read = tiadc_readl(adc_dev, REG_FIFO1); | |
252 | ||
253 | return 0; | |
5e53a69b PR |
254 | } |
255 | ||
ca9a5638 ZL |
256 | static int tiadc_buffer_postdisable(struct iio_dev *indio_dev) |
257 | { | |
258 | tiadc_step_config(indio_dev); | |
259 | ||
260 | return 0; | |
261 | } | |
262 | ||
263 | static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = { | |
264 | .preenable = &tiadc_buffer_preenable, | |
265 | .postenable = &tiadc_buffer_postenable, | |
266 | .predisable = &tiadc_buffer_predisable, | |
267 | .postdisable = &tiadc_buffer_postdisable, | |
268 | }; | |
269 | ||
98c08cf4 | 270 | static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev, |
ca9a5638 ZL |
271 | irqreturn_t (*pollfunc_bh)(int irq, void *p), |
272 | irqreturn_t (*pollfunc_th)(int irq, void *p), | |
273 | int irq, | |
274 | unsigned long flags, | |
275 | const struct iio_buffer_setup_ops *setup_ops) | |
276 | { | |
fe26980e | 277 | struct iio_buffer *buffer; |
ca9a5638 ZL |
278 | int ret; |
279 | ||
7ab374a0 | 280 | buffer = iio_kfifo_allocate(); |
fe26980e | 281 | if (!buffer) |
ca9a5638 ZL |
282 | return -ENOMEM; |
283 | ||
fe26980e LPC |
284 | iio_device_attach_buffer(indio_dev, buffer); |
285 | ||
ca9a5638 ZL |
286 | ret = request_threaded_irq(irq, pollfunc_th, pollfunc_bh, |
287 | flags, indio_dev->name, indio_dev); | |
288 | if (ret) | |
289 | goto error_kfifo_free; | |
290 | ||
291 | indio_dev->setup_ops = setup_ops; | |
9d0be85d | 292 | indio_dev->modes |= INDIO_BUFFER_SOFTWARE; |
ca9a5638 | 293 | |
ca9a5638 ZL |
294 | return 0; |
295 | ||
ca9a5638 ZL |
296 | error_kfifo_free: |
297 | iio_kfifo_free(indio_dev->buffer); | |
298 | return ret; | |
299 | } | |
300 | ||
301 | static void tiadc_iio_buffered_hardware_remove(struct iio_dev *indio_dev) | |
302 | { | |
303 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
304 | ||
305 | free_irq(adc_dev->mfd_tscadc->irq, indio_dev); | |
306 | iio_kfifo_free(indio_dev->buffer); | |
ca9a5638 ZL |
307 | } |
308 | ||
309 | ||
c80df483 PA |
310 | static const char * const chan_name_ain[] = { |
311 | "AIN0", | |
312 | "AIN1", | |
313 | "AIN2", | |
314 | "AIN3", | |
315 | "AIN4", | |
316 | "AIN5", | |
317 | "AIN6", | |
318 | "AIN7", | |
319 | }; | |
320 | ||
5e53a69b PR |
321 | static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) |
322 | { | |
c80df483 | 323 | struct tiadc_device *adc_dev = iio_priv(indio_dev); |
5e53a69b | 324 | struct iio_chan_spec *chan_array; |
c80df483 | 325 | struct iio_chan_spec *chan; |
5e53a69b PR |
326 | int i; |
327 | ||
328 | indio_dev->num_channels = channels; | |
c80df483 | 329 | chan_array = kcalloc(channels, |
5e53a69b | 330 | sizeof(struct iio_chan_spec), GFP_KERNEL); |
5e53a69b PR |
331 | if (chan_array == NULL) |
332 | return -ENOMEM; | |
333 | ||
c80df483 PA |
334 | chan = chan_array; |
335 | for (i = 0; i < channels; i++, chan++) { | |
336 | ||
5e53a69b PR |
337 | chan->type = IIO_VOLTAGE; |
338 | chan->indexed = 1; | |
18926ede | 339 | chan->channel = adc_dev->channel_line[i]; |
6c572522 | 340 | chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); |
18926ede | 341 | chan->datasheet_name = chan_name_ain[chan->channel]; |
ca9a5638 | 342 | chan->scan_index = i; |
c80df483 PA |
343 | chan->scan_type.sign = 'u'; |
344 | chan->scan_type.realbits = 12; | |
0f6fc7d5 | 345 | chan->scan_type.storagebits = 16; |
5e53a69b PR |
346 | } |
347 | ||
348 | indio_dev->channels = chan_array; | |
349 | ||
c80df483 | 350 | return 0; |
5e53a69b PR |
351 | } |
352 | ||
353 | static void tiadc_channels_remove(struct iio_dev *indio_dev) | |
354 | { | |
355 | kfree(indio_dev->channels); | |
356 | } | |
357 | ||
358 | static int tiadc_read_raw(struct iio_dev *indio_dev, | |
359 | struct iio_chan_spec const *chan, | |
360 | int *val, int *val2, long mask) | |
361 | { | |
362 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
b1451e54 PR |
363 | int i, map_val; |
364 | unsigned int fifo1count, read, stepid; | |
1460c152 | 365 | bool found = false; |
b1451e54 | 366 | u32 step_en; |
7ca6740c | 367 | unsigned long timeout; |
ca9a5638 ZL |
368 | |
369 | if (iio_buffer_enabled(indio_dev)) | |
370 | return -EBUSY; | |
371 | ||
7ca6740c SAS |
372 | step_en = get_adc_chan_step_mask(adc_dev, chan); |
373 | if (!step_en) | |
374 | return -EINVAL; | |
375 | ||
376 | fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); | |
377 | while (fifo1count--) | |
378 | tiadc_readl(adc_dev, REG_FIFO1); | |
379 | ||
7e170c6e | 380 | am335x_tsc_se_set_once(adc_dev->mfd_tscadc, step_en); |
b1451e54 | 381 | |
7ca6740c SAS |
382 | timeout = jiffies + usecs_to_jiffies |
383 | (IDLE_TIMEOUT * adc_dev->channels); | |
384 | /* Wait for Fifo threshold interrupt */ | |
385 | while (1) { | |
386 | fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); | |
387 | if (fifo1count) | |
388 | break; | |
389 | ||
390 | if (time_after(jiffies, timeout)) { | |
391 | am335x_tsc_se_adc_done(adc_dev->mfd_tscadc); | |
b1451e54 PR |
392 | return -EAGAIN; |
393 | } | |
fb7f8ce3 | 394 | } |
baa3c652 | 395 | map_val = adc_dev->channel_step[chan->scan_index]; |
5e53a69b PR |
396 | |
397 | /* | |
7ca6740c SAS |
398 | * We check the complete FIFO. We programmed just one entry but in case |
399 | * something went wrong we left empty handed (-EAGAIN previously) and | |
400 | * then the value apeared somehow in the FIFO we would have two entries. | |
401 | * Therefore we read every item and keep only the latest version of the | |
402 | * requested channel. | |
5e53a69b | 403 | */ |
5e53a69b | 404 | for (i = 0; i < fifo1count; i++) { |
18926ede | 405 | read = tiadc_readl(adc_dev, REG_FIFO1); |
b1451e54 PR |
406 | stepid = read & FIFOREAD_CHNLID_MASK; |
407 | stepid = stepid >> 0x10; | |
408 | ||
409 | if (stepid == map_val) { | |
410 | read = read & FIFOREAD_DATA_MASK; | |
1460c152 | 411 | found = true; |
0f6fc7d5 | 412 | *val = (u16) read; |
1460c152 | 413 | } |
5e53a69b | 414 | } |
7ca6740c | 415 | am335x_tsc_se_adc_done(adc_dev->mfd_tscadc); |
b1451e54 | 416 | |
1460c152 SAS |
417 | if (found == false) |
418 | return -EBUSY; | |
5e53a69b PR |
419 | return IIO_VAL_INT; |
420 | } | |
421 | ||
422 | static const struct iio_info tiadc_info = { | |
423 | .read_raw = &tiadc_read_raw, | |
bc93aa76 | 424 | .driver_module = THIS_MODULE, |
5e53a69b PR |
425 | }; |
426 | ||
dee1f550 V |
427 | static int tiadc_parse_dt(struct platform_device *pdev, |
428 | struct tiadc_device *adc_dev) | |
429 | { | |
430 | struct device_node *node = pdev->dev.of_node; | |
431 | struct property *prop; | |
432 | const __be32 *cur; | |
433 | int channels = 0; | |
434 | u32 val; | |
435 | ||
436 | of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) { | |
437 | adc_dev->channel_line[channels] = val; | |
5dc11e81 V |
438 | |
439 | /* Set Default values for optional DT parameters */ | |
440 | adc_dev->open_delay[channels] = STEPCONFIG_OPENDLY; | |
441 | adc_dev->sample_delay[channels] = STEPCONFIG_SAMPLEDLY; | |
442 | adc_dev->step_avg[channels] = 16; | |
443 | ||
dee1f550 V |
444 | channels++; |
445 | } | |
446 | ||
5dc11e81 V |
447 | of_property_read_u32_array(node, "ti,chan-step-avg", |
448 | adc_dev->step_avg, channels); | |
449 | of_property_read_u32_array(node, "ti,chan-step-opendelay", | |
450 | adc_dev->open_delay, channels); | |
451 | of_property_read_u32_array(node, "ti,chan-step-sampledelay", | |
452 | adc_dev->sample_delay, channels); | |
453 | ||
dee1f550 V |
454 | adc_dev->channels = channels; |
455 | return 0; | |
456 | } | |
457 | ||
fc52692c | 458 | static int tiadc_probe(struct platform_device *pdev) |
5e53a69b PR |
459 | { |
460 | struct iio_dev *indio_dev; | |
461 | struct tiadc_device *adc_dev; | |
6f39ac4e | 462 | struct device_node *node = pdev->dev.of_node; |
5e53a69b PR |
463 | int err; |
464 | ||
0ead4fb2 SAS |
465 | if (!node) { |
466 | dev_err(&pdev->dev, "Could not find valid DT data.\n"); | |
5e53a69b PR |
467 | return -EINVAL; |
468 | } | |
469 | ||
a0648130 SK |
470 | indio_dev = devm_iio_device_alloc(&pdev->dev, |
471 | sizeof(struct tiadc_device)); | |
5e53a69b PR |
472 | if (indio_dev == NULL) { |
473 | dev_err(&pdev->dev, "failed to allocate iio device\n"); | |
a0648130 | 474 | return -ENOMEM; |
5e53a69b PR |
475 | } |
476 | adc_dev = iio_priv(indio_dev); | |
477 | ||
6f39ac4e | 478 | adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev); |
dee1f550 | 479 | tiadc_parse_dt(pdev, adc_dev); |
5e53a69b PR |
480 | |
481 | indio_dev->dev.parent = &pdev->dev; | |
482 | indio_dev->name = dev_name(&pdev->dev); | |
483 | indio_dev->modes = INDIO_DIRECT_MODE; | |
484 | indio_dev->info = &tiadc_info; | |
485 | ||
ca9a5638 ZL |
486 | tiadc_step_config(indio_dev); |
487 | tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD); | |
5e53a69b PR |
488 | |
489 | err = tiadc_channel_init(indio_dev, adc_dev->channels); | |
490 | if (err < 0) | |
a0648130 | 491 | return err; |
5e53a69b | 492 | |
ca9a5638 ZL |
493 | err = tiadc_iio_buffered_hardware_setup(indio_dev, |
494 | &tiadc_worker_h, | |
495 | &tiadc_irq_h, | |
496 | adc_dev->mfd_tscadc->irq, | |
497 | IRQF_SHARED, | |
498 | &tiadc_buffer_setup_ops); | |
499 | ||
5e53a69b PR |
500 | if (err) |
501 | goto err_free_channels; | |
502 | ||
ca9a5638 ZL |
503 | err = iio_device_register(indio_dev); |
504 | if (err) | |
505 | goto err_buffer_unregister; | |
506 | ||
5e53a69b PR |
507 | platform_set_drvdata(pdev, indio_dev); |
508 | ||
509 | return 0; | |
510 | ||
ca9a5638 ZL |
511 | err_buffer_unregister: |
512 | tiadc_iio_buffered_hardware_remove(indio_dev); | |
5e53a69b PR |
513 | err_free_channels: |
514 | tiadc_channels_remove(indio_dev); | |
5e53a69b PR |
515 | return err; |
516 | } | |
517 | ||
fc52692c | 518 | static int tiadc_remove(struct platform_device *pdev) |
5e53a69b PR |
519 | { |
520 | struct iio_dev *indio_dev = platform_get_drvdata(pdev); | |
abeccee4 PR |
521 | struct tiadc_device *adc_dev = iio_priv(indio_dev); |
522 | u32 step_en; | |
5e53a69b PR |
523 | |
524 | iio_device_unregister(indio_dev); | |
ca9a5638 | 525 | tiadc_iio_buffered_hardware_remove(indio_dev); |
5e53a69b PR |
526 | tiadc_channels_remove(indio_dev); |
527 | ||
abeccee4 PR |
528 | step_en = get_adc_step_mask(adc_dev); |
529 | am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en); | |
530 | ||
5e53a69b PR |
531 | return 0; |
532 | } | |
533 | ||
534 | #ifdef CONFIG_PM | |
535 | static int tiadc_suspend(struct device *dev) | |
536 | { | |
537 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
538 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
a9bce1b0 | 539 | struct ti_tscadc_dev *tscadc_dev; |
5e53a69b PR |
540 | unsigned int idle; |
541 | ||
a9bce1b0 | 542 | tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); |
5e53a69b PR |
543 | if (!device_may_wakeup(tscadc_dev->dev)) { |
544 | idle = tiadc_readl(adc_dev, REG_CTRL); | |
545 | idle &= ~(CNTRLREG_TSCSSENB); | |
546 | tiadc_writel(adc_dev, REG_CTRL, (idle | | |
547 | CNTRLREG_POWERDOWN)); | |
548 | } | |
549 | ||
550 | return 0; | |
551 | } | |
552 | ||
553 | static int tiadc_resume(struct device *dev) | |
554 | { | |
555 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
556 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | |
557 | unsigned int restore; | |
558 | ||
559 | /* Make sure ADC is powered up */ | |
560 | restore = tiadc_readl(adc_dev, REG_CTRL); | |
561 | restore &= ~(CNTRLREG_POWERDOWN); | |
562 | tiadc_writel(adc_dev, REG_CTRL, restore); | |
563 | ||
ca9a5638 | 564 | tiadc_step_config(indio_dev); |
7ca6740c SAS |
565 | am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, |
566 | adc_dev->buffer_en_ch_steps); | |
5e53a69b PR |
567 | return 0; |
568 | } | |
569 | ||
570 | static const struct dev_pm_ops tiadc_pm_ops = { | |
571 | .suspend = tiadc_suspend, | |
572 | .resume = tiadc_resume, | |
573 | }; | |
574 | #define TIADC_PM_OPS (&tiadc_pm_ops) | |
575 | #else | |
576 | #define TIADC_PM_OPS NULL | |
577 | #endif | |
578 | ||
6f39ac4e PR |
579 | static const struct of_device_id ti_adc_dt_ids[] = { |
580 | { .compatible = "ti,am3359-adc", }, | |
581 | { } | |
582 | }; | |
583 | MODULE_DEVICE_TABLE(of, ti_adc_dt_ids); | |
584 | ||
5e53a69b PR |
585 | static struct platform_driver tiadc_driver = { |
586 | .driver = { | |
9f99928f | 587 | .name = "TI-am335x-adc", |
5e53a69b | 588 | .pm = TIADC_PM_OPS, |
de06b344 | 589 | .of_match_table = ti_adc_dt_ids, |
5e53a69b PR |
590 | }, |
591 | .probe = tiadc_probe, | |
fc52692c | 592 | .remove = tiadc_remove, |
5e53a69b | 593 | }; |
5e53a69b PR |
594 | module_platform_driver(tiadc_driver); |
595 | ||
596 | MODULE_DESCRIPTION("TI ADC controller driver"); | |
597 | MODULE_AUTHOR("Rachna Patil <rachna@ti.com>"); | |
598 | MODULE_LICENSE("GPL"); |