1 | // SPDX-License-Identifier: GPL-2.0 |
---|---|
2 | /* |
3 | * This file is the ADC part of the STM32 DFSDM driver |
4 | * |
5 | * Copyright (C) 2017, STMicroelectronics - All Rights Reserved |
6 | * Author: Arnaud Pouliquen <arnaud.pouliquen@st.com>. |
7 | */ |
8 | |
9 | #include <linux/dmaengine.h> |
10 | #include <linux/dma-mapping.h> |
11 | #include <linux/iio/adc/stm32-dfsdm-adc.h> |
12 | #include <linux/iio/buffer.h> |
13 | #include <linux/iio/hw-consumer.h> |
14 | #include <linux/iio/sysfs.h> |
15 | #include <linux/iio/timer/stm32-lptim-trigger.h> |
16 | #include <linux/iio/timer/stm32-timer-trigger.h> |
17 | #include <linux/iio/trigger.h> |
18 | #include <linux/iio/trigger_consumer.h> |
19 | #include <linux/iio/triggered_buffer.h> |
20 | #include <linux/interrupt.h> |
21 | #include <linux/module.h> |
22 | #include <linux/of.h> |
23 | #include <linux/of_platform.h> |
24 | #include <linux/platform_device.h> |
25 | #include <linux/regmap.h> |
26 | #include <linux/slab.h> |
27 | |
28 | #include "stm32-dfsdm.h" |
29 | |
30 | #define DFSDM_DMA_BUFFER_SIZE (4 * PAGE_SIZE) |
31 | |
32 | /* Conversion timeout */ |
33 | #define DFSDM_TIMEOUT_US 100000 |
34 | #define DFSDM_TIMEOUT (msecs_to_jiffies(DFSDM_TIMEOUT_US / 1000)) |
35 | |
36 | /* Oversampling attribute default */ |
37 | #define DFSDM_DEFAULT_OVERSAMPLING 100 |
38 | |
39 | /* Oversampling max values */ |
40 | #define DFSDM_MAX_INT_OVERSAMPLING 256 |
41 | #define DFSDM_MAX_FL_OVERSAMPLING 1024 |
42 | |
43 | /* Limit filter output resolution to 31 bits. (i.e. sample range is +/-2^30) */ |
44 | #define DFSDM_DATA_MAX BIT(30) |
45 | /* |
46 | * Data are output as two's complement data in a 24 bit field. |
47 | * Data from filters are in the range +/-2^(n-1) |
48 | * 2^(n-1) maximum positive value cannot be coded in 2's complement n bits |
49 | * An extra bit is required to avoid wrap-around of the binary code for 2^(n-1) |
50 | * So, the resolution of samples from filter is actually limited to 23 bits |
51 | */ |
52 | #define DFSDM_DATA_RES 24 |
53 | |
54 | /* Filter configuration */ |
55 | #define DFSDM_CR1_CFG_MASK (DFSDM_CR1_RCH_MASK | DFSDM_CR1_RCONT_MASK | \ |
56 | DFSDM_CR1_RSYNC_MASK | DFSDM_CR1_JSYNC_MASK | \ |
57 | DFSDM_CR1_JSCAN_MASK) |
58 | |
59 | enum sd_converter_type { |
60 | DFSDM_AUDIO, |
61 | DFSDM_IIO, |
62 | }; |
63 | |
64 | struct stm32_dfsdm_dev_data { |
65 | int type; |
66 | int (*init)(struct device *dev, struct iio_dev *indio_dev); |
67 | unsigned int num_channels; |
68 | const struct regmap_config *regmap_cfg; |
69 | }; |
70 | |
71 | struct stm32_dfsdm_adc { |
72 | struct stm32_dfsdm *dfsdm; |
73 | const struct stm32_dfsdm_dev_data *dev_data; |
74 | unsigned int fl_id; |
75 | unsigned int nconv; |
76 | unsigned long smask; |
77 | |
78 | /* ADC specific */ |
79 | unsigned int oversamp; |
80 | struct iio_hw_consumer *hwc; |
81 | struct completion completion; |
82 | u32 *buffer; |
83 | |
84 | /* Audio specific */ |
85 | unsigned int spi_freq; /* SPI bus clock frequency */ |
86 | unsigned int sample_freq; /* Sample frequency after filter decimation */ |
87 | int (*cb)(const void *data, size_t size, void *cb_priv); |
88 | void *cb_priv; |
89 | |
90 | /* DMA */ |
91 | u8 *rx_buf; |
92 | unsigned int bufi; /* Buffer current position */ |
93 | unsigned int buf_sz; /* Buffer size */ |
94 | struct dma_chan *dma_chan; |
95 | dma_addr_t dma_buf; |
96 | }; |
97 | |
98 | struct stm32_dfsdm_str2field { |
99 | const char *name; |
100 | unsigned int val; |
101 | }; |
102 | |
103 | /* DFSDM channel serial interface type */ |
104 | static const struct stm32_dfsdm_str2field stm32_dfsdm_chan_type[] = { |
105 | { "SPI_R", 0 }, /* SPI with data on rising edge */ |
106 | { "SPI_F", 1 }, /* SPI with data on falling edge */ |
107 | { "MANCH_R", 2 }, /* Manchester codec, rising edge = logic 0 */ |
108 | { "MANCH_F", 3 }, /* Manchester codec, falling edge = logic 1 */ |
109 | {}, |
110 | }; |
111 | |
112 | /* DFSDM channel clock source */ |
113 | static const struct stm32_dfsdm_str2field stm32_dfsdm_chan_src[] = { |
114 | /* External SPI clock (CLKIN x) */ |
115 | { "CLKIN", DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL }, |
116 | /* Internal SPI clock (CLKOUT) */ |
117 | { "CLKOUT", DFSDM_CHANNEL_SPI_CLOCK_INTERNAL }, |
118 | /* Internal SPI clock divided by 2 (falling edge) */ |
119 | { "CLKOUT_F", DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING }, |
120 | /* Internal SPI clock divided by 2 (falling edge) */ |
121 | { "CLKOUT_R", DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING }, |
122 | {}, |
123 | }; |
124 | |
125 | static int stm32_dfsdm_str2val(const char *str, |
126 | const struct stm32_dfsdm_str2field *list) |
127 | { |
128 | const struct stm32_dfsdm_str2field *p = list; |
129 | |
130 | for (p = list; p && p->name; p++) |
131 | if (!strcmp(p->name, str)) |
132 | return p->val; |
133 | |
134 | return -EINVAL; |
135 | } |
136 | |
137 | /** |
138 | * struct stm32_dfsdm_trig_info - DFSDM trigger info |
139 | * @name: name of the trigger, corresponding to its source |
140 | * @jextsel: trigger signal selection |
141 | */ |
142 | struct stm32_dfsdm_trig_info { |
143 | const char *name; |
144 | unsigned int jextsel; |
145 | }; |
146 | |
147 | /* hardware injected trigger enable, edge selection */ |
148 | enum stm32_dfsdm_jexten { |
149 | STM32_DFSDM_JEXTEN_DISABLED, |
150 | STM32_DFSDM_JEXTEN_RISING_EDGE, |
151 | STM32_DFSDM_JEXTEN_FALLING_EDGE, |
152 | STM32_DFSDM_EXTEN_BOTH_EDGES, |
153 | }; |
154 | |
155 | static const struct stm32_dfsdm_trig_info stm32_dfsdm_trigs[] = { |
156 | { TIM1_TRGO, 0 }, |
157 | { TIM1_TRGO2, 1 }, |
158 | { TIM8_TRGO, 2 }, |
159 | { TIM8_TRGO2, 3 }, |
160 | { TIM3_TRGO, 4 }, |
161 | { TIM4_TRGO, 5 }, |
162 | { TIM16_OC1, 6 }, |
163 | { TIM6_TRGO, 7 }, |
164 | { TIM7_TRGO, 8 }, |
165 | { LPTIM1_OUT, 26 }, |
166 | { LPTIM2_OUT, 27 }, |
167 | { LPTIM3_OUT, 28 }, |
168 | {}, |
169 | }; |
170 | |
171 | static int stm32_dfsdm_get_jextsel(struct iio_dev *indio_dev, |
172 | struct iio_trigger *trig) |
173 | { |
174 | int i; |
175 | |
176 | /* lookup triggers registered by stm32 timer trigger driver */ |
177 | for (i = 0; stm32_dfsdm_trigs[i].name; i++) { |
178 | /** |
179 | * Checking both stm32 timer trigger type and trig name |
180 | * should be safe against arbitrary trigger names. |
181 | */ |
182 | if ((is_stm32_timer_trigger(trig) || |
183 | is_stm32_lptim_trigger(trig)) && |
184 | !strcmp(stm32_dfsdm_trigs[i].name, trig->name)) { |
185 | return stm32_dfsdm_trigs[i].jextsel; |
186 | } |
187 | } |
188 | |
189 | return -EINVAL; |
190 | } |
191 | |
192 | static int stm32_dfsdm_compute_osrs(struct stm32_dfsdm_filter *fl, |
193 | unsigned int fast, unsigned int oversamp) |
194 | { |
195 | unsigned int i, d, fosr, iosr; |
196 | u64 res, max; |
197 | int bits, shift; |
198 | unsigned int m = 1; /* multiplication factor */ |
199 | unsigned int p = fl->ford; /* filter order (ford) */ |
200 | struct stm32_dfsdm_filter_osr *flo = &fl->flo[fast]; |
201 | |
202 | pr_debug("Requested oversampling: %d\n", oversamp); |
203 | /* |
204 | * This function tries to compute filter oversampling and integrator |
205 | * oversampling, base on oversampling ratio requested by user. |
206 | * |
207 | * Decimation d depends on the filter order and the oversampling ratios. |
208 | * ford: filter order |
209 | * fosr: filter over sampling ratio |
210 | * iosr: integrator over sampling ratio |
211 | */ |
212 | if (fl->ford == DFSDM_FASTSINC_ORDER) { |
213 | m = 2; |
214 | p = 2; |
215 | } |
216 | |
217 | /* |
218 | * Look for filter and integrator oversampling ratios which allows |
219 | * to maximize data output resolution. |
220 | */ |
221 | for (fosr = 1; fosr <= DFSDM_MAX_FL_OVERSAMPLING; fosr++) { |
222 | for (iosr = 1; iosr <= DFSDM_MAX_INT_OVERSAMPLING; iosr++) { |
223 | if (fast) |
224 | d = fosr * iosr; |
225 | else if (fl->ford == DFSDM_FASTSINC_ORDER) |
226 | d = fosr * (iosr + 3) + 2; |
227 | else |
228 | d = fosr * (iosr - 1 + p) + p; |
229 | |
230 | if (d > oversamp) |
231 | break; |
232 | else if (d != oversamp) |
233 | continue; |
234 | /* |
235 | * Check resolution (limited to signed 32 bits) |
236 | * res <= 2^31 |
237 | * Sincx filters: |
238 | * res = m * fosr^p x iosr (with m=1, p=ford) |
239 | * FastSinc filter |
240 | * res = m * fosr^p x iosr (with m=2, p=2) |
241 | */ |
242 | res = fosr; |
243 | for (i = p - 1; i > 0; i--) { |
244 | res = res * (u64)fosr; |
245 | if (res > DFSDM_DATA_MAX) |
246 | break; |
247 | } |
248 | if (res > DFSDM_DATA_MAX) |
249 | continue; |
250 | |
251 | res = res * (u64)m * (u64)iosr; |
252 | if (res > DFSDM_DATA_MAX) |
253 | continue; |
254 | |
255 | if (res >= flo->res) { |
256 | flo->res = res; |
257 | flo->fosr = fosr; |
258 | flo->iosr = iosr; |
259 | |
260 | bits = fls(x: flo->res); |
261 | /* 8 LBSs in data register contain chan info */ |
262 | max = flo->res << 8; |
263 | |
264 | /* if resolution is not a power of two */ |
265 | if (flo->res > BIT(bits - 1)) |
266 | bits++; |
267 | else |
268 | max--; |
269 | |
270 | shift = DFSDM_DATA_RES - bits; |
271 | /* |
272 | * Compute right/left shift |
273 | * Right shift is performed by hardware |
274 | * when transferring samples to data register. |
275 | * Left shift is done by software on buffer |
276 | */ |
277 | if (shift > 0) { |
278 | /* Resolution is lower than 24 bits */ |
279 | flo->rshift = 0; |
280 | flo->lshift = shift; |
281 | } else { |
282 | /* |
283 | * If resolution is 24 bits or more, |
284 | * max positive value may be ambiguous |
285 | * (equal to max negative value as sign |
286 | * bit is dropped). |
287 | * Reduce resolution to 23 bits (rshift) |
288 | * to keep the sign on bit 23 and treat |
289 | * saturation before rescaling on 24 |
290 | * bits (lshift). |
291 | */ |
292 | flo->rshift = 1 - shift; |
293 | flo->lshift = 1; |
294 | max >>= flo->rshift; |
295 | } |
296 | flo->max = (s32)max; |
297 | flo->bits = bits; |
298 | |
299 | pr_debug("fast %d, fosr %d, iosr %d, res 0x%llx/%d bits, rshift %d, lshift %d\n", |
300 | fast, flo->fosr, flo->iosr, |
301 | flo->res, bits, flo->rshift, |
302 | flo->lshift); |
303 | } |
304 | } |
305 | } |
306 | |
307 | if (!flo->res) |
308 | return -EINVAL; |
309 | |
310 | return 0; |
311 | } |
312 | |
313 | static int stm32_dfsdm_compute_all_osrs(struct iio_dev *indio_dev, |
314 | unsigned int oversamp) |
315 | { |
316 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
317 | struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id]; |
318 | int ret0, ret1; |
319 | |
320 | memset(&fl->flo[0], 0, sizeof(fl->flo[0])); |
321 | memset(&fl->flo[1], 0, sizeof(fl->flo[1])); |
322 | |
323 | ret0 = stm32_dfsdm_compute_osrs(fl, fast: 0, oversamp); |
324 | ret1 = stm32_dfsdm_compute_osrs(fl, fast: 1, oversamp); |
325 | if (ret0 < 0 && ret1 < 0) { |
326 | dev_err(&indio_dev->dev, |
327 | "Filter parameters not found: errors %d/%d\n", |
328 | ret0, ret1); |
329 | return -EINVAL; |
330 | } |
331 | |
332 | return 0; |
333 | } |
334 | |
335 | static int stm32_dfsdm_start_channel(struct iio_dev *indio_dev) |
336 | { |
337 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
338 | struct regmap *regmap = adc->dfsdm->regmap; |
339 | const struct iio_chan_spec *chan; |
340 | unsigned int bit; |
341 | int ret; |
342 | |
343 | for_each_set_bit(bit, &adc->smask, sizeof(adc->smask) * BITS_PER_BYTE) { |
344 | chan = indio_dev->channels + bit; |
345 | ret = regmap_update_bits(map: regmap, DFSDM_CHCFGR1(chan->channel), |
346 | DFSDM_CHCFGR1_CHEN_MASK, |
347 | DFSDM_CHCFGR1_CHEN(1)); |
348 | if (ret < 0) |
349 | return ret; |
350 | } |
351 | |
352 | return 0; |
353 | } |
354 | |
355 | static void stm32_dfsdm_stop_channel(struct iio_dev *indio_dev) |
356 | { |
357 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
358 | struct regmap *regmap = adc->dfsdm->regmap; |
359 | const struct iio_chan_spec *chan; |
360 | unsigned int bit; |
361 | |
362 | for_each_set_bit(bit, &adc->smask, sizeof(adc->smask) * BITS_PER_BYTE) { |
363 | chan = indio_dev->channels + bit; |
364 | regmap_update_bits(map: regmap, DFSDM_CHCFGR1(chan->channel), |
365 | DFSDM_CHCFGR1_CHEN_MASK, |
366 | DFSDM_CHCFGR1_CHEN(0)); |
367 | } |
368 | } |
369 | |
370 | static int stm32_dfsdm_chan_configure(struct stm32_dfsdm *dfsdm, |
371 | struct stm32_dfsdm_channel *ch) |
372 | { |
373 | unsigned int id = ch->id; |
374 | struct regmap *regmap = dfsdm->regmap; |
375 | int ret; |
376 | |
377 | ret = regmap_update_bits(map: regmap, DFSDM_CHCFGR1(id), |
378 | DFSDM_CHCFGR1_SITP_MASK, |
379 | DFSDM_CHCFGR1_SITP(ch->type)); |
380 | if (ret < 0) |
381 | return ret; |
382 | ret = regmap_update_bits(map: regmap, DFSDM_CHCFGR1(id), |
383 | DFSDM_CHCFGR1_SPICKSEL_MASK, |
384 | DFSDM_CHCFGR1_SPICKSEL(ch->src)); |
385 | if (ret < 0) |
386 | return ret; |
387 | return regmap_update_bits(map: regmap, DFSDM_CHCFGR1(id), |
388 | DFSDM_CHCFGR1_CHINSEL_MASK, |
389 | DFSDM_CHCFGR1_CHINSEL(ch->alt_si)); |
390 | } |
391 | |
392 | static int stm32_dfsdm_start_filter(struct stm32_dfsdm_adc *adc, |
393 | unsigned int fl_id, |
394 | struct iio_trigger *trig) |
395 | { |
396 | struct stm32_dfsdm *dfsdm = adc->dfsdm; |
397 | int ret; |
398 | |
399 | /* Enable filter */ |
400 | ret = regmap_update_bits(map: dfsdm->regmap, DFSDM_CR1(fl_id), |
401 | DFSDM_CR1_DFEN_MASK, DFSDM_CR1_DFEN(1)); |
402 | if (ret < 0) |
403 | return ret; |
404 | |
405 | /* Nothing more to do for injected (scan mode/triggered) conversions */ |
406 | if (adc->nconv > 1 || trig) |
407 | return 0; |
408 | |
409 | /* Software start (single or continuous) regular conversion */ |
410 | return regmap_update_bits(map: dfsdm->regmap, DFSDM_CR1(fl_id), |
411 | DFSDM_CR1_RSWSTART_MASK, |
412 | DFSDM_CR1_RSWSTART(1)); |
413 | } |
414 | |
415 | static void stm32_dfsdm_stop_filter(struct stm32_dfsdm *dfsdm, |
416 | unsigned int fl_id) |
417 | { |
418 | /* Disable conversion */ |
419 | regmap_update_bits(map: dfsdm->regmap, DFSDM_CR1(fl_id), |
420 | DFSDM_CR1_DFEN_MASK, DFSDM_CR1_DFEN(0)); |
421 | } |
422 | |
423 | static int stm32_dfsdm_filter_set_trig(struct iio_dev *indio_dev, |
424 | unsigned int fl_id, |
425 | struct iio_trigger *trig) |
426 | { |
427 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
428 | struct regmap *regmap = adc->dfsdm->regmap; |
429 | u32 jextsel = 0, jexten = STM32_DFSDM_JEXTEN_DISABLED; |
430 | int ret; |
431 | |
432 | if (trig) { |
433 | ret = stm32_dfsdm_get_jextsel(indio_dev, trig); |
434 | if (ret < 0) |
435 | return ret; |
436 | |
437 | /* set trigger source and polarity (default to rising edge) */ |
438 | jextsel = ret; |
439 | jexten = STM32_DFSDM_JEXTEN_RISING_EDGE; |
440 | } |
441 | |
442 | ret = regmap_update_bits(map: regmap, DFSDM_CR1(fl_id), |
443 | DFSDM_CR1_JEXTSEL_MASK | DFSDM_CR1_JEXTEN_MASK, |
444 | DFSDM_CR1_JEXTSEL(jextsel) | |
445 | DFSDM_CR1_JEXTEN(jexten)); |
446 | if (ret < 0) |
447 | return ret; |
448 | |
449 | return 0; |
450 | } |
451 | |
452 | static int stm32_dfsdm_channels_configure(struct iio_dev *indio_dev, |
453 | unsigned int fl_id, |
454 | struct iio_trigger *trig) |
455 | { |
456 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
457 | struct regmap *regmap = adc->dfsdm->regmap; |
458 | struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id]; |
459 | struct stm32_dfsdm_filter_osr *flo = &fl->flo[0]; |
460 | const struct iio_chan_spec *chan; |
461 | unsigned int bit; |
462 | int ret; |
463 | |
464 | fl->fast = 0; |
465 | |
466 | /* |
467 | * In continuous mode, use fast mode configuration, |
468 | * if it provides a better resolution. |
469 | */ |
470 | if (adc->nconv == 1 && !trig && iio_buffer_enabled(indio_dev)) { |
471 | if (fl->flo[1].res >= fl->flo[0].res) { |
472 | fl->fast = 1; |
473 | flo = &fl->flo[1]; |
474 | } |
475 | } |
476 | |
477 | if (!flo->res) |
478 | return -EINVAL; |
479 | |
480 | dev_dbg(&indio_dev->dev, "Samples actual resolution: %d bits", |
481 | min(flo->bits, (u32)DFSDM_DATA_RES - 1)); |
482 | |
483 | for_each_set_bit(bit, &adc->smask, |
484 | sizeof(adc->smask) * BITS_PER_BYTE) { |
485 | chan = indio_dev->channels + bit; |
486 | |
487 | ret = regmap_update_bits(map: regmap, |
488 | DFSDM_CHCFGR2(chan->channel), |
489 | DFSDM_CHCFGR2_DTRBS_MASK, |
490 | DFSDM_CHCFGR2_DTRBS(flo->rshift)); |
491 | if (ret) |
492 | return ret; |
493 | } |
494 | |
495 | return 0; |
496 | } |
497 | |
498 | static int stm32_dfsdm_filter_configure(struct iio_dev *indio_dev, |
499 | unsigned int fl_id, |
500 | struct iio_trigger *trig) |
501 | { |
502 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
503 | struct regmap *regmap = adc->dfsdm->regmap; |
504 | struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id]; |
505 | struct stm32_dfsdm_filter_osr *flo = &fl->flo[fl->fast]; |
506 | u32 cr1; |
507 | const struct iio_chan_spec *chan; |
508 | unsigned int bit, jchg = 0; |
509 | int ret; |
510 | |
511 | /* Average integrator oversampling */ |
512 | ret = regmap_update_bits(map: regmap, DFSDM_FCR(fl_id), DFSDM_FCR_IOSR_MASK, |
513 | DFSDM_FCR_IOSR(flo->iosr - 1)); |
514 | if (ret) |
515 | return ret; |
516 | |
517 | /* Filter order and Oversampling */ |
518 | ret = regmap_update_bits(map: regmap, DFSDM_FCR(fl_id), DFSDM_FCR_FOSR_MASK, |
519 | DFSDM_FCR_FOSR(flo->fosr - 1)); |
520 | if (ret) |
521 | return ret; |
522 | |
523 | ret = regmap_update_bits(map: regmap, DFSDM_FCR(fl_id), DFSDM_FCR_FORD_MASK, |
524 | DFSDM_FCR_FORD(fl->ford)); |
525 | if (ret) |
526 | return ret; |
527 | |
528 | ret = stm32_dfsdm_filter_set_trig(indio_dev, fl_id, trig); |
529 | if (ret) |
530 | return ret; |
531 | |
532 | ret = regmap_update_bits(map: regmap, DFSDM_CR1(fl_id), |
533 | DFSDM_CR1_FAST_MASK, |
534 | DFSDM_CR1_FAST(fl->fast)); |
535 | if (ret) |
536 | return ret; |
537 | |
538 | /* |
539 | * DFSDM modes configuration W.R.T audio/iio type modes |
540 | * ---------------------------------------------------------------- |
541 | * Modes | regular | regular | injected | injected | |
542 | * | | continuous | | + scan | |
543 | * --------------|---------|--------------|----------|------------| |
544 | * single conv | x | | | | |
545 | * (1 chan) | | | | | |
546 | * --------------|---------|--------------|----------|------------| |
547 | * 1 Audio chan | | sample freq | | | |
548 | * | | or sync_mode | | | |
549 | * --------------|---------|--------------|----------|------------| |
550 | * 1 IIO chan | | sample freq | trigger | | |
551 | * | | or sync_mode | | | |
552 | * --------------|---------|--------------|----------|------------| |
553 | * 2+ IIO chans | | | | trigger or | |
554 | * | | | | sync_mode | |
555 | * ---------------------------------------------------------------- |
556 | */ |
557 | if (adc->nconv == 1 && !trig) { |
558 | bit = __ffs(adc->smask); |
559 | chan = indio_dev->channels + bit; |
560 | |
561 | /* Use regular conversion for single channel without trigger */ |
562 | cr1 = DFSDM_CR1_RCH(chan->channel); |
563 | |
564 | /* Continuous conversions triggered by SPI clk in buffer mode */ |
565 | if (iio_buffer_enabled(indio_dev)) |
566 | cr1 |= DFSDM_CR1_RCONT(1); |
567 | |
568 | cr1 |= DFSDM_CR1_RSYNC(fl->sync_mode); |
569 | } else { |
570 | /* Use injected conversion for multiple channels */ |
571 | for_each_set_bit(bit, &adc->smask, |
572 | sizeof(adc->smask) * BITS_PER_BYTE) { |
573 | chan = indio_dev->channels + bit; |
574 | jchg |= BIT(chan->channel); |
575 | } |
576 | ret = regmap_write(map: regmap, DFSDM_JCHGR(fl_id), val: jchg); |
577 | if (ret < 0) |
578 | return ret; |
579 | |
580 | /* Use scan mode for multiple channels */ |
581 | cr1 = DFSDM_CR1_JSCAN((adc->nconv > 1) ? 1 : 0); |
582 | |
583 | /* |
584 | * Continuous conversions not supported in injected mode, |
585 | * either use: |
586 | * - conversions in sync with filter 0 |
587 | * - triggered conversions |
588 | */ |
589 | if (!fl->sync_mode && !trig) |
590 | return -EINVAL; |
591 | cr1 |= DFSDM_CR1_JSYNC(fl->sync_mode); |
592 | } |
593 | |
594 | return regmap_update_bits(map: regmap, DFSDM_CR1(fl_id), DFSDM_CR1_CFG_MASK, |
595 | val: cr1); |
596 | } |
597 | |
598 | static int stm32_dfsdm_channel_parse_of(struct stm32_dfsdm *dfsdm, |
599 | struct iio_dev *indio_dev, |
600 | struct iio_chan_spec *ch) |
601 | { |
602 | struct stm32_dfsdm_channel *df_ch; |
603 | const char *of_str; |
604 | int chan_idx = ch->scan_index; |
605 | int ret, val; |
606 | |
607 | ret = of_property_read_u32_index(np: indio_dev->dev.of_node, |
608 | propname: "st,adc-channels", index: chan_idx, |
609 | out_value: &ch->channel); |
610 | if (ret < 0) { |
611 | dev_err(&indio_dev->dev, |
612 | " Error parsing 'st,adc-channels' for idx %d\n", |
613 | chan_idx); |
614 | return ret; |
615 | } |
616 | if (ch->channel >= dfsdm->num_chs) { |
617 | dev_err(&indio_dev->dev, |
618 | " Error bad channel number %d (max = %d)\n", |
619 | ch->channel, dfsdm->num_chs); |
620 | return -EINVAL; |
621 | } |
622 | |
623 | ret = of_property_read_string_index(np: indio_dev->dev.of_node, |
624 | propname: "st,adc-channel-names", index: chan_idx, |
625 | output: &ch->datasheet_name); |
626 | if (ret < 0) { |
627 | dev_err(&indio_dev->dev, |
628 | " Error parsing 'st,adc-channel-names' for idx %d\n", |
629 | chan_idx); |
630 | return ret; |
631 | } |
632 | |
633 | df_ch = &dfsdm->ch_list[ch->channel]; |
634 | df_ch->id = ch->channel; |
635 | |
636 | ret = of_property_read_string_index(np: indio_dev->dev.of_node, |
637 | propname: "st,adc-channel-types", index: chan_idx, |
638 | output: &of_str); |
639 | if (!ret) { |
640 | val = stm32_dfsdm_str2val(str: of_str, list: stm32_dfsdm_chan_type); |
641 | if (val < 0) |
642 | return val; |
643 | } else { |
644 | val = 0; |
645 | } |
646 | df_ch->type = val; |
647 | |
648 | ret = of_property_read_string_index(np: indio_dev->dev.of_node, |
649 | propname: "st,adc-channel-clk-src", index: chan_idx, |
650 | output: &of_str); |
651 | if (!ret) { |
652 | val = stm32_dfsdm_str2val(str: of_str, list: stm32_dfsdm_chan_src); |
653 | if (val < 0) |
654 | return val; |
655 | } else { |
656 | val = 0; |
657 | } |
658 | df_ch->src = val; |
659 | |
660 | ret = of_property_read_u32_index(np: indio_dev->dev.of_node, |
661 | propname: "st,adc-alt-channel", index: chan_idx, |
662 | out_value: &df_ch->alt_si); |
663 | if (ret < 0) |
664 | df_ch->alt_si = 0; |
665 | |
666 | return 0; |
667 | } |
668 | |
669 | static ssize_t dfsdm_adc_audio_get_spiclk(struct iio_dev *indio_dev, |
670 | uintptr_t priv, |
671 | const struct iio_chan_spec *chan, |
672 | char *buf) |
673 | { |
674 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
675 | |
676 | return snprintf(buf, PAGE_SIZE, fmt: "%d\n", adc->spi_freq); |
677 | } |
678 | |
679 | static int dfsdm_adc_set_samp_freq(struct iio_dev *indio_dev, |
680 | unsigned int sample_freq, |
681 | unsigned int spi_freq) |
682 | { |
683 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
684 | unsigned int oversamp; |
685 | int ret; |
686 | |
687 | oversamp = DIV_ROUND_CLOSEST(spi_freq, sample_freq); |
688 | if (spi_freq % sample_freq) |
689 | dev_dbg(&indio_dev->dev, |
690 | "Rate not accurate. requested (%u), actual (%u)\n", |
691 | sample_freq, spi_freq / oversamp); |
692 | |
693 | ret = stm32_dfsdm_compute_all_osrs(indio_dev, oversamp); |
694 | if (ret < 0) |
695 | return ret; |
696 | |
697 | adc->sample_freq = spi_freq / oversamp; |
698 | adc->oversamp = oversamp; |
699 | |
700 | return 0; |
701 | } |
702 | |
703 | static ssize_t dfsdm_adc_audio_set_spiclk(struct iio_dev *indio_dev, |
704 | uintptr_t priv, |
705 | const struct iio_chan_spec *chan, |
706 | const char *buf, size_t len) |
707 | { |
708 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
709 | struct stm32_dfsdm_channel *ch = &adc->dfsdm->ch_list[chan->channel]; |
710 | unsigned int sample_freq = adc->sample_freq; |
711 | unsigned int spi_freq; |
712 | int ret; |
713 | |
714 | dev_err(&indio_dev->dev, "enter %s\n", __func__); |
715 | /* If DFSDM is master on SPI, SPI freq can not be updated */ |
716 | if (ch->src != DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL) |
717 | return -EPERM; |
718 | |
719 | ret = kstrtoint(s: buf, base: 0, res: &spi_freq); |
720 | if (ret) |
721 | return ret; |
722 | |
723 | if (!spi_freq) |
724 | return -EINVAL; |
725 | |
726 | if (sample_freq) { |
727 | ret = dfsdm_adc_set_samp_freq(indio_dev, sample_freq, spi_freq); |
728 | if (ret < 0) |
729 | return ret; |
730 | } |
731 | adc->spi_freq = spi_freq; |
732 | |
733 | return len; |
734 | } |
735 | |
736 | static int stm32_dfsdm_start_conv(struct iio_dev *indio_dev, |
737 | struct iio_trigger *trig) |
738 | { |
739 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
740 | struct regmap *regmap = adc->dfsdm->regmap; |
741 | int ret; |
742 | |
743 | ret = stm32_dfsdm_channels_configure(indio_dev, fl_id: adc->fl_id, trig); |
744 | if (ret < 0) |
745 | return ret; |
746 | |
747 | ret = stm32_dfsdm_start_channel(indio_dev); |
748 | if (ret < 0) |
749 | return ret; |
750 | |
751 | ret = stm32_dfsdm_filter_configure(indio_dev, fl_id: adc->fl_id, trig); |
752 | if (ret < 0) |
753 | goto stop_channels; |
754 | |
755 | ret = stm32_dfsdm_start_filter(adc, fl_id: adc->fl_id, trig); |
756 | if (ret < 0) |
757 | goto filter_unconfigure; |
758 | |
759 | return 0; |
760 | |
761 | filter_unconfigure: |
762 | regmap_update_bits(map: regmap, DFSDM_CR1(adc->fl_id), |
763 | DFSDM_CR1_CFG_MASK, val: 0); |
764 | stop_channels: |
765 | stm32_dfsdm_stop_channel(indio_dev); |
766 | |
767 | return ret; |
768 | } |
769 | |
770 | static void stm32_dfsdm_stop_conv(struct iio_dev *indio_dev) |
771 | { |
772 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
773 | struct regmap *regmap = adc->dfsdm->regmap; |
774 | |
775 | stm32_dfsdm_stop_filter(dfsdm: adc->dfsdm, fl_id: adc->fl_id); |
776 | |
777 | regmap_update_bits(map: regmap, DFSDM_CR1(adc->fl_id), |
778 | DFSDM_CR1_CFG_MASK, val: 0); |
779 | |
780 | stm32_dfsdm_stop_channel(indio_dev); |
781 | } |
782 | |
783 | static int stm32_dfsdm_set_watermark(struct iio_dev *indio_dev, |
784 | unsigned int val) |
785 | { |
786 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
787 | unsigned int watermark = DFSDM_DMA_BUFFER_SIZE / 2; |
788 | unsigned int rx_buf_sz = DFSDM_DMA_BUFFER_SIZE; |
789 | |
790 | /* |
791 | * DMA cyclic transfers are used, buffer is split into two periods. |
792 | * There should be : |
793 | * - always one buffer (period) DMA is working on |
794 | * - one buffer (period) driver pushed to ASoC side. |
795 | */ |
796 | watermark = min(watermark, val * (unsigned int)(sizeof(u32))); |
797 | adc->buf_sz = min(rx_buf_sz, watermark * 2 * adc->nconv); |
798 | |
799 | return 0; |
800 | } |
801 | |
802 | static unsigned int stm32_dfsdm_adc_dma_residue(struct stm32_dfsdm_adc *adc) |
803 | { |
804 | struct dma_tx_state state; |
805 | enum dma_status status; |
806 | |
807 | status = dmaengine_tx_status(chan: adc->dma_chan, |
808 | cookie: adc->dma_chan->cookie, |
809 | state: &state); |
810 | if (status == DMA_IN_PROGRESS) { |
811 | /* Residue is size in bytes from end of buffer */ |
812 | unsigned int i = adc->buf_sz - state.residue; |
813 | unsigned int size; |
814 | |
815 | /* Return available bytes */ |
816 | if (i >= adc->bufi) |
817 | size = i - adc->bufi; |
818 | else |
819 | size = adc->buf_sz + i - adc->bufi; |
820 | |
821 | return size; |
822 | } |
823 | |
824 | return 0; |
825 | } |
826 | |
827 | static inline void stm32_dfsdm_process_data(struct stm32_dfsdm_adc *adc, |
828 | s32 *buffer) |
829 | { |
830 | struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id]; |
831 | struct stm32_dfsdm_filter_osr *flo = &fl->flo[fl->fast]; |
832 | unsigned int i = adc->nconv; |
833 | s32 *ptr = buffer; |
834 | |
835 | while (i--) { |
836 | /* Mask 8 LSB that contains the channel ID */ |
837 | *ptr &= 0xFFFFFF00; |
838 | /* Convert 2^(n-1) sample to 2^(n-1)-1 to avoid wrap-around */ |
839 | if (*ptr > flo->max) |
840 | *ptr -= 1; |
841 | /* |
842 | * Samples from filter are retrieved with 23 bits resolution |
843 | * or less. Shift left to align MSB on 24 bits. |
844 | */ |
845 | *ptr <<= flo->lshift; |
846 | |
847 | ptr++; |
848 | } |
849 | } |
850 | |
851 | static void stm32_dfsdm_dma_buffer_done(void *data) |
852 | { |
853 | struct iio_dev *indio_dev = data; |
854 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
855 | int available = stm32_dfsdm_adc_dma_residue(adc); |
856 | size_t old_pos; |
857 | |
858 | /* |
859 | * FIXME: In Kernel interface does not support cyclic DMA buffer,and |
860 | * offers only an interface to push data samples per samples. |
861 | * For this reason IIO buffer interface is not used and interface is |
862 | * bypassed using a private callback registered by ASoC. |
863 | * This should be a temporary solution waiting a cyclic DMA engine |
864 | * support in IIO. |
865 | */ |
866 | |
867 | dev_dbg(&indio_dev->dev, "pos = %d, available = %d\n", |
868 | adc->bufi, available); |
869 | old_pos = adc->bufi; |
870 | |
871 | while (available >= indio_dev->scan_bytes) { |
872 | s32 *buffer = (s32 *)&adc->rx_buf[adc->bufi]; |
873 | |
874 | stm32_dfsdm_process_data(adc, buffer); |
875 | |
876 | available -= indio_dev->scan_bytes; |
877 | adc->bufi += indio_dev->scan_bytes; |
878 | if (adc->bufi >= adc->buf_sz) { |
879 | if (adc->cb) |
880 | adc->cb(&adc->rx_buf[old_pos], |
881 | adc->buf_sz - old_pos, adc->cb_priv); |
882 | adc->bufi = 0; |
883 | old_pos = 0; |
884 | } |
885 | /* |
886 | * In DMA mode the trigger services of IIO are not used |
887 | * (e.g. no call to iio_trigger_poll). |
888 | * Calling irq handler associated to the hardware trigger is not |
889 | * relevant as the conversions have already been done. Data |
890 | * transfers are performed directly in DMA callback instead. |
891 | * This implementation avoids to call trigger irq handler that |
892 | * may sleep, in an atomic context (DMA irq handler context). |
893 | */ |
894 | if (adc->dev_data->type == DFSDM_IIO) |
895 | iio_push_to_buffers(indio_dev, data: buffer); |
896 | } |
897 | if (adc->cb) |
898 | adc->cb(&adc->rx_buf[old_pos], adc->bufi - old_pos, |
899 | adc->cb_priv); |
900 | } |
901 | |
902 | static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev) |
903 | { |
904 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
905 | /* |
906 | * The DFSDM supports half-word transfers. However, for 16 bits record, |
907 | * 4 bytes buswidth is kept, to avoid losing samples LSBs when left |
908 | * shift is required. |
909 | */ |
910 | struct dma_slave_config config = { |
911 | .src_addr = (dma_addr_t)adc->dfsdm->phys_base, |
912 | .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, |
913 | }; |
914 | struct dma_async_tx_descriptor *desc; |
915 | dma_cookie_t cookie; |
916 | int ret; |
917 | |
918 | if (!adc->dma_chan) |
919 | return -EINVAL; |
920 | |
921 | dev_dbg(&indio_dev->dev, "size=%d watermark=%d\n", |
922 | adc->buf_sz, adc->buf_sz / 2); |
923 | |
924 | if (adc->nconv == 1 && !indio_dev->trig) |
925 | config.src_addr += DFSDM_RDATAR(adc->fl_id); |
926 | else |
927 | config.src_addr += DFSDM_JDATAR(adc->fl_id); |
928 | ret = dmaengine_slave_config(chan: adc->dma_chan, config: &config); |
929 | if (ret) |
930 | return ret; |
931 | |
932 | /* Prepare a DMA cyclic transaction */ |
933 | desc = dmaengine_prep_dma_cyclic(chan: adc->dma_chan, |
934 | buf_addr: adc->dma_buf, |
935 | buf_len: adc->buf_sz, period_len: adc->buf_sz / 2, |
936 | dir: DMA_DEV_TO_MEM, |
937 | flags: DMA_PREP_INTERRUPT); |
938 | if (!desc) |
939 | return -EBUSY; |
940 | |
941 | desc->callback = stm32_dfsdm_dma_buffer_done; |
942 | desc->callback_param = indio_dev; |
943 | |
944 | cookie = dmaengine_submit(desc); |
945 | ret = dma_submit_error(cookie); |
946 | if (ret) |
947 | goto err_stop_dma; |
948 | |
949 | /* Issue pending DMA requests */ |
950 | dma_async_issue_pending(chan: adc->dma_chan); |
951 | |
952 | if (adc->nconv == 1 && !indio_dev->trig) { |
953 | /* Enable regular DMA transfer*/ |
954 | ret = regmap_update_bits(map: adc->dfsdm->regmap, |
955 | DFSDM_CR1(adc->fl_id), |
956 | DFSDM_CR1_RDMAEN_MASK, |
957 | DFSDM_CR1_RDMAEN_MASK); |
958 | } else { |
959 | /* Enable injected DMA transfer*/ |
960 | ret = regmap_update_bits(map: adc->dfsdm->regmap, |
961 | DFSDM_CR1(adc->fl_id), |
962 | DFSDM_CR1_JDMAEN_MASK, |
963 | DFSDM_CR1_JDMAEN_MASK); |
964 | } |
965 | |
966 | if (ret < 0) |
967 | goto err_stop_dma; |
968 | |
969 | return 0; |
970 | |
971 | err_stop_dma: |
972 | dmaengine_terminate_all(chan: adc->dma_chan); |
973 | |
974 | return ret; |
975 | } |
976 | |
977 | static void stm32_dfsdm_adc_dma_stop(struct iio_dev *indio_dev) |
978 | { |
979 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
980 | |
981 | if (!adc->dma_chan) |
982 | return; |
983 | |
984 | regmap_update_bits(map: adc->dfsdm->regmap, DFSDM_CR1(adc->fl_id), |
985 | DFSDM_CR1_RDMAEN_MASK | DFSDM_CR1_JDMAEN_MASK, val: 0); |
986 | dmaengine_terminate_all(chan: adc->dma_chan); |
987 | } |
988 | |
989 | static int stm32_dfsdm_update_scan_mode(struct iio_dev *indio_dev, |
990 | const unsigned long *scan_mask) |
991 | { |
992 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
993 | |
994 | adc->nconv = bitmap_weight(src: scan_mask, nbits: indio_dev->masklength); |
995 | adc->smask = *scan_mask; |
996 | |
997 | dev_dbg(&indio_dev->dev, "nconv=%d mask=%lx\n", adc->nconv, *scan_mask); |
998 | |
999 | return 0; |
1000 | } |
1001 | |
1002 | static int stm32_dfsdm_postenable(struct iio_dev *indio_dev) |
1003 | { |
1004 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
1005 | int ret; |
1006 | |
1007 | /* Reset adc buffer index */ |
1008 | adc->bufi = 0; |
1009 | |
1010 | if (adc->hwc) { |
1011 | ret = iio_hw_consumer_enable(hwc: adc->hwc); |
1012 | if (ret < 0) |
1013 | return ret; |
1014 | } |
1015 | |
1016 | ret = stm32_dfsdm_start_dfsdm(dfsdm: adc->dfsdm); |
1017 | if (ret < 0) |
1018 | goto err_stop_hwc; |
1019 | |
1020 | ret = stm32_dfsdm_adc_dma_start(indio_dev); |
1021 | if (ret) { |
1022 | dev_err(&indio_dev->dev, "Can't start DMA\n"); |
1023 | goto stop_dfsdm; |
1024 | } |
1025 | |
1026 | ret = stm32_dfsdm_start_conv(indio_dev, trig: indio_dev->trig); |
1027 | if (ret) { |
1028 | dev_err(&indio_dev->dev, "Can't start conversion\n"); |
1029 | goto err_stop_dma; |
1030 | } |
1031 | |
1032 | return 0; |
1033 | |
1034 | err_stop_dma: |
1035 | stm32_dfsdm_adc_dma_stop(indio_dev); |
1036 | stop_dfsdm: |
1037 | stm32_dfsdm_stop_dfsdm(dfsdm: adc->dfsdm); |
1038 | err_stop_hwc: |
1039 | if (adc->hwc) |
1040 | iio_hw_consumer_disable(hwc: adc->hwc); |
1041 | |
1042 | return ret; |
1043 | } |
1044 | |
1045 | static int stm32_dfsdm_predisable(struct iio_dev *indio_dev) |
1046 | { |
1047 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
1048 | |
1049 | stm32_dfsdm_stop_conv(indio_dev); |
1050 | |
1051 | stm32_dfsdm_adc_dma_stop(indio_dev); |
1052 | |
1053 | stm32_dfsdm_stop_dfsdm(dfsdm: adc->dfsdm); |
1054 | |
1055 | if (adc->hwc) |
1056 | iio_hw_consumer_disable(hwc: adc->hwc); |
1057 | |
1058 | return 0; |
1059 | } |
1060 | |
1061 | static const struct iio_buffer_setup_ops stm32_dfsdm_buffer_setup_ops = { |
1062 | .postenable = &stm32_dfsdm_postenable, |
1063 | .predisable = &stm32_dfsdm_predisable, |
1064 | }; |
1065 | |
1066 | /** |
1067 | * stm32_dfsdm_get_buff_cb() - register a callback that will be called when |
1068 | * DMA transfer period is achieved. |
1069 | * |
1070 | * @iio_dev: Handle to IIO device. |
1071 | * @cb: Pointer to callback function: |
1072 | * - data: pointer to data buffer |
1073 | * - size: size in byte of the data buffer |
1074 | * - private: pointer to consumer private structure. |
1075 | * @private: Pointer to consumer private structure. |
1076 | */ |
1077 | int stm32_dfsdm_get_buff_cb(struct iio_dev *iio_dev, |
1078 | int (*cb)(const void *data, size_t size, |
1079 | void *private), |
1080 | void *private) |
1081 | { |
1082 | struct stm32_dfsdm_adc *adc; |
1083 | |
1084 | if (!iio_dev) |
1085 | return -EINVAL; |
1086 | adc = iio_priv(indio_dev: iio_dev); |
1087 | |
1088 | adc->cb = cb; |
1089 | adc->cb_priv = private; |
1090 | |
1091 | return 0; |
1092 | } |
1093 | EXPORT_SYMBOL_GPL(stm32_dfsdm_get_buff_cb); |
1094 | |
1095 | /** |
1096 | * stm32_dfsdm_release_buff_cb - unregister buffer callback |
1097 | * |
1098 | * @iio_dev: Handle to IIO device. |
1099 | */ |
1100 | int stm32_dfsdm_release_buff_cb(struct iio_dev *iio_dev) |
1101 | { |
1102 | struct stm32_dfsdm_adc *adc; |
1103 | |
1104 | if (!iio_dev) |
1105 | return -EINVAL; |
1106 | adc = iio_priv(indio_dev: iio_dev); |
1107 | |
1108 | adc->cb = NULL; |
1109 | adc->cb_priv = NULL; |
1110 | |
1111 | return 0; |
1112 | } |
1113 | EXPORT_SYMBOL_GPL(stm32_dfsdm_release_buff_cb); |
1114 | |
1115 | static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev, |
1116 | const struct iio_chan_spec *chan, int *res) |
1117 | { |
1118 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
1119 | long timeout; |
1120 | int ret; |
1121 | |
1122 | reinit_completion(x: &adc->completion); |
1123 | |
1124 | adc->buffer = res; |
1125 | |
1126 | ret = stm32_dfsdm_start_dfsdm(dfsdm: adc->dfsdm); |
1127 | if (ret < 0) |
1128 | return ret; |
1129 | |
1130 | ret = regmap_update_bits(map: adc->dfsdm->regmap, DFSDM_CR2(adc->fl_id), |
1131 | DFSDM_CR2_REOCIE_MASK, DFSDM_CR2_REOCIE(1)); |
1132 | if (ret < 0) |
1133 | goto stop_dfsdm; |
1134 | |
1135 | adc->nconv = 1; |
1136 | adc->smask = BIT(chan->scan_index); |
1137 | ret = stm32_dfsdm_start_conv(indio_dev, NULL); |
1138 | if (ret < 0) { |
1139 | regmap_update_bits(map: adc->dfsdm->regmap, DFSDM_CR2(adc->fl_id), |
1140 | DFSDM_CR2_REOCIE_MASK, DFSDM_CR2_REOCIE(0)); |
1141 | goto stop_dfsdm; |
1142 | } |
1143 | |
1144 | timeout = wait_for_completion_interruptible_timeout(x: &adc->completion, |
1145 | DFSDM_TIMEOUT); |
1146 | |
1147 | /* Mask IRQ for regular conversion achievement*/ |
1148 | regmap_update_bits(map: adc->dfsdm->regmap, DFSDM_CR2(adc->fl_id), |
1149 | DFSDM_CR2_REOCIE_MASK, DFSDM_CR2_REOCIE(0)); |
1150 | |
1151 | if (timeout == 0) |
1152 | ret = -ETIMEDOUT; |
1153 | else if (timeout < 0) |
1154 | ret = timeout; |
1155 | else |
1156 | ret = IIO_VAL_INT; |
1157 | |
1158 | stm32_dfsdm_stop_conv(indio_dev); |
1159 | |
1160 | stm32_dfsdm_process_data(adc, buffer: res); |
1161 | |
1162 | stop_dfsdm: |
1163 | stm32_dfsdm_stop_dfsdm(dfsdm: adc->dfsdm); |
1164 | |
1165 | return ret; |
1166 | } |
1167 | |
1168 | static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev, |
1169 | struct iio_chan_spec const *chan, |
1170 | int val, int val2, long mask) |
1171 | { |
1172 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
1173 | struct stm32_dfsdm_channel *ch = &adc->dfsdm->ch_list[chan->channel]; |
1174 | unsigned int spi_freq; |
1175 | int ret = -EINVAL; |
1176 | |
1177 | switch (ch->src) { |
1178 | case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL: |
1179 | spi_freq = adc->dfsdm->spi_master_freq; |
1180 | break; |
1181 | case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING: |
1182 | case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING: |
1183 | spi_freq = adc->dfsdm->spi_master_freq / 2; |
1184 | break; |
1185 | default: |
1186 | spi_freq = adc->spi_freq; |
1187 | } |
1188 | |
1189 | switch (mask) { |
1190 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: |
1191 | ret = iio_device_claim_direct_mode(indio_dev); |
1192 | if (ret) |
1193 | return ret; |
1194 | |
1195 | ret = stm32_dfsdm_compute_all_osrs(indio_dev, oversamp: val); |
1196 | if (!ret) { |
1197 | dev_dbg(&indio_dev->dev, |
1198 | "Sampling rate changed from (%u) to (%u)\n", |
1199 | adc->sample_freq, spi_freq / val); |
1200 | adc->oversamp = val; |
1201 | adc->sample_freq = spi_freq / val; |
1202 | } |
1203 | iio_device_release_direct_mode(indio_dev); |
1204 | return ret; |
1205 | |
1206 | case IIO_CHAN_INFO_SAMP_FREQ: |
1207 | if (!val) |
1208 | return -EINVAL; |
1209 | |
1210 | ret = iio_device_claim_direct_mode(indio_dev); |
1211 | if (ret) |
1212 | return ret; |
1213 | |
1214 | ret = dfsdm_adc_set_samp_freq(indio_dev, sample_freq: val, spi_freq); |
1215 | iio_device_release_direct_mode(indio_dev); |
1216 | return ret; |
1217 | } |
1218 | |
1219 | return -EINVAL; |
1220 | } |
1221 | |
1222 | static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev, |
1223 | struct iio_chan_spec const *chan, int *val, |
1224 | int *val2, long mask) |
1225 | { |
1226 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
1227 | int ret; |
1228 | |
1229 | switch (mask) { |
1230 | case IIO_CHAN_INFO_RAW: |
1231 | ret = iio_device_claim_direct_mode(indio_dev); |
1232 | if (ret) |
1233 | return ret; |
1234 | ret = iio_hw_consumer_enable(hwc: adc->hwc); |
1235 | if (ret < 0) { |
1236 | dev_err(&indio_dev->dev, |
1237 | "%s: IIO enable failed (channel %d)\n", |
1238 | __func__, chan->channel); |
1239 | iio_device_release_direct_mode(indio_dev); |
1240 | return ret; |
1241 | } |
1242 | ret = stm32_dfsdm_single_conv(indio_dev, chan, res: val); |
1243 | iio_hw_consumer_disable(hwc: adc->hwc); |
1244 | if (ret < 0) { |
1245 | dev_err(&indio_dev->dev, |
1246 | "%s: Conversion failed (channel %d)\n", |
1247 | __func__, chan->channel); |
1248 | iio_device_release_direct_mode(indio_dev); |
1249 | return ret; |
1250 | } |
1251 | iio_device_release_direct_mode(indio_dev); |
1252 | return IIO_VAL_INT; |
1253 | |
1254 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: |
1255 | *val = adc->oversamp; |
1256 | |
1257 | return IIO_VAL_INT; |
1258 | |
1259 | case IIO_CHAN_INFO_SAMP_FREQ: |
1260 | *val = adc->sample_freq; |
1261 | |
1262 | return IIO_VAL_INT; |
1263 | } |
1264 | |
1265 | return -EINVAL; |
1266 | } |
1267 | |
1268 | static int stm32_dfsdm_validate_trigger(struct iio_dev *indio_dev, |
1269 | struct iio_trigger *trig) |
1270 | { |
1271 | return stm32_dfsdm_get_jextsel(indio_dev, trig) < 0 ? -EINVAL : 0; |
1272 | } |
1273 | |
1274 | static const struct iio_info stm32_dfsdm_info_audio = { |
1275 | .hwfifo_set_watermark = stm32_dfsdm_set_watermark, |
1276 | .read_raw = stm32_dfsdm_read_raw, |
1277 | .write_raw = stm32_dfsdm_write_raw, |
1278 | .update_scan_mode = stm32_dfsdm_update_scan_mode, |
1279 | }; |
1280 | |
1281 | static const struct iio_info stm32_dfsdm_info_adc = { |
1282 | .hwfifo_set_watermark = stm32_dfsdm_set_watermark, |
1283 | .read_raw = stm32_dfsdm_read_raw, |
1284 | .write_raw = stm32_dfsdm_write_raw, |
1285 | .update_scan_mode = stm32_dfsdm_update_scan_mode, |
1286 | .validate_trigger = stm32_dfsdm_validate_trigger, |
1287 | }; |
1288 | |
1289 | static irqreturn_t stm32_dfsdm_irq(int irq, void *arg) |
1290 | { |
1291 | struct iio_dev *indio_dev = arg; |
1292 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
1293 | struct regmap *regmap = adc->dfsdm->regmap; |
1294 | unsigned int status, int_en; |
1295 | |
1296 | regmap_read(map: regmap, DFSDM_ISR(adc->fl_id), val: &status); |
1297 | regmap_read(map: regmap, DFSDM_CR2(adc->fl_id), val: &int_en); |
1298 | |
1299 | if (status & DFSDM_ISR_REOCF_MASK) { |
1300 | /* Read the data register clean the IRQ status */ |
1301 | regmap_read(map: regmap, DFSDM_RDATAR(adc->fl_id), val: adc->buffer); |
1302 | complete(&adc->completion); |
1303 | } |
1304 | |
1305 | if (status & DFSDM_ISR_ROVRF_MASK) { |
1306 | if (int_en & DFSDM_CR2_ROVRIE_MASK) |
1307 | dev_warn(&indio_dev->dev, "Overrun detected\n"); |
1308 | regmap_update_bits(map: regmap, DFSDM_ICR(adc->fl_id), |
1309 | DFSDM_ICR_CLRROVRF_MASK, |
1310 | DFSDM_ICR_CLRROVRF_MASK); |
1311 | } |
1312 | |
1313 | return IRQ_HANDLED; |
1314 | } |
1315 | |
1316 | /* |
1317 | * Define external info for SPI Frequency and audio sampling rate that can be |
1318 | * configured by ASoC driver through consumer.h API |
1319 | */ |
1320 | static const struct iio_chan_spec_ext_info dfsdm_adc_audio_ext_info[] = { |
1321 | /* spi_clk_freq : clock freq on SPI/manchester bus used by channel */ |
1322 | { |
1323 | .name = "spi_clk_freq", |
1324 | .shared = IIO_SHARED_BY_TYPE, |
1325 | .read = dfsdm_adc_audio_get_spiclk, |
1326 | .write = dfsdm_adc_audio_set_spiclk, |
1327 | }, |
1328 | {}, |
1329 | }; |
1330 | |
1331 | static void stm32_dfsdm_dma_release(struct iio_dev *indio_dev) |
1332 | { |
1333 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
1334 | |
1335 | if (adc->dma_chan) { |
1336 | dma_free_coherent(dev: adc->dma_chan->device->dev, |
1337 | DFSDM_DMA_BUFFER_SIZE, |
1338 | cpu_addr: adc->rx_buf, dma_handle: adc->dma_buf); |
1339 | dma_release_channel(chan: adc->dma_chan); |
1340 | } |
1341 | } |
1342 | |
1343 | static int stm32_dfsdm_dma_request(struct device *dev, |
1344 | struct iio_dev *indio_dev) |
1345 | { |
1346 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
1347 | |
1348 | adc->dma_chan = dma_request_chan(dev, name: "rx"); |
1349 | if (IS_ERR(ptr: adc->dma_chan)) { |
1350 | int ret = PTR_ERR(ptr: adc->dma_chan); |
1351 | |
1352 | adc->dma_chan = NULL; |
1353 | return ret; |
1354 | } |
1355 | |
1356 | adc->rx_buf = dma_alloc_coherent(dev: adc->dma_chan->device->dev, |
1357 | DFSDM_DMA_BUFFER_SIZE, |
1358 | dma_handle: &adc->dma_buf, GFP_KERNEL); |
1359 | if (!adc->rx_buf) { |
1360 | dma_release_channel(chan: adc->dma_chan); |
1361 | return -ENOMEM; |
1362 | } |
1363 | |
1364 | indio_dev->modes |= INDIO_BUFFER_SOFTWARE; |
1365 | indio_dev->setup_ops = &stm32_dfsdm_buffer_setup_ops; |
1366 | |
1367 | return 0; |
1368 | } |
1369 | |
1370 | static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev, |
1371 | struct iio_chan_spec *ch) |
1372 | { |
1373 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
1374 | int ret; |
1375 | |
1376 | ret = stm32_dfsdm_channel_parse_of(dfsdm: adc->dfsdm, indio_dev, ch); |
1377 | if (ret < 0) |
1378 | return ret; |
1379 | |
1380 | ch->type = IIO_VOLTAGE; |
1381 | ch->indexed = 1; |
1382 | |
1383 | /* |
1384 | * IIO_CHAN_INFO_RAW: used to compute regular conversion |
1385 | * IIO_CHAN_INFO_OVERSAMPLING_RATIO: used to set oversampling |
1386 | */ |
1387 | ch->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); |
1388 | ch->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) | |
1389 | BIT(IIO_CHAN_INFO_SAMP_FREQ); |
1390 | |
1391 | if (adc->dev_data->type == DFSDM_AUDIO) { |
1392 | ch->ext_info = dfsdm_adc_audio_ext_info; |
1393 | } else { |
1394 | ch->scan_type.shift = 8; |
1395 | } |
1396 | ch->scan_type.sign = 's'; |
1397 | ch->scan_type.realbits = 24; |
1398 | ch->scan_type.storagebits = 32; |
1399 | |
1400 | return stm32_dfsdm_chan_configure(dfsdm: adc->dfsdm, |
1401 | ch: &adc->dfsdm->ch_list[ch->channel]); |
1402 | } |
1403 | |
1404 | static int stm32_dfsdm_audio_init(struct device *dev, struct iio_dev *indio_dev) |
1405 | { |
1406 | struct iio_chan_spec *ch; |
1407 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
1408 | struct stm32_dfsdm_channel *d_ch; |
1409 | int ret; |
1410 | |
1411 | ch = devm_kzalloc(dev: &indio_dev->dev, size: sizeof(*ch), GFP_KERNEL); |
1412 | if (!ch) |
1413 | return -ENOMEM; |
1414 | |
1415 | ch->scan_index = 0; |
1416 | |
1417 | ret = stm32_dfsdm_adc_chan_init_one(indio_dev, ch); |
1418 | if (ret < 0) { |
1419 | dev_err(&indio_dev->dev, "Channels init failed\n"); |
1420 | return ret; |
1421 | } |
1422 | ch->info_mask_separate = BIT(IIO_CHAN_INFO_SAMP_FREQ); |
1423 | |
1424 | d_ch = &adc->dfsdm->ch_list[ch->channel]; |
1425 | if (d_ch->src != DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL) |
1426 | adc->spi_freq = adc->dfsdm->spi_master_freq; |
1427 | |
1428 | indio_dev->num_channels = 1; |
1429 | indio_dev->channels = ch; |
1430 | |
1431 | return stm32_dfsdm_dma_request(dev, indio_dev); |
1432 | } |
1433 | |
1434 | static int stm32_dfsdm_adc_init(struct device *dev, struct iio_dev *indio_dev) |
1435 | { |
1436 | struct iio_chan_spec *ch; |
1437 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
1438 | int num_ch; |
1439 | int ret, chan_idx; |
1440 | |
1441 | adc->oversamp = DFSDM_DEFAULT_OVERSAMPLING; |
1442 | ret = stm32_dfsdm_compute_all_osrs(indio_dev, oversamp: adc->oversamp); |
1443 | if (ret < 0) |
1444 | return ret; |
1445 | |
1446 | num_ch = of_property_count_u32_elems(np: indio_dev->dev.of_node, |
1447 | propname: "st,adc-channels"); |
1448 | if (num_ch < 0 || num_ch > adc->dfsdm->num_chs) { |
1449 | dev_err(&indio_dev->dev, "Bad st,adc-channels\n"); |
1450 | return num_ch < 0 ? num_ch : -EINVAL; |
1451 | } |
1452 | |
1453 | /* Bind to SD modulator IIO device */ |
1454 | adc->hwc = devm_iio_hw_consumer_alloc(dev: &indio_dev->dev); |
1455 | if (IS_ERR(ptr: adc->hwc)) |
1456 | return -EPROBE_DEFER; |
1457 | |
1458 | ch = devm_kcalloc(dev: &indio_dev->dev, n: num_ch, size: sizeof(*ch), |
1459 | GFP_KERNEL); |
1460 | if (!ch) |
1461 | return -ENOMEM; |
1462 | |
1463 | for (chan_idx = 0; chan_idx < num_ch; chan_idx++) { |
1464 | ch[chan_idx].scan_index = chan_idx; |
1465 | ret = stm32_dfsdm_adc_chan_init_one(indio_dev, ch: &ch[chan_idx]); |
1466 | if (ret < 0) { |
1467 | dev_err(&indio_dev->dev, "Channels init failed\n"); |
1468 | return ret; |
1469 | } |
1470 | } |
1471 | |
1472 | indio_dev->num_channels = num_ch; |
1473 | indio_dev->channels = ch; |
1474 | |
1475 | init_completion(x: &adc->completion); |
1476 | |
1477 | /* Optionally request DMA */ |
1478 | ret = stm32_dfsdm_dma_request(dev, indio_dev); |
1479 | if (ret) { |
1480 | if (ret != -ENODEV) |
1481 | return dev_err_probe(dev, err: ret, |
1482 | fmt: "DMA channel request failed with\n"); |
1483 | |
1484 | dev_dbg(dev, "No DMA support\n"); |
1485 | return 0; |
1486 | } |
1487 | |
1488 | ret = iio_triggered_buffer_setup(indio_dev, |
1489 | &iio_pollfunc_store_time, NULL, |
1490 | &stm32_dfsdm_buffer_setup_ops); |
1491 | if (ret) { |
1492 | stm32_dfsdm_dma_release(indio_dev); |
1493 | dev_err(&indio_dev->dev, "buffer setup failed\n"); |
1494 | return ret; |
1495 | } |
1496 | |
1497 | /* lptimer/timer hardware triggers */ |
1498 | indio_dev->modes |= INDIO_HARDWARE_TRIGGERED; |
1499 | |
1500 | return 0; |
1501 | } |
1502 | |
1503 | static const struct stm32_dfsdm_dev_data stm32h7_dfsdm_adc_data = { |
1504 | .type = DFSDM_IIO, |
1505 | .init = stm32_dfsdm_adc_init, |
1506 | }; |
1507 | |
1508 | static const struct stm32_dfsdm_dev_data stm32h7_dfsdm_audio_data = { |
1509 | .type = DFSDM_AUDIO, |
1510 | .init = stm32_dfsdm_audio_init, |
1511 | }; |
1512 | |
1513 | static const struct of_device_id stm32_dfsdm_adc_match[] = { |
1514 | { |
1515 | .compatible = "st,stm32-dfsdm-adc", |
1516 | .data = &stm32h7_dfsdm_adc_data, |
1517 | }, |
1518 | { |
1519 | .compatible = "st,stm32-dfsdm-dmic", |
1520 | .data = &stm32h7_dfsdm_audio_data, |
1521 | }, |
1522 | {} |
1523 | }; |
1524 | MODULE_DEVICE_TABLE(of, stm32_dfsdm_adc_match); |
1525 | |
1526 | static int stm32_dfsdm_adc_probe(struct platform_device *pdev) |
1527 | { |
1528 | struct device *dev = &pdev->dev; |
1529 | struct stm32_dfsdm_adc *adc; |
1530 | struct device_node *np = dev->of_node; |
1531 | const struct stm32_dfsdm_dev_data *dev_data; |
1532 | struct iio_dev *iio; |
1533 | char *name; |
1534 | int ret, irq, val; |
1535 | |
1536 | dev_data = of_device_get_match_data(dev); |
1537 | iio = devm_iio_device_alloc(parent: dev, sizeof_priv: sizeof(*adc)); |
1538 | if (!iio) { |
1539 | dev_err(dev, "%s: Failed to allocate IIO\n", __func__); |
1540 | return -ENOMEM; |
1541 | } |
1542 | |
1543 | adc = iio_priv(indio_dev: iio); |
1544 | adc->dfsdm = dev_get_drvdata(dev: dev->parent); |
1545 | |
1546 | iio->dev.of_node = np; |
1547 | iio->modes = INDIO_DIRECT_MODE; |
1548 | |
1549 | platform_set_drvdata(pdev, data: iio); |
1550 | |
1551 | ret = of_property_read_u32(np: dev->of_node, propname: "reg", out_value: &adc->fl_id); |
1552 | if (ret != 0 || adc->fl_id >= adc->dfsdm->num_fls) { |
1553 | dev_err(dev, "Missing or bad reg property\n"); |
1554 | return -EINVAL; |
1555 | } |
1556 | |
1557 | name = devm_kzalloc(dev, size: sizeof("dfsdm-adc0"), GFP_KERNEL); |
1558 | if (!name) |
1559 | return -ENOMEM; |
1560 | if (dev_data->type == DFSDM_AUDIO) { |
1561 | iio->info = &stm32_dfsdm_info_audio; |
1562 | snprintf(buf: name, size: sizeof("dfsdm-pdm0"), fmt: "dfsdm-pdm%d", adc->fl_id); |
1563 | } else { |
1564 | iio->info = &stm32_dfsdm_info_adc; |
1565 | snprintf(buf: name, size: sizeof("dfsdm-adc0"), fmt: "dfsdm-adc%d", adc->fl_id); |
1566 | } |
1567 | iio->name = name; |
1568 | |
1569 | /* |
1570 | * In a first step IRQs generated for channels are not treated. |
1571 | * So IRQ associated to filter instance 0 is dedicated to the Filter 0. |
1572 | */ |
1573 | irq = platform_get_irq(pdev, 0); |
1574 | if (irq < 0) |
1575 | return irq; |
1576 | |
1577 | ret = devm_request_irq(dev, irq, handler: stm32_dfsdm_irq, |
1578 | irqflags: 0, devname: pdev->name, dev_id: iio); |
1579 | if (ret < 0) { |
1580 | dev_err(dev, "Failed to request IRQ\n"); |
1581 | return ret; |
1582 | } |
1583 | |
1584 | ret = of_property_read_u32(np: dev->of_node, propname: "st,filter-order", out_value: &val); |
1585 | if (ret < 0) { |
1586 | dev_err(dev, "Failed to set filter order\n"); |
1587 | return ret; |
1588 | } |
1589 | |
1590 | adc->dfsdm->fl_list[adc->fl_id].ford = val; |
1591 | |
1592 | ret = of_property_read_u32(np: dev->of_node, propname: "st,filter0-sync", out_value: &val); |
1593 | if (!ret) |
1594 | adc->dfsdm->fl_list[adc->fl_id].sync_mode = val; |
1595 | |
1596 | adc->dev_data = dev_data; |
1597 | ret = dev_data->init(dev, iio); |
1598 | if (ret < 0) |
1599 | return ret; |
1600 | |
1601 | ret = iio_device_register(iio); |
1602 | if (ret < 0) |
1603 | goto err_cleanup; |
1604 | |
1605 | if (dev_data->type == DFSDM_AUDIO) { |
1606 | ret = of_platform_populate(root: np, NULL, NULL, parent: dev); |
1607 | if (ret < 0) { |
1608 | dev_err(dev, "Failed to find an audio DAI\n"); |
1609 | goto err_unregister; |
1610 | } |
1611 | } |
1612 | |
1613 | return 0; |
1614 | |
1615 | err_unregister: |
1616 | iio_device_unregister(indio_dev: iio); |
1617 | err_cleanup: |
1618 | stm32_dfsdm_dma_release(indio_dev: iio); |
1619 | |
1620 | return ret; |
1621 | } |
1622 | |
1623 | static void stm32_dfsdm_adc_remove(struct platform_device *pdev) |
1624 | { |
1625 | struct iio_dev *indio_dev = platform_get_drvdata(pdev); |
1626 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
1627 | |
1628 | if (adc->dev_data->type == DFSDM_AUDIO) |
1629 | of_platform_depopulate(parent: &pdev->dev); |
1630 | iio_device_unregister(indio_dev); |
1631 | stm32_dfsdm_dma_release(indio_dev); |
1632 | } |
1633 | |
1634 | static int stm32_dfsdm_adc_suspend(struct device *dev) |
1635 | { |
1636 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
1637 | |
1638 | if (iio_buffer_enabled(indio_dev)) |
1639 | stm32_dfsdm_predisable(indio_dev); |
1640 | |
1641 | return 0; |
1642 | } |
1643 | |
1644 | static int stm32_dfsdm_adc_resume(struct device *dev) |
1645 | { |
1646 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
1647 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
1648 | const struct iio_chan_spec *chan; |
1649 | struct stm32_dfsdm_channel *ch; |
1650 | int i, ret; |
1651 | |
1652 | /* restore channels configuration */ |
1653 | for (i = 0; i < indio_dev->num_channels; i++) { |
1654 | chan = indio_dev->channels + i; |
1655 | ch = &adc->dfsdm->ch_list[chan->channel]; |
1656 | ret = stm32_dfsdm_chan_configure(dfsdm: adc->dfsdm, ch); |
1657 | if (ret) |
1658 | return ret; |
1659 | } |
1660 | |
1661 | if (iio_buffer_enabled(indio_dev)) |
1662 | stm32_dfsdm_postenable(indio_dev); |
1663 | |
1664 | return 0; |
1665 | } |
1666 | |
1667 | static DEFINE_SIMPLE_DEV_PM_OPS(stm32_dfsdm_adc_pm_ops, |
1668 | stm32_dfsdm_adc_suspend, |
1669 | stm32_dfsdm_adc_resume); |
1670 | |
1671 | static struct platform_driver stm32_dfsdm_adc_driver = { |
1672 | .driver = { |
1673 | .name = "stm32-dfsdm-adc", |
1674 | .of_match_table = stm32_dfsdm_adc_match, |
1675 | .pm = pm_sleep_ptr(&stm32_dfsdm_adc_pm_ops), |
1676 | }, |
1677 | .probe = stm32_dfsdm_adc_probe, |
1678 | .remove_new = stm32_dfsdm_adc_remove, |
1679 | }; |
1680 | module_platform_driver(stm32_dfsdm_adc_driver); |
1681 | |
1682 | MODULE_DESCRIPTION("STM32 sigma delta ADC"); |
1683 | MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>"); |
1684 | MODULE_LICENSE("GPL v2"); |
1685 |
Definitions
- sd_converter_type
- stm32_dfsdm_dev_data
- stm32_dfsdm_adc
- stm32_dfsdm_str2field
- stm32_dfsdm_chan_type
- stm32_dfsdm_chan_src
- stm32_dfsdm_str2val
- stm32_dfsdm_trig_info
- stm32_dfsdm_jexten
- stm32_dfsdm_trigs
- stm32_dfsdm_get_jextsel
- stm32_dfsdm_compute_osrs
- stm32_dfsdm_compute_all_osrs
- stm32_dfsdm_start_channel
- stm32_dfsdm_stop_channel
- stm32_dfsdm_chan_configure
- stm32_dfsdm_start_filter
- stm32_dfsdm_stop_filter
- stm32_dfsdm_filter_set_trig
- stm32_dfsdm_channels_configure
- stm32_dfsdm_filter_configure
- stm32_dfsdm_channel_parse_of
- dfsdm_adc_audio_get_spiclk
- dfsdm_adc_set_samp_freq
- dfsdm_adc_audio_set_spiclk
- stm32_dfsdm_start_conv
- stm32_dfsdm_stop_conv
- stm32_dfsdm_set_watermark
- stm32_dfsdm_adc_dma_residue
- stm32_dfsdm_process_data
- stm32_dfsdm_dma_buffer_done
- stm32_dfsdm_adc_dma_start
- stm32_dfsdm_adc_dma_stop
- stm32_dfsdm_update_scan_mode
- stm32_dfsdm_postenable
- stm32_dfsdm_predisable
- stm32_dfsdm_buffer_setup_ops
- stm32_dfsdm_get_buff_cb
- stm32_dfsdm_release_buff_cb
- stm32_dfsdm_single_conv
- stm32_dfsdm_write_raw
- stm32_dfsdm_read_raw
- stm32_dfsdm_validate_trigger
- stm32_dfsdm_info_audio
- stm32_dfsdm_info_adc
- stm32_dfsdm_irq
- dfsdm_adc_audio_ext_info
- stm32_dfsdm_dma_release
- stm32_dfsdm_dma_request
- stm32_dfsdm_adc_chan_init_one
- stm32_dfsdm_audio_init
- stm32_dfsdm_adc_init
- stm32h7_dfsdm_adc_data
- stm32h7_dfsdm_audio_data
- stm32_dfsdm_adc_match
- stm32_dfsdm_adc_probe
- stm32_dfsdm_adc_remove
- stm32_dfsdm_adc_suspend
- stm32_dfsdm_adc_resume
- stm32_dfsdm_adc_pm_ops
Improve your Profiling and Debugging skills
Find out more