* This code is licenced under the GPL.
*/
-#include "vl.h"
+#include "hw.h"
+#include "qemu-timer.h"
+#include "sysemu.h"
+#include "pxa.h"
#define OSMR0 0x00
#define OSMR1 0x04
};
struct pxa2xx_timer4_s {
- uint32_t value;
- int level;
- qemu_irq irq;
- QEMUTimer *qtimer;
- int num;
- void *info;
+ struct pxa2xx_timer0_s tm;
int32_t oldclock;
int32_t clock;
uint64_t lastload;
};
typedef struct {
- uint32_t base;
int32_t clock;
int32_t oldclock;
uint64_t lastload;
uint32_t events;
uint32_t irq_enabled;
uint32_t reset3;
- CPUState *cpustate;
- int64_t qemu_ticks;
uint32_t snapshot;
} pxa2xx_timer_info;
counter = counters[n];
if (!s->tm4[counter].freq) {
- qemu_del_timer(s->timer[n].qtimer);
+ qemu_del_timer(s->tm4[n].tm.qtimer);
return;
}
s->tm4[counter].lastload,
s->tm4[counter].freq, ticks_per_sec);
- new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].value - now_vm),
+ new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].tm.value - now_vm),
ticks_per_sec, s->tm4[counter].freq);
- qemu_mod_timer(s->timer[n].qtimer, new_qemu);
+ qemu_mod_timer(s->tm4[n].tm.qtimer, new_qemu);
}
static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
int tm = 0;
- offset -= s->base;
-
switch (offset) {
case OSMR3: tm ++;
case OSMR2: tm ++;
case OSMR4:
if (!s->tm4)
goto badreg;
- return s->tm4[tm].value;
+ return s->tm4[tm].tm.value;
case OSCR:
return s->clock + muldiv64(qemu_get_clock(vm_clock) -
s->lastload, s->freq, ticks_per_sec);
return s->snapshot;
default:
badreg:
- cpu_abort(cpu_single_env, "pxa2xx_timer_read: Bad offset "
- REG_FMT "\n", offset);
+ hw_error("pxa2xx_timer_read: Bad offset " REG_FMT "\n", offset);
}
return 0;
int i, tm = 0;
pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
- offset -= s->base;
-
switch (offset) {
case OSMR3: tm ++;
case OSMR2: tm ++;
case OSMR4:
if (!s->tm4)
goto badreg;
- s->tm4[tm].value = value;
+ s->tm4[tm].tm.value = value;
pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
break;
case OSCR:
}
if (s->tm4) {
for (i = 0; i < 8; i ++, value >>= 1)
- if (s->tm4[i].level && (value & 1))
- s->tm4[i].level = 0;
+ if (s->tm4[i].tm.level && (value & 1))
+ s->tm4[i].tm.level = 0;
if (!(s->events & 0xff0))
- qemu_irq_lower(s->tm4->irq);
+ qemu_irq_lower(s->tm4->tm.irq);
}
break;
case OWER: /* XXX: Reset on OSMR3 match? */
break;
default:
badreg:
- cpu_abort(cpu_single_env, "pxa2xx_timer_write: Bad offset "
- REG_FMT "\n", offset);
+ hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset);
}
}
if (t->num == 3)
if (i->reset3 & 1) {
i->reset3 = 0;
- cpu_reset(i->cpustate);
+ qemu_system_reset_request();
}
}
static void pxa2xx_timer_tick4(void *opaque)
{
struct pxa2xx_timer4_s *t = (struct pxa2xx_timer4_s *) opaque;
- pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->info;
+ pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->tm.info;
- pxa2xx_timer_tick(opaque);
+ pxa2xx_timer_tick(&t->tm);
if (t->control & (1 << 3))
t->clock = 0;
if (t->control & (1 << 6))
- pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->num - 4);
+ pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->tm.num - 4);
+}
+
+static void pxa2xx_timer_save(QEMUFile *f, void *opaque)
+{
+ pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
+ int i;
+
+ qemu_put_be32s(f, (uint32_t *) &s->clock);
+ qemu_put_be32s(f, (uint32_t *) &s->oldclock);
+ qemu_put_be64s(f, &s->lastload);
+
+ for (i = 0; i < 4; i ++) {
+ qemu_put_be32s(f, &s->timer[i].value);
+ qemu_put_be32(f, s->timer[i].level);
+ }
+ if (s->tm4)
+ for (i = 0; i < 8; i ++) {
+ qemu_put_be32s(f, &s->tm4[i].tm.value);
+ qemu_put_be32(f, s->tm4[i].tm.level);
+ qemu_put_sbe32s(f, &s->tm4[i].oldclock);
+ qemu_put_sbe32s(f, &s->tm4[i].clock);
+ qemu_put_be64s(f, &s->tm4[i].lastload);
+ qemu_put_be32s(f, &s->tm4[i].freq);
+ qemu_put_be32s(f, &s->tm4[i].control);
+ }
+
+ qemu_put_be32s(f, &s->events);
+ qemu_put_be32s(f, &s->irq_enabled);
+ qemu_put_be32s(f, &s->reset3);
+ qemu_put_be32s(f, &s->snapshot);
+}
+
+static int pxa2xx_timer_load(QEMUFile *f, void *opaque, int version_id)
+{
+ pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
+ int64_t now;
+ int i;
+
+ qemu_get_be32s(f, (uint32_t *) &s->clock);
+ qemu_get_be32s(f, (uint32_t *) &s->oldclock);
+ qemu_get_be64s(f, &s->lastload);
+
+ now = qemu_get_clock(vm_clock);
+ for (i = 0; i < 4; i ++) {
+ qemu_get_be32s(f, &s->timer[i].value);
+ s->timer[i].level = qemu_get_be32(f);
+ }
+ pxa2xx_timer_update(s, now);
+
+ if (s->tm4)
+ for (i = 0; i < 8; i ++) {
+ qemu_get_be32s(f, &s->tm4[i].tm.value);
+ s->tm4[i].tm.level = qemu_get_be32(f);
+ qemu_get_sbe32s(f, &s->tm4[i].oldclock);
+ qemu_get_sbe32s(f, &s->tm4[i].clock);
+ qemu_get_be64s(f, &s->tm4[i].lastload);
+ qemu_get_be32s(f, &s->tm4[i].freq);
+ qemu_get_be32s(f, &s->tm4[i].control);
+ pxa2xx_timer_update4(s, now, i);
+ }
+
+ qemu_get_be32s(f, &s->events);
+ qemu_get_be32s(f, &s->irq_enabled);
+ qemu_get_be32s(f, &s->reset3);
+ qemu_get_be32s(f, &s->snapshot);
+
+ return 0;
}
static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
- qemu_irq *irqs, CPUState *cpustate)
+ qemu_irq *irqs)
{
int i;
int iomemtype;
pxa2xx_timer_info *s;
s = (pxa2xx_timer_info *) qemu_mallocz(sizeof(pxa2xx_timer_info));
- s->base = base;
s->irq_enabled = 0;
s->oldclock = 0;
s->clock = 0;
s->lastload = qemu_get_clock(vm_clock);
s->reset3 = 0;
- s->cpustate = cpustate;
for (i = 0; i < 4; i ++) {
s->timer[i].value = 0;
iomemtype = cpu_register_io_memory(0, pxa2xx_timer_readfn,
pxa2xx_timer_writefn, s);
- cpu_register_physical_memory(base, 0x00000fff, iomemtype);
+ cpu_register_physical_memory(base, 0x00001000, iomemtype);
+
+ register_savevm("pxa2xx_timer", 0, 0,
+ pxa2xx_timer_save, pxa2xx_timer_load, s);
+
return s;
}
-void pxa25x_timer_init(target_phys_addr_t base,
- qemu_irq *irqs, CPUState *cpustate)
+void pxa25x_timer_init(target_phys_addr_t base, qemu_irq *irqs)
{
- pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs, cpustate);
+ pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs);
s->freq = PXA25X_FREQ;
s->tm4 = 0;
}
void pxa27x_timer_init(target_phys_addr_t base,
- qemu_irq *irqs, qemu_irq irq4, CPUState *cpustate)
+ qemu_irq *irqs, qemu_irq irq4)
{
- pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs, cpustate);
+ pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs);
int i;
s->freq = PXA27X_FREQ;
s->tm4 = (struct pxa2xx_timer4_s *) qemu_mallocz(8 *
sizeof(struct pxa2xx_timer4_s));
for (i = 0; i < 8; i ++) {
- s->tm4[i].value = 0;
- s->tm4[i].irq = irq4;
- s->tm4[i].info = s;
- s->tm4[i].num = i + 4;
- s->tm4[i].level = 0;
+ s->tm4[i].tm.value = 0;
+ s->tm4[i].tm.irq = irq4;
+ s->tm4[i].tm.info = s;
+ s->tm4[i].tm.num = i + 4;
+ s->tm4[i].tm.level = 0;
s->tm4[i].freq = 0;
s->tm4[i].control = 0x0;
- s->tm4[i].qtimer = qemu_new_timer(vm_clock,
+ s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock,
pxa2xx_timer_tick4, &s->tm4[i]);
}
}