drivers: pwm: stm32: fix timer clock calculation

Calculation of the timer clock was wrong for some F4/F7/H7 series.

Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
This commit is contained in:
Gerard Marull-Paretas 2020-10-16 20:07:27 +02:00 committed by Carles Cufí
commit 6b81695946
2 changed files with 38 additions and 27 deletions

View file

@ -7,6 +7,7 @@ config PWM_STM32
bool "STM32 MCU PWM driver"
depends on SOC_FAMILY_STM32
select USE_STM32_LL_TIM
select USE_STM32_LL_RCC if SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X || SOC_SERIES_STM32H7X
help
This option enables the PWM driver for STM32 family of
processors. Say y if you wish to use PWM port on STM32

View file

@ -125,33 +125,6 @@ static int get_tim_clk(const struct stm32_pclken *pclken, uint32_t *tim_clk)
} else {
apb_psc = CONFIG_CLOCK_STM32_D2PPRE2;
}
/*
* Depending on pre-scaler selection (TIMPRE), timer clock frequency
* is defined as follows:
*
* - TIMPRE=0: If the APB prescaler (PPRE1, PPRE2) is configured to a
* division factor of 1 then the timer clock equals to APB bus clock.
* Otherwise the timer clock is set to twice the frequency of APB bus
* clock.
* - TIMPRE=1: If the APB prescaler (PPRE1, PPRE2) is configured to a
* division factor of 1, 2 or 4, then the timer clock equals to HCLK.
* Otherwise, the timer clock frequencies are set to four times to
* the frequency of the APB domain.
*/
if (LL_RCC_GetTIMPrescaler() == LL_RCC_TIM_PRESCALER_TWICE) {
if (apb_psc == 1u) {
*tim_clk = bus_clk;
} else {
*tim_clk = bus_clk * 2u;
}
} else {
if (apb_psc == 1u || apb_psc == 2u || apb_psc == 4u) {
*tim_clk = SystemCoreClock;
} else {
*tim_clk = bus_clk * 4u;
}
}
#else
if (pclken->bus == STM32_CLOCK_BUS_APB1) {
apb_psc = CONFIG_CLOCK_STM32_APB1_PRESCALER;
@ -161,7 +134,44 @@ static int get_tim_clk(const struct stm32_pclken *pclken, uint32_t *tim_clk)
apb_psc = CONFIG_CLOCK_STM32_APB2_PRESCALER;
}
#endif
#endif
#if defined(RCC_DCKCFGR_TIMPRE) || defined(RCC_DCKCFGR1_TIMPRE) || \
defined(RCC_CFGR_TIMPRE)
/*
* There are certain series (some F4, F7 and H7) that have the TIMPRE
* bit to control the clock frequency of all the timers connected to
* APB1 and APB2 domains.
*
* Up to a certain threshold value of APB{1,2} prescaler, timer clock
* equals to HCLK. This threshold value depends on TIMPRE setting
* (2 if TIMPRE=0, 4 if TIMPRE=1). Above threshold, timer clock is set
* to a multiple of the APB domain clock PCLK{1,2} (2 if TIMPRE=0, 4 if
* TIMPRE=1).
*/
if (LL_RCC_GetTIMPrescaler() == LL_RCC_TIM_PRESCALER_TWICE) {
/* TIMPRE = 0 */
if (apb_psc <= 2u) {
LL_RCC_ClocksTypeDef clocks;
LL_RCC_GetSystemClocksFreq(&clocks);
*tim_clk = clocks.HCLK_Frequency;
} else {
*tim_clk = bus_clk * 2u;
}
} else {
/* TIMPRE = 1 */
if (apb_psc <= 4u) {
LL_RCC_ClocksTypeDef clocks;
LL_RCC_GetSystemClocksFreq(&clocks);
*tim_clk = clocks.HCLK_Frequency;
} else {
*tim_clk = bus_clk * 4u;
}
}
#else
/*
* If the APB prescaler equals 1, the timer clock frequencies
* are set to the same frequency as that of the APB domain.