]>
Commit | Line | Data |
---|---|---|
27e17719 LD |
1 | /* |
2 | * Atmel ADC driver for SAMA5D2 devices and compatible. | |
3 | * | |
4 | * Copyright (C) 2015 Atmel, | |
5 | * 2015 Ludovic Desroches <ludovic.desroches@atmel.com> | |
6 | * | |
7 | * This software is licensed under the terms of the GNU General Public | |
8 | * License version 2, as published by the Free Software Foundation, and | |
9 | * may be copied, distributed, and modified under those terms. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | */ | |
16 | ||
17 | #include <linux/bitops.h> | |
18 | #include <linux/clk.h> | |
19 | #include <linux/interrupt.h> | |
20 | #include <linux/io.h> | |
21 | #include <linux/module.h> | |
22 | #include <linux/of_device.h> | |
23 | #include <linux/platform_device.h> | |
24 | #include <linux/sched.h> | |
25 | #include <linux/wait.h> | |
26 | #include <linux/iio/iio.h> | |
27 | #include <linux/iio/sysfs.h> | |
5e1a1da0 EH |
28 | #include <linux/iio/buffer.h> |
29 | #include <linux/iio/trigger.h> | |
30 | #include <linux/iio/trigger_consumer.h> | |
31 | #include <linux/iio/triggered_buffer.h> | |
500a2eef | 32 | #include <linux/pinctrl/consumer.h> |
27e17719 LD |
33 | #include <linux/regulator/consumer.h> |
34 | ||
35 | /* Control Register */ | |
36 | #define AT91_SAMA5D2_CR 0x00 | |
37 | /* Software Reset */ | |
38 | #define AT91_SAMA5D2_CR_SWRST BIT(0) | |
39 | /* Start Conversion */ | |
40 | #define AT91_SAMA5D2_CR_START BIT(1) | |
41 | /* Touchscreen Calibration */ | |
42 | #define AT91_SAMA5D2_CR_TSCALIB BIT(2) | |
43 | /* Comparison Restart */ | |
44 | #define AT91_SAMA5D2_CR_CMPRST BIT(4) | |
45 | ||
46 | /* Mode Register */ | |
47 | #define AT91_SAMA5D2_MR 0x04 | |
48 | /* Trigger Selection */ | |
49 | #define AT91_SAMA5D2_MR_TRGSEL(v) ((v) << 1) | |
50 | /* ADTRG */ | |
51 | #define AT91_SAMA5D2_MR_TRGSEL_TRIG0 0 | |
52 | /* TIOA0 */ | |
53 | #define AT91_SAMA5D2_MR_TRGSEL_TRIG1 1 | |
54 | /* TIOA1 */ | |
55 | #define AT91_SAMA5D2_MR_TRGSEL_TRIG2 2 | |
56 | /* TIOA2 */ | |
57 | #define AT91_SAMA5D2_MR_TRGSEL_TRIG3 3 | |
58 | /* PWM event line 0 */ | |
59 | #define AT91_SAMA5D2_MR_TRGSEL_TRIG4 4 | |
60 | /* PWM event line 1 */ | |
61 | #define AT91_SAMA5D2_MR_TRGSEL_TRIG5 5 | |
62 | /* TIOA3 */ | |
63 | #define AT91_SAMA5D2_MR_TRGSEL_TRIG6 6 | |
64 | /* RTCOUT0 */ | |
65 | #define AT91_SAMA5D2_MR_TRGSEL_TRIG7 7 | |
66 | /* Sleep Mode */ | |
67 | #define AT91_SAMA5D2_MR_SLEEP BIT(5) | |
68 | /* Fast Wake Up */ | |
69 | #define AT91_SAMA5D2_MR_FWUP BIT(6) | |
70 | /* Prescaler Rate Selection */ | |
71 | #define AT91_SAMA5D2_MR_PRESCAL(v) ((v) << AT91_SAMA5D2_MR_PRESCAL_OFFSET) | |
72 | #define AT91_SAMA5D2_MR_PRESCAL_OFFSET 8 | |
73 | #define AT91_SAMA5D2_MR_PRESCAL_MAX 0xff | |
94b24230 | 74 | #define AT91_SAMA5D2_MR_PRESCAL_MASK GENMASK(15, 8) |
27e17719 LD |
75 | /* Startup Time */ |
76 | #define AT91_SAMA5D2_MR_STARTUP(v) ((v) << 16) | |
94b24230 | 77 | #define AT91_SAMA5D2_MR_STARTUP_MASK GENMASK(19, 16) |
27e17719 LD |
78 | /* Analog Change */ |
79 | #define AT91_SAMA5D2_MR_ANACH BIT(23) | |
80 | /* Tracking Time */ | |
81 | #define AT91_SAMA5D2_MR_TRACKTIM(v) ((v) << 24) | |
82 | #define AT91_SAMA5D2_MR_TRACKTIM_MAX 0xff | |
83 | /* Transfer Time */ | |
84 | #define AT91_SAMA5D2_MR_TRANSFER(v) ((v) << 28) | |
85 | #define AT91_SAMA5D2_MR_TRANSFER_MAX 0x3 | |
86 | /* Use Sequence Enable */ | |
87 | #define AT91_SAMA5D2_MR_USEQ BIT(31) | |
88 | ||
89 | /* Channel Sequence Register 1 */ | |
90 | #define AT91_SAMA5D2_SEQR1 0x08 | |
91 | /* Channel Sequence Register 2 */ | |
92 | #define AT91_SAMA5D2_SEQR2 0x0c | |
93 | /* Channel Enable Register */ | |
94 | #define AT91_SAMA5D2_CHER 0x10 | |
95 | /* Channel Disable Register */ | |
96 | #define AT91_SAMA5D2_CHDR 0x14 | |
97 | /* Channel Status Register */ | |
98 | #define AT91_SAMA5D2_CHSR 0x18 | |
99 | /* Last Converted Data Register */ | |
100 | #define AT91_SAMA5D2_LCDR 0x20 | |
101 | /* Interrupt Enable Register */ | |
f0fa15cc | 102 | #define AT91_SAMA5D2_IER 0x24 |
27e17719 | 103 | /* Interrupt Disable Register */ |
f0fa15cc | 104 | #define AT91_SAMA5D2_IDR 0x28 |
27e17719 | 105 | /* Interrupt Mask Register */ |
f0fa15cc | 106 | #define AT91_SAMA5D2_IMR 0x2c |
27e17719 | 107 | /* Interrupt Status Register */ |
f0fa15cc | 108 | #define AT91_SAMA5D2_ISR 0x30 |
27e17719 LD |
109 | /* Last Channel Trigger Mode Register */ |
110 | #define AT91_SAMA5D2_LCTMR 0x34 | |
111 | /* Last Channel Compare Window Register */ | |
112 | #define AT91_SAMA5D2_LCCWR 0x38 | |
113 | /* Overrun Status Register */ | |
114 | #define AT91_SAMA5D2_OVER 0x3c | |
115 | /* Extended Mode Register */ | |
f0fa15cc | 116 | #define AT91_SAMA5D2_EMR 0x40 |
27e17719 | 117 | /* Compare Window Register */ |
f0fa15cc | 118 | #define AT91_SAMA5D2_CWR 0x44 |
27e17719 | 119 | /* Channel Gain Register */ |
f0fa15cc | 120 | #define AT91_SAMA5D2_CGR 0x48 |
d6511322 | 121 | |
27e17719 | 122 | /* Channel Offset Register */ |
f0fa15cc | 123 | #define AT91_SAMA5D2_COR 0x4c |
d6511322 LD |
124 | #define AT91_SAMA5D2_COR_DIFF_OFFSET 16 |
125 | ||
27e17719 LD |
126 | /* Channel Data Register 0 */ |
127 | #define AT91_SAMA5D2_CDR0 0x50 | |
128 | /* Analog Control Register */ | |
f0fa15cc | 129 | #define AT91_SAMA5D2_ACR 0x94 |
27e17719 LD |
130 | /* Touchscreen Mode Register */ |
131 | #define AT91_SAMA5D2_TSMR 0xb0 | |
132 | /* Touchscreen X Position Register */ | |
133 | #define AT91_SAMA5D2_XPOSR 0xb4 | |
134 | /* Touchscreen Y Position Register */ | |
135 | #define AT91_SAMA5D2_YPOSR 0xb8 | |
136 | /* Touchscreen Pressure Register */ | |
137 | #define AT91_SAMA5D2_PRESSR 0xbc | |
138 | /* Trigger Register */ | |
139 | #define AT91_SAMA5D2_TRGR 0xc0 | |
5e1a1da0 EH |
140 | /* Mask for TRGMOD field of TRGR register */ |
141 | #define AT91_SAMA5D2_TRGR_TRGMOD_MASK GENMASK(2, 0) | |
142 | /* No trigger, only software trigger can start conversions */ | |
143 | #define AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER 0 | |
144 | /* Trigger Mode external trigger rising edge */ | |
145 | #define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE 1 | |
146 | /* Trigger Mode external trigger falling edge */ | |
147 | #define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL 2 | |
148 | /* Trigger Mode external trigger any edge */ | |
149 | #define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY 3 | |
150 | ||
27e17719 LD |
151 | /* Correction Select Register */ |
152 | #define AT91_SAMA5D2_COSR 0xd0 | |
153 | /* Correction Value Register */ | |
f0fa15cc | 154 | #define AT91_SAMA5D2_CVR 0xd4 |
27e17719 LD |
155 | /* Channel Error Correction Register */ |
156 | #define AT91_SAMA5D2_CECR 0xd8 | |
157 | /* Write Protection Mode Register */ | |
158 | #define AT91_SAMA5D2_WPMR 0xe4 | |
159 | /* Write Protection Status Register */ | |
160 | #define AT91_SAMA5D2_WPSR 0xe8 | |
161 | /* Version Register */ | |
162 | #define AT91_SAMA5D2_VERSION 0xfc | |
163 | ||
5e1a1da0 EH |
164 | #define AT91_SAMA5D2_HW_TRIG_CNT 3 |
165 | #define AT91_SAMA5D2_SINGLE_CHAN_CNT 12 | |
166 | #define AT91_SAMA5D2_DIFF_CHAN_CNT 6 | |
167 | ||
168 | /* | |
169 | * Maximum number of bytes to hold conversion from all channels | |
170 | * plus the timestamp | |
171 | */ | |
172 | #define AT91_BUFFER_MAX_BYTES ((AT91_SAMA5D2_SINGLE_CHAN_CNT + \ | |
173 | AT91_SAMA5D2_DIFF_CHAN_CNT) * 2 + 8) | |
174 | ||
175 | #define AT91_BUFFER_MAX_HWORDS (AT91_BUFFER_MAX_BYTES / 2) | |
176 | ||
d6511322 | 177 | #define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \ |
27e17719 LD |
178 | { \ |
179 | .type = IIO_VOLTAGE, \ | |
180 | .channel = num, \ | |
181 | .address = addr, \ | |
5e1a1da0 | 182 | .scan_index = num, \ |
27e17719 LD |
183 | .scan_type = { \ |
184 | .sign = 'u', \ | |
185 | .realbits = 12, \ | |
5e1a1da0 | 186 | .storagebits = 16, \ |
27e17719 LD |
187 | }, \ |
188 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
189 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ | |
190 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ | |
191 | .datasheet_name = "CH"#num, \ | |
192 | .indexed = 1, \ | |
193 | } | |
194 | ||
d6511322 LD |
195 | #define AT91_SAMA5D2_CHAN_DIFF(num, num2, addr) \ |
196 | { \ | |
197 | .type = IIO_VOLTAGE, \ | |
198 | .differential = 1, \ | |
199 | .channel = num, \ | |
200 | .channel2 = num2, \ | |
201 | .address = addr, \ | |
5e1a1da0 | 202 | .scan_index = num + AT91_SAMA5D2_SINGLE_CHAN_CNT, \ |
d6511322 LD |
203 | .scan_type = { \ |
204 | .sign = 's', \ | |
205 | .realbits = 12, \ | |
5e1a1da0 | 206 | .storagebits = 16, \ |
d6511322 LD |
207 | }, \ |
208 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
209 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ | |
210 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ | |
211 | .datasheet_name = "CH"#num"-CH"#num2, \ | |
212 | .indexed = 1, \ | |
213 | } | |
214 | ||
27e17719 LD |
215 | #define at91_adc_readl(st, reg) readl_relaxed(st->base + reg) |
216 | #define at91_adc_writel(st, reg, val) writel_relaxed(val, st->base + reg) | |
217 | ||
218 | struct at91_adc_soc_info { | |
219 | unsigned startup_time; | |
220 | unsigned min_sample_rate; | |
221 | unsigned max_sample_rate; | |
222 | }; | |
223 | ||
5e1a1da0 EH |
224 | struct at91_adc_trigger { |
225 | char *name; | |
226 | unsigned int trgmod_value; | |
227 | unsigned int edge_type; | |
ca4c3023 | 228 | bool hw_trig; |
5e1a1da0 EH |
229 | }; |
230 | ||
27e17719 LD |
231 | struct at91_adc_state { |
232 | void __iomem *base; | |
233 | int irq; | |
234 | struct clk *per_clk; | |
235 | struct regulator *reg; | |
236 | struct regulator *vref; | |
d7bdcc3f | 237 | int vref_uv; |
5e1a1da0 EH |
238 | struct iio_trigger *trig; |
239 | const struct at91_adc_trigger *selected_trig; | |
27e17719 LD |
240 | const struct iio_chan_spec *chan; |
241 | bool conversion_done; | |
242 | u32 conversion_value; | |
243 | struct at91_adc_soc_info soc_info; | |
244 | wait_queue_head_t wq_data_available; | |
5e1a1da0 | 245 | u16 buffer[AT91_BUFFER_MAX_HWORDS]; |
27e17719 LD |
246 | /* |
247 | * lock to prevent concurrent 'single conversion' requests through | |
248 | * sysfs. | |
249 | */ | |
250 | struct mutex lock; | |
251 | }; | |
252 | ||
5e1a1da0 EH |
253 | static const struct at91_adc_trigger at91_adc_trigger_list[] = { |
254 | { | |
255 | .name = "external_rising", | |
256 | .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE, | |
257 | .edge_type = IRQ_TYPE_EDGE_RISING, | |
ca4c3023 | 258 | .hw_trig = true, |
5e1a1da0 EH |
259 | }, |
260 | { | |
261 | .name = "external_falling", | |
262 | .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL, | |
263 | .edge_type = IRQ_TYPE_EDGE_FALLING, | |
ca4c3023 | 264 | .hw_trig = true, |
5e1a1da0 EH |
265 | }, |
266 | { | |
267 | .name = "external_any", | |
268 | .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY, | |
269 | .edge_type = IRQ_TYPE_EDGE_BOTH, | |
ca4c3023 EH |
270 | .hw_trig = true, |
271 | }, | |
272 | { | |
273 | .name = "software", | |
274 | .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER, | |
275 | .edge_type = IRQ_TYPE_NONE, | |
276 | .hw_trig = false, | |
5e1a1da0 EH |
277 | }, |
278 | }; | |
279 | ||
27e17719 | 280 | static const struct iio_chan_spec at91_adc_channels[] = { |
d6511322 LD |
281 | AT91_SAMA5D2_CHAN_SINGLE(0, 0x50), |
282 | AT91_SAMA5D2_CHAN_SINGLE(1, 0x54), | |
283 | AT91_SAMA5D2_CHAN_SINGLE(2, 0x58), | |
284 | AT91_SAMA5D2_CHAN_SINGLE(3, 0x5c), | |
285 | AT91_SAMA5D2_CHAN_SINGLE(4, 0x60), | |
286 | AT91_SAMA5D2_CHAN_SINGLE(5, 0x64), | |
287 | AT91_SAMA5D2_CHAN_SINGLE(6, 0x68), | |
288 | AT91_SAMA5D2_CHAN_SINGLE(7, 0x6c), | |
289 | AT91_SAMA5D2_CHAN_SINGLE(8, 0x70), | |
290 | AT91_SAMA5D2_CHAN_SINGLE(9, 0x74), | |
291 | AT91_SAMA5D2_CHAN_SINGLE(10, 0x78), | |
292 | AT91_SAMA5D2_CHAN_SINGLE(11, 0x7c), | |
293 | AT91_SAMA5D2_CHAN_DIFF(0, 1, 0x50), | |
294 | AT91_SAMA5D2_CHAN_DIFF(2, 3, 0x58), | |
295 | AT91_SAMA5D2_CHAN_DIFF(4, 5, 0x60), | |
296 | AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68), | |
297 | AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70), | |
298 | AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78), | |
5e1a1da0 EH |
299 | IIO_CHAN_SOFT_TIMESTAMP(AT91_SAMA5D2_SINGLE_CHAN_CNT |
300 | + AT91_SAMA5D2_DIFF_CHAN_CNT + 1), | |
27e17719 LD |
301 | }; |
302 | ||
5e1a1da0 EH |
303 | static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state) |
304 | { | |
305 | struct iio_dev *indio = iio_trigger_get_drvdata(trig); | |
306 | struct at91_adc_state *st = iio_priv(indio); | |
307 | u32 status = at91_adc_readl(st, AT91_SAMA5D2_TRGR); | |
308 | u8 bit; | |
309 | ||
310 | /* clear TRGMOD */ | |
311 | status &= ~AT91_SAMA5D2_TRGR_TRGMOD_MASK; | |
312 | ||
313 | if (state) | |
314 | status |= st->selected_trig->trgmod_value; | |
315 | ||
316 | /* set/unset hw trigger */ | |
317 | at91_adc_writel(st, AT91_SAMA5D2_TRGR, status); | |
318 | ||
319 | for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) { | |
320 | struct iio_chan_spec const *chan = indio->channels + bit; | |
321 | ||
322 | if (state) { | |
323 | at91_adc_writel(st, AT91_SAMA5D2_CHER, | |
324 | BIT(chan->channel)); | |
325 | at91_adc_writel(st, AT91_SAMA5D2_IER, | |
326 | BIT(chan->channel)); | |
327 | } else { | |
328 | at91_adc_writel(st, AT91_SAMA5D2_IDR, | |
329 | BIT(chan->channel)); | |
330 | at91_adc_writel(st, AT91_SAMA5D2_CHDR, | |
331 | BIT(chan->channel)); | |
332 | } | |
333 | } | |
334 | ||
335 | return 0; | |
336 | } | |
337 | ||
338 | static int at91_adc_reenable_trigger(struct iio_trigger *trig) | |
339 | { | |
340 | struct iio_dev *indio = iio_trigger_get_drvdata(trig); | |
341 | struct at91_adc_state *st = iio_priv(indio); | |
342 | ||
343 | enable_irq(st->irq); | |
344 | ||
345 | /* Needed to ACK the DRDY interruption */ | |
346 | at91_adc_readl(st, AT91_SAMA5D2_LCDR); | |
347 | return 0; | |
348 | } | |
349 | ||
350 | static const struct iio_trigger_ops at91_adc_trigger_ops = { | |
351 | .owner = THIS_MODULE, | |
352 | .set_trigger_state = &at91_adc_configure_trigger, | |
353 | .try_reenable = &at91_adc_reenable_trigger, | |
354 | }; | |
355 | ||
356 | static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio, | |
357 | char *trigger_name) | |
358 | { | |
359 | struct iio_trigger *trig; | |
360 | int ret; | |
361 | ||
362 | trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name, | |
363 | indio->id, trigger_name); | |
364 | if (!trig) | |
365 | return NULL; | |
366 | ||
367 | trig->dev.parent = indio->dev.parent; | |
368 | iio_trigger_set_drvdata(trig, indio); | |
369 | trig->ops = &at91_adc_trigger_ops; | |
370 | ||
371 | ret = devm_iio_trigger_register(&indio->dev, trig); | |
372 | if (ret) | |
373 | return ERR_PTR(ret); | |
374 | ||
375 | return trig; | |
376 | } | |
377 | ||
378 | static int at91_adc_trigger_init(struct iio_dev *indio) | |
379 | { | |
380 | struct at91_adc_state *st = iio_priv(indio); | |
381 | ||
382 | st->trig = at91_adc_allocate_trigger(indio, st->selected_trig->name); | |
383 | if (IS_ERR(st->trig)) { | |
384 | dev_err(&indio->dev, | |
385 | "could not allocate trigger\n"); | |
386 | return PTR_ERR(st->trig); | |
387 | } | |
388 | ||
389 | return 0; | |
390 | } | |
391 | ||
392 | static irqreturn_t at91_adc_trigger_handler(int irq, void *p) | |
393 | { | |
394 | struct iio_poll_func *pf = p; | |
395 | struct iio_dev *indio = pf->indio_dev; | |
396 | struct at91_adc_state *st = iio_priv(indio); | |
397 | int i = 0; | |
398 | u8 bit; | |
399 | ||
400 | for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) { | |
401 | struct iio_chan_spec const *chan = indio->channels + bit; | |
402 | ||
403 | st->buffer[i] = at91_adc_readl(st, chan->address); | |
404 | i++; | |
405 | } | |
406 | ||
407 | iio_push_to_buffers_with_timestamp(indio, st->buffer, pf->timestamp); | |
408 | ||
409 | iio_trigger_notify_done(indio->trig); | |
410 | ||
411 | return IRQ_HANDLED; | |
412 | } | |
413 | ||
414 | static int at91_adc_buffer_init(struct iio_dev *indio) | |
415 | { | |
416 | return devm_iio_triggered_buffer_setup(&indio->dev, indio, | |
417 | &iio_pollfunc_store_time, | |
418 | &at91_adc_trigger_handler, NULL); | |
419 | } | |
420 | ||
27e17719 LD |
421 | static unsigned at91_adc_startup_time(unsigned startup_time_min, |
422 | unsigned adc_clk_khz) | |
423 | { | |
2df331cf | 424 | static const unsigned int startup_lookup[] = { |
27e17719 LD |
425 | 0, 8, 16, 24, |
426 | 64, 80, 96, 112, | |
427 | 512, 576, 640, 704, | |
428 | 768, 832, 896, 960 | |
429 | }; | |
430 | unsigned ticks_min, i; | |
431 | ||
432 | /* | |
433 | * Since the adc frequency is checked before, there is no reason | |
434 | * to not meet the startup time constraint. | |
435 | */ | |
436 | ||
437 | ticks_min = startup_time_min * adc_clk_khz / 1000; | |
438 | for (i = 0; i < ARRAY_SIZE(startup_lookup); i++) | |
439 | if (startup_lookup[i] > ticks_min) | |
440 | break; | |
441 | ||
442 | return i; | |
443 | } | |
444 | ||
445 | static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq) | |
446 | { | |
447 | struct iio_dev *indio_dev = iio_priv_to_dev(st); | |
94b24230 | 448 | unsigned f_per, prescal, startup, mr; |
27e17719 LD |
449 | |
450 | f_per = clk_get_rate(st->per_clk); | |
451 | prescal = (f_per / (2 * freq)) - 1; | |
452 | ||
453 | startup = at91_adc_startup_time(st->soc_info.startup_time, | |
454 | freq / 1000); | |
455 | ||
94b24230 LD |
456 | mr = at91_adc_readl(st, AT91_SAMA5D2_MR); |
457 | mr &= ~(AT91_SAMA5D2_MR_STARTUP_MASK | AT91_SAMA5D2_MR_PRESCAL_MASK); | |
458 | mr |= AT91_SAMA5D2_MR_STARTUP(startup); | |
459 | mr |= AT91_SAMA5D2_MR_PRESCAL(prescal); | |
460 | at91_adc_writel(st, AT91_SAMA5D2_MR, mr); | |
27e17719 LD |
461 | |
462 | dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u\n", | |
463 | freq, startup, prescal); | |
464 | } | |
465 | ||
466 | static unsigned at91_adc_get_sample_freq(struct at91_adc_state *st) | |
467 | { | |
468 | unsigned f_adc, f_per = clk_get_rate(st->per_clk); | |
469 | unsigned mr, prescal; | |
470 | ||
471 | mr = at91_adc_readl(st, AT91_SAMA5D2_MR); | |
472 | prescal = (mr >> AT91_SAMA5D2_MR_PRESCAL_OFFSET) | |
473 | & AT91_SAMA5D2_MR_PRESCAL_MAX; | |
474 | f_adc = f_per / (2 * (prescal + 1)); | |
475 | ||
476 | return f_adc; | |
477 | } | |
478 | ||
479 | static irqreturn_t at91_adc_interrupt(int irq, void *private) | |
480 | { | |
481 | struct iio_dev *indio = private; | |
482 | struct at91_adc_state *st = iio_priv(indio); | |
483 | u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR); | |
484 | u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR); | |
485 | ||
5e1a1da0 EH |
486 | if (!(status & imr)) |
487 | return IRQ_NONE; | |
488 | ||
489 | if (iio_buffer_enabled(indio)) { | |
490 | disable_irq_nosync(irq); | |
491 | iio_trigger_poll(indio->trig); | |
492 | } else { | |
27e17719 LD |
493 | st->conversion_value = at91_adc_readl(st, st->chan->address); |
494 | st->conversion_done = true; | |
495 | wake_up_interruptible(&st->wq_data_available); | |
27e17719 | 496 | } |
5e1a1da0 | 497 | return IRQ_HANDLED; |
27e17719 LD |
498 | } |
499 | ||
500 | static int at91_adc_read_raw(struct iio_dev *indio_dev, | |
501 | struct iio_chan_spec const *chan, | |
502 | int *val, int *val2, long mask) | |
503 | { | |
504 | struct at91_adc_state *st = iio_priv(indio_dev); | |
d6511322 | 505 | u32 cor = 0; |
27e17719 LD |
506 | int ret; |
507 | ||
508 | switch (mask) { | |
509 | case IIO_CHAN_INFO_RAW: | |
5e1a1da0 EH |
510 | /* we cannot use software trigger if hw trigger enabled */ |
511 | ret = iio_device_claim_direct_mode(indio_dev); | |
512 | if (ret) | |
513 | return ret; | |
514 | ||
27e17719 LD |
515 | mutex_lock(&st->lock); |
516 | ||
517 | st->chan = chan; | |
518 | ||
d6511322 LD |
519 | if (chan->differential) |
520 | cor = (BIT(chan->channel) | BIT(chan->channel2)) << | |
521 | AT91_SAMA5D2_COR_DIFF_OFFSET; | |
522 | ||
523 | at91_adc_writel(st, AT91_SAMA5D2_COR, cor); | |
27e17719 LD |
524 | at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel)); |
525 | at91_adc_writel(st, AT91_SAMA5D2_IER, BIT(chan->channel)); | |
526 | at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START); | |
527 | ||
528 | ret = wait_event_interruptible_timeout(st->wq_data_available, | |
529 | st->conversion_done, | |
530 | msecs_to_jiffies(1000)); | |
531 | if (ret == 0) | |
532 | ret = -ETIMEDOUT; | |
533 | ||
534 | if (ret > 0) { | |
535 | *val = st->conversion_value; | |
d6511322 LD |
536 | if (chan->scan_type.sign == 's') |
537 | *val = sign_extend32(*val, 11); | |
27e17719 LD |
538 | ret = IIO_VAL_INT; |
539 | st->conversion_done = false; | |
540 | } | |
541 | ||
542 | at91_adc_writel(st, AT91_SAMA5D2_IDR, BIT(chan->channel)); | |
543 | at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel)); | |
544 | ||
545 | mutex_unlock(&st->lock); | |
5e1a1da0 EH |
546 | |
547 | iio_device_release_direct_mode(indio_dev); | |
27e17719 LD |
548 | return ret; |
549 | ||
550 | case IIO_CHAN_INFO_SCALE: | |
551 | *val = st->vref_uv / 1000; | |
d6511322 LD |
552 | if (chan->differential) |
553 | *val *= 2; | |
27e17719 LD |
554 | *val2 = chan->scan_type.realbits; |
555 | return IIO_VAL_FRACTIONAL_LOG2; | |
556 | ||
557 | case IIO_CHAN_INFO_SAMP_FREQ: | |
558 | *val = at91_adc_get_sample_freq(st); | |
559 | return IIO_VAL_INT; | |
560 | ||
561 | default: | |
562 | return -EINVAL; | |
563 | } | |
564 | } | |
565 | ||
566 | static int at91_adc_write_raw(struct iio_dev *indio_dev, | |
567 | struct iio_chan_spec const *chan, | |
568 | int val, int val2, long mask) | |
569 | { | |
570 | struct at91_adc_state *st = iio_priv(indio_dev); | |
571 | ||
572 | if (mask != IIO_CHAN_INFO_SAMP_FREQ) | |
573 | return -EINVAL; | |
574 | ||
575 | if (val < st->soc_info.min_sample_rate || | |
576 | val > st->soc_info.max_sample_rate) | |
577 | return -EINVAL; | |
578 | ||
579 | at91_adc_setup_samp_freq(st, val); | |
580 | ||
581 | return 0; | |
582 | } | |
583 | ||
584 | static const struct iio_info at91_adc_info = { | |
585 | .read_raw = &at91_adc_read_raw, | |
586 | .write_raw = &at91_adc_write_raw, | |
587 | .driver_module = THIS_MODULE, | |
588 | }; | |
589 | ||
500a2eef EH |
590 | static void at91_adc_hw_init(struct at91_adc_state *st) |
591 | { | |
592 | at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST); | |
593 | at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff); | |
594 | /* | |
595 | * Transfer field must be set to 2 according to the datasheet and | |
596 | * allows different analog settings for each channel. | |
597 | */ | |
598 | at91_adc_writel(st, AT91_SAMA5D2_MR, | |
599 | AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH); | |
600 | ||
601 | at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate); | |
602 | } | |
603 | ||
27e17719 LD |
604 | static int at91_adc_probe(struct platform_device *pdev) |
605 | { | |
606 | struct iio_dev *indio_dev; | |
607 | struct at91_adc_state *st; | |
608 | struct resource *res; | |
5e1a1da0 | 609 | int ret, i; |
ca4c3023 | 610 | u32 edge_type = IRQ_TYPE_NONE; |
27e17719 | 611 | |
61be8fde | 612 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st)); |
27e17719 LD |
613 | if (!indio_dev) |
614 | return -ENOMEM; | |
615 | ||
616 | indio_dev->dev.parent = &pdev->dev; | |
617 | indio_dev->name = dev_name(&pdev->dev); | |
618 | indio_dev->modes = INDIO_DIRECT_MODE; | |
619 | indio_dev->info = &at91_adc_info; | |
620 | indio_dev->channels = at91_adc_channels; | |
621 | indio_dev->num_channels = ARRAY_SIZE(at91_adc_channels); | |
622 | ||
623 | st = iio_priv(indio_dev); | |
624 | ||
625 | ret = of_property_read_u32(pdev->dev.of_node, | |
626 | "atmel,min-sample-rate-hz", | |
627 | &st->soc_info.min_sample_rate); | |
628 | if (ret) { | |
629 | dev_err(&pdev->dev, | |
630 | "invalid or missing value for atmel,min-sample-rate-hz\n"); | |
631 | return ret; | |
632 | } | |
633 | ||
634 | ret = of_property_read_u32(pdev->dev.of_node, | |
635 | "atmel,max-sample-rate-hz", | |
636 | &st->soc_info.max_sample_rate); | |
637 | if (ret) { | |
638 | dev_err(&pdev->dev, | |
639 | "invalid or missing value for atmel,max-sample-rate-hz\n"); | |
640 | return ret; | |
641 | } | |
642 | ||
643 | ret = of_property_read_u32(pdev->dev.of_node, "atmel,startup-time-ms", | |
644 | &st->soc_info.startup_time); | |
645 | if (ret) { | |
646 | dev_err(&pdev->dev, | |
647 | "invalid or missing value for atmel,startup-time-ms\n"); | |
648 | return ret; | |
649 | } | |
650 | ||
5e1a1da0 EH |
651 | ret = of_property_read_u32(pdev->dev.of_node, |
652 | "atmel,trigger-edge-type", &edge_type); | |
653 | if (ret) { | |
ca4c3023 EH |
654 | dev_dbg(&pdev->dev, |
655 | "atmel,trigger-edge-type not specified, only software trigger available\n"); | |
5e1a1da0 EH |
656 | } |
657 | ||
658 | st->selected_trig = NULL; | |
659 | ||
ca4c3023 EH |
660 | /* find the right trigger, or no trigger at all */ |
661 | for (i = 0; i < AT91_SAMA5D2_HW_TRIG_CNT + 1; i++) | |
5e1a1da0 EH |
662 | if (at91_adc_trigger_list[i].edge_type == edge_type) { |
663 | st->selected_trig = &at91_adc_trigger_list[i]; | |
664 | break; | |
665 | } | |
666 | ||
667 | if (!st->selected_trig) { | |
668 | dev_err(&pdev->dev, "invalid external trigger edge value\n"); | |
669 | return -EINVAL; | |
670 | } | |
671 | ||
27e17719 LD |
672 | init_waitqueue_head(&st->wq_data_available); |
673 | mutex_init(&st->lock); | |
674 | ||
675 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
676 | if (!res) | |
677 | return -EINVAL; | |
678 | ||
679 | st->base = devm_ioremap_resource(&pdev->dev, res); | |
680 | if (IS_ERR(st->base)) | |
681 | return PTR_ERR(st->base); | |
682 | ||
683 | st->irq = platform_get_irq(pdev, 0); | |
684 | if (st->irq <= 0) { | |
685 | if (!st->irq) | |
686 | st->irq = -ENXIO; | |
687 | ||
688 | return st->irq; | |
689 | } | |
690 | ||
691 | st->per_clk = devm_clk_get(&pdev->dev, "adc_clk"); | |
692 | if (IS_ERR(st->per_clk)) | |
693 | return PTR_ERR(st->per_clk); | |
694 | ||
695 | st->reg = devm_regulator_get(&pdev->dev, "vddana"); | |
696 | if (IS_ERR(st->reg)) | |
697 | return PTR_ERR(st->reg); | |
698 | ||
699 | st->vref = devm_regulator_get(&pdev->dev, "vref"); | |
700 | if (IS_ERR(st->vref)) | |
701 | return PTR_ERR(st->vref); | |
702 | ||
703 | ret = devm_request_irq(&pdev->dev, st->irq, at91_adc_interrupt, 0, | |
704 | pdev->dev.driver->name, indio_dev); | |
705 | if (ret) | |
706 | return ret; | |
707 | ||
708 | ret = regulator_enable(st->reg); | |
709 | if (ret) | |
710 | return ret; | |
711 | ||
712 | ret = regulator_enable(st->vref); | |
713 | if (ret) | |
714 | goto reg_disable; | |
715 | ||
716 | st->vref_uv = regulator_get_voltage(st->vref); | |
717 | if (st->vref_uv <= 0) { | |
718 | ret = -EINVAL; | |
719 | goto vref_disable; | |
720 | } | |
721 | ||
500a2eef | 722 | at91_adc_hw_init(st); |
27e17719 LD |
723 | |
724 | ret = clk_prepare_enable(st->per_clk); | |
725 | if (ret) | |
726 | goto vref_disable; | |
727 | ||
8e6cb470 MV |
728 | platform_set_drvdata(pdev, indio_dev); |
729 | ||
ca4c3023 EH |
730 | if (st->selected_trig->hw_trig) { |
731 | ret = at91_adc_buffer_init(indio_dev); | |
732 | if (ret < 0) { | |
733 | dev_err(&pdev->dev, "couldn't initialize the buffer.\n"); | |
734 | goto per_clk_disable_unprepare; | |
735 | } | |
5e1a1da0 | 736 | |
ca4c3023 EH |
737 | ret = at91_adc_trigger_init(indio_dev); |
738 | if (ret < 0) { | |
739 | dev_err(&pdev->dev, "couldn't setup the triggers.\n"); | |
740 | goto per_clk_disable_unprepare; | |
741 | } | |
5e1a1da0 EH |
742 | } |
743 | ||
27e17719 LD |
744 | ret = iio_device_register(indio_dev); |
745 | if (ret < 0) | |
746 | goto per_clk_disable_unprepare; | |
747 | ||
ca4c3023 EH |
748 | if (st->selected_trig->hw_trig) |
749 | dev_info(&pdev->dev, "setting up trigger as %s\n", | |
750 | st->selected_trig->name); | |
5e1a1da0 | 751 | |
27e17719 LD |
752 | dev_info(&pdev->dev, "version: %x\n", |
753 | readl_relaxed(st->base + AT91_SAMA5D2_VERSION)); | |
754 | ||
755 | return 0; | |
756 | ||
757 | per_clk_disable_unprepare: | |
758 | clk_disable_unprepare(st->per_clk); | |
759 | vref_disable: | |
760 | regulator_disable(st->vref); | |
761 | reg_disable: | |
762 | regulator_disable(st->reg); | |
763 | return ret; | |
764 | } | |
765 | ||
766 | static int at91_adc_remove(struct platform_device *pdev) | |
767 | { | |
768 | struct iio_dev *indio_dev = platform_get_drvdata(pdev); | |
769 | struct at91_adc_state *st = iio_priv(indio_dev); | |
770 | ||
771 | iio_device_unregister(indio_dev); | |
772 | ||
773 | clk_disable_unprepare(st->per_clk); | |
774 | ||
775 | regulator_disable(st->vref); | |
776 | regulator_disable(st->reg); | |
777 | ||
778 | return 0; | |
779 | } | |
780 | ||
500a2eef EH |
781 | static __maybe_unused int at91_adc_suspend(struct device *dev) |
782 | { | |
783 | struct iio_dev *indio_dev = | |
784 | platform_get_drvdata(to_platform_device(dev)); | |
785 | struct at91_adc_state *st = iio_priv(indio_dev); | |
786 | ||
787 | /* | |
788 | * Do a sofware reset of the ADC before we go to suspend. | |
789 | * this will ensure that all pins are free from being muxed by the ADC | |
790 | * and can be used by for other devices. | |
791 | * Otherwise, ADC will hog them and we can't go to suspend mode. | |
792 | */ | |
793 | at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST); | |
794 | ||
795 | clk_disable_unprepare(st->per_clk); | |
796 | regulator_disable(st->vref); | |
797 | regulator_disable(st->reg); | |
798 | ||
799 | return pinctrl_pm_select_sleep_state(dev); | |
800 | } | |
801 | ||
802 | static __maybe_unused int at91_adc_resume(struct device *dev) | |
803 | { | |
804 | struct iio_dev *indio_dev = | |
805 | platform_get_drvdata(to_platform_device(dev)); | |
806 | struct at91_adc_state *st = iio_priv(indio_dev); | |
807 | int ret; | |
808 | ||
809 | ret = pinctrl_pm_select_default_state(dev); | |
810 | if (ret) | |
811 | goto resume_failed; | |
812 | ||
813 | ret = regulator_enable(st->reg); | |
814 | if (ret) | |
815 | goto resume_failed; | |
816 | ||
817 | ret = regulator_enable(st->vref); | |
818 | if (ret) | |
819 | goto reg_disable_resume; | |
820 | ||
821 | ret = clk_prepare_enable(st->per_clk); | |
822 | if (ret) | |
823 | goto vref_disable_resume; | |
824 | ||
825 | at91_adc_hw_init(st); | |
826 | ||
827 | /* reconfiguring trigger hardware state */ | |
828 | if (iio_buffer_enabled(indio_dev)) | |
829 | at91_adc_configure_trigger(st->trig, true); | |
830 | ||
831 | return 0; | |
832 | ||
833 | vref_disable_resume: | |
834 | regulator_disable(st->vref); | |
835 | reg_disable_resume: | |
836 | regulator_disable(st->reg); | |
837 | resume_failed: | |
838 | dev_err(&indio_dev->dev, "failed to resume\n"); | |
839 | return ret; | |
840 | } | |
841 | ||
842 | static SIMPLE_DEV_PM_OPS(at91_adc_pm_ops, at91_adc_suspend, at91_adc_resume); | |
843 | ||
27e17719 LD |
844 | static const struct of_device_id at91_adc_dt_match[] = { |
845 | { | |
846 | .compatible = "atmel,sama5d2-adc", | |
847 | }, { | |
848 | /* sentinel */ | |
849 | } | |
850 | }; | |
851 | MODULE_DEVICE_TABLE(of, at91_adc_dt_match); | |
852 | ||
853 | static struct platform_driver at91_adc_driver = { | |
854 | .probe = at91_adc_probe, | |
855 | .remove = at91_adc_remove, | |
856 | .driver = { | |
857 | .name = "at91-sama5d2_adc", | |
858 | .of_match_table = at91_adc_dt_match, | |
500a2eef | 859 | .pm = &at91_adc_pm_ops, |
27e17719 LD |
860 | }, |
861 | }; | |
862 | module_platform_driver(at91_adc_driver) | |
863 | ||
864 | MODULE_AUTHOR("Ludovic Desroches <ludovic.desroches@atmel.com>"); | |
865 | MODULE_DESCRIPTION("Atmel AT91 SAMA5D2 ADC"); | |
866 | MODULE_LICENSE("GPL v2"); |