.. | .. |
---|
12 | 12 | #include <linux/iio/buffer.h> |
---|
13 | 13 | #include <linux/iio/hw-consumer.h> |
---|
14 | 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> |
---|
15 | 20 | #include <linux/interrupt.h> |
---|
16 | 21 | #include <linux/module.h> |
---|
17 | 22 | #include <linux/of_device.h> |
---|
.. | .. |
---|
34 | 39 | #define DFSDM_MAX_INT_OVERSAMPLING 256 |
---|
35 | 40 | #define DFSDM_MAX_FL_OVERSAMPLING 1024 |
---|
36 | 41 | |
---|
37 | | -/* Max sample resolutions */ |
---|
38 | | -#define DFSDM_MAX_RES BIT(31) |
---|
39 | | -#define DFSDM_DATA_RES BIT(23) |
---|
| 42 | +/* Limit filter output resolution to 31 bits. (i.e. sample range is +/-2^30) */ |
---|
| 43 | +#define DFSDM_DATA_MAX BIT(30) |
---|
| 44 | +/* |
---|
| 45 | + * Data are output as two's complement data in a 24 bit field. |
---|
| 46 | + * Data from filters are in the range +/-2^(n-1) |
---|
| 47 | + * 2^(n-1) maximum positive value cannot be coded in 2's complement n bits |
---|
| 48 | + * An extra bit is required to avoid wrap-around of the binary code for 2^(n-1) |
---|
| 49 | + * So, the resolution of samples from filter is actually limited to 23 bits |
---|
| 50 | + */ |
---|
| 51 | +#define DFSDM_DATA_RES 24 |
---|
| 52 | + |
---|
| 53 | +/* Filter configuration */ |
---|
| 54 | +#define DFSDM_CR1_CFG_MASK (DFSDM_CR1_RCH_MASK | DFSDM_CR1_RCONT_MASK | \ |
---|
| 55 | + DFSDM_CR1_RSYNC_MASK | DFSDM_CR1_JSYNC_MASK | \ |
---|
| 56 | + DFSDM_CR1_JSCAN_MASK) |
---|
40 | 57 | |
---|
41 | 58 | enum sd_converter_type { |
---|
42 | 59 | DFSDM_AUDIO, |
---|
.. | .. |
---|
54 | 71 | struct stm32_dfsdm *dfsdm; |
---|
55 | 72 | const struct stm32_dfsdm_dev_data *dev_data; |
---|
56 | 73 | unsigned int fl_id; |
---|
| 74 | + unsigned int nconv; |
---|
| 75 | + unsigned long smask; |
---|
57 | 76 | |
---|
58 | 77 | /* ADC specific */ |
---|
59 | 78 | unsigned int oversamp; |
---|
.. | .. |
---|
114 | 133 | return -EINVAL; |
---|
115 | 134 | } |
---|
116 | 135 | |
---|
117 | | -static int stm32_dfsdm_set_osrs(struct stm32_dfsdm_filter *fl, |
---|
118 | | - unsigned int fast, unsigned int oversamp) |
---|
| 136 | +/** |
---|
| 137 | + * struct stm32_dfsdm_trig_info - DFSDM trigger info |
---|
| 138 | + * @name: name of the trigger, corresponding to its source |
---|
| 139 | + * @jextsel: trigger signal selection |
---|
| 140 | + */ |
---|
| 141 | +struct stm32_dfsdm_trig_info { |
---|
| 142 | + const char *name; |
---|
| 143 | + unsigned int jextsel; |
---|
| 144 | +}; |
---|
| 145 | + |
---|
| 146 | +/* hardware injected trigger enable, edge selection */ |
---|
| 147 | +enum stm32_dfsdm_jexten { |
---|
| 148 | + STM32_DFSDM_JEXTEN_DISABLED, |
---|
| 149 | + STM32_DFSDM_JEXTEN_RISING_EDGE, |
---|
| 150 | + STM32_DFSDM_JEXTEN_FALLING_EDGE, |
---|
| 151 | + STM32_DFSDM_EXTEN_BOTH_EDGES, |
---|
| 152 | +}; |
---|
| 153 | + |
---|
| 154 | +static const struct stm32_dfsdm_trig_info stm32_dfsdm_trigs[] = { |
---|
| 155 | + { TIM1_TRGO, 0 }, |
---|
| 156 | + { TIM1_TRGO2, 1 }, |
---|
| 157 | + { TIM8_TRGO, 2 }, |
---|
| 158 | + { TIM8_TRGO2, 3 }, |
---|
| 159 | + { TIM3_TRGO, 4 }, |
---|
| 160 | + { TIM4_TRGO, 5 }, |
---|
| 161 | + { TIM16_OC1, 6 }, |
---|
| 162 | + { TIM6_TRGO, 7 }, |
---|
| 163 | + { TIM7_TRGO, 8 }, |
---|
| 164 | + { LPTIM1_OUT, 26 }, |
---|
| 165 | + { LPTIM2_OUT, 27 }, |
---|
| 166 | + { LPTIM3_OUT, 28 }, |
---|
| 167 | + {}, |
---|
| 168 | +}; |
---|
| 169 | + |
---|
| 170 | +static int stm32_dfsdm_get_jextsel(struct iio_dev *indio_dev, |
---|
| 171 | + struct iio_trigger *trig) |
---|
| 172 | +{ |
---|
| 173 | + int i; |
---|
| 174 | + |
---|
| 175 | + /* lookup triggers registered by stm32 timer trigger driver */ |
---|
| 176 | + for (i = 0; stm32_dfsdm_trigs[i].name; i++) { |
---|
| 177 | + /** |
---|
| 178 | + * Checking both stm32 timer trigger type and trig name |
---|
| 179 | + * should be safe against arbitrary trigger names. |
---|
| 180 | + */ |
---|
| 181 | + if ((is_stm32_timer_trigger(trig) || |
---|
| 182 | + is_stm32_lptim_trigger(trig)) && |
---|
| 183 | + !strcmp(stm32_dfsdm_trigs[i].name, trig->name)) { |
---|
| 184 | + return stm32_dfsdm_trigs[i].jextsel; |
---|
| 185 | + } |
---|
| 186 | + } |
---|
| 187 | + |
---|
| 188 | + return -EINVAL; |
---|
| 189 | +} |
---|
| 190 | + |
---|
| 191 | +static int stm32_dfsdm_compute_osrs(struct stm32_dfsdm_filter *fl, |
---|
| 192 | + unsigned int fast, unsigned int oversamp) |
---|
119 | 193 | { |
---|
120 | 194 | unsigned int i, d, fosr, iosr; |
---|
121 | | - u64 res; |
---|
122 | | - s64 delta; |
---|
| 195 | + u64 res, max; |
---|
| 196 | + int bits, shift; |
---|
123 | 197 | unsigned int m = 1; /* multiplication factor */ |
---|
124 | 198 | unsigned int p = fl->ford; /* filter order (ford) */ |
---|
| 199 | + struct stm32_dfsdm_filter_osr *flo = &fl->flo[fast]; |
---|
125 | 200 | |
---|
126 | 201 | pr_debug("%s: Requested oversampling: %d\n", __func__, oversamp); |
---|
127 | 202 | /* |
---|
.. | .. |
---|
140 | 215 | |
---|
141 | 216 | /* |
---|
142 | 217 | * Look for filter and integrator oversampling ratios which allows |
---|
143 | | - * to reach 24 bits data output resolution. |
---|
144 | | - * Leave as soon as if exact resolution if reached. |
---|
145 | | - * Otherwise the higher resolution below 32 bits is kept. |
---|
| 218 | + * to maximize data output resolution. |
---|
146 | 219 | */ |
---|
147 | | - fl->res = 0; |
---|
148 | 220 | for (fosr = 1; fosr <= DFSDM_MAX_FL_OVERSAMPLING; fosr++) { |
---|
149 | 221 | for (iosr = 1; iosr <= DFSDM_MAX_INT_OVERSAMPLING; iosr++) { |
---|
150 | 222 | if (fast) |
---|
.. | .. |
---|
169 | 241 | res = fosr; |
---|
170 | 242 | for (i = p - 1; i > 0; i--) { |
---|
171 | 243 | res = res * (u64)fosr; |
---|
172 | | - if (res > DFSDM_MAX_RES) |
---|
| 244 | + if (res > DFSDM_DATA_MAX) |
---|
173 | 245 | break; |
---|
174 | 246 | } |
---|
175 | | - if (res > DFSDM_MAX_RES) |
---|
| 247 | + if (res > DFSDM_DATA_MAX) |
---|
176 | 248 | continue; |
---|
| 249 | + |
---|
177 | 250 | res = res * (u64)m * (u64)iosr; |
---|
178 | | - if (res > DFSDM_MAX_RES) |
---|
| 251 | + if (res > DFSDM_DATA_MAX) |
---|
179 | 252 | continue; |
---|
180 | 253 | |
---|
181 | | - delta = res - DFSDM_DATA_RES; |
---|
| 254 | + if (res >= flo->res) { |
---|
| 255 | + flo->res = res; |
---|
| 256 | + flo->fosr = fosr; |
---|
| 257 | + flo->iosr = iosr; |
---|
182 | 258 | |
---|
183 | | - if (res >= fl->res) { |
---|
184 | | - fl->res = res; |
---|
185 | | - fl->fosr = fosr; |
---|
186 | | - fl->iosr = iosr; |
---|
187 | | - fl->fast = fast; |
---|
188 | | - pr_debug("%s: fosr = %d, iosr = %d\n", |
---|
189 | | - __func__, fl->fosr, fl->iosr); |
---|
| 259 | + bits = fls(flo->res); |
---|
| 260 | + /* 8 LBSs in data register contain chan info */ |
---|
| 261 | + max = flo->res << 8; |
---|
| 262 | + |
---|
| 263 | + /* if resolution is not a power of two */ |
---|
| 264 | + if (flo->res > BIT(bits - 1)) |
---|
| 265 | + bits++; |
---|
| 266 | + else |
---|
| 267 | + max--; |
---|
| 268 | + |
---|
| 269 | + shift = DFSDM_DATA_RES - bits; |
---|
| 270 | + /* |
---|
| 271 | + * Compute right/left shift |
---|
| 272 | + * Right shift is performed by hardware |
---|
| 273 | + * when transferring samples to data register. |
---|
| 274 | + * Left shift is done by software on buffer |
---|
| 275 | + */ |
---|
| 276 | + if (shift > 0) { |
---|
| 277 | + /* Resolution is lower than 24 bits */ |
---|
| 278 | + flo->rshift = 0; |
---|
| 279 | + flo->lshift = shift; |
---|
| 280 | + } else { |
---|
| 281 | + /* |
---|
| 282 | + * If resolution is 24 bits or more, |
---|
| 283 | + * max positive value may be ambiguous |
---|
| 284 | + * (equal to max negative value as sign |
---|
| 285 | + * bit is dropped). |
---|
| 286 | + * Reduce resolution to 23 bits (rshift) |
---|
| 287 | + * to keep the sign on bit 23 and treat |
---|
| 288 | + * saturation before rescaling on 24 |
---|
| 289 | + * bits (lshift). |
---|
| 290 | + */ |
---|
| 291 | + flo->rshift = 1 - shift; |
---|
| 292 | + flo->lshift = 1; |
---|
| 293 | + max >>= flo->rshift; |
---|
| 294 | + } |
---|
| 295 | + flo->max = (s32)max; |
---|
| 296 | + flo->bits = bits; |
---|
| 297 | + |
---|
| 298 | + pr_debug("%s: fast %d, fosr %d, iosr %d, res 0x%llx/%d bits, rshift %d, lshift %d\n", |
---|
| 299 | + __func__, fast, flo->fosr, flo->iosr, |
---|
| 300 | + flo->res, bits, flo->rshift, |
---|
| 301 | + flo->lshift); |
---|
190 | 302 | } |
---|
191 | | - |
---|
192 | | - if (!delta) |
---|
193 | | - return 0; |
---|
194 | 303 | } |
---|
195 | 304 | } |
---|
196 | 305 | |
---|
197 | | - if (!fl->res) |
---|
| 306 | + if (!flo->res) |
---|
198 | 307 | return -EINVAL; |
---|
199 | 308 | |
---|
200 | 309 | return 0; |
---|
201 | 310 | } |
---|
202 | 311 | |
---|
203 | | -static int stm32_dfsdm_start_channel(struct stm32_dfsdm *dfsdm, |
---|
204 | | - unsigned int ch_id) |
---|
| 312 | +static int stm32_dfsdm_compute_all_osrs(struct iio_dev *indio_dev, |
---|
| 313 | + unsigned int oversamp) |
---|
205 | 314 | { |
---|
206 | | - return regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(ch_id), |
---|
207 | | - DFSDM_CHCFGR1_CHEN_MASK, |
---|
208 | | - DFSDM_CHCFGR1_CHEN(1)); |
---|
| 315 | + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
| 316 | + struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id]; |
---|
| 317 | + int ret0, ret1; |
---|
| 318 | + |
---|
| 319 | + memset(&fl->flo[0], 0, sizeof(fl->flo[0])); |
---|
| 320 | + memset(&fl->flo[1], 0, sizeof(fl->flo[1])); |
---|
| 321 | + |
---|
| 322 | + ret0 = stm32_dfsdm_compute_osrs(fl, 0, oversamp); |
---|
| 323 | + ret1 = stm32_dfsdm_compute_osrs(fl, 1, oversamp); |
---|
| 324 | + if (ret0 < 0 && ret1 < 0) { |
---|
| 325 | + dev_err(&indio_dev->dev, |
---|
| 326 | + "Filter parameters not found: errors %d/%d\n", |
---|
| 327 | + ret0, ret1); |
---|
| 328 | + return -EINVAL; |
---|
| 329 | + } |
---|
| 330 | + |
---|
| 331 | + return 0; |
---|
209 | 332 | } |
---|
210 | 333 | |
---|
211 | | -static void stm32_dfsdm_stop_channel(struct stm32_dfsdm *dfsdm, |
---|
212 | | - unsigned int ch_id) |
---|
| 334 | +static int stm32_dfsdm_start_channel(struct iio_dev *indio_dev) |
---|
213 | 335 | { |
---|
214 | | - regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(ch_id), |
---|
215 | | - DFSDM_CHCFGR1_CHEN_MASK, DFSDM_CHCFGR1_CHEN(0)); |
---|
| 336 | + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
| 337 | + struct regmap *regmap = adc->dfsdm->regmap; |
---|
| 338 | + const struct iio_chan_spec *chan; |
---|
| 339 | + unsigned int bit; |
---|
| 340 | + int ret; |
---|
| 341 | + |
---|
| 342 | + for_each_set_bit(bit, &adc->smask, sizeof(adc->smask) * BITS_PER_BYTE) { |
---|
| 343 | + chan = indio_dev->channels + bit; |
---|
| 344 | + ret = regmap_update_bits(regmap, DFSDM_CHCFGR1(chan->channel), |
---|
| 345 | + DFSDM_CHCFGR1_CHEN_MASK, |
---|
| 346 | + DFSDM_CHCFGR1_CHEN(1)); |
---|
| 347 | + if (ret < 0) |
---|
| 348 | + return ret; |
---|
| 349 | + } |
---|
| 350 | + |
---|
| 351 | + return 0; |
---|
| 352 | +} |
---|
| 353 | + |
---|
| 354 | +static void stm32_dfsdm_stop_channel(struct iio_dev *indio_dev) |
---|
| 355 | +{ |
---|
| 356 | + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
| 357 | + struct regmap *regmap = adc->dfsdm->regmap; |
---|
| 358 | + const struct iio_chan_spec *chan; |
---|
| 359 | + unsigned int bit; |
---|
| 360 | + |
---|
| 361 | + for_each_set_bit(bit, &adc->smask, sizeof(adc->smask) * BITS_PER_BYTE) { |
---|
| 362 | + chan = indio_dev->channels + bit; |
---|
| 363 | + regmap_update_bits(regmap, DFSDM_CHCFGR1(chan->channel), |
---|
| 364 | + DFSDM_CHCFGR1_CHEN_MASK, |
---|
| 365 | + DFSDM_CHCFGR1_CHEN(0)); |
---|
| 366 | + } |
---|
216 | 367 | } |
---|
217 | 368 | |
---|
218 | 369 | static int stm32_dfsdm_chan_configure(struct stm32_dfsdm *dfsdm, |
---|
.. | .. |
---|
237 | 388 | DFSDM_CHCFGR1_CHINSEL(ch->alt_si)); |
---|
238 | 389 | } |
---|
239 | 390 | |
---|
240 | | -static int stm32_dfsdm_start_filter(struct stm32_dfsdm *dfsdm, |
---|
241 | | - unsigned int fl_id) |
---|
| 391 | +static int stm32_dfsdm_start_filter(struct stm32_dfsdm_adc *adc, |
---|
| 392 | + unsigned int fl_id, |
---|
| 393 | + struct iio_trigger *trig) |
---|
242 | 394 | { |
---|
| 395 | + struct stm32_dfsdm *dfsdm = adc->dfsdm; |
---|
243 | 396 | int ret; |
---|
244 | 397 | |
---|
245 | 398 | /* Enable filter */ |
---|
.. | .. |
---|
248 | 401 | if (ret < 0) |
---|
249 | 402 | return ret; |
---|
250 | 403 | |
---|
251 | | - /* Start conversion */ |
---|
| 404 | + /* Nothing more to do for injected (scan mode/triggered) conversions */ |
---|
| 405 | + if (adc->nconv > 1 || trig) |
---|
| 406 | + return 0; |
---|
| 407 | + |
---|
| 408 | + /* Software start (single or continuous) regular conversion */ |
---|
252 | 409 | return regmap_update_bits(dfsdm->regmap, DFSDM_CR1(fl_id), |
---|
253 | 410 | DFSDM_CR1_RSWSTART_MASK, |
---|
254 | 411 | DFSDM_CR1_RSWSTART(1)); |
---|
.. | .. |
---|
262 | 419 | DFSDM_CR1_DFEN_MASK, DFSDM_CR1_DFEN(0)); |
---|
263 | 420 | } |
---|
264 | 421 | |
---|
265 | | -static int stm32_dfsdm_filter_configure(struct stm32_dfsdm *dfsdm, |
---|
266 | | - unsigned int fl_id, unsigned int ch_id) |
---|
| 422 | +static int stm32_dfsdm_filter_set_trig(struct iio_dev *indio_dev, |
---|
| 423 | + unsigned int fl_id, |
---|
| 424 | + struct iio_trigger *trig) |
---|
267 | 425 | { |
---|
268 | | - struct regmap *regmap = dfsdm->regmap; |
---|
269 | | - struct stm32_dfsdm_filter *fl = &dfsdm->fl_list[fl_id]; |
---|
| 426 | + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
| 427 | + struct regmap *regmap = adc->dfsdm->regmap; |
---|
| 428 | + u32 jextsel = 0, jexten = STM32_DFSDM_JEXTEN_DISABLED; |
---|
| 429 | + int ret; |
---|
| 430 | + |
---|
| 431 | + if (trig) { |
---|
| 432 | + ret = stm32_dfsdm_get_jextsel(indio_dev, trig); |
---|
| 433 | + if (ret < 0) |
---|
| 434 | + return ret; |
---|
| 435 | + |
---|
| 436 | + /* set trigger source and polarity (default to rising edge) */ |
---|
| 437 | + jextsel = ret; |
---|
| 438 | + jexten = STM32_DFSDM_JEXTEN_RISING_EDGE; |
---|
| 439 | + } |
---|
| 440 | + |
---|
| 441 | + ret = regmap_update_bits(regmap, DFSDM_CR1(fl_id), |
---|
| 442 | + DFSDM_CR1_JEXTSEL_MASK | DFSDM_CR1_JEXTEN_MASK, |
---|
| 443 | + DFSDM_CR1_JEXTSEL(jextsel) | |
---|
| 444 | + DFSDM_CR1_JEXTEN(jexten)); |
---|
| 445 | + if (ret < 0) |
---|
| 446 | + return ret; |
---|
| 447 | + |
---|
| 448 | + return 0; |
---|
| 449 | +} |
---|
| 450 | + |
---|
| 451 | +static int stm32_dfsdm_channels_configure(struct iio_dev *indio_dev, |
---|
| 452 | + unsigned int fl_id, |
---|
| 453 | + struct iio_trigger *trig) |
---|
| 454 | +{ |
---|
| 455 | + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
| 456 | + struct regmap *regmap = adc->dfsdm->regmap; |
---|
| 457 | + struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id]; |
---|
| 458 | + struct stm32_dfsdm_filter_osr *flo = &fl->flo[0]; |
---|
| 459 | + const struct iio_chan_spec *chan; |
---|
| 460 | + unsigned int bit; |
---|
| 461 | + int ret; |
---|
| 462 | + |
---|
| 463 | + fl->fast = 0; |
---|
| 464 | + |
---|
| 465 | + /* |
---|
| 466 | + * In continuous mode, use fast mode configuration, |
---|
| 467 | + * if it provides a better resolution. |
---|
| 468 | + */ |
---|
| 469 | + if (adc->nconv == 1 && !trig && |
---|
| 470 | + (indio_dev->currentmode & INDIO_BUFFER_SOFTWARE)) { |
---|
| 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(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; |
---|
270 | 509 | int ret; |
---|
271 | 510 | |
---|
272 | 511 | /* Average integrator oversampling */ |
---|
273 | 512 | ret = regmap_update_bits(regmap, DFSDM_FCR(fl_id), DFSDM_FCR_IOSR_MASK, |
---|
274 | | - DFSDM_FCR_IOSR(fl->iosr - 1)); |
---|
| 513 | + DFSDM_FCR_IOSR(flo->iosr - 1)); |
---|
275 | 514 | if (ret) |
---|
276 | 515 | return ret; |
---|
277 | 516 | |
---|
278 | 517 | /* Filter order and Oversampling */ |
---|
279 | 518 | ret = regmap_update_bits(regmap, DFSDM_FCR(fl_id), DFSDM_FCR_FOSR_MASK, |
---|
280 | | - DFSDM_FCR_FOSR(fl->fosr - 1)); |
---|
| 519 | + DFSDM_FCR_FOSR(flo->fosr - 1)); |
---|
281 | 520 | if (ret) |
---|
282 | 521 | return ret; |
---|
283 | 522 | |
---|
.. | .. |
---|
286 | 525 | if (ret) |
---|
287 | 526 | return ret; |
---|
288 | 527 | |
---|
289 | | - /* No scan mode supported for the moment */ |
---|
290 | | - ret = regmap_update_bits(regmap, DFSDM_CR1(fl_id), DFSDM_CR1_RCH_MASK, |
---|
291 | | - DFSDM_CR1_RCH(ch_id)); |
---|
| 528 | + ret = stm32_dfsdm_filter_set_trig(indio_dev, fl_id, trig); |
---|
292 | 529 | if (ret) |
---|
293 | 530 | return ret; |
---|
294 | 531 | |
---|
295 | | - return regmap_update_bits(regmap, DFSDM_CR1(fl_id), |
---|
296 | | - DFSDM_CR1_RSYNC_MASK, |
---|
297 | | - DFSDM_CR1_RSYNC(fl->sync_mode)); |
---|
| 532 | + ret = regmap_update_bits(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 (indio_dev->currentmode & INDIO_BUFFER_SOFTWARE) |
---|
| 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(regmap, DFSDM_JCHGR(fl_id), 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(regmap, DFSDM_CR1(fl_id), DFSDM_CR1_CFG_MASK, |
---|
| 595 | + cr1); |
---|
298 | 596 | } |
---|
299 | 597 | |
---|
300 | 598 | static int stm32_dfsdm_channel_parse_of(struct stm32_dfsdm *dfsdm, |
---|
.. | .. |
---|
378 | 676 | return snprintf(buf, PAGE_SIZE, "%d\n", adc->spi_freq); |
---|
379 | 677 | } |
---|
380 | 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 | + |
---|
381 | 703 | static ssize_t dfsdm_adc_audio_set_spiclk(struct iio_dev *indio_dev, |
---|
382 | 704 | uintptr_t priv, |
---|
383 | 705 | const struct iio_chan_spec *chan, |
---|
384 | 706 | const char *buf, size_t len) |
---|
385 | 707 | { |
---|
386 | 708 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
387 | | - struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id]; |
---|
388 | 709 | struct stm32_dfsdm_channel *ch = &adc->dfsdm->ch_list[chan->channel]; |
---|
389 | 710 | unsigned int sample_freq = adc->sample_freq; |
---|
390 | 711 | unsigned int spi_freq; |
---|
.. | .. |
---|
403 | 724 | return -EINVAL; |
---|
404 | 725 | |
---|
405 | 726 | if (sample_freq) { |
---|
406 | | - if (spi_freq % sample_freq) |
---|
407 | | - dev_warn(&indio_dev->dev, |
---|
408 | | - "Sampling rate not accurate (%d)\n", |
---|
409 | | - spi_freq / (spi_freq / sample_freq)); |
---|
410 | | - |
---|
411 | | - ret = stm32_dfsdm_set_osrs(fl, 0, (spi_freq / sample_freq)); |
---|
412 | | - if (ret < 0) { |
---|
413 | | - dev_err(&indio_dev->dev, |
---|
414 | | - "No filter parameters that match!\n"); |
---|
| 727 | + ret = dfsdm_adc_set_samp_freq(indio_dev, sample_freq, spi_freq); |
---|
| 728 | + if (ret < 0) |
---|
415 | 729 | return ret; |
---|
416 | | - } |
---|
417 | 730 | } |
---|
418 | 731 | adc->spi_freq = spi_freq; |
---|
419 | 732 | |
---|
420 | 733 | return len; |
---|
421 | 734 | } |
---|
422 | 735 | |
---|
423 | | -static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc, |
---|
424 | | - const struct iio_chan_spec *chan, |
---|
425 | | - bool dma) |
---|
| 736 | +static int stm32_dfsdm_start_conv(struct iio_dev *indio_dev, |
---|
| 737 | + struct iio_trigger *trig) |
---|
426 | 738 | { |
---|
| 739 | + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
427 | 740 | struct regmap *regmap = adc->dfsdm->regmap; |
---|
428 | 741 | int ret; |
---|
429 | | - unsigned int dma_en = 0, cont_en = 0; |
---|
430 | 742 | |
---|
431 | | - ret = stm32_dfsdm_start_channel(adc->dfsdm, chan->channel); |
---|
| 743 | + ret = stm32_dfsdm_channels_configure(indio_dev, adc->fl_id, trig); |
---|
432 | 744 | if (ret < 0) |
---|
433 | 745 | return ret; |
---|
434 | 746 | |
---|
435 | | - ret = stm32_dfsdm_filter_configure(adc->dfsdm, adc->fl_id, |
---|
436 | | - chan->channel); |
---|
| 747 | + ret = stm32_dfsdm_start_channel(indio_dev); |
---|
| 748 | + if (ret < 0) |
---|
| 749 | + return ret; |
---|
| 750 | + |
---|
| 751 | + ret = stm32_dfsdm_filter_configure(indio_dev, adc->fl_id, trig); |
---|
437 | 752 | if (ret < 0) |
---|
438 | 753 | goto stop_channels; |
---|
439 | 754 | |
---|
440 | | - if (dma) { |
---|
441 | | - /* Enable DMA transfer*/ |
---|
442 | | - dma_en = DFSDM_CR1_RDMAEN(1); |
---|
443 | | - /* Enable conversion triggered by SPI clock*/ |
---|
444 | | - cont_en = DFSDM_CR1_RCONT(1); |
---|
445 | | - } |
---|
446 | | - /* Enable DMA transfer*/ |
---|
447 | | - ret = regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), |
---|
448 | | - DFSDM_CR1_RDMAEN_MASK, dma_en); |
---|
| 755 | + ret = stm32_dfsdm_start_filter(adc, adc->fl_id, trig); |
---|
449 | 756 | if (ret < 0) |
---|
450 | | - goto stop_channels; |
---|
451 | | - |
---|
452 | | - /* Enable conversion triggered by SPI clock*/ |
---|
453 | | - ret = regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), |
---|
454 | | - DFSDM_CR1_RCONT_MASK, cont_en); |
---|
455 | | - if (ret < 0) |
---|
456 | | - goto stop_channels; |
---|
457 | | - |
---|
458 | | - ret = stm32_dfsdm_start_filter(adc->dfsdm, adc->fl_id); |
---|
459 | | - if (ret < 0) |
---|
460 | | - goto stop_channels; |
---|
| 757 | + goto filter_unconfigure; |
---|
461 | 758 | |
---|
462 | 759 | return 0; |
---|
463 | 760 | |
---|
| 761 | +filter_unconfigure: |
---|
| 762 | + regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), |
---|
| 763 | + DFSDM_CR1_CFG_MASK, 0); |
---|
464 | 764 | stop_channels: |
---|
465 | | - regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), |
---|
466 | | - DFSDM_CR1_RDMAEN_MASK, 0); |
---|
467 | | - |
---|
468 | | - regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), |
---|
469 | | - DFSDM_CR1_RCONT_MASK, 0); |
---|
470 | | - stm32_dfsdm_stop_channel(adc->dfsdm, chan->channel); |
---|
| 765 | + stm32_dfsdm_stop_channel(indio_dev); |
---|
471 | 766 | |
---|
472 | 767 | return ret; |
---|
473 | 768 | } |
---|
474 | 769 | |
---|
475 | | -static void stm32_dfsdm_stop_conv(struct stm32_dfsdm_adc *adc, |
---|
476 | | - const struct iio_chan_spec *chan) |
---|
| 770 | +static void stm32_dfsdm_stop_conv(struct iio_dev *indio_dev) |
---|
477 | 771 | { |
---|
| 772 | + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
478 | 773 | struct regmap *regmap = adc->dfsdm->regmap; |
---|
479 | 774 | |
---|
480 | 775 | stm32_dfsdm_stop_filter(adc->dfsdm, adc->fl_id); |
---|
481 | 776 | |
---|
482 | | - /* Clean conversion options */ |
---|
483 | 777 | regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), |
---|
484 | | - DFSDM_CR1_RDMAEN_MASK, 0); |
---|
| 778 | + DFSDM_CR1_CFG_MASK, 0); |
---|
485 | 779 | |
---|
486 | | - regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), |
---|
487 | | - DFSDM_CR1_RCONT_MASK, 0); |
---|
488 | | - |
---|
489 | | - stm32_dfsdm_stop_channel(adc->dfsdm, chan->channel); |
---|
| 780 | + stm32_dfsdm_stop_channel(indio_dev); |
---|
490 | 781 | } |
---|
491 | 782 | |
---|
492 | 783 | static int stm32_dfsdm_set_watermark(struct iio_dev *indio_dev, |
---|
.. | .. |
---|
494 | 785 | { |
---|
495 | 786 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
496 | 787 | unsigned int watermark = DFSDM_DMA_BUFFER_SIZE / 2; |
---|
| 788 | + unsigned int rx_buf_sz = DFSDM_DMA_BUFFER_SIZE; |
---|
497 | 789 | |
---|
498 | 790 | /* |
---|
499 | 791 | * DMA cyclic transfers are used, buffer is split into two periods. |
---|
.. | .. |
---|
502 | 794 | * - one buffer (period) driver pushed to ASoC side. |
---|
503 | 795 | */ |
---|
504 | 796 | watermark = min(watermark, val * (unsigned int)(sizeof(u32))); |
---|
505 | | - adc->buf_sz = watermark * 2; |
---|
| 797 | + adc->buf_sz = min(rx_buf_sz, watermark * 2 * adc->nconv); |
---|
506 | 798 | |
---|
507 | 799 | return 0; |
---|
508 | 800 | } |
---|
.. | .. |
---|
532 | 824 | return 0; |
---|
533 | 825 | } |
---|
534 | 826 | |
---|
535 | | -static void stm32_dfsdm_audio_dma_buffer_done(void *data) |
---|
| 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) |
---|
536 | 852 | { |
---|
537 | 853 | struct iio_dev *indio_dev = data; |
---|
538 | 854 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
.. | .. |
---|
553 | 869 | old_pos = adc->bufi; |
---|
554 | 870 | |
---|
555 | 871 | while (available >= indio_dev->scan_bytes) { |
---|
556 | | - u32 *buffer = (u32 *)&adc->rx_buf[adc->bufi]; |
---|
| 872 | + s32 *buffer = (s32 *)&adc->rx_buf[adc->bufi]; |
---|
557 | 873 | |
---|
558 | | - /* Mask 8 LSB that contains the channel ID */ |
---|
559 | | - *buffer = (*buffer & 0xFFFFFF00) << 8; |
---|
| 874 | + stm32_dfsdm_process_data(adc, buffer); |
---|
| 875 | + |
---|
560 | 876 | available -= indio_dev->scan_bytes; |
---|
561 | 877 | adc->bufi += indio_dev->scan_bytes; |
---|
562 | 878 | if (adc->bufi >= adc->buf_sz) { |
---|
.. | .. |
---|
566 | 882 | adc->bufi = 0; |
---|
567 | 883 | old_pos = 0; |
---|
568 | 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, buffer); |
---|
569 | 896 | } |
---|
570 | 897 | if (adc->cb) |
---|
571 | 898 | adc->cb(&adc->rx_buf[old_pos], adc->bufi - old_pos, |
---|
.. | .. |
---|
575 | 902 | static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev) |
---|
576 | 903 | { |
---|
577 | 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 | + }; |
---|
578 | 914 | struct dma_async_tx_descriptor *desc; |
---|
579 | 915 | dma_cookie_t cookie; |
---|
580 | 916 | int ret; |
---|
.. | .. |
---|
585 | 921 | dev_dbg(&indio_dev->dev, "%s size=%d watermark=%d\n", __func__, |
---|
586 | 922 | adc->buf_sz, adc->buf_sz / 2); |
---|
587 | 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(adc->dma_chan, &config); |
---|
| 929 | + if (ret) |
---|
| 930 | + return ret; |
---|
| 931 | + |
---|
588 | 932 | /* Prepare a DMA cyclic transaction */ |
---|
589 | 933 | desc = dmaengine_prep_dma_cyclic(adc->dma_chan, |
---|
590 | 934 | adc->dma_buf, |
---|
.. | .. |
---|
594 | 938 | if (!desc) |
---|
595 | 939 | return -EBUSY; |
---|
596 | 940 | |
---|
597 | | - desc->callback = stm32_dfsdm_audio_dma_buffer_done; |
---|
| 941 | + desc->callback = stm32_dfsdm_dma_buffer_done; |
---|
598 | 942 | desc->callback_param = indio_dev; |
---|
599 | 943 | |
---|
600 | 944 | cookie = dmaengine_submit(desc); |
---|
601 | 945 | ret = dma_submit_error(cookie); |
---|
602 | | - if (ret) { |
---|
603 | | - dmaengine_terminate_all(adc->dma_chan); |
---|
604 | | - return ret; |
---|
605 | | - } |
---|
| 946 | + if (ret) |
---|
| 947 | + goto err_stop_dma; |
---|
606 | 948 | |
---|
607 | 949 | /* Issue pending DMA requests */ |
---|
608 | 950 | dma_async_issue_pending(adc->dma_chan); |
---|
| 951 | + |
---|
| 952 | + if (adc->nconv == 1 && !indio_dev->trig) { |
---|
| 953 | + /* Enable regular DMA transfer*/ |
---|
| 954 | + ret = regmap_update_bits(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(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(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(adc->dfsdm->regmap, DFSDM_CR1(adc->fl_id), |
---|
| 985 | + DFSDM_CR1_RDMAEN_MASK | DFSDM_CR1_JDMAEN_MASK, 0); |
---|
| 986 | + dmaengine_terminate_all(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(scan_mask, indio_dev->masklength); |
---|
| 995 | + adc->smask = *scan_mask; |
---|
| 996 | + |
---|
| 997 | + dev_dbg(&indio_dev->dev, "nconv=%d mask=%lx\n", adc->nconv, *scan_mask); |
---|
609 | 998 | |
---|
610 | 999 | return 0; |
---|
611 | 1000 | } |
---|
.. | .. |
---|
613 | 1002 | static int stm32_dfsdm_postenable(struct iio_dev *indio_dev) |
---|
614 | 1003 | { |
---|
615 | 1004 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
616 | | - const struct iio_chan_spec *chan = &indio_dev->channels[0]; |
---|
617 | 1005 | int ret; |
---|
618 | 1006 | |
---|
619 | 1007 | /* Reset adc buffer index */ |
---|
620 | 1008 | adc->bufi = 0; |
---|
621 | 1009 | |
---|
| 1010 | + if (adc->hwc) { |
---|
| 1011 | + ret = iio_hw_consumer_enable(adc->hwc); |
---|
| 1012 | + if (ret < 0) |
---|
| 1013 | + return ret; |
---|
| 1014 | + } |
---|
| 1015 | + |
---|
622 | 1016 | ret = stm32_dfsdm_start_dfsdm(adc->dfsdm); |
---|
623 | 1017 | if (ret < 0) |
---|
624 | | - return ret; |
---|
| 1018 | + goto err_stop_hwc; |
---|
625 | 1019 | |
---|
626 | | - ret = stm32_dfsdm_start_conv(adc, chan, true); |
---|
| 1020 | + ret = stm32_dfsdm_adc_dma_start(indio_dev); |
---|
627 | 1021 | if (ret) { |
---|
628 | | - dev_err(&indio_dev->dev, "Can't start conversion\n"); |
---|
| 1022 | + dev_err(&indio_dev->dev, "Can't start DMA\n"); |
---|
629 | 1023 | goto stop_dfsdm; |
---|
630 | 1024 | } |
---|
631 | 1025 | |
---|
632 | | - if (adc->dma_chan) { |
---|
633 | | - ret = stm32_dfsdm_adc_dma_start(indio_dev); |
---|
634 | | - if (ret) { |
---|
635 | | - dev_err(&indio_dev->dev, "Can't start DMA\n"); |
---|
636 | | - goto err_stop_conv; |
---|
637 | | - } |
---|
| 1026 | + ret = stm32_dfsdm_start_conv(indio_dev, indio_dev->trig); |
---|
| 1027 | + if (ret) { |
---|
| 1028 | + dev_err(&indio_dev->dev, "Can't start conversion\n"); |
---|
| 1029 | + goto err_stop_dma; |
---|
638 | 1030 | } |
---|
639 | 1031 | |
---|
640 | 1032 | return 0; |
---|
641 | 1033 | |
---|
642 | | -err_stop_conv: |
---|
643 | | - stm32_dfsdm_stop_conv(adc, chan); |
---|
| 1034 | +err_stop_dma: |
---|
| 1035 | + stm32_dfsdm_adc_dma_stop(indio_dev); |
---|
644 | 1036 | stop_dfsdm: |
---|
645 | 1037 | stm32_dfsdm_stop_dfsdm(adc->dfsdm); |
---|
| 1038 | +err_stop_hwc: |
---|
| 1039 | + if (adc->hwc) |
---|
| 1040 | + iio_hw_consumer_disable(adc->hwc); |
---|
646 | 1041 | |
---|
647 | 1042 | return ret; |
---|
648 | 1043 | } |
---|
.. | .. |
---|
650 | 1045 | static int stm32_dfsdm_predisable(struct iio_dev *indio_dev) |
---|
651 | 1046 | { |
---|
652 | 1047 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
653 | | - const struct iio_chan_spec *chan = &indio_dev->channels[0]; |
---|
654 | 1048 | |
---|
655 | | - if (adc->dma_chan) |
---|
656 | | - dmaengine_terminate_all(adc->dma_chan); |
---|
| 1049 | + stm32_dfsdm_stop_conv(indio_dev); |
---|
657 | 1050 | |
---|
658 | | - stm32_dfsdm_stop_conv(adc, chan); |
---|
| 1051 | + stm32_dfsdm_adc_dma_stop(indio_dev); |
---|
659 | 1052 | |
---|
660 | 1053 | stm32_dfsdm_stop_dfsdm(adc->dfsdm); |
---|
| 1054 | + |
---|
| 1055 | + if (adc->hwc) |
---|
| 1056 | + iio_hw_consumer_disable(adc->hwc); |
---|
661 | 1057 | |
---|
662 | 1058 | return 0; |
---|
663 | 1059 | } |
---|
.. | .. |
---|
736 | 1132 | if (ret < 0) |
---|
737 | 1133 | goto stop_dfsdm; |
---|
738 | 1134 | |
---|
739 | | - ret = stm32_dfsdm_start_conv(adc, chan, false); |
---|
| 1135 | + adc->nconv = 1; |
---|
| 1136 | + adc->smask = BIT(chan->scan_index); |
---|
| 1137 | + ret = stm32_dfsdm_start_conv(indio_dev, NULL); |
---|
740 | 1138 | if (ret < 0) { |
---|
741 | 1139 | regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR2(adc->fl_id), |
---|
742 | 1140 | DFSDM_CR2_REOCIE_MASK, DFSDM_CR2_REOCIE(0)); |
---|
.. | .. |
---|
757 | 1155 | else |
---|
758 | 1156 | ret = IIO_VAL_INT; |
---|
759 | 1157 | |
---|
760 | | - stm32_dfsdm_stop_conv(adc, chan); |
---|
| 1158 | + stm32_dfsdm_stop_conv(indio_dev); |
---|
| 1159 | + |
---|
| 1160 | + stm32_dfsdm_process_data(adc, res); |
---|
761 | 1161 | |
---|
762 | 1162 | stop_dfsdm: |
---|
763 | 1163 | stm32_dfsdm_stop_dfsdm(adc->dfsdm); |
---|
.. | .. |
---|
770 | 1170 | int val, int val2, long mask) |
---|
771 | 1171 | { |
---|
772 | 1172 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
773 | | - struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id]; |
---|
774 | 1173 | struct stm32_dfsdm_channel *ch = &adc->dfsdm->ch_list[chan->channel]; |
---|
775 | 1174 | unsigned int spi_freq; |
---|
776 | 1175 | int ret = -EINVAL; |
---|
777 | 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 | + |
---|
778 | 1189 | switch (mask) { |
---|
779 | 1190 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: |
---|
780 | | - ret = stm32_dfsdm_set_osrs(fl, 0, val); |
---|
781 | | - if (!ret) |
---|
782 | | - adc->oversamp = val; |
---|
| 1191 | + ret = iio_device_claim_direct_mode(indio_dev); |
---|
| 1192 | + if (ret) |
---|
| 1193 | + return ret; |
---|
783 | 1194 | |
---|
| 1195 | + ret = stm32_dfsdm_compute_all_osrs(indio_dev, 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); |
---|
784 | 1204 | return ret; |
---|
785 | 1205 | |
---|
786 | 1206 | case IIO_CHAN_INFO_SAMP_FREQ: |
---|
787 | 1207 | if (!val) |
---|
788 | 1208 | return -EINVAL; |
---|
789 | 1209 | |
---|
790 | | - switch (ch->src) { |
---|
791 | | - case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL: |
---|
792 | | - spi_freq = adc->dfsdm->spi_master_freq; |
---|
793 | | - break; |
---|
794 | | - case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING: |
---|
795 | | - case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING: |
---|
796 | | - spi_freq = adc->dfsdm->spi_master_freq / 2; |
---|
797 | | - break; |
---|
798 | | - default: |
---|
799 | | - spi_freq = adc->spi_freq; |
---|
800 | | - } |
---|
801 | | - |
---|
802 | | - if (spi_freq % val) |
---|
803 | | - dev_warn(&indio_dev->dev, |
---|
804 | | - "Sampling rate not accurate (%d)\n", |
---|
805 | | - spi_freq / (spi_freq / val)); |
---|
806 | | - |
---|
807 | | - ret = stm32_dfsdm_set_osrs(fl, 0, (spi_freq / val)); |
---|
808 | | - if (ret < 0) { |
---|
809 | | - dev_err(&indio_dev->dev, |
---|
810 | | - "Not able to find parameter that match!\n"); |
---|
| 1210 | + ret = iio_device_claim_direct_mode(indio_dev); |
---|
| 1211 | + if (ret) |
---|
811 | 1212 | return ret; |
---|
812 | | - } |
---|
813 | | - adc->sample_freq = val; |
---|
814 | 1213 | |
---|
815 | | - return 0; |
---|
| 1214 | + ret = dfsdm_adc_set_samp_freq(indio_dev, val, spi_freq); |
---|
| 1215 | + iio_device_release_direct_mode(indio_dev); |
---|
| 1216 | + return ret; |
---|
816 | 1217 | } |
---|
817 | 1218 | |
---|
818 | 1219 | return -EINVAL; |
---|
.. | .. |
---|
827 | 1228 | |
---|
828 | 1229 | switch (mask) { |
---|
829 | 1230 | case IIO_CHAN_INFO_RAW: |
---|
| 1231 | + ret = iio_device_claim_direct_mode(indio_dev); |
---|
| 1232 | + if (ret) |
---|
| 1233 | + return ret; |
---|
830 | 1234 | ret = iio_hw_consumer_enable(adc->hwc); |
---|
831 | 1235 | if (ret < 0) { |
---|
832 | 1236 | dev_err(&indio_dev->dev, |
---|
833 | 1237 | "%s: IIO enable failed (channel %d)\n", |
---|
834 | 1238 | __func__, chan->channel); |
---|
| 1239 | + iio_device_release_direct_mode(indio_dev); |
---|
835 | 1240 | return ret; |
---|
836 | 1241 | } |
---|
837 | 1242 | ret = stm32_dfsdm_single_conv(indio_dev, chan, val); |
---|
.. | .. |
---|
840 | 1245 | dev_err(&indio_dev->dev, |
---|
841 | 1246 | "%s: Conversion failed (channel %d)\n", |
---|
842 | 1247 | __func__, chan->channel); |
---|
| 1248 | + iio_device_release_direct_mode(indio_dev); |
---|
843 | 1249 | return ret; |
---|
844 | 1250 | } |
---|
| 1251 | + iio_device_release_direct_mode(indio_dev); |
---|
845 | 1252 | return IIO_VAL_INT; |
---|
846 | 1253 | |
---|
847 | 1254 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: |
---|
.. | .. |
---|
858 | 1265 | return -EINVAL; |
---|
859 | 1266 | } |
---|
860 | 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 | + |
---|
861 | 1274 | static const struct iio_info stm32_dfsdm_info_audio = { |
---|
862 | 1275 | .hwfifo_set_watermark = stm32_dfsdm_set_watermark, |
---|
863 | 1276 | .read_raw = stm32_dfsdm_read_raw, |
---|
864 | 1277 | .write_raw = stm32_dfsdm_write_raw, |
---|
| 1278 | + .update_scan_mode = stm32_dfsdm_update_scan_mode, |
---|
865 | 1279 | }; |
---|
866 | 1280 | |
---|
867 | 1281 | static const struct iio_info stm32_dfsdm_info_adc = { |
---|
| 1282 | + .hwfifo_set_watermark = stm32_dfsdm_set_watermark, |
---|
868 | 1283 | .read_raw = stm32_dfsdm_read_raw, |
---|
869 | 1284 | .write_raw = stm32_dfsdm_write_raw, |
---|
| 1285 | + .update_scan_mode = stm32_dfsdm_update_scan_mode, |
---|
| 1286 | + .validate_trigger = stm32_dfsdm_validate_trigger, |
---|
870 | 1287 | }; |
---|
871 | 1288 | |
---|
872 | 1289 | static irqreturn_t stm32_dfsdm_irq(int irq, void *arg) |
---|
873 | 1290 | { |
---|
874 | | - struct stm32_dfsdm_adc *adc = arg; |
---|
875 | | - struct iio_dev *indio_dev = iio_priv_to_dev(adc); |
---|
| 1291 | + struct iio_dev *indio_dev = arg; |
---|
| 1292 | + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
876 | 1293 | struct regmap *regmap = adc->dfsdm->regmap; |
---|
877 | 1294 | unsigned int status, int_en; |
---|
878 | 1295 | |
---|
.. | .. |
---|
927 | 1344 | struct iio_dev *indio_dev) |
---|
928 | 1345 | { |
---|
929 | 1346 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
930 | | - struct dma_slave_config config = { |
---|
931 | | - .src_addr = (dma_addr_t)adc->dfsdm->phys_base + |
---|
932 | | - DFSDM_RDATAR(adc->fl_id), |
---|
933 | | - .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, |
---|
934 | | - }; |
---|
935 | | - int ret; |
---|
936 | 1347 | |
---|
937 | 1348 | adc->dma_chan = dma_request_chan(dev, "rx"); |
---|
938 | 1349 | if (IS_ERR(adc->dma_chan)) { |
---|
.. | .. |
---|
946 | 1357 | DFSDM_DMA_BUFFER_SIZE, |
---|
947 | 1358 | &adc->dma_buf, GFP_KERNEL); |
---|
948 | 1359 | if (!adc->rx_buf) { |
---|
949 | | - ret = -ENOMEM; |
---|
950 | | - goto err_release; |
---|
| 1360 | + dma_release_channel(adc->dma_chan); |
---|
| 1361 | + return -ENOMEM; |
---|
951 | 1362 | } |
---|
952 | 1363 | |
---|
953 | | - ret = dmaengine_slave_config(adc->dma_chan, &config); |
---|
954 | | - if (ret) |
---|
955 | | - goto err_free; |
---|
| 1364 | + indio_dev->modes |= INDIO_BUFFER_SOFTWARE; |
---|
| 1365 | + indio_dev->setup_ops = &stm32_dfsdm_buffer_setup_ops; |
---|
956 | 1366 | |
---|
957 | 1367 | return 0; |
---|
958 | | - |
---|
959 | | -err_free: |
---|
960 | | - dma_free_coherent(adc->dma_chan->device->dev, DFSDM_DMA_BUFFER_SIZE, |
---|
961 | | - adc->rx_buf, adc->dma_buf); |
---|
962 | | -err_release: |
---|
963 | | - dma_release_channel(adc->dma_chan); |
---|
964 | | - |
---|
965 | | - return ret; |
---|
966 | 1368 | } |
---|
967 | 1369 | |
---|
968 | 1370 | static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev, |
---|
.. | .. |
---|
983 | 1385 | * IIO_CHAN_INFO_OVERSAMPLING_RATIO: used to set oversampling |
---|
984 | 1386 | */ |
---|
985 | 1387 | ch->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); |
---|
986 | | - ch->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); |
---|
| 1388 | + ch->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) | |
---|
| 1389 | + BIT(IIO_CHAN_INFO_SAMP_FREQ); |
---|
987 | 1390 | |
---|
988 | 1391 | if (adc->dev_data->type == DFSDM_AUDIO) { |
---|
989 | 1392 | ch->ext_info = dfsdm_adc_audio_ext_info; |
---|
.. | .. |
---|
1004 | 1407 | struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
1005 | 1408 | struct stm32_dfsdm_channel *d_ch; |
---|
1006 | 1409 | int ret; |
---|
1007 | | - |
---|
1008 | | - indio_dev->modes |= INDIO_BUFFER_SOFTWARE; |
---|
1009 | | - indio_dev->setup_ops = &stm32_dfsdm_buffer_setup_ops; |
---|
1010 | 1410 | |
---|
1011 | 1411 | ch = devm_kzalloc(&indio_dev->dev, sizeof(*ch), GFP_KERNEL); |
---|
1012 | 1412 | if (!ch) |
---|
.. | .. |
---|
1039 | 1439 | int ret, chan_idx; |
---|
1040 | 1440 | |
---|
1041 | 1441 | adc->oversamp = DFSDM_DEFAULT_OVERSAMPLING; |
---|
1042 | | - ret = stm32_dfsdm_set_osrs(&adc->dfsdm->fl_list[adc->fl_id], 0, |
---|
1043 | | - adc->oversamp); |
---|
| 1442 | + ret = stm32_dfsdm_compute_all_osrs(indio_dev, adc->oversamp); |
---|
1044 | 1443 | if (ret < 0) |
---|
1045 | 1444 | return ret; |
---|
1046 | 1445 | |
---|
.. | .. |
---|
1075 | 1474 | |
---|
1076 | 1475 | init_completion(&adc->completion); |
---|
1077 | 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, ret, |
---|
| 1482 | + "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 | + |
---|
1078 | 1500 | return 0; |
---|
1079 | 1501 | } |
---|
1080 | 1502 | |
---|
.. | .. |
---|
1099 | 1521 | }, |
---|
1100 | 1522 | {} |
---|
1101 | 1523 | }; |
---|
| 1524 | +MODULE_DEVICE_TABLE(of, stm32_dfsdm_adc_match); |
---|
1102 | 1525 | |
---|
1103 | 1526 | static int stm32_dfsdm_adc_probe(struct platform_device *pdev) |
---|
1104 | 1527 | { |
---|
.. | .. |
---|
1120 | 1543 | adc = iio_priv(iio); |
---|
1121 | 1544 | adc->dfsdm = dev_get_drvdata(dev->parent); |
---|
1122 | 1545 | |
---|
1123 | | - iio->dev.parent = dev; |
---|
1124 | 1546 | iio->dev.of_node = np; |
---|
1125 | | - iio->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; |
---|
| 1547 | + iio->modes = INDIO_DIRECT_MODE; |
---|
1126 | 1548 | |
---|
1127 | | - platform_set_drvdata(pdev, adc); |
---|
| 1549 | + platform_set_drvdata(pdev, iio); |
---|
1128 | 1550 | |
---|
1129 | 1551 | ret = of_property_read_u32(dev->of_node, "reg", &adc->fl_id); |
---|
1130 | 1552 | if (ret != 0 || adc->fl_id >= adc->dfsdm->num_fls) { |
---|
.. | .. |
---|
1149 | 1571 | * So IRQ associated to filter instance 0 is dedicated to the Filter 0. |
---|
1150 | 1572 | */ |
---|
1151 | 1573 | irq = platform_get_irq(pdev, 0); |
---|
1152 | | - if (irq < 0) { |
---|
1153 | | - if (irq != -EPROBE_DEFER) |
---|
1154 | | - dev_err(dev, "Failed to get IRQ: %d\n", irq); |
---|
| 1574 | + if (irq < 0) |
---|
1155 | 1575 | return irq; |
---|
1156 | | - } |
---|
1157 | 1576 | |
---|
1158 | 1577 | ret = devm_request_irq(dev, irq, stm32_dfsdm_irq, |
---|
1159 | | - 0, pdev->name, adc); |
---|
| 1578 | + 0, pdev->name, iio); |
---|
1160 | 1579 | if (ret < 0) { |
---|
1161 | 1580 | dev_err(dev, "Failed to request IRQ\n"); |
---|
1162 | 1581 | return ret; |
---|
.. | .. |
---|
1203 | 1622 | |
---|
1204 | 1623 | static int stm32_dfsdm_adc_remove(struct platform_device *pdev) |
---|
1205 | 1624 | { |
---|
1206 | | - struct stm32_dfsdm_adc *adc = platform_get_drvdata(pdev); |
---|
1207 | | - struct iio_dev *indio_dev = iio_priv_to_dev(adc); |
---|
| 1625 | + struct iio_dev *indio_dev = platform_get_drvdata(pdev); |
---|
| 1626 | + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
1208 | 1627 | |
---|
1209 | 1628 | if (adc->dev_data->type == DFSDM_AUDIO) |
---|
1210 | 1629 | of_platform_depopulate(&pdev->dev); |
---|
.. | .. |
---|
1214 | 1633 | return 0; |
---|
1215 | 1634 | } |
---|
1216 | 1635 | |
---|
| 1636 | +static int __maybe_unused stm32_dfsdm_adc_suspend(struct device *dev) |
---|
| 1637 | +{ |
---|
| 1638 | + struct iio_dev *indio_dev = dev_get_drvdata(dev); |
---|
| 1639 | + |
---|
| 1640 | + if (iio_buffer_enabled(indio_dev)) |
---|
| 1641 | + stm32_dfsdm_predisable(indio_dev); |
---|
| 1642 | + |
---|
| 1643 | + return 0; |
---|
| 1644 | +} |
---|
| 1645 | + |
---|
| 1646 | +static int __maybe_unused stm32_dfsdm_adc_resume(struct device *dev) |
---|
| 1647 | +{ |
---|
| 1648 | + struct iio_dev *indio_dev = dev_get_drvdata(dev); |
---|
| 1649 | + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); |
---|
| 1650 | + const struct iio_chan_spec *chan; |
---|
| 1651 | + struct stm32_dfsdm_channel *ch; |
---|
| 1652 | + int i, ret; |
---|
| 1653 | + |
---|
| 1654 | + /* restore channels configuration */ |
---|
| 1655 | + for (i = 0; i < indio_dev->num_channels; i++) { |
---|
| 1656 | + chan = indio_dev->channels + i; |
---|
| 1657 | + ch = &adc->dfsdm->ch_list[chan->channel]; |
---|
| 1658 | + ret = stm32_dfsdm_chan_configure(adc->dfsdm, ch); |
---|
| 1659 | + if (ret) |
---|
| 1660 | + return ret; |
---|
| 1661 | + } |
---|
| 1662 | + |
---|
| 1663 | + if (iio_buffer_enabled(indio_dev)) |
---|
| 1664 | + stm32_dfsdm_postenable(indio_dev); |
---|
| 1665 | + |
---|
| 1666 | + return 0; |
---|
| 1667 | +} |
---|
| 1668 | + |
---|
| 1669 | +static SIMPLE_DEV_PM_OPS(stm32_dfsdm_adc_pm_ops, |
---|
| 1670 | + stm32_dfsdm_adc_suspend, stm32_dfsdm_adc_resume); |
---|
| 1671 | + |
---|
1217 | 1672 | static struct platform_driver stm32_dfsdm_adc_driver = { |
---|
1218 | 1673 | .driver = { |
---|
1219 | 1674 | .name = "stm32-dfsdm-adc", |
---|
1220 | 1675 | .of_match_table = stm32_dfsdm_adc_match, |
---|
| 1676 | + .pm = &stm32_dfsdm_adc_pm_ops, |
---|
1221 | 1677 | }, |
---|
1222 | 1678 | .probe = stm32_dfsdm_adc_probe, |
---|
1223 | 1679 | .remove = stm32_dfsdm_adc_remove, |
---|