Revision 5ef98b47 hw/etraxfs_timer.c
b/hw/etraxfs_timer.c | ||
---|---|---|
46 | 46 |
struct fs_timer_t { |
47 | 47 |
CPUState *env; |
48 | 48 |
qemu_irq *irq; |
49 |
qemu_irq *nmi; |
|
49 | 50 |
target_phys_addr_t base; |
50 | 51 |
|
51 | 52 |
QEMUBH *bh_t0; |
... | ... | |
56 | 57 |
ptimer_state *ptimer_wd; |
57 | 58 |
struct timeval last; |
58 | 59 |
|
60 |
int wd_hits; |
|
61 |
|
|
59 | 62 |
/* Control registers. */ |
60 | 63 |
uint32_t rw_tmr0_div; |
61 | 64 |
uint32_t r_tmr0_data; |
... | ... | |
129 | 132 |
unsigned int freq_hz; |
130 | 133 |
unsigned int div; |
131 | 134 |
uint32_t ctrl; |
135 |
|
|
132 | 136 |
ptimer_state *timer; |
133 | 137 |
|
134 | 138 |
if (tnum == 0) { |
... | ... | |
163 | 167 |
|
164 | 168 |
D(printf ("freq_hz=%d div=%d\n", freq_hz, div)); |
165 | 169 |
div = div * TIMER_SLOWDOWN; |
166 |
div >>= 15;
|
|
167 |
freq_hz >>= 15;
|
|
170 |
div >>= 10;
|
|
171 |
freq_hz >>= 10;
|
|
168 | 172 |
ptimer_set_freq(timer, freq_hz); |
169 | 173 |
ptimer_set_limit(timer, div, 0); |
170 | 174 |
|
... | ... | |
216 | 220 |
|
217 | 221 |
static void watchdog_hit(void *opaque) |
218 | 222 |
{ |
219 |
qemu_system_reset_request(); |
|
223 |
struct fs_timer_t *t = opaque; |
|
224 |
if (t->wd_hits == 0) { |
|
225 |
/* real hw gives a single tick before reseting but we are |
|
226 |
a bit friendlier to compensate for our slower execution. */ |
|
227 |
ptimer_set_count(t->ptimer_wd, 10); |
|
228 |
ptimer_run(t->ptimer_wd, 1); |
|
229 |
qemu_irq_raise(t->nmi[0]); |
|
230 |
} |
|
231 |
else |
|
232 |
qemu_system_reset_request(); |
|
233 |
|
|
234 |
t->wd_hits++; |
|
220 | 235 |
} |
221 | 236 |
|
222 | 237 |
static inline void timer_watchdog_update(struct fs_timer_t *t, uint32_t value) |
... | ... | |
237 | 252 |
D(printf("en=%d new_key=%x oldkey=%x cmd=%d cnt=%d\n", |
238 | 253 |
wd_en, new_key, wd_key, new_cmd, wd_cnt)); |
239 | 254 |
|
255 |
if (t->wd_hits) |
|
256 |
qemu_irq_lower(t->nmi[0]); |
|
257 |
|
|
258 |
t->wd_hits = 0; |
|
259 |
|
|
240 | 260 |
ptimer_set_freq(t->ptimer_wd, 760); |
241 | 261 |
if (wd_cnt == 0) |
242 | 262 |
wd_cnt = 256; |
... | ... | |
320 | 340 |
qemu_irq_lower(t->irq[0]); |
321 | 341 |
} |
322 | 342 |
|
323 |
void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, |
|
343 |
void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, qemu_irq *nmi,
|
|
324 | 344 |
target_phys_addr_t base) |
325 | 345 |
{ |
326 | 346 |
static struct fs_timer_t *t; |
... | ... | |
337 | 357 |
t->ptimer_t1 = ptimer_init(t->bh_t1); |
338 | 358 |
t->ptimer_wd = ptimer_init(t->bh_wd); |
339 | 359 |
t->irq = irqs; |
360 |
t->nmi = nmi; |
|
340 | 361 |
t->env = env; |
341 | 362 |
t->base = base; |
342 | 363 |
|
Also available in: Unified diff