summaryrefslogtreecommitdiff
path: root/drivers/mfd/stm32-timers.c
diff options
context:
space:
mode:
authorFabrice Gasnier <fabrice.gasnier@foss.st.com>2025-01-10 10:19:16 +0100
committerLee Jones <lee@kernel.org>2025-03-14 08:59:05 +0000
commit7dc0dddbe503fce55ffe31ae5e8a861256a31e3f (patch)
treeb7d4fa907007b11093aa3dadafc29e304cbbccb1 /drivers/mfd/stm32-timers.c
parent7b4270d17bf9c03c03e13972bcbb8dccec3956fa (diff)
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>
Diffstat (limited to 'drivers/mfd/stm32-timers.c')
-rw-r--r--drivers/mfd/stm32-timers.c31
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);