diff options
Diffstat (limited to 'drivers/mfd/stm32-timers.c')
-rw-r--r-- | drivers/mfd/stm32-timers.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/drivers/mfd/stm32-timers.c b/drivers/mfd/stm32-timers.c index 650724e19b88..e3c116ee4034 100644 --- a/drivers/mfd/stm32-timers.c +++ b/drivers/mfd/stm32-timers.c @@ -9,6 +9,7 @@ #include <linux/module.h> #include <linux/of_platform.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/reset.h> #define STM32_TIMERS_MAX_REGISTERS 0x3fc @@ -173,6 +174,31 @@ static void stm32_timers_get_arr_size(struct stm32_timers *ddata) regmap_write(ddata->regmap, TIM_ARR, arr); } +static int stm32_timers_probe_hwcfgr(struct device *dev, struct stm32_timers *ddata) +{ + u32 val; + + ddata->ipidr = (uintptr_t)device_get_match_data(dev); + if (!ddata->ipidr) { + /* Fallback to legacy method for probing counter width */ + stm32_timers_get_arr_size(ddata); + return 0; + } + + regmap_read(ddata->regmap, TIM_IPIDR, &val); + if (val != ddata->ipidr) { + dev_err(dev, "Unsupported device detected: %u\n", val); + return -EINVAL; + } + + regmap_read(ddata->regmap, TIM_HWCFGR2, &val); + + /* Counter width in bits, max reload value is BIT(width) - 1 */ + ddata->max_arr = BIT(FIELD_GET(TIM_HWCFGR2_CNT_WIDTH, val)) - 1; + + return 0; +} + static int stm32_timers_dma_probe(struct device *dev, struct stm32_timers *ddata) { @@ -285,7 +311,9 @@ static int stm32_timers_probe(struct platform_device *pdev) if (IS_ERR(ddata->clk)) return PTR_ERR(ddata->clk); - stm32_timers_get_arr_size(ddata); + ret = stm32_timers_probe_hwcfgr(dev, ddata); + if (ret) + return ret; ret = stm32_timers_irq_probe(pdev, ddata); if (ret) @@ -320,6 +348,7 @@ static void stm32_timers_remove(struct platform_device *pdev) static const struct of_device_id stm32_timers_of_match[] = { { .compatible = "st,stm32-timers", }, + { .compatible = "st,stm32mp25-timers", .data = (void *)STM32MP25_TIM_IPIDR }, { /* end node */ }, }; MODULE_DEVICE_TABLE(of, stm32_timers_of_match); |