| /* Copyright (c) 2012 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. |
| */ |
| |
| /* Watchdog driver */ |
| |
| #include "common.h" |
| #include "gpio.h" |
| #include "hooks.h" |
| #include "hwtimer.h" |
| #include "registers.h" |
| #include "task.h" |
| #include "timer.h" |
| #include "util.h" |
| #include "watchdog.h" |
| |
| /* |
| * LSI oscillator frequency is typically 38 kHz, but it may be between 28-56 |
| * kHz and we don't calibrate it to know. Use 56 kHz so that we pick a counter |
| * value large enough that we reload before the worst-case watchdog delay |
| * (fastest LSI clock). |
| */ |
| #define LSI_CLOCK 56000 |
| |
| /* |
| * Use largest prescaler divider = /256. This gives a worst-case watchdog |
| * clock of 56000/256 = 218 Hz, and a maximum timeout period of (4095/218 Hz) = |
| * 18.7 sec. |
| */ |
| #define IWDG_PRESCALER 6 |
| #define IWDG_PRESCALER_DIV (4 << IWDG_PRESCALER) |
| |
| void watchdog_reload(void) |
| { |
| /* Reload the watchdog */ |
| STM32_IWDG_KR = STM32_IWDG_KR_RELOAD; |
| |
| #ifdef CONFIG_WATCHDOG_HELP |
| hwtimer_reset_watchdog(); |
| #endif |
| } |
| DECLARE_HOOK(HOOK_TICK, watchdog_reload, HOOK_PRIO_DEFAULT); |
| |
| int watchdog_init(void) |
| { |
| /* Unlock watchdog registers */ |
| STM32_IWDG_KR = STM32_IWDG_KR_UNLOCK; |
| |
| /* Set the prescaler between the LSI clock and the watchdog counter */ |
| STM32_IWDG_PR = IWDG_PRESCALER & 7; |
| |
| /* Set the reload value of the watchdog counter */ |
| STM32_IWDG_RLR = MIN(STM32_IWDG_RLR_MAX, CONFIG_WATCHDOG_PERIOD_MS * |
| (LSI_CLOCK / IWDG_PRESCALER_DIV) / 1000); |
| |
| /* Start the watchdog (and re-lock registers) */ |
| STM32_IWDG_KR = STM32_IWDG_KR_START; |
| |
| #ifdef CONFIG_WATCHDOG_HELP |
| /* Use a harder timer to warn about an impending watchdog reset */ |
| hwtimer_setup_watchdog(); |
| #endif |
| |
| return EC_SUCCESS; |
| } |