Commit | Line | Data |
---|---|---|
bc2c90c9 | 1 | /* |
07a4257e | 2 | * Freescale MXS LRADC driver |
bc2c90c9 MV |
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 | ||
ae5896d4 SW |
18 | #include <linux/bitops.h> |
19 | #include <linux/clk.h> | |
20 | #include <linux/completion.h> | |
21 | #include <linux/device.h> | |
97f4be60 | 22 | #include <linux/err.h> |
ae5896d4 | 23 | #include <linux/input.h> |
bc2c90c9 | 24 | #include <linux/interrupt.h> |
bc2c90c9 | 25 | #include <linux/io.h> |
ae5896d4 | 26 | #include <linux/kernel.h> |
bc2c90c9 | 27 | #include <linux/module.h> |
5723dde9 | 28 | #include <linux/mutex.h> |
ae5896d4 SW |
29 | #include <linux/of.h> |
30 | #include <linux/of_device.h> | |
bc2c90c9 | 31 | #include <linux/platform_device.h> |
ae5896d4 | 32 | #include <linux/slab.h> |
bc2c90c9 | 33 | #include <linux/stmp_device.h> |
ae5896d4 | 34 | #include <linux/sysfs.h> |
bc2c90c9 | 35 | |
bc2c90c9 | 36 | #include <linux/iio/buffer.h> |
ae5896d4 | 37 | #include <linux/iio/iio.h> |
bc2c90c9 MV |
38 | #include <linux/iio/trigger.h> |
39 | #include <linux/iio/trigger_consumer.h> | |
40 | #include <linux/iio/triggered_buffer.h> | |
ae5896d4 | 41 | #include <linux/iio/sysfs.h> |
bc2c90c9 MV |
42 | |
43 | #define DRIVER_NAME "mxs-lradc" | |
44 | ||
45 | #define LRADC_MAX_DELAY_CHANS 4 | |
46 | #define LRADC_MAX_MAPPED_CHANS 8 | |
47 | #define LRADC_MAX_TOTAL_CHANS 16 | |
48 | ||
49 | #define LRADC_DELAY_TIMER_HZ 2000 | |
50 | ||
51 | /* | |
52 | * Make this runtime configurable if necessary. Currently, if the buffered mode | |
53 | * is enabled, the LRADC takes LRADC_DELAY_TIMER_LOOP samples of data before | |
54 | * triggering IRQ. The sampling happens every (LRADC_DELAY_TIMER_PER / 2000) | |
55 | * seconds. The result is that the samples arrive every 500mS. | |
56 | */ | |
57 | #define LRADC_DELAY_TIMER_PER 200 | |
58 | #define LRADC_DELAY_TIMER_LOOP 5 | |
59 | ||
06ddd353 MV |
60 | /* |
61 | * Once the pen touches the touchscreen, the touchscreen switches from | |
62 | * IRQ-driven mode to polling mode to prevent interrupt storm. The polling | |
63 | * is realized by worker thread, which is called every 20 or so milliseconds. | |
66926d11 | 64 | * This gives the touchscreen enough fluency and does not strain the system |
06ddd353 MV |
65 | * too much. |
66 | */ | |
67 | #define LRADC_TS_SAMPLE_DELAY_MS 5 | |
68 | ||
69 | /* | |
70 | * The LRADC reads the following amount of samples from each touchscreen | |
66926d11 | 71 | * channel and the driver then computes average of these. |
06ddd353 MV |
72 | */ |
73 | #define LRADC_TS_SAMPLE_AMOUNT 4 | |
74 | ||
5e1f9aca MV |
75 | enum mxs_lradc_id { |
76 | IMX23_LRADC, | |
77 | IMX28_LRADC, | |
78 | }; | |
79 | ||
80 | static const char * const mx23_lradc_irq_names[] = { | |
81 | "mxs-lradc-touchscreen", | |
82 | "mxs-lradc-channel0", | |
83 | "mxs-lradc-channel1", | |
84 | "mxs-lradc-channel2", | |
85 | "mxs-lradc-channel3", | |
86 | "mxs-lradc-channel4", | |
87 | "mxs-lradc-channel5", | |
88 | "mxs-lradc-channel6", | |
89 | "mxs-lradc-channel7", | |
90 | }; | |
91 | ||
92 | static const char * const mx28_lradc_irq_names[] = { | |
bc2c90c9 MV |
93 | "mxs-lradc-touchscreen", |
94 | "mxs-lradc-thresh0", | |
95 | "mxs-lradc-thresh1", | |
96 | "mxs-lradc-channel0", | |
97 | "mxs-lradc-channel1", | |
98 | "mxs-lradc-channel2", | |
99 | "mxs-lradc-channel3", | |
100 | "mxs-lradc-channel4", | |
101 | "mxs-lradc-channel5", | |
102 | "mxs-lradc-channel6", | |
103 | "mxs-lradc-channel7", | |
104 | "mxs-lradc-button0", | |
105 | "mxs-lradc-button1", | |
106 | }; | |
107 | ||
5e1f9aca MV |
108 | struct mxs_lradc_of_config { |
109 | const int irq_count; | |
110 | const char * const *irq_name; | |
0e4f0075 | 111 | const u32 *vref_mv; |
f6db68a4 HP |
112 | }; |
113 | ||
114 | #define VREF_MV_BASE 1850 | |
115 | ||
0e4f0075 | 116 | static const u32 mx23_vref_mv[LRADC_MAX_TOTAL_CHANS] = { |
f6db68a4 HP |
117 | VREF_MV_BASE, /* CH0 */ |
118 | VREF_MV_BASE, /* CH1 */ | |
119 | VREF_MV_BASE, /* CH2 */ | |
120 | VREF_MV_BASE, /* CH3 */ | |
121 | VREF_MV_BASE, /* CH4 */ | |
122 | VREF_MV_BASE, /* CH5 */ | |
123 | VREF_MV_BASE * 2, /* CH6 VDDIO */ | |
124 | VREF_MV_BASE * 4, /* CH7 VBATT */ | |
125 | VREF_MV_BASE, /* CH8 Temp sense 0 */ | |
126 | VREF_MV_BASE, /* CH9 Temp sense 1 */ | |
127 | VREF_MV_BASE, /* CH10 */ | |
128 | VREF_MV_BASE, /* CH11 */ | |
129 | VREF_MV_BASE, /* CH12 USB_DP */ | |
130 | VREF_MV_BASE, /* CH13 USB_DN */ | |
131 | VREF_MV_BASE, /* CH14 VBG */ | |
132 | VREF_MV_BASE * 4, /* CH15 VDD5V */ | |
133 | }; | |
134 | ||
0e4f0075 | 135 | static const u32 mx28_vref_mv[LRADC_MAX_TOTAL_CHANS] = { |
f6db68a4 HP |
136 | VREF_MV_BASE, /* CH0 */ |
137 | VREF_MV_BASE, /* CH1 */ | |
138 | VREF_MV_BASE, /* CH2 */ | |
139 | VREF_MV_BASE, /* CH3 */ | |
140 | VREF_MV_BASE, /* CH4 */ | |
141 | VREF_MV_BASE, /* CH5 */ | |
142 | VREF_MV_BASE, /* CH6 */ | |
143 | VREF_MV_BASE * 4, /* CH7 VBATT */ | |
144 | VREF_MV_BASE, /* CH8 Temp sense 0 */ | |
145 | VREF_MV_BASE, /* CH9 Temp sense 1 */ | |
146 | VREF_MV_BASE * 2, /* CH10 VDDIO */ | |
147 | VREF_MV_BASE, /* CH11 VTH */ | |
148 | VREF_MV_BASE * 2, /* CH12 VDDA */ | |
149 | VREF_MV_BASE, /* CH13 VDDD */ | |
150 | VREF_MV_BASE, /* CH14 VBG */ | |
151 | VREF_MV_BASE * 4, /* CH15 VDD5V */ | |
5e1f9aca MV |
152 | }; |
153 | ||
ad76fda7 | 154 | static const struct mxs_lradc_of_config mxs_lradc_of_config[] = { |
5e1f9aca MV |
155 | [IMX23_LRADC] = { |
156 | .irq_count = ARRAY_SIZE(mx23_lradc_irq_names), | |
157 | .irq_name = mx23_lradc_irq_names, | |
f6db68a4 | 158 | .vref_mv = mx23_vref_mv, |
5e1f9aca MV |
159 | }, |
160 | [IMX28_LRADC] = { | |
161 | .irq_count = ARRAY_SIZE(mx28_lradc_irq_names), | |
162 | .irq_name = mx28_lradc_irq_names, | |
f6db68a4 | 163 | .vref_mv = mx28_vref_mv, |
5e1f9aca MV |
164 | }, |
165 | }; | |
166 | ||
06ddd353 MV |
167 | enum mxs_lradc_ts { |
168 | MXS_LRADC_TOUCHSCREEN_NONE = 0, | |
169 | MXS_LRADC_TOUCHSCREEN_4WIRE, | |
170 | MXS_LRADC_TOUCHSCREEN_5WIRE, | |
bc2c90c9 MV |
171 | }; |
172 | ||
dee05308 JB |
173 | /* |
174 | * Touchscreen handling | |
175 | */ | |
176 | enum lradc_ts_plate { | |
177 | LRADC_TOUCH = 0, | |
178 | LRADC_SAMPLE_X, | |
179 | LRADC_SAMPLE_Y, | |
180 | LRADC_SAMPLE_PRESSURE, | |
181 | LRADC_SAMPLE_VALID, | |
182 | }; | |
183 | ||
aba70f2a HP |
184 | enum mxs_lradc_divbytwo { |
185 | MXS_LRADC_DIV_DISABLED = 0, | |
186 | MXS_LRADC_DIV_ENABLED, | |
187 | }; | |
188 | ||
d5acf594 HP |
189 | struct mxs_lradc_scale { |
190 | unsigned int integer; | |
191 | unsigned int nano; | |
192 | }; | |
193 | ||
bc2c90c9 MV |
194 | struct mxs_lradc { |
195 | struct device *dev; | |
196 | void __iomem *base; | |
197 | int irq[13]; | |
198 | ||
18da755d JB |
199 | struct clk *clk; |
200 | ||
0e4f0075 | 201 | u32 *buffer; |
bc2c90c9 MV |
202 | struct iio_trigger *trig; |
203 | ||
204 | struct mutex lock; | |
205 | ||
bc2c90c9 | 206 | struct completion completion; |
06ddd353 | 207 | |
0e4f0075 | 208 | const u32 *vref_mv; |
d5acf594 | 209 | struct mxs_lradc_scale scale_avail[LRADC_MAX_TOTAL_CHANS][2]; |
38125b2c | 210 | unsigned long is_divided; |
f6db68a4 | 211 | |
06ddd353 | 212 | /* |
f81197b8 KM |
213 | * When the touchscreen is enabled, we give it two private virtual |
214 | * channels: #6 and #7. This means that only 6 virtual channels (instead | |
215 | * of 8) will be available for buffered capture. | |
216 | */ | |
217 | #define TOUCHSCREEN_VCHANNEL1 7 | |
218 | #define TOUCHSCREEN_VCHANNEL2 6 | |
86bf7f3e KM |
219 | #define BUFFER_VCHANS_LIMITED 0x3f |
220 | #define BUFFER_VCHANS_ALL 0xff | |
221 | u8 buffer_vchans; | |
f81197b8 KM |
222 | |
223 | /* | |
06ddd353 MV |
224 | * Furthermore, certain LRADC channels are shared between touchscreen |
225 | * and/or touch-buttons and generic LRADC block. Therefore when using | |
226 | * either of these, these channels are not available for the regular | |
227 | * sampling. The shared channels are as follows: | |
228 | * | |
229 | * CH0 -- Touch button #0 | |
230 | * CH1 -- Touch button #1 | |
231 | * CH2 -- Touch screen XPUL | |
232 | * CH3 -- Touch screen YPLL | |
233 | * CH4 -- Touch screen XNUL | |
234 | * CH5 -- Touch screen YNLR | |
235 | * CH6 -- Touch screen WIPER (5-wire only) | |
236 | * | |
66926d11 | 237 | * The bit fields below represents which parts of the LRADC block are |
06ddd353 MV |
238 | * switched into special mode of operation. These channels can not |
239 | * be sampled as regular LRADC channels. The driver will refuse any | |
240 | * attempt to sample these channels. | |
241 | */ | |
418880f5 | 242 | #define CHAN_MASK_TOUCHBUTTON (BIT(1) | BIT(0)) |
06ddd353 MV |
243 | #define CHAN_MASK_TOUCHSCREEN_4WIRE (0xf << 2) |
244 | #define CHAN_MASK_TOUCHSCREEN_5WIRE (0x1f << 2) | |
245 | enum mxs_lradc_ts use_touchscreen; | |
06ddd353 MV |
246 | bool use_touchbutton; |
247 | ||
248 | struct input_dev *ts_input; | |
ccff5297 JB |
249 | |
250 | enum mxs_lradc_id soc; | |
66926d11 | 251 | enum lradc_ts_plate cur_plate; /* state machine */ |
dee05308 JB |
252 | bool ts_valid; |
253 | unsigned ts_x_pos; | |
254 | unsigned ts_y_pos; | |
255 | unsigned ts_pressure; | |
256 | ||
257 | /* handle touchscreen's physical behaviour */ | |
258 | /* samples per coordinate */ | |
259 | unsigned over_sample_cnt; | |
260 | /* time clocks between samples */ | |
261 | unsigned over_sample_delay; | |
262 | /* time in clocks to wait after the plates where switched */ | |
263 | unsigned settling_delay; | |
bc2c90c9 MV |
264 | }; |
265 | ||
266 | #define LRADC_CTRL0 0x00 | |
418880f5 HM |
267 | # define LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE BIT(23) |
268 | # define LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE BIT(22) | |
269 | # define LRADC_CTRL0_MX28_YNNSW /* YM */ BIT(21) | |
270 | # define LRADC_CTRL0_MX28_YPNSW /* YP */ BIT(20) | |
271 | # define LRADC_CTRL0_MX28_YPPSW /* YP */ BIT(19) | |
272 | # define LRADC_CTRL0_MX28_XNNSW /* XM */ BIT(18) | |
273 | # define LRADC_CTRL0_MX28_XNPSW /* XM */ BIT(17) | |
274 | # define LRADC_CTRL0_MX28_XPPSW /* XP */ BIT(16) | |
275 | ||
276 | # define LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE BIT(20) | |
277 | # define LRADC_CTRL0_MX23_YM BIT(19) | |
278 | # define LRADC_CTRL0_MX23_XM BIT(18) | |
279 | # define LRADC_CTRL0_MX23_YP BIT(17) | |
280 | # define LRADC_CTRL0_MX23_XP BIT(16) | |
8c06f714 | 281 | |
7e4d4a6f JB |
282 | # define LRADC_CTRL0_MX28_PLATE_MASK \ |
283 | (LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE | \ | |
284 | LRADC_CTRL0_MX28_YNNSW | LRADC_CTRL0_MX28_YPNSW | \ | |
285 | LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW | \ | |
286 | LRADC_CTRL0_MX28_XNPSW | LRADC_CTRL0_MX28_XPPSW) | |
bc2c90c9 | 287 | |
8c06f714 JB |
288 | # define LRADC_CTRL0_MX23_PLATE_MASK \ |
289 | (LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE | \ | |
290 | LRADC_CTRL0_MX23_YM | LRADC_CTRL0_MX23_XM | \ | |
291 | LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_XP) | |
292 | ||
bc2c90c9 | 293 | #define LRADC_CTRL1 0x10 |
418880f5 | 294 | #define LRADC_CTRL1_TOUCH_DETECT_IRQ_EN BIT(24) |
bc2c90c9 | 295 | #define LRADC_CTRL1_LRADC_IRQ_EN(n) (1 << ((n) + 16)) |
7e4d4a6f | 296 | #define LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK (0x1fff << 16) |
8c06f714 | 297 | #define LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK (0x01ff << 16) |
06ddd353 | 298 | #define LRADC_CTRL1_LRADC_IRQ_EN_OFFSET 16 |
418880f5 | 299 | #define LRADC_CTRL1_TOUCH_DETECT_IRQ BIT(8) |
06ddd353 | 300 | #define LRADC_CTRL1_LRADC_IRQ(n) (1 << (n)) |
7e4d4a6f | 301 | #define LRADC_CTRL1_MX28_LRADC_IRQ_MASK 0x1fff |
8c06f714 | 302 | #define LRADC_CTRL1_MX23_LRADC_IRQ_MASK 0x01ff |
06ddd353 | 303 | #define LRADC_CTRL1_LRADC_IRQ_OFFSET 0 |
bc2c90c9 MV |
304 | |
305 | #define LRADC_CTRL2 0x20 | |
aba70f2a | 306 | #define LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET 24 |
418880f5 | 307 | #define LRADC_CTRL2_TEMPSENSE_PWD BIT(15) |
bc2c90c9 | 308 | |
06ddd353 | 309 | #define LRADC_STATUS 0x40 |
418880f5 | 310 | #define LRADC_STATUS_TOUCH_DETECT_RAW BIT(0) |
06ddd353 | 311 | |
bc2c90c9 | 312 | #define LRADC_CH(n) (0x50 + (0x10 * (n))) |
418880f5 | 313 | #define LRADC_CH_ACCUMULATE BIT(29) |
bc2c90c9 MV |
314 | #define LRADC_CH_NUM_SAMPLES_MASK (0x1f << 24) |
315 | #define LRADC_CH_NUM_SAMPLES_OFFSET 24 | |
dee05308 JB |
316 | #define LRADC_CH_NUM_SAMPLES(x) \ |
317 | ((x) << LRADC_CH_NUM_SAMPLES_OFFSET) | |
bc2c90c9 MV |
318 | #define LRADC_CH_VALUE_MASK 0x3ffff |
319 | #define LRADC_CH_VALUE_OFFSET 0 | |
320 | ||
321 | #define LRADC_DELAY(n) (0xd0 + (0x10 * (n))) | |
f89c2b39 | 322 | #define LRADC_DELAY_TRIGGER_LRADCS_MASK (0xffUL << 24) |
bc2c90c9 | 323 | #define LRADC_DELAY_TRIGGER_LRADCS_OFFSET 24 |
dee05308 JB |
324 | #define LRADC_DELAY_TRIGGER(x) \ |
325 | (((x) << LRADC_DELAY_TRIGGER_LRADCS_OFFSET) & \ | |
326 | LRADC_DELAY_TRIGGER_LRADCS_MASK) | |
e0c961bd | 327 | #define LRADC_DELAY_KICK BIT(20) |
bc2c90c9 MV |
328 | #define LRADC_DELAY_TRIGGER_DELAYS_MASK (0xf << 16) |
329 | #define LRADC_DELAY_TRIGGER_DELAYS_OFFSET 16 | |
dee05308 JB |
330 | #define LRADC_DELAY_TRIGGER_DELAYS(x) \ |
331 | (((x) << LRADC_DELAY_TRIGGER_DELAYS_OFFSET) & \ | |
332 | LRADC_DELAY_TRIGGER_DELAYS_MASK) | |
bc2c90c9 MV |
333 | #define LRADC_DELAY_LOOP_COUNT_MASK (0x1f << 11) |
334 | #define LRADC_DELAY_LOOP_COUNT_OFFSET 11 | |
dee05308 JB |
335 | #define LRADC_DELAY_LOOP(x) \ |
336 | (((x) << LRADC_DELAY_LOOP_COUNT_OFFSET) & \ | |
337 | LRADC_DELAY_LOOP_COUNT_MASK) | |
bc2c90c9 MV |
338 | #define LRADC_DELAY_DELAY_MASK 0x7ff |
339 | #define LRADC_DELAY_DELAY_OFFSET 0 | |
dee05308 JB |
340 | #define LRADC_DELAY_DELAY(x) \ |
341 | (((x) << LRADC_DELAY_DELAY_OFFSET) & \ | |
342 | LRADC_DELAY_DELAY_MASK) | |
bc2c90c9 MV |
343 | |
344 | #define LRADC_CTRL4 0x140 | |
345 | #define LRADC_CTRL4_LRADCSELECT_MASK(n) (0xf << ((n) * 4)) | |
346 | #define LRADC_CTRL4_LRADCSELECT_OFFSET(n) ((n) * 4) | |
f81197b8 KM |
347 | #define LRADC_CTRL4_LRADCSELECT(n, x) \ |
348 | (((x) << LRADC_CTRL4_LRADCSELECT_OFFSET(n)) & \ | |
349 | LRADC_CTRL4_LRADCSELECT_MASK(n)) | |
bc2c90c9 | 350 | |
1eb70a97 HP |
351 | #define LRADC_RESOLUTION 12 |
352 | #define LRADC_SINGLE_SAMPLE_MASK ((1 << LRADC_RESOLUTION) - 1) | |
353 | ||
f0b83cc8 JB |
354 | static void mxs_lradc_reg_set(struct mxs_lradc *lradc, u32 val, u32 reg) |
355 | { | |
356 | writel(val, lradc->base + reg + STMP_OFFSET_REG_SET); | |
357 | } | |
358 | ||
359 | static void mxs_lradc_reg_clear(struct mxs_lradc *lradc, u32 val, u32 reg) | |
360 | { | |
361 | writel(val, lradc->base + reg + STMP_OFFSET_REG_CLR); | |
362 | } | |
363 | ||
364 | static void mxs_lradc_reg_wrt(struct mxs_lradc *lradc, u32 val, u32 reg) | |
365 | { | |
366 | writel(val, lradc->base + reg); | |
367 | } | |
368 | ||
369 | static u32 mxs_lradc_plate_mask(struct mxs_lradc *lradc) | |
370 | { | |
8c06f714 JB |
371 | if (lradc->soc == IMX23_LRADC) |
372 | return LRADC_CTRL0_MX23_PLATE_MASK; | |
0f8ad68b | 373 | return LRADC_CTRL0_MX28_PLATE_MASK; |
f0b83cc8 JB |
374 | } |
375 | ||
376 | static u32 mxs_lradc_irq_en_mask(struct mxs_lradc *lradc) | |
377 | { | |
8c06f714 JB |
378 | if (lradc->soc == IMX23_LRADC) |
379 | return LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK; | |
0f8ad68b | 380 | return LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK; |
f0b83cc8 JB |
381 | } |
382 | ||
383 | static u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc) | |
384 | { | |
8c06f714 JB |
385 | if (lradc->soc == IMX23_LRADC) |
386 | return LRADC_CTRL1_MX23_LRADC_IRQ_MASK; | |
0f8ad68b | 387 | return LRADC_CTRL1_MX28_LRADC_IRQ_MASK; |
f0b83cc8 JB |
388 | } |
389 | ||
390 | static u32 mxs_lradc_touch_detect_bit(struct mxs_lradc *lradc) | |
391 | { | |
8c06f714 JB |
392 | if (lradc->soc == IMX23_LRADC) |
393 | return LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE; | |
0f8ad68b | 394 | return LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE; |
f0b83cc8 JB |
395 | } |
396 | ||
397 | static u32 mxs_lradc_drive_x_plate(struct mxs_lradc *lradc) | |
398 | { | |
8c06f714 JB |
399 | if (lradc->soc == IMX23_LRADC) |
400 | return LRADC_CTRL0_MX23_XP | LRADC_CTRL0_MX23_XM; | |
0f8ad68b | 401 | return LRADC_CTRL0_MX28_XPPSW | LRADC_CTRL0_MX28_XNNSW; |
f0b83cc8 JB |
402 | } |
403 | ||
404 | static u32 mxs_lradc_drive_y_plate(struct mxs_lradc *lradc) | |
405 | { | |
8c06f714 JB |
406 | if (lradc->soc == IMX23_LRADC) |
407 | return LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_YM; | |
0f8ad68b | 408 | return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_YNNSW; |
f0b83cc8 JB |
409 | } |
410 | ||
411 | static u32 mxs_lradc_drive_pressure(struct mxs_lradc *lradc) | |
412 | { | |
8c06f714 JB |
413 | if (lradc->soc == IMX23_LRADC) |
414 | return LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_XM; | |
0f8ad68b | 415 | return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW; |
f0b83cc8 JB |
416 | } |
417 | ||
dee05308 JB |
418 | static bool mxs_lradc_check_touch_event(struct mxs_lradc *lradc) |
419 | { | |
420 | return !!(readl(lradc->base + LRADC_STATUS) & | |
421 | LRADC_STATUS_TOUCH_DETECT_RAW); | |
422 | } | |
423 | ||
f81197b8 KM |
424 | static void mxs_lradc_map_channel(struct mxs_lradc *lradc, unsigned vch, |
425 | unsigned ch) | |
426 | { | |
427 | mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(vch), | |
e8ef49f0 | 428 | LRADC_CTRL4); |
f81197b8 KM |
429 | mxs_lradc_reg_set(lradc, LRADC_CTRL4_LRADCSELECT(vch, ch), LRADC_CTRL4); |
430 | } | |
431 | ||
dee05308 JB |
432 | static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch) |
433 | { | |
434 | /* | |
435 | * prepare for oversampling conversion | |
436 | * | |
437 | * from the datasheet: | |
438 | * "The ACCUMULATE bit in the appropriate channel register | |
439 | * HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0; | |
440 | * otherwise, the IRQs will not fire." | |
441 | */ | |
442 | mxs_lradc_reg_wrt(lradc, LRADC_CH_ACCUMULATE | | |
e8ef49f0 IC |
443 | LRADC_CH_NUM_SAMPLES(lradc->over_sample_cnt - 1), |
444 | LRADC_CH(ch)); | |
dee05308 | 445 | |
f836c459 KS |
446 | /* |
447 | * from the datasheet: | |
dee05308 JB |
448 | * "Software must clear this register in preparation for a |
449 | * multi-cycle accumulation. | |
450 | */ | |
451 | mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch)); | |
452 | ||
c22d2672 SW |
453 | /* |
454 | * prepare the delay/loop unit according to the oversampling count | |
455 | * | |
456 | * from the datasheet: | |
457 | * "The DELAY fields in HW_LRADC_DELAY0, HW_LRADC_DELAY1, | |
458 | * HW_LRADC_DELAY2, and HW_LRADC_DELAY3 must be non-zero; otherwise, | |
459 | * the LRADC will not trigger the delay group." | |
460 | */ | |
dee05308 | 461 | mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch) | |
e8ef49f0 IC |
462 | LRADC_DELAY_TRIGGER_DELAYS(0) | |
463 | LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) | | |
464 | LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), | |
465 | LRADC_DELAY(3)); | |
dee05308 | 466 | |
f81197b8 | 467 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch), LRADC_CTRL1); |
dee05308 | 468 | |
dee05308 JB |
469 | /* |
470 | * after changing the touchscreen plates setting | |
471 | * the signals need some initial time to settle. Start the | |
472 | * SoC's delay unit and start the conversion later | |
473 | * and automatically. | |
474 | */ | |
e8ef49f0 IC |
475 | mxs_lradc_reg_wrt( |
476 | lradc, | |
0c05a5d6 | 477 | LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */ |
418880f5 | 478 | LRADC_DELAY_TRIGGER_DELAYS(BIT(3)) | /* trigger DELAY unit#3 */ |
dee05308 JB |
479 | LRADC_DELAY_KICK | |
480 | LRADC_DELAY_DELAY(lradc->settling_delay), | |
e8ef49f0 | 481 | LRADC_DELAY(2)); |
dee05308 JB |
482 | } |
483 | ||
484 | /* | |
485 | * Pressure detection is special: | |
486 | * We want to do both required measurements for the pressure detection in | |
487 | * one turn. Use the hardware features to chain both conversions and let the | |
488 | * hardware report one interrupt if both conversions are done | |
489 | */ | |
490 | static void mxs_lradc_setup_ts_pressure(struct mxs_lradc *lradc, unsigned ch1, | |
e8ef49f0 | 491 | unsigned ch2) |
dee05308 JB |
492 | { |
493 | u32 reg; | |
494 | ||
495 | /* | |
496 | * prepare for oversampling conversion | |
497 | * | |
498 | * from the datasheet: | |
499 | * "The ACCUMULATE bit in the appropriate channel register | |
500 | * HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0; | |
501 | * otherwise, the IRQs will not fire." | |
502 | */ | |
503 | reg = LRADC_CH_ACCUMULATE | | |
504 | LRADC_CH_NUM_SAMPLES(lradc->over_sample_cnt - 1); | |
505 | mxs_lradc_reg_wrt(lradc, reg, LRADC_CH(ch1)); | |
506 | mxs_lradc_reg_wrt(lradc, reg, LRADC_CH(ch2)); | |
507 | ||
f836c459 KS |
508 | /* |
509 | * from the datasheet: | |
dee05308 JB |
510 | * "Software must clear this register in preparation for a |
511 | * multi-cycle accumulation. | |
512 | */ | |
513 | mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch1)); | |
514 | mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch2)); | |
515 | ||
516 | /* prepare the delay/loop unit according to the oversampling count */ | |
e8ef49f0 IC |
517 | mxs_lradc_reg_wrt( |
518 | lradc, | |
519 | LRADC_DELAY_TRIGGER(1 << ch1) | | |
520 | LRADC_DELAY_TRIGGER(1 << ch2) | /* start both channels */ | |
521 | LRADC_DELAY_TRIGGER_DELAYS(0) | | |
522 | LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) | | |
523 | LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), | |
524 | LRADC_DELAY(3)); | |
dee05308 | 525 | |
f81197b8 | 526 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch2), LRADC_CTRL1); |
dee05308 | 527 | |
dee05308 JB |
528 | /* |
529 | * after changing the touchscreen plates setting | |
530 | * the signals need some initial time to settle. Start the | |
531 | * SoC's delay unit and start the conversion later | |
532 | * and automatically. | |
533 | */ | |
e8ef49f0 IC |
534 | mxs_lradc_reg_wrt( |
535 | lradc, | |
0c05a5d6 | 536 | LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */ |
418880f5 | 537 | LRADC_DELAY_TRIGGER_DELAYS(BIT(3)) | /* trigger DELAY unit#3 */ |
dee05308 JB |
538 | LRADC_DELAY_KICK | |
539 | LRADC_DELAY_DELAY(lradc->settling_delay), LRADC_DELAY(2)); | |
540 | } | |
541 | ||
542 | static unsigned mxs_lradc_read_raw_channel(struct mxs_lradc *lradc, | |
e8ef49f0 | 543 | unsigned channel) |
dee05308 JB |
544 | { |
545 | u32 reg; | |
546 | unsigned num_samples, val; | |
547 | ||
548 | reg = readl(lradc->base + LRADC_CH(channel)); | |
549 | if (reg & LRADC_CH_ACCUMULATE) | |
550 | num_samples = lradc->over_sample_cnt; | |
551 | else | |
552 | num_samples = 1; | |
553 | ||
554 | val = (reg & LRADC_CH_VALUE_MASK) >> LRADC_CH_VALUE_OFFSET; | |
555 | return val / num_samples; | |
556 | } | |
557 | ||
558 | static unsigned mxs_lradc_read_ts_pressure(struct mxs_lradc *lradc, | |
e8ef49f0 | 559 | unsigned ch1, unsigned ch2) |
dee05308 JB |
560 | { |
561 | u32 reg, mask; | |
562 | unsigned pressure, m1, m2; | |
563 | ||
564 | mask = LRADC_CTRL1_LRADC_IRQ(ch1) | LRADC_CTRL1_LRADC_IRQ(ch2); | |
565 | reg = readl(lradc->base + LRADC_CTRL1) & mask; | |
566 | ||
567 | while (reg != mask) { | |
568 | reg = readl(lradc->base + LRADC_CTRL1) & mask; | |
569 | dev_dbg(lradc->dev, "One channel is still busy: %X\n", reg); | |
570 | } | |
571 | ||
572 | m1 = mxs_lradc_read_raw_channel(lradc, ch1); | |
573 | m2 = mxs_lradc_read_raw_channel(lradc, ch2); | |
574 | ||
575 | if (m2 == 0) { | |
576 | dev_warn(lradc->dev, "Cannot calculate pressure\n"); | |
577 | return 1 << (LRADC_RESOLUTION - 1); | |
578 | } | |
579 | ||
580 | /* simply scale the value from 0 ... max ADC resolution */ | |
581 | pressure = m1; | |
582 | pressure *= (1 << LRADC_RESOLUTION); | |
583 | pressure /= m2; | |
584 | ||
585 | dev_dbg(lradc->dev, "Pressure = %u\n", pressure); | |
586 | return pressure; | |
587 | } | |
588 | ||
589 | #define TS_CH_XP 2 | |
590 | #define TS_CH_YP 3 | |
591 | #define TS_CH_XM 4 | |
592 | #define TS_CH_YM 5 | |
593 | ||
dee05308 JB |
594 | /* |
595 | * YP(open)--+-------------+ | |
596 | * | |--+ | |
597 | * | | | | |
598 | * YM(-)--+-------------+ | | |
599 | * +--------------+ | |
600 | * | | | |
601 | * XP(weak+) XM(open) | |
602 | * | |
603 | * "weak+" means 200k Ohm VDDIO | |
604 | * (-) means GND | |
605 | */ | |
606 | static void mxs_lradc_setup_touch_detection(struct mxs_lradc *lradc) | |
607 | { | |
608 | /* | |
609 | * In order to detect a touch event the 'touch detect enable' bit | |
610 | * enables: | |
611 | * - a weak pullup to the X+ connector | |
612 | * - a strong ground at the Y- connector | |
613 | */ | |
614 | mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); | |
615 | mxs_lradc_reg_set(lradc, mxs_lradc_touch_detect_bit(lradc), | |
e8ef49f0 | 616 | LRADC_CTRL0); |
dee05308 JB |
617 | } |
618 | ||
619 | /* | |
620 | * YP(meas)--+-------------+ | |
621 | * | |--+ | |
622 | * | | | | |
623 | * YM(open)--+-------------+ | | |
624 | * +--------------+ | |
625 | * | | | |
626 | * XP(+) XM(-) | |
627 | * | |
628 | * (+) means here 1.85 V | |
629 | * (-) means here GND | |
630 | */ | |
631 | static void mxs_lradc_prepare_x_pos(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_x_plate(lradc), LRADC_CTRL0); | |
635 | ||
636 | lradc->cur_plate = LRADC_SAMPLE_X; | |
f81197b8 KM |
637 | mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YP); |
638 | mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1); | |
dee05308 JB |
639 | } |
640 | ||
641 | /* | |
642 | * YP(+)--+-------------+ | |
643 | * | |--+ | |
644 | * | | | | |
645 | * YM(-)--+-------------+ | | |
646 | * +--------------+ | |
647 | * | | | |
648 | * XP(open) XM(meas) | |
649 | * | |
650 | * (+) means here 1.85 V | |
651 | * (-) means here GND | |
652 | */ | |
653 | static void mxs_lradc_prepare_y_pos(struct mxs_lradc *lradc) | |
654 | { | |
655 | mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); | |
656 | mxs_lradc_reg_set(lradc, mxs_lradc_drive_y_plate(lradc), LRADC_CTRL0); | |
657 | ||
658 | lradc->cur_plate = LRADC_SAMPLE_Y; | |
f81197b8 KM |
659 | mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_XM); |
660 | mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1); | |
dee05308 JB |
661 | } |
662 | ||
663 | /* | |
664 | * YP(+)--+-------------+ | |
665 | * | |--+ | |
666 | * | | | | |
667 | * YM(meas)--+-------------+ | | |
668 | * +--------------+ | |
669 | * | | | |
670 | * XP(meas) XM(-) | |
671 | * | |
672 | * (+) means here 1.85 V | |
673 | * (-) means here GND | |
674 | */ | |
675 | static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc) | |
676 | { | |
677 | mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); | |
678 | mxs_lradc_reg_set(lradc, mxs_lradc_drive_pressure(lradc), LRADC_CTRL0); | |
679 | ||
680 | lradc->cur_plate = LRADC_SAMPLE_PRESSURE; | |
f81197b8 KM |
681 | mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YM); |
682 | mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL2, TS_CH_XP); | |
683 | mxs_lradc_setup_ts_pressure(lradc, TOUCHSCREEN_VCHANNEL2, | |
e8ef49f0 | 684 | TOUCHSCREEN_VCHANNEL1); |
dee05308 JB |
685 | } |
686 | ||
687 | static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc) | |
688 | { | |
9cf6fcc1 SW |
689 | /* Configure the touchscreen type */ |
690 | if (lradc->soc == IMX28_LRADC) { | |
691 | mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, | |
692 | LRADC_CTRL0); | |
693 | ||
694 | if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) | |
695 | mxs_lradc_reg_set(lradc, | |
696 | LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, | |
697 | LRADC_CTRL0); | |
698 | } | |
699 | ||
dee05308 JB |
700 | mxs_lradc_setup_touch_detection(lradc); |
701 | ||
702 | lradc->cur_plate = LRADC_TOUCH; | |
703 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ | | |
e8ef49f0 | 704 | LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); |
dee05308 JB |
705 | mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); |
706 | } | |
707 | ||
f81197b8 KM |
708 | static void mxs_lradc_start_touch_event(struct mxs_lradc *lradc) |
709 | { | |
e8ef49f0 IC |
710 | mxs_lradc_reg_clear(lradc, |
711 | LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, | |
712 | LRADC_CTRL1); | |
f81197b8 | 713 | mxs_lradc_reg_set(lradc, |
e8ef49f0 IC |
714 | LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1), |
715 | LRADC_CTRL1); | |
f81197b8 KM |
716 | /* |
717 | * start with the Y-pos, because it uses nearly the same plate | |
718 | * settings like the touch detection | |
719 | */ | |
720 | mxs_lradc_prepare_y_pos(lradc); | |
721 | } | |
722 | ||
dee05308 JB |
723 | static void mxs_lradc_report_ts_event(struct mxs_lradc *lradc) |
724 | { | |
725 | input_report_abs(lradc->ts_input, ABS_X, lradc->ts_x_pos); | |
726 | input_report_abs(lradc->ts_input, ABS_Y, lradc->ts_y_pos); | |
727 | input_report_abs(lradc->ts_input, ABS_PRESSURE, lradc->ts_pressure); | |
728 | input_report_key(lradc->ts_input, BTN_TOUCH, 1); | |
729 | input_sync(lradc->ts_input); | |
730 | } | |
731 | ||
732 | static void mxs_lradc_complete_touch_event(struct mxs_lradc *lradc) | |
733 | { | |
734 | mxs_lradc_setup_touch_detection(lradc); | |
735 | lradc->cur_plate = LRADC_SAMPLE_VALID; | |
736 | /* | |
737 | * start a dummy conversion to burn time to settle the signals | |
738 | * note: we are not interested in the conversion's value | |
739 | */ | |
f81197b8 KM |
740 | mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(TOUCHSCREEN_VCHANNEL1)); |
741 | mxs_lradc_reg_clear(lradc, | |
e8ef49f0 IC |
742 | LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) | |
743 | LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2), | |
744 | LRADC_CTRL1); | |
745 | mxs_lradc_reg_wrt( | |
746 | lradc, | |
747 | LRADC_DELAY_TRIGGER(1 << TOUCHSCREEN_VCHANNEL1) | | |
748 | LRADC_DELAY_KICK | LRADC_DELAY_DELAY(10), /* waste 5 ms */ | |
749 | LRADC_DELAY(2)); | |
dee05308 JB |
750 | } |
751 | ||
752 | /* | |
753 | * in order to avoid false measurements, report only samples where | |
754 | * the surface is still touched after the position measurement | |
755 | */ | |
756 | static void mxs_lradc_finish_touch_event(struct mxs_lradc *lradc, bool valid) | |
757 | { | |
758 | /* if it is still touched, report the sample */ | |
759 | if (valid && mxs_lradc_check_touch_event(lradc)) { | |
760 | lradc->ts_valid = true; | |
761 | mxs_lradc_report_ts_event(lradc); | |
762 | } | |
763 | ||
764 | /* if it is even still touched, continue with the next measurement */ | |
765 | if (mxs_lradc_check_touch_event(lradc)) { | |
766 | mxs_lradc_prepare_y_pos(lradc); | |
767 | return; | |
768 | } | |
769 | ||
770 | if (lradc->ts_valid) { | |
771 | /* signal the release */ | |
772 | lradc->ts_valid = false; | |
773 | input_report_key(lradc->ts_input, BTN_TOUCH, 0); | |
774 | input_sync(lradc->ts_input); | |
775 | } | |
776 | ||
777 | /* if it is released, wait for the next touch via IRQ */ | |
760dbe1d | 778 | lradc->cur_plate = LRADC_TOUCH; |
f81197b8 KM |
779 | mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); |
780 | mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); | |
e8ef49f0 IC |
781 | mxs_lradc_reg_clear(lradc, |
782 | LRADC_CTRL1_TOUCH_DETECT_IRQ | | |
783 | LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) | | |
784 | LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1), | |
785 | LRADC_CTRL1); | |
dee05308 JB |
786 | mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); |
787 | } | |
788 | ||
789 | /* touchscreen's state machine */ | |
790 | static void mxs_lradc_handle_touch(struct mxs_lradc *lradc) | |
791 | { | |
dee05308 JB |
792 | switch (lradc->cur_plate) { |
793 | case LRADC_TOUCH: | |
f81197b8 KM |
794 | if (mxs_lradc_check_touch_event(lradc)) |
795 | mxs_lradc_start_touch_event(lradc); | |
dee05308 | 796 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, |
e8ef49f0 | 797 | LRADC_CTRL1); |
dee05308 JB |
798 | return; |
799 | ||
800 | case LRADC_SAMPLE_Y: | |
e8ef49f0 IC |
801 | lradc->ts_y_pos = |
802 | mxs_lradc_read_raw_channel(lradc, | |
803 | TOUCHSCREEN_VCHANNEL1); | |
dee05308 JB |
804 | mxs_lradc_prepare_x_pos(lradc); |
805 | return; | |
806 | ||
807 | case LRADC_SAMPLE_X: | |
e8ef49f0 IC |
808 | lradc->ts_x_pos = |
809 | mxs_lradc_read_raw_channel(lradc, | |
810 | TOUCHSCREEN_VCHANNEL1); | |
dee05308 JB |
811 | mxs_lradc_prepare_pressure(lradc); |
812 | return; | |
813 | ||
814 | case LRADC_SAMPLE_PRESSURE: | |
e8ef49f0 IC |
815 | lradc->ts_pressure = |
816 | mxs_lradc_read_ts_pressure(lradc, | |
817 | TOUCHSCREEN_VCHANNEL2, | |
818 | TOUCHSCREEN_VCHANNEL1); | |
dee05308 JB |
819 | mxs_lradc_complete_touch_event(lradc); |
820 | return; | |
821 | ||
822 | case LRADC_SAMPLE_VALID: | |
dee05308 JB |
823 | mxs_lradc_finish_touch_event(lradc, 1); |
824 | break; | |
825 | } | |
826 | } | |
827 | ||
bc2c90c9 MV |
828 | /* |
829 | * Raw I/O operations | |
830 | */ | |
c8231a9a | 831 | static int mxs_lradc_read_single(struct iio_dev *iio_dev, int chan, int *val) |
bc2c90c9 MV |
832 | { |
833 | struct mxs_lradc *lradc = iio_priv(iio_dev); | |
834 | int ret; | |
835 | ||
bc2c90c9 | 836 | /* |
66926d11 | 837 | * See if there is no buffered operation in progress. If there is, simply |
bc2c90c9 MV |
838 | * bail out. This can be improved to support both buffered and raw IO at |
839 | * the same time, yet the code becomes horribly complicated. Therefore I | |
840 | * applied KISS principle here. | |
841 | */ | |
842 | ret = mutex_trylock(&lradc->lock); | |
843 | if (!ret) | |
844 | return -EBUSY; | |
845 | ||
16735d02 | 846 | reinit_completion(&lradc->completion); |
bc2c90c9 MV |
847 | |
848 | /* | |
849 | * No buffered operation in progress, map the channel and trigger it. | |
850 | * Virtual channel 0 is always used here as the others are always not | |
851 | * used if doing raw sampling. | |
852 | */ | |
8c06f714 | 853 | if (lradc->soc == IMX28_LRADC) |
86bf7f3e | 854 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), |
e8ef49f0 | 855 | LRADC_CTRL1); |
6abe0300 | 856 | mxs_lradc_reg_clear(lradc, 0x1, LRADC_CTRL0); |
bc2c90c9 | 857 | |
19bc4981 RH |
858 | /* Enable / disable the divider per requirement */ |
859 | if (test_bit(chan, &lradc->is_divided)) | |
e8ef49f0 IC |
860 | mxs_lradc_reg_set(lradc, |
861 | 1 << LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET, | |
862 | LRADC_CTRL2); | |
19bc4981 RH |
863 | else |
864 | mxs_lradc_reg_clear(lradc, | |
e8ef49f0 IC |
865 | 1 << LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET, |
866 | LRADC_CTRL2); | |
19bc4981 | 867 | |
06ddd353 | 868 | /* Clean the slot's previous content, then set new one. */ |
168934c9 | 869 | mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(0), |
e8ef49f0 | 870 | LRADC_CTRL4); |
c8231a9a | 871 | mxs_lradc_reg_set(lradc, chan, LRADC_CTRL4); |
06ddd353 | 872 | |
f0b83cc8 | 873 | mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(0)); |
bc2c90c9 MV |
874 | |
875 | /* Enable the IRQ and start sampling the channel. */ | |
f0b83cc8 | 876 | mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), LRADC_CTRL1); |
418880f5 | 877 | mxs_lradc_reg_set(lradc, BIT(0), LRADC_CTRL0); |
bc2c90c9 MV |
878 | |
879 | /* Wait for completion on the channel, 1 second max. */ | |
880 | ret = wait_for_completion_killable_timeout(&lradc->completion, HZ); | |
881 | if (!ret) | |
882 | ret = -ETIMEDOUT; | |
883 | if (ret < 0) | |
884 | goto err; | |
885 | ||
886 | /* Read the data. */ | |
887 | *val = readl(lradc->base + LRADC_CH(0)) & LRADC_CH_VALUE_MASK; | |
888 | ret = IIO_VAL_INT; | |
889 | ||
890 | err: | |
f0b83cc8 | 891 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), LRADC_CTRL1); |
bc2c90c9 MV |
892 | |
893 | mutex_unlock(&lradc->lock); | |
894 | ||
895 | return ret; | |
896 | } | |
897 | ||
c8231a9a AB |
898 | static int mxs_lradc_read_temp(struct iio_dev *iio_dev, int *val) |
899 | { | |
900 | int ret, min, max; | |
901 | ||
902 | ret = mxs_lradc_read_single(iio_dev, 8, &min); | |
903 | if (ret != IIO_VAL_INT) | |
904 | return ret; | |
905 | ||
906 | ret = mxs_lradc_read_single(iio_dev, 9, &max); | |
907 | if (ret != IIO_VAL_INT) | |
908 | return ret; | |
909 | ||
910 | *val = max - min; | |
911 | ||
912 | return IIO_VAL_INT; | |
913 | } | |
914 | ||
915 | static int mxs_lradc_read_raw(struct iio_dev *iio_dev, | |
e8ef49f0 IC |
916 | const struct iio_chan_spec *chan, |
917 | int *val, int *val2, long m) | |
c8231a9a | 918 | { |
f6db68a4 HP |
919 | struct mxs_lradc *lradc = iio_priv(iio_dev); |
920 | ||
c8231a9a AB |
921 | switch (m) { |
922 | case IIO_CHAN_INFO_RAW: | |
923 | if (chan->type == IIO_TEMP) | |
924 | return mxs_lradc_read_temp(iio_dev, val); | |
925 | ||
926 | return mxs_lradc_read_single(iio_dev, chan->channel, val); | |
927 | ||
928 | case IIO_CHAN_INFO_SCALE: | |
929 | if (chan->type == IIO_TEMP) { | |
f836c459 KS |
930 | /* |
931 | * From the datasheet, we have to multiply by 1.012 and | |
c8231a9a AB |
932 | * divide by 4 |
933 | */ | |
934 | *val = 0; | |
935 | *val2 = 253000; | |
936 | return IIO_VAL_INT_PLUS_MICRO; | |
937 | } | |
938 | ||
f6db68a4 | 939 | *val = lradc->vref_mv[chan->channel]; |
aba70f2a | 940 | *val2 = chan->scan_type.realbits - |
38125b2c | 941 | test_bit(chan->channel, &lradc->is_divided); |
f6db68a4 | 942 | return IIO_VAL_FRACTIONAL_LOG2; |
c8231a9a AB |
943 | |
944 | case IIO_CHAN_INFO_OFFSET: | |
945 | if (chan->type == IIO_TEMP) { | |
f836c459 KS |
946 | /* |
947 | * The calculated value from the ADC is in Kelvin, we | |
b94e2280 AB |
948 | * want Celsius for hwmon so the offset is -273.15 |
949 | * The offset is applied before scaling so it is | |
950 | * actually -213.15 * 4 / 1.012 = -1079.644268 | |
c8231a9a | 951 | */ |
b94e2280 AB |
952 | *val = -1079; |
953 | *val2 = 644268; | |
c8231a9a AB |
954 | |
955 | return IIO_VAL_INT_PLUS_MICRO; | |
956 | } | |
957 | ||
958 | return -EINVAL; | |
959 | ||
960 | default: | |
961 | break; | |
962 | } | |
963 | ||
964 | return -EINVAL; | |
965 | } | |
966 | ||
aba70f2a HP |
967 | static int mxs_lradc_write_raw(struct iio_dev *iio_dev, |
968 | const struct iio_chan_spec *chan, | |
969 | int val, int val2, long m) | |
970 | { | |
971 | struct mxs_lradc *lradc = iio_priv(iio_dev); | |
972 | struct mxs_lradc_scale *scale_avail = | |
973 | lradc->scale_avail[chan->channel]; | |
974 | int ret; | |
975 | ||
976 | ret = mutex_trylock(&lradc->lock); | |
977 | if (!ret) | |
978 | return -EBUSY; | |
979 | ||
980 | switch (m) { | |
981 | case IIO_CHAN_INFO_SCALE: | |
982 | ret = -EINVAL; | |
983 | if (val == scale_avail[MXS_LRADC_DIV_DISABLED].integer && | |
984 | val2 == scale_avail[MXS_LRADC_DIV_DISABLED].nano) { | |
985 | /* divider by two disabled */ | |
38125b2c | 986 | clear_bit(chan->channel, &lradc->is_divided); |
aba70f2a HP |
987 | ret = 0; |
988 | } else if (val == scale_avail[MXS_LRADC_DIV_ENABLED].integer && | |
989 | val2 == scale_avail[MXS_LRADC_DIV_ENABLED].nano) { | |
990 | /* divider by two enabled */ | |
38125b2c | 991 | set_bit(chan->channel, &lradc->is_divided); |
aba70f2a HP |
992 | ret = 0; |
993 | } | |
994 | ||
995 | break; | |
996 | default: | |
997 | ret = -EINVAL; | |
998 | break; | |
999 | } | |
1000 | ||
1001 | mutex_unlock(&lradc->lock); | |
1002 | ||
1003 | return ret; | |
1004 | } | |
1005 | ||
1006 | static int mxs_lradc_write_raw_get_fmt(struct iio_dev *iio_dev, | |
1007 | const struct iio_chan_spec *chan, | |
1008 | long m) | |
1009 | { | |
1010 | return IIO_VAL_INT_PLUS_NANO; | |
1011 | } | |
1012 | ||
d5acf594 | 1013 | static ssize_t mxs_lradc_show_scale_available_ch(struct device *dev, |
e8ef49f0 IC |
1014 | struct device_attribute *attr, |
1015 | char *buf, | |
1016 | int ch) | |
d5acf594 HP |
1017 | { |
1018 | struct iio_dev *iio = dev_to_iio_dev(dev); | |
1019 | struct mxs_lradc *lradc = iio_priv(iio); | |
1020 | int i, len = 0; | |
1021 | ||
1022 | for (i = 0; i < ARRAY_SIZE(lradc->scale_avail[ch]); i++) | |
e257a16e | 1023 | len += sprintf(buf + len, "%u.%09u ", |
d5acf594 HP |
1024 | lradc->scale_avail[ch][i].integer, |
1025 | lradc->scale_avail[ch][i].nano); | |
1026 | ||
1027 | len += sprintf(buf + len, "\n"); | |
1028 | ||
1029 | return len; | |
1030 | } | |
1031 | ||
1032 | static ssize_t mxs_lradc_show_scale_available(struct device *dev, | |
e8ef49f0 IC |
1033 | struct device_attribute *attr, |
1034 | char *buf) | |
d5acf594 HP |
1035 | { |
1036 | struct iio_dev_attr *iio_attr = to_iio_dev_attr(attr); | |
1037 | ||
1038 | return mxs_lradc_show_scale_available_ch(dev, attr, buf, | |
1039 | iio_attr->address); | |
1040 | } | |
1041 | ||
1042 | #define SHOW_SCALE_AVAILABLE_ATTR(ch) \ | |
1043 | static IIO_DEVICE_ATTR(in_voltage##ch##_scale_available, S_IRUGO, \ | |
1044 | mxs_lradc_show_scale_available, NULL, ch) | |
1045 | ||
1046 | SHOW_SCALE_AVAILABLE_ATTR(0); | |
1047 | SHOW_SCALE_AVAILABLE_ATTR(1); | |
1048 | SHOW_SCALE_AVAILABLE_ATTR(2); | |
1049 | SHOW_SCALE_AVAILABLE_ATTR(3); | |
1050 | SHOW_SCALE_AVAILABLE_ATTR(4); | |
1051 | SHOW_SCALE_AVAILABLE_ATTR(5); | |
1052 | SHOW_SCALE_AVAILABLE_ATTR(6); | |
1053 | SHOW_SCALE_AVAILABLE_ATTR(7); | |
d5acf594 HP |
1054 | SHOW_SCALE_AVAILABLE_ATTR(10); |
1055 | SHOW_SCALE_AVAILABLE_ATTR(11); | |
1056 | SHOW_SCALE_AVAILABLE_ATTR(12); | |
1057 | SHOW_SCALE_AVAILABLE_ATTR(13); | |
1058 | SHOW_SCALE_AVAILABLE_ATTR(14); | |
1059 | SHOW_SCALE_AVAILABLE_ATTR(15); | |
1060 | ||
1061 | static struct attribute *mxs_lradc_attributes[] = { | |
1062 | &iio_dev_attr_in_voltage0_scale_available.dev_attr.attr, | |
1063 | &iio_dev_attr_in_voltage1_scale_available.dev_attr.attr, | |
1064 | &iio_dev_attr_in_voltage2_scale_available.dev_attr.attr, | |
1065 | &iio_dev_attr_in_voltage3_scale_available.dev_attr.attr, | |
1066 | &iio_dev_attr_in_voltage4_scale_available.dev_attr.attr, | |
1067 | &iio_dev_attr_in_voltage5_scale_available.dev_attr.attr, | |
1068 | &iio_dev_attr_in_voltage6_scale_available.dev_attr.attr, | |
1069 | &iio_dev_attr_in_voltage7_scale_available.dev_attr.attr, | |
d5acf594 HP |
1070 | &iio_dev_attr_in_voltage10_scale_available.dev_attr.attr, |
1071 | &iio_dev_attr_in_voltage11_scale_available.dev_attr.attr, | |
1072 | &iio_dev_attr_in_voltage12_scale_available.dev_attr.attr, | |
1073 | &iio_dev_attr_in_voltage13_scale_available.dev_attr.attr, | |
1074 | &iio_dev_attr_in_voltage14_scale_available.dev_attr.attr, | |
1075 | &iio_dev_attr_in_voltage15_scale_available.dev_attr.attr, | |
1076 | NULL | |
1077 | }; | |
1078 | ||
1079 | static const struct attribute_group mxs_lradc_attribute_group = { | |
1080 | .attrs = mxs_lradc_attributes, | |
1081 | }; | |
1082 | ||
bc2c90c9 MV |
1083 | static const struct iio_info mxs_lradc_iio_info = { |
1084 | .driver_module = THIS_MODULE, | |
1085 | .read_raw = mxs_lradc_read_raw, | |
aba70f2a HP |
1086 | .write_raw = mxs_lradc_write_raw, |
1087 | .write_raw_get_fmt = mxs_lradc_write_raw_get_fmt, | |
d5acf594 | 1088 | .attrs = &mxs_lradc_attribute_group, |
bc2c90c9 MV |
1089 | }; |
1090 | ||
06ddd353 MV |
1091 | static int mxs_lradc_ts_open(struct input_dev *dev) |
1092 | { | |
1093 | struct mxs_lradc *lradc = input_get_drvdata(dev); | |
1094 | ||
06ddd353 | 1095 | /* Enable the touch-detect circuitry. */ |
dee05308 | 1096 | mxs_lradc_enable_touch_detection(lradc); |
06ddd353 MV |
1097 | |
1098 | return 0; | |
1099 | } | |
1100 | ||
dee05308 | 1101 | static void mxs_lradc_disable_ts(struct mxs_lradc *lradc) |
06ddd353 | 1102 | { |
dee05308 JB |
1103 | /* stop all interrupts from firing */ |
1104 | mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN | | |
f81197b8 KM |
1105 | LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) | |
1106 | LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL2), LRADC_CTRL1); | |
06ddd353 | 1107 | |
dee05308 JB |
1108 | /* Power-down touchscreen touch-detect circuitry. */ |
1109 | mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); | |
1110 | } | |
06ddd353 | 1111 | |
dee05308 JB |
1112 | static void mxs_lradc_ts_close(struct input_dev *dev) |
1113 | { | |
1114 | struct mxs_lradc *lradc = input_get_drvdata(dev); | |
06ddd353 | 1115 | |
dee05308 | 1116 | mxs_lradc_disable_ts(lradc); |
06ddd353 MV |
1117 | } |
1118 | ||
1119 | static int mxs_lradc_ts_register(struct mxs_lradc *lradc) | |
1120 | { | |
1121 | struct input_dev *input; | |
1122 | struct device *dev = lradc->dev; | |
1123 | int ret; | |
1124 | ||
1125 | if (!lradc->use_touchscreen) | |
1126 | return 0; | |
1127 | ||
1128 | input = input_allocate_device(); | |
f99a92c3 | 1129 | if (!input) |
06ddd353 | 1130 | return -ENOMEM; |
06ddd353 MV |
1131 | |
1132 | input->name = DRIVER_NAME; | |
1133 | input->id.bustype = BUS_HOST; | |
1134 | input->dev.parent = dev; | |
1135 | input->open = mxs_lradc_ts_open; | |
1136 | input->close = mxs_lradc_ts_close; | |
1137 | ||
1138 | __set_bit(EV_ABS, input->evbit); | |
1139 | __set_bit(EV_KEY, input->evbit); | |
1140 | __set_bit(BTN_TOUCH, input->keybit); | |
922b3aa6 | 1141 | __set_bit(INPUT_PROP_DIRECT, input->propbit); |
1eb70a97 HP |
1142 | input_set_abs_params(input, ABS_X, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0); |
1143 | input_set_abs_params(input, ABS_Y, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0); | |
1144 | input_set_abs_params(input, ABS_PRESSURE, 0, LRADC_SINGLE_SAMPLE_MASK, | |
1145 | 0, 0); | |
06ddd353 MV |
1146 | |
1147 | lradc->ts_input = input; | |
1148 | input_set_drvdata(input, lradc); | |
1149 | ret = input_register_device(input); | |
1150 | if (ret) | |
1151 | input_free_device(lradc->ts_input); | |
1152 | ||
1153 | return ret; | |
1154 | } | |
1155 | ||
1156 | static void mxs_lradc_ts_unregister(struct mxs_lradc *lradc) | |
1157 | { | |
1158 | if (!lradc->use_touchscreen) | |
1159 | return; | |
1160 | ||
dee05308 | 1161 | mxs_lradc_disable_ts(lradc); |
06ddd353 MV |
1162 | input_unregister_device(lradc->ts_input); |
1163 | } | |
1164 | ||
bc2c90c9 MV |
1165 | /* |
1166 | * IRQ Handling | |
1167 | */ | |
1168 | static irqreturn_t mxs_lradc_handle_irq(int irq, void *data) | |
1169 | { | |
1170 | struct iio_dev *iio = data; | |
1171 | struct mxs_lradc *lradc = iio_priv(iio); | |
1172 | unsigned long reg = readl(lradc->base + LRADC_CTRL1); | |
0e4f0075 IC |
1173 | u32 clr_irq = mxs_lradc_irq_mask(lradc); |
1174 | const u32 ts_irq_mask = | |
dee05308 | 1175 | LRADC_CTRL1_TOUCH_DETECT_IRQ | |
f81197b8 KM |
1176 | LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) | |
1177 | LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2); | |
bc2c90c9 | 1178 | |
f0b83cc8 | 1179 | if (!(reg & mxs_lradc_irq_mask(lradc))) |
bc2c90c9 MV |
1180 | return IRQ_NONE; |
1181 | ||
f81197b8 | 1182 | if (lradc->use_touchscreen && (reg & ts_irq_mask)) { |
dee05308 | 1183 | mxs_lradc_handle_touch(lradc); |
bc2c90c9 | 1184 | |
f81197b8 KM |
1185 | /* Make sure we don't clear the next conversion's interrupt. */ |
1186 | clr_irq &= ~(LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) | | |
1187 | LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2)); | |
1188 | } | |
1189 | ||
89bb35e2 KM |
1190 | if (iio_buffer_enabled(iio)) { |
1191 | if (reg & lradc->buffer_vchans) | |
1192 | iio_trigger_poll(iio->trig); | |
1193 | } else if (reg & LRADC_CTRL1_LRADC_IRQ(0)) { | |
bc2c90c9 | 1194 | complete(&lradc->completion); |
89bb35e2 | 1195 | } |
bc2c90c9 | 1196 | |
f81197b8 | 1197 | mxs_lradc_reg_clear(lradc, reg & clr_irq, LRADC_CTRL1); |
bc2c90c9 MV |
1198 | |
1199 | return IRQ_HANDLED; | |
1200 | } | |
1201 | ||
1202 | /* | |
1203 | * Trigger handling | |
1204 | */ | |
1205 | static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p) | |
1206 | { | |
1207 | struct iio_poll_func *pf = p; | |
1208 | struct iio_dev *iio = pf->indio_dev; | |
1209 | struct mxs_lradc *lradc = iio_priv(iio); | |
0e4f0075 | 1210 | const u32 chan_value = LRADC_CH_ACCUMULATE | |
bc2c90c9 | 1211 | ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); |
7b7a4efe | 1212 | unsigned int i, j = 0; |
bc2c90c9 | 1213 | |
f4914e5e | 1214 | for_each_set_bit(i, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) { |
bc2c90c9 | 1215 | lradc->buffer[j] = readl(lradc->base + LRADC_CH(j)); |
f0b83cc8 | 1216 | mxs_lradc_reg_wrt(lradc, chan_value, LRADC_CH(j)); |
bc2c90c9 MV |
1217 | lradc->buffer[j] &= LRADC_CH_VALUE_MASK; |
1218 | lradc->buffer[j] /= LRADC_DELAY_TIMER_LOOP; | |
1219 | j++; | |
1220 | } | |
1221 | ||
4fa10de6 | 1222 | iio_push_to_buffers_with_timestamp(iio, lradc->buffer, pf->timestamp); |
bc2c90c9 MV |
1223 | |
1224 | iio_trigger_notify_done(iio->trig); | |
1225 | ||
1226 | return IRQ_HANDLED; | |
1227 | } | |
1228 | ||
1229 | static int mxs_lradc_configure_trigger(struct iio_trigger *trig, bool state) | |
1230 | { | |
1e9663c6 | 1231 | struct iio_dev *iio = iio_trigger_get_drvdata(trig); |
bc2c90c9 | 1232 | struct mxs_lradc *lradc = iio_priv(iio); |
0e4f0075 | 1233 | const u32 st = state ? STMP_OFFSET_REG_SET : STMP_OFFSET_REG_CLR; |
bc2c90c9 | 1234 | |
f0b83cc8 | 1235 | mxs_lradc_reg_wrt(lradc, LRADC_DELAY_KICK, LRADC_DELAY(0) + st); |
bc2c90c9 MV |
1236 | |
1237 | return 0; | |
1238 | } | |
1239 | ||
1240 | static const struct iio_trigger_ops mxs_lradc_trigger_ops = { | |
1241 | .owner = THIS_MODULE, | |
1242 | .set_trigger_state = &mxs_lradc_configure_trigger, | |
1243 | }; | |
1244 | ||
1245 | static int mxs_lradc_trigger_init(struct iio_dev *iio) | |
1246 | { | |
1247 | int ret; | |
1248 | struct iio_trigger *trig; | |
e1b1fa66 | 1249 | struct mxs_lradc *lradc = iio_priv(iio); |
bc2c90c9 MV |
1250 | |
1251 | trig = iio_trigger_alloc("%s-dev%i", iio->name, iio->id); | |
603f102f | 1252 | if (!trig) |
bc2c90c9 MV |
1253 | return -ENOMEM; |
1254 | ||
e1b1fa66 | 1255 | trig->dev.parent = lradc->dev; |
1e9663c6 | 1256 | iio_trigger_set_drvdata(trig, iio); |
bc2c90c9 MV |
1257 | trig->ops = &mxs_lradc_trigger_ops; |
1258 | ||
1259 | ret = iio_trigger_register(trig); | |
1260 | if (ret) { | |
1261 | iio_trigger_free(trig); | |
1262 | return ret; | |
1263 | } | |
1264 | ||
e1b1fa66 | 1265 | lradc->trig = trig; |
bc2c90c9 MV |
1266 | |
1267 | return 0; | |
1268 | } | |
1269 | ||
1270 | static void mxs_lradc_trigger_remove(struct iio_dev *iio) | |
1271 | { | |
e1b1fa66 MV |
1272 | struct mxs_lradc *lradc = iio_priv(iio); |
1273 | ||
1274 | iio_trigger_unregister(lradc->trig); | |
1275 | iio_trigger_free(lradc->trig); | |
bc2c90c9 MV |
1276 | } |
1277 | ||
1278 | static int mxs_lradc_buffer_preenable(struct iio_dev *iio) | |
1279 | { | |
1280 | struct mxs_lradc *lradc = iio_priv(iio); | |
06ddd353 MV |
1281 | int ret = 0, chan, ofs = 0; |
1282 | unsigned long enable = 0; | |
0e4f0075 IC |
1283 | u32 ctrl4_set = 0; |
1284 | u32 ctrl4_clr = 0; | |
1285 | u32 ctrl1_irq = 0; | |
1286 | const u32 chan_value = LRADC_CH_ACCUMULATE | | |
bc2c90c9 | 1287 | ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); |
168934c9 AO |
1288 | const int len = bitmap_weight(iio->active_scan_mask, |
1289 | LRADC_MAX_TOTAL_CHANS); | |
bc2c90c9 MV |
1290 | |
1291 | if (!len) | |
1292 | return -EINVAL; | |
1293 | ||
1294 | /* | |
1295 | * Lock the driver so raw access can not be done during buffered | |
1296 | * operation. This simplifies the code a lot. | |
1297 | */ | |
1298 | ret = mutex_trylock(&lradc->lock); | |
1299 | if (!ret) | |
1300 | return -EBUSY; | |
1301 | ||
5b12d0ac | 1302 | lradc->buffer = kmalloc_array(len, sizeof(*lradc->buffer), GFP_KERNEL); |
bc2c90c9 MV |
1303 | if (!lradc->buffer) { |
1304 | ret = -ENOMEM; | |
1305 | goto err_mem; | |
1306 | } | |
1307 | ||
8c06f714 | 1308 | if (lradc->soc == IMX28_LRADC) |
e8ef49f0 IC |
1309 | mxs_lradc_reg_clear( |
1310 | lradc, | |
86bf7f3e KM |
1311 | lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET, |
1312 | LRADC_CTRL1); | |
6abe0300 | 1313 | mxs_lradc_reg_clear(lradc, lradc->buffer_vchans, LRADC_CTRL0); |
bc2c90c9 | 1314 | |
c80712c7 | 1315 | for_each_set_bit(chan, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) { |
06ddd353 MV |
1316 | ctrl4_set |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs); |
1317 | ctrl4_clr |= LRADC_CTRL4_LRADCSELECT_MASK(ofs); | |
bc2c90c9 | 1318 | ctrl1_irq |= LRADC_CTRL1_LRADC_IRQ_EN(ofs); |
f0b83cc8 | 1319 | mxs_lradc_reg_wrt(lradc, chan_value, LRADC_CH(ofs)); |
06ddd353 | 1320 | bitmap_set(&enable, ofs, 1); |
bc2c90c9 | 1321 | ofs++; |
73327b4c | 1322 | } |
bc2c90c9 | 1323 | |
f0b83cc8 | 1324 | mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK | |
e8ef49f0 | 1325 | LRADC_DELAY_KICK, LRADC_DELAY(0)); |
f0b83cc8 JB |
1326 | mxs_lradc_reg_clear(lradc, ctrl4_clr, LRADC_CTRL4); |
1327 | mxs_lradc_reg_set(lradc, ctrl4_set, LRADC_CTRL4); | |
1328 | mxs_lradc_reg_set(lradc, ctrl1_irq, LRADC_CTRL1); | |
1329 | mxs_lradc_reg_set(lradc, enable << LRADC_DELAY_TRIGGER_LRADCS_OFFSET, | |
e8ef49f0 | 1330 | LRADC_DELAY(0)); |
bc2c90c9 MV |
1331 | |
1332 | return 0; | |
1333 | ||
bc2c90c9 MV |
1334 | err_mem: |
1335 | mutex_unlock(&lradc->lock); | |
1336 | return ret; | |
1337 | } | |
1338 | ||
1339 | static int mxs_lradc_buffer_postdisable(struct iio_dev *iio) | |
1340 | { | |
1341 | struct mxs_lradc *lradc = iio_priv(iio); | |
1342 | ||
f0b83cc8 | 1343 | mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK | |
e8ef49f0 | 1344 | LRADC_DELAY_KICK, LRADC_DELAY(0)); |
bc2c90c9 | 1345 | |
6abe0300 | 1346 | mxs_lradc_reg_clear(lradc, lradc->buffer_vchans, LRADC_CTRL0); |
8c06f714 | 1347 | if (lradc->soc == IMX28_LRADC) |
e8ef49f0 IC |
1348 | mxs_lradc_reg_clear( |
1349 | lradc, | |
86bf7f3e KM |
1350 | lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET, |
1351 | LRADC_CTRL1); | |
bc2c90c9 MV |
1352 | |
1353 | kfree(lradc->buffer); | |
1354 | mutex_unlock(&lradc->lock); | |
1355 | ||
1356 | return 0; | |
1357 | } | |
1358 | ||
1359 | static bool mxs_lradc_validate_scan_mask(struct iio_dev *iio, | |
e8ef49f0 | 1360 | const unsigned long *mask) |
bc2c90c9 | 1361 | { |
06ddd353 | 1362 | struct mxs_lradc *lradc = iio_priv(iio); |
f4914e5e | 1363 | const int map_chans = bitmap_weight(mask, LRADC_MAX_TOTAL_CHANS); |
06ddd353 MV |
1364 | int rsvd_chans = 0; |
1365 | unsigned long rsvd_mask = 0; | |
1366 | ||
1367 | if (lradc->use_touchbutton) | |
1368 | rsvd_mask |= CHAN_MASK_TOUCHBUTTON; | |
1369 | if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_4WIRE) | |
1370 | rsvd_mask |= CHAN_MASK_TOUCHSCREEN_4WIRE; | |
1371 | if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) | |
1372 | rsvd_mask |= CHAN_MASK_TOUCHSCREEN_5WIRE; | |
1373 | ||
1374 | if (lradc->use_touchbutton) | |
1375 | rsvd_chans++; | |
1376 | if (lradc->use_touchscreen) | |
f81197b8 | 1377 | rsvd_chans += 2; |
06ddd353 MV |
1378 | |
1379 | /* Test for attempts to map channels with special mode of operation. */ | |
f4914e5e | 1380 | if (bitmap_intersects(mask, &rsvd_mask, LRADC_MAX_TOTAL_CHANS)) |
06ddd353 MV |
1381 | return false; |
1382 | ||
1383 | /* Test for attempts to map more channels then available slots. */ | |
1384 | if (map_chans + rsvd_chans > LRADC_MAX_MAPPED_CHANS) | |
1385 | return false; | |
1386 | ||
1387 | return true; | |
bc2c90c9 MV |
1388 | } |
1389 | ||
1390 | static const struct iio_buffer_setup_ops mxs_lradc_buffer_ops = { | |
1391 | .preenable = &mxs_lradc_buffer_preenable, | |
1392 | .postenable = &iio_triggered_buffer_postenable, | |
1393 | .predisable = &iio_triggered_buffer_predisable, | |
1394 | .postdisable = &mxs_lradc_buffer_postdisable, | |
1395 | .validate_scan_mask = &mxs_lradc_validate_scan_mask, | |
1396 | }; | |
1397 | ||
1398 | /* | |
1399 | * Driver initialization | |
1400 | */ | |
1401 | ||
829aed1a | 1402 | #define MXS_ADC_CHAN(idx, chan_type, name) { \ |
bc2c90c9 MV |
1403 | .type = (chan_type), \ |
1404 | .indexed = 1, \ | |
1405 | .scan_index = (idx), \ | |
f6db68a4 HP |
1406 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
1407 | BIT(IIO_CHAN_INFO_SCALE), \ | |
bc2c90c9 | 1408 | .channel = (idx), \ |
d5acf594 | 1409 | .address = (idx), \ |
bc2c90c9 MV |
1410 | .scan_type = { \ |
1411 | .sign = 'u', \ | |
1eb70a97 | 1412 | .realbits = LRADC_RESOLUTION, \ |
bc2c90c9 MV |
1413 | .storagebits = 32, \ |
1414 | }, \ | |
829aed1a | 1415 | .datasheet_name = (name), \ |
bc2c90c9 MV |
1416 | } |
1417 | ||
829aed1a SW |
1418 | static const struct iio_chan_spec mx23_lradc_chan_spec[] = { |
1419 | MXS_ADC_CHAN(0, IIO_VOLTAGE, "LRADC0"), | |
1420 | MXS_ADC_CHAN(1, IIO_VOLTAGE, "LRADC1"), | |
1421 | MXS_ADC_CHAN(2, IIO_VOLTAGE, "LRADC2"), | |
1422 | MXS_ADC_CHAN(3, IIO_VOLTAGE, "LRADC3"), | |
1423 | MXS_ADC_CHAN(4, IIO_VOLTAGE, "LRADC4"), | |
1424 | MXS_ADC_CHAN(5, IIO_VOLTAGE, "LRADC5"), | |
1425 | MXS_ADC_CHAN(6, IIO_VOLTAGE, "VDDIO"), | |
1426 | MXS_ADC_CHAN(7, IIO_VOLTAGE, "VBATT"), | |
c8231a9a AB |
1427 | /* Combined Temperature sensors */ |
1428 | { | |
1429 | .type = IIO_TEMP, | |
1430 | .indexed = 1, | |
1431 | .scan_index = 8, | |
1432 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | |
1433 | BIT(IIO_CHAN_INFO_OFFSET) | | |
1434 | BIT(IIO_CHAN_INFO_SCALE), | |
1435 | .channel = 8, | |
1436 | .scan_type = {.sign = 'u', .realbits = 18, .storagebits = 32,}, | |
829aed1a | 1437 | .datasheet_name = "TEMP_DIE", |
c8231a9a | 1438 | }, |
03305e53 SW |
1439 | /* Hidden channel to keep indexes */ |
1440 | { | |
1441 | .type = IIO_TEMP, | |
1442 | .indexed = 1, | |
1443 | .scan_index = -1, | |
1444 | .channel = 9, | |
1445 | }, | |
829aed1a SW |
1446 | MXS_ADC_CHAN(10, IIO_VOLTAGE, NULL), |
1447 | MXS_ADC_CHAN(11, IIO_VOLTAGE, NULL), | |
1448 | MXS_ADC_CHAN(12, IIO_VOLTAGE, "USB_DP"), | |
1449 | MXS_ADC_CHAN(13, IIO_VOLTAGE, "USB_DN"), | |
1450 | MXS_ADC_CHAN(14, IIO_VOLTAGE, "VBG"), | |
1451 | MXS_ADC_CHAN(15, IIO_VOLTAGE, "VDD5V"), | |
1452 | }; | |
1453 | ||
1454 | static const struct iio_chan_spec mx28_lradc_chan_spec[] = { | |
1455 | MXS_ADC_CHAN(0, IIO_VOLTAGE, "LRADC0"), | |
1456 | MXS_ADC_CHAN(1, IIO_VOLTAGE, "LRADC1"), | |
1457 | MXS_ADC_CHAN(2, IIO_VOLTAGE, "LRADC2"), | |
1458 | MXS_ADC_CHAN(3, IIO_VOLTAGE, "LRADC3"), | |
1459 | MXS_ADC_CHAN(4, IIO_VOLTAGE, "LRADC4"), | |
1460 | MXS_ADC_CHAN(5, IIO_VOLTAGE, "LRADC5"), | |
1461 | MXS_ADC_CHAN(6, IIO_VOLTAGE, "LRADC6"), | |
1462 | MXS_ADC_CHAN(7, IIO_VOLTAGE, "VBATT"), | |
1463 | /* Combined Temperature sensors */ | |
1464 | { | |
1465 | .type = IIO_TEMP, | |
1466 | .indexed = 1, | |
1467 | .scan_index = 8, | |
1468 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | |
1469 | BIT(IIO_CHAN_INFO_OFFSET) | | |
1470 | BIT(IIO_CHAN_INFO_SCALE), | |
1471 | .channel = 8, | |
1472 | .scan_type = {.sign = 'u', .realbits = 18, .storagebits = 32,}, | |
1473 | .datasheet_name = "TEMP_DIE", | |
1474 | }, | |
1475 | /* Hidden channel to keep indexes */ | |
1476 | { | |
1477 | .type = IIO_TEMP, | |
1478 | .indexed = 1, | |
1479 | .scan_index = -1, | |
1480 | .channel = 9, | |
1481 | }, | |
1482 | MXS_ADC_CHAN(10, IIO_VOLTAGE, "VDDIO"), | |
1483 | MXS_ADC_CHAN(11, IIO_VOLTAGE, "VTH"), | |
1484 | MXS_ADC_CHAN(12, IIO_VOLTAGE, "VDDA"), | |
1485 | MXS_ADC_CHAN(13, IIO_VOLTAGE, "VDDD"), | |
1486 | MXS_ADC_CHAN(14, IIO_VOLTAGE, "VBG"), | |
1487 | MXS_ADC_CHAN(15, IIO_VOLTAGE, "VDD5V"), | |
bc2c90c9 MV |
1488 | }; |
1489 | ||
850c25c8 | 1490 | static void mxs_lradc_hw_init(struct mxs_lradc *lradc) |
bc2c90c9 | 1491 | { |
06ddd353 | 1492 | /* The ADC always uses DELAY CHANNEL 0. */ |
0e4f0075 | 1493 | const u32 adc_cfg = |
06ddd353 | 1494 | (1 << (LRADC_DELAY_TRIGGER_DELAYS_OFFSET + 0)) | |
bc2c90c9 MV |
1495 | (LRADC_DELAY_TIMER_PER << LRADC_DELAY_DELAY_OFFSET); |
1496 | ||
06ddd353 | 1497 | /* Configure DELAY CHANNEL 0 for generic ADC sampling. */ |
f0b83cc8 | 1498 | mxs_lradc_reg_wrt(lradc, adc_cfg, LRADC_DELAY(0)); |
06ddd353 MV |
1499 | |
1500 | /* Disable remaining DELAY CHANNELs */ | |
f0b83cc8 JB |
1501 | mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(1)); |
1502 | mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); | |
1503 | mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); | |
06ddd353 | 1504 | |
bc2c90c9 | 1505 | /* Start internal temperature sensing. */ |
f0b83cc8 | 1506 | mxs_lradc_reg_wrt(lradc, 0, LRADC_CTRL2); |
bc2c90c9 MV |
1507 | } |
1508 | ||
1509 | static void mxs_lradc_hw_stop(struct mxs_lradc *lradc) | |
1510 | { | |
1511 | int i; | |
1512 | ||
f0b83cc8 | 1513 | mxs_lradc_reg_clear(lradc, mxs_lradc_irq_en_mask(lradc), LRADC_CTRL1); |
bc2c90c9 MV |
1514 | |
1515 | for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++) | |
f0b83cc8 | 1516 | mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(i)); |
bc2c90c9 MV |
1517 | } |
1518 | ||
5e1f9aca MV |
1519 | static const struct of_device_id mxs_lradc_dt_ids[] = { |
1520 | { .compatible = "fsl,imx23-lradc", .data = (void *)IMX23_LRADC, }, | |
1521 | { .compatible = "fsl,imx28-lradc", .data = (void *)IMX28_LRADC, }, | |
1522 | { /* sentinel */ } | |
1523 | }; | |
1524 | MODULE_DEVICE_TABLE(of, mxs_lradc_dt_ids); | |
1525 | ||
dee05308 | 1526 | static int mxs_lradc_probe_touchscreen(struct mxs_lradc *lradc, |
e8ef49f0 | 1527 | struct device_node *lradc_node) |
dee05308 | 1528 | { |
e9c88fb5 JB |
1529 | int ret; |
1530 | u32 ts_wires = 0, adapt; | |
1531 | ||
1532 | ret = of_property_read_u32(lradc_node, "fsl,lradc-touchscreen-wires", | |
e8ef49f0 | 1533 | &ts_wires); |
e9c88fb5 JB |
1534 | if (ret) |
1535 | return -ENODEV; /* touchscreen feature disabled */ | |
1536 | ||
1537 | switch (ts_wires) { | |
1538 | case 4: | |
1539 | lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_4WIRE; | |
1540 | break; | |
1541 | case 5: | |
1542 | if (lradc->soc == IMX28_LRADC) { | |
1543 | lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_5WIRE; | |
1544 | break; | |
1545 | } | |
1546 | /* fall through an error message for i.MX23 */ | |
1547 | default: | |
1548 | dev_err(lradc->dev, | |
1549 | "Unsupported number of touchscreen wires (%d)\n", | |
1550 | ts_wires); | |
1551 | return -EINVAL; | |
1552 | } | |
1553 | ||
c22d2672 SW |
1554 | if (of_property_read_u32(lradc_node, "fsl,ave-ctrl", &adapt)) { |
1555 | lradc->over_sample_cnt = 4; | |
1556 | } else { | |
1557 | if (adapt < 1 || adapt > 32) { | |
1558 | dev_err(lradc->dev, "Invalid sample count (%u)\n", | |
1559 | adapt); | |
1560 | return -EINVAL; | |
1561 | } | |
e9c88fb5 | 1562 | lradc->over_sample_cnt = adapt; |
c22d2672 | 1563 | } |
e9c88fb5 | 1564 | |
c22d2672 SW |
1565 | if (of_property_read_u32(lradc_node, "fsl,ave-delay", &adapt)) { |
1566 | lradc->over_sample_delay = 2; | |
1567 | } else { | |
1568 | if (adapt < 2 || adapt > LRADC_DELAY_DELAY_MASK + 1) { | |
1569 | dev_err(lradc->dev, "Invalid sample delay (%u)\n", | |
1570 | adapt); | |
1571 | return -EINVAL; | |
1572 | } | |
e9c88fb5 | 1573 | lradc->over_sample_delay = adapt; |
c22d2672 | 1574 | } |
e9c88fb5 | 1575 | |
c22d2672 SW |
1576 | if (of_property_read_u32(lradc_node, "fsl,settling", &adapt)) { |
1577 | lradc->settling_delay = 10; | |
1578 | } else { | |
1579 | if (adapt < 1 || adapt > LRADC_DELAY_DELAY_MASK) { | |
1580 | dev_err(lradc->dev, "Invalid settling delay (%u)\n", | |
1581 | adapt); | |
1582 | return -EINVAL; | |
1583 | } | |
e9c88fb5 | 1584 | lradc->settling_delay = adapt; |
c22d2672 | 1585 | } |
dee05308 JB |
1586 | |
1587 | return 0; | |
1588 | } | |
1589 | ||
4ae1c61f | 1590 | static int mxs_lradc_probe(struct platform_device *pdev) |
bc2c90c9 | 1591 | { |
5e1f9aca MV |
1592 | const struct of_device_id *of_id = |
1593 | of_match_device(mxs_lradc_dt_ids, &pdev->dev); | |
1594 | const struct mxs_lradc_of_config *of_cfg = | |
1595 | &mxs_lradc_of_config[(enum mxs_lradc_id)of_id->data]; | |
bc2c90c9 | 1596 | struct device *dev = &pdev->dev; |
06ddd353 | 1597 | struct device_node *node = dev->of_node; |
bc2c90c9 MV |
1598 | struct mxs_lradc *lradc; |
1599 | struct iio_dev *iio; | |
1600 | struct resource *iores; | |
dee05308 | 1601 | int ret = 0, touch_ret; |
d5acf594 | 1602 | int i, s; |
0e4f0075 | 1603 | u64 scale_uv; |
bc2c90c9 MV |
1604 | |
1605 | /* Allocate the IIO device. */ | |
073c33d5 | 1606 | iio = devm_iio_device_alloc(dev, sizeof(*lradc)); |
bc2c90c9 MV |
1607 | if (!iio) { |
1608 | dev_err(dev, "Failed to allocate IIO device\n"); | |
1609 | return -ENOMEM; | |
1610 | } | |
1611 | ||
1612 | lradc = iio_priv(iio); | |
ccff5297 | 1613 | lradc->soc = (enum mxs_lradc_id)of_id->data; |
bc2c90c9 MV |
1614 | |
1615 | /* Grab the memory area */ | |
1616 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
1617 | lradc->dev = &pdev->dev; | |
97f4be60 | 1618 | lradc->base = devm_ioremap_resource(dev, iores); |
073c33d5 SK |
1619 | if (IS_ERR(lradc->base)) |
1620 | return PTR_ERR(lradc->base); | |
bc2c90c9 | 1621 | |
18da755d JB |
1622 | lradc->clk = devm_clk_get(&pdev->dev, NULL); |
1623 | if (IS_ERR(lradc->clk)) { | |
1624 | dev_err(dev, "Failed to get the delay unit clock\n"); | |
1625 | return PTR_ERR(lradc->clk); | |
1626 | } | |
1627 | ret = clk_prepare_enable(lradc->clk); | |
1628 | if (ret != 0) { | |
1629 | dev_err(dev, "Failed to enable the delay unit clock\n"); | |
1630 | return ret; | |
1631 | } | |
1632 | ||
dee05308 | 1633 | touch_ret = mxs_lradc_probe_touchscreen(lradc, node); |
06ddd353 | 1634 | |
86bf7f3e KM |
1635 | if (touch_ret == 0) |
1636 | lradc->buffer_vchans = BUFFER_VCHANS_LIMITED; | |
1637 | else | |
1638 | lradc->buffer_vchans = BUFFER_VCHANS_ALL; | |
1639 | ||
bc2c90c9 | 1640 | /* Grab all IRQ sources */ |
5e1f9aca | 1641 | for (i = 0; i < of_cfg->irq_count; i++) { |
bc2c90c9 | 1642 | lradc->irq[i] = platform_get_irq(pdev, i); |
75d7ed3b FE |
1643 | if (lradc->irq[i] < 0) { |
1644 | ret = lradc->irq[i]; | |
1645 | goto err_clk; | |
1646 | } | |
bc2c90c9 MV |
1647 | |
1648 | ret = devm_request_irq(dev, lradc->irq[i], | |
e8ef49f0 IC |
1649 | mxs_lradc_handle_irq, 0, |
1650 | of_cfg->irq_name[i], iio); | |
bc2c90c9 | 1651 | if (ret) |
75d7ed3b | 1652 | goto err_clk; |
bc2c90c9 MV |
1653 | } |
1654 | ||
f6db68a4 HP |
1655 | lradc->vref_mv = of_cfg->vref_mv; |
1656 | ||
bc2c90c9 MV |
1657 | platform_set_drvdata(pdev, iio); |
1658 | ||
1659 | init_completion(&lradc->completion); | |
1660 | mutex_init(&lradc->lock); | |
1661 | ||
1662 | iio->name = pdev->name; | |
1663 | iio->dev.parent = &pdev->dev; | |
1664 | iio->info = &mxs_lradc_iio_info; | |
1665 | iio->modes = INDIO_DIRECT_MODE; | |
f4914e5e | 1666 | iio->masklength = LRADC_MAX_TOTAL_CHANS; |
bc2c90c9 | 1667 | |
829aed1a SW |
1668 | if (lradc->soc == IMX23_LRADC) { |
1669 | iio->channels = mx23_lradc_chan_spec; | |
1670 | iio->num_channels = ARRAY_SIZE(mx23_lradc_chan_spec); | |
1671 | } else { | |
1672 | iio->channels = mx28_lradc_chan_spec; | |
1673 | iio->num_channels = ARRAY_SIZE(mx28_lradc_chan_spec); | |
1674 | } | |
1675 | ||
bc2c90c9 | 1676 | ret = iio_triggered_buffer_setup(iio, &iio_pollfunc_store_time, |
e8ef49f0 IC |
1677 | &mxs_lradc_trigger_handler, |
1678 | &mxs_lradc_buffer_ops); | |
bc2c90c9 | 1679 | if (ret) |
75d7ed3b | 1680 | goto err_clk; |
bc2c90c9 MV |
1681 | |
1682 | ret = mxs_lradc_trigger_init(iio); | |
1683 | if (ret) | |
1684 | goto err_trig; | |
1685 | ||
d5acf594 HP |
1686 | /* Populate available ADC input ranges */ |
1687 | for (i = 0; i < LRADC_MAX_TOTAL_CHANS; i++) { | |
1688 | for (s = 0; s < ARRAY_SIZE(lradc->scale_avail[i]); s++) { | |
1689 | /* | |
1690 | * [s=0] = optional divider by two disabled (default) | |
1691 | * [s=1] = optional divider by two enabled | |
1692 | * | |
1693 | * The scale is calculated by doing: | |
1694 | * Vref >> (realbits - s) | |
1695 | * which multiplies by two on the second component | |
1696 | * of the array. | |
1697 | */ | |
1698 | scale_uv = ((u64)lradc->vref_mv[i] * 100000000) >> | |
d4bf105b | 1699 | (LRADC_RESOLUTION - s); |
d5acf594 HP |
1700 | lradc->scale_avail[i][s].nano = |
1701 | do_div(scale_uv, 100000000) * 10; | |
1702 | lradc->scale_avail[i][s].integer = scale_uv; | |
1703 | } | |
1704 | } | |
1705 | ||
850c25c8 | 1706 | ret = stmp_reset_block(lradc->base); |
947123d5 FE |
1707 | if (ret) |
1708 | goto err_dev; | |
f6e8a968 | 1709 | |
850c25c8 SW |
1710 | /* Configure the hardware. */ |
1711 | mxs_lradc_hw_init(lradc); | |
1712 | ||
06ddd353 | 1713 | /* Register the touchscreen input device. */ |
dee05308 JB |
1714 | if (touch_ret == 0) { |
1715 | ret = mxs_lradc_ts_register(lradc); | |
1716 | if (ret) | |
1717 | goto err_ts_register; | |
1718 | } | |
06ddd353 | 1719 | |
bc2c90c9 MV |
1720 | /* Register IIO device. */ |
1721 | ret = iio_device_register(iio); | |
1722 | if (ret) { | |
1723 | dev_err(dev, "Failed to register IIO device\n"); | |
06ddd353 | 1724 | goto err_ts; |
bc2c90c9 MV |
1725 | } |
1726 | ||
bc2c90c9 MV |
1727 | return 0; |
1728 | ||
06ddd353 MV |
1729 | err_ts: |
1730 | mxs_lradc_ts_unregister(lradc); | |
a0ef6db7 FE |
1731 | err_ts_register: |
1732 | mxs_lradc_hw_stop(lradc); | |
bc2c90c9 MV |
1733 | err_dev: |
1734 | mxs_lradc_trigger_remove(iio); | |
1735 | err_trig: | |
1736 | iio_triggered_buffer_cleanup(iio); | |
75d7ed3b FE |
1737 | err_clk: |
1738 | clk_disable_unprepare(lradc->clk); | |
bc2c90c9 MV |
1739 | return ret; |
1740 | } | |
1741 | ||
447d4f29 | 1742 | static int mxs_lradc_remove(struct platform_device *pdev) |
bc2c90c9 MV |
1743 | { |
1744 | struct iio_dev *iio = platform_get_drvdata(pdev); | |
1745 | struct mxs_lradc *lradc = iio_priv(iio); | |
1746 | ||
a0ef6db7 | 1747 | iio_device_unregister(iio); |
06ddd353 | 1748 | mxs_lradc_ts_unregister(lradc); |
bc2c90c9 | 1749 | mxs_lradc_hw_stop(lradc); |
bc2c90c9 | 1750 | mxs_lradc_trigger_remove(iio); |
a0ef6db7 | 1751 | iio_triggered_buffer_cleanup(iio); |
bc2c90c9 | 1752 | |
18da755d | 1753 | clk_disable_unprepare(lradc->clk); |
f836c459 | 1754 | |
bc2c90c9 MV |
1755 | return 0; |
1756 | } | |
1757 | ||
bc2c90c9 MV |
1758 | static struct platform_driver mxs_lradc_driver = { |
1759 | .driver = { | |
1760 | .name = DRIVER_NAME, | |
bc2c90c9 MV |
1761 | .of_match_table = mxs_lradc_dt_ids, |
1762 | }, | |
1763 | .probe = mxs_lradc_probe, | |
e543acf0 | 1764 | .remove = mxs_lradc_remove, |
bc2c90c9 MV |
1765 | }; |
1766 | ||
1767 | module_platform_driver(mxs_lradc_driver); | |
1768 | ||
1769 | MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); | |
07a4257e | 1770 | MODULE_DESCRIPTION("Freescale MXS LRADC driver"); |
bc2c90c9 | 1771 | MODULE_LICENSE("GPL v2"); |
8c4a8c9d | 1772 | MODULE_ALIAS("platform:" DRIVER_NAME); |