summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2017-02-21 14:43:44 +0100
committerchrome-bot <chrome-bot@chromium.org>2017-02-23 16:02:03 -0800
commitf07d03dcb13dd18b72b2c95170175a82c03d69dc (patch)
treee1bbc57198acbf6b095a6623f62b85cf28157da5
parent0d858f1544cfd50f4a63f348d722bb16d638c0b1 (diff)
downloadchrome-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.h11
-rw-r--r--chip/stm32/clock-stm32l4.c3
-rw-r--r--chip/stm32/hwtimer32.c38
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;