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

iio: adc: stm32-dfsdm: add id registers support

Add support of identification registers to STM32 DFSDM
to allow hardware capabilities discovery and configuration check.
The number of filters and channels, are read from registers,
when they are available.

Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com>
Link: https://lore.kernel.org/r/20230105125331.328275-1-olivier.moysan@foss.st.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Olivier Moysan and committed by
Jonathan Cameron
bfcae956 14e5b7ab

+124 -35
+83 -16
drivers/iio/adc/stm32-dfsdm-core.c
··· 6 6 * Author(s): Arnaud Pouliquen <arnaud.pouliquen@st.com> for STMicroelectronics. 7 7 */ 8 8 9 + #include <linux/bitfield.h> 9 10 #include <linux/clk.h> 10 11 #include <linux/iio/iio.h> 11 12 #include <linux/iio/sysfs.h> ··· 20 19 21 20 #include "stm32-dfsdm.h" 22 21 22 + /** 23 + * struct stm32_dfsdm_dev_data - DFSDM compatible configuration data 24 + * @ipid: DFSDM identification number. Used only if hardware provides identification registers 25 + * @num_filters: DFSDM number of filters. Unused if identification registers are available 26 + * @num_channels: DFSDM number of channels. Unused if identification registers are available 27 + * @regmap_cfg: SAI register map configuration pointer 28 + */ 23 29 struct stm32_dfsdm_dev_data { 30 + u32 ipid; 24 31 unsigned int num_filters; 25 32 unsigned int num_channels; 26 33 const struct regmap_config *regmap_cfg; ··· 36 27 37 28 #define STM32H7_DFSDM_NUM_FILTERS 4 38 29 #define STM32H7_DFSDM_NUM_CHANNELS 8 39 - #define STM32MP1_DFSDM_NUM_FILTERS 6 40 - #define STM32MP1_DFSDM_NUM_CHANNELS 8 41 30 42 31 static bool stm32_dfsdm_volatile_reg(struct device *dev, unsigned int reg) 43 32 { ··· 82 75 }; 83 76 84 77 static const struct stm32_dfsdm_dev_data stm32mp1_dfsdm_data = { 85 - .num_filters = STM32MP1_DFSDM_NUM_FILTERS, 86 - .num_channels = STM32MP1_DFSDM_NUM_CHANNELS, 78 + .ipid = STM32MP15_IPIDR_NUMBER, 87 79 .regmap_cfg = &stm32mp1_dfsdm_regmap_cfg, 88 80 }; 89 81 ··· 301 295 }; 302 296 MODULE_DEVICE_TABLE(of, stm32_dfsdm_of_match); 303 297 298 + static int stm32_dfsdm_probe_identification(struct platform_device *pdev, 299 + struct dfsdm_priv *priv, 300 + const struct stm32_dfsdm_dev_data *dev_data) 301 + { 302 + struct device_node *np = pdev->dev.of_node; 303 + struct device_node *child; 304 + struct stm32_dfsdm *dfsdm = &priv->dfsdm; 305 + const char *compat; 306 + int ret, count = 0; 307 + u32 id, val; 308 + 309 + if (!dev_data->ipid) { 310 + dfsdm->num_fls = dev_data->num_filters; 311 + dfsdm->num_chs = dev_data->num_channels; 312 + return 0; 313 + } 314 + 315 + ret = regmap_read(dfsdm->regmap, DFSDM_IPIDR, &id); 316 + if (ret) 317 + return ret; 318 + 319 + if (id != dev_data->ipid) { 320 + dev_err(&pdev->dev, "Unexpected IP version: 0x%x", id); 321 + return -EINVAL; 322 + } 323 + 324 + for_each_child_of_node(np, child) { 325 + ret = of_property_read_string(child, "compatible", &compat); 326 + if (ret) 327 + continue; 328 + /* Count only child nodes with dfsdm compatible */ 329 + if (strstr(compat, "dfsdm")) 330 + count++; 331 + } 332 + 333 + ret = regmap_read(dfsdm->regmap, DFSDM_HWCFGR, &val); 334 + if (ret) 335 + return ret; 336 + 337 + dfsdm->num_fls = FIELD_GET(DFSDM_HWCFGR_NBF_MASK, val); 338 + dfsdm->num_chs = FIELD_GET(DFSDM_HWCFGR_NBT_MASK, val); 339 + 340 + if (count > dfsdm->num_fls) { 341 + dev_err(&pdev->dev, "Unexpected child number: %d", count); 342 + return -EINVAL; 343 + } 344 + 345 + ret = regmap_read(dfsdm->regmap, DFSDM_VERR, &val); 346 + if (ret) 347 + return ret; 348 + 349 + dev_dbg(&pdev->dev, "DFSDM version: %lu.%lu. %d channels/%d filters\n", 350 + FIELD_GET(DFSDM_VERR_MAJREV_MASK, val), 351 + FIELD_GET(DFSDM_VERR_MINREV_MASK, val), 352 + dfsdm->num_chs, dfsdm->num_fls); 353 + 354 + return 0; 355 + } 356 + 304 357 static int stm32_dfsdm_probe(struct platform_device *pdev) 305 358 { 306 359 struct dfsdm_priv *priv; ··· 376 311 dev_data = of_device_get_match_data(&pdev->dev); 377 312 378 313 dfsdm = &priv->dfsdm; 379 - dfsdm->fl_list = devm_kcalloc(&pdev->dev, dev_data->num_filters, 380 - sizeof(*dfsdm->fl_list), GFP_KERNEL); 381 - if (!dfsdm->fl_list) 382 - return -ENOMEM; 383 - 384 - dfsdm->num_fls = dev_data->num_filters; 385 - dfsdm->ch_list = devm_kcalloc(&pdev->dev, dev_data->num_channels, 386 - sizeof(*dfsdm->ch_list), 387 - GFP_KERNEL); 388 - if (!dfsdm->ch_list) 389 - return -ENOMEM; 390 - dfsdm->num_chs = dev_data->num_channels; 391 314 392 315 ret = stm32_dfsdm_parse_of(pdev, priv); 393 316 if (ret < 0) ··· 390 337 __func__, ret); 391 338 return ret; 392 339 } 340 + 341 + ret = stm32_dfsdm_probe_identification(pdev, priv, dev_data); 342 + if (ret < 0) 343 + return ret; 344 + 345 + dfsdm->fl_list = devm_kcalloc(&pdev->dev, dfsdm->num_fls, 346 + sizeof(*dfsdm->fl_list), GFP_KERNEL); 347 + if (!dfsdm->fl_list) 348 + return -ENOMEM; 349 + 350 + dfsdm->ch_list = devm_kcalloc(&pdev->dev, dfsdm->num_chs, 351 + sizeof(*dfsdm->ch_list), GFP_KERNEL); 352 + if (!dfsdm->ch_list) 353 + return -ENOMEM; 393 354 394 355 platform_set_drvdata(pdev, dfsdm); 395 356
+41 -19
drivers/iio/adc/stm32-dfsdm.h
··· 13 13 14 14 /* 15 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 - * -------------------------------------------------------- 16 + * __________________________________________________________ 17 + * | Offset | Registers block | 18 + * ---------------------------------------------------------- 19 + * | 0x000 | CHANNEL 0 + COMMON CHANNEL FIELDS | 20 + * ---------------------------------------------------------- 21 + * | 0x020 | CHANNEL 1 | 22 + * ---------------------------------------------------------- 23 + * | ... | ..... | 24 + * ---------------------------------------------------------- 25 + * | 0x20 x n | CHANNEL n | 26 + * ---------------------------------------------------------- 27 + * | 0x100 | FILTER 0 + COMMON FILTER FIELDs | 28 + * ---------------------------------------------------------- 29 + * | 0x200 | FILTER 1 | 30 + * ---------------------------------------------------------- 31 + * | | ..... | 32 + * ---------------------------------------------------------- 33 + * | 0x100 x m | FILTER m | 34 + * ---------------------------------------------------------- 35 + * | | ..... | 36 + * ---------------------------------------------------------- 37 + * | 0x7F0-7FC | Identification registers | 38 + * ---------------------------------------------------------- 35 39 */ 36 40 37 41 /* ··· 234 230 #define DFSDM_AWCFR_AWLTF(v) FIELD_PREP(DFSDM_AWCFR_AWLTF_MASK, v) 235 231 #define DFSDM_AWCFR_AWHTF_MASK GENMASK(15, 8) 236 232 #define DFSDM_AWCFR_AWHTF(v) FIELD_PREP(DFSDM_AWCFR_AWHTF_MASK, v) 233 + 234 + /* 235 + * Identification register definitions 236 + */ 237 + #define DFSDM_HWCFGR 0x7F0 238 + #define DFSDM_VERR 0x7F4 239 + #define DFSDM_IPIDR 0x7F8 240 + #define DFSDM_SIDR 0x7FC 241 + 242 + /* HWCFGR: Hardware configuration register */ 243 + #define DFSDM_HWCFGR_NBT_MASK GENMASK(7, 0) 244 + #define DFSDM_HWCFGR_NBF_MASK GENMASK(15, 8) 245 + 246 + /* VERR: Version register */ 247 + #define DFSDM_VERR_MINREV_MASK GENMASK(3, 0) 248 + #define DFSDM_VERR_MAJREV_MASK GENMASK(7, 4) 249 + 250 + #define STM32MP15_IPIDR_NUMBER 0x00110031 237 251 238 252 /* DFSDM filter order */ 239 253 enum stm32_dfsdm_sinc_order {