[PATCH 1/3] arm: stm32mp2: add multifunction timer support for stm32mp25

Patrice CHOTARD patrice.chotard at foss.st.com
Thu Jul 31 11:15:00 CEST 2025



On 7/28/25 11:03, Patrice CHOTARD wrote:
> 
> 
> On 6/20/25 17:49, Cheick Traore wrote:
>> 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 at foss.st.com>
>> ---
>>
>>  arch/arm/mach-stm32mp/include/mach/timers.h |  9 ++++++
>>  arch/arm/mach-stm32mp/timers.c              | 34 ++++++++++++++++++++-
>>  2 files changed, 42 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/mach-stm32mp/include/mach/timers.h b/arch/arm/mach-stm32mp/include/mach/timers.h
>> index a84465bb28e..8209dd84911 100644
>> --- a/arch/arm/mach-stm32mp/include/mach/timers.h
>> +++ b/arch/arm/mach-stm32mp/include/mach/timers.h
>> @@ -29,6 +29,10 @@
>>  #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))
>> @@ -40,11 +44,16 @@
>>  #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 {
>> diff --git a/arch/arm/mach-stm32mp/timers.c b/arch/arm/mach-stm32mp/timers.c
>> index a3207895f40..1940ba42f74 100644
>> --- a/arch/arm/mach-stm32mp/timers.c
>> +++ b/arch/arm/mach-stm32mp/timers.c
>> @@ -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 },
>>  	{}
>>  };
>>  
> Hi Cheick
> 
> Reviewed-by: Patrice Chotard <patrice.chotard at foss.st.com>
> 
> Thanks

Applied to u-boot-stm32/master

Thanks
Patrice


More information about the U-Boot mailing list