]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
arm: stm32mp2: add multifunction timer support for stm32mp25
authorCheick Traore <cheick.traore@foss.st.com>
Fri, 20 Jun 2025 15:49:58 +0000 (17:49 +0200)
committerPatrice Chotard <patrice.chotard@foss.st.com>
Tue, 29 Jul 2025 14:44:58 +0000 (16:44 +0200)
Add support for STM32MP25 SoC.
Identification and hardware configuration registers allow to read the
timer version and capabilities (counter width, ...).
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: Cheick Traore <cheick.traore@foss.st.com>
Reviewed-by: Patrice Chotard <patrice.chotard@foss.st.com>
arch/arm/mach-stm32mp/include/mach/timers.h
arch/arm/mach-stm32mp/timers.c

index a84465bb28e28a1cdb8b2702f91a8ef202f0d62f..8209dd84911509ac8e4cd2aae716a9322d9d003a 100644 (file)
 #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_ARPE   BIT(7)
 #define TIM_CCER_CCXE  (BIT(0) | BIT(4) | BIT(8) | BIT(12))
 #define TIM_CCMR_M1    (BIT(6) | BIT(5))  /* Channel PWM Mode 1 */
 #define TIM_BDTR_MOE   BIT(15) /* Main Output Enable      */
 #define TIM_EGR_UG     BIT(0)  /* Update Generation       */
+#define TIM_HWCFGR2_CNT_WIDTH  GENMASK(15, 8)  /* Counter width */
+#define TIM_HWCFGR1_NB_OF_DT   GENMASK(7, 4)   /* Complementary outputs & dead-time generators */
 
 #define MAX_TIM_PSC            0xFFFF
 
+#define STM32MP25_TIM_IPIDR    0x00120002
+
 struct stm32_timers_plat {
        void __iomem *base;
+       u32 ipidr;
 };
 
 struct stm32_timers_priv {
index a3207895f4068151c7c46b08d88824a2ae3be325..1940ba42f7469256704ef36cf4f466ea87e073d0 100644 (file)
@@ -10,6 +10,7 @@
 #include <asm/io.h>
 #include <asm/arch/timers.h>
 #include <dm/device_compat.h>
+#include <linux/bitfield.h>
 
 static void stm32_timers_get_arr_size(struct udevice *dev)
 {
@@ -29,6 +30,33 @@ static void stm32_timers_get_arr_size(struct udevice *dev)
        writel(arr, plat->base + TIM_ARR);
 }
 
+static int stm32_timers_probe_hwcfgr(struct udevice *dev)
+{
+       struct stm32_timers_plat *plat = dev_get_plat(dev);
+       struct stm32_timers_priv *priv = dev_get_priv(dev);
+       u32 val;
+
+       if (!plat->ipidr) {
+               /* fallback to legacy method for probing counter width */
+               stm32_timers_get_arr_size(dev);
+               return 0;
+       }
+
+       val = readl(plat->base + TIM_IPIDR);
+       /* Sanity check on IP identification register */
+       if (val != plat->ipidr) {
+               dev_err(dev, "Unexpected identification: %u\n", val);
+               return -EINVAL;
+       }
+
+       val = readl(plat->base + TIM_HWCFGR2);
+       /* Counter width in bits, max reload value is BIT(width) - 1 */
+       priv->max_arr = BIT(FIELD_GET(TIM_HWCFGR2_CNT_WIDTH, val)) - 1;
+       dev_dbg(dev, "TIM width: %ld\n", FIELD_GET(TIM_HWCFGR2_CNT_WIDTH, val));
+
+       return 0;
+}
+
 static int stm32_timers_of_to_plat(struct udevice *dev)
 {
        struct stm32_timers_plat *plat = dev_get_plat(dev);
@@ -38,6 +66,7 @@ static int stm32_timers_of_to_plat(struct udevice *dev)
                dev_err(dev, "can't get address\n");
                return -ENOENT;
        }
+       plat->ipidr = (u32)dev_get_driver_data(dev);
 
        return 0;
 }
@@ -60,13 +89,16 @@ static int stm32_timers_probe(struct udevice *dev)
 
        priv->rate = clk_get_rate(&clk);
 
-       stm32_timers_get_arr_size(dev);
+       ret = stm32_timers_probe_hwcfgr(dev);
+       if (ret)
+               clk_disable(&clk);
 
        return ret;
 }
 
 static const struct udevice_id stm32_timers_ids[] = {
        { .compatible = "st,stm32-timers" },
+       { .compatible = "st,stm32mp25-timers", .data = STM32MP25_TIM_IPIDR },
        {}
 };