Commit 703243a044c8b7d5c52fdf67e4c1aacf1d6c4d76
1 parent
b7d35e65
Adds interrupt support to the sh specific timer code (Magnus Damm).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3812 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
33 additions
and
18 deletions
hw/sh.h
... | ... | @@ -2,6 +2,8 @@ |
2 | 2 | #define QEMU_SH_H |
3 | 3 | /* Definitions for SH board emulation. */ |
4 | 4 | |
5 | +#include "sh_intc.h" | |
6 | + | |
5 | 7 | /* sh7750.c */ |
6 | 8 | struct SH7750State; |
7 | 9 | |
... | ... | @@ -25,7 +27,10 @@ int sh7750_register_io_device(struct SH7750State *s, |
25 | 27 | #define TMU012_FEAT_TOCR (1 << 0) |
26 | 28 | #define TMU012_FEAT_3CHAN (1 << 1) |
27 | 29 | #define TMU012_FEAT_EXTCLK (1 << 2) |
28 | -void tmu012_init(uint32_t base, int feat, uint32_t freq); | |
30 | +void tmu012_init(target_phys_addr_t base, int feat, uint32_t freq, | |
31 | + struct intc_source *ch0_irq, struct intc_source *ch1_irq, | |
32 | + struct intc_source *ch2_irq0, struct intc_source *ch2_irq1); | |
33 | + | |
29 | 34 | |
30 | 35 | /* sh_serial.c */ |
31 | 36 | #define SH_SERIAL_FEAT_SCIF (1 << 0) | ... | ... |
hw/sh7750.c
... | ... | @@ -559,8 +559,11 @@ SH7750State *sh7750_init(CPUSH4State * cpu) |
559 | 559 | |
560 | 560 | tmu012_init(0x1fd80000, |
561 | 561 | TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK, |
562 | - s->periph_freq); | |
563 | - | |
562 | + s->periph_freq, | |
563 | + sh_intc_source(&s->intc, TMU0), | |
564 | + sh_intc_source(&s->intc, TMU1), | |
565 | + sh_intc_source(&s->intc, TMU2_TUNI), | |
566 | + sh_intc_source(&s->intc, TMU2_TICPI)); | |
564 | 567 | |
565 | 568 | if (cpu_model & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) { |
566 | 569 | sh_intc_register_sources(&s->intc, |
... | ... | @@ -578,7 +581,10 @@ SH7750State *sh7750_init(CPUSH4State * cpu) |
578 | 581 | sh_intc_register_sources(&s->intc, |
579 | 582 | _INTC_ARRAY(vectors_tmu34), |
580 | 583 | NULL, 0); |
581 | - tmu012_init(0x1e100000, 0, s->periph_freq); | |
584 | + tmu012_init(0x1e100000, 0, s->periph_freq, | |
585 | + sh_intc_source(&s->intc, TMU3), | |
586 | + sh_intc_source(&s->intc, TMU4), | |
587 | + NULL, NULL); | |
582 | 588 | } |
583 | 589 | |
584 | 590 | if (cpu_model & (SH_CPU_SH7751_ALL)) { | ... | ... |
hw/sh_timer.c
... | ... | @@ -33,23 +33,23 @@ typedef struct { |
33 | 33 | uint32_t tcpr; |
34 | 34 | int freq; |
35 | 35 | int int_level; |
36 | + int old_level; | |
36 | 37 | int feat; |
37 | 38 | int enabled; |
38 | - qemu_irq irq; | |
39 | + struct intc_source *irq; | |
39 | 40 | } sh_timer_state; |
40 | 41 | |
41 | 42 | /* Check all active timers, and schedule the next timer interrupt. */ |
42 | 43 | |
43 | 44 | static void sh_timer_update(sh_timer_state *s) |
44 | 45 | { |
45 | -#if 0 /* not yet */ | |
46 | - /* Update interrupts. */ | |
47 | - if (s->int_level && (s->tcr & TIMER_TCR_UNIE)) { | |
48 | - qemu_irq_raise(s->irq); | |
49 | - } else { | |
50 | - qemu_irq_lower(s->irq); | |
51 | - } | |
52 | -#endif | |
46 | + int new_level = s->int_level && (s->tcr & TIMER_TCR_UNIE); | |
47 | + | |
48 | + if (new_level != s->old_level) | |
49 | + sh_intc_toggle_source(s->irq, 0, new_level ? 1 : -1); | |
50 | + | |
51 | + s->old_level = s->int_level; | |
52 | + s->int_level = new_level; | |
53 | 53 | } |
54 | 54 | |
55 | 55 | static uint32_t sh_timer_read(void *opaque, target_phys_addr_t offset) |
... | ... | @@ -185,7 +185,7 @@ static void sh_timer_tick(void *opaque) |
185 | 185 | sh_timer_update(s); |
186 | 186 | } |
187 | 187 | |
188 | -static void *sh_timer_init(uint32_t freq, int feat) | |
188 | +static void *sh_timer_init(uint32_t freq, int feat, struct intc_source *irq) | |
189 | 189 | { |
190 | 190 | sh_timer_state *s; |
191 | 191 | QEMUBH *bh; |
... | ... | @@ -198,6 +198,7 @@ static void *sh_timer_init(uint32_t freq, int feat) |
198 | 198 | s->tcpr = 0xdeadbeef; |
199 | 199 | s->tcor = 0; |
200 | 200 | s->enabled = 0; |
201 | + s->irq = irq; | |
201 | 202 | |
202 | 203 | bh = qemu_bh_new(sh_timer_tick, s); |
203 | 204 | s->timer = ptimer_init(bh); |
... | ... | @@ -305,7 +306,9 @@ static CPUWriteMemoryFunc *tmu012_writefn[] = { |
305 | 306 | tmu012_write |
306 | 307 | }; |
307 | 308 | |
308 | -void tmu012_init(uint32_t base, int feat, uint32_t freq) | |
309 | +void tmu012_init(target_phys_addr_t base, int feat, uint32_t freq, | |
310 | + struct intc_source *ch0_irq, struct intc_source *ch1_irq, | |
311 | + struct intc_source *ch2_irq0, struct intc_source *ch2_irq1) | |
309 | 312 | { |
310 | 313 | int iomemtype; |
311 | 314 | tmu012_state *s; |
... | ... | @@ -314,10 +317,11 @@ void tmu012_init(uint32_t base, int feat, uint32_t freq) |
314 | 317 | s = (tmu012_state *)qemu_mallocz(sizeof(tmu012_state)); |
315 | 318 | s->base = base; |
316 | 319 | s->feat = feat; |
317 | - s->timer[0] = sh_timer_init(freq, timer_feat); | |
318 | - s->timer[1] = sh_timer_init(freq, timer_feat); | |
320 | + s->timer[0] = sh_timer_init(freq, timer_feat, ch0_irq); | |
321 | + s->timer[1] = sh_timer_init(freq, timer_feat, ch1_irq); | |
319 | 322 | if (feat & TMU012_FEAT_3CHAN) |
320 | - s->timer[2] = sh_timer_init(freq, timer_feat | TIMER_FEAT_CAPT); | |
323 | + s->timer[2] = sh_timer_init(freq, timer_feat | TIMER_FEAT_CAPT, | |
324 | + ch2_irq0); /* ch2_irq1 not supported */ | |
321 | 325 | iomemtype = cpu_register_io_memory(0, tmu012_readfn, |
322 | 326 | tmu012_writefn, s); |
323 | 327 | cpu_register_physical_memory(base, 0x00001000, iomemtype); | ... | ... |