From 703243a044c8b7d5c52fdf67e4c1aacf1d6c4d76 Mon Sep 17 00:00:00 2001 From: balrog Date: Wed, 12 Dec 2007 01:11:42 +0000 Subject: [PATCH] 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 --- hw/sh.h | 7 ++++++- hw/sh7750.c | 12 +++++++++--- hw/sh_timer.c | 32 ++++++++++++++++++-------------- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/hw/sh.h b/hw/sh.h index 57a2485cba..7df31640ef 100644 --- a/hw/sh.h +++ b/hw/sh.h @@ -2,6 +2,8 @@ #define QEMU_SH_H /* Definitions for SH board emulation. */ +#include "sh_intc.h" + /* sh7750.c */ struct SH7750State; @@ -25,7 +27,10 @@ int sh7750_register_io_device(struct SH7750State *s, #define TMU012_FEAT_TOCR (1 << 0) #define TMU012_FEAT_3CHAN (1 << 1) #define TMU012_FEAT_EXTCLK (1 << 2) -void tmu012_init(uint32_t base, int feat, uint32_t freq); +void tmu012_init(target_phys_addr_t base, int feat, uint32_t freq, + struct intc_source *ch0_irq, struct intc_source *ch1_irq, + struct intc_source *ch2_irq0, struct intc_source *ch2_irq1); + /* sh_serial.c */ #define SH_SERIAL_FEAT_SCIF (1 << 0) diff --git a/hw/sh7750.c b/hw/sh7750.c index c6702883a4..45a5c7f098 100644 --- a/hw/sh7750.c +++ b/hw/sh7750.c @@ -559,8 +559,11 @@ SH7750State *sh7750_init(CPUSH4State * cpu) tmu012_init(0x1fd80000, TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK, - s->periph_freq); - + s->periph_freq, + sh_intc_source(&s->intc, TMU0), + sh_intc_source(&s->intc, TMU1), + sh_intc_source(&s->intc, TMU2_TUNI), + sh_intc_source(&s->intc, TMU2_TICPI)); if (cpu_model & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) { sh_intc_register_sources(&s->intc, @@ -578,7 +581,10 @@ SH7750State *sh7750_init(CPUSH4State * cpu) sh_intc_register_sources(&s->intc, _INTC_ARRAY(vectors_tmu34), NULL, 0); - tmu012_init(0x1e100000, 0, s->periph_freq); + tmu012_init(0x1e100000, 0, s->periph_freq, + sh_intc_source(&s->intc, TMU3), + sh_intc_source(&s->intc, TMU4), + NULL, NULL); } if (cpu_model & (SH_CPU_SH7751_ALL)) { diff --git a/hw/sh_timer.c b/hw/sh_timer.c index 2247929c2d..df265d2d2a 100644 --- a/hw/sh_timer.c +++ b/hw/sh_timer.c @@ -33,23 +33,23 @@ typedef struct { uint32_t tcpr; int freq; int int_level; + int old_level; int feat; int enabled; - qemu_irq irq; + struct intc_source *irq; } sh_timer_state; /* Check all active timers, and schedule the next timer interrupt. */ static void sh_timer_update(sh_timer_state *s) { -#if 0 /* not yet */ - /* Update interrupts. */ - if (s->int_level && (s->tcr & TIMER_TCR_UNIE)) { - qemu_irq_raise(s->irq); - } else { - qemu_irq_lower(s->irq); - } -#endif + int new_level = s->int_level && (s->tcr & TIMER_TCR_UNIE); + + if (new_level != s->old_level) + sh_intc_toggle_source(s->irq, 0, new_level ? 1 : -1); + + s->old_level = s->int_level; + s->int_level = new_level; } static uint32_t sh_timer_read(void *opaque, target_phys_addr_t offset) @@ -185,7 +185,7 @@ static void sh_timer_tick(void *opaque) sh_timer_update(s); } -static void *sh_timer_init(uint32_t freq, int feat) +static void *sh_timer_init(uint32_t freq, int feat, struct intc_source *irq) { sh_timer_state *s; QEMUBH *bh; @@ -198,6 +198,7 @@ static void *sh_timer_init(uint32_t freq, int feat) s->tcpr = 0xdeadbeef; s->tcor = 0; s->enabled = 0; + s->irq = irq; bh = qemu_bh_new(sh_timer_tick, s); s->timer = ptimer_init(bh); @@ -305,7 +306,9 @@ static CPUWriteMemoryFunc *tmu012_writefn[] = { tmu012_write }; -void tmu012_init(uint32_t base, int feat, uint32_t freq) +void tmu012_init(target_phys_addr_t base, int feat, uint32_t freq, + struct intc_source *ch0_irq, struct intc_source *ch1_irq, + struct intc_source *ch2_irq0, struct intc_source *ch2_irq1) { int iomemtype; tmu012_state *s; @@ -314,10 +317,11 @@ void tmu012_init(uint32_t base, int feat, uint32_t freq) s = (tmu012_state *)qemu_mallocz(sizeof(tmu012_state)); s->base = base; s->feat = feat; - s->timer[0] = sh_timer_init(freq, timer_feat); - s->timer[1] = sh_timer_init(freq, timer_feat); + s->timer[0] = sh_timer_init(freq, timer_feat, ch0_irq); + s->timer[1] = sh_timer_init(freq, timer_feat, ch1_irq); if (feat & TMU012_FEAT_3CHAN) - s->timer[2] = sh_timer_init(freq, timer_feat | TIMER_FEAT_CAPT); + s->timer[2] = sh_timer_init(freq, timer_feat | TIMER_FEAT_CAPT, + ch2_irq0); /* ch2_irq1 not supported */ iomemtype = cpu_register_io_memory(0, tmu012_readfn, tmu012_writefn, s); cpu_register_physical_memory(base, 0x00001000, iomemtype);