diff options
Diffstat (limited to 'firmware/target/arm/imx233/system-imx233.c')
-rw-r--r-- | firmware/target/arm/imx233/system-imx233.c | 52 |
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 | |||
51 | static 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 | |||
62 | static 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 | |||
72 | void 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 | |||
84 | static 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 | |||
48 | void imx233_chip_reset(void) | 97 | void 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} */ |