aboutsummaryrefslogtreecommitdiff
path: root/hw/etraxfs_timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/etraxfs_timer.c')
-rw-r--r--hw/etraxfs_timer.c151
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);
}