| .. | .. |
|---|
| 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, |
|---|