summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx233/system-imx233.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx233/system-imx233.c')
-rw-r--r--firmware/target/arm/imx233/system-imx233.c52
1 files changed, 51 insertions, 1 deletions
diff --git a/firmware/target/arm/imx233/system-imx233.c b/firmware/target/arm/imx233/system-imx233.c
index b25ccb5c47..5298f7cff9 100644
--- a/firmware/target/arm/imx233/system-imx233.c
+++ b/firmware/target/arm/imx233/system-imx233.c
@@ -45,6 +45,55 @@
45#include "fmradio_i2c.h" 45#include "fmradio_i2c.h"
46#include "powermgmt-imx233.h" 46#include "powermgmt-imx233.h"
47 47
48#define WATCHDOG_HW_DELAY (10 * HZ)
49#define WATCHDOG_SW_DELAY (5 * HZ)
50
51static void woof_woof(void)
52{
53 /* stop hadrware watchdog, we catched the error */
54 imx233_rtc_enable_watchdog(false);
55 uint32_t pc = HW_DIGCTL_SCRATCH0;
56 /* write a "SWI #0xdead" instruction at the faulty instruction so that it
57 * will trigger a proper backtrace */
58 *(uint32_t *)pc = 0xef00dead;
59 commit_discard_idcache();
60}
61
62static void good_dog(void)
63{
64 imx233_rtc_reset_watchdog(WATCHDOG_HW_DELAY * 1000 / HZ); /* ms */
65 imx233_rtc_enable_watchdog(true);
66 imx233_timrot_setup(TIMER_WATCHDOG, false, WATCHDOG_SW_DELAY * 1000 / HZ,
67 BV_TIMROT_TIMCTRLn_SELECT__1KHZ_XTAL, BV_TIMROT_TIMCTRLn_PRESCALE__DIV_BY_1,
68 false, &woof_woof);
69 imx233_timrot_set_priority(TIMER_WATCHDOG, ICOLL_PRIO_WATCHDOG);
70}
71
72void imx233_keep_alive(void)
73{
74 /* setting up a timer is not exactly a cheap operation so only do so
75 * every second */
76 static uint32_t last_alive = 0;
77 if(imx233_us_elapsed(last_alive, 1000000))
78 {
79 good_dog();
80 last_alive = HW_DIGCTL_MICROSECONDS;
81 }
82}
83
84static void watchdog_init(void)
85{
86 /* setup two mechanisms:
87 * - hardware watchdog to reset the player after 10 seconds
88 * - software watchdog using a timer to panic after 5 seconds
89 * The hardware mechanism ensures reset when the player is completely
90 * dead and it actually resets the whole chip. On the contrary, the software
91 * mechanism allows partial recovery by panicing and printing (maybe) useful
92 * information, it uses a dedicated timer with the highest level of interrupt
93 * priority so it works even if the player is stuck in IRQ context */
94 good_dog();
95}
96
48void imx233_chip_reset(void) 97void imx233_chip_reset(void)
49{ 98{
50#if IMX233_SUBTARGET >= 3700 99#if IMX233_SUBTARGET >= 3700
@@ -60,7 +109,6 @@ void system_reboot(void)
60 109
61 disable_irq(); 110 disable_irq();
62 111
63 /* use watchdog to reset */
64 imx233_chip_reset(); 112 imx233_chip_reset();
65 while(1); 113 while(1);
66} 114}
@@ -134,6 +182,8 @@ void system_init(void)
134 imx233_power_init(); 182 imx233_power_init();
135 imx233_i2c_init(); 183 imx233_i2c_init();
136 imx233_powermgmt_init(); 184 imx233_powermgmt_init();
185 /* setup watchdog */
186 watchdog_init();
137 187
138 /* make sure auto-slow is disable now, we don't know at which frequency we 188 /* make sure auto-slow is disable now, we don't know at which frequency we
139 * are running and auto-slow could violate constraints on {xbus,hbus} */ 189 * are running and auto-slow could violate constraints on {xbus,hbus} */