diff options
author | Shawn Nematbakhsh <shawnn@chromium.org> | 2017-12-08 14:51:31 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-12-11 12:47:48 -0800 |
commit | 01e43230ca686d5f11517319c4fefb8d125f4987 (patch) | |
tree | 9dcb0878a6bd911f0c39dbc3cfac1b17817853d5 /chip | |
parent | b23fdca572d5078c3722616a37d76963b68e0f33 (diff) | |
download | chrome-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')
-rw-r--r-- | chip/stm32/clock-stm32f0.c | 18 |
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) |