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,6 +2,8 @@ | ||
2 | #define QEMU_SH_H | 2 | #define QEMU_SH_H |
3 | /* Definitions for SH board emulation. */ | 3 | /* Definitions for SH board emulation. */ |
4 | 4 | ||
5 | +#include "sh_intc.h" | ||
6 | + | ||
5 | /* sh7750.c */ | 7 | /* sh7750.c */ |
6 | struct SH7750State; | 8 | struct SH7750State; |
7 | 9 | ||
@@ -25,7 +27,10 @@ int sh7750_register_io_device(struct SH7750State *s, | @@ -25,7 +27,10 @@ int sh7750_register_io_device(struct SH7750State *s, | ||
25 | #define TMU012_FEAT_TOCR (1 << 0) | 27 | #define TMU012_FEAT_TOCR (1 << 0) |
26 | #define TMU012_FEAT_3CHAN (1 << 1) | 28 | #define TMU012_FEAT_3CHAN (1 << 1) |
27 | #define TMU012_FEAT_EXTCLK (1 << 2) | 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 | /* sh_serial.c */ | 35 | /* sh_serial.c */ |
31 | #define SH_SERIAL_FEAT_SCIF (1 << 0) | 36 | #define SH_SERIAL_FEAT_SCIF (1 << 0) |
hw/sh7750.c
@@ -559,8 +559,11 @@ SH7750State *sh7750_init(CPUSH4State * cpu) | @@ -559,8 +559,11 @@ SH7750State *sh7750_init(CPUSH4State * cpu) | ||
559 | 559 | ||
560 | tmu012_init(0x1fd80000, | 560 | tmu012_init(0x1fd80000, |
561 | TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK, | 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 | if (cpu_model & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) { | 568 | if (cpu_model & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) { |
566 | sh_intc_register_sources(&s->intc, | 569 | sh_intc_register_sources(&s->intc, |
@@ -578,7 +581,10 @@ SH7750State *sh7750_init(CPUSH4State * cpu) | @@ -578,7 +581,10 @@ SH7750State *sh7750_init(CPUSH4State * cpu) | ||
578 | sh_intc_register_sources(&s->intc, | 581 | sh_intc_register_sources(&s->intc, |
579 | _INTC_ARRAY(vectors_tmu34), | 582 | _INTC_ARRAY(vectors_tmu34), |
580 | NULL, 0); | 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 | if (cpu_model & (SH_CPU_SH7751_ALL)) { | 590 | if (cpu_model & (SH_CPU_SH7751_ALL)) { |
hw/sh_timer.c
@@ -33,23 +33,23 @@ typedef struct { | @@ -33,23 +33,23 @@ typedef struct { | ||
33 | uint32_t tcpr; | 33 | uint32_t tcpr; |
34 | int freq; | 34 | int freq; |
35 | int int_level; | 35 | int int_level; |
36 | + int old_level; | ||
36 | int feat; | 37 | int feat; |
37 | int enabled; | 38 | int enabled; |
38 | - qemu_irq irq; | 39 | + struct intc_source *irq; |
39 | } sh_timer_state; | 40 | } sh_timer_state; |
40 | 41 | ||
41 | /* Check all active timers, and schedule the next timer interrupt. */ | 42 | /* Check all active timers, and schedule the next timer interrupt. */ |
42 | 43 | ||
43 | static void sh_timer_update(sh_timer_state *s) | 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 | static uint32_t sh_timer_read(void *opaque, target_phys_addr_t offset) | 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,7 +185,7 @@ static void sh_timer_tick(void *opaque) | ||
185 | sh_timer_update(s); | 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 | sh_timer_state *s; | 190 | sh_timer_state *s; |
191 | QEMUBH *bh; | 191 | QEMUBH *bh; |
@@ -198,6 +198,7 @@ static void *sh_timer_init(uint32_t freq, int feat) | @@ -198,6 +198,7 @@ static void *sh_timer_init(uint32_t freq, int feat) | ||
198 | s->tcpr = 0xdeadbeef; | 198 | s->tcpr = 0xdeadbeef; |
199 | s->tcor = 0; | 199 | s->tcor = 0; |
200 | s->enabled = 0; | 200 | s->enabled = 0; |
201 | + s->irq = irq; | ||
201 | 202 | ||
202 | bh = qemu_bh_new(sh_timer_tick, s); | 203 | bh = qemu_bh_new(sh_timer_tick, s); |
203 | s->timer = ptimer_init(bh); | 204 | s->timer = ptimer_init(bh); |
@@ -305,7 +306,9 @@ static CPUWriteMemoryFunc *tmu012_writefn[] = { | @@ -305,7 +306,9 @@ static CPUWriteMemoryFunc *tmu012_writefn[] = { | ||
305 | tmu012_write | 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 | int iomemtype; | 313 | int iomemtype; |
311 | tmu012_state *s; | 314 | tmu012_state *s; |
@@ -314,10 +317,11 @@ void tmu012_init(uint32_t base, int feat, uint32_t freq) | @@ -314,10 +317,11 @@ void tmu012_init(uint32_t base, int feat, uint32_t freq) | ||
314 | s = (tmu012_state *)qemu_mallocz(sizeof(tmu012_state)); | 317 | s = (tmu012_state *)qemu_mallocz(sizeof(tmu012_state)); |
315 | s->base = base; | 318 | s->base = base; |
316 | s->feat = feat; | 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 | if (feat & TMU012_FEAT_3CHAN) | 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 | iomemtype = cpu_register_io_memory(0, tmu012_readfn, | 325 | iomemtype = cpu_register_io_memory(0, tmu012_readfn, |
322 | tmu012_writefn, s); | 326 | tmu012_writefn, s); |
323 | cpu_register_physical_memory(base, 0x00001000, iomemtype); | 327 | cpu_register_physical_memory(base, 0x00001000, iomemtype); |