diff options
Diffstat (limited to 'hw/etraxfs_timer.c')
-rw-r--r-- | hw/etraxfs_timer.c | 151 |
1 files changed, 65 insertions, 86 deletions
diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c index e295f8a..7c9eb92 100644 --- a/hw/etraxfs_timer.c +++ b/hw/etraxfs_timer.c @@ -28,27 +28,28 @@ #define D(x) -#define R_TIME 0xb001e038 -#define RW_TMR0_DIV 0xb001e000 -#define R_TMR0_DATA 0xb001e004 -#define RW_TMR0_CTRL 0xb001e008 -#define RW_TMR1_DIV 0xb001e010 -#define R_TMR1_DATA 0xb001e014 -#define RW_TMR1_CTRL 0xb001e018 - -#define RW_WD_CTRL 0xb001e040 -#define RW_INTR_MASK 0xb001e048 -#define RW_ACK_INTR 0xb001e04c -#define R_INTR 0xb001e050 -#define R_MASKED_INTR 0xb001e054 +#define RW_TMR0_DIV 0x00 +#define R_TMR0_DATA 0x04 +#define RW_TMR0_CTRL 0x08 +#define RW_TMR1_DIV 0x10 +#define R_TMR1_DATA 0x14 +#define RW_TMR1_CTRL 0x18 +#define R_TIME 0x38 +#define RW_WD_CTRL 0x40 +#define RW_INTR_MASK 0x48 +#define RW_ACK_INTR 0x4c +#define R_INTR 0x50 +#define R_MASKED_INTR 0x54 struct fs_timer_t { + CPUState *env; + qemu_irq *irq; + target_phys_addr_t base; + QEMUBH *bh; + ptimer_state *ptimer; unsigned int limit; int scale; - ptimer_state *ptimer; - CPUState *env; - qemu_irq *irq; uint32_t mask; struct timeval last; @@ -57,16 +58,6 @@ struct fs_timer_t { uint32_t r_intr; }; -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) { @@ -78,31 +69,23 @@ int diff_timeval_us(struct timeval *a, struct timeval *b) return diff; } -static uint32_t timer_readb (void *opaque, target_phys_addr_t addr) +static uint32_t timer_rinvalid (void *opaque, target_phys_addr_t addr) { - CPUState *env; - uint32_t r = 0; - - 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; - uint32_t r = 0; - - env = opaque; - D(printf ("%s %x pc=%x\n", __func__, addr, env->pc)); - return r; + struct fs_timer_t *t = opaque; + CPUState *env = t->env; + cpu_abort(env, "Unsupported short access. reg=%x pc=%x.\n", + addr, env->pc); + return 0; } static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) { - CPUState *env = opaque; + struct fs_timer_t *t = opaque; + D(CPUState *env = t->env); uint32_t r = 0; - int t = timer_index(addr); + /* Make addr relative to this instances base. */ + addr -= t->base; switch (addr) { case R_TMR0_DATA: break; @@ -113,21 +96,21 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) { struct timeval now; gettimeofday(&now, NULL); - if (!(timer[t].last.tv_sec == 0 - && timer[t].last.tv_usec == 0)) { - r = diff_timeval_us(&now, &timer[t].last); + if (!(t->last.tv_sec == 0 + && t->last.tv_usec == 0)) { + r = diff_timeval_us(&now, &t->last); r *= 1000; /* convert to ns. */ r++; /* make sure we increase for each call. */ } - timer[t].last = now; + t->last = now; break; } case RW_INTR_MASK: - r = timer[t].rw_intr_mask; + r = t->rw_intr_mask; break; case R_MASKED_INTR: - r = timer[t].r_intr & timer[t].rw_intr_mask; + r = t->r_intr & t->rw_intr_mask; break; default: D(printf ("%s %x p=%x\n", __func__, addr, env->pc)); @@ -137,18 +120,12 @@ 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) +timer_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value) { - 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; - env = opaque; - D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc)); + struct fs_timer_t *t = opaque; + CPUState *env = t->env; + cpu_abort(env, "Unsupported short access. reg=%x pc=%x.\n", + addr, env->pc); } static void write_ctrl(struct fs_timer_t *t, uint32_t v) @@ -212,20 +189,22 @@ static void timer_ack_irq(struct fs_timer_t *t) static void timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { - CPUState *env = opaque; - int t = timer_index(addr); + struct fs_timer_t *t = opaque; + CPUState *env = t->env; D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc)); + /* Make addr relative to this instances base. */ + addr -= t->base; switch (addr) { case RW_TMR0_DIV: D(printf ("RW_TMR0_DIV=%x\n", value)); - timer[t].limit = value; + t->limit = value; break; case RW_TMR0_CTRL: D(printf ("RW_TMR0_CTRL=%x\n", value)); - write_ctrl(&timer[t], value); + write_ctrl(t, value); break; case RW_TMR1_DIV: D(printf ("RW_TMR1_DIV=%x\n", value)); @@ -235,14 +214,14 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) break; case RW_INTR_MASK: D(printf ("RW_INTR_MASK=%x\n", value)); - timer[t].rw_intr_mask = value; + t->rw_intr_mask = value; break; case RW_WD_CTRL: D(printf ("RW_WD_CTRL=%x\n", value)); break; case RW_ACK_INTR: - timer[t].r_intr &= ~value; - timer_ack_irq(&timer[t]); + t->r_intr &= ~value; + timer_ack_irq(t); break; default: printf ("%s %x %x pc=%x\n", @@ -252,14 +231,14 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) } static CPUReadMemoryFunc *timer_read[] = { - &timer_readb, - &timer_readw, + &timer_rinvalid, + &timer_rinvalid, &timer_readl, }; static CPUWriteMemoryFunc *timer_write[] = { - &timer_writeb, - &timer_writew, + &timer_winvalid, + &timer_winvalid, &timer_writel, }; @@ -273,23 +252,23 @@ static void timer_irq(void *opaque) } } -void etraxfs_timer_init(CPUState *env, qemu_irq *irqs) +void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, + target_phys_addr_t base) { + static struct fs_timer_t *t; int timer_regs; - timer[0].bh = qemu_bh_new(timer_irq, &timer[0]); - timer[0].ptimer = ptimer_init(timer[0].bh); - timer[0].irq = irqs + 26; - timer[0].mask = 1; - timer[0].env = env; + t = qemu_mallocz(sizeof *t); + if (!t) + return; - timer[1].bh = qemu_bh_new(timer_irq, &timer[1]); - timer[1].ptimer = ptimer_init(timer[1].bh); - timer[1].irq = irqs + 26; - timer[1].mask = 1; - timer[1].env = env; + t->bh = qemu_bh_new(timer_irq, t); + t->ptimer = ptimer_init(t->bh); + t->irq = irqs + 26; + t->mask = 1; + t->env = env; + t->base = base; - 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); + timer_regs = cpu_register_io_memory(0, timer_read, timer_write, t); + cpu_register_physical_memory (base, 0x5c, timer_regs); } |