aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaud Pouliquen <arnaud.pouliquen@st.com>2018-01-10 05:13:11 -0500
committerMark Brown <broonie@kernel.org>2018-01-10 05:30:12 -0500
commite2e6771c646251657fafb2a78db566d5c2c70635 (patch)
treeaa1ebf0a0ff9f1a289112b22938622622dea2add
parentbed73904e76fc08d0ec3a7ba3eb2ddbb2e38862c (diff)
IIO: ADC: add STM32 DFSDM sigma delta ADC support
Add DFSDM driver to handle sigma delta ADC. Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/iio/adc/Kconfig13
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/stm32-dfsdm-adc.c728
3 files changed, 742 insertions, 0 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 776192e68ad5..39e3b345a6c8 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -680,6 +680,19 @@ config STM32_DFSDM_CORE
680 This driver can also be built as a module. If so, the module 680 This driver can also be built as a module. If so, the module
681 will be called stm32-dfsdm-core. 681 will be called stm32-dfsdm-core.
682 682
683config STM32_DFSDM_ADC
684 tristate "STMicroelectronics STM32 dfsdm adc"
685 depends on (ARCH_STM32 && OF) || COMPILE_TEST
686 select STM32_DFSDM_CORE
687 select REGMAP_MMIO
688 select IIO_BUFFER_HW_CONSUMER
689 help
690 Select this option to support ADCSigma delta modulator for
691 STMicroelectronics STM32 digital filter for sigma delta converter.
692
693 This driver can also be built as a module. If so, the module
694 will be called stm32-dfsdm-adc.
695
683config STX104 696config STX104
684 tristate "Apex Embedded Systems STX104 driver" 697 tristate "Apex Embedded Systems STX104 driver"
685 depends on PC104 && X86 && ISA_BUS_API 698 depends on PC104 && X86 && ISA_BUS_API
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 8dda348f1920..28a9423997f3 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_SUN4I_GPADC) += sun4i-gpadc-iio.o
65obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o 65obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o
66obj-$(CONFIG_STM32_ADC) += stm32-adc.o 66obj-$(CONFIG_STM32_ADC) += stm32-adc.o
67obj-$(CONFIG_STM32_DFSDM_CORE) += stm32-dfsdm-core.o 67obj-$(CONFIG_STM32_DFSDM_CORE) += stm32-dfsdm-core.o
68obj-$(CONFIG_STM32_DFSDM_ADC) += stm32-dfsdm-adc.o
68obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o 69obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
69obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o 70obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o
70obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o 71obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o
diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
new file mode 100644
index 000000000000..68b5920e92cb
--- /dev/null
+++ b/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -0,0 +1,728 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * This file is the ADC part of the STM32 DFSDM driver
4 *
5 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
6 * Author: Arnaud Pouliquen <arnaud.pouliquen@st.com>.
7 */
8
9#include <linux/interrupt.h>
10#include <linux/iio/buffer.h>
11#include <linux/iio/hw-consumer.h>
12#include <linux/iio/iio.h>
13#include <linux/iio/sysfs.h>
14#include <linux/module.h>
15#include <linux/of.h>
16#include <linux/platform_device.h>
17#include <linux/regmap.h>
18#include <linux/slab.h>
19
20#include "stm32-dfsdm.h"
21
22/* Conversion timeout */
23#define DFSDM_TIMEOUT_US 100000
24#define DFSDM_TIMEOUT (msecs_to_jiffies(DFSDM_TIMEOUT_US / 1000))
25
26/* Oversampling attribute default */
27#define DFSDM_DEFAULT_OVERSAMPLING 100
28
29/* Oversampling max values */
30#define DFSDM_MAX_INT_OVERSAMPLING 256
31#define DFSDM_MAX_FL_OVERSAMPLING 1024
32
33/* Max sample resolutions */
34#define DFSDM_MAX_RES BIT(31)
35#define DFSDM_DATA_RES BIT(23)
36
37enum sd_converter_type {
38 DFSDM_AUDIO,
39 DFSDM_IIO,
40};
41
42struct stm32_dfsdm_dev_data {
43 int type;
44 int (*init)(struct iio_dev *indio_dev);
45 unsigned int num_channels;
46 const struct regmap_config *regmap_cfg;
47};
48
49struct stm32_dfsdm_adc {
50 struct stm32_dfsdm *dfsdm;
51 const struct stm32_dfsdm_dev_data *dev_data;
52 unsigned int fl_id;
53 unsigned int ch_id;
54
55 /* ADC specific */
56 unsigned int oversamp;
57 struct iio_hw_consumer *hwc;
58 struct completion completion;
59 u32 *buffer;
60
61};
62
63struct stm32_dfsdm_str2field {
64 const char *name;
65 unsigned int val;
66};
67
68/* DFSDM channel serial interface type */
69static const struct stm32_dfsdm_str2field stm32_dfsdm_chan_type[] = {
70 { "SPI_R", 0 }, /* SPI with data on rising edge */
71 { "SPI_F", 1 }, /* SPI with data on falling edge */
72 { "MANCH_R", 2 }, /* Manchester codec, rising edge = logic 0 */
73 { "MANCH_F", 3 }, /* Manchester codec, falling edge = logic 1 */
74 {},
75};
76
77/* DFSDM channel clock source */
78static const struct stm32_dfsdm_str2field stm32_dfsdm_chan_src[] = {
79 /* External SPI clock (CLKIN x) */
80 { "CLKIN", DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL },
81 /* Internal SPI clock (CLKOUT) */
82 { "CLKOUT", DFSDM_CHANNEL_SPI_CLOCK_INTERNAL },
83 /* Internal SPI clock divided by 2 (falling edge) */
84 { "CLKOUT_F", DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING },
85 /* Internal SPI clock divided by 2 (falling edge) */
86 { "CLKOUT_R", DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING },
87 {},
88};
89
90static int stm32_dfsdm_str2val(const char *str,
91 const struct stm32_dfsdm_str2field *list)
92{
93 const struct stm32_dfsdm_str2field *p = list;
94
95 for (p = list; p && p->name; p++)
96 if (!strcmp(p->name, str))
97 return p->val;
98
99 return -EINVAL;
100}
101
102static int stm32_dfsdm_set_osrs(struct stm32_dfsdm_filter *fl,
103 unsigned int fast, unsigned int oversamp)
104{
105 unsigned int i, d, fosr, iosr;
106 u64 res;
107 s64 delta;
108 unsigned int m = 1; /* multiplication factor */
109 unsigned int p = fl->ford; /* filter order (ford) */
110
111 pr_debug("%s: Requested oversampling: %d\n", __func__, oversamp);
112 /*
113 * This function tries to compute filter oversampling and integrator
114 * oversampling, base on oversampling ratio requested by user.
115 *
116 * Decimation d depends on the filter order and the oversampling ratios.
117 * ford: filter order
118 * fosr: filter over sampling ratio
119 * iosr: integrator over sampling ratio
120 */
121 if (fl->ford == DFSDM_FASTSINC_ORDER) {
122 m = 2;
123 p = 2;
124 }
125
126 /*
127 * Look for filter and integrator oversampling ratios which allows
128 * to reach 24 bits data output resolution.
129 * Leave as soon as if exact resolution if reached.
130 * Otherwise the higher resolution below 32 bits is kept.
131 */
132 for (fosr = 1; fosr <= DFSDM_MAX_FL_OVERSAMPLING; fosr++) {
133 for (iosr = 1; iosr <= DFSDM_MAX_INT_OVERSAMPLING; iosr++) {
134 if (fast)
135 d = fosr * iosr;
136 else if (fl->ford == DFSDM_FASTSINC_ORDER)
137 d = fosr * (iosr + 3) + 2;
138 else
139 d = fosr * (iosr - 1 + p) + p;
140
141 if (d > oversamp)
142 break;
143 else if (d != oversamp)
144 continue;
145 /*
146 * Check resolution (limited to signed 32 bits)
147 * res <= 2^31
148 * Sincx filters:
149 * res = m * fosr^p x iosr (with m=1, p=ford)
150 * FastSinc filter
151 * res = m * fosr^p x iosr (with m=2, p=2)
152 */
153 res = fosr;
154 for (i = p - 1; i > 0; i--) {
155 res = res * (u64)fosr;
156 if (res > DFSDM_MAX_RES)
157 break;
158 }
159 if (res > DFSDM_MAX_RES)
160 continue;
161 res = res * (u64)m * (u64)iosr;
162 if (res > DFSDM_MAX_RES)
163 continue;
164
165 delta = res - DFSDM_DATA_RES;
166
167 if (res >= fl->res) {
168 fl->res = res;
169 fl->fosr = fosr;
170 fl->iosr = iosr;
171 fl->fast = fast;
172 pr_debug("%s: fosr = %d, iosr = %d\n",
173 __func__, fl->fosr, fl->iosr);
174 }
175
176 if (!delta)
177 return 0;
178 }
179 }
180
181 if (!fl->fosr)
182 return -EINVAL;
183
184 return 0;
185}
186
187static int stm32_dfsdm_start_channel(struct stm32_dfsdm *dfsdm,
188 unsigned int ch_id)
189{
190 return regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(ch_id),
191 DFSDM_CHCFGR1_CHEN_MASK,
192 DFSDM_CHCFGR1_CHEN(1));
193}
194
195static void stm32_dfsdm_stop_channel(struct stm32_dfsdm *dfsdm,
196 unsigned int ch_id)
197{
198 regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(ch_id),
199 DFSDM_CHCFGR1_CHEN_MASK, DFSDM_CHCFGR1_CHEN(0));
200}
201
202static int stm32_dfsdm_chan_configure(struct stm32_dfsdm *dfsdm,
203 struct stm32_dfsdm_channel *ch)
204{
205 unsigned int id = ch->id;
206 struct regmap *regmap = dfsdm->regmap;
207 int ret;
208
209 ret = regmap_update_bits(regmap, DFSDM_CHCFGR1(id),
210 DFSDM_CHCFGR1_SITP_MASK,
211 DFSDM_CHCFGR1_SITP(ch->type));
212 if (ret < 0)
213 return ret;
214 ret = regmap_update_bits(regmap, DFSDM_CHCFGR1(id),
215 DFSDM_CHCFGR1_SPICKSEL_MASK,
216 DFSDM_CHCFGR1_SPICKSEL(ch->src));
217 if (ret < 0)
218 return ret;
219 return regmap_update_bits(regmap, DFSDM_CHCFGR1(id),
220 DFSDM_CHCFGR1_CHINSEL_MASK,
221 DFSDM_CHCFGR1_CHINSEL(ch->alt_si));
222}
223
224static int stm32_dfsdm_start_filter(struct stm32_dfsdm *dfsdm,
225 unsigned int fl_id)
226{
227 int ret;
228
229 /* Enable filter */
230 ret = regmap_update_bits(dfsdm->regmap, DFSDM_CR1(fl_id),
231 DFSDM_CR1_DFEN_MASK, DFSDM_CR1_DFEN(1));
232 if (ret < 0)
233 return ret;
234
235 /* Start conversion */
236 return regmap_update_bits(dfsdm->regmap, DFSDM_CR1(fl_id),
237 DFSDM_CR1_RSWSTART_MASK,
238 DFSDM_CR1_RSWSTART(1));
239}
240
241void stm32_dfsdm_stop_filter(struct stm32_dfsdm *dfsdm, unsigned int fl_id)
242{
243 /* Disable conversion */
244 regmap_update_bits(dfsdm->regmap, DFSDM_CR1(fl_id),
245 DFSDM_CR1_DFEN_MASK, DFSDM_CR1_DFEN(0));
246}
247
248static int stm32_dfsdm_filter_configure(struct stm32_dfsdm *dfsdm,
249 unsigned int fl_id, unsigned int ch_id)
250{
251 struct regmap *regmap = dfsdm->regmap;
252 struct stm32_dfsdm_filter *fl = &dfsdm->fl_list[fl_id];
253 int ret;
254
255 /* Average integrator oversampling */
256 ret = regmap_update_bits(regmap, DFSDM_FCR(fl_id), DFSDM_FCR_IOSR_MASK,
257 DFSDM_FCR_IOSR(fl->iosr - 1));
258 if (ret)
259 return ret;
260
261 /* Filter order and Oversampling */
262 ret = regmap_update_bits(regmap, DFSDM_FCR(fl_id), DFSDM_FCR_FOSR_MASK,
263 DFSDM_FCR_FOSR(fl->fosr - 1));
264 if (ret)
265 return ret;
266
267 ret = regmap_update_bits(regmap, DFSDM_FCR(fl_id), DFSDM_FCR_FORD_MASK,
268 DFSDM_FCR_FORD(fl->ford));
269 if (ret)
270 return ret;
271
272 /* No scan mode supported for the moment */
273 ret = regmap_update_bits(regmap, DFSDM_CR1(fl_id), DFSDM_CR1_RCH_MASK,
274 DFSDM_CR1_RCH(ch_id));
275 if (ret)
276 return ret;
277
278 return regmap_update_bits(regmap, DFSDM_CR1(fl_id),
279 DFSDM_CR1_RSYNC_MASK,
280 DFSDM_CR1_RSYNC(fl->sync_mode));
281}
282
283int stm32_dfsdm_channel_parse_of(struct stm32_dfsdm *dfsdm,
284 struct iio_dev *indio_dev,
285 struct iio_chan_spec *ch)
286{
287 struct stm32_dfsdm_channel *df_ch;
288 const char *of_str;
289 int chan_idx = ch->scan_index;
290 int ret, val;
291
292 ret = of_property_read_u32_index(indio_dev->dev.of_node,
293 "st,adc-channels", chan_idx,
294 &ch->channel);
295 if (ret < 0) {
296 dev_err(&indio_dev->dev,
297 " Error parsing 'st,adc-channels' for idx %d\n",
298 chan_idx);
299 return ret;
300 }
301 if (ch->channel >= dfsdm->num_chs) {
302 dev_err(&indio_dev->dev,
303 " Error bad channel number %d (max = %d)\n",
304 ch->channel, dfsdm->num_chs);
305 return -EINVAL;
306 }
307
308 ret = of_property_read_string_index(indio_dev->dev.of_node,
309 "st,adc-channel-names", chan_idx,
310 &ch->datasheet_name);
311 if (ret < 0) {
312 dev_err(&indio_dev->dev,
313 " Error parsing 'st,adc-channel-names' for idx %d\n",
314 chan_idx);
315 return ret;
316 }
317
318 df_ch = &dfsdm->ch_list[ch->channel];
319 df_ch->id = ch->channel;
320
321 ret = of_property_read_string_index(indio_dev->dev.of_node,
322 "st,adc-channel-types", chan_idx,
323 &of_str);
324 if (!ret) {
325 val = stm32_dfsdm_str2val(of_str, stm32_dfsdm_chan_type);
326 if (val < 0)
327 return val;
328 } else {
329 val = 0;
330 }
331 df_ch->type = val;
332
333 ret = of_property_read_string_index(indio_dev->dev.of_node,
334 "st,adc-channel-clk-src", chan_idx,
335 &of_str);
336 if (!ret) {
337 val = stm32_dfsdm_str2val(of_str, stm32_dfsdm_chan_src);
338 if (val < 0)
339 return val;
340 } else {
341 val = 0;
342 }
343 df_ch->src = val;
344
345 ret = of_property_read_u32_index(indio_dev->dev.of_node,
346 "st,adc-alt-channel", chan_idx,
347 &df_ch->alt_si);
348 if (ret < 0)
349 df_ch->alt_si = 0;
350
351 return 0;
352}
353
354static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc, bool dma)
355{
356 struct regmap *regmap = adc->dfsdm->regmap;
357 int ret;
358
359 ret = stm32_dfsdm_start_channel(adc->dfsdm, adc->ch_id);
360 if (ret < 0)
361 return ret;
362
363 ret = stm32_dfsdm_filter_configure(adc->dfsdm, adc->fl_id,
364 adc->ch_id);
365 if (ret < 0)
366 goto stop_channels;
367
368 ret = stm32_dfsdm_start_filter(adc->dfsdm, adc->fl_id);
369 if (ret < 0)
370 goto stop_channels;
371
372 return 0;
373
374stop_channels:
375 regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id),
376 DFSDM_CR1_RDMAEN_MASK, 0);
377
378 regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id),
379 DFSDM_CR1_RCONT_MASK, 0);
380 stm32_dfsdm_stop_channel(adc->dfsdm, adc->fl_id);
381
382 return ret;
383}
384
385static void stm32_dfsdm_stop_conv(struct stm32_dfsdm_adc *adc)
386{
387 struct regmap *regmap = adc->dfsdm->regmap;
388
389 stm32_dfsdm_stop_filter(adc->dfsdm, adc->fl_id);
390
391 /* Clean conversion options */
392 regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id),
393 DFSDM_CR1_RDMAEN_MASK, 0);
394
395 regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id),
396 DFSDM_CR1_RCONT_MASK, 0);
397
398 stm32_dfsdm_stop_channel(adc->dfsdm, adc->ch_id);
399}
400
401static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev,
402 const struct iio_chan_spec *chan, int *res)
403{
404 struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
405 long timeout;
406 int ret;
407
408 reinit_completion(&adc->completion);
409
410 adc->buffer = res;
411
412 ret = stm32_dfsdm_start_dfsdm(adc->dfsdm);
413 if (ret < 0)
414 return ret;
415
416 ret = regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR2(adc->fl_id),
417 DFSDM_CR2_REOCIE_MASK, DFSDM_CR2_REOCIE(1));
418 if (ret < 0)
419 goto stop_dfsdm;
420
421 ret = stm32_dfsdm_start_conv(adc, false);
422 if (ret < 0) {
423 regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR2(adc->fl_id),
424 DFSDM_CR2_REOCIE_MASK, DFSDM_CR2_REOCIE(0));
425 goto stop_dfsdm;
426 }
427
428 timeout = wait_for_completion_interruptible_timeout(&adc->completion,
429 DFSDM_TIMEOUT);
430
431 /* Mask IRQ for regular conversion achievement*/
432 regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR2(adc->fl_id),
433 DFSDM_CR2_REOCIE_MASK, DFSDM_CR2_REOCIE(0));
434
435 if (timeout == 0)
436 ret = -ETIMEDOUT;
437 else if (timeout < 0)
438 ret = timeout;
439 else
440 ret = IIO_VAL_INT;
441
442 stm32_dfsdm_stop_conv(adc);
443
444stop_dfsdm:
445 stm32_dfsdm_stop_dfsdm(adc->dfsdm);
446
447 return ret;
448}
449
450static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev,
451 struct iio_chan_spec const *chan,
452 int val, int val2, long mask)
453{
454 struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
455 struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
456 int ret = -EINVAL;
457
458 if (mask == IIO_CHAN_INFO_OVERSAMPLING_RATIO) {
459 ret = stm32_dfsdm_set_osrs(fl, 0, val);
460 if (!ret)
461 adc->oversamp = val;
462 }
463
464 return ret;
465}
466
467static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev,
468 struct iio_chan_spec const *chan, int *val,
469 int *val2, long mask)
470{
471 struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
472 int ret;
473
474 switch (mask) {
475 case IIO_CHAN_INFO_RAW:
476 ret = iio_hw_consumer_enable(adc->hwc);
477 if (ret < 0) {
478 dev_err(&indio_dev->dev,
479 "%s: IIO enable failed (channel %d)\n",
480 __func__, chan->channel);
481 return ret;
482 }
483 ret = stm32_dfsdm_single_conv(indio_dev, chan, val);
484 iio_hw_consumer_disable(adc->hwc);
485 if (ret < 0) {
486 dev_err(&indio_dev->dev,
487 "%s: Conversion failed (channel %d)\n",
488 __func__, chan->channel);
489 return ret;
490 }
491 return IIO_VAL_INT;
492
493 case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
494 *val = adc->oversamp;
495
496 return IIO_VAL_INT;
497 }
498
499 return -EINVAL;
500}
501
502static const struct iio_info stm32_dfsdm_info_adc = {
503 .read_raw = stm32_dfsdm_read_raw,
504 .write_raw = stm32_dfsdm_write_raw,
505};
506
507static irqreturn_t stm32_dfsdm_irq(int irq, void *arg)
508{
509 struct stm32_dfsdm_adc *adc = arg;
510 struct iio_dev *indio_dev = iio_priv_to_dev(adc);
511 struct regmap *regmap = adc->dfsdm->regmap;
512 unsigned int status, int_en;
513
514 regmap_read(regmap, DFSDM_ISR(adc->fl_id), &status);
515 regmap_read(regmap, DFSDM_CR2(adc->fl_id), &int_en);
516
517 if (status & DFSDM_ISR_REOCF_MASK) {
518 /* Read the data register clean the IRQ status */
519 regmap_read(regmap, DFSDM_RDATAR(adc->fl_id), adc->buffer);
520 complete(&adc->completion);
521 }
522
523 if (status & DFSDM_ISR_ROVRF_MASK) {
524 if (int_en & DFSDM_CR2_ROVRIE_MASK)
525 dev_warn(&indio_dev->dev, "Overrun detected\n");
526 regmap_update_bits(regmap, DFSDM_ICR(adc->fl_id),
527 DFSDM_ICR_CLRROVRF_MASK,
528 DFSDM_ICR_CLRROVRF_MASK);
529 }
530
531 return IRQ_HANDLED;
532}
533
534static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev,
535 struct iio_chan_spec *ch)
536{
537 struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
538 int ret;
539
540 ret = stm32_dfsdm_channel_parse_of(adc->dfsdm, indio_dev, ch);
541 if (ret < 0)
542 return ret;
543
544 ch->type = IIO_VOLTAGE;
545 ch->indexed = 1;
546
547 /*
548 * IIO_CHAN_INFO_RAW: used to compute regular conversion
549 * IIO_CHAN_INFO_OVERSAMPLING_RATIO: used to set oversampling
550 */
551 ch->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
552 ch->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
553
554 ch->scan_type.sign = 'u';
555 ch->scan_type.realbits = 24;
556 ch->scan_type.storagebits = 32;
557 adc->ch_id = ch->channel;
558
559 return stm32_dfsdm_chan_configure(adc->dfsdm,
560 &adc->dfsdm->ch_list[ch->channel]);
561}
562
563static int stm32_dfsdm_adc_init(struct iio_dev *indio_dev)
564{
565 struct iio_chan_spec *ch;
566 struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
567 int num_ch;
568 int ret, chan_idx;
569
570 adc->oversamp = DFSDM_DEFAULT_OVERSAMPLING;
571 ret = stm32_dfsdm_set_osrs(&adc->dfsdm->fl_list[adc->fl_id], 0,
572 adc->oversamp);
573 if (ret < 0)
574 return ret;
575
576 num_ch = of_property_count_u32_elems(indio_dev->dev.of_node,
577 "st,adc-channels");
578 if (num_ch < 0 || num_ch > adc->dfsdm->num_chs) {
579 dev_err(&indio_dev->dev, "Bad st,adc-channels\n");
580 return num_ch < 0 ? num_ch : -EINVAL;
581 }
582
583 /* Bind to SD modulator IIO device */
584 adc->hwc = devm_iio_hw_consumer_alloc(&indio_dev->dev);
585 if (IS_ERR(adc->hwc))
586 return -EPROBE_DEFER;
587
588 ch = devm_kcalloc(&indio_dev->dev, num_ch, sizeof(*ch),
589 GFP_KERNEL);
590 if (!ch)
591 return -ENOMEM;
592
593 for (chan_idx = 0; chan_idx < num_ch; chan_idx++) {
594 ch->scan_index = chan_idx;
595 ret = stm32_dfsdm_adc_chan_init_one(indio_dev, ch);
596 if (ret < 0) {
597 dev_err(&indio_dev->dev, "Channels init failed\n");
598 return ret;
599 }
600 }
601
602 indio_dev->num_channels = num_ch;
603 indio_dev->channels = ch;
604
605 init_completion(&adc->completion);
606
607 return 0;
608}
609
610static const struct stm32_dfsdm_dev_data stm32h7_dfsdm_adc_data = {
611 .type = DFSDM_IIO,
612 .init = stm32_dfsdm_adc_init,
613};
614
615static const struct of_device_id stm32_dfsdm_adc_match[] = {
616 {
617 .compatible = "st,stm32-dfsdm-adc",
618 .data = &stm32h7_dfsdm_adc_data,
619 },
620 {}
621};
622
623static int stm32_dfsdm_adc_probe(struct platform_device *pdev)
624{
625 struct device *dev = &pdev->dev;
626 struct stm32_dfsdm_adc *adc;
627 struct device_node *np = dev->of_node;
628 const struct stm32_dfsdm_dev_data *dev_data;
629 struct iio_dev *iio;
630 const struct of_device_id *of_id;
631 char *name;
632 int ret, irq, val;
633
634 of_id = of_match_node(stm32_dfsdm_adc_match, np);
635 if (!of_id->data) {
636 dev_err(&pdev->dev, "Data associated to device is missing\n");
637 return -EINVAL;
638 }
639
640 dev_data = (const struct stm32_dfsdm_dev_data *)of_id->data;
641
642 iio = devm_iio_device_alloc(dev, sizeof(*adc));
643 if (IS_ERR(iio)) {
644 dev_err(dev, "%s: Failed to allocate IIO\n", __func__);
645 return PTR_ERR(iio);
646 }
647
648 adc = iio_priv(iio);
649 if (IS_ERR(adc)) {
650 dev_err(dev, "%s: Failed to allocate ADC\n", __func__);
651 return PTR_ERR(adc);
652 }
653 adc->dfsdm = dev_get_drvdata(dev->parent);
654
655 iio->dev.parent = dev;
656 iio->dev.of_node = np;
657 iio->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
658
659 platform_set_drvdata(pdev, adc);
660
661 ret = of_property_read_u32(dev->of_node, "reg", &adc->fl_id);
662 if (ret != 0) {
663 dev_err(dev, "Missing reg property\n");
664 return -EINVAL;
665 }
666
667 name = devm_kzalloc(dev, sizeof("dfsdm-adc0"), GFP_KERNEL);
668 if (!name)
669 return -ENOMEM;
670 iio->info = &stm32_dfsdm_info_adc;
671 snprintf(name, sizeof("dfsdm-adc0"), "dfsdm-adc%d", adc->fl_id);
672 iio->name = name;
673
674 /*
675 * In a first step IRQs generated for channels are not treated.
676 * So IRQ associated to filter instance 0 is dedicated to the Filter 0.
677 */
678 irq = platform_get_irq(pdev, 0);
679 ret = devm_request_irq(dev, irq, stm32_dfsdm_irq,
680 0, pdev->name, adc);
681 if (ret < 0) {
682 dev_err(dev, "Failed to request IRQ\n");
683 return ret;
684 }
685
686 ret = of_property_read_u32(dev->of_node, "st,filter-order", &val);
687 if (ret < 0) {
688 dev_err(dev, "Failed to set filter order\n");
689 return ret;
690 }
691
692 adc->dfsdm->fl_list[adc->fl_id].ford = val;
693
694 ret = of_property_read_u32(dev->of_node, "st,filter0-sync", &val);
695 if (!ret)
696 adc->dfsdm->fl_list[adc->fl_id].sync_mode = val;
697
698 adc->dev_data = dev_data;
699 ret = dev_data->init(iio);
700 if (ret < 0)
701 return ret;
702
703 return iio_device_register(iio);
704}
705
706static int stm32_dfsdm_adc_remove(struct platform_device *pdev)
707{
708 struct stm32_dfsdm_adc *adc = platform_get_drvdata(pdev);
709 struct iio_dev *indio_dev = iio_priv_to_dev(adc);
710
711 iio_device_unregister(indio_dev);
712
713 return 0;
714}
715
716static struct platform_driver stm32_dfsdm_adc_driver = {
717 .driver = {
718 .name = "stm32-dfsdm-adc",
719 .of_match_table = stm32_dfsdm_adc_match,
720 },
721 .probe = stm32_dfsdm_adc_probe,
722 .remove = stm32_dfsdm_adc_remove,
723};
724module_platform_driver(stm32_dfsdm_adc_driver);
725
726MODULE_DESCRIPTION("STM32 sigma delta ADC");
727MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>");
728MODULE_LICENSE("GPL v2");