diff options
Diffstat (limited to 'firmware/target/arm/imx233')
-rw-r--r-- | firmware/target/arm/imx233/icoll-imx233.c | 3 | ||||
-rw-r--r-- | firmware/target/arm/imx233/system-imx233.c | 52 | ||||
-rw-r--r-- | firmware/target/arm/imx233/system-target.h | 3 | ||||
-rw-r--r-- | firmware/target/arm/imx233/timrot-imx233.h | 1 |
4 files changed, 58 insertions, 1 deletions
diff --git a/firmware/target/arm/imx233/icoll-imx233.c b/firmware/target/arm/imx233/icoll-imx233.c index e42e0f3291..e23af602db 100644 --- a/firmware/target/arm/imx233/icoll-imx233.c +++ b/firmware/target/arm/imx233/icoll-imx233.c | |||
@@ -146,6 +146,7 @@ struct imx233_icoll_irq_info_t imx233_icoll_get_irq_info(int src) | |||
146 | 146 | ||
147 | static void do_irq_stat(void) | 147 | static void do_irq_stat(void) |
148 | { | 148 | { |
149 | imx233_keep_alive(); | ||
149 | static unsigned counter = 0; | 150 | static unsigned counter = 0; |
150 | if(counter++ >= HZ) | 151 | if(counter++ >= HZ) |
151 | { | 152 | { |
@@ -180,6 +181,8 @@ void irq_handler(void) | |||
180 | asm volatile( | 181 | asm volatile( |
181 | "sub lr, lr, #4 \n" /* Create return address */ | 182 | "sub lr, lr, #4 \n" /* Create return address */ |
182 | "stmfd sp!, { r0-r5, r12, lr } \n" /* Save what gets clobbered */ | 183 | "stmfd sp!, { r0-r5, r12, lr } \n" /* Save what gets clobbered */ |
184 | "ldr r5, =0x8001c290 \n" /* Save pointer to instruction */ | ||
185 | "str lr, [r5] \n" /* in HW_DIGCTL_SCRATCH0 */ | ||
183 | "ldr r4, =0x80000000 \n" /* Read HW_ICOLL_VECTOR */ | 186 | "ldr r4, =0x80000000 \n" /* Read HW_ICOLL_VECTOR */ |
184 | "ldr r0, [r4] \n" /* and notify as side-effect */ | 187 | "ldr r0, [r4] \n" /* and notify as side-effect */ |
185 | "mrs lr, spsr \n" /* Save SPSR_irq */ | 188 | "mrs lr, spsr \n" /* Save SPSR_irq */ |
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} */ |
diff --git a/firmware/target/arm/imx233/system-target.h b/firmware/target/arm/imx233/system-target.h index 33e8f12265..6272cf7a85 100644 --- a/firmware/target/arm/imx233/system-target.h +++ b/firmware/target/arm/imx233/system-target.h | |||
@@ -68,4 +68,7 @@ void usb_remove_int(void); | |||
68 | 68 | ||
69 | bool dbg_hw_target_info(void); | 69 | bool dbg_hw_target_info(void); |
70 | 70 | ||
71 | /* for watchdog */ | ||
72 | void imx233_keep_alive(void); | ||
73 | |||
71 | #endif /* SYSTEM_TARGET_H */ | 74 | #endif /* SYSTEM_TARGET_H */ |
diff --git a/firmware/target/arm/imx233/timrot-imx233.h b/firmware/target/arm/imx233/timrot-imx233.h index f1a7780f34..e33de39390 100644 --- a/firmware/target/arm/imx233/timrot-imx233.h +++ b/firmware/target/arm/imx233/timrot-imx233.h | |||
@@ -32,6 +32,7 @@ enum | |||
32 | { | 32 | { |
33 | TIMER_TICK, /* for tick task */ | 33 | TIMER_TICK, /* for tick task */ |
34 | TIMER_USER, /* for user timer */ | 34 | TIMER_USER, /* for user timer */ |
35 | TIMER_WATCHDOG, /* for watchdog */ | ||
35 | }; | 36 | }; |
36 | 37 | ||
37 | struct imx233_timrot_info_t | 38 | struct imx233_timrot_info_t |