Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Arnaud Pouliquen and committed by
Mark Brown
bed73904 6c82f947

+632
+12
drivers/iio/adc/Kconfig
··· 668 668 This driver can also be built as a module. If so, the module 669 669 will be called stm32-adc. 670 670 671 + config 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 + 671 683 config STX104 672 684 tristate "Apex Embedded Systems STX104 driver" 673 685 depends on PC104 && X86 && ISA_BUS_API
+1
drivers/iio/adc/Makefile
··· 64 64 obj-$(CONFIG_SUN4I_GPADC) += sun4i-gpadc-iio.o 65 65 obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o 66 66 obj-$(CONFIG_STM32_ADC) += stm32-adc.o 67 + obj-$(CONFIG_STM32_DFSDM_CORE) += stm32-dfsdm-core.o 67 68 obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o 68 69 obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o 69 70 obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o
+309
drivers/iio/adc/stm32-dfsdm-core.c
··· 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 + 20 + struct 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 + 29 + static 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 + 49 + static 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 + 58 + static 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 + 64 + struct 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 + */ 82 + int 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 + 123 + disable_aclk: 124 + clk_disable_unprepare(priv->aclk); 125 + disable_clk: 126 + clk_disable_unprepare(priv->clk); 127 + 128 + error_ret: 129 + atomic_dec(&priv->n_active_ch); 130 + 131 + return ret; 132 + } 133 + EXPORT_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 + */ 141 + int 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 + } 170 + EXPORT_SYMBOL_GPL(stm32_dfsdm_stop_dfsdm); 171 + 172 + static 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 + 233 + static const struct of_device_id stm32_dfsdm_of_match[] = { 234 + { 235 + .compatible = "st,stm32h7-dfsdm", 236 + .data = &stm32h7_dfsdm_data, 237 + }, 238 + {} 239 + }; 240 + MODULE_DEVICE_TABLE(of, stm32_dfsdm_of_match); 241 + 242 + static 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 + 297 + static 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 + 305 + module_platform_driver(stm32_dfsdm_driver); 306 + 307 + MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>"); 308 + MODULE_DESCRIPTION("STMicroelectronics STM32 dfsdm driver"); 309 + MODULE_LICENSE("GPL v2");
+310
drivers/iio/adc/stm32-dfsdm.h
··· 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 */ 235 + enum 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 + */ 254 + struct 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 + */ 270 + struct 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 + */ 288 + struct 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 */ 300 + enum 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 + 307 + int stm32_dfsdm_start_dfsdm(struct stm32_dfsdm *dfsdm); 308 + int stm32_dfsdm_stop_dfsdm(struct stm32_dfsdm *dfsdm); 309 + 310 + #endif