diff options
Diffstat (limited to 'chip/stm32/hwtimer32.c')
-rw-r--r-- | chip/stm32/hwtimer32.c | 333 |
1 files changed, 0 insertions, 333 deletions
diff --git a/chip/stm32/hwtimer32.c b/chip/stm32/hwtimer32.c deleted file mode 100644 index 963fa44e51..0000000000 --- a/chip/stm32/hwtimer32.c +++ /dev/null @@ -1,333 +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. - */ - -/* Hardware 32-bit timer driver */ - -#include "clock.h" -#include "clock-f.h" -#include "common.h" -#include "hooks.h" -#include "hwtimer.h" -#include "panic.h" -#include "registers.h" -#include "task.h" -#include "timer.h" -#include "watchdog.h" - -#define IRQ_TIM(n) CONCAT2(STM32_IRQ_TIM, n) - -void __hw_clock_event_set(uint32_t deadline) -{ - /* set the match on the deadline */ - STM32_TIM32_CCR1(TIM_CLOCK32) = deadline; - /* Clear the match flags */ - STM32_TIM_SR(TIM_CLOCK32) = ~2; - /* Set the match interrupt */ - STM32_TIM_DIER(TIM_CLOCK32) |= 2; -} - -uint32_t __hw_clock_event_get(void) -{ - return STM32_TIM32_CCR1(TIM_CLOCK32); -} - -void __hw_clock_event_clear(void) -{ - /* Disable the match interrupts */ - STM32_TIM_DIER(TIM_CLOCK32) &= ~2; -} - -uint32_t __hw_clock_source_read(void) -{ - return STM32_TIM32_CNT(TIM_CLOCK32); -} - -void __hw_clock_source_set(uint32_t ts) -{ - STM32_TIM32_CNT(TIM_CLOCK32) = ts; -} - -void __hw_clock_source_irq(void) -{ - uint32_t stat_tim = STM32_TIM_SR(TIM_CLOCK32); - - /* Clear status */ - STM32_TIM_SR(TIM_CLOCK32) = 0; - - /* - * Find expired timers and set the new timer deadline - * signal overflow if the update interrupt flag is set. - */ - process_timers(stat_tim & 0x01); -} -DECLARE_IRQ(IRQ_TIM(TIM_CLOCK32), __hw_clock_source_irq, 1); - -void __hw_timer_enable_clock(int n, int enable) -{ - volatile uint32_t *reg; - uint32_t mask = 0; - - /* - * Mapping of timers to reg/mask is split into a few different ranges, - * some specific to individual chips. - */ -#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32H7) - if (n == 1) { - reg = &STM32_RCC_APB2ENR; - mask = STM32_RCC_PB2_TIM1; - } -#elif defined(CHIP_FAMILY_STM32L) || defined(CHIP_FAMILY_STM32F4) - if (n >= 9 && n <= 11) { - reg = &STM32_RCC_APB2ENR; - mask = STM32_RCC_PB2_TIM9 << (n - 9); - } -#endif - -#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32H7) - if (n >= 15 && n <= 17) { - reg = &STM32_RCC_APB2ENR; - mask = STM32_RCC_PB2_TIM15 << (n - 15); - } -#endif - -#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3) || \ -defined(CHIP_FAMILY_STM32H7) - if (n == 14) { - reg = &STM32_RCC_APB1ENR; - mask = STM32_RCC_PB1_TIM14; - } -#endif - -#if defined(CHIP_FAMILY_STM32F3) || defined(CHIP_FAMILY_STM32H7) - if (n == 12 || n == 13) { - reg = &STM32_RCC_APB1ENR; - mask = STM32_RCC_PB1_TIM12 << (n - 12); - } -#endif -#if defined(CHIP_FAMILY_STM32F3) - if (n == 18) { - reg = &STM32_RCC_APB1ENR; - mask = STM32_RCC_PB1_TIM18; - } - if (n == 19) { - reg = &STM32_RCC_APB2ENR; - mask = STM32_RCC_PB2_TIM19; - } -#endif -#if defined(CHIP_FAMILY_STM32G4) - reg = &STM32_RCC_APB2ENR; - if (n == 1) - mask = STM32_RCC_APB2ENR_TIM1; - else if (n == 8) - mask = STM32_RCC_APB2ENR_TIM8; - else if (n == 20) - mask = STM32_RCC_APB2ENR_TIM20; - else if (n >= 15 && n <= 17) - mask = STM32_RCC_APB2ENR_TIM15 << (n - 15); -#endif -#if defined(CHIP_FAMILY_STM32L4) - if (n >= 2 && n <= 7) { - reg = &STM32_RCC_APB1ENR1; - mask = STM32_RCC_PB1_TIM2 << (n - 2); - } else if (n == 1 || n == 15 || n == 16) { - reg = &STM32_RCC_APB2ENR; - mask = (n == 1) ? STM32_RCC_APB2ENR_TIM1EN : - (n == 15) ? STM32_RCC_APB2ENR_TIM15EN : - STM32_RCC_APB2ENR_TIM16EN; - } -#else - if (n >= 2 && n <= 7) { - reg = &STM32_RCC_APB1ENR; - mask = STM32_RCC_PB1_TIM2 << (n - 2); - } -#endif - - if (!mask) - return; - - if (enable) - *reg |= mask; - else - *reg &= ~mask; -} - -#if defined(CHIP_FAMILY_STM32L) || defined(CHIP_FAMILY_STM32L4) || \ - defined(CHIP_FAMILY_STM32F4) || defined(CHIP_FAMILY_STM32H7) -/* for families using a variable clock feeding the timer */ -static void update_prescaler(void) -{ - uint32_t t; - /* - * Pre-scaler value : - * the timer is incrementing every microsecond - */ - STM32_TIM_PSC(TIM_CLOCK32) = (clock_get_timer_freq() / SECOND) - 1; - /* - * Forcing reloading the pre-scaler, - * but try to maintain a sensible time-keeping while triggering - * the update event. - */ - interrupt_disable(); - /* Ignore the next update */ - STM32_TIM_DIER(TIM_CLOCK32) &= ~0x0001; - /* - * prepare to reload the counter with the current value - * to avoid rolling backward the microsecond counter. - */ - t = STM32_TIM32_CNT(TIM_CLOCK32) + 1; - /* issue an update event, reloads the pre-scaler and the counter */ - STM32_TIM_EGR(TIM_CLOCK32) = 0x0001; - /* clear the 'spurious' update unless we were going to roll-over */ - if (t) - STM32_TIM_SR(TIM_CLOCK32) = ~1; - /* restore a sensible time value */ - STM32_TIM32_CNT(TIM_CLOCK32) = t; - /* restore roll-over events */ - STM32_TIM_DIER(TIM_CLOCK32) |= 0x0001; - interrupt_enable(); - -#ifdef CONFIG_WATCHDOG_HELP - /* Watchdog timer runs at 1KHz */ - STM32_TIM_PSC(TIM_WATCHDOG) = - (clock_get_timer_freq() / SECOND * MSEC)- 1; -#endif /* CONFIG_WATCHDOG_HELP */ -} -DECLARE_HOOK(HOOK_FREQ_CHANGE, update_prescaler, HOOK_PRIO_DEFAULT); -#endif /* CHIP_FAMILY_STM32L || CHIP_FAMILY_STM32L4 || */ - /* CHIP_FAMILY_STM32F4 || CHIP_FAMILY_STM32H7 */ - -int __hw_clock_source_init(uint32_t start_t) -{ - /* Enable TIM peripheral block clocks */ - __hw_timer_enable_clock(TIM_CLOCK32, 1); - /* Delay 1 APB clock cycle after the clock is enabled */ - clock_wait_bus_cycles(BUS_APB, 1); - - /* - * Timer configuration : Upcounter, counter disabled, update event only - * on overflow. - */ - STM32_TIM_CR1(TIM_CLOCK32) = 0x0004; - /* No special configuration */ - STM32_TIM_CR2(TIM_CLOCK32) = 0x0000; - STM32_TIM_SMCR(TIM_CLOCK32) = 0x0000; - - /* Auto-reload value : 32-bit free-running counter */ - STM32_TIM32_ARR(TIM_CLOCK32) = 0xffffffff; - - /* Update prescaler to increment every microsecond */ - STM32_TIM_PSC(TIM_CLOCK32) = (clock_get_timer_freq() / SECOND) - 1; - - /* Reload the pre-scaler */ - STM32_TIM_EGR(TIM_CLOCK32) = 0x0001; - - /* Set up the overflow interrupt */ - STM32_TIM_DIER(TIM_CLOCK32) = 0x0001; - - /* Start counting */ - STM32_TIM_CR1(TIM_CLOCK32) |= 1; - - /* Override the count with the start value now that counting has - * started. */ - __hw_clock_source_set(start_t); - - /* Enable timer interrupts */ - task_enable_irq(IRQ_TIM(TIM_CLOCK32)); - - return IRQ_TIM(TIM_CLOCK32); -} - -#ifdef CONFIG_WATCHDOG_HELP - -#define IRQ_WD IRQ_TIM(TIM_WATCHDOG) - -void __keep watchdog_check(uint32_t excep_lr, uint32_t excep_sp) -{ - /* clear status */ - STM32_TIM_SR(TIM_WATCHDOG) = 0; - - watchdog_trace(excep_lr, excep_sp); -} - -void IRQ_HANDLER(IRQ_WD)(void) __attribute__((naked)); -void IRQ_HANDLER(IRQ_WD)(void) -{ - /* Naked call so we can extract raw LR and SP */ - asm volatile("mov r0, lr\n" - "mov r1, sp\n" - /* Must push registers in pairs to keep 64-bit aligned - * stack for ARM EABI. */ - "push {r0, lr}\n" - "bl watchdog_check\n" - "pop {r0,pc}\n"); -} -const struct irq_priority __keep IRQ_PRIORITY(IRQ_WD) - __attribute__((section(".rodata.irqprio"))) - = {IRQ_WD, 0}; /* put the watchdog at the highest - priority */ - -void hwtimer_setup_watchdog(void) -{ - int freq; - - /* Enable clock */ - __hw_timer_enable_clock(TIM_WATCHDOG, 1); - /* Delay 1 APB clock cycle after the clock is enabled */ - clock_wait_bus_cycles(BUS_APB, 1); - - /* - * Timer configuration : Up counter, counter disabled, update - * event only on overflow. - */ - STM32_TIM_CR1(TIM_WATCHDOG) = 0x0004; - /* No special configuration */ - STM32_TIM_CR2(TIM_WATCHDOG) = 0x0000; - STM32_TIM_SMCR(TIM_WATCHDOG) = 0x0000; - - /* - * all timers has 16-bit prescale. - * For clock freq > 64MHz, 16bit prescale cannot meet 1KHz. - * set prescale as 10KHz and 10 times arr value instead. - * For clock freq < 64MHz, timer runs at 1KHz. - */ - freq = clock_get_timer_freq(); - - if (freq <= 64000000 || !IS_ENABLED(CHIP_FAMILY_STM32L4)) { - /* AUto-reload value */ - STM32_TIM_ARR(TIM_WATCHDOG) = CONFIG_AUX_TIMER_PERIOD_MS; - - /* Update prescaler: watchdog timer runs at 1KHz */ - STM32_TIM_PSC(TIM_WATCHDOG) = - (freq / SECOND * MSEC) - 1; - } -#ifdef CHIP_FAMILY_STM32L4 - else { - /* 10 times ARR value with 10KHz timer */ - STM32_TIM_ARR(TIM_WATCHDOG) = CONFIG_AUX_TIMER_PERIOD_MS * 10; - - /* Update prescaler: watchdog timer runs at 10KHz */ - STM32_TIM_PSC(TIM_WATCHDOG) = (freq / SECOND / 10 * MSEC) - 1; - } -#endif - /* Reload the pre-scaler */ - STM32_TIM_EGR(TIM_WATCHDOG) = 0x0001; - - /* setup the overflow interrupt */ - STM32_TIM_DIER(TIM_WATCHDOG) = 0x0001; - STM32_TIM_SR(TIM_WATCHDOG) = 0; - - /* Start counting */ - STM32_TIM_CR1(TIM_WATCHDOG) |= 1; - - /* Enable timer interrupts */ - task_enable_irq(IRQ_WD); -} - -void hwtimer_reset_watchdog(void) -{ - STM32_TIM_CNT(TIM_WATCHDOG) = 0x0000; -} - -#endif /* CONFIG_WATCHDOG_HELP */ |