aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaud Pouliquen <arnaud.pouliquen@st.com>2018-01-10 05:13:10 -0500
committerMark Brown <broonie@kernel.org>2018-01-10 05:30:11 -0500
commitbed73904e76fc08d0ec3a7ba3eb2ddbb2e38862c (patch)
tree99193706b1e4dc8d0a1906f827af83428dbcbc6f
parent6c82f947fc9784b774cad0b90c20a5d703f9b763 (diff)
IIO: ADC: add stm32 DFSDM core support
Add driver for stm32 DFSDM pheripheral. Its converts a sigma delta stream in n bit samples through a low pass filter and an integrator. stm32-dfsdm-core driver is the core part supporting the filter instances dedicated to sigma-delta ADC or audio PDM microphone purpose. 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/Kconfig12
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/stm32-dfsdm-core.c309
-rw-r--r--drivers/iio/adc/stm32-dfsdm.h310
4 files changed, 632 insertions, 0 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 5f9d04a8ba53..776192e68ad5 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -668,6 +668,18 @@ config STM32_ADC
668 This driver can also be built as a module. If so, the module 668 This driver can also be built as a module. If so, the module
669 will be called stm32-adc. 669 will be called stm32-adc.
670 670
671config STM32_DFSDM_CORE
672 tristate "STMicroelectronics STM32 DFSDM core"
673 depends on (ARCH_STM32 && OF) || COMPILE_TEST
674 select REGMAP
675 select REGMAP_MMIO
676 help
677 Select this option to enable the driver for STMicroelectronics
678 STM32 digital filter for sigma delta converter.
679
680 This driver can also be built as a module. If so, the module
681 will be called stm32-dfsdm-core.
682
671config STX104 683config STX104
672 tristate "Apex Embedded Systems STX104 driver" 684 tristate "Apex Embedded Systems STX104 driver"
673 depends on PC104 && X86 && ISA_BUS_API 685 depends on PC104 && X86 && ISA_BUS_API
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index fa5e7949f642..8dda348f1920 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -64,6 +64,7 @@ obj-$(CONFIG_STX104) += stx104.o
64obj-$(CONFIG_SUN4I_GPADC) += sun4i-gpadc-iio.o 64obj-$(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_TI_ADC081C) += ti-adc081c.o 68obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
68obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o 69obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o
69obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o 70obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o
diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c
new file mode 100644
index 000000000000..72427414db7f
--- /dev/null
+++ b/drivers/iio/adc/stm32-dfsdm-core.c
@@ -0,0 +1,309 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * This file is part the core part STM32 DFSDM driver
4 *
5 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
6 * Author(s): Arnaud Pouliquen <arnaud.pouliquen@st.com> for STMicroelectronics.
7 */
8
9#include <linux/clk.h>
10#include <linux/iio/iio.h>
11#include <linux/iio/sysfs.h>
12#include <linux/interrupt.h>
13#include <linux/module.h>
14#include <linux/of_device.h>
15#include <linux/regmap.h>
16#include <linux/slab.h>
17
18#include "stm32-dfsdm.h"
19
20struct stm32_dfsdm_dev_data {
21 unsigned int num_filters;
22 unsigned int num_channels;
23 const struct regmap_config *regmap_cfg;
24};
25
26#define STM32H7_DFSDM_NUM_FILTERS 4
27#define STM32H7_DFSDM_NUM_CHANNELS 8
28
29static bool stm32_dfsdm_volatile_reg(struct device *dev, unsigned int reg)
30{
31 if (reg < DFSDM_FILTER_BASE_ADR)
32 return false;
33
34 /*
35 * Mask is done on register to avoid to list registers of all
36 * filter instances.
37 */
38 switch (reg & DFSDM_FILTER_REG_MASK) {
39 case DFSDM_CR1(0) & DFSDM_FILTER_REG_MASK:
40 case DFSDM_ISR(0) & DFSDM_FILTER_REG_MASK:
41 case DFSDM_JDATAR(0) & DFSDM_FILTER_REG_MASK:
42 case DFSDM_RDATAR(0) & DFSDM_FILTER_REG_MASK:
43 return true;
44 }
45
46 return false;
47}
48
49static const struct regmap_config stm32h7_dfsdm_regmap_cfg = {
50 .reg_bits = 32,
51 .val_bits = 32,
52 .reg_stride = sizeof(u32),
53 .max_register = 0x2B8,
54 .volatile_reg = stm32_dfsdm_volatile_reg,
55 .fast_io = true,
56};
57
58static const struct stm32_dfsdm_dev_data stm32h7_dfsdm_data = {
59 .num_filters = STM32H7_DFSDM_NUM_FILTERS,
60 .num_channels = STM32H7_DFSDM_NUM_CHANNELS,
61 .regmap_cfg = &stm32h7_dfsdm_regmap_cfg,
62};
63
64struct dfsdm_priv {
65 struct platform_device *pdev; /* platform device */
66
67 struct stm32_dfsdm dfsdm; /* common data exported for all instances */
68
69 unsigned int spi_clk_out_div; /* SPI clkout divider value */
70 atomic_t n_active_ch; /* number of current active channels */
71
72 struct clk *clk; /* DFSDM clock */
73 struct clk *aclk; /* audio clock */
74};
75
76/**
77 * stm32_dfsdm_start_dfsdm - start global dfsdm interface.
78 *
79 * Enable interface if n_active_ch is not null.
80 * @dfsdm: Handle used to retrieve dfsdm context.
81 */
82int stm32_dfsdm_start_dfsdm(struct stm32_dfsdm *dfsdm)
83{
84 struct dfsdm_priv *priv = container_of(dfsdm, struct dfsdm_priv, dfsdm);
85 struct device *dev = &priv->pdev->dev;
86 unsigned int clk_div = priv->spi_clk_out_div;
87 int ret;
88
89 if (atomic_inc_return(&priv->n_active_ch) == 1) {
90 ret = clk_prepare_enable(priv->clk);
91 if (ret < 0) {
92 dev_err(dev, "Failed to start clock\n");
93 goto error_ret;
94 }
95 if (priv->aclk) {
96 ret = clk_prepare_enable(priv->aclk);
97 if (ret < 0) {
98 dev_err(dev, "Failed to start audio clock\n");
99 goto disable_clk;
100 }
101 }
102
103 /* Output the SPI CLKOUT (if clk_div == 0 clock if OFF) */
104 ret = regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(0),
105 DFSDM_CHCFGR1_CKOUTDIV_MASK,
106 DFSDM_CHCFGR1_CKOUTDIV(clk_div));
107 if (ret < 0)
108 goto disable_aclk;
109
110 /* Global enable of DFSDM interface */
111 ret = regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(0),
112 DFSDM_CHCFGR1_DFSDMEN_MASK,
113 DFSDM_CHCFGR1_DFSDMEN(1));
114 if (ret < 0)
115 goto disable_aclk;
116 }
117
118 dev_dbg(dev, "%s: n_active_ch %d\n", __func__,
119 atomic_read(&priv->n_active_ch));
120
121 return 0;
122
123disable_aclk:
124 clk_disable_unprepare(priv->aclk);
125disable_clk:
126 clk_disable_unprepare(priv->clk);
127
128error_ret:
129 atomic_dec(&priv->n_active_ch);
130
131 return ret;
132}
133EXPORT_SYMBOL_GPL(stm32_dfsdm_start_dfsdm);
134
135/**
136 * stm32_dfsdm_stop_dfsdm - stop global DFSDM interface.
137 *
138 * Disable interface if n_active_ch is null
139 * @dfsdm: Handle used to retrieve dfsdm context.
140 */
141int stm32_dfsdm_stop_dfsdm(struct stm32_dfsdm *dfsdm)
142{
143 struct dfsdm_priv *priv = container_of(dfsdm, struct dfsdm_priv, dfsdm);
144 int ret;
145
146 if (atomic_dec_and_test(&priv->n_active_ch)) {
147 /* Global disable of DFSDM interface */
148 ret = regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(0),
149 DFSDM_CHCFGR1_DFSDMEN_MASK,
150 DFSDM_CHCFGR1_DFSDMEN(0));
151 if (ret < 0)
152 return ret;
153
154 /* Stop SPI CLKOUT */
155 ret = regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(0),
156 DFSDM_CHCFGR1_CKOUTDIV_MASK,
157 DFSDM_CHCFGR1_CKOUTDIV(0));
158 if (ret < 0)
159 return ret;
160
161 clk_disable_unprepare(priv->clk);
162 if (priv->aclk)
163 clk_disable_unprepare(priv->aclk);
164 }
165 dev_dbg(&priv->pdev->dev, "%s: n_active_ch %d\n", __func__,
166 atomic_read(&priv->n_active_ch));
167
168 return 0;
169}
170EXPORT_SYMBOL_GPL(stm32_dfsdm_stop_dfsdm);
171
172static int stm32_dfsdm_parse_of(struct platform_device *pdev,
173 struct dfsdm_priv *priv)
174{
175 struct device_node *node = pdev->dev.of_node;
176 struct resource *res;
177 unsigned long clk_freq;
178 unsigned int spi_freq, rem;
179 int ret;
180
181 if (!node)
182 return -EINVAL;
183
184 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
185 if (!res) {
186 dev_err(&pdev->dev, "Failed to get memory resource\n");
187 return -ENODEV;
188 }
189 priv->dfsdm.phys_base = res->start;
190 priv->dfsdm.base = devm_ioremap_resource(&pdev->dev, res);
191
192 /*
193 * "dfsdm" clock is mandatory for DFSDM peripheral clocking.
194 * "dfsdm" or "audio" clocks can be used as source clock for
195 * the SPI clock out signal and internal processing, depending
196 * on use case.
197 */
198 priv->clk = devm_clk_get(&pdev->dev, "dfsdm");
199 if (IS_ERR(priv->clk)) {
200 dev_err(&pdev->dev, "No stm32_dfsdm_clk clock found\n");
201 return -EINVAL;
202 }
203
204 priv->aclk = devm_clk_get(&pdev->dev, "audio");
205 if (IS_ERR(priv->aclk))
206 priv->aclk = NULL;
207
208 if (priv->aclk)
209 clk_freq = clk_get_rate(priv->aclk);
210 else
211 clk_freq = clk_get_rate(priv->clk);
212
213 /* SPI clock out frequency */
214 ret = of_property_read_u32(pdev->dev.of_node, "spi-max-frequency",
215 &spi_freq);
216 if (ret < 0) {
217 /* No SPI master mode */
218 return 0;
219 }
220
221 priv->spi_clk_out_div = div_u64_rem(clk_freq, spi_freq, &rem) - 1;
222 priv->dfsdm.spi_master_freq = spi_freq;
223
224 if (rem) {
225 dev_warn(&pdev->dev, "SPI clock not accurate\n");
226 dev_warn(&pdev->dev, "%ld = %d * %d + %d\n",
227 clk_freq, spi_freq, priv->spi_clk_out_div + 1, rem);
228 }
229
230 return 0;
231};
232
233static const struct of_device_id stm32_dfsdm_of_match[] = {
234 {
235 .compatible = "st,stm32h7-dfsdm",
236 .data = &stm32h7_dfsdm_data,
237 },
238 {}
239};
240MODULE_DEVICE_TABLE(of, stm32_dfsdm_of_match);
241
242static int stm32_dfsdm_probe(struct platform_device *pdev)
243{
244 struct dfsdm_priv *priv;
245 struct device_node *pnode = pdev->dev.of_node;
246 const struct of_device_id *of_id;
247 const struct stm32_dfsdm_dev_data *dev_data;
248 struct stm32_dfsdm *dfsdm;
249 int ret;
250
251 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
252 if (!priv)
253 return -ENOMEM;
254
255 priv->pdev = pdev;
256
257 of_id = of_match_node(stm32_dfsdm_of_match, pnode);
258 if (!of_id->data) {
259 dev_err(&pdev->dev, "Data associated to device is missing\n");
260 return -EINVAL;
261 }
262
263 dev_data = (const struct stm32_dfsdm_dev_data *)of_id->data;
264 dfsdm = &priv->dfsdm;
265 dfsdm->fl_list = devm_kcalloc(&pdev->dev, dev_data->num_filters,
266 sizeof(*dfsdm->fl_list), GFP_KERNEL);
267 if (!dfsdm->fl_list)
268 return -ENOMEM;
269
270 dfsdm->num_fls = dev_data->num_filters;
271 dfsdm->ch_list = devm_kcalloc(&pdev->dev, dev_data->num_channels,
272 sizeof(*dfsdm->ch_list),
273 GFP_KERNEL);
274 if (!dfsdm->ch_list)
275 return -ENOMEM;
276 dfsdm->num_chs = dev_data->num_channels;
277
278 ret = stm32_dfsdm_parse_of(pdev, priv);
279 if (ret < 0)
280 return ret;
281
282 dfsdm->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "dfsdm",
283 dfsdm->base,
284 &stm32h7_dfsdm_regmap_cfg);
285 if (IS_ERR(dfsdm->regmap)) {
286 ret = PTR_ERR(dfsdm->regmap);
287 dev_err(&pdev->dev, "%s: Failed to allocate regmap: %d\n",
288 __func__, ret);
289 return ret;
290 }
291
292 platform_set_drvdata(pdev, dfsdm);
293
294 return devm_of_platform_populate(&pdev->dev);
295}
296
297static struct platform_driver stm32_dfsdm_driver = {
298 .probe = stm32_dfsdm_probe,
299 .driver = {
300 .name = "stm32-dfsdm",
301 .of_match_table = stm32_dfsdm_of_match,
302 },
303};
304
305module_platform_driver(stm32_dfsdm_driver);
306
307MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>");
308MODULE_DESCRIPTION("STMicroelectronics STM32 dfsdm driver");
309MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/stm32-dfsdm.h b/drivers/iio/adc/stm32-dfsdm.h
new file mode 100644
index 000000000000..8708394b0725
--- /dev/null
+++ b/drivers/iio/adc/stm32-dfsdm.h
@@ -0,0 +1,310 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * This file is part of STM32 DFSDM driver
4 *
5 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
6 * Author(s): Arnaud Pouliquen <arnaud.pouliquen@st.com>.
7 */
8
9#ifndef MDF_STM32_DFSDM__H
10#define MDF_STM32_DFSDM__H
11
12#include <linux/bitfield.h>
13
14/*
15 * STM32 DFSDM - global register map
16 * ________________________________________________________
17 * | Offset | Registers block |
18 * --------------------------------------------------------
19 * | 0x000 | CHANNEL 0 + COMMON CHANNEL FIELDS |
20 * --------------------------------------------------------
21 * | 0x020 | CHANNEL 1 |
22 * --------------------------------------------------------
23 * | ... | ..... |
24 * --------------------------------------------------------
25 * | 0x0E0 | CHANNEL 7 |
26 * --------------------------------------------------------
27 * | 0x100 | FILTER 0 + COMMON FILTER FIELDs |
28 * --------------------------------------------------------
29 * | 0x200 | FILTER 1 |
30 * --------------------------------------------------------
31 * | 0x300 | FILTER 2 |
32 * --------------------------------------------------------
33 * | 0x400 | FILTER 3 |
34 * --------------------------------------------------------
35 */
36
37/*
38 * Channels register definitions
39 */
40#define DFSDM_CHCFGR1(y) ((y) * 0x20 + 0x00)
41#define DFSDM_CHCFGR2(y) ((y) * 0x20 + 0x04)
42#define DFSDM_AWSCDR(y) ((y) * 0x20 + 0x08)
43#define DFSDM_CHWDATR(y) ((y) * 0x20 + 0x0C)
44#define DFSDM_CHDATINR(y) ((y) * 0x20 + 0x10)
45
46/* CHCFGR1: Channel configuration register 1 */
47#define DFSDM_CHCFGR1_SITP_MASK GENMASK(1, 0)
48#define DFSDM_CHCFGR1_SITP(v) FIELD_PREP(DFSDM_CHCFGR1_SITP_MASK, v)
49#define DFSDM_CHCFGR1_SPICKSEL_MASK GENMASK(3, 2)
50#define DFSDM_CHCFGR1_SPICKSEL(v) FIELD_PREP(DFSDM_CHCFGR1_SPICKSEL_MASK, v)
51#define DFSDM_CHCFGR1_SCDEN_MASK BIT(5)
52#define DFSDM_CHCFGR1_SCDEN(v) FIELD_PREP(DFSDM_CHCFGR1_SCDEN_MASK, v)
53#define DFSDM_CHCFGR1_CKABEN_MASK BIT(6)
54#define DFSDM_CHCFGR1_CKABEN(v) FIELD_PREP(DFSDM_CHCFGR1_CKABEN_MASK, v)
55#define DFSDM_CHCFGR1_CHEN_MASK BIT(7)
56#define DFSDM_CHCFGR1_CHEN(v) FIELD_PREP(DFSDM_CHCFGR1_CHEN_MASK, v)
57#define DFSDM_CHCFGR1_CHINSEL_MASK BIT(8)
58#define DFSDM_CHCFGR1_CHINSEL(v) FIELD_PREP(DFSDM_CHCFGR1_CHINSEL_MASK, v)
59#define DFSDM_CHCFGR1_DATMPX_MASK GENMASK(13, 12)
60#define DFSDM_CHCFGR1_DATMPX(v) FIELD_PREP(DFSDM_CHCFGR1_DATMPX_MASK, v)
61#define DFSDM_CHCFGR1_DATPACK_MASK GENMASK(15, 14)
62#define DFSDM_CHCFGR1_DATPACK(v) FIELD_PREP(DFSDM_CHCFGR1_DATPACK_MASK, v)
63#define DFSDM_CHCFGR1_CKOUTDIV_MASK GENMASK(23, 16)
64#define DFSDM_CHCFGR1_CKOUTDIV(v) FIELD_PREP(DFSDM_CHCFGR1_CKOUTDIV_MASK, v)
65#define DFSDM_CHCFGR1_CKOUTSRC_MASK BIT(30)
66#define DFSDM_CHCFGR1_CKOUTSRC(v) FIELD_PREP(DFSDM_CHCFGR1_CKOUTSRC_MASK, v)
67#define DFSDM_CHCFGR1_DFSDMEN_MASK BIT(31)
68#define DFSDM_CHCFGR1_DFSDMEN(v) FIELD_PREP(DFSDM_CHCFGR1_DFSDMEN_MASK, v)
69
70/* CHCFGR2: Channel configuration register 2 */
71#define DFSDM_CHCFGR2_DTRBS_MASK GENMASK(7, 3)
72#define DFSDM_CHCFGR2_DTRBS(v) FIELD_PREP(DFSDM_CHCFGR2_DTRBS_MASK, v)
73#define DFSDM_CHCFGR2_OFFSET_MASK GENMASK(31, 8)
74#define DFSDM_CHCFGR2_OFFSET(v) FIELD_PREP(DFSDM_CHCFGR2_OFFSET_MASK, v)
75
76/* AWSCDR: Channel analog watchdog and short circuit detector */
77#define DFSDM_AWSCDR_SCDT_MASK GENMASK(7, 0)
78#define DFSDM_AWSCDR_SCDT(v) FIELD_PREP(DFSDM_AWSCDR_SCDT_MASK, v)
79#define DFSDM_AWSCDR_BKSCD_MASK GENMASK(15, 12)
80#define DFSDM_AWSCDR_BKSCD(v) FIELD_PREP(DFSDM_AWSCDR_BKSCD_MASK, v)
81#define DFSDM_AWSCDR_AWFOSR_MASK GENMASK(20, 16)
82#define DFSDM_AWSCDR_AWFOSR(v) FIELD_PREP(DFSDM_AWSCDR_AWFOSR_MASK, v)
83#define DFSDM_AWSCDR_AWFORD_MASK GENMASK(23, 22)
84#define DFSDM_AWSCDR_AWFORD(v) FIELD_PREP(DFSDM_AWSCDR_AWFORD_MASK, v)
85
86/*
87 * Filters register definitions
88 */
89#define DFSDM_FILTER_BASE_ADR 0x100
90#define DFSDM_FILTER_REG_MASK 0x7F
91#define DFSDM_FILTER_X_BASE_ADR(x) ((x) * 0x80 + DFSDM_FILTER_BASE_ADR)
92
93#define DFSDM_CR1(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x00)
94#define DFSDM_CR2(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x04)
95#define DFSDM_ISR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x08)
96#define DFSDM_ICR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x0C)
97#define DFSDM_JCHGR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x10)
98#define DFSDM_FCR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x14)
99#define DFSDM_JDATAR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x18)
100#define DFSDM_RDATAR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x1C)
101#define DFSDM_AWHTR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x20)
102#define DFSDM_AWLTR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x24)
103#define DFSDM_AWSR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x28)
104#define DFSDM_AWCFR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x2C)
105#define DFSDM_EXMAX(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x30)
106#define DFSDM_EXMIN(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x34)
107#define DFSDM_CNVTIMR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x38)
108
109/* CR1 Control register 1 */
110#define DFSDM_CR1_DFEN_MASK BIT(0)
111#define DFSDM_CR1_DFEN(v) FIELD_PREP(DFSDM_CR1_DFEN_MASK, v)
112#define DFSDM_CR1_JSWSTART_MASK BIT(1)
113#define DFSDM_CR1_JSWSTART(v) FIELD_PREP(DFSDM_CR1_JSWSTART_MASK, v)
114#define DFSDM_CR1_JSYNC_MASK BIT(3)
115#define DFSDM_CR1_JSYNC(v) FIELD_PREP(DFSDM_CR1_JSYNC_MASK, v)
116#define DFSDM_CR1_JSCAN_MASK BIT(4)
117#define DFSDM_CR1_JSCAN(v) FIELD_PREP(DFSDM_CR1_JSCAN_MASK, v)
118#define DFSDM_CR1_JDMAEN_MASK BIT(5)
119#define DFSDM_CR1_JDMAEN(v) FIELD_PREP(DFSDM_CR1_JDMAEN_MASK, v)
120#define DFSDM_CR1_JEXTSEL_MASK GENMASK(12, 8)
121#define DFSDM_CR1_JEXTSEL(v) FIELD_PREP(DFSDM_CR1_JEXTSEL_MASK, v)
122#define DFSDM_CR1_JEXTEN_MASK GENMASK(14, 13)
123#define DFSDM_CR1_JEXTEN(v) FIELD_PREP(DFSDM_CR1_JEXTEN_MASK, v)
124#define DFSDM_CR1_RSWSTART_MASK BIT(17)
125#define DFSDM_CR1_RSWSTART(v) FIELD_PREP(DFSDM_CR1_RSWSTART_MASK, v)
126#define DFSDM_CR1_RCONT_MASK BIT(18)
127#define DFSDM_CR1_RCONT(v) FIELD_PREP(DFSDM_CR1_RCONT_MASK, v)
128#define DFSDM_CR1_RSYNC_MASK BIT(19)
129#define DFSDM_CR1_RSYNC(v) FIELD_PREP(DFSDM_CR1_RSYNC_MASK, v)
130#define DFSDM_CR1_RDMAEN_MASK BIT(21)
131#define DFSDM_CR1_RDMAEN(v) FIELD_PREP(DFSDM_CR1_RDMAEN_MASK, v)
132#define DFSDM_CR1_RCH_MASK GENMASK(26, 24)
133#define DFSDM_CR1_RCH(v) FIELD_PREP(DFSDM_CR1_RCH_MASK, v)
134#define DFSDM_CR1_FAST_MASK BIT(29)
135#define DFSDM_CR1_FAST(v) FIELD_PREP(DFSDM_CR1_FAST_MASK, v)
136#define DFSDM_CR1_AWFSEL_MASK BIT(30)
137#define DFSDM_CR1_AWFSEL(v) FIELD_PREP(DFSDM_CR1_AWFSEL_MASK, v)
138
139/* CR2: Control register 2 */
140#define DFSDM_CR2_IE_MASK GENMASK(6, 0)
141#define DFSDM_CR2_IE(v) FIELD_PREP(DFSDM_CR2_IE_MASK, v)
142#define DFSDM_CR2_JEOCIE_MASK BIT(0)
143#define DFSDM_CR2_JEOCIE(v) FIELD_PREP(DFSDM_CR2_JEOCIE_MASK, v)
144#define DFSDM_CR2_REOCIE_MASK BIT(1)
145#define DFSDM_CR2_REOCIE(v) FIELD_PREP(DFSDM_CR2_REOCIE_MASK, v)
146#define DFSDM_CR2_JOVRIE_MASK BIT(2)
147#define DFSDM_CR2_JOVRIE(v) FIELD_PREP(DFSDM_CR2_JOVRIE_MASK, v)
148#define DFSDM_CR2_ROVRIE_MASK BIT(3)
149#define DFSDM_CR2_ROVRIE(v) FIELD_PREP(DFSDM_CR2_ROVRIE_MASK, v)
150#define DFSDM_CR2_AWDIE_MASK BIT(4)
151#define DFSDM_CR2_AWDIE(v) FIELD_PREP(DFSDM_CR2_AWDIE_MASK, v)
152#define DFSDM_CR2_SCDIE_MASK BIT(5)
153#define DFSDM_CR2_SCDIE(v) FIELD_PREP(DFSDM_CR2_SCDIE_MASK, v)
154#define DFSDM_CR2_CKABIE_MASK BIT(6)
155#define DFSDM_CR2_CKABIE(v) FIELD_PREP(DFSDM_CR2_CKABIE_MASK, v)
156#define DFSDM_CR2_EXCH_MASK GENMASK(15, 8)
157#define DFSDM_CR2_EXCH(v) FIELD_PREP(DFSDM_CR2_EXCH_MASK, v)
158#define DFSDM_CR2_AWDCH_MASK GENMASK(23, 16)
159#define DFSDM_CR2_AWDCH(v) FIELD_PREP(DFSDM_CR2_AWDCH_MASK, v)
160
161/* ISR: Interrupt status register */
162#define DFSDM_ISR_JEOCF_MASK BIT(0)
163#define DFSDM_ISR_JEOCF(v) FIELD_PREP(DFSDM_ISR_JEOCF_MASK, v)
164#define DFSDM_ISR_REOCF_MASK BIT(1)
165#define DFSDM_ISR_REOCF(v) FIELD_PREP(DFSDM_ISR_REOCF_MASK, v)
166#define DFSDM_ISR_JOVRF_MASK BIT(2)
167#define DFSDM_ISR_JOVRF(v) FIELD_PREP(DFSDM_ISR_JOVRF_MASK, v)
168#define DFSDM_ISR_ROVRF_MASK BIT(3)
169#define DFSDM_ISR_ROVRF(v) FIELD_PREP(DFSDM_ISR_ROVRF_MASK, v)
170#define DFSDM_ISR_AWDF_MASK BIT(4)
171#define DFSDM_ISR_AWDF(v) FIELD_PREP(DFSDM_ISR_AWDF_MASK, v)
172#define DFSDM_ISR_JCIP_MASK BIT(13)
173#define DFSDM_ISR_JCIP(v) FIELD_PREP(DFSDM_ISR_JCIP_MASK, v)
174#define DFSDM_ISR_RCIP_MASK BIT(14)
175#define DFSDM_ISR_RCIP(v) FIELD_PREP(DFSDM_ISR_RCIP, v)
176#define DFSDM_ISR_CKABF_MASK GENMASK(23, 16)
177#define DFSDM_ISR_CKABF(v) FIELD_PREP(DFSDM_ISR_CKABF_MASK, v)
178#define DFSDM_ISR_SCDF_MASK GENMASK(31, 24)
179#define DFSDM_ISR_SCDF(v) FIELD_PREP(DFSDM_ISR_SCDF_MASK, v)
180
181/* ICR: Interrupt flag clear register */
182#define DFSDM_ICR_CLRJOVRF_MASK BIT(2)
183#define DFSDM_ICR_CLRJOVRF(v) FIELD_PREP(DFSDM_ICR_CLRJOVRF_MASK, v)
184#define DFSDM_ICR_CLRROVRF_MASK BIT(3)
185#define DFSDM_ICR_CLRROVRF(v) FIELD_PREP(DFSDM_ICR_CLRROVRF_MASK, v)
186#define DFSDM_ICR_CLRCKABF_MASK GENMASK(23, 16)
187#define DFSDM_ICR_CLRCKABF(v) FIELD_PREP(DFSDM_ICR_CLRCKABF_MASK, v)
188#define DFSDM_ICR_CLRCKABF_CH_MASK(y) BIT(16 + (y))
189#define DFSDM_ICR_CLRCKABF_CH(v, y) \
190 (((v) << (16 + (y))) & DFSDM_ICR_CLRCKABF_CH_MASK(y))
191#define DFSDM_ICR_CLRSCDF_MASK GENMASK(31, 24)
192#define DFSDM_ICR_CLRSCDF(v) FIELD_PREP(DFSDM_ICR_CLRSCDF_MASK, v)
193#define DFSDM_ICR_CLRSCDF_CH_MASK(y) BIT(24 + (y))
194#define DFSDM_ICR_CLRSCDF_CH(v, y) \
195 (((v) << (24 + (y))) & DFSDM_ICR_CLRSCDF_MASK(y))
196
197/* FCR: Filter control register */
198#define DFSDM_FCR_IOSR_MASK GENMASK(7, 0)
199#define DFSDM_FCR_IOSR(v) FIELD_PREP(DFSDM_FCR_IOSR_MASK, v)
200#define DFSDM_FCR_FOSR_MASK GENMASK(25, 16)
201#define DFSDM_FCR_FOSR(v) FIELD_PREP(DFSDM_FCR_FOSR_MASK, v)
202#define DFSDM_FCR_FORD_MASK GENMASK(31, 29)
203#define DFSDM_FCR_FORD(v) FIELD_PREP(DFSDM_FCR_FORD_MASK, v)
204
205/* RDATAR: Filter data register for regular channel */
206#define DFSDM_DATAR_CH_MASK GENMASK(2, 0)
207#define DFSDM_DATAR_DATA_OFFSET 8
208#define DFSDM_DATAR_DATA_MASK GENMASK(31, DFSDM_DATAR_DATA_OFFSET)
209
210/* AWLTR: Filter analog watchdog low threshold register */
211#define DFSDM_AWLTR_BKAWL_MASK GENMASK(3, 0)
212#define DFSDM_AWLTR_BKAWL(v) FIELD_PREP(DFSDM_AWLTR_BKAWL_MASK, v)
213#define DFSDM_AWLTR_AWLT_MASK GENMASK(31, 8)
214#define DFSDM_AWLTR_AWLT(v) FIELD_PREP(DFSDM_AWLTR_AWLT_MASK, v)
215
216/* AWHTR: Filter analog watchdog low threshold register */
217#define DFSDM_AWHTR_BKAWH_MASK GENMASK(3, 0)
218#define DFSDM_AWHTR_BKAWH(v) FIELD_PREP(DFSDM_AWHTR_BKAWH_MASK, v)
219#define DFSDM_AWHTR_AWHT_MASK GENMASK(31, 8)
220#define DFSDM_AWHTR_AWHT(v) FIELD_PREP(DFSDM_AWHTR_AWHT_MASK, v)
221
222/* AWSR: Filter watchdog status register */
223#define DFSDM_AWSR_AWLTF_MASK GENMASK(7, 0)
224#define DFSDM_AWSR_AWLTF(v) FIELD_PREP(DFSDM_AWSR_AWLTF_MASK, v)
225#define DFSDM_AWSR_AWHTF_MASK GENMASK(15, 8)
226#define DFSDM_AWSR_AWHTF(v) FIELD_PREP(DFSDM_AWSR_AWHTF_MASK, v)
227
228/* AWCFR: Filter watchdog status register */
229#define DFSDM_AWCFR_AWLTF_MASK GENMASK(7, 0)
230#define DFSDM_AWCFR_AWLTF(v) FIELD_PREP(DFSDM_AWCFR_AWLTF_MASK, v)
231#define DFSDM_AWCFR_AWHTF_MASK GENMASK(15, 8)
232#define DFSDM_AWCFR_AWHTF(v) FIELD_PREP(DFSDM_AWCFR_AWHTF_MASK, v)
233
234/* DFSDM filter order */
235enum stm32_dfsdm_sinc_order {
236 DFSDM_FASTSINC_ORDER, /* FastSinc filter type */
237 DFSDM_SINC1_ORDER, /* Sinc 1 filter type */
238 DFSDM_SINC2_ORDER, /* Sinc 2 filter type */
239 DFSDM_SINC3_ORDER, /* Sinc 3 filter type */
240 DFSDM_SINC4_ORDER, /* Sinc 4 filter type (N.A. for watchdog) */
241 DFSDM_SINC5_ORDER, /* Sinc 5 filter type (N.A. for watchdog) */
242 DFSDM_NB_SINC_ORDER,
243};
244
245/**
246 * struct stm32_dfsdm_filter - structure relative to stm32 FDSDM filter
247 * @iosr: integrator oversampling
248 * @fosr: filter oversampling
249 * @ford: filter order
250 * @res: output sample resolution
251 * @sync_mode: filter synchronized with filter 0
252 * @fast: filter fast mode
253 */
254struct stm32_dfsdm_filter {
255 unsigned int iosr;
256 unsigned int fosr;
257 enum stm32_dfsdm_sinc_order ford;
258 u64 res;
259 unsigned int sync_mode;
260 unsigned int fast;
261};
262
263/**
264 * struct stm32_dfsdm_channel - structure relative to stm32 FDSDM channel
265 * @id: id of the channel
266 * @type: interface type linked to stm32_dfsdm_chan_type
267 * @src: interface type linked to stm32_dfsdm_chan_src
268 * @alt_si: alternative serial input interface
269 */
270struct stm32_dfsdm_channel {
271 unsigned int id;
272 unsigned int type;
273 unsigned int src;
274 unsigned int alt_si;
275};
276
277/**
278 * struct stm32_dfsdm - stm32 FDSDM driver common data (for all instances)
279 * @base: control registers base cpu addr
280 * @phys_base: DFSDM IP register physical address
281 * @regmap: regmap for register read/write
282 * @fl_list: filter resources list
283 * @num_fls: number of filter resources available
284 * @ch_list: channel resources list
285 * @num_chs: number of channel resources available
286 * @spi_master_freq: SPI clock out frequency
287 */
288struct stm32_dfsdm {
289 void __iomem *base;
290 phys_addr_t phys_base;
291 struct regmap *regmap;
292 struct stm32_dfsdm_filter *fl_list;
293 unsigned int num_fls;
294 struct stm32_dfsdm_channel *ch_list;
295 unsigned int num_chs;
296 unsigned int spi_master_freq;
297};
298
299/* DFSDM channel serial spi clock source */
300enum stm32_dfsdm_spi_clk_src {
301 DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL,
302 DFSDM_CHANNEL_SPI_CLOCK_INTERNAL,
303 DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING,
304 DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING
305};
306
307int stm32_dfsdm_start_dfsdm(struct stm32_dfsdm *dfsdm);
308int stm32_dfsdm_stop_dfsdm(struct stm32_dfsdm *dfsdm);
309
310#endif