summaryrefslogtreecommitdiff
path: root/chip/stm32/clock-f.c
diff options
context:
space:
mode:
authorNick Sanders <nsanders@chromium.org>2016-07-26 13:17:09 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-08-17 16:19:07 -0700
commit6fcd163da5169bfca36ab8c15cfd9d0624acae19 (patch)
treecc1e3cd999fa3df95547356e8160fd966aa26bc3 /chip/stm32/clock-f.c
parent6fad4f8588242cd6202e1177e145073c6aff6b7a (diff)
downloadchrome-ec-6fcd163da5169bfca36ab8c15cfd9d0624acae19.tar.gz
stm32f446e-eval: add support for stm32f446
This adds basic support for the stm32f446. This consists of: * New DMA model for stm32f4 * New clock domain support. * MCO oscillator gpio export support. * Flash support for irregular blocks. BUG=chromium:608039 TEST=boots w/ correct clock, stm32f0 also boots. BRANCH=None Change-Id: I1c5cf6ddca09009c9dac60da8a3d0c5ceedfcf4d Signed-off-by: Nick Sanders <nsanders@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/363992 Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Diffstat (limited to 'chip/stm32/clock-f.c')
-rw-r--r--chip/stm32/clock-f.c209
1 files changed, 209 insertions, 0 deletions
diff --git a/chip/stm32/clock-f.c b/chip/stm32/clock-f.c
new file mode 100644
index 0000000000..02773dc678
--- /dev/null
+++ b/chip/stm32/clock-f.c
@@ -0,0 +1,209 @@
+/* Copyright 2016 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Clocks and power management settings */
+
+#include "chipset.h"
+#include "clock.h"
+#include "clock-f.h"
+#include "common.h"
+#include "console.h"
+#include "cpu.h"
+#include "hooks.h"
+#include "hwtimer.h"
+#include "registers.h"
+#include "system.h"
+#include "task.h"
+#include "timer.h"
+#include "util.h"
+
+/* Console output macros */
+#define CPUTS(outstr) cputs(CC_CLOCK, outstr)
+#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args)
+
+
+/* Convert between RTC regs in BCD and seconds */
+uint32_t rtc_to_sec(uint32_t rtc)
+{
+ uint32_t sec;
+
+ /* convert the hours field */
+ sec = (((rtc & 0x300000) >> 20) * 10 + ((rtc & 0xf0000) >> 16)) * 3600;
+ /* convert the minutes field */
+ sec += (((rtc & 0x7000) >> 12) * 10 + ((rtc & 0xf00) >> 8)) * 60;
+ /* convert the seconds field */
+ sec += ((rtc & 0x70) >> 4) * 10 + (rtc & 0xf);
+
+ return sec;
+}
+uint32_t sec_to_rtc(uint32_t sec)
+{
+ uint32_t rtc;
+
+ /* convert the hours field */
+ rtc = ((sec / 36000) << 20) | (((sec / 3600) % 10) << 16);
+ /* convert the minutes field */
+ rtc |= (((sec % 3600) / 600) << 12) | (((sec % 600) / 60) << 8);
+ /* convert the seconds field */
+ rtc |= (((sec % 60) / 10) << 4) | (sec % 10);
+
+ return rtc;
+}
+
+/* Return time diff between two rtc readings */
+int32_t get_rtc_diff(uint32_t rtc0, uint32_t rtc0ss,
+ uint32_t rtc1, uint32_t rtc1ss)
+{
+ int32_t diff;
+
+ /* Note: this only looks at the diff mod 10 seconds */
+ diff = ((rtc1 & 0xf) * SECOND +
+ rtcss_to_us(rtc1ss)) -
+ ((rtc0 & 0xf) * SECOND +
+ rtcss_to_us(rtc0ss));
+
+ return (diff < 0) ? (diff + 10*SECOND) : diff;
+}
+
+void rtc_read(uint32_t *rtc, uint32_t *rtcss)
+{
+ /* Read current time synchronously */
+ do {
+ *rtc = STM32_RTC_TR;
+ /*
+ * RTC_SSR must be read twice with identical values because
+ * glitches may occur for reads close to the RTCCLK edge.
+ */
+ do {
+ *rtcss = STM32_RTC_SSR;
+ } while (*rtcss != STM32_RTC_SSR);
+ } while (*rtc != STM32_RTC_TR);
+}
+
+void set_rtc_alarm(uint32_t delay_s, uint32_t delay_us,
+ uint32_t *rtc, uint32_t *rtcss)
+{
+ uint32_t alarm_sec, alarm_us;
+
+ /* Alarm must be within 1 day (86400 seconds) */
+ ASSERT((delay_s + delay_us / SECOND) < 86400);
+
+ rtc_unlock_regs();
+
+ /* Make sure alarm is disabled */
+ STM32_RTC_CR &= ~STM32_RTC_CR_ALRAE;
+ while (!(STM32_RTC_ISR & STM32_RTC_ISR_ALRAWF))
+ ;
+ STM32_RTC_ISR &= ~STM32_RTC_ISR_ALRAF;
+
+ rtc_read(rtc, rtcss);
+
+ /* Calculate alarm time */
+ alarm_sec = rtc_to_sec(*rtc) + delay_s;
+ alarm_us = rtcss_to_us(*rtcss) + delay_us;
+ alarm_sec = alarm_sec + alarm_us / SECOND;
+ alarm_us = alarm_us % 1000000;
+ /*
+ * If seconds is greater than 1 day, subtract by 1 day to deal with
+ * 24-hour rollover.
+ */
+ if (alarm_sec >= 86400)
+ alarm_sec -= 86400;
+
+ /* Set alarm time */
+ STM32_RTC_ALRMAR = sec_to_rtc(alarm_sec);
+ STM32_RTC_ALRMASSR = us_to_rtcss(alarm_us);
+ /* Check for match on hours, minutes, seconds, and subsecond */
+ STM32_RTC_ALRMAR |= 0xc0000000;
+ STM32_RTC_ALRMASSR |= 0x0f000000;
+
+ /* Enable alarm and alarm interrupt */
+ STM32_EXTI_PR = EXTI_RTC_ALR_EVENT;
+ STM32_EXTI_IMR |= EXTI_RTC_ALR_EVENT;
+ STM32_RTC_CR |= STM32_RTC_CR_ALRAE;
+
+ rtc_lock_regs();
+}
+
+void reset_rtc_alarm(uint32_t *rtc, uint32_t *rtcss)
+{
+ rtc_unlock_regs();
+
+ /* Disable alarm */
+ STM32_RTC_CR &= ~STM32_RTC_CR_ALRAE;
+ STM32_RTC_ISR &= ~STM32_RTC_ISR_ALRAF;
+
+ /* Disable RTC alarm interrupt */
+ STM32_EXTI_IMR &= ~EXTI_RTC_ALR_EVENT;
+ STM32_EXTI_PR = EXTI_RTC_ALR_EVENT;
+
+ /* Read current time */
+ rtc_read(rtc, rtcss);
+
+ rtc_lock_regs();
+}
+
+void __rtc_alarm_irq(void)
+{
+ uint32_t rtc, rtcss;
+
+ reset_rtc_alarm(&rtc, &rtcss);
+}
+DECLARE_IRQ(STM32_IRQ_RTC_ALARM, __rtc_alarm_irq, 1);
+
+void clock_init(void)
+{
+ /*
+ * The initial state :
+ * SYSCLK from HSI (=8MHz), no divider on AHB, APB1, APB2
+ * PLL unlocked, RTC enabled on LSE
+ */
+
+ /*
+ * put 1 Wait-State for flash access to ensure proper reads at 48Mhz
+ * and enable prefetch buffer.
+ */
+ /* Enable data and instruction cache. */
+ STM32_FLASH_ACR = STM32_FLASH_ACR_LATENCY | STM32_FLASH_ACR_PRFTEN;
+
+ config_hispeed_clock();
+
+ rtc_init();
+}
+
+/*****************************************************************************/
+/* Console commands */
+
+#ifdef CONFIG_CMD_RTC_ALARM
+static int command_rtc_alarm_test(int argc, char **argv)
+{
+ int s = 1, us = 0;
+ uint32_t rtc, rtcss;
+ char *e;
+
+ ccprintf("Setting RTC alarm\n");
+
+ if (argc > 1) {
+ s = strtoi(argv[1], &e, 10);
+ if (*e)
+ return EC_ERROR_PARAM1;
+
+ }
+ if (argc > 2) {
+ us = strtoi(argv[2], &e, 10);
+ if (*e)
+ return EC_ERROR_PARAM2;
+
+ }
+
+ set_rtc_alarm(s, us, &rtc, &rtcss);
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(rtc_alarm, command_rtc_alarm_test,
+ "[seconds [microseconds]]",
+ "Test alarm",
+ NULL);
+#endif /* CONFIG_CMD_RTC_ALARM */
+