mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-10 17:41:54 +00:00
pit: Fix watchdog help for STM32L
Clean up timer initialization code to be more general, so that we can
use timer 9 for the LSB on STM32L. Then use timer 4 for the watchdog
helper.
BUG=chrome-os-partner:18781
BRANCH=none
TEST=From EC console:
timerinfo -> current time still counts up properly
waitms 2000 -> prints watchdog info before rebooting
Change-Id: Ib0ba496b0eadb93756dcd1841857546910baf2a9
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/59612
Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
committed by
ChromeBot
parent
c7e60d03aa
commit
8a66ae3182
@@ -49,6 +49,7 @@
|
||||
/* Timer selection */
|
||||
#define TIM_CLOCK_MSB 3
|
||||
#define TIM_CLOCK_LSB 4
|
||||
#define TIM_WATCHDOG 1
|
||||
|
||||
/* GPIO signal list */
|
||||
enum gpio_signal {
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
#define CONFIG_ASSERT_HELP
|
||||
#define CONFIG_CONSOLE_CMDHELP
|
||||
#define CONFIG_PANIC_HELP
|
||||
#define CONFIG_TASK_PROFILING
|
||||
#define CONFIG_TASK_PROFILING
|
||||
#define CONFIG_WATCHDOG_HELP
|
||||
|
||||
/* Optional features */
|
||||
#define CONFIG_BATTERY_BQ20Z453
|
||||
@@ -44,7 +45,6 @@
|
||||
#ifdef PORT_TO_PIT
|
||||
/* TODO(rspangler): enable these features when they compile */
|
||||
#define CONFIG_LOW_POWER_IDLE
|
||||
#define CONFIG_WATCHDOG_HELP
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
@@ -74,7 +74,8 @@
|
||||
|
||||
/* Timer selection */
|
||||
#define TIM_CLOCK_MSB 3
|
||||
#define TIM_CLOCK_LSB 4
|
||||
#define TIM_CLOCK_LSB 9
|
||||
#define TIM_WATCHDOG 4
|
||||
|
||||
/* GPIO signal list */
|
||||
enum gpio_signal {
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
/* Timer selection */
|
||||
#define TIM_CLOCK_MSB 3
|
||||
#define TIM_CLOCK_LSB 4
|
||||
#define TIM_WATCHDOG 1
|
||||
|
||||
/* GPIO signal list */
|
||||
enum gpio_signal {
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
/* Timer selection */
|
||||
#define TIM_CLOCK_MSB 2
|
||||
#define TIM_CLOCK_LSB 4
|
||||
#define TIM_WATCHDOG 1
|
||||
|
||||
/* ADC signal */
|
||||
enum adc_channel {
|
||||
|
||||
@@ -16,21 +16,59 @@
|
||||
/* Divider to get microsecond for the clock */
|
||||
#define CLOCKSOURCE_DIVIDER (CPU_CLOCK / SECOND)
|
||||
|
||||
#define TIM_WD_IRQ STM32_IRQ_TIM1_UP_TIM16
|
||||
#define TIM_WD 1 /* Timer to use for watchdog */
|
||||
/*
|
||||
* Trigger select mapping for slave timer from master timer. This is
|
||||
* unfortunately not very straightforward; there's no tidy way to do this
|
||||
* algorithmically. To avoid burning memory for a lookup table, use macros to
|
||||
* compute the offset. This also has the benefit that compilation will fail if
|
||||
* an unsupported master/slave pairing is used.
|
||||
*
|
||||
* Slave Master
|
||||
* 1 15 2 3 4 (STM32F100 only)
|
||||
* 2 9 10 3 4
|
||||
* 3 9 2 11 4
|
||||
* 4 10 2 3 9
|
||||
* 9 2 3 10 11 (STM32L15x only)
|
||||
* --------------------
|
||||
* ts = 0 1 2 3
|
||||
*/
|
||||
#define STM32_TIM_TS_SLAVE_1_MASTER_15 0
|
||||
#define STM32_TIM_TS_SLAVE_1_MASTER_2 1
|
||||
#define STM32_TIM_TS_SLAVE_1_MASTER_3 2
|
||||
#define STM32_TIM_TS_SLAVE_1_MASTER_4 3
|
||||
#define STM32_TIM_TS_SLAVE_2_MASTER_9 0
|
||||
#define STM32_TIM_TS_SLAVE_2_MASTER_10 1
|
||||
#define STM32_TIM_TS_SLAVE_2_MASTER_3 2
|
||||
#define STM32_TIM_TS_SLAVE_2_MASTER_4 3
|
||||
#define STM32_TIM_TS_SLAVE_3_MASTER_9 0
|
||||
#define STM32_TIM_TS_SLAVE_3_MASTER_2 1
|
||||
#define STM32_TIM_TS_SLAVE_3_MASTER_11 2
|
||||
#define STM32_TIM_TS_SLAVE_3_MASTER_4 3
|
||||
#define STM32_TIM_TS_SLAVE_4_MASTER_10 0
|
||||
#define STM32_TIM_TS_SLAVE_4_MASTER_2 1
|
||||
#define STM32_TIM_TS_SLAVE_4_MASTER_3 2
|
||||
#define STM32_TIM_TS_SLAVE_4_MASTER_9 3
|
||||
#define STM32_TIM_TS_SLAVE_9_MASTER_2 0
|
||||
#define STM32_TIM_TS_SLAVE_9_MASTER_3 1
|
||||
#define STM32_TIM_TS_SLAVE_9_MASTER_10 2
|
||||
#define STM32_TIM_TS_SLAVE_9_MASTER_11 3
|
||||
#define TSMAP1(slave, master) STM32_TIM_TS_SLAVE_ ## slave ## _MASTER_ ## master
|
||||
#define TSMAP(slave, master) TSMAP1(slave, master)
|
||||
|
||||
/*
|
||||
* TIM_CLOCK_MSB and TIM_CLOCK_LSB must be defined per board. The available
|
||||
* values are 2, 3, and 4. This gives us flexibility to make any of the three
|
||||
* timer as a PWM source.
|
||||
* Timers are defined per board. This gives us flexibility to work around
|
||||
* timers which are dedicated to board-specific PWM sources.
|
||||
*/
|
||||
#define IRQ_TIM(n) STM32_CAT(STM32_IRQ_TIM, n, )
|
||||
#define IRQ_MSB IRQ_TIM(TIM_CLOCK_MSB)
|
||||
#define IRQ_LSB IRQ_TIM(TIM_CLOCK_LSB)
|
||||
#define IRQ_WD IRQ_TIM(TIM_WATCHDOG)
|
||||
|
||||
enum {
|
||||
TIM_WD_BASE = STM32_TIM1_BASE,
|
||||
};
|
||||
/* TIM1 has fancy names for its IRQs; remap count-up IRQ for the macro above */
|
||||
#define STM32_IRQ_TIM1 STM32_IRQ_TIM1_UP_TIM16
|
||||
|
||||
#define TIM_BASE(n) STM32_CAT(STM32_TIM, n, _BASE)
|
||||
#define TIM_WD_BASE TIM_BASE(TIM_WATCHDOG)
|
||||
|
||||
static uint32_t last_deadline;
|
||||
|
||||
@@ -123,6 +161,16 @@ static void __hw_clock_source_irq(void)
|
||||
DECLARE_IRQ(IRQ_MSB, __hw_clock_source_irq, 1);
|
||||
DECLARE_IRQ(IRQ_LSB, __hw_clock_source_irq, 1);
|
||||
|
||||
void __hw_timer_enable_clock(int n)
|
||||
{
|
||||
if (n == 1) /* STM32F only */
|
||||
STM32_RCC_APB2ENR |= 1 << 11;
|
||||
else if (n >= 2 && n <= 7)
|
||||
STM32_RCC_APB1ENR |= 1 << (n - 2);
|
||||
else if (n >= 9 && n <= 11) /* STM32L only */
|
||||
STM32_RCC_APB2ENR |= 1 << (n - 7);
|
||||
}
|
||||
|
||||
int __hw_clock_source_init(uint32_t start_t)
|
||||
{
|
||||
/*
|
||||
@@ -132,8 +180,8 @@ int __hw_clock_source_init(uint32_t start_t)
|
||||
*/
|
||||
|
||||
/* Enable TIM_CLOCK_MSB and TIM_CLOCK_LSB clocks */
|
||||
STM32_RCC_APB1ENR |= (1 << (TIM_CLOCK_MSB - 2)) |
|
||||
(1 << (TIM_CLOCK_LSB - 2));
|
||||
__hw_timer_enable_clock(TIM_CLOCK_MSB);
|
||||
__hw_timer_enable_clock(TIM_CLOCK_LSB);
|
||||
|
||||
/*
|
||||
* Timer configuration : Upcounter, counter disabled, update event only
|
||||
@@ -147,9 +195,11 @@ int __hw_clock_source_init(uint32_t start_t)
|
||||
*/
|
||||
STM32_TIM_CR2(TIM_CLOCK_MSB) = 0x0000;
|
||||
STM32_TIM_CR2(TIM_CLOCK_LSB) = 0x0020;
|
||||
/* TIM_CLOCK_MSB (slave mode) uses TIM_CLOCK_LSB as internal trigger */
|
||||
STM32_TIM_SMCR(TIM_CLOCK_MSB) = 0x0007 | ((TIM_CLOCK_LSB - 1) << 4);
|
||||
|
||||
STM32_TIM_SMCR(TIM_CLOCK_MSB) = 0x0007 |
|
||||
(TSMAP(TIM_CLOCK_MSB, TIM_CLOCK_LSB) << 4);
|
||||
STM32_TIM_SMCR(TIM_CLOCK_LSB) = 0x0000;
|
||||
|
||||
/* Auto-reload value : 16-bit free-running counters */
|
||||
STM32_TIM_ARR(TIM_CLOCK_MSB) = 0xffff;
|
||||
STM32_TIM_ARR(TIM_CLOCK_LSB) = 0xffff;
|
||||
@@ -184,12 +234,7 @@ int __hw_clock_source_init(uint32_t start_t)
|
||||
return IRQ_LSB;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't have TIM1 on STM32L, so don't support this function for now. TIM5
|
||||
* doesn't appear to exist in either variant, and TIM9 cannot be triggered as a
|
||||
* slave from TIM4. We could perhaps use TIM9 as our fast counter on STM32L.
|
||||
*/
|
||||
#if defined(CONFIG_WATCHDOG) && !defined(CHIP_VARIANT_stm32l15x)
|
||||
#ifdef CONFIG_WATCHDOG_HELP
|
||||
|
||||
void watchdog_check(uint32_t excep_lr, uint32_t excep_sp)
|
||||
{
|
||||
@@ -201,8 +246,8 @@ void watchdog_check(uint32_t excep_lr, uint32_t excep_sp)
|
||||
watchdog_trace(excep_lr, excep_sp);
|
||||
}
|
||||
|
||||
void IRQ_HANDLER(TIM_WD_IRQ)(void) __attribute__((naked));
|
||||
void IRQ_HANDLER(TIM_WD_IRQ)(void)
|
||||
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"
|
||||
@@ -215,9 +260,9 @@ void IRQ_HANDLER(TIM_WD_IRQ)(void)
|
||||
"pop {r0, lr}\n"
|
||||
"b task_resched_if_needed\n");
|
||||
}
|
||||
const struct irq_priority IRQ_BUILD_NAME(prio_, TIM_WD_IRQ, )
|
||||
const struct irq_priority IRQ_BUILD_NAME(prio_, IRQ_WD, )
|
||||
__attribute__((section(".rodata.irqprio")))
|
||||
= {TIM_WD_IRQ, 0}; /* put the watchdog at the highest
|
||||
= {IRQ_WD, 0}; /* put the watchdog at the highest
|
||||
priority */
|
||||
|
||||
void hwtimer_setup_watchdog(void)
|
||||
@@ -225,11 +270,7 @@ void hwtimer_setup_watchdog(void)
|
||||
struct timer_ctlr *timer = (struct timer_ctlr *)TIM_WD_BASE;
|
||||
|
||||
/* Enable clock */
|
||||
#if TIM_WD == 1
|
||||
STM32_RCC_APB2ENR |= 1 << 11;
|
||||
#else
|
||||
STM32_RCC_APB1ENR |= 1 << (TIM_WD - 2);
|
||||
#endif
|
||||
__hw_timer_enable_clock(TIM_WATCHDOG);
|
||||
|
||||
/*
|
||||
* Timer configuration : Down counter, counter disabled, update
|
||||
@@ -238,7 +279,7 @@ void hwtimer_setup_watchdog(void)
|
||||
timer->cr1 = 0x0014 | (1 << 7);
|
||||
|
||||
/* TIM (slave mode) uses TIM_CLOCK_LSB as internal trigger */
|
||||
timer->smcr = 0x0007 | ((TIM_CLOCK_LSB - 1) << 4);
|
||||
timer->smcr = 0x0007 | (TSMAP(TIM_WATCHDOG, TIM_CLOCK_LSB) << 4);
|
||||
|
||||
/*
|
||||
* The auto-reload value is based on the period between rollovers for
|
||||
@@ -247,7 +288,7 @@ void hwtimer_setup_watchdog(void)
|
||||
* to obtain the number of times TIM_CLOCK_LSB can overflow before we
|
||||
* generate an interrupt.
|
||||
*/
|
||||
timer->arr = timer->cnt = WATCHDOG_PERIOD_MS * 1000 / (1 << 16);
|
||||
timer->arr = timer->cnt = WATCHDOG_PERIOD_MS * MSEC / (1 << 16);
|
||||
|
||||
/* count on every TIM_CLOCK_LSB overflow */
|
||||
timer->psc = 0;
|
||||
@@ -262,7 +303,7 @@ void hwtimer_setup_watchdog(void)
|
||||
timer->cr1 |= 1;
|
||||
|
||||
/* Enable timer interrupts */
|
||||
task_enable_irq(TIM_WD_IRQ);
|
||||
task_enable_irq(IRQ_WD);
|
||||
}
|
||||
|
||||
void hwtimer_reset_watchdog(void)
|
||||
@@ -272,4 +313,4 @@ void hwtimer_reset_watchdog(void)
|
||||
timer->cnt = timer->arr;
|
||||
}
|
||||
|
||||
#endif /* defined(CONFIG_WATCHDOG) && !defined(CHIP_VARIANT_stm32l15x) */
|
||||
#endif /* defined(CONFIG_WATCHDOG) */
|
||||
|
||||
@@ -26,6 +26,13 @@ uint32_t __hw_clock_source_read(void);
|
||||
/* Override the current value of the hardware counter */
|
||||
void __hw_clock_source_set(uint32_t ts);
|
||||
|
||||
/**
|
||||
* Enable clock to a timer.
|
||||
*
|
||||
* @param n Timer number to enable
|
||||
*/
|
||||
void __hw_timer_enable_clock(int n);
|
||||
|
||||
/**
|
||||
* Initializes the hardware timer used to provide clock services, using the
|
||||
* specified start timer value.
|
||||
|
||||
Reference in New Issue
Block a user