]>
Commit | Line | Data |
---|---|---|
bc2c90c9 MV |
1 | /* |
2 | * Freescale i.MX28 LRADC driver | |
3 | * | |
4 | * Copyright (c) 2012 DENX Software Engineering, GmbH. | |
5 | * Marek Vasut <marex@denx.de> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | */ | |
17 | ||
97f4be60 | 18 | #include <linux/err.h> |
bc2c90c9 MV |
19 | #include <linux/interrupt.h> |
20 | #include <linux/device.h> | |
21 | #include <linux/kernel.h> | |
22 | #include <linux/slab.h> | |
23 | #include <linux/of.h> | |
24 | #include <linux/of_device.h> | |
25 | #include <linux/sysfs.h> | |
26 | #include <linux/list.h> | |
27 | #include <linux/io.h> | |
28 | #include <linux/module.h> | |
29 | #include <linux/platform_device.h> | |
30 | #include <linux/spinlock.h> | |
31 | #include <linux/wait.h> | |
32 | #include <linux/sched.h> | |
33 | #include <linux/stmp_device.h> | |
34 | #include <linux/bitops.h> | |
35 | #include <linux/completion.h> | |
06ddd353 MV |
36 | #include <linux/delay.h> |
37 | #include <linux/input.h> | |
18da755d | 38 | #include <linux/clk.h> |
bc2c90c9 | 39 | |
bc2c90c9 MV |
40 | #include <linux/iio/iio.h> |
41 | #include <linux/iio/buffer.h> | |
42 | #include <linux/iio/trigger.h> | |
43 | #include <linux/iio/trigger_consumer.h> | |
44 | #include <linux/iio/triggered_buffer.h> | |
45 | ||
46 | #define DRIVER_NAME "mxs-lradc" | |
47 | ||
48 | #define LRADC_MAX_DELAY_CHANS 4 | |
49 | #define LRADC_MAX_MAPPED_CHANS 8 | |
50 | #define LRADC_MAX_TOTAL_CHANS 16 | |
51 | ||
52 | #define LRADC_DELAY_TIMER_HZ 2000 | |
53 | ||
54 | /* | |
55 | * Make this runtime configurable if necessary. Currently, if the buffered mode | |
56 | * is enabled, the LRADC takes LRADC_DELAY_TIMER_LOOP samples of data before | |
57 | * triggering IRQ. The sampling happens every (LRADC_DELAY_TIMER_PER / 2000) | |
58 | * seconds. The result is that the samples arrive every 500mS. | |
59 | */ | |
60 | #define LRADC_DELAY_TIMER_PER 200 | |
61 | #define LRADC_DELAY_TIMER_LOOP 5 | |
62 | ||
06ddd353 MV |
63 | /* |
64 | * Once the pen touches the touchscreen, the touchscreen switches from | |
65 | * IRQ-driven mode to polling mode to prevent interrupt storm. The polling | |
66 | * is realized by worker thread, which is called every 20 or so milliseconds. | |
67 | * This gives the touchscreen enough fluence and does not strain the system | |
68 | * too much. | |
69 | */ | |
70 | #define LRADC_TS_SAMPLE_DELAY_MS 5 | |
71 | ||
72 | /* | |
73 | * The LRADC reads the following amount of samples from each touchscreen | |
74 | * channel and the driver then computes avarage of these. | |
75 | */ | |
76 | #define LRADC_TS_SAMPLE_AMOUNT 4 | |
77 | ||
5e1f9aca MV |
78 | enum mxs_lradc_id { |
79 | IMX23_LRADC, | |
80 | IMX28_LRADC, | |
81 | }; | |
82 | ||
83 | static const char * const mx23_lradc_irq_names[] = { | |
84 | "mxs-lradc-touchscreen", | |
85 | "mxs-lradc-channel0", | |
86 | "mxs-lradc-channel1", | |
87 | "mxs-lradc-channel2", | |
88 | "mxs-lradc-channel3", | |
89 | "mxs-lradc-channel4", | |
90 | "mxs-lradc-channel5", | |
91 | "mxs-lradc-channel6", | |
92 | "mxs-lradc-channel7", | |
93 | }; | |
94 | ||
95 | static const char * const mx28_lradc_irq_names[] = { | |
bc2c90c9 MV |
96 | "mxs-lradc-touchscreen", |
97 | "mxs-lradc-thresh0", | |
98 | "mxs-lradc-thresh1", | |
99 | "mxs-lradc-channel0", | |
100 | "mxs-lradc-channel1", | |
101 | "mxs-lradc-channel2", | |
102 | "mxs-lradc-channel3", | |
103 | "mxs-lradc-channel4", | |
104 | "mxs-lradc-channel5", | |
105 | "mxs-lradc-channel6", | |
106 | "mxs-lradc-channel7", | |
107 | "mxs-lradc-button0", | |
108 | "mxs-lradc-button1", | |
109 | }; | |
110 | ||
5e1f9aca MV |
111 | struct mxs_lradc_of_config { |
112 | const int irq_count; | |
113 | const char * const *irq_name; | |
114 | }; | |
115 | ||
ad76fda7 | 116 | static const struct mxs_lradc_of_config mxs_lradc_of_config[] = { |
5e1f9aca MV |
117 | [IMX23_LRADC] = { |
118 | .irq_count = ARRAY_SIZE(mx23_lradc_irq_names), | |
119 | .irq_name = mx23_lradc_irq_names, | |
120 | }, | |
121 | [IMX28_LRADC] = { | |
122 | .irq_count = ARRAY_SIZE(mx28_lradc_irq_names), | |
123 | .irq_name = mx28_lradc_irq_names, | |
124 | }, | |
125 | }; | |
126 | ||
06ddd353 MV |
127 | enum mxs_lradc_ts { |
128 | MXS_LRADC_TOUCHSCREEN_NONE = 0, | |
129 | MXS_LRADC_TOUCHSCREEN_4WIRE, | |
130 | MXS_LRADC_TOUCHSCREEN_5WIRE, | |
bc2c90c9 MV |
131 | }; |
132 | ||
dee05308 JB |
133 | /* |
134 | * Touchscreen handling | |
135 | */ | |
136 | enum lradc_ts_plate { | |
137 | LRADC_TOUCH = 0, | |
138 | LRADC_SAMPLE_X, | |
139 | LRADC_SAMPLE_Y, | |
140 | LRADC_SAMPLE_PRESSURE, | |
141 | LRADC_SAMPLE_VALID, | |
142 | }; | |
143 | ||
bc2c90c9 MV |
144 | struct mxs_lradc { |
145 | struct device *dev; | |
146 | void __iomem *base; | |
147 | int irq[13]; | |
148 | ||
18da755d JB |
149 | struct clk *clk; |
150 | ||
bc2c90c9 MV |
151 | uint32_t *buffer; |
152 | struct iio_trigger *trig; | |
153 | ||
154 | struct mutex lock; | |
155 | ||
bc2c90c9 | 156 | struct completion completion; |
06ddd353 MV |
157 | |
158 | /* | |
159 | * Touchscreen LRADC channels receives a private slot in the CTRL4 | |
160 | * register, the slot #7. Therefore only 7 slots instead of 8 in the | |
161 | * CTRL4 register can be mapped to LRADC channels when using the | |
162 | * touchscreen. | |
163 | * | |
164 | * Furthermore, certain LRADC channels are shared between touchscreen | |
165 | * and/or touch-buttons and generic LRADC block. Therefore when using | |
166 | * either of these, these channels are not available for the regular | |
167 | * sampling. The shared channels are as follows: | |
168 | * | |
169 | * CH0 -- Touch button #0 | |
170 | * CH1 -- Touch button #1 | |
171 | * CH2 -- Touch screen XPUL | |
172 | * CH3 -- Touch screen YPLL | |
173 | * CH4 -- Touch screen XNUL | |
174 | * CH5 -- Touch screen YNLR | |
175 | * CH6 -- Touch screen WIPER (5-wire only) | |
176 | * | |
177 | * The bitfields below represents which parts of the LRADC block are | |
178 | * switched into special mode of operation. These channels can not | |
179 | * be sampled as regular LRADC channels. The driver will refuse any | |
180 | * attempt to sample these channels. | |
181 | */ | |
182 | #define CHAN_MASK_TOUCHBUTTON (0x3 << 0) | |
183 | #define CHAN_MASK_TOUCHSCREEN_4WIRE (0xf << 2) | |
184 | #define CHAN_MASK_TOUCHSCREEN_5WIRE (0x1f << 2) | |
185 | enum mxs_lradc_ts use_touchscreen; | |
06ddd353 MV |
186 | bool use_touchbutton; |
187 | ||
188 | struct input_dev *ts_input; | |
ccff5297 JB |
189 | |
190 | enum mxs_lradc_id soc; | |
dee05308 JB |
191 | enum lradc_ts_plate cur_plate; /* statemachine */ |
192 | bool ts_valid; | |
193 | unsigned ts_x_pos; | |
194 | unsigned ts_y_pos; | |
195 | unsigned ts_pressure; | |
196 | ||
197 | /* handle touchscreen's physical behaviour */ | |
198 | /* samples per coordinate */ | |
199 | unsigned over_sample_cnt; | |
200 | /* time clocks between samples */ | |
201 | unsigned over_sample_delay; | |
202 | /* time in clocks to wait after the plates where switched */ | |
203 | unsigned settling_delay; | |
bc2c90c9 MV |
204 | }; |
205 | ||
206 | #define LRADC_CTRL0 0x00 | |
7e4d4a6f JB |
207 | # define LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE (1 << 23) |
208 | # define LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE (1 << 22) | |
209 | # define LRADC_CTRL0_MX28_YNNSW /* YM */ (1 << 21) | |
210 | # define LRADC_CTRL0_MX28_YPNSW /* YP */ (1 << 20) | |
211 | # define LRADC_CTRL0_MX28_YPPSW /* YP */ (1 << 19) | |
212 | # define LRADC_CTRL0_MX28_XNNSW /* XM */ (1 << 18) | |
213 | # define LRADC_CTRL0_MX28_XNPSW /* XM */ (1 << 17) | |
214 | # define LRADC_CTRL0_MX28_XPPSW /* XP */ (1 << 16) | |
215 | ||
8c06f714 JB |
216 | # define LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE (1 << 20) |
217 | # define LRADC_CTRL0_MX23_YM (1 << 19) | |
218 | # define LRADC_CTRL0_MX23_XM (1 << 18) | |
219 | # define LRADC_CTRL0_MX23_YP (1 << 17) | |
220 | # define LRADC_CTRL0_MX23_XP (1 << 16) | |
221 | ||
7e4d4a6f JB |
222 | # define LRADC_CTRL0_MX28_PLATE_MASK \ |
223 | (LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE | \ | |
224 | LRADC_CTRL0_MX28_YNNSW | LRADC_CTRL0_MX28_YPNSW | \ | |
225 | LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW | \ | |
226 | LRADC_CTRL0_MX28_XNPSW | LRADC_CTRL0_MX28_XPPSW) | |
bc2c90c9 | 227 | |
8c06f714 JB |
228 | # define LRADC_CTRL0_MX23_PLATE_MASK \ |
229 | (LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE | \ | |
230 | LRADC_CTRL0_MX23_YM | LRADC_CTRL0_MX23_XM | \ | |
231 | LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_XP) | |
232 | ||
bc2c90c9 | 233 | #define LRADC_CTRL1 0x10 |
06ddd353 | 234 | #define LRADC_CTRL1_TOUCH_DETECT_IRQ_EN (1 << 24) |
bc2c90c9 | 235 | #define LRADC_CTRL1_LRADC_IRQ_EN(n) (1 << ((n) + 16)) |
7e4d4a6f | 236 | #define LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK (0x1fff << 16) |
8c06f714 | 237 | #define LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK (0x01ff << 16) |
06ddd353 MV |
238 | #define LRADC_CTRL1_LRADC_IRQ_EN_OFFSET 16 |
239 | #define LRADC_CTRL1_TOUCH_DETECT_IRQ (1 << 8) | |
240 | #define LRADC_CTRL1_LRADC_IRQ(n) (1 << (n)) | |
7e4d4a6f | 241 | #define LRADC_CTRL1_MX28_LRADC_IRQ_MASK 0x1fff |
8c06f714 | 242 | #define LRADC_CTRL1_MX23_LRADC_IRQ_MASK 0x01ff |
06ddd353 | 243 | #define LRADC_CTRL1_LRADC_IRQ_OFFSET 0 |
bc2c90c9 MV |
244 | |
245 | #define LRADC_CTRL2 0x20 | |
246 | #define LRADC_CTRL2_TEMPSENSE_PWD (1 << 15) | |
247 | ||
06ddd353 MV |
248 | #define LRADC_STATUS 0x40 |
249 | #define LRADC_STATUS_TOUCH_DETECT_RAW (1 << 0) | |
250 | ||
bc2c90c9 MV |
251 | #define LRADC_CH(n) (0x50 + (0x10 * (n))) |
252 | #define LRADC_CH_ACCUMULATE (1 << 29) | |
253 | #define LRADC_CH_NUM_SAMPLES_MASK (0x1f << 24) | |
254 | #define LRADC_CH_NUM_SAMPLES_OFFSET 24 | |
dee05308 JB |
255 | #define LRADC_CH_NUM_SAMPLES(x) \ |
256 | ((x) << LRADC_CH_NUM_SAMPLES_OFFSET) | |
bc2c90c9 MV |
257 | #define LRADC_CH_VALUE_MASK 0x3ffff |
258 | #define LRADC_CH_VALUE_OFFSET 0 | |
259 | ||
260 | #define LRADC_DELAY(n) (0xd0 + (0x10 * (n))) | |
261 | #define LRADC_DELAY_TRIGGER_LRADCS_MASK (0xff << 24) | |
262 | #define LRADC_DELAY_TRIGGER_LRADCS_OFFSET 24 | |
dee05308 JB |
263 | #define LRADC_DELAY_TRIGGER(x) \ |
264 | (((x) << LRADC_DELAY_TRIGGER_LRADCS_OFFSET) & \ | |
265 | LRADC_DELAY_TRIGGER_LRADCS_MASK) | |
bc2c90c9 MV |
266 | #define LRADC_DELAY_KICK (1 << 20) |
267 | #define LRADC_DELAY_TRIGGER_DELAYS_MASK (0xf << 16) | |
268 | #define LRADC_DELAY_TRIGGER_DELAYS_OFFSET 16 | |
dee05308 JB |
269 | #define LRADC_DELAY_TRIGGER_DELAYS(x) \ |
270 | (((x) << LRADC_DELAY_TRIGGER_DELAYS_OFFSET) & \ | |
271 | LRADC_DELAY_TRIGGER_DELAYS_MASK) | |
bc2c90c9 MV |
272 | #define LRADC_DELAY_LOOP_COUNT_MASK (0x1f << 11) |
273 | #define LRADC_DELAY_LOOP_COUNT_OFFSET 11 | |
dee05308 JB |
274 | #define LRADC_DELAY_LOOP(x) \ |
275 | (((x) << LRADC_DELAY_LOOP_COUNT_OFFSET) & \ | |
276 | LRADC_DELAY_LOOP_COUNT_MASK) | |
bc2c90c9 MV |
277 | #define LRADC_DELAY_DELAY_MASK 0x7ff |
278 | #define LRADC_DELAY_DELAY_OFFSET 0 | |
dee05308 JB |
279 | #define LRADC_DELAY_DELAY(x) \ |
280 | (((x) << LRADC_DELAY_DELAY_OFFSET) & \ | |
281 | LRADC_DELAY_DELAY_MASK) | |
bc2c90c9 MV |
282 | |
283 | #define LRADC_CTRL4 0x140 | |
284 | #define LRADC_CTRL4_LRADCSELECT_MASK(n) (0xf << ((n) * 4)) | |
285 | #define LRADC_CTRL4_LRADCSELECT_OFFSET(n) ((n) * 4) | |
286 | ||
1eb70a97 HP |
287 | #define LRADC_RESOLUTION 12 |
288 | #define LRADC_SINGLE_SAMPLE_MASK ((1 << LRADC_RESOLUTION) - 1) | |
289 | ||
f0b83cc8 JB |
290 | static void mxs_lradc_reg_set(struct mxs_lradc *lradc, u32 val, u32 reg) |
291 | { | |
292 | writel(val, lradc->base + reg + STMP_OFFSET_REG_SET); | |
293 | } | |
294 | ||
295 | static void mxs_lradc_reg_clear(struct mxs_lradc *lradc, u32 val, u32 reg) | |
296 | { | |
297 | writel(val, lradc->base + reg + STMP_OFFSET_REG_CLR); | |
298 | } | |
299 | ||
300 | static void mxs_lradc_reg_wrt(struct mxs_lradc *lradc, u32 val, u32 reg) | |
301 | { | |
302 | writel(val, lradc->base + reg); | |
303 | } | |
304 | ||
305 | static u32 mxs_lradc_plate_mask(struct mxs_lradc *lradc) | |
306 | { | |
8c06f714 JB |
307 | if (lradc->soc == IMX23_LRADC) |
308 | return LRADC_CTRL0_MX23_PLATE_MASK; | |
309 | else | |
310 | return LRADC_CTRL0_MX28_PLATE_MASK; | |
f0b83cc8 JB |
311 | } |
312 | ||
313 | static u32 mxs_lradc_irq_en_mask(struct mxs_lradc *lradc) | |
314 | { | |
8c06f714 JB |
315 | if (lradc->soc == IMX23_LRADC) |
316 | return LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK; | |
317 | else | |
318 | return LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK; | |
f0b83cc8 JB |
319 | } |
320 | ||
321 | static u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc) | |
322 | { | |
8c06f714 JB |
323 | if (lradc->soc == IMX23_LRADC) |
324 | return LRADC_CTRL1_MX23_LRADC_IRQ_MASK; | |
325 | else | |
326 | return LRADC_CTRL1_MX28_LRADC_IRQ_MASK; | |
f0b83cc8 JB |
327 | } |
328 | ||
329 | static u32 mxs_lradc_touch_detect_bit(struct mxs_lradc *lradc) | |
330 | { | |
8c06f714 JB |
331 | if (lradc->soc == IMX23_LRADC) |
332 | return LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE; | |
333 | else | |
334 | return LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE; | |
f0b83cc8 JB |
335 | } |
336 | ||
337 | static u32 mxs_lradc_drive_x_plate(struct mxs_lradc *lradc) | |
338 | { | |
8c06f714 JB |
339 | if (lradc->soc == IMX23_LRADC) |
340 | return LRADC_CTRL0_MX23_XP | LRADC_CTRL0_MX23_XM; | |
341 | else | |
342 | return LRADC_CTRL0_MX28_XPPSW | LRADC_CTRL0_MX28_XNNSW; | |
f0b83cc8 JB |
343 | } |
344 | ||
345 | static u32 mxs_lradc_drive_y_plate(struct mxs_lradc *lradc) | |
346 | { | |
8c06f714 JB |
347 | if (lradc->soc == IMX23_LRADC) |
348 | return LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_YM; | |
349 | else | |
350 | return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_YNNSW; | |
f0b83cc8 JB |
351 | } |
352 | ||
353 | static u32 mxs_lradc_drive_pressure(struct mxs_lradc *lradc) | |
354 | { | |
8c06f714 JB |
355 | if (lradc->soc == IMX23_LRADC) |
356 | return LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_XM; | |
357 | else | |
358 | return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW; | |
f0b83cc8 JB |
359 | } |
360 | ||
dee05308 JB |
361 | static bool mxs_lradc_check_touch_event(struct mxs_lradc *lradc) |
362 | { | |
363 | return !!(readl(lradc->base + LRADC_STATUS) & | |
364 | LRADC_STATUS_TOUCH_DETECT_RAW); | |
365 | } | |
366 | ||
367 | static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch) | |
368 | { | |
369 | /* | |
370 | * prepare for oversampling conversion | |
371 | * | |
372 | * from the datasheet: | |
373 | * "The ACCUMULATE bit in the appropriate channel register | |
374 | * HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0; | |
375 | * otherwise, the IRQs will not fire." | |
376 | */ | |
377 | mxs_lradc_reg_wrt(lradc, LRADC_CH_ACCUMULATE | | |
378 | LRADC_CH_NUM_SAMPLES(lradc->over_sample_cnt - 1), | |
379 | LRADC_CH(ch)); | |
380 | ||
381 | /* from the datasheet: | |
382 | * "Software must clear this register in preparation for a | |
383 | * multi-cycle accumulation. | |
384 | */ | |
385 | mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch)); | |
386 | ||
387 | /* prepare the delay/loop unit according to the oversampling count */ | |
388 | mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch) | | |
389 | LRADC_DELAY_TRIGGER_DELAYS(0) | | |
390 | LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) | | |
391 | LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), | |
392 | LRADC_DELAY(3)); | |
393 | ||
394 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) | | |
395 | LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) | | |
396 | LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); | |
397 | ||
398 | /* wake us again, when the complete conversion is done */ | |
399 | mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch), LRADC_CTRL1); | |
400 | /* | |
401 | * after changing the touchscreen plates setting | |
402 | * the signals need some initial time to settle. Start the | |
403 | * SoC's delay unit and start the conversion later | |
404 | * and automatically. | |
405 | */ | |
406 | mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */ | |
407 | LRADC_DELAY_TRIGGER_DELAYS(1 << 3) | /* trigger DELAY unit#3 */ | |
408 | LRADC_DELAY_KICK | | |
409 | LRADC_DELAY_DELAY(lradc->settling_delay), | |
410 | LRADC_DELAY(2)); | |
411 | } | |
412 | ||
413 | /* | |
414 | * Pressure detection is special: | |
415 | * We want to do both required measurements for the pressure detection in | |
416 | * one turn. Use the hardware features to chain both conversions and let the | |
417 | * hardware report one interrupt if both conversions are done | |
418 | */ | |
419 | static void mxs_lradc_setup_ts_pressure(struct mxs_lradc *lradc, unsigned ch1, | |
420 | unsigned ch2) | |
421 | { | |
422 | u32 reg; | |
423 | ||
424 | /* | |
425 | * prepare for oversampling conversion | |
426 | * | |
427 | * from the datasheet: | |
428 | * "The ACCUMULATE bit in the appropriate channel register | |
429 | * HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0; | |
430 | * otherwise, the IRQs will not fire." | |
431 | */ | |
432 | reg = LRADC_CH_ACCUMULATE | | |
433 | LRADC_CH_NUM_SAMPLES(lradc->over_sample_cnt - 1); | |
434 | mxs_lradc_reg_wrt(lradc, reg, LRADC_CH(ch1)); | |
435 | mxs_lradc_reg_wrt(lradc, reg, LRADC_CH(ch2)); | |
436 | ||
437 | /* from the datasheet: | |
438 | * "Software must clear this register in preparation for a | |
439 | * multi-cycle accumulation. | |
440 | */ | |
441 | mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch1)); | |
442 | mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch2)); | |
443 | ||
444 | /* prepare the delay/loop unit according to the oversampling count */ | |
445 | mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch1) | | |
446 | LRADC_DELAY_TRIGGER(1 << ch2) | /* start both channels */ | |
447 | LRADC_DELAY_TRIGGER_DELAYS(0) | | |
448 | LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) | | |
449 | LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), | |
450 | LRADC_DELAY(3)); | |
451 | ||
452 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) | | |
453 | LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) | | |
454 | LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); | |
455 | ||
456 | /* wake us again, when the conversions are done */ | |
457 | mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch2), LRADC_CTRL1); | |
458 | /* | |
459 | * after changing the touchscreen plates setting | |
460 | * the signals need some initial time to settle. Start the | |
461 | * SoC's delay unit and start the conversion later | |
462 | * and automatically. | |
463 | */ | |
464 | mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */ | |
465 | LRADC_DELAY_TRIGGER_DELAYS(1 << 3) | /* trigger DELAY unit#3 */ | |
466 | LRADC_DELAY_KICK | | |
467 | LRADC_DELAY_DELAY(lradc->settling_delay), LRADC_DELAY(2)); | |
468 | } | |
469 | ||
470 | static unsigned mxs_lradc_read_raw_channel(struct mxs_lradc *lradc, | |
471 | unsigned channel) | |
472 | { | |
473 | u32 reg; | |
474 | unsigned num_samples, val; | |
475 | ||
476 | reg = readl(lradc->base + LRADC_CH(channel)); | |
477 | if (reg & LRADC_CH_ACCUMULATE) | |
478 | num_samples = lradc->over_sample_cnt; | |
479 | else | |
480 | num_samples = 1; | |
481 | ||
482 | val = (reg & LRADC_CH_VALUE_MASK) >> LRADC_CH_VALUE_OFFSET; | |
483 | return val / num_samples; | |
484 | } | |
485 | ||
486 | static unsigned mxs_lradc_read_ts_pressure(struct mxs_lradc *lradc, | |
487 | unsigned ch1, unsigned ch2) | |
488 | { | |
489 | u32 reg, mask; | |
490 | unsigned pressure, m1, m2; | |
491 | ||
492 | mask = LRADC_CTRL1_LRADC_IRQ(ch1) | LRADC_CTRL1_LRADC_IRQ(ch2); | |
493 | reg = readl(lradc->base + LRADC_CTRL1) & mask; | |
494 | ||
495 | while (reg != mask) { | |
496 | reg = readl(lradc->base + LRADC_CTRL1) & mask; | |
497 | dev_dbg(lradc->dev, "One channel is still busy: %X\n", reg); | |
498 | } | |
499 | ||
500 | m1 = mxs_lradc_read_raw_channel(lradc, ch1); | |
501 | m2 = mxs_lradc_read_raw_channel(lradc, ch2); | |
502 | ||
503 | if (m2 == 0) { | |
504 | dev_warn(lradc->dev, "Cannot calculate pressure\n"); | |
505 | return 1 << (LRADC_RESOLUTION - 1); | |
506 | } | |
507 | ||
508 | /* simply scale the value from 0 ... max ADC resolution */ | |
509 | pressure = m1; | |
510 | pressure *= (1 << LRADC_RESOLUTION); | |
511 | pressure /= m2; | |
512 | ||
513 | dev_dbg(lradc->dev, "Pressure = %u\n", pressure); | |
514 | return pressure; | |
515 | } | |
516 | ||
517 | #define TS_CH_XP 2 | |
518 | #define TS_CH_YP 3 | |
519 | #define TS_CH_XM 4 | |
520 | #define TS_CH_YM 5 | |
521 | ||
522 | static int mxs_lradc_read_ts_channel(struct mxs_lradc *lradc) | |
523 | { | |
524 | u32 reg; | |
525 | int val; | |
526 | ||
527 | reg = readl(lradc->base + LRADC_CTRL1); | |
528 | ||
529 | /* only channels 3 to 5 are of interest here */ | |
530 | if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YP)) { | |
531 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YP) | | |
532 | LRADC_CTRL1_LRADC_IRQ(TS_CH_YP), LRADC_CTRL1); | |
533 | val = mxs_lradc_read_raw_channel(lradc, TS_CH_YP); | |
534 | } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_XM)) { | |
535 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_XM) | | |
536 | LRADC_CTRL1_LRADC_IRQ(TS_CH_XM), LRADC_CTRL1); | |
537 | val = mxs_lradc_read_raw_channel(lradc, TS_CH_XM); | |
538 | } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YM)) { | |
539 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YM) | | |
540 | LRADC_CTRL1_LRADC_IRQ(TS_CH_YM), LRADC_CTRL1); | |
541 | val = mxs_lradc_read_raw_channel(lradc, TS_CH_YM); | |
542 | } else { | |
543 | return -EIO; | |
544 | } | |
545 | ||
546 | mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); | |
547 | mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); | |
548 | ||
549 | return val; | |
550 | } | |
551 | ||
552 | /* | |
553 | * YP(open)--+-------------+ | |
554 | * | |--+ | |
555 | * | | | | |
556 | * YM(-)--+-------------+ | | |
557 | * +--------------+ | |
558 | * | | | |
559 | * XP(weak+) XM(open) | |
560 | * | |
561 | * "weak+" means 200k Ohm VDDIO | |
562 | * (-) means GND | |
563 | */ | |
564 | static void mxs_lradc_setup_touch_detection(struct mxs_lradc *lradc) | |
565 | { | |
566 | /* | |
567 | * In order to detect a touch event the 'touch detect enable' bit | |
568 | * enables: | |
569 | * - a weak pullup to the X+ connector | |
570 | * - a strong ground at the Y- connector | |
571 | */ | |
572 | mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); | |
573 | mxs_lradc_reg_set(lradc, mxs_lradc_touch_detect_bit(lradc), | |
574 | LRADC_CTRL0); | |
575 | } | |
576 | ||
577 | /* | |
578 | * YP(meas)--+-------------+ | |
579 | * | |--+ | |
580 | * | | | | |
581 | * YM(open)--+-------------+ | | |
582 | * +--------------+ | |
583 | * | | | |
584 | * XP(+) XM(-) | |
585 | * | |
586 | * (+) means here 1.85 V | |
587 | * (-) means here GND | |
588 | */ | |
589 | static void mxs_lradc_prepare_x_pos(struct mxs_lradc *lradc) | |
590 | { | |
591 | mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); | |
592 | mxs_lradc_reg_set(lradc, mxs_lradc_drive_x_plate(lradc), LRADC_CTRL0); | |
593 | ||
594 | lradc->cur_plate = LRADC_SAMPLE_X; | |
595 | mxs_lradc_setup_ts_channel(lradc, TS_CH_YP); | |
596 | } | |
597 | ||
598 | /* | |
599 | * YP(+)--+-------------+ | |
600 | * | |--+ | |
601 | * | | | | |
602 | * YM(-)--+-------------+ | | |
603 | * +--------------+ | |
604 | * | | | |
605 | * XP(open) XM(meas) | |
606 | * | |
607 | * (+) means here 1.85 V | |
608 | * (-) means here GND | |
609 | */ | |
610 | static void mxs_lradc_prepare_y_pos(struct mxs_lradc *lradc) | |
611 | { | |
612 | mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); | |
613 | mxs_lradc_reg_set(lradc, mxs_lradc_drive_y_plate(lradc), LRADC_CTRL0); | |
614 | ||
615 | lradc->cur_plate = LRADC_SAMPLE_Y; | |
616 | mxs_lradc_setup_ts_channel(lradc, TS_CH_XM); | |
617 | } | |
618 | ||
619 | /* | |
620 | * YP(+)--+-------------+ | |
621 | * | |--+ | |
622 | * | | | | |
623 | * YM(meas)--+-------------+ | | |
624 | * +--------------+ | |
625 | * | | | |
626 | * XP(meas) XM(-) | |
627 | * | |
628 | * (+) means here 1.85 V | |
629 | * (-) means here GND | |
630 | */ | |
631 | static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc) | |
632 | { | |
633 | mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); | |
634 | mxs_lradc_reg_set(lradc, mxs_lradc_drive_pressure(lradc), LRADC_CTRL0); | |
635 | ||
636 | lradc->cur_plate = LRADC_SAMPLE_PRESSURE; | |
637 | mxs_lradc_setup_ts_pressure(lradc, TS_CH_XP, TS_CH_YM); | |
638 | } | |
639 | ||
640 | static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc) | |
641 | { | |
642 | mxs_lradc_setup_touch_detection(lradc); | |
643 | ||
644 | lradc->cur_plate = LRADC_TOUCH; | |
645 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ | | |
646 | LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); | |
647 | mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); | |
648 | } | |
649 | ||
650 | static void mxs_lradc_report_ts_event(struct mxs_lradc *lradc) | |
651 | { | |
652 | input_report_abs(lradc->ts_input, ABS_X, lradc->ts_x_pos); | |
653 | input_report_abs(lradc->ts_input, ABS_Y, lradc->ts_y_pos); | |
654 | input_report_abs(lradc->ts_input, ABS_PRESSURE, lradc->ts_pressure); | |
655 | input_report_key(lradc->ts_input, BTN_TOUCH, 1); | |
656 | input_sync(lradc->ts_input); | |
657 | } | |
658 | ||
659 | static void mxs_lradc_complete_touch_event(struct mxs_lradc *lradc) | |
660 | { | |
661 | mxs_lradc_setup_touch_detection(lradc); | |
662 | lradc->cur_plate = LRADC_SAMPLE_VALID; | |
663 | /* | |
664 | * start a dummy conversion to burn time to settle the signals | |
665 | * note: we are not interested in the conversion's value | |
666 | */ | |
667 | mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(5)); | |
668 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); | |
669 | mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(5), LRADC_CTRL1); | |
670 | mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << 5) | | |
671 | LRADC_DELAY_KICK | LRADC_DELAY_DELAY(10), /* waste 5 ms */ | |
672 | LRADC_DELAY(2)); | |
673 | } | |
674 | ||
675 | /* | |
676 | * in order to avoid false measurements, report only samples where | |
677 | * the surface is still touched after the position measurement | |
678 | */ | |
679 | static void mxs_lradc_finish_touch_event(struct mxs_lradc *lradc, bool valid) | |
680 | { | |
681 | /* if it is still touched, report the sample */ | |
682 | if (valid && mxs_lradc_check_touch_event(lradc)) { | |
683 | lradc->ts_valid = true; | |
684 | mxs_lradc_report_ts_event(lradc); | |
685 | } | |
686 | ||
687 | /* if it is even still touched, continue with the next measurement */ | |
688 | if (mxs_lradc_check_touch_event(lradc)) { | |
689 | mxs_lradc_prepare_y_pos(lradc); | |
690 | return; | |
691 | } | |
692 | ||
693 | if (lradc->ts_valid) { | |
694 | /* signal the release */ | |
695 | lradc->ts_valid = false; | |
696 | input_report_key(lradc->ts_input, BTN_TOUCH, 0); | |
697 | input_sync(lradc->ts_input); | |
698 | } | |
699 | ||
700 | /* if it is released, wait for the next touch via IRQ */ | |
701 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1); | |
702 | mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); | |
703 | } | |
704 | ||
705 | /* touchscreen's state machine */ | |
706 | static void mxs_lradc_handle_touch(struct mxs_lradc *lradc) | |
707 | { | |
708 | int val; | |
709 | ||
710 | switch (lradc->cur_plate) { | |
711 | case LRADC_TOUCH: | |
712 | /* | |
713 | * start with the Y-pos, because it uses nearly the same plate | |
714 | * settings like the touch detection | |
715 | */ | |
716 | if (mxs_lradc_check_touch_event(lradc)) { | |
717 | mxs_lradc_reg_clear(lradc, | |
718 | LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, | |
719 | LRADC_CTRL1); | |
720 | mxs_lradc_prepare_y_pos(lradc); | |
721 | } | |
722 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, | |
723 | LRADC_CTRL1); | |
724 | return; | |
725 | ||
726 | case LRADC_SAMPLE_Y: | |
727 | val = mxs_lradc_read_ts_channel(lradc); | |
728 | if (val < 0) { | |
729 | mxs_lradc_enable_touch_detection(lradc); /* re-start */ | |
730 | return; | |
731 | } | |
732 | lradc->ts_y_pos = val; | |
733 | mxs_lradc_prepare_x_pos(lradc); | |
734 | return; | |
735 | ||
736 | case LRADC_SAMPLE_X: | |
737 | val = mxs_lradc_read_ts_channel(lradc); | |
738 | if (val < 0) { | |
739 | mxs_lradc_enable_touch_detection(lradc); /* re-start */ | |
740 | return; | |
741 | } | |
742 | lradc->ts_x_pos = val; | |
743 | mxs_lradc_prepare_pressure(lradc); | |
744 | return; | |
745 | ||
746 | case LRADC_SAMPLE_PRESSURE: | |
747 | lradc->ts_pressure = | |
748 | mxs_lradc_read_ts_pressure(lradc, TS_CH_XP, TS_CH_YM); | |
749 | mxs_lradc_complete_touch_event(lradc); | |
750 | return; | |
751 | ||
752 | case LRADC_SAMPLE_VALID: | |
753 | val = mxs_lradc_read_ts_channel(lradc); /* ignore the value */ | |
754 | mxs_lradc_finish_touch_event(lradc, 1); | |
755 | break; | |
756 | } | |
757 | } | |
758 | ||
bc2c90c9 MV |
759 | /* |
760 | * Raw I/O operations | |
761 | */ | |
762 | static int mxs_lradc_read_raw(struct iio_dev *iio_dev, | |
763 | const struct iio_chan_spec *chan, | |
764 | int *val, int *val2, long m) | |
765 | { | |
766 | struct mxs_lradc *lradc = iio_priv(iio_dev); | |
767 | int ret; | |
768 | ||
769 | if (m != IIO_CHAN_INFO_RAW) | |
770 | return -EINVAL; | |
771 | ||
772 | /* Check for invalid channel */ | |
773 | if (chan->channel > LRADC_MAX_TOTAL_CHANS) | |
774 | return -EINVAL; | |
775 | ||
776 | /* | |
777 | * See if there is no buffered operation in progess. If there is, simply | |
778 | * bail out. This can be improved to support both buffered and raw IO at | |
779 | * the same time, yet the code becomes horribly complicated. Therefore I | |
780 | * applied KISS principle here. | |
781 | */ | |
782 | ret = mutex_trylock(&lradc->lock); | |
783 | if (!ret) | |
784 | return -EBUSY; | |
785 | ||
16735d02 | 786 | reinit_completion(&lradc->completion); |
bc2c90c9 MV |
787 | |
788 | /* | |
789 | * No buffered operation in progress, map the channel and trigger it. | |
790 | * Virtual channel 0 is always used here as the others are always not | |
791 | * used if doing raw sampling. | |
792 | */ | |
8c06f714 JB |
793 | if (lradc->soc == IMX28_LRADC) |
794 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, | |
f0b83cc8 JB |
795 | LRADC_CTRL1); |
796 | mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); | |
bc2c90c9 | 797 | |
06ddd353 | 798 | /* Clean the slot's previous content, then set new one. */ |
f0b83cc8 JB |
799 | mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(0), LRADC_CTRL4); |
800 | mxs_lradc_reg_set(lradc, chan->channel, LRADC_CTRL4); | |
06ddd353 | 801 | |
f0b83cc8 | 802 | mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(0)); |
bc2c90c9 MV |
803 | |
804 | /* Enable the IRQ and start sampling the channel. */ | |
f0b83cc8 JB |
805 | mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), LRADC_CTRL1); |
806 | mxs_lradc_reg_set(lradc, 1 << 0, LRADC_CTRL0); | |
bc2c90c9 MV |
807 | |
808 | /* Wait for completion on the channel, 1 second max. */ | |
809 | ret = wait_for_completion_killable_timeout(&lradc->completion, HZ); | |
810 | if (!ret) | |
811 | ret = -ETIMEDOUT; | |
812 | if (ret < 0) | |
813 | goto err; | |
814 | ||
815 | /* Read the data. */ | |
816 | *val = readl(lradc->base + LRADC_CH(0)) & LRADC_CH_VALUE_MASK; | |
817 | ret = IIO_VAL_INT; | |
818 | ||
819 | err: | |
f0b83cc8 | 820 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), LRADC_CTRL1); |
bc2c90c9 MV |
821 | |
822 | mutex_unlock(&lradc->lock); | |
823 | ||
824 | return ret; | |
825 | } | |
826 | ||
827 | static const struct iio_info mxs_lradc_iio_info = { | |
828 | .driver_module = THIS_MODULE, | |
829 | .read_raw = mxs_lradc_read_raw, | |
830 | }; | |
831 | ||
06ddd353 MV |
832 | static int mxs_lradc_ts_open(struct input_dev *dev) |
833 | { | |
834 | struct mxs_lradc *lradc = input_get_drvdata(dev); | |
835 | ||
06ddd353 | 836 | /* Enable the touch-detect circuitry. */ |
dee05308 | 837 | mxs_lradc_enable_touch_detection(lradc); |
06ddd353 MV |
838 | |
839 | return 0; | |
840 | } | |
841 | ||
dee05308 | 842 | static void mxs_lradc_disable_ts(struct mxs_lradc *lradc) |
06ddd353 | 843 | { |
dee05308 JB |
844 | /* stop all interrupts from firing */ |
845 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN | | |
846 | LRADC_CTRL1_LRADC_IRQ_EN(2) | LRADC_CTRL1_LRADC_IRQ_EN(3) | | |
847 | LRADC_CTRL1_LRADC_IRQ_EN(4) | LRADC_CTRL1_LRADC_IRQ_EN(5), | |
848 | LRADC_CTRL1); | |
06ddd353 | 849 | |
dee05308 JB |
850 | /* Power-down touchscreen touch-detect circuitry. */ |
851 | mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); | |
852 | } | |
06ddd353 | 853 | |
dee05308 JB |
854 | static void mxs_lradc_ts_close(struct input_dev *dev) |
855 | { | |
856 | struct mxs_lradc *lradc = input_get_drvdata(dev); | |
06ddd353 | 857 | |
dee05308 | 858 | mxs_lradc_disable_ts(lradc); |
06ddd353 MV |
859 | } |
860 | ||
861 | static int mxs_lradc_ts_register(struct mxs_lradc *lradc) | |
862 | { | |
863 | struct input_dev *input; | |
864 | struct device *dev = lradc->dev; | |
865 | int ret; | |
866 | ||
867 | if (!lradc->use_touchscreen) | |
868 | return 0; | |
869 | ||
870 | input = input_allocate_device(); | |
f99a92c3 | 871 | if (!input) |
06ddd353 | 872 | return -ENOMEM; |
06ddd353 MV |
873 | |
874 | input->name = DRIVER_NAME; | |
875 | input->id.bustype = BUS_HOST; | |
876 | input->dev.parent = dev; | |
877 | input->open = mxs_lradc_ts_open; | |
878 | input->close = mxs_lradc_ts_close; | |
879 | ||
880 | __set_bit(EV_ABS, input->evbit); | |
881 | __set_bit(EV_KEY, input->evbit); | |
882 | __set_bit(BTN_TOUCH, input->keybit); | |
1eb70a97 HP |
883 | input_set_abs_params(input, ABS_X, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0); |
884 | input_set_abs_params(input, ABS_Y, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0); | |
885 | input_set_abs_params(input, ABS_PRESSURE, 0, LRADC_SINGLE_SAMPLE_MASK, | |
886 | 0, 0); | |
06ddd353 MV |
887 | |
888 | lradc->ts_input = input; | |
889 | input_set_drvdata(input, lradc); | |
890 | ret = input_register_device(input); | |
891 | if (ret) | |
892 | input_free_device(lradc->ts_input); | |
893 | ||
894 | return ret; | |
895 | } | |
896 | ||
897 | static void mxs_lradc_ts_unregister(struct mxs_lradc *lradc) | |
898 | { | |
899 | if (!lradc->use_touchscreen) | |
900 | return; | |
901 | ||
dee05308 | 902 | mxs_lradc_disable_ts(lradc); |
06ddd353 MV |
903 | input_unregister_device(lradc->ts_input); |
904 | } | |
905 | ||
bc2c90c9 MV |
906 | /* |
907 | * IRQ Handling | |
908 | */ | |
909 | static irqreturn_t mxs_lradc_handle_irq(int irq, void *data) | |
910 | { | |
911 | struct iio_dev *iio = data; | |
912 | struct mxs_lradc *lradc = iio_priv(iio); | |
913 | unsigned long reg = readl(lradc->base + LRADC_CTRL1); | |
06ddd353 | 914 | const uint32_t ts_irq_mask = |
dee05308 JB |
915 | LRADC_CTRL1_TOUCH_DETECT_IRQ | |
916 | LRADC_CTRL1_LRADC_IRQ(2) | | |
917 | LRADC_CTRL1_LRADC_IRQ(3) | | |
918 | LRADC_CTRL1_LRADC_IRQ(4) | | |
919 | LRADC_CTRL1_LRADC_IRQ(5); | |
bc2c90c9 | 920 | |
f0b83cc8 | 921 | if (!(reg & mxs_lradc_irq_mask(lradc))) |
bc2c90c9 MV |
922 | return IRQ_NONE; |
923 | ||
dee05308 JB |
924 | if (lradc->use_touchscreen && (reg & ts_irq_mask)) |
925 | mxs_lradc_handle_touch(lradc); | |
bc2c90c9 MV |
926 | |
927 | if (iio_buffer_enabled(iio)) | |
928 | iio_trigger_poll(iio->trig, iio_get_time_ns()); | |
929 | else if (reg & LRADC_CTRL1_LRADC_IRQ(0)) | |
930 | complete(&lradc->completion); | |
931 | ||
f0b83cc8 | 932 | mxs_lradc_reg_clear(lradc, reg & mxs_lradc_irq_mask(lradc), LRADC_CTRL1); |
bc2c90c9 MV |
933 | |
934 | return IRQ_HANDLED; | |
935 | } | |
936 | ||
937 | /* | |
938 | * Trigger handling | |
939 | */ | |
940 | static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p) | |
941 | { | |
942 | struct iio_poll_func *pf = p; | |
943 | struct iio_dev *iio = pf->indio_dev; | |
944 | struct mxs_lradc *lradc = iio_priv(iio); | |
bc2c90c9 MV |
945 | const uint32_t chan_value = LRADC_CH_ACCUMULATE | |
946 | ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); | |
7b7a4efe | 947 | unsigned int i, j = 0; |
bc2c90c9 | 948 | |
f4914e5e | 949 | for_each_set_bit(i, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) { |
bc2c90c9 | 950 | lradc->buffer[j] = readl(lradc->base + LRADC_CH(j)); |
f0b83cc8 | 951 | mxs_lradc_reg_wrt(lradc, chan_value, LRADC_CH(j)); |
bc2c90c9 MV |
952 | lradc->buffer[j] &= LRADC_CH_VALUE_MASK; |
953 | lradc->buffer[j] /= LRADC_DELAY_TIMER_LOOP; | |
954 | j++; | |
955 | } | |
956 | ||
4fa10de6 | 957 | iio_push_to_buffers_with_timestamp(iio, lradc->buffer, pf->timestamp); |
bc2c90c9 MV |
958 | |
959 | iio_trigger_notify_done(iio->trig); | |
960 | ||
961 | return IRQ_HANDLED; | |
962 | } | |
963 | ||
964 | static int mxs_lradc_configure_trigger(struct iio_trigger *trig, bool state) | |
965 | { | |
1e9663c6 | 966 | struct iio_dev *iio = iio_trigger_get_drvdata(trig); |
bc2c90c9 MV |
967 | struct mxs_lradc *lradc = iio_priv(iio); |
968 | const uint32_t st = state ? STMP_OFFSET_REG_SET : STMP_OFFSET_REG_CLR; | |
969 | ||
f0b83cc8 | 970 | mxs_lradc_reg_wrt(lradc, LRADC_DELAY_KICK, LRADC_DELAY(0) + st); |
bc2c90c9 MV |
971 | |
972 | return 0; | |
973 | } | |
974 | ||
975 | static const struct iio_trigger_ops mxs_lradc_trigger_ops = { | |
976 | .owner = THIS_MODULE, | |
977 | .set_trigger_state = &mxs_lradc_configure_trigger, | |
978 | }; | |
979 | ||
980 | static int mxs_lradc_trigger_init(struct iio_dev *iio) | |
981 | { | |
982 | int ret; | |
983 | struct iio_trigger *trig; | |
e1b1fa66 | 984 | struct mxs_lradc *lradc = iio_priv(iio); |
bc2c90c9 MV |
985 | |
986 | trig = iio_trigger_alloc("%s-dev%i", iio->name, iio->id); | |
987 | if (trig == NULL) | |
988 | return -ENOMEM; | |
989 | ||
e1b1fa66 | 990 | trig->dev.parent = lradc->dev; |
1e9663c6 | 991 | iio_trigger_set_drvdata(trig, iio); |
bc2c90c9 MV |
992 | trig->ops = &mxs_lradc_trigger_ops; |
993 | ||
994 | ret = iio_trigger_register(trig); | |
995 | if (ret) { | |
996 | iio_trigger_free(trig); | |
997 | return ret; | |
998 | } | |
999 | ||
e1b1fa66 | 1000 | lradc->trig = trig; |
bc2c90c9 MV |
1001 | |
1002 | return 0; | |
1003 | } | |
1004 | ||
1005 | static void mxs_lradc_trigger_remove(struct iio_dev *iio) | |
1006 | { | |
e1b1fa66 MV |
1007 | struct mxs_lradc *lradc = iio_priv(iio); |
1008 | ||
1009 | iio_trigger_unregister(lradc->trig); | |
1010 | iio_trigger_free(lradc->trig); | |
bc2c90c9 MV |
1011 | } |
1012 | ||
1013 | static int mxs_lradc_buffer_preenable(struct iio_dev *iio) | |
1014 | { | |
1015 | struct mxs_lradc *lradc = iio_priv(iio); | |
06ddd353 MV |
1016 | int ret = 0, chan, ofs = 0; |
1017 | unsigned long enable = 0; | |
1018 | uint32_t ctrl4_set = 0; | |
1019 | uint32_t ctrl4_clr = 0; | |
bc2c90c9 MV |
1020 | uint32_t ctrl1_irq = 0; |
1021 | const uint32_t chan_value = LRADC_CH_ACCUMULATE | | |
1022 | ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); | |
c80712c7 | 1023 | const int len = bitmap_weight(iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS); |
bc2c90c9 MV |
1024 | |
1025 | if (!len) | |
1026 | return -EINVAL; | |
1027 | ||
1028 | /* | |
1029 | * Lock the driver so raw access can not be done during buffered | |
1030 | * operation. This simplifies the code a lot. | |
1031 | */ | |
1032 | ret = mutex_trylock(&lradc->lock); | |
1033 | if (!ret) | |
1034 | return -EBUSY; | |
1035 | ||
1036 | lradc->buffer = kmalloc(len * sizeof(*lradc->buffer), GFP_KERNEL); | |
1037 | if (!lradc->buffer) { | |
1038 | ret = -ENOMEM; | |
1039 | goto err_mem; | |
1040 | } | |
1041 | ||
8c06f714 JB |
1042 | if (lradc->soc == IMX28_LRADC) |
1043 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, | |
f0b83cc8 JB |
1044 | LRADC_CTRL1); |
1045 | mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); | |
bc2c90c9 | 1046 | |
c80712c7 | 1047 | for_each_set_bit(chan, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) { |
06ddd353 MV |
1048 | ctrl4_set |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs); |
1049 | ctrl4_clr |= LRADC_CTRL4_LRADCSELECT_MASK(ofs); | |
bc2c90c9 | 1050 | ctrl1_irq |= LRADC_CTRL1_LRADC_IRQ_EN(ofs); |
f0b83cc8 | 1051 | mxs_lradc_reg_wrt(lradc, chan_value, LRADC_CH(ofs)); |
06ddd353 | 1052 | bitmap_set(&enable, ofs, 1); |
bc2c90c9 | 1053 | ofs++; |
73327b4c | 1054 | } |
bc2c90c9 | 1055 | |
f0b83cc8 JB |
1056 | mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK | |
1057 | LRADC_DELAY_KICK, LRADC_DELAY(0)); | |
1058 | mxs_lradc_reg_clear(lradc, ctrl4_clr, LRADC_CTRL4); | |
1059 | mxs_lradc_reg_set(lradc, ctrl4_set, LRADC_CTRL4); | |
1060 | mxs_lradc_reg_set(lradc, ctrl1_irq, LRADC_CTRL1); | |
1061 | mxs_lradc_reg_set(lradc, enable << LRADC_DELAY_TRIGGER_LRADCS_OFFSET, | |
1062 | LRADC_DELAY(0)); | |
bc2c90c9 MV |
1063 | |
1064 | return 0; | |
1065 | ||
bc2c90c9 MV |
1066 | err_mem: |
1067 | mutex_unlock(&lradc->lock); | |
1068 | return ret; | |
1069 | } | |
1070 | ||
1071 | static int mxs_lradc_buffer_postdisable(struct iio_dev *iio) | |
1072 | { | |
1073 | struct mxs_lradc *lradc = iio_priv(iio); | |
1074 | ||
f0b83cc8 JB |
1075 | mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK | |
1076 | LRADC_DELAY_KICK, LRADC_DELAY(0)); | |
bc2c90c9 | 1077 | |
f0b83cc8 | 1078 | mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); |
8c06f714 JB |
1079 | if (lradc->soc == IMX28_LRADC) |
1080 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, | |
f0b83cc8 | 1081 | LRADC_CTRL1); |
bc2c90c9 MV |
1082 | |
1083 | kfree(lradc->buffer); | |
1084 | mutex_unlock(&lradc->lock); | |
1085 | ||
1086 | return 0; | |
1087 | } | |
1088 | ||
1089 | static bool mxs_lradc_validate_scan_mask(struct iio_dev *iio, | |
1090 | const unsigned long *mask) | |
1091 | { | |
06ddd353 | 1092 | struct mxs_lradc *lradc = iio_priv(iio); |
f4914e5e | 1093 | const int map_chans = bitmap_weight(mask, LRADC_MAX_TOTAL_CHANS); |
06ddd353 MV |
1094 | int rsvd_chans = 0; |
1095 | unsigned long rsvd_mask = 0; | |
1096 | ||
1097 | if (lradc->use_touchbutton) | |
1098 | rsvd_mask |= CHAN_MASK_TOUCHBUTTON; | |
1099 | if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_4WIRE) | |
1100 | rsvd_mask |= CHAN_MASK_TOUCHSCREEN_4WIRE; | |
1101 | if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) | |
1102 | rsvd_mask |= CHAN_MASK_TOUCHSCREEN_5WIRE; | |
1103 | ||
1104 | if (lradc->use_touchbutton) | |
1105 | rsvd_chans++; | |
1106 | if (lradc->use_touchscreen) | |
1107 | rsvd_chans++; | |
1108 | ||
1109 | /* Test for attempts to map channels with special mode of operation. */ | |
f4914e5e | 1110 | if (bitmap_intersects(mask, &rsvd_mask, LRADC_MAX_TOTAL_CHANS)) |
06ddd353 MV |
1111 | return false; |
1112 | ||
1113 | /* Test for attempts to map more channels then available slots. */ | |
1114 | if (map_chans + rsvd_chans > LRADC_MAX_MAPPED_CHANS) | |
1115 | return false; | |
1116 | ||
1117 | return true; | |
bc2c90c9 MV |
1118 | } |
1119 | ||
1120 | static const struct iio_buffer_setup_ops mxs_lradc_buffer_ops = { | |
1121 | .preenable = &mxs_lradc_buffer_preenable, | |
1122 | .postenable = &iio_triggered_buffer_postenable, | |
1123 | .predisable = &iio_triggered_buffer_predisable, | |
1124 | .postdisable = &mxs_lradc_buffer_postdisable, | |
1125 | .validate_scan_mask = &mxs_lradc_validate_scan_mask, | |
1126 | }; | |
1127 | ||
1128 | /* | |
1129 | * Driver initialization | |
1130 | */ | |
1131 | ||
1132 | #define MXS_ADC_CHAN(idx, chan_type) { \ | |
1133 | .type = (chan_type), \ | |
1134 | .indexed = 1, \ | |
1135 | .scan_index = (idx), \ | |
78a5fa67 | 1136 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
bc2c90c9 MV |
1137 | .channel = (idx), \ |
1138 | .scan_type = { \ | |
1139 | .sign = 'u', \ | |
1eb70a97 | 1140 | .realbits = LRADC_RESOLUTION, \ |
bc2c90c9 MV |
1141 | .storagebits = 32, \ |
1142 | }, \ | |
1143 | } | |
1144 | ||
1145 | static const struct iio_chan_spec mxs_lradc_chan_spec[] = { | |
1146 | MXS_ADC_CHAN(0, IIO_VOLTAGE), | |
1147 | MXS_ADC_CHAN(1, IIO_VOLTAGE), | |
1148 | MXS_ADC_CHAN(2, IIO_VOLTAGE), | |
1149 | MXS_ADC_CHAN(3, IIO_VOLTAGE), | |
1150 | MXS_ADC_CHAN(4, IIO_VOLTAGE), | |
1151 | MXS_ADC_CHAN(5, IIO_VOLTAGE), | |
1152 | MXS_ADC_CHAN(6, IIO_VOLTAGE), | |
1153 | MXS_ADC_CHAN(7, IIO_VOLTAGE), /* VBATT */ | |
1154 | MXS_ADC_CHAN(8, IIO_TEMP), /* Temp sense 0 */ | |
1155 | MXS_ADC_CHAN(9, IIO_TEMP), /* Temp sense 1 */ | |
1156 | MXS_ADC_CHAN(10, IIO_VOLTAGE), /* VDDIO */ | |
1157 | MXS_ADC_CHAN(11, IIO_VOLTAGE), /* VTH */ | |
1158 | MXS_ADC_CHAN(12, IIO_VOLTAGE), /* VDDA */ | |
1159 | MXS_ADC_CHAN(13, IIO_VOLTAGE), /* VDDD */ | |
1160 | MXS_ADC_CHAN(14, IIO_VOLTAGE), /* VBG */ | |
1161 | MXS_ADC_CHAN(15, IIO_VOLTAGE), /* VDD5V */ | |
1162 | }; | |
1163 | ||
947123d5 | 1164 | static int mxs_lradc_hw_init(struct mxs_lradc *lradc) |
bc2c90c9 | 1165 | { |
06ddd353 MV |
1166 | /* The ADC always uses DELAY CHANNEL 0. */ |
1167 | const uint32_t adc_cfg = | |
1168 | (1 << (LRADC_DELAY_TRIGGER_DELAYS_OFFSET + 0)) | | |
bc2c90c9 MV |
1169 | (LRADC_DELAY_TIMER_PER << LRADC_DELAY_DELAY_OFFSET); |
1170 | ||
947123d5 FE |
1171 | int ret = stmp_reset_block(lradc->base); |
1172 | if (ret) | |
1173 | return ret; | |
bc2c90c9 | 1174 | |
06ddd353 | 1175 | /* Configure DELAY CHANNEL 0 for generic ADC sampling. */ |
f0b83cc8 | 1176 | mxs_lradc_reg_wrt(lradc, adc_cfg, LRADC_DELAY(0)); |
06ddd353 MV |
1177 | |
1178 | /* Disable remaining DELAY CHANNELs */ | |
f0b83cc8 JB |
1179 | mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(1)); |
1180 | mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); | |
1181 | mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); | |
06ddd353 MV |
1182 | |
1183 | /* Configure the touchscreen type */ | |
8c06f714 JB |
1184 | if (lradc->soc == IMX28_LRADC) { |
1185 | mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, | |
f0b83cc8 | 1186 | LRADC_CTRL0); |
06ddd353 | 1187 | |
f0b83cc8 JB |
1188 | if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) |
1189 | mxs_lradc_reg_set(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, | |
1190 | LRADC_CTRL0); | |
06ddd353 | 1191 | } |
bc2c90c9 MV |
1192 | |
1193 | /* Start internal temperature sensing. */ | |
f0b83cc8 | 1194 | mxs_lradc_reg_wrt(lradc, 0, LRADC_CTRL2); |
947123d5 FE |
1195 | |
1196 | return 0; | |
bc2c90c9 MV |
1197 | } |
1198 | ||
1199 | static void mxs_lradc_hw_stop(struct mxs_lradc *lradc) | |
1200 | { | |
1201 | int i; | |
1202 | ||
f0b83cc8 | 1203 | mxs_lradc_reg_clear(lradc, mxs_lradc_irq_en_mask(lradc), LRADC_CTRL1); |
bc2c90c9 MV |
1204 | |
1205 | for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++) | |
f0b83cc8 | 1206 | mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(i)); |
bc2c90c9 MV |
1207 | } |
1208 | ||
5e1f9aca MV |
1209 | static const struct of_device_id mxs_lradc_dt_ids[] = { |
1210 | { .compatible = "fsl,imx23-lradc", .data = (void *)IMX23_LRADC, }, | |
1211 | { .compatible = "fsl,imx28-lradc", .data = (void *)IMX28_LRADC, }, | |
1212 | { /* sentinel */ } | |
1213 | }; | |
1214 | MODULE_DEVICE_TABLE(of, mxs_lradc_dt_ids); | |
1215 | ||
dee05308 JB |
1216 | static int mxs_lradc_probe_touchscreen(struct mxs_lradc *lradc, |
1217 | struct device_node *lradc_node) | |
1218 | { | |
e9c88fb5 JB |
1219 | int ret; |
1220 | u32 ts_wires = 0, adapt; | |
1221 | ||
1222 | ret = of_property_read_u32(lradc_node, "fsl,lradc-touchscreen-wires", | |
1223 | &ts_wires); | |
1224 | if (ret) | |
1225 | return -ENODEV; /* touchscreen feature disabled */ | |
1226 | ||
1227 | switch (ts_wires) { | |
1228 | case 4: | |
1229 | lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_4WIRE; | |
1230 | break; | |
1231 | case 5: | |
1232 | if (lradc->soc == IMX28_LRADC) { | |
1233 | lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_5WIRE; | |
1234 | break; | |
1235 | } | |
1236 | /* fall through an error message for i.MX23 */ | |
1237 | default: | |
1238 | dev_err(lradc->dev, | |
1239 | "Unsupported number of touchscreen wires (%d)\n", | |
1240 | ts_wires); | |
1241 | return -EINVAL; | |
1242 | } | |
1243 | ||
dee05308 | 1244 | lradc->over_sample_cnt = 4; |
e9c88fb5 JB |
1245 | ret = of_property_read_u32(lradc_node, "fsl,ave-ctrl", &adapt); |
1246 | if (ret == 0) | |
1247 | lradc->over_sample_cnt = adapt; | |
1248 | ||
dee05308 | 1249 | lradc->over_sample_delay = 2; |
e9c88fb5 JB |
1250 | ret = of_property_read_u32(lradc_node, "fsl,ave-delay", &adapt); |
1251 | if (ret == 0) | |
1252 | lradc->over_sample_delay = adapt; | |
1253 | ||
dee05308 | 1254 | lradc->settling_delay = 10; |
e9c88fb5 JB |
1255 | ret = of_property_read_u32(lradc_node, "fsl,settling", &adapt); |
1256 | if (ret == 0) | |
1257 | lradc->settling_delay = adapt; | |
dee05308 JB |
1258 | |
1259 | return 0; | |
1260 | } | |
1261 | ||
4ae1c61f | 1262 | static int mxs_lradc_probe(struct platform_device *pdev) |
bc2c90c9 | 1263 | { |
5e1f9aca MV |
1264 | const struct of_device_id *of_id = |
1265 | of_match_device(mxs_lradc_dt_ids, &pdev->dev); | |
1266 | const struct mxs_lradc_of_config *of_cfg = | |
1267 | &mxs_lradc_of_config[(enum mxs_lradc_id)of_id->data]; | |
bc2c90c9 | 1268 | struct device *dev = &pdev->dev; |
06ddd353 | 1269 | struct device_node *node = dev->of_node; |
bc2c90c9 MV |
1270 | struct mxs_lradc *lradc; |
1271 | struct iio_dev *iio; | |
1272 | struct resource *iores; | |
dee05308 | 1273 | int ret = 0, touch_ret; |
bc2c90c9 MV |
1274 | int i; |
1275 | ||
1276 | /* Allocate the IIO device. */ | |
073c33d5 | 1277 | iio = devm_iio_device_alloc(dev, sizeof(*lradc)); |
bc2c90c9 MV |
1278 | if (!iio) { |
1279 | dev_err(dev, "Failed to allocate IIO device\n"); | |
1280 | return -ENOMEM; | |
1281 | } | |
1282 | ||
1283 | lradc = iio_priv(iio); | |
ccff5297 | 1284 | lradc->soc = (enum mxs_lradc_id)of_id->data; |
bc2c90c9 MV |
1285 | |
1286 | /* Grab the memory area */ | |
1287 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
1288 | lradc->dev = &pdev->dev; | |
97f4be60 | 1289 | lradc->base = devm_ioremap_resource(dev, iores); |
073c33d5 SK |
1290 | if (IS_ERR(lradc->base)) |
1291 | return PTR_ERR(lradc->base); | |
bc2c90c9 | 1292 | |
18da755d JB |
1293 | lradc->clk = devm_clk_get(&pdev->dev, NULL); |
1294 | if (IS_ERR(lradc->clk)) { | |
1295 | dev_err(dev, "Failed to get the delay unit clock\n"); | |
1296 | return PTR_ERR(lradc->clk); | |
1297 | } | |
1298 | ret = clk_prepare_enable(lradc->clk); | |
1299 | if (ret != 0) { | |
1300 | dev_err(dev, "Failed to enable the delay unit clock\n"); | |
1301 | return ret; | |
1302 | } | |
1303 | ||
dee05308 | 1304 | touch_ret = mxs_lradc_probe_touchscreen(lradc, node); |
06ddd353 | 1305 | |
bc2c90c9 | 1306 | /* Grab all IRQ sources */ |
5e1f9aca | 1307 | for (i = 0; i < of_cfg->irq_count; i++) { |
bc2c90c9 | 1308 | lradc->irq[i] = platform_get_irq(pdev, i); |
073c33d5 SK |
1309 | if (lradc->irq[i] < 0) |
1310 | return -EINVAL; | |
bc2c90c9 MV |
1311 | |
1312 | ret = devm_request_irq(dev, lradc->irq[i], | |
1313 | mxs_lradc_handle_irq, 0, | |
5e1f9aca | 1314 | of_cfg->irq_name[i], iio); |
bc2c90c9 | 1315 | if (ret) |
073c33d5 | 1316 | return ret; |
bc2c90c9 MV |
1317 | } |
1318 | ||
1319 | platform_set_drvdata(pdev, iio); | |
1320 | ||
1321 | init_completion(&lradc->completion); | |
1322 | mutex_init(&lradc->lock); | |
1323 | ||
1324 | iio->name = pdev->name; | |
1325 | iio->dev.parent = &pdev->dev; | |
1326 | iio->info = &mxs_lradc_iio_info; | |
1327 | iio->modes = INDIO_DIRECT_MODE; | |
1328 | iio->channels = mxs_lradc_chan_spec; | |
1329 | iio->num_channels = ARRAY_SIZE(mxs_lradc_chan_spec); | |
f4914e5e | 1330 | iio->masklength = LRADC_MAX_TOTAL_CHANS; |
bc2c90c9 MV |
1331 | |
1332 | ret = iio_triggered_buffer_setup(iio, &iio_pollfunc_store_time, | |
1333 | &mxs_lradc_trigger_handler, | |
1334 | &mxs_lradc_buffer_ops); | |
1335 | if (ret) | |
073c33d5 | 1336 | return ret; |
bc2c90c9 MV |
1337 | |
1338 | ret = mxs_lradc_trigger_init(iio); | |
1339 | if (ret) | |
1340 | goto err_trig; | |
1341 | ||
f6e8a968 | 1342 | /* Configure the hardware. */ |
947123d5 FE |
1343 | ret = mxs_lradc_hw_init(lradc); |
1344 | if (ret) | |
1345 | goto err_dev; | |
f6e8a968 | 1346 | |
06ddd353 | 1347 | /* Register the touchscreen input device. */ |
dee05308 JB |
1348 | if (touch_ret == 0) { |
1349 | ret = mxs_lradc_ts_register(lradc); | |
1350 | if (ret) | |
1351 | goto err_ts_register; | |
1352 | } | |
06ddd353 | 1353 | |
bc2c90c9 MV |
1354 | /* Register IIO device. */ |
1355 | ret = iio_device_register(iio); | |
1356 | if (ret) { | |
1357 | dev_err(dev, "Failed to register IIO device\n"); | |
06ddd353 | 1358 | goto err_ts; |
bc2c90c9 MV |
1359 | } |
1360 | ||
bc2c90c9 MV |
1361 | return 0; |
1362 | ||
06ddd353 MV |
1363 | err_ts: |
1364 | mxs_lradc_ts_unregister(lradc); | |
a0ef6db7 FE |
1365 | err_ts_register: |
1366 | mxs_lradc_hw_stop(lradc); | |
bc2c90c9 MV |
1367 | err_dev: |
1368 | mxs_lradc_trigger_remove(iio); | |
1369 | err_trig: | |
1370 | iio_triggered_buffer_cleanup(iio); | |
bc2c90c9 MV |
1371 | return ret; |
1372 | } | |
1373 | ||
447d4f29 | 1374 | static int mxs_lradc_remove(struct platform_device *pdev) |
bc2c90c9 MV |
1375 | { |
1376 | struct iio_dev *iio = platform_get_drvdata(pdev); | |
1377 | struct mxs_lradc *lradc = iio_priv(iio); | |
1378 | ||
a0ef6db7 | 1379 | iio_device_unregister(iio); |
06ddd353 | 1380 | mxs_lradc_ts_unregister(lradc); |
bc2c90c9 | 1381 | mxs_lradc_hw_stop(lradc); |
bc2c90c9 | 1382 | mxs_lradc_trigger_remove(iio); |
a0ef6db7 | 1383 | iio_triggered_buffer_cleanup(iio); |
bc2c90c9 | 1384 | |
18da755d | 1385 | clk_disable_unprepare(lradc->clk); |
bc2c90c9 MV |
1386 | return 0; |
1387 | } | |
1388 | ||
bc2c90c9 MV |
1389 | static struct platform_driver mxs_lradc_driver = { |
1390 | .driver = { | |
1391 | .name = DRIVER_NAME, | |
1392 | .owner = THIS_MODULE, | |
1393 | .of_match_table = mxs_lradc_dt_ids, | |
1394 | }, | |
1395 | .probe = mxs_lradc_probe, | |
e543acf0 | 1396 | .remove = mxs_lradc_remove, |
bc2c90c9 MV |
1397 | }; |
1398 | ||
1399 | module_platform_driver(mxs_lradc_driver); | |
1400 | ||
1401 | MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); | |
1402 | MODULE_DESCRIPTION("Freescale i.MX28 LRADC driver"); | |
1403 | MODULE_LICENSE("GPL v2"); | |
8c4a8c9d | 1404 | MODULE_ALIAS("platform:" DRIVER_NAME); |