summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/stm32/clock-stm32f0.c26
-rw-r--r--chip/stm32/clock-stm32f4.c4
-rw-r--r--chip/stm32/registers.h16
-rw-r--r--chip/stm32/system.c32
-rw-r--r--include/config.h3
5 files changed, 55 insertions, 26 deletions
diff --git a/chip/stm32/clock-stm32f0.c b/chip/stm32/clock-stm32f0.c
index b7eb68ca07..fe1ccd4aa4 100644
--- a/chip/stm32/clock-stm32f0.c
+++ b/chip/stm32/clock-stm32f0.c
@@ -59,26 +59,27 @@ static int dsleep_recovery_margin_us = 1000000;
#endif /* CONFIG_LOW_POWER_IDLE */
/*
- * RTC clock frequency (connected to LSI clock)
+ * RTC clock frequency (By default connected to LSI clock)
*
- * TODO(crosbug.com/p/12281): Calibrate LSI frequency on a per-chip basis. The
- * LSI on any given chip can be between 30 kHz to 60 kHz. Without calibration,
- * LSI frequency may be off by as much as 50%. Fortunately, we don't do any
- * high-precision delays based solely on LSI.
- */
-/*
- * Set synchronous clock freq to LSI/2 (20kHz) to maximize subsecond
- * resolution. Set asynchronous clock to 1 Hz.
+ * The LSI on any given chip can be between 30 kHz to 60 kHz.
+ * Without calibration, LSI frequency may be off by as much as 50%.
+ *
+ * Set synchronous clock freq to (RTC clock source / 2) to maximize
+ * subsecond resolution. Set asynchronous clock to 1 Hz.
*/
-#define RTC_FREQ (40000 / 2) /* Hz */
+
+#ifdef CONFIG_STM32_CLOCK_LSE
+#define RTC_FREQ (32768 / (RTC_PREDIV_A + 1)) /* Hz */
+#else /* LSI clock, 40kHz-ish */
+#define RTC_FREQ (40000 / (RTC_PREDIV_A + 1)) /* Hz */
+#endif
#define RTC_PREDIV_S (RTC_FREQ - 1)
#define RTC_PREDIV_A 1
#define US_PER_RTC_TICK (1000000 / RTC_FREQ)
-
int32_t rtcss_to_us(uint32_t rtcss)
{
- return ((RTC_PREDIV_S - rtcss) * US_PER_RTC_TICK);
+ return ((RTC_PREDIV_S - (rtcss & 0x7fff)) * US_PER_RTC_TICK);
}
uint32_t us_to_rtcss(int32_t us)
@@ -86,7 +87,6 @@ uint32_t us_to_rtcss(int32_t us)
return (RTC_PREDIV_S - (us / US_PER_RTC_TICK));
}
-
void config_hispeed_clock(void)
{
#ifdef CHIP_FAMILY_STM32F3
diff --git a/chip/stm32/clock-stm32f4.c b/chip/stm32/clock-stm32f4.c
index eacb3d59e0..ed4ffe6848 100644
--- a/chip/stm32/clock-stm32f4.c
+++ b/chip/stm32/clock-stm32f4.c
@@ -166,13 +166,13 @@ void config_hispeed_clock(void)
/* Setup RTC Clock input */
STM32_RCC_BDCR |= STM32_RCC_BDCR_BDRST;
#ifdef CONFIG_STM32_CLOCK_HSE_HZ
- STM32_RCC_BDCR = STM32_RCC_BDCR_RTCEN | BCDR_RTCSEL(BDCR_SRC_HSE);
+ STM32_RCC_BDCR = STM32_RCC_BDCR_RTCEN | BDCR_RTCSEL(BDCR_SRC_HSE);
#else
/* Ensure that LSI is ON */
wait_for_ready(&(STM32_RCC_CSR),
STM32_RCC_CSR_LSION, STM32_RCC_CSR_LSIRDY);
- STM32_RCC_BDCR = STM32_RCC_BDCR_RTCEN | BCDR_RTCSEL(BDCR_SRC_LSI);
+ STM32_RCC_BDCR = STM32_RCC_BDCR_RTCEN | BDCR_RTCSEL(BDCR_SRC_LSI);
#endif
}
diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h
index bfe5b7321c..491718f631 100644
--- a/chip/stm32/registers.h
+++ b/chip/stm32/registers.h
@@ -1109,11 +1109,6 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define STM32_RCC_APB2LPENR REG32(STM32_RCC_BASE + 0x64)
#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x70)
-#define STM32_RCC_BDCR_BDRST (1 << 16)
-#define STM32_RCC_BDCR_RTCEN (1 << 15)
-#define BCDR_RTCSEL(source) (((source) & 0x3) << 8)
-#define BDCR_SRC_HSE 0x3
-#define BDCR_SRC_LSI 0x2
#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x74)
#define STM32_RCC_CSR_LSION (1 << 0)
#define STM32_RCC_CSR_LSIRDY (1 << 1)
@@ -1141,6 +1136,17 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#error Unsupported chip variant
#endif
+/* RTC domain control register */
+#define STM32_RCC_BDCR_BDRST (1 << 16)
+#define STM32_RCC_BDCR_RTCEN (1 << 15)
+#define STM32_RCC_BDCR_LSERDY (1 << 1)
+#define STM32_RCC_BDCR_LSEON (1 << 0)
+#define BDCR_RTCSEL_MASK ((0x3) << 8)
+#define BDCR_RTCSEL(source) (((source) << 8) & BDCR_RTCSEL_MASK)
+#define BDCR_SRC_LSE 0x1
+#define BDCR_SRC_LSI 0x2
+#define BDCR_SRC_HSE 0x3
+
/* Peripheral bits for RCC_APB/AHB and DBGMCU regs */
#define STM32_RCC_PB1_TIM2 (1 << 0)
#define STM32_RCC_PB1_TIM3 (1 << 1)
diff --git a/chip/stm32/system.c b/chip/stm32/system.c
index d0c69101ef..884a5d9ed2 100644
--- a/chip/stm32/system.c
+++ b/chip/stm32/system.c
@@ -18,6 +18,18 @@
#include "version.h"
#include "watchdog.h"
+#ifdef CONFIG_STM32_CLOCK_LSE
+#define BDCR_SRC BDCR_SRC_LSE
+#define BDCR_RDY STM32_RCC_BDCR_LSERDY
+#else
+#define BDCR_SRC BDCR_SRC_LSI
+#define BDCR_RDY 0
+#endif
+#define BDCR_ENABLE_VALUE (STM32_RCC_BDCR_RTCEN | BDCR_RTCSEL(BDCR_SRC) | \
+ BDCR_RDY)
+#define BDCR_ENABLE_MASK (BDCR_ENABLE_VALUE | BDCR_RTCSEL_MASK | \
+ STM32_RCC_BDCR_BDRST)
+
enum bkpdata_index {
BKPDATA_INDEX_SCRATCHPAD, /* General-purpose scratchpad */
BKPDATA_INDEX_SAVED_RESET_FLAGS, /* Saved reset flags */
@@ -249,18 +261,26 @@ void system_pre_init(void)
/* re-configure RTC if needed */
#ifdef CHIP_FAMILY_STM32L
if ((STM32_RCC_CSR & 0x00C30000) != 0x00420000) {
- /* the RTC settings are bad, we need to reset it */
+ /* The RTC settings are bad, we need to reset it */
STM32_RCC_CSR |= 0x00800000;
/* Enable RTC and use LSI as clock source */
STM32_RCC_CSR = (STM32_RCC_CSR & ~0x00C30000) | 0x00420000;
}
#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3) || \
defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32F4)
- if ((STM32_RCC_BDCR & 0x00018300) != 0x00008200) {
- /* the RTC settings are bad, we need to reset it */
- STM32_RCC_BDCR |= 0x00010000;
- /* Enable RTC and use LSI as clock source */
- STM32_RCC_BDCR = (STM32_RCC_BDCR & ~0x00018300) | 0x00008200;
+ if ((STM32_RCC_BDCR & BDCR_ENABLE_MASK) != BDCR_ENABLE_VALUE) {
+ /* The RTC settings are bad, we need to reset it */
+ STM32_RCC_BDCR |= STM32_RCC_BDCR_BDRST;
+ STM32_RCC_BDCR = STM32_RCC_BDCR & ~BDCR_ENABLE_MASK;
+#ifdef CONFIG_STM32_CLOCK_LSE
+ /* Turn on LSE */
+ STM32_RCC_BDCR |= STM32_RCC_BDCR_LSEON;
+ /* Wait for LSE to be ready */
+ while (!(STM32_RCC_BDCR & STM32_RCC_BDCR_LSERDY))
+ ;
+#endif
+ /* Select clock source and enable RTC */
+ STM32_RCC_BDCR |= BDCR_RTCSEL(BDCR_SRC) | STM32_RCC_BDCR_RTCEN;
}
#else
#error "Unsupported chip family"
diff --git a/include/config.h b/include/config.h
index 86dacbe74f..f60766d165 100644
--- a/include/config.h
+++ b/include/config.h
@@ -668,6 +668,9 @@
/* Indicate if a clock source is connected to stm32f4's "HSE" specific input */
#undef CONFIG_STM32_CLOCK_HSE_HZ
+/* Indicate if a clock source is connected to "LSE" specific input */
+#undef CONFIG_STM32_CLOCK_LSE
+
/*
* Chip config for clock source
* define = external crystal oscillator / undef = internal clock source