]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
mfd: stm32-timers: Add support for stm32mp25
authorFabrice Gasnier <fabrice.gasnier@foss.st.com>
Fri, 10 Jan 2025 09:19:16 +0000 (10:19 +0100)
committerLee Jones <lee@kernel.org>
Fri, 14 Mar 2025 08:59:05 +0000 (08:59 +0000)
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>
drivers/mfd/stm32-timers.c
include/linux/mfd/stm32-timers.h

index 650724e19b88622ea0bb54b44ac9c3e4e94c59f0..e3c116ee4034ace9dffadff16621dccafe8fc4b9 100644 (file)
@@ -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);
index f09ba598c97ae929877a525a18bc694aa6cbc717..23b0cae4a9f87347e29da40e07f0a2a2a0fd955d 100644 (file)
@@ -33,6 +33,9 @@
 #define TIM_DCR                0x48                    /* DMA control register                 */
 #define TIM_DMAR       0x4C                    /* DMA register for transfer            */
 #define TIM_TISEL      0x68                    /* Input Selection                      */
+#define TIM_HWCFGR2    0x3EC                   /* hardware configuration 2 Reg (MP25)  */
+#define TIM_HWCFGR1    0x3F0                   /* hardware configuration 1 Reg (MP25)  */
+#define TIM_IPIDR      0x3F8                   /* IP identification Reg (MP25)         */
 
 #define TIM_CR1_CEN            BIT(0)                                  /* Counter Enable                               */
 #define TIM_CR1_DIR            BIT(4)                                  /* Counter Direction                            */
 #define TIM_BDTR_BKF(x)                (0xf << (16 + (x) * 4))
 #define TIM_DCR_DBA            GENMASK(4, 0)                           /* DMA base addr                                */
 #define TIM_DCR_DBL            GENMASK(12, 8)                          /* DMA burst len                                */
+#define TIM_HWCFGR1_NB_OF_CC   GENMASK(3, 0)                           /* Capture/compare channels                     */
+#define TIM_HWCFGR1_NB_OF_DT   GENMASK(7, 4)                           /* Complementary outputs & dead-time generators */
+#define TIM_HWCFGR2_CNT_WIDTH  GENMASK(15, 8)                          /* Counter width                                */
 
 #define MAX_TIM_PSC                            0xFFFF
 #define MAX_TIM_ICPSC                          0x3
 #define TIM_BDTR_BKF_MASK                      0xF
 #define TIM_BDTR_BKF_SHIFT(x)                  (16 + (x) * 4)
 
+#define STM32MP25_TIM_IPIDR    0x00120002
+
 enum stm32_timers_dmas {
        STM32_TIMERS_DMA_CH1,
        STM32_TIMERS_DMA_CH2,
@@ -151,6 +159,7 @@ struct stm32_timers_dma {
 
 struct stm32_timers {
        struct clk *clk;
+       u32 ipidr;
        struct regmap *regmap;
        u32 max_arr;
        struct stm32_timers_dma dma; /* Only to be used by the parent */