summaryrefslogtreecommitdiff
path: root/chip/stm32/clock-stm32f0.c
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2017-12-08 14:51:31 -0800
committerchrome-bot <chrome-bot@chromium.org>2017-12-11 12:47:48 -0800
commit01e43230ca686d5f11517319c4fefb8d125f4987 (patch)
tree9dcb0878a6bd911f0c39dbc3cfac1b17817853d5 /chip/stm32/clock-stm32f0.c
parentb23fdca572d5078c3722616a37d76963b68e0f33 (diff)
downloadchrome-ec-01e43230ca686d5f11517319c4fefb8d125f4987.tar.gz
stm32f0 / stm32f3: rtc: Fix register <-> time conversion
us_to_rtcss() could return an invalid value when us approached 1 sec due to precision loss in the divisor. Change the calculation order to divide last to eliminate precision loss. BUG=b:68185182 BRANCH=None TEST=On scarlet, Verify hw clock closely matches reality w/ low-power idle. Verify EC doesn't watchdog for 5 hours in S5 / G3 w/ low-power idle. Verify suspend-stress-test still succeeds to wake device on alarm. Change-Id: Id40797dd4291e94a54a09bbbdbc1a7f7a00a01b4 Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/818332 Commit-Ready: Shawn N <shawnn@chromium.org> Tested-by: Brian Norris <briannorris@chromium.org> Tested-by: Shawn N <shawnn@chromium.org> Reviewed-by: Philip Chen <philipchen@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'chip/stm32/clock-stm32f0.c')
-rw-r--r--chip/stm32/clock-stm32f0.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/chip/stm32/clock-stm32f0.c b/chip/stm32/clock-stm32f0.c
index fe1ccd4aa4..2db0244cf9 100644
--- a/chip/stm32/clock-stm32f0.c
+++ b/chip/stm32/clock-stm32f0.c
@@ -68,23 +68,33 @@ static int dsleep_recovery_margin_us = 1000000;
* subsecond resolution. Set asynchronous clock to 1 Hz.
*/
+#define RTC_PREDIV_A 1
#ifdef CONFIG_STM32_CLOCK_LSE
#define RTC_FREQ (32768 / (RTC_PREDIV_A + 1)) /* Hz */
+/* GCD(RTC_FREQ, 1000000) */
+#define RTC_GCD 64
#else /* LSI clock, 40kHz-ish */
#define RTC_FREQ (40000 / (RTC_PREDIV_A + 1)) /* Hz */
+/* GCD(RTC_FREQ, 1000000) */
+#define RTC_GCD 20000
#endif
#define RTC_PREDIV_S (RTC_FREQ - 1)
-#define RTC_PREDIV_A 1
-#define US_PER_RTC_TICK (1000000 / RTC_FREQ)
+
+/*
+ * There are (1000000 / RTC_FREQ) us per RTC tick, take GCD of both terms
+ * for conversion calculations to fit in 32 bits.
+ */
+#define US_GCD (1000000 / RTC_GCD)
+#define RTC_FREQ_GCD (RTC_FREQ / RTC_GCD)
int32_t rtcss_to_us(uint32_t rtcss)
{
- return ((RTC_PREDIV_S - (rtcss & 0x7fff)) * US_PER_RTC_TICK);
+ return ((RTC_PREDIV_S - (rtcss & 0x7fff)) * US_GCD) / RTC_FREQ_GCD;
}
uint32_t us_to_rtcss(int32_t us)
{
- return (RTC_PREDIV_S - (us / US_PER_RTC_TICK));
+ return RTC_PREDIV_S - us * RTC_FREQ_GCD / US_GCD;
}
void config_hispeed_clock(void)