[U-Boot] [PATCH 0/6] Add DM timer support for STM32 SoCs family

From: Patrice Chotard patrice.chotard@st.com
Add DM timer support for all STM32F7/F4/H7 SoCs family. Clock driver for STM32F4/F7 and H7 need to updated to get timer clock rate. Remove all defines or files previously used for timer usage in arch/arm/include/asm/arch-stm32fx and in arch/arm/mach-stm32/stm32fx.
Patrice Chotard (6): timer: stm32: Add timer support for STM32 SoCs family clk: clk_stm32f: Fix stm32_clk_get_rate() for timer clk: clk_stm32h7: Fix stm32_clk_get_rate() for timer clk: clk_stm32h7: Fix prescaler for Domain 3 ARM: dts: stm32: Add timer support for STM32F7 board: stm32: switch to DM STM32 timer
arch/arm/dts/stm32f7-u-boot.dtsi | 8 ++ arch/arm/dts/stm32f746.dtsi | 7 ++ arch/arm/include/asm/arch-stm32f4/stm32.h | 3 - arch/arm/include/asm/arch-stm32f4/stm32_defs.h | 15 --- arch/arm/include/asm/arch-stm32f7/gpt.h | 53 --------- arch/arm/include/asm/arch-stm32f7/stm32.h | 5 - arch/arm/include/asm/arch-stm32f7/stm32_defs.h | 15 --- arch/arm/include/asm/arch-stm32f7/stm32_periph.h | 4 - arch/arm/mach-stm32/Kconfig | 7 ++ arch/arm/mach-stm32/Makefile | 2 - arch/arm/mach-stm32/stm32f4/Makefile | 11 -- arch/arm/mach-stm32/stm32f4/timer.c | 115 ------------------- arch/arm/mach-stm32/stm32f7/Makefile | 8 -- arch/arm/mach-stm32/stm32f7/timer.c | 113 ------------------- board/st/stm32f746-disco/stm32f746-disco.c | 1 - drivers/clk/clk_stm32f.c | 131 +++++++++++++++------ drivers/clk/clk_stm32h7.c | 109 +++++++++++++++--- drivers/spi/stm32_qspi.c | 1 - drivers/timer/Kconfig | 7 ++ drivers/timer/Makefile | 1 + drivers/timer/stm32_timer.c | 138 +++++++++++++++++++++++ include/configs/stm32h743-disco.h | 3 +- include/configs/stm32h743-eval.h | 3 +- include/stm32_rcc.h | 5 + 24 files changed, 368 insertions(+), 397 deletions(-) delete mode 100644 arch/arm/include/asm/arch-stm32f4/stm32_defs.h delete mode 100644 arch/arm/include/asm/arch-stm32f7/gpt.h delete mode 100644 arch/arm/include/asm/arch-stm32f7/stm32_defs.h delete mode 100644 arch/arm/mach-stm32/stm32f4/Makefile delete mode 100644 arch/arm/mach-stm32/stm32f4/timer.c delete mode 100644 arch/arm/mach-stm32/stm32f7/Makefile delete mode 100644 arch/arm/mach-stm32/stm32f7/timer.c create mode 100644 drivers/timer/stm32_timer.c

From: Patrice Chotard patrice.chotard@st.com
This timer driver is using GPT Timer (General Purpose Timer) available on all STM32 SOCs family. This driver can be used on STM32F4/F7 and H7 SoCs family
Signed-off-by: Patrice Chotard patrice.chotard@st.com --- drivers/timer/Kconfig | 7 +++ drivers/timer/Makefile | 1 + drivers/timer/stm32_timer.c | 138 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 drivers/timer/stm32_timer.c
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 3a1f8311c12e..2c9689672627 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -119,4 +119,11 @@ config ROCKCHIP_TIMER Select this to enable support for the timer found on Rockchip devices.
+config STM32_TIMER + bool "STM32 timer support" + depends on TIMER + help + Select this to enable support for the timer found on + STM32 devices. + endmenu diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile index 15e515407e30..a6e7832154a1 100644 --- a/drivers/timer/Makefile +++ b/drivers/timer/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_AG101P_TIMER) += ag101p_timer.o obj-$(CONFIG_ATCPIT100_TIMER) += atcpit100_timer.o obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o obj-$(CONFIG_ATMEL_PIT_TIMER) += atmel_pit_timer.o +obj-$(CONFIG_STM32_TIMER) += stm32_timer.o diff --git a/drivers/timer/stm32_timer.c b/drivers/timer/stm32_timer.c new file mode 100644 index 000000000000..344e6fba1e95 --- /dev/null +++ b/drivers/timer/stm32_timer.c @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * Author(s): Patrice Chotard, patrice.chotard@st.com for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <fdtdec.h> +#include <timer.h> + +#include <asm/io.h> + +/* Timer control1 register */ +#define CR1_CEN BIT(0) +#define CR1_ARPE BIT(7) + +/* Event Generation Register register */ +#define EGR_UG BIT(0) + +/* Auto reload register for free running config */ +#define GPT_FREE_RUNNING 0xFFFFFFFF + +struct stm32_timer_regs { + u32 cr1; + u32 cr2; + u32 smcr; + u32 dier; + u32 sr; + u32 egr; + u32 ccmr1; + u32 ccmr2; + u32 ccer; + u32 cnt; + u32 psc; + u32 arr; + u32 reserved; + u32 ccr1; + u32 ccr2; + u32 ccr3; + u32 ccr4; + u32 reserved1; + u32 dcr; + u32 dmar; + u32 tim2_5_or; +}; + +struct stm32_timer_priv { + struct stm32_timer_regs *base; +}; + +static int stm32_timer_get_count(struct udevice *dev, u64 *count) +{ + struct stm32_timer_priv *priv = dev_get_priv(dev); + struct stm32_timer_regs *regs = priv->base; + + *count = readl(®s->cnt); + + return 0; +} + +static int stm32_timer_probe(struct udevice *dev) +{ + struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct stm32_timer_priv *priv = dev_get_priv(dev); + struct stm32_timer_regs *regs; + struct clk clk; + fdt_addr_t addr; + int ret; + u32 rate, psc; + + addr = dev_read_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->base = (struct stm32_timer_regs *)addr; + + 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\n"); + return ret; + } + + regs = priv->base; + + /* Stop the timer */ + clrbits_le32(®s->cr1, CR1_CEN); + + /* get timer clock */ + rate = clk_get_rate(&clk); + + /* we set timer prescaler to obtain a 1MHz timer counter frequency */ + psc = (rate / CONFIG_SYS_HZ_CLOCK) - 1; + writel(psc, ®s->psc); + + /* Set timer frequency to 1MHz */ + uc_priv->clock_rate = CONFIG_SYS_HZ_CLOCK; + + /* Configure timer for auto-reload */ + setbits_le32(®s->cr1, CR1_ARPE); + + /* load value for auto reload */ + writel(GPT_FREE_RUNNING, ®s->arr); + + /* start timer */ + setbits_le32(®s->cr1, CR1_CEN); + + /* Update generation */ + setbits_le32(®s->egr, EGR_UG); + + return 0; +} + +static const struct timer_ops stm32_timer_ops = { + .get_count = stm32_timer_get_count, +}; + +static const struct udevice_id stm32_timer_ids[] = { + { .compatible = "st,stm32-timer" }, + {} +}; + +U_BOOT_DRIVER(stm32_timer) = { + .name = "stm32_timer", + .id = UCLASS_TIMER, + .of_match = stm32_timer_ids, + .priv_auto_alloc_size = sizeof(struct stm32_timer_priv), + .probe = stm32_timer_probe, + .ops = &stm32_timer_ops, + .flags = DM_FLAG_PRE_RELOC, +}; +

On Wed, Feb 07, 2018 at 10:44:45AM +0100, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
This timer driver is using GPT Timer (General Purpose Timer) available on all STM32 SOCs family. This driver can be used on STM32F4/F7 and H7 SoCs family
Signed-off-by: Patrice Chotard patrice.chotard@st.com
Applied to u-boot/master, thanks!

From: Patrice Chotard patrice.chotard@st.com
For timer clock, an additionnal prescaler is used which was not taken into account previously.
Signed-off-by: Patrice Chotard patrice.chotard@st.com --- drivers/clk/clk_stm32f.c | 116 ++++++++++++++++++++++++++++++++++++++++------- include/stm32_rcc.h | 5 ++ 2 files changed, 104 insertions(+), 17 deletions(-)
diff --git a/drivers/clk/clk_stm32f.c b/drivers/clk/clk_stm32f.c index 926b249ff3b7..bde31607cfe9 100644 --- a/drivers/clk/clk_stm32f.c +++ b/drivers/clk/clk_stm32f.c @@ -63,6 +63,7 @@ #define RCC_PLLSAICFGR_PLLSAIQ_4 BIT(26) #define RCC_PLLSAICFGR_PLLSAIR_2 BIT(29)
+#define RCC_DCKCFGRX_TIMPRE BIT(24) #define RCC_DCKCFGRX_CK48MSEL BIT(27) #define RCC_DCKCFGRX_SDMMC1SEL BIT(28) #define RCC_DCKCFGR2_SDMMC2SEL BIT(29) @@ -260,21 +261,88 @@ static unsigned long stm32_clk_pll48clk_rate(struct stm32_clk *priv, return sysclk / pllq; }
-static unsigned long stm32_clk_get_rate(struct clk *clk) +static bool stm32_get_timpre(struct stm32_clk *priv) { - struct stm32_clk *priv = dev_get_priv(clk->dev); struct stm32_rcc_regs *regs = priv->base; - u32 sysclk = 0; - u32 shift = 0; - u16 pllm, plln, pllp; + u32 val; + + if (priv->info.v2) /*stm32f7 case */ + val = readl(®s->dckcfgr2); + else + val = readl(®s->dckcfgr); + /* get timer prescaler */ + return !!(val & RCC_DCKCFGRX_TIMPRE); +} + +static u32 stm32_get_hclk_rate(struct stm32_rcc_regs *regs, u32 sysclk) +{ + u8 shift; /* Prescaler table lookups for clock computation */ u8 ahb_psc_table[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9 }; + + shift = ahb_psc_table[( + (readl(®s->cfgr) & RCC_CFGR_AHB_PSC_MASK) + >> RCC_CFGR_HPRE_SHIFT)]; + + return sysclk >> shift; +}; + +static u8 stm32_get_apb_shift(struct stm32_rcc_regs *regs, enum apb apb) +{ + /* Prescaler table lookups for clock computation */ u8 apb_psc_table[8] = { 0, 0, 0, 0, 1, 2, 3, 4 };
+ if (apb == APB1) + return apb_psc_table[( + (readl(®s->cfgr) & RCC_CFGR_APB1_PSC_MASK) + >> RCC_CFGR_PPRE1_SHIFT)]; + else /* APB2 */ + return apb_psc_table[( + (readl(®s->cfgr) & RCC_CFGR_APB2_PSC_MASK) + >> RCC_CFGR_PPRE2_SHIFT)]; +}; + +static u32 stm32_get_timer_rate(struct stm32_clk *priv, u32 sysclk, + enum apb apb) +{ + struct stm32_rcc_regs *regs = priv->base; + u8 shift = stm32_get_apb_shift(regs, apb); + + if (stm32_get_timpre(priv)) + /* + * if APB prescaler is configured to a + * division factor of 1, 2 or 4 + */ + switch (shift) { + case 0: + case 1: + case 2: + return stm32_get_hclk_rate(regs, sysclk); + default: + return (sysclk >> shift) * 4; + } + else + /* + * if APB prescaler is configured to a + * division factor of 1 + */ + if (shift == 0) + return sysclk; + else + return (sysclk >> shift) * 2; +}; + +static ulong stm32_clk_get_rate(struct clk *clk) +{ + struct stm32_clk *priv = dev_get_priv(clk->dev); + struct stm32_rcc_regs *regs = priv->base; + u32 sysclk = 0; + u16 pllm, plln, pllp; + if ((readl(®s->cfgr) & RCC_CFGR_SWS_MASK) == RCC_CFGR_SWS_PLL) { pllm = (readl(®s->pllcfgr) & RCC_PLLCFGR_PLLM_MASK); @@ -293,16 +361,24 @@ static unsigned long stm32_clk_get_rate(struct clk *clk) * AHB1, AHB2 and AHB3 */ case STM32F7_AHB1_CLOCK(GPIOA) ... STM32F7_AHB3_CLOCK(QSPI): - shift = ahb_psc_table[( - (readl(®s->cfgr) & RCC_CFGR_AHB_PSC_MASK) - >> RCC_CFGR_HPRE_SHIFT)]; - return sysclk >>= shift; + return stm32_get_hclk_rate(regs, sysclk); /* APB1 CLOCK */ case STM32F7_APB1_CLOCK(TIM2) ... STM32F7_APB1_CLOCK(UART8): - shift = apb_psc_table[( - (readl(®s->cfgr) & RCC_CFGR_APB1_PSC_MASK) - >> RCC_CFGR_PPRE1_SHIFT)]; - return sysclk >>= shift; + /* For timer clock, an additionnal prescaler is used*/ + switch (clk->id) { + case STM32F7_APB1_CLOCK(TIM2): + case STM32F7_APB1_CLOCK(TIM3): + case STM32F7_APB1_CLOCK(TIM4): + case STM32F7_APB1_CLOCK(TIM5): + case STM32F7_APB1_CLOCK(TIM6): + case STM32F7_APB1_CLOCK(TIM7): + case STM32F7_APB1_CLOCK(TIM12): + case STM32F7_APB1_CLOCK(TIM13): + case STM32F7_APB1_CLOCK(TIM14): + return stm32_get_timer_rate(priv, sysclk, APB1); + } + return (sysclk >> stm32_get_apb_shift(regs, APB1)); + /* APB2 CLOCK */ case STM32F7_APB2_CLOCK(TIM1) ... STM32F7_APB2_CLOCK(LTDC): /* @@ -325,12 +401,18 @@ static unsigned long stm32_clk_get_rate(struct clk *clk) else return stm32_clk_pll48clk_rate(priv, sysclk); break; + + /* For timer clock, an additionnal prescaler is used*/ + case STM32F7_APB2_CLOCK(TIM1): + case STM32F7_APB2_CLOCK(TIM8): + case STM32F7_APB2_CLOCK(TIM9): + case STM32F7_APB2_CLOCK(TIM10): + case STM32F7_APB2_CLOCK(TIM11): + return stm32_get_timer_rate(priv, sysclk, APB2); + break; } + return (sysclk >> stm32_get_apb_shift(regs, APB2));
- shift = apb_psc_table[( - (readl(®s->cfgr) & RCC_CFGR_APB2_PSC_MASK) - >> RCC_CFGR_PPRE2_SHIFT)]; - return sysclk >>= shift; default: pr_err("clock index %ld out of range\n", clk->id); return -EINVAL; diff --git a/include/stm32_rcc.h b/include/stm32_rcc.h index 063177bc9877..484bc305f9c0 100644 --- a/include/stm32_rcc.h +++ b/include/stm32_rcc.h @@ -45,6 +45,11 @@ enum soc_family { STM32F7, };
+enum apb { + APB1, + APB2, +}; + struct stm32_rcc_clk { char *drv_name; enum soc_family soc;

On Wed, Feb 07, 2018 at 10:44:46AM +0100, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
For timer clock, an additionnal prescaler is used which was not taken into account previously.
Signed-off-by: Patrice Chotard patrice.chotard@st.com
Applied to u-boot/master, thanks!

From: Patrice Chotard patrice.chotard@st.com
For timer clock, an additional prescaler is used which was not taken into account previously.
Signed-off-by: Patrice Chotard patrice.chotard@st.com --- drivers/clk/clk_stm32h7.c | 102 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 90 insertions(+), 12 deletions(-)
diff --git a/drivers/clk/clk_stm32h7.c b/drivers/clk/clk_stm32h7.c index c9594d405a0c..92db71431e45 100644 --- a/drivers/clk/clk_stm32h7.c +++ b/drivers/clk/clk_stm32h7.c @@ -35,6 +35,7 @@ DECLARE_GLOBAL_DATA_PTR; #define RCC_CFGR_SW_CSI 1 #define RCC_CFGR_SW_HSE 2 #define RCC_CFGR_SW_PLL1 3 +#define RCC_CFGR_TIMPRE BIT(15)
#define RCC_PLLCKSELR_PLLSRC_HSI 0 #define RCC_PLLCKSELR_PLLSRC_CSI 1 @@ -339,6 +340,11 @@ struct pll_psc sys_pll_psc = { .divr = 2, };
+enum apb { + APB1, + APB2, +}; + int configure_clocks(struct udevice *dev) { struct stm32_clk *priv = dev_get_priv(dev); @@ -562,6 +568,67 @@ static u32 stm32_get_PLL1_rate(struct stm32_rcc_regs *regs, return -EINVAL; }
+static u32 stm32_get_apb_psc(struct stm32_rcc_regs *regs, enum apb apb) +{ + u16 prescaler_table[8] = {2, 4, 8, 16, 64, 128, 256, 512}; + u32 d2cfgr = readl(®s->d2cfgr); + + if (apb == APB1) { + if (d2cfgr & RCC_D2CFGR_D2PPRE1_DIVIDED) + /* get D2 domain APB1 prescaler */ + return prescaler_table[ + ((d2cfgr & RCC_D2CFGR_D2PPRE1_DIVIDER) + >> RCC_D2CFGR_D2PPRE1_SHIFT)]; + } else { /* APB2 */ + if (d2cfgr & RCC_D2CFGR_D2PPRE2_DIVIDED) + /* get D2 domain APB2 prescaler */ + return prescaler_table[ + ((d2cfgr & RCC_D2CFGR_D2PPRE2_DIVIDER) + >> RCC_D2CFGR_D2PPRE2_SHIFT)]; + } + + return 1; +}; + +static u32 stm32_get_timer_rate(struct stm32_clk *priv, u32 sysclk, + enum apb apb) +{ + struct stm32_rcc_regs *regs = priv->rcc_base; +u32 psc = stm32_get_apb_psc(regs, apb); + + if (readl(®s->cfgr) & RCC_CFGR_TIMPRE) + /* + * if APB prescaler is configured to a + * division factor of 1, 2 or 4 + */ + switch (psc) { + case 1: + case 2: + case 4: + return sysclk; + case 8: + return sysclk / 2; + case 16: + return sysclk / 4; + default: + pr_err("unexpected prescaler value (%d)\n", psc); + return 0; + } + else + switch (psc) { + case 1: + return sysclk; + case 2: + case 4: + case 8: + case 16: + return sysclk / psc; + default: + pr_err("unexpected prescaler value (%d)\n", psc); + return 0; + } +}; + static ulong stm32_clk_get_rate(struct clk *clk) { struct stm32_clk *priv = dev_get_priv(clk->dev); @@ -660,31 +727,42 @@ static ulong stm32_clk_get_rate(struct clk *clk)
case RCC_APB1LENR: case RCC_APB1HENR: - if (d1cfgr & RCC_D2CFGR_D2PPRE1_DIVIDED) { - /* get D2 domain APB1 prescaler */ - idx = (d1cfgr & RCC_D2CFGR_D2PPRE1_DIVIDER) >> - RCC_D2CFGR_D2PPRE1_SHIFT; - sysclk = sysclk / prescaler_table[idx]; + /* special case for GPT timers */ + switch (clk->id) { + case TIM14_CK: + case TIM13_CK: + case TIM12_CK: + case TIM7_CK: + case TIM6_CK: + case TIM5_CK: + case TIM4_CK: + case TIM3_CK: + case TIM2_CK: + return stm32_get_timer_rate(priv, sysclk, APB1); }
debug("%s system clock: freq after APB1 prescaler = %ld\n", __func__, sysclk);
- return sysclk; + return (sysclk / stm32_get_apb_psc(regs, APB1)); break;
case RCC_APB2ENR: - if (d1cfgr & RCC_D2CFGR_D2PPRE2_DIVIDED) { - /* get D2 domain APB1 prescaler */ - idx = (d1cfgr & RCC_D2CFGR_D2PPRE2_DIVIDER) >> - RCC_D2CFGR_D2PPRE2_SHIFT; - sysclk = sysclk / prescaler_table[idx]; + /* special case for timers */ + switch (clk->id) { + case TIM17_CK: + case TIM16_CK: + case TIM15_CK: + case TIM8_CK: + case TIM1_CK: + return stm32_get_timer_rate(priv, sysclk, APB2); }
debug("%s system clock: freq after APB2 prescaler = %ld\n", __func__, sysclk);
- return sysclk; + return (sysclk / stm32_get_apb_psc(regs, APB2)); + break;
default:

On Wed, Feb 07, 2018 at 10:44:47AM +0100, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
For timer clock, an additional prescaler is used which was not taken into account previously.
Signed-off-by: Patrice Chotard patrice.chotard@st.com
Applied to u-boot/master, thanks!

From: Patrice Chotard patrice.chotard@st.com
d1cfgr register was used to calculate the domain 3 prescaler value instead of d3cfgr.
Signed-off-by: Patrice Chotard patrice.chotard@st.com --- drivers/clk/clk_stm32h7.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/clk_stm32h7.c b/drivers/clk/clk_stm32h7.c index 92db71431e45..9ee2e2e999a2 100644 --- a/drivers/clk/clk_stm32h7.c +++ b/drivers/clk/clk_stm32h7.c @@ -635,7 +635,7 @@ static ulong stm32_clk_get_rate(struct clk *clk) struct stm32_rcc_regs *regs = priv->rcc_base; ulong sysclk = 0; u32 gate_offset; - u32 d1cfgr; + u32 d1cfgr, d3cfgr; /* prescaler table lookups for clock computation */ u16 prescaler_table[8] = {2, 4, 8, 16, 64, 128, 256, 512}; u8 source, idx; @@ -712,9 +712,10 @@ static ulong stm32_clk_get_rate(struct clk *clk) break;
case RCC_APB4ENR: - if (d1cfgr & RCC_D3CFGR_D3PPRE_DIVIDED) { + d3cfgr = readl(®s->d3cfgr); + if (d3cfgr & RCC_D3CFGR_D3PPRE_DIVIDED) { /* get D3 domain APB4 prescaler */ - idx = (d1cfgr & RCC_D3CFGR_D3PPRE_DIVIDER) >> + idx = (d3cfgr & RCC_D3CFGR_D3PPRE_DIVIDER) >> RCC_D3CFGR_D3PPRE_SHIFT; sysclk = sysclk / prescaler_table[idx]; }

On Wed, Feb 07, 2018 at 10:44:48AM +0100, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
d1cfgr register was used to calculate the domain 3 prescaler value instead of d3cfgr.
Signed-off-by: Patrice Chotard patrice.chotard@st.com
Applied to u-boot/master, thanks!

From: Patrice Chotard patrice.chotard@st.com
Add missing timer node to enable timer5 for STM32F7 SoCs family
Signed-off-by: Patrice Chotard patrice.chotard@st.com --- arch/arm/dts/stm32f7-u-boot.dtsi | 8 ++++++++ arch/arm/dts/stm32f746.dtsi | 7 +++++++ 2 files changed, 15 insertions(+)
diff --git a/arch/arm/dts/stm32f7-u-boot.dtsi b/arch/arm/dts/stm32f7-u-boot.dtsi index 9a9e4e5f3718..4a677192a2dd 100644 --- a/arch/arm/dts/stm32f7-u-boot.dtsi +++ b/arch/arm/dts/stm32f7-u-boot.dtsi @@ -1,3 +1,11 @@ +/{ + soc { + timer5: timer@40000c00 { + u-boot,dm-pre-reloc; + }; + }; +}; + &pinctrl { usart1_pins_a: usart1@0 { u-boot,dm-pre-reloc; diff --git a/arch/arm/dts/stm32f746.dtsi b/arch/arm/dts/stm32f746.dtsi index 46d148eab2c8..8c6fa133e0ab 100644 --- a/arch/arm/dts/stm32f746.dtsi +++ b/arch/arm/dts/stm32f746.dtsi @@ -323,6 +323,13 @@ pinctrl-names = "default", "opendrain"; max-frequency = <48000000>; }; + + timer5: timer@40000c00 { + compatible = "st,stm32-timer"; + reg = <0x40000c00 0x400>; + interrupts = <50>; + clocks = <&rcc 0 STM32F7_APB1_CLOCK(TIM5)>; + }; }; };

On Wed, Feb 07, 2018 at 10:44:49AM +0100, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Add missing timer node to enable timer5 for STM32F7 SoCs family
Signed-off-by: Patrice Chotard patrice.chotard@st.com
Applied to u-boot/master, thanks!

From: Patrice Chotard patrice.chotard@st.com
Use available DM stm32_timer driver instead of dedicated mach-stm32/stm32fx/timer.c.
Remove all defines or files previously used for timer usage in arch/arm/include/asm/arch-stm32fx and in arch/arm/mach-stm32/stm32fx
Enable DM STM32_TIMER for STM32F4/F7 and H7.
Signed-off-by: Patrice Chotard patrice.chotard@st.com --- arch/arm/include/asm/arch-stm32f4/stm32.h | 3 - arch/arm/include/asm/arch-stm32f4/stm32_defs.h | 15 --- arch/arm/include/asm/arch-stm32f7/gpt.h | 53 ----------- arch/arm/include/asm/arch-stm32f7/stm32.h | 5 - arch/arm/include/asm/arch-stm32f7/stm32_defs.h | 15 --- arch/arm/include/asm/arch-stm32f7/stm32_periph.h | 4 - arch/arm/mach-stm32/Kconfig | 7 ++ arch/arm/mach-stm32/Makefile | 2 - arch/arm/mach-stm32/stm32f4/Makefile | 11 --- arch/arm/mach-stm32/stm32f4/timer.c | 115 ----------------------- arch/arm/mach-stm32/stm32f7/Makefile | 8 -- arch/arm/mach-stm32/stm32f7/timer.c | 113 ---------------------- board/st/stm32f746-disco/stm32f746-disco.c | 1 - drivers/clk/clk_stm32f.c | 15 --- drivers/spi/stm32_qspi.c | 1 - include/configs/stm32h743-disco.h | 3 +- include/configs/stm32h743-eval.h | 3 +- 17 files changed, 9 insertions(+), 365 deletions(-) delete mode 100644 arch/arm/include/asm/arch-stm32f4/stm32_defs.h delete mode 100644 arch/arm/include/asm/arch-stm32f7/gpt.h delete mode 100644 arch/arm/include/asm/arch-stm32f7/stm32_defs.h delete mode 100644 arch/arm/mach-stm32/stm32f4/Makefile delete mode 100644 arch/arm/mach-stm32/stm32f4/timer.c delete mode 100644 arch/arm/mach-stm32/stm32f7/Makefile delete mode 100644 arch/arm/mach-stm32/stm32f7/timer.c
diff --git a/arch/arm/include/asm/arch-stm32f4/stm32.h b/arch/arm/include/asm/arch-stm32f4/stm32.h index 0449fcecede0..763b18cb5412 100644 --- a/arch/arm/include/asm/arch-stm32f4/stm32.h +++ b/arch/arm/include/asm/arch-stm32f4/stm32.h @@ -38,9 +38,6 @@ struct stm32_u_id_regs { #define STM32_U_ID_BASE (STM32_SYSMEM_BASE + 0x7A10) #define STM32_U_ID ((struct stm32_u_id_regs *)STM32_U_ID_BASE)
-#define STM32_RCC_BASE (STM32_AHB1PERIPH_BASE + 0x3800) -#define STM32_RCC ((struct stm32_rcc_regs *)STM32_RCC_BASE) - #define FLASH_CNTL_BASE (STM32_AHB1PERIPH_BASE + 0x3C00)
static const u32 sect_sz_kb[CONFIG_SYS_MAX_FLASH_SECT] = { diff --git a/arch/arm/include/asm/arch-stm32f4/stm32_defs.h b/arch/arm/include/asm/arch-stm32f4/stm32_defs.h deleted file mode 100644 index 9a967ac38a1f..000000000000 --- a/arch/arm/include/asm/arch-stm32f4/stm32_defs.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (C) 2016, STMicroelectronics - All Rights Reserved - * Author(s): Vikas Manocha, vikas.manocha@st.com for STMicroelectronics. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __STM32_DEFS_H__ -#define __STM32_DEFS_H__ -#include <asm/arch/stm32_periph.h> - -int clock_setup(enum periph_clock); - -#endif - diff --git a/arch/arm/include/asm/arch-stm32f7/gpt.h b/arch/arm/include/asm/arch-stm32f7/gpt.h deleted file mode 100644 index b43dc612c847..000000000000 --- a/arch/arm/include/asm/arch-stm32f7/gpt.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2016, STMicroelectronics - All Rights Reserved - * Author(s): Vikas Manocha, vikas.manocha@st.com for STMicroelectronics. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef _STM32_GPT_H -#define _STM32_GPT_H - -#include <asm/arch/stm32.h> - -struct gpt_regs { - u32 cr1; - u32 cr2; - u32 smcr; - u32 dier; - u32 sr; - u32 egr; - u32 ccmr1; - u32 ccmr2; - u32 ccer; - u32 cnt; - u32 psc; - u32 arr; - u32 reserved; - u32 ccr1; - u32 ccr2; - u32 ccr3; - u32 ccr4; - u32 reserved1; - u32 dcr; - u32 dmar; - u32 tim2_5_or; -}; - -struct gpt_regs *const gpt1_regs_ptr = - (struct gpt_regs *)TIM2_BASE; - -/* Timer control1 register */ -#define GPT_CR1_CEN BIT(0) -#define GPT_MODE_AUTO_RELOAD BIT(7) - -/* Auto reload register for free running config */ -#define GPT_FREE_RUNNING 0xFFFFFFFF - -/* Timer, HZ specific defines */ -#define CONFIG_STM32_HZ 1000 - -/* Timer Event Generation registers */ -#define TIM_EGR_UG BIT(0) - -#endif diff --git a/arch/arm/include/asm/arch-stm32f7/stm32.h b/arch/arm/include/asm/arch-stm32f7/stm32.h index f54e6f195575..40df89142608 100644 --- a/arch/arm/include/asm/arch-stm32f7/stm32.h +++ b/arch/arm/include/asm/arch-stm32f7/stm32.h @@ -25,7 +25,6 @@ #define AHB2_PERIPH_BASE (PERIPH_BASE + 0x10000000) #define AHB3_PERIPH_BASE (PERIPH_BASE + 0x20000000)
-#define TIM2_BASE (APB1_PERIPH_BASE + 0x0000) #define USART2_BASE (APB1_PERIPH_BASE + 0x4400) #define USART3_BASE (APB1_PERIPH_BASE + 0x4800) #define PWR_BASE (APB1_PERIPH_BASE + 0x7000) @@ -45,7 +44,6 @@ #define STM32_GPIOI_BASE (AHB1_PERIPH_BASE + 0x2000) #define STM32_GPIOJ_BASE (AHB1_PERIPH_BASE + 0x2400) #define STM32_GPIOK_BASE (AHB1_PERIPH_BASE + 0x2800) -#define RCC_BASE (AHB1_PERIPH_BASE + 0x3800) #define FLASH_CNTL_BASE (AHB1_PERIPH_BASE + 0x3C00)
@@ -59,9 +57,6 @@ static const u32 sect_sz_kb[CONFIG_SYS_MAX_FLASH_SECT] = {
#define STM32_BUS_MASK GENMASK(31, 16)
-#define STM32_RCC ((struct stm32_rcc_regs *)RCC_BASE) - - void stm32_flash_latency_cfg(int latency);
#endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/include/asm/arch-stm32f7/stm32_defs.h b/arch/arm/include/asm/arch-stm32f7/stm32_defs.h deleted file mode 100644 index 9a967ac38a1f..000000000000 --- a/arch/arm/include/asm/arch-stm32f7/stm32_defs.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (C) 2016, STMicroelectronics - All Rights Reserved - * Author(s): Vikas Manocha, vikas.manocha@st.com for STMicroelectronics. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __STM32_DEFS_H__ -#define __STM32_DEFS_H__ -#include <asm/arch/stm32_periph.h> - -int clock_setup(enum periph_clock); - -#endif - diff --git a/arch/arm/include/asm/arch-stm32f7/stm32_periph.h b/arch/arm/include/asm/arch-stm32f7/stm32_periph.h index 7b8f66a0346b..38d4ade13d2f 100644 --- a/arch/arm/include/asm/arch-stm32f7/stm32_periph.h +++ b/arch/arm/include/asm/arch-stm32f7/stm32_periph.h @@ -20,8 +20,4 @@ enum periph_id { PERIPH_ID_QUADSPI = 92, };
-enum periph_clock { - TIMER2_CLOCK_CFG, -}; - #endif /* __ASM_ARM_ARCH_PERIPH_H */ diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig index f79b1a2c700e..13532843fbc8 100644 --- a/arch/arm/mach-stm32/Kconfig +++ b/arch/arm/mach-stm32/Kconfig @@ -13,6 +13,8 @@ config STM32F4 select STM32_RCC select STM32_RESET select STM32_SERIAL + select STM32_TIMER + select TIMER
config STM32F7 bool "stm32f7 family" @@ -27,6 +29,8 @@ config STM32F7 select STM32_RCC select STM32_RESET select STM32_SERIAL + select STM32_TIMER + select TIMER select SUPPORT_SPL select SPL select SPL_BOARD_INIT @@ -46,6 +50,7 @@ config STM32F7 select SPL_RAM select SPL_SERIAL_SUPPORT select SPL_SYS_MALLOC_SIMPLE + select SPL_TIMER select SPL_XIP_SUPPORT
config STM32H7 @@ -62,7 +67,9 @@ config STM32H7 select STM32_RCC select STM32_RESET select STM32_SERIAL + select STM32_TIMER select SYSCON + select TIMER
source "arch/arm/mach-stm32/stm32f4/Kconfig" source "arch/arm/mach-stm32/stm32f7/Kconfig" diff --git a/arch/arm/mach-stm32/Makefile b/arch/arm/mach-stm32/Makefile index c2806af69b04..d0f2a96b9fff 100644 --- a/arch/arm/mach-stm32/Makefile +++ b/arch/arm/mach-stm32/Makefile @@ -5,5 +5,3 @@ # SPDX-License-Identifier: GPL-2.0+ # obj-y += soc.o -obj-$(CONFIG_STM32F4) += stm32f4/ -obj-$(CONFIG_STM32F7) += stm32f7/ diff --git a/arch/arm/mach-stm32/stm32f4/Makefile b/arch/arm/mach-stm32/stm32f4/Makefile deleted file mode 100644 index 86c81bbe445b..000000000000 --- a/arch/arm/mach-stm32/stm32f4/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# (C) Copyright 2000-2006 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. -# -# (C) Copyright 2015 -# Kamil Lulko, kamil.lulko@gmail.com -# -# SPDX-License-Identifier: GPL-2.0+ -# - -obj-y += timer.o diff --git a/arch/arm/mach-stm32/stm32f4/timer.c b/arch/arm/mach-stm32/stm32f4/timer.c deleted file mode 100644 index 00b1d4abdac5..000000000000 --- a/arch/arm/mach-stm32/stm32f4/timer.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * (C) Copyright 2015 - * Kamil Lulko, kamil.lulko@gmail.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <stm32_rcc.h> -#include <asm/io.h> -#include <asm/armv7m.h> -#include <asm/arch/stm32.h> - -DECLARE_GLOBAL_DATA_PTR; - -#define STM32_TIM2_BASE (STM32_APB1PERIPH_BASE + 0x0000) - -#define RCC_APB1ENR_TIM2EN (1 << 0) - -struct stm32_tim2_5 { - u32 cr1; - u32 cr2; - u32 smcr; - u32 dier; - u32 sr; - u32 egr; - u32 ccmr1; - u32 ccmr2; - u32 ccer; - u32 cnt; - u32 psc; - u32 arr; - u32 reserved1; - u32 ccr1; - u32 ccr2; - u32 ccr3; - u32 ccr4; - u32 reserved2; - u32 dcr; - u32 dmar; - u32 or; -}; - -#define TIM_CR1_CEN (1 << 0) - -#define TIM_EGR_UG (1 << 0) - -int timer_init(void) -{ - struct stm32_tim2_5 *tim = (struct stm32_tim2_5 *)STM32_TIM2_BASE; - - setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_TIM2EN); - - writel(((CONFIG_SYS_CLK_FREQ / 2) / CONFIG_SYS_HZ_CLOCK) - 1, - &tim->psc); - - writel(0xFFFFFFFF, &tim->arr); - writel(TIM_CR1_CEN, &tim->cr1); - setbits_le32(&tim->egr, TIM_EGR_UG); - - gd->arch.tbl = 0; - gd->arch.tbu = 0; - gd->arch.lastinc = 0; - - return 0; -} - -ulong get_timer(ulong base) -{ - return (get_ticks() / (CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ)) - base; -} - -unsigned long long get_ticks(void) -{ - struct stm32_tim2_5 *tim = (struct stm32_tim2_5 *)STM32_TIM2_BASE; - u32 now; - - now = readl(&tim->cnt); - - if (now >= gd->arch.lastinc) - gd->arch.tbl += (now - gd->arch.lastinc); - else - gd->arch.tbl += (0xFFFFFFFF - gd->arch.lastinc) + now; - - gd->arch.lastinc = now; - - return gd->arch.tbl; -} - -void reset_timer(void) -{ - struct stm32_tim2_5 *tim = (struct stm32_tim2_5 *)STM32_TIM2_BASE; - - gd->arch.lastinc = readl(&tim->cnt); - gd->arch.tbl = 0; -} - -/* delay x useconds */ -void __udelay(ulong usec) -{ - unsigned long long start; - - start = get_ticks(); /* get current timestamp */ - while ((get_ticks() - start) < usec) - ; /* loop till time has passed */ -} - -/* - * This function is derived from PowerPC code (timebase clock frequency). - * On ARM it returns the number of timer ticks per second. - */ -ulong get_tbclk(void) -{ - return CONFIG_SYS_HZ_CLOCK; -} diff --git a/arch/arm/mach-stm32/stm32f7/Makefile b/arch/arm/mach-stm32/stm32f7/Makefile deleted file mode 100644 index 8132c1323403..000000000000 --- a/arch/arm/mach-stm32/stm32f7/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright (C) 2016, STMicroelectronics - All Rights Reserved -# Author(s): Vikas Manocha, vikas.manocha@st.com for STMicroelectronics. -# -# SPDX-License-Identifier: GPL-2.0+ -# - -obj-y += timer.o diff --git a/arch/arm/mach-stm32/stm32f7/timer.c b/arch/arm/mach-stm32/stm32f7/timer.c deleted file mode 100644 index 69d37a7c708c..000000000000 --- a/arch/arm/mach-stm32/stm32f7/timer.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2016, STMicroelectronics - All Rights Reserved - * Author(s): Vikas Manocha, vikas.manocha@st.com for STMicroelectronics. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <stm32_rcc.h> -#include <asm/io.h> -#include <asm/arch/stm32.h> -#include <asm/arch/stm32_defs.h> -#include <asm/arch/gpt.h> - -#define READ_TIMER() (readl(&gpt1_regs_ptr->cnt) & GPT_FREE_RUNNING) -#define GPT_RESOLUTION (CONFIG_SYS_HZ_CLOCK/CONFIG_STM32_HZ) - -DECLARE_GLOBAL_DATA_PTR; - -#define timestamp gd->arch.tbl -#define lastdec gd->arch.lastinc - -int timer_init(void) -{ - /* Timer2 clock configuration */ - clock_setup(TIMER2_CLOCK_CFG); - /* Stop the timer */ - writel(readl(&gpt1_regs_ptr->cr1) & ~GPT_CR1_CEN, &gpt1_regs_ptr->cr1); - - writel((CONFIG_SYS_CLK_FREQ / 2 / CONFIG_SYS_HZ_CLOCK) - 1, - &gpt1_regs_ptr->psc); - - /* Configure timer for auto-reload */ - writel(readl(&gpt1_regs_ptr->cr1) | GPT_MODE_AUTO_RELOAD, - &gpt1_regs_ptr->cr1); - - /* load value for free running */ - writel(GPT_FREE_RUNNING, &gpt1_regs_ptr->arr); - - /* start timer */ - writel(readl(&gpt1_regs_ptr->cr1) | GPT_CR1_CEN, &gpt1_regs_ptr->cr1); - - writel(readl(&gpt1_regs_ptr->egr) | TIM_EGR_UG, &gpt1_regs_ptr->egr); - - /* Reset the timer */ - lastdec = READ_TIMER(); - timestamp = 0; - - return 0; -} - -/* - * timer without interrupts - */ -ulong get_timer(ulong base) -{ - return (get_timer_masked() / GPT_RESOLUTION) - base; -} - -void __udelay(unsigned long usec) -{ - ulong tmo; - ulong start = get_timer_masked(); - ulong tenudelcnt = CONFIG_SYS_HZ_CLOCK / (1000 * 100); - ulong rndoff; - - rndoff = (usec % 10) ? 1 : 0; - - /* tenudelcnt timer tick gives 10 microsecconds delay */ - tmo = ((usec / 10) + rndoff) * tenudelcnt; - - while ((ulong) (get_timer_masked() - start) < tmo) - ; -} - -ulong get_timer_masked(void) -{ - ulong now = READ_TIMER(); - - if (now >= lastdec) { - /* normal mode */ - timestamp += now - lastdec; - } else { - /* we have an overflow ... */ - timestamp += now + GPT_FREE_RUNNING - lastdec; - } - lastdec = now; - - return timestamp; -} - -void udelay_masked(unsigned long usec) -{ - return udelay(usec); -} - -/* - * This function is derived from PowerPC code (read timebase as long long). - * On ARM it just returns the timer value. - */ -unsigned long long get_ticks(void) -{ - return get_timer(0); -} - -/* - * This function is derived from PowerPC code (timebase clock frequency). - * On ARM it returns the number of timer ticks per second. - */ -ulong get_tbclk(void) -{ - return CONFIG_STM32_HZ; -} diff --git a/board/st/stm32f746-disco/stm32f746-disco.c b/board/st/stm32f746-disco/stm32f746-disco.c index 8da70281f976..ec39468fb8a2 100644 --- a/board/st/stm32f746-disco/stm32f746-disco.c +++ b/board/st/stm32f746-disco/stm32f746-disco.c @@ -14,7 +14,6 @@ #include <asm/arch/stm32.h> #include <asm/arch/gpio.h> #include <asm/arch/stm32_periph.h> -#include <asm/arch/stm32_defs.h> #include <asm/arch/syscfg.h> #include <asm/gpio.h>
diff --git a/drivers/clk/clk_stm32f.c b/drivers/clk/clk_stm32f.c index bde31607cfe9..f1f02995d9c0 100644 --- a/drivers/clk/clk_stm32f.c +++ b/drivers/clk/clk_stm32f.c @@ -87,10 +87,6 @@ #define RCC_APB2ENR_SYSCFGEN BIT(14) #define RCC_APB2ENR_SAI1EN BIT(22)
-enum periph_clock { - TIMER2_CLOCK_CFG, -}; - static const struct stm32_clk_info stm32f4_clk_info = { /* 180 MHz */ .sys_pll_psc = { @@ -438,17 +434,6 @@ static int stm32_clk_enable(struct clk *clk) return 0; }
-void clock_setup(int peripheral) -{ - switch (peripheral) { - case TIMER2_CLOCK_CFG: - setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_TIM2EN); - break; - default: - break; - } -} - static int stm32_clk_probe(struct udevice *dev) { struct ofnode_phandle_args args; diff --git a/drivers/spi/stm32_qspi.c b/drivers/spi/stm32_qspi.c index ef2b64ec5fbb..558708a4a7b0 100644 --- a/drivers/spi/stm32_qspi.c +++ b/drivers/spi/stm32_qspi.c @@ -16,7 +16,6 @@ #include <dm.h> #include <errno.h> #include <asm/arch/stm32.h> -#include <asm/arch/stm32_defs.h> #include <clk.h>
DECLARE_GLOBAL_DATA_PTR; diff --git a/include/configs/stm32h743-disco.h b/include/configs/stm32h743-disco.h index 1494203e83b2..f81bd05cc915 100644 --- a/include/configs/stm32h743-disco.h +++ b/include/configs/stm32h743-disco.h @@ -25,8 +25,7 @@
#define CONFIG_ENV_SIZE (8 << 10)
-#define CONFIG_SYS_ARCH_TIMER -#define CONFIG_SYS_HZ_CLOCK 250000000 +#define CONFIG_SYS_HZ_CLOCK 1000000
#define CONFIG_CMDLINE_TAG #define CONFIG_SETUP_MEMORY_TAGS diff --git a/include/configs/stm32h743-eval.h b/include/configs/stm32h743-eval.h index 1494203e83b2..f81bd05cc915 100644 --- a/include/configs/stm32h743-eval.h +++ b/include/configs/stm32h743-eval.h @@ -25,8 +25,7 @@
#define CONFIG_ENV_SIZE (8 << 10)
-#define CONFIG_SYS_ARCH_TIMER -#define CONFIG_SYS_HZ_CLOCK 250000000 +#define CONFIG_SYS_HZ_CLOCK 1000000
#define CONFIG_CMDLINE_TAG #define CONFIG_SETUP_MEMORY_TAGS

On Wed, Feb 07, 2018 at 10:44:50AM +0100, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Use available DM stm32_timer driver instead of dedicated mach-stm32/stm32fx/timer.c.
Remove all defines or files previously used for timer usage in arch/arm/include/asm/arch-stm32fx and in arch/arm/mach-stm32/stm32fx
Enable DM STM32_TIMER for STM32F4/F7 and H7.
Signed-off-by: Patrice Chotard patrice.chotard@st.com
Applied to u-boot/master, thanks!
participants (2)
-
patrice.chotard@st.com
-
Tom Rini