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

mfd: stm32-timers: Add support for stm32mp25

Add support for STM32MP25 SoC. Use newly introduced compatible, to handle
new features.
Identification and hardware configuration registers allow to read the
timer version and capabilities (counter width, number of channels...).
So, rework the probe to avoid touching ARR register by simply read the
counter width when available. This may avoid messing with a possibly
running timer.
Also add useful bit fields to stm32-timers header file.

Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
Link: https://lore.kernel.org/r/20250110091922.980627-3-fabrice.gasnier@foss.st.com
Signed-off-by: Lee Jones <lee@kernel.org>

authored by

Fabrice Gasnier and committed by
Lee Jones
7dc0dddb 7b4270d1

+39 -1
+30 -1
drivers/mfd/stm32-timers.c
··· 9 9 #include <linux/module.h> 10 10 #include <linux/of_platform.h> 11 11 #include <linux/platform_device.h> 12 + #include <linux/property.h> 12 13 #include <linux/reset.h> 13 14 14 15 #define STM32_TIMERS_MAX_REGISTERS 0x3fc ··· 174 173 regmap_write(ddata->regmap, TIM_ARR, arr); 175 174 } 176 175 176 + static int stm32_timers_probe_hwcfgr(struct device *dev, struct stm32_timers *ddata) 177 + { 178 + u32 val; 179 + 180 + ddata->ipidr = (uintptr_t)device_get_match_data(dev); 181 + if (!ddata->ipidr) { 182 + /* Fallback to legacy method for probing counter width */ 183 + stm32_timers_get_arr_size(ddata); 184 + return 0; 185 + } 186 + 187 + regmap_read(ddata->regmap, TIM_IPIDR, &val); 188 + if (val != ddata->ipidr) { 189 + dev_err(dev, "Unsupported device detected: %u\n", val); 190 + return -EINVAL; 191 + } 192 + 193 + regmap_read(ddata->regmap, TIM_HWCFGR2, &val); 194 + 195 + /* Counter width in bits, max reload value is BIT(width) - 1 */ 196 + ddata->max_arr = BIT(FIELD_GET(TIM_HWCFGR2_CNT_WIDTH, val)) - 1; 197 + 198 + return 0; 199 + } 200 + 177 201 static int stm32_timers_dma_probe(struct device *dev, 178 202 struct stm32_timers *ddata) 179 203 { ··· 311 285 if (IS_ERR(ddata->clk)) 312 286 return PTR_ERR(ddata->clk); 313 287 314 - stm32_timers_get_arr_size(ddata); 288 + ret = stm32_timers_probe_hwcfgr(dev, ddata); 289 + if (ret) 290 + return ret; 315 291 316 292 ret = stm32_timers_irq_probe(pdev, ddata); 317 293 if (ret) ··· 348 320 349 321 static const struct of_device_id stm32_timers_of_match[] = { 350 322 { .compatible = "st,stm32-timers", }, 323 + { .compatible = "st,stm32mp25-timers", .data = (void *)STM32MP25_TIM_IPIDR }, 351 324 { /* end node */ }, 352 325 }; 353 326 MODULE_DEVICE_TABLE(of, stm32_timers_of_match);
+9
include/linux/mfd/stm32-timers.h
··· 33 33 #define TIM_DCR 0x48 /* DMA control register */ 34 34 #define TIM_DMAR 0x4C /* DMA register for transfer */ 35 35 #define TIM_TISEL 0x68 /* Input Selection */ 36 + #define TIM_HWCFGR2 0x3EC /* hardware configuration 2 Reg (MP25) */ 37 + #define TIM_HWCFGR1 0x3F0 /* hardware configuration 1 Reg (MP25) */ 38 + #define TIM_IPIDR 0x3F8 /* IP identification Reg (MP25) */ 36 39 37 40 #define TIM_CR1_CEN BIT(0) /* Counter Enable */ 38 41 #define TIM_CR1_DIR BIT(4) /* Counter Direction */ ··· 103 100 #define TIM_BDTR_BKF(x) (0xf << (16 + (x) * 4)) 104 101 #define TIM_DCR_DBA GENMASK(4, 0) /* DMA base addr */ 105 102 #define TIM_DCR_DBL GENMASK(12, 8) /* DMA burst len */ 103 + #define TIM_HWCFGR1_NB_OF_CC GENMASK(3, 0) /* Capture/compare channels */ 104 + #define TIM_HWCFGR1_NB_OF_DT GENMASK(7, 4) /* Complementary outputs & dead-time generators */ 105 + #define TIM_HWCFGR2_CNT_WIDTH GENMASK(15, 8) /* Counter width */ 106 106 107 107 #define MAX_TIM_PSC 0xFFFF 108 108 #define MAX_TIM_ICPSC 0x3 ··· 118 112 #define TIM_SMCR_TS_SHIFT 4 119 113 #define TIM_BDTR_BKF_MASK 0xF 120 114 #define TIM_BDTR_BKF_SHIFT(x) (16 + (x) * 4) 115 + 116 + #define STM32MP25_TIM_IPIDR 0x00120002 121 117 122 118 enum stm32_timers_dmas { 123 119 STM32_TIMERS_DMA_CH1, ··· 159 151 160 152 struct stm32_timers { 161 153 struct clk *clk; 154 + u32 ipidr; 162 155 struct regmap *regmap; 163 156 u32 max_arr; 164 157 struct stm32_timers_dma dma; /* Only to be used by the parent */