summaryrefslogtreecommitdiff
path: root/chip/stm32/clock-stm32f0.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/stm32/clock-stm32f0.c')
-rw-r--r--chip/stm32/clock-stm32f0.c503
1 files changed, 0 insertions, 503 deletions
diff --git a/chip/stm32/clock-stm32f0.c b/chip/stm32/clock-stm32f0.c
deleted file mode 100644
index 0f63bdd394..0000000000
--- a/chip/stm32/clock-stm32f0.c
+++ /dev/null
@@ -1,503 +0,0 @@
-/* Copyright 2014 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 "uart.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_CLOCK, outstr)
-#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args)
-
-/* use 48Mhz USB-synchronized High-speed oscillator */
-#define HSI48_CLOCK 48000000
-
-/* use PLL at 38.4MHz as system clock. */
-#define PLL_CLOCK 38400000
-
-/* Low power idle statistics */
-#ifdef CONFIG_LOW_POWER_IDLE
-static int idle_sleep_cnt;
-static int idle_dsleep_cnt;
-static uint64_t idle_dsleep_time_us;
-static int dsleep_recovery_margin_us = 1000000;
-
-/*
- * minimum delay to enter stop mode
- *
- * STOP_MODE_LATENCY: max time to wake up from STOP mode with regulator in low
- * power mode is 5 us + PLL locking time is 200us.
- *
- * SET_RTC_MATCH_DELAY: max time to set RTC match alarm. If we set the alarm
- * in the past, it will never wake up and cause a watchdog.
- * For STM32F3, we are using HSE, which requires additional time to start up.
- * Therefore, the latency for STM32F3 is set longer.
- *
- * RESTORE_HOST_ALARM_LATENCY: max latency between the deferred routine is
- * called and the host alarm is actually restored. In practice, the max latency
- * is measured as ~600us. 1000us should be conservative enough to guarantee
- * we won't miss the host alarm.
- */
-#ifdef CHIP_VARIANT_STM32F373
-#define STOP_MODE_LATENCY 500 /* us */
-#elif defined(CHIP_VARIANT_STM32F05X)
-#define STOP_MODE_LATENCY 300 /* us */
-#elif (CPU_CLOCK == PLL_CLOCK)
-#define STOP_MODE_LATENCY 300 /* us */
-#else
-#define STOP_MODE_LATENCY 50 /* us */
-#endif
-#define SET_RTC_MATCH_DELAY 200 /* us */
-
-#ifdef CONFIG_HOSTCMD_RTC
-#define RESTORE_HOST_ALARM_LATENCY 1000 /* us */
-#endif
-
-#endif /* CONFIG_LOW_POWER_IDLE */
-
-/*
- * RTC clock frequency (By default connected to LSI clock)
- *
- * 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_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)
-
-/*
- * 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_GCD) / RTC_FREQ_GCD;
-}
-
-uint32_t us_to_rtcss(int32_t us)
-{
- return RTC_PREDIV_S - us * RTC_FREQ_GCD / US_GCD;
-}
-
-void config_hispeed_clock(void)
-{
-#ifdef CHIP_FAMILY_STM32F3
- /* Ensure that HSE is ON */
- wait_for_ready(&STM32_RCC_CR, BIT(16), BIT(17));
-
- /*
- * HSE = 24MHz, no prescalar, no MCO, with PLL *2 => 48MHz SYSCLK
- * HCLK = SYSCLK, PCLK = HCLK / 2 = 24MHz
- * ADCCLK = PCLK / 6 = 4MHz
- * USB uses SYSCLK = 48MHz
- */
- STM32_RCC_CFGR = 0x0041a400;
-
- /* Enable the PLL */
- STM32_RCC_CR |= 0x01000000;
-
- /* Wait until the PLL is ready */
- while (!(STM32_RCC_CR & 0x02000000))
- ;
-
- /* Switch SYSCLK to PLL */
- STM32_RCC_CFGR |= 0x2;
-
- /* Wait until the PLL is the clock source */
- while ((STM32_RCC_CFGR & 0xc) != 0x8)
- ;
-/* F03X and F05X and F070 don't have HSI48 */
-#elif defined(CHIP_VARIANT_STM32F03X) || \
-defined(CHIP_VARIANT_STM32F05X) || \
-defined(CHIP_VARIANT_STM32F070)
- /* If PLL is the clock source, PLL has already been set up. */
- if ((STM32_RCC_CFGR & 0xc) == 0x8)
- return;
-
- /* Ensure that HSI is ON */
- wait_for_ready(&STM32_RCC_CR, BIT(0), BIT(1));
-
- /*
- * HSI = 8MHz, HSI/2 with PLL *12 = ~48 MHz
- * therefore PCLK = FCLK = SYSCLK = 48MHz
- */
- /* Switch the PLL source to HSI/2 */
- STM32_RCC_CFGR &= ~(0x00018000);
-
- /*
- * Specify HSI/2 clock as input clock to PLL and set PLL (*12).
- */
- STM32_RCC_CFGR |= 0x00280000;
-
- /* Enable the PLL. */
- STM32_RCC_CR |= 0x01000000;
-
- /* Wait until PLL is ready. */
- while (!(STM32_RCC_CR & 0x02000000))
- ;
-
- /* Switch SYSCLK to PLL. */
- STM32_RCC_CFGR |= 0x2;
-
- /* wait until the PLL is the clock source */
- while ((STM32_RCC_CFGR & 0xc) != 0x8)
- ;
-#else
- /* Ensure that HSI48 is ON */
- wait_for_ready(&STM32_RCC_CR2, BIT(16), BIT(17));
-
-#if (CPU_CLOCK == HSI48_CLOCK)
- /*
- * HSI48 = 48MHz, no prescaler, no MCO, no PLL
- * therefore PCLK = FCLK = SYSCLK = 48MHz
- * USB uses HSI48 = 48MHz
- */
-
-#ifdef CONFIG_USB
- /*
- * Configure and enable Clock Recovery System
- *
- * Since we are running from the internal RC HSI48 clock, the CSR
- * is needed to guarantee an accurate 48MHz clock for USB.
- *
- * The default values configure the CRS to use the periodic USB SOF
- * as the SYNC signal for calibrating the HSI48.
- *
- */
-
- /* Enable Clock Recovery System */
- STM32_RCC_APB1ENR |= STM32_RCC_PB1_CRS;
-
- /* Enable automatic trimming */
- STM32_CRS_CR |= STM32_CRS_CR_AUTOTRIMEN;
-
- /* Enable oscillator clock for the frequency error counter */
- STM32_CRS_CR |= STM32_CRS_CR_CEN;
-#endif
-
- /* switch SYSCLK to HSI48 */
- STM32_RCC_CFGR = 0x00000003;
-
- /* wait until the HSI48 is the clock source */
- while ((STM32_RCC_CFGR & 0xc) != 0xc)
- ;
-
-#elif (CPU_CLOCK == PLL_CLOCK)
- /*
- * HSI48 = 48MHz, no prescalar, no MCO, with PLL *4/5 => 38.4MHz SYSCLK
- * therefore PCLK = FCLK = SYSCLK = 38.4MHz
- * USB uses HSI48 = 48MHz
- */
-
- /* If PLL is the clock source, PLL has already been set up. */
- if ((STM32_RCC_CFGR & 0xc) == 0x8)
- return;
-
- /*
- * Specify HSI48 clock as input clock to PLL and set PLL multiplier
- * and divider.
- */
- STM32_RCC_CFGR = 0x00098000;
- STM32_RCC_CFGR2 = 0x4;
-
- /* Enable the PLL. */
- STM32_RCC_CR |= 0x01000000;
-
- /* Wait until PLL is ready. */
- while (!(STM32_RCC_CR & 0x02000000))
- ;
-
- /* Switch SYSCLK to PLL. */
- STM32_RCC_CFGR |= 0x2;
-
- /* wait until the PLL is the clock source */
- while ((STM32_RCC_CFGR & 0xc) != 0x8)
- ;
-
-#else
-#error "CPU_CLOCK must be either 48MHz or 38.4MHz"
-#endif
-#endif
-}
-
-#ifdef CONFIG_HIBERNATE
-void __enter_hibernate(uint32_t seconds, uint32_t microseconds)
-{
- struct rtc_time_reg rtc;
-
- if (seconds || microseconds)
- set_rtc_alarm(seconds, microseconds, &rtc, 0);
-
- /* interrupts off now */
- asm volatile("cpsid i");
-
-#ifdef CONFIG_HIBERNATE_WAKEUP_PINS
- /* enable the wake up pins */
- STM32_PWR_CSR |= CONFIG_HIBERNATE_WAKEUP_PINS;
-#endif
- STM32_PWR_CR |= 0xe;
- CPU_SCB_SYSCTRL |= 0x4;
- /* go to Standby mode */
- asm("wfi");
-
- /* we should never reach that point */
- while (1)
- ;
-}
-#endif
-
-#ifdef CONFIG_HOSTCMD_RTC
-static void restore_host_wake_alarm_deferred(void)
-{
- restore_host_wake_alarm();
-}
-DECLARE_DEFERRED(restore_host_wake_alarm_deferred);
-#endif
-
-#ifdef CONFIG_LOW_POWER_IDLE
-
-void clock_refresh_console_in_use(void)
-{
-}
-
-void __idle(void)
-{
- timestamp_t t0;
- uint32_t rtc_diff;
- int next_delay, margin_us;
- struct rtc_time_reg rtc0, rtc1;
-
- while (1) {
- asm volatile("cpsid i");
-
- t0 = get_time();
- next_delay = __hw_clock_event_get() - t0.le.lo;
-
-#ifdef CONFIG_LOW_POWER_IDLE_LIMITED
- if (idle_is_disabled())
- goto en_int;
-#endif
-
- if (DEEP_SLEEP_ALLOWED &&
-#ifdef CONFIG_HOSTCMD_RTC
- /*
- * Don't go to deep sleep mode if we might miss the
- * wake alarm that the host requested. Note that the
- * host alarm always aligns to second. Considering the
- * worst case, we have to ensure alarm won't go off
- * within RESTORE_HOST_ALARM_LATENCY + 1 second after
- * EC exits deep sleep mode.
- */
- !is_host_wake_alarm_expired(
- (timestamp_t)(next_delay + t0.val + SECOND +
- RESTORE_HOST_ALARM_LATENCY)) &&
-#endif
- (next_delay > (STOP_MODE_LATENCY + SET_RTC_MATCH_DELAY))) {
- /* Deep-sleep in STOP mode */
- idle_dsleep_cnt++;
-
- uart_enable_wakeup(1);
-
- /* Set deep sleep bit */
- CPU_SCB_SYSCTRL |= 0x4;
-
- set_rtc_alarm(0, next_delay - STOP_MODE_LATENCY,
- &rtc0, 0);
- asm("wfi");
-
- CPU_SCB_SYSCTRL &= ~0x4;
-
- uart_enable_wakeup(0);
-
- /*
- * By default only HSI 8MHz is enabled here. Re-enable
- * high-speed clock if in use.
- */
- config_hispeed_clock();
-
- /* Fast forward timer according to RTC counter */
- reset_rtc_alarm(&rtc1);
- rtc_diff = get_rtc_diff(&rtc0, &rtc1);
- t0.val = t0.val + rtc_diff;
- force_time(t0);
-
-#ifdef CONFIG_HOSTCMD_RTC
- hook_call_deferred(
- &restore_host_wake_alarm_deferred_data, 0);
-#endif
- /* Record time spent in deep sleep. */
- idle_dsleep_time_us += rtc_diff;
-
- /* Calculate how close we were to missing deadline */
- margin_us = next_delay - rtc_diff;
- if (margin_us < 0)
- /* Use CPUTS to save stack space */
- CPUTS("Idle overslept!\n");
-
- /* Record the closest to missing a deadline. */
- if (margin_us < dsleep_recovery_margin_us)
- dsleep_recovery_margin_us = margin_us;
- } else {
- idle_sleep_cnt++;
-
- /* Normal idle : only CPU clock stopped */
- asm("wfi");
- }
-#ifdef CONFIG_LOW_POWER_IDLE_LIMITED
-en_int:
-#endif
- asm volatile("cpsie i");
- }
-}
-#endif /* CONFIG_LOW_POWER_IDLE */
-
-int clock_get_freq(void)
-{
- return CPU_CLOCK;
-}
-
-void clock_wait_bus_cycles(enum bus_type bus, uint32_t cycles)
-{
- volatile uint32_t unused __attribute__((unused));
-
- if (bus == BUS_AHB) {
- while (cycles--)
- unused = STM32_DMA1_REGS->isr;
- } else { /* APB */
- while (cycles--)
- unused = STM32_USART_BRR(STM32_USART1_BASE);
- }
-}
-
-void clock_enable_module(enum module_id module, int enable)
-{
- if (module == MODULE_ADC) {
- if (enable)
- STM32_RCC_APB2ENR |= STM32_RCC_APB2ENR_ADCEN;
- else
- STM32_RCC_APB2ENR &= ~STM32_RCC_APB2ENR_ADCEN;
- return;
- } else if (module == MODULE_USB) {
- if (enable)
- STM32_RCC_APB1ENR |= STM32_RCC_PB1_USB;
- else
- STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_USB;
- }
-}
-
-int clock_is_module_enabled(enum module_id module)
-{
- if (module == MODULE_ADC)
- return !!(STM32_RCC_APB2ENR & STM32_RCC_APB2ENR_ADCEN);
- else if (module == MODULE_USB)
- return !!(STM32_RCC_APB1ENR & STM32_RCC_PB1_USB);
- return 0;
-}
-
-void rtc_init(void)
-{
- rtc_unlock_regs();
-
- /* Enter RTC initialize mode */
- STM32_RTC_ISR |= STM32_RTC_ISR_INIT;
- while (!(STM32_RTC_ISR & STM32_RTC_ISR_INITF))
- ;
-
- /* Set clock prescalars */
- STM32_RTC_PRER = (RTC_PREDIV_A << 16) | RTC_PREDIV_S;
-
- /* Start RTC timer */
- STM32_RTC_ISR &= ~STM32_RTC_ISR_INIT;
- while (STM32_RTC_ISR & STM32_RTC_ISR_INITF)
- ;
-
- /* Enable RTC alarm interrupt */
- STM32_RTC_CR |= STM32_RTC_CR_ALRAIE | STM32_RTC_CR_BYPSHAD;
- STM32_EXTI_RTSR |= EXTI_RTC_ALR_EVENT;
- task_enable_irq(STM32_IRQ_RTC_ALARM);
-
- rtc_lock_regs();
-}
-
-#if defined(CONFIG_CMD_RTC) || defined(CONFIG_HOSTCMD_RTC)
-void rtc_set(uint32_t sec)
-{
- struct rtc_time_reg rtc;
-
- sec_to_rtc(sec, &rtc);
- rtc_unlock_regs();
-
- /* Disable alarm */
- STM32_RTC_CR &= ~STM32_RTC_CR_ALRAE;
-
- /* Enter RTC initialize mode */
- STM32_RTC_ISR |= STM32_RTC_ISR_INIT;
- while (!(STM32_RTC_ISR & STM32_RTC_ISR_INITF))
- ;
-
- /* Set clock prescalars */
- STM32_RTC_PRER = (RTC_PREDIV_A << 16) | RTC_PREDIV_S;
-
- STM32_RTC_TR = rtc.rtc_tr;
- STM32_RTC_DR = rtc.rtc_dr;
- /* Start RTC timer */
- STM32_RTC_ISR &= ~STM32_RTC_ISR_INIT;
-
- rtc_lock_regs();
-}
-#endif
-
-#if defined(CONFIG_LOW_POWER_IDLE) && defined(CONFIG_COMMON_RUNTIME)
-#ifdef CONFIG_CMD_IDLE_STATS
-/**
- * Print low power idle statistics
- */
-static int command_idle_stats(int argc, char **argv)
-{
- timestamp_t ts = get_time();
-
- ccprintf("Num idle calls that sleep: %d\n", idle_sleep_cnt);
- ccprintf("Num idle calls that deep-sleep: %d\n", idle_dsleep_cnt);
- ccprintf("Time spent in deep-sleep: %.6llds\n",
- idle_dsleep_time_us);
- ccprintf("Total time on: %.6llds\n", ts.val);
- ccprintf("Deep-sleep closest to wake deadline: %dus\n",
- dsleep_recovery_margin_us);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats,
- "",
- "Print last idle stats");
-#endif /* CONFIG_CMD_IDLE_STATS */
-#endif