On 3/6/25 15:16, Patrice CHOTARD wrote:
> 
> 
> On 3/6/25 11:56, Cheick Traore wrote:
>> Add support for STM32MP timer multi-function driver.
>> These timers can be use as counter, trigger or pwm generator.
>> This driver will be used to manage the main resources of the timer to
>> provide them to the functionnalities which need these ones.
>>
>> Signed-off-by: Cheick Traore <[email protected]>
>> ---
>>
>>  arch/arm/mach-stm32mp/Kconfig               |  6 ++
>>  arch/arm/mach-stm32mp/Makefile              |  1 +
>>  arch/arm/mach-stm32mp/include/mach/timers.h | 55 ++++++++++++++
>>  arch/arm/mach-stm32mp/timers.c              | 82 +++++++++++++++++++++
>>  4 files changed, 144 insertions(+)
>>  create mode 100644 arch/arm/mach-stm32mp/include/mach/timers.h
>>  create mode 100644 arch/arm/mach-stm32mp/timers.c
>>
>> diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig
>> index 25663a99464..002da2e3d3b 100644
>> --- a/arch/arm/mach-stm32mp/Kconfig
>> +++ b/arch/arm/mach-stm32mp/Kconfig
>> @@ -153,6 +153,12 @@ config CMD_STM32KEY
>>              This command is used to evaluate the secure boot on stm32mp SOC,
>>              it is deactivated by default in real products.
>>  
>> +config MFD_STM32_TIMERS
>> +    bool "STM32 multifonction timer support"
>> +    help
>> +      Select this to enable support for the multifunction timer found on
>> +      STM32 devices.
>> +
>>  source "arch/arm/mach-stm32mp/Kconfig.13x"
>>  source "arch/arm/mach-stm32mp/Kconfig.15x"
>>  source "arch/arm/mach-stm32mp/Kconfig.25x"
>> diff --git a/arch/arm/mach-stm32mp/Makefile b/arch/arm/mach-stm32mp/Makefile
>> index db7ed19bd91..103e3410ad9 100644
>> --- a/arch/arm/mach-stm32mp/Makefile
>> +++ b/arch/arm/mach-stm32mp/Makefile
>> @@ -12,6 +12,7 @@ obj-$(CONFIG_STM32MP15X) += stm32mp1/
>>  obj-$(CONFIG_STM32MP13X) += stm32mp1/
>>  obj-$(CONFIG_STM32MP25X) += stm32mp2/
>>  
>> +obj-$(CONFIG_MFD_STM32_TIMERS) += timers.o
>>  obj-$(CONFIG_STM32_ECDSA_VERIFY) += ecdsa_romapi.o
>>  ifndef CONFIG_XPL_BUILD
>>  obj-y += cmd_stm32prog/
>> diff --git a/arch/arm/mach-stm32mp/include/mach/timers.h 
>> b/arch/arm/mach-stm32mp/include/mach/timers.h
>> new file mode 100644
>> index 00000000000..a84465bb28e
>> --- /dev/null
>> +++ b/arch/arm/mach-stm32mp/include/mach/timers.h
>> @@ -0,0 +1,55 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Copyright (C) 2025, STMicroelectronics - All Rights Reserved
>> + * Author: Cheick Traore <[email protected]>
>> + *
>> + * Originally based on the Linux kernel v6.1 
>> include/linux/mfd/stm32-timers.h.
>> + */
>> +
>> +#ifndef __STM32_TIMERS_H
>> +#define __STM32_TIMERS_H
>> +
>> +#include <clk.h>
>> +
>> +#define TIM_CR1             0x00    /* Control Register 1      */
>> +#define TIM_CR2             0x04    /* Control Register 2      */
>> +#define TIM_SMCR    0x08    /* Slave mode control reg  */
>> +#define TIM_DIER    0x0C    /* DMA/interrupt register  */
>> +#define TIM_SR              0x10    /* Status register         */
>> +#define TIM_EGR             0x14    /* Event Generation Reg    */
>> +#define TIM_CCMR1   0x18    /* Capt/Comp 1 Mode Reg    */
>> +#define TIM_CCMR2   0x1C    /* Capt/Comp 2 Mode Reg    */
>> +#define TIM_CCER    0x20    /* Capt/Comp Enable Reg    */
>> +#define TIM_CNT             0x24    /* Counter                 */
>> +#define TIM_PSC             0x28    /* Prescaler               */
>> +#define TIM_ARR             0x2c    /* Auto-Reload Register    */
>> +#define TIM_CCRx(x) (0x34 + 4 * ((x) - 1))  /* Capt/Comp Register x (x ∈ 
>> {1, .. 4}) */
>> +#define TIM_BDTR    0x44    /* Break and Dead-Time Reg */
>> +#define TIM_DCR             0x48    /* DMA control register    */
>> +#define TIM_DMAR    0x4C    /* DMA register for transfer */
>> +#define TIM_TISEL   0x68    /* Input Selection         */
>> +
>> +#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_CCER_CC1E       BIT(0)
>> +#define TIM_CCER_CC1P       BIT(1)  /* Capt/Comp 1  Polarity   */
>> +#define TIM_CCER_CC1NE      BIT(2)  /* Capt/Comp 1N out Ena    */
>> +#define TIM_CCER_CC1NP      BIT(3)  /* Capt/Comp 1N Polarity   */
>> +#define TIM_CCMR_PE BIT(3)  /* Channel Preload Enable  */
>> +#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 MAX_TIM_PSC         0xFFFF
>> +
>> +struct stm32_timers_plat {
>> +    void __iomem *base;
>> +};
>> +
>> +struct stm32_timers_priv {
>> +    u32 max_arr;
>> +    ulong rate;
>> +};
>> +
>> +#endif
>> diff --git a/arch/arm/mach-stm32mp/timers.c b/arch/arm/mach-stm32mp/timers.c
>> new file mode 100644
>> index 00000000000..a3207895f40
>> --- /dev/null
>> +++ b/arch/arm/mach-stm32mp/timers.c
>> @@ -0,0 +1,82 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (C) 2025, STMicroelectronics - All Rights Reserved
>> + * Author: Cheick Traore <[email protected]>
>> + *
>> + * Originally based on the Linux kernel v6.1 drivers/mfd/stm32-timers.c.
>> + */
>> +
>> +#include <dm.h>
>> +#include <asm/io.h>
>> +#include <asm/arch/timers.h>
>> +#include <dm/device_compat.h>
>> +
>> +static void stm32_timers_get_arr_size(struct udevice *dev)
>> +{
>> +    struct stm32_timers_plat *plat = dev_get_plat(dev);
>> +    struct stm32_timers_priv *priv = dev_get_priv(dev);
>> +    u32 arr;
>> +
>> +    /* Backup ARR to restore it after getting the maximum value */
>> +    arr = readl(plat->base + TIM_ARR);
>> +
>> +    /*
>> +     * Only the available bits will be written so when readback
>> +     * we get the maximum value of auto reload register
>> +     */
>> +    writel(~0L, plat->base + TIM_ARR);
>> +    priv->max_arr = readl(plat->base + TIM_ARR);
>> +    writel(arr, plat->base + TIM_ARR);
>> +}
>> +
>> +static int stm32_timers_of_to_plat(struct udevice *dev)
>> +{
>> +    struct stm32_timers_plat *plat = dev_get_plat(dev);
>> +
>> +    plat->base = dev_read_addr_ptr(dev);
>> +    if (!plat->base) {
>> +            dev_err(dev, "can't get address\n");
>> +            return -ENOENT;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +static int stm32_timers_probe(struct udevice *dev)
>> +{
>> +    struct stm32_timers_priv *priv = dev_get_priv(dev);
>> +    struct clk clk;
>> +    int ret = 0;
>> +
>> +    ret = clk_get_by_index(dev, 0, &clk);
>> +    if (ret < 0)
>> +            return ret;
>> +
>> +    ret = clk_enable(&clk);
>> +    if (ret) {
>> +            dev_err(dev, "failed to enable clock: ret=%d\n", ret);
>> +            return ret;
>> +    }
>> +
>> +    priv->rate = clk_get_rate(&clk);
>> +
>> +    stm32_timers_get_arr_size(dev);
>> +
>> +    return ret;
>> +}
>> +
>> +static const struct udevice_id stm32_timers_ids[] = {
>> +    { .compatible = "st,stm32-timers" },
>> +    {}
>> +};
>> +
>> +U_BOOT_DRIVER(stm32_timers) = {
>> +    .name  = "stm32_timers",
>> +    .id = UCLASS_NOP,
>> +    .of_match = stm32_timers_ids,
>> +    .of_to_plat = stm32_timers_of_to_plat,
>> +    .plat_auto = sizeof(struct stm32_timers_plat),
>> +    .probe = stm32_timers_probe,
>> +    .priv_auto = sizeof(struct stm32_timers_priv),
>> +    .bind = dm_scan_fdt_dev,
>> +};
> 
> 
> Reviewed-by: Patrice Chotard <[email protected]>
> 
> Thanks
> Patrice
Applied to u-boot-stm32/next

Thanks
Patrice

Reply via email to