diff options
author | Vincent Palatin <vpalatin@chromium.org> | 2017-02-21 14:43:44 +0100 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-02-23 16:02:03 -0800 |
commit | f07d03dcb13dd18b72b2c95170175a82c03d69dc (patch) | |
tree | e1bbc57198acbf6b095a6623f62b85cf28157da5 | |
parent | 0d858f1544cfd50f4a63f348d722bb16d638c0b1 (diff) | |
download | chrome-ec-f07d03dcb13dd18b72b2c95170175a82c03d69dc.tar.gz |
stm32: more clocks support for STM32L4 family
Add the option to use the PLL connected the 16Mhz HSI oscillator.
Fix the system timer pre-scaling when changing frequency:
- we need to generate an update event immediately as on a 32-bit timer it
might take a very long time before going an actual update event.
- we need to ensure that the OS timestamp is monotonic and sensible
across the frequency jump.
Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
BRANCH=none
BUG=chrome-os-partner:62893
TEST=manual, on STM32L4 console, do several gettime and compare against
wall time, switch to 80Mhz with 'clock pll', verify again gettime
against wall clock.
Change-Id: Ibddbd46173b7594d16fb07e4b57660a50c636568
Reviewed-on: https://chromium-review.googlesource.com/445776
Commit-Ready: Vincent Palatin <vpalatin@chromium.org>
Tested-by: Vincent Palatin <vpalatin@chromium.org>
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
-rw-r--r-- | board/eve_fp/board.h | 11 | ||||
-rw-r--r-- | chip/stm32/clock-stm32l4.c | 3 | ||||
-rw-r--r-- | chip/stm32/hwtimer32.c | 38 |
3 files changed, 45 insertions, 7 deletions
diff --git a/board/eve_fp/board.h b/board/eve_fp/board.h index 016b83733a..454b4e7f93 100644 --- a/board/eve_fp/board.h +++ b/board/eve_fp/board.h @@ -36,6 +36,17 @@ #define TIM_CLOCK32 2 #define TIM_WATCHDOG 16 +/* + * PLL configuration for 80Mhz: + * SYSCLK = HSE * n/m/r = 16 * 10 / 2 = 80 Mhz + */ +#undef STM32_PLLM +#define STM32_PLLM 1 +#undef STM32_PLLN +#define STM32_PLLN 10 +#undef STM32_PLLR +#define STM32_PLLR 2 + #ifndef __ASSEMBLER__ #include "gpio_signal.h" diff --git a/chip/stm32/clock-stm32l4.c b/chip/stm32/clock-stm32l4.c index 29c548e56e..18a23b8d16 100644 --- a/chip/stm32/clock-stm32l4.c +++ b/chip/stm32/clock-stm32l4.c @@ -372,6 +372,9 @@ static int command_clock(int argc, char **argv) clock_set_osc(OSC_HSE, OSC_INIT); else if (!strcasecmp(argv[1], "pll")) clock_set_osc(OSC_PLL, OSC_HSE); +#else + else if (!strcasecmp(argv[1], "pll")) + clock_set_osc(OSC_PLL, OSC_HSI); #endif else return EC_ERROR_PARAM1; diff --git a/chip/stm32/hwtimer32.c b/chip/stm32/hwtimer32.c index 1b47015bdb..0bd6fa12c9 100644 --- a/chip/stm32/hwtimer32.c +++ b/chip/stm32/hwtimer32.c @@ -126,16 +126,39 @@ void __hw_timer_enable_clock(int n, int enable) *reg &= ~mask; } +#if defined(CHIP_FAMILY_STM32L) || defined(CHIP_FAMILY_STM32L4) +/* for families using a variable clock feeding the timer */ static void update_prescaler(void) { + uint32_t t; /* * Pre-scaler value : * the timer is incrementing every microsecond - * - * This will take effect at the next update event (when the current - * prescaler counter ticks down, or if forced via EGR). */ STM32_TIM_PSC(TIM_CLOCK32) = (clock_get_freq() / SECOND) - 1; + /* + * Forcing reloading the pre-scaler, + * but try to maintain a sensible time-keeping while triggering + * the update event. + */ + interrupt_disable(); + /* Ignore the next update */ + STM32_TIM_DIER(TIM_CLOCK32) &= ~0x0001; + /* + * prepare to reload the counter with the current value + * to avoid rolling backward the microsecond counter. + */ + t = STM32_TIM32_CNT(TIM_CLOCK32) + 1; + /* issue an update event, reloads the pre-scaler and the counter */ + STM32_TIM_EGR(TIM_CLOCK32) = 0x0001; + /* clear the 'spurious' update unless we were going to roll-over */ + if (t) + STM32_TIM_SR(TIM_CLOCK32) = ~1; + /* restore a sensible time value */ + STM32_TIM32_CNT(TIM_CLOCK32) = t; + /* restore roll-over events */ + STM32_TIM_DIER(TIM_CLOCK32) |= 0x0001; + interrupt_enable(); #ifdef CONFIG_WATCHDOG_HELP /* Watchdog timer runs at 1KHz */ @@ -143,6 +166,7 @@ static void update_prescaler(void) #endif /* CONFIG_WATCHDOG_HELP */ } DECLARE_HOOK(HOOK_FREQ_CHANGE, update_prescaler, HOOK_PRIO_DEFAULT); +#endif /* defined(CHIP_FAMILY_STM32L) || defined(CHIP_FAMILY_STM32L4) */ int __hw_clock_source_init(uint32_t start_t) { @@ -163,8 +187,8 @@ int __hw_clock_source_init(uint32_t start_t) /* Auto-reload value : 32-bit free-running counter */ STM32_TIM32_ARR(TIM_CLOCK32) = 0xffffffff; - /* Update prescaler */ - update_prescaler(); + /* Update prescaler to increment every microsecond */ + STM32_TIM_PSC(TIM_CLOCK32) = (clock_get_freq() / SECOND) - 1; /* Reload the pre-scaler */ STM32_TIM_EGR(TIM_CLOCK32) = 0x0001; @@ -233,8 +257,8 @@ void hwtimer_setup_watchdog(void) /* AUto-reload value */ STM32_TIM_ARR(TIM_WATCHDOG) = CONFIG_AUX_TIMER_PERIOD_MS; - /* Update prescaler */ - update_prescaler(); + /* Update prescaler: watchdog timer runs at 1KHz */ + STM32_TIM_PSC(TIM_WATCHDOG) = (clock_get_freq() / SECOND * MSEC) - 1; /* Reload the pre-scaler */ STM32_TIM_EGR(TIM_WATCHDOG) = 0x0001; |