diff options
Diffstat (limited to 'hw/etraxfs_timer.c')
-rw-r--r-- | hw/etraxfs_timer.c | 96 |
1 files changed, 61 insertions, 35 deletions
diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c index efa6bf9b61..bf7a23f7f9 100644 --- a/hw/etraxfs_timer.c +++ b/hw/etraxfs_timer.c @@ -26,6 +26,8 @@ #include "hw.h" #include "qemu-timer.h" +#define D(x) + void etrax_ack_irq(CPUState *env, uint32_t mask); #define R_TIME 0xb001e038 @@ -54,9 +56,18 @@ struct fs_timer_t { CPUState *env; qemu_irq *irq; uint32_t mask; + struct timeval last; }; -static struct fs_timer_t timer0; +static struct fs_timer_t timer[2]; + +static inline int timer_index(target_phys_addr_t addr) +{ + int t = 0; + if (addr >= 0xb005e000) + t = 1; + return t; +} /* diff two timevals. Return a single int in us. */ int diff_timeval_us(struct timeval *a, struct timeval *b) @@ -71,16 +82,20 @@ int diff_timeval_us(struct timeval *a, struct timeval *b) static uint32_t timer_readb (void *opaque, target_phys_addr_t addr) { - CPUState *env = opaque; + CPUState *env; uint32_t r = 0; - printf ("%s %x pc=%x\n", __func__, addr, env->pc); + + env = opaque; + D(printf ("%s %x pc=%x\n", __func__, addr, env->pc)); return r; } static uint32_t timer_readw (void *opaque, target_phys_addr_t addr) { - CPUState *env = opaque; + CPUState *env; uint32_t r = 0; - printf ("%s %x pc=%x\n", __func__, addr, env->pc); + + env = opaque; + D(printf ("%s %x pc=%x\n", __func__, addr, env->pc)); return r; } @@ -88,24 +103,25 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) { CPUState *env = opaque; uint32_t r = 0; + int t = timer_index(addr); switch (addr) { case R_TMR0_DATA: break; case R_TMR1_DATA: - printf ("R_TMR1_DATA\n"); + D(printf ("R_TMR1_DATA\n")); break; case R_TIME: { - static struct timeval last; struct timeval now; gettimeofday(&now, NULL); - if (!(last.tv_sec == 0 && last.tv_usec == 0)) { - r = diff_timeval_us(&now, &last); + if (!(timer[t].last.tv_sec == 0 + && timer[t].last.tv_usec == 0)) { + r = diff_timeval_us(&now, &timer[t].last); r *= 1000; /* convert to ns. */ r++; /* make sure we increase for each call. */ } - last = now; + timer[t].last = now; break; } @@ -125,14 +141,16 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) static void timer_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) { - CPUState *env = opaque; - printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); + CPUState *env; + env = opaque; + D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc)); } static void timer_writew (void *opaque, target_phys_addr_t addr, uint32_t value) { - CPUState *env = opaque; - printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); + CPUState *env; + env = opaque; + D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc)); } static void write_ctrl(struct fs_timer_t *t, uint32_t v) @@ -165,7 +183,7 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v) if (t->limit > 2048) { t->scale = 2048; - ptimer_set_period(timer0.ptimer, freq_hz / t->scale); + ptimer_set_period(t->ptimer, freq_hz / t->scale); } printf ("op=%d\n", op); @@ -187,11 +205,11 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v) } } -static void timer_ack_irq(void) +static void timer_ack_irq(struct fs_timer_t *t) { - if (!(r_intr & timer0.mask & rw_intr_mask)) { - qemu_irq_lower(timer0.irq[0]); - etrax_ack_irq(timer0.env, 1 << 0x1b); + if (!(r_intr & t->mask & rw_intr_mask)) { + qemu_irq_lower(t->irq[0]); + etrax_ack_irq(t->env, 1 << 0x1b); } } @@ -199,31 +217,33 @@ static void timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { CPUState *env = opaque; - printf ("%s %x %x pc=%x\n", - __func__, addr, value, env->pc); + int t = timer_index(addr); + + D(printf ("%s %x %x pc=%x\n", + __func__, addr, value, env->pc)); switch (addr) { case RW_TMR0_DIV: - printf ("RW_TMR0_DIV=%x\n", value); - timer0.limit = value; + D(printf ("RW_TMR0_DIV=%x\n", value)); + timer[t].limit = value; break; case RW_TMR0_CTRL: - printf ("RW_TMR0_CTRL=%x\n", value); - write_ctrl(&timer0, value); + D(printf ("RW_TMR0_CTRL=%x\n", value)); + write_ctrl(&timer[t], value); break; case RW_TMR1_DIV: - printf ("RW_TMR1_DIV=%x\n", value); + D(printf ("RW_TMR1_DIV=%x\n", value)); break; case RW_TMR1_CTRL: - printf ("RW_TMR1_CTRL=%x\n", value); + D(printf ("RW_TMR1_CTRL=%x\n", value)); break; case RW_INTR_MASK: - printf ("RW_INTR_MASK=%x\n", value); + D(printf ("RW_INTR_MASK=%x\n", value)); rw_intr_mask = value; break; case RW_ACK_INTR: r_intr &= ~value; - timer_ack_irq(); + timer_ack_irq(&timer[t]); break; default: printf ("%s %x %x pc=%x\n", @@ -247,7 +267,6 @@ static CPUWriteMemoryFunc *timer_write[] = { static void timer_irq(void *opaque) { struct fs_timer_t *t = opaque; - r_intr |= t->mask; if (t->mask & rw_intr_mask) { qemu_irq_raise(t->irq[0]); @@ -258,12 +277,19 @@ void etraxfs_timer_init(CPUState *env, qemu_irq *irqs) { int timer_regs; - timer0.bh = qemu_bh_new(timer_irq, &timer0); - timer0.ptimer = ptimer_init(timer0.bh); - timer0.irq = irqs + 0x1b; - timer0.mask = 1; - timer0.env = env; + timer[0].bh = qemu_bh_new(timer_irq, &timer[0]); + timer[0].ptimer = ptimer_init(timer[0].bh); + timer[0].irq = irqs + 0x1b; + timer[0].mask = 1; + timer[0].env = env; + + timer[1].bh = qemu_bh_new(timer_irq, &timer[1]); + timer[1].ptimer = ptimer_init(timer[1].bh); + timer[1].irq = irqs + 0x1b; + timer[1].mask = 1; + timer[1].env = env; timer_regs = cpu_register_io_memory(0, timer_read, timer_write, env); cpu_register_physical_memory (0xb001e000, 0x5c, timer_regs); + cpu_register_physical_memory (0xb005e000, 0x5c, timer_regs); } |