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->tm.info; 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->tm.num - 4); }
static void pxa2xx_timer_tick4(void *opaque) { PXA2xxTimer4 *t = (PXA2xxTimer4 *) opaque; PXA2xxTimerInfo *i = (PXA2xxTimerInfo *) t->tm.info; 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_ns(vm_clock), t->tm.num - 4); if (i->events & 0xff0) qemu_irq_raise(i->irq4); }
static int pxa25x_timer_post_load(void *opaque, int version_id) { PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque; int64_t now; int i; now = qemu_get_clock_ns(vm_clock); pxa2xx_timer_update(s, now); if (pxa2xx_timer_has_tm4(s)) for (i = 0; i < 8; i ++) pxa2xx_timer_update4(s, now, i); return 0; }
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, &s->clock); qemu_get_be32s(f, &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_be32s(f, &s->tm4[i].oldclock); qemu_get_be32s(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 void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset, uint64_t value, unsigned size) { int i, tm = 0; PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque; switch (offset) { case OSMR3: tm ++; case OSMR2: tm ++; case OSMR1: tm ++; case OSMR0: s->timer[tm].value = value; pxa2xx_timer_update(s, qemu_get_clock_ns(vm_clock)); break; case OSMR11: tm ++; case OSMR10: tm ++; case OSMR9: tm ++; case OSMR8: tm ++; case OSMR7: tm ++; case OSMR6: tm ++; case OSMR5: tm ++; case OSMR4: if (!pxa2xx_timer_has_tm4(s)) goto badreg; s->tm4[tm].tm.value = value; pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm); break; case OSCR: s->oldclock = s->clock; s->lastload = qemu_get_clock_ns(vm_clock); s->clock = value; pxa2xx_timer_update(s, s->lastload); break; case OSCR11: tm ++; case OSCR10: tm ++; case OSCR9: tm ++; case OSCR8: tm ++; case OSCR7: tm ++; case OSCR6: tm ++; case OSCR5: tm ++; case OSCR4: if (!pxa2xx_timer_has_tm4(s)) goto badreg; s->tm4[tm].oldclock = s->tm4[tm].clock; s->tm4[tm].lastload = qemu_get_clock_ns(vm_clock); s->tm4[tm].clock = value; pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm); break; case OIER: s->irq_enabled = value & 0xfff; break; case OSSR: /* Status register */ value &= s->events; s->events &= ~value; for (i = 0; i < 4; i ++, value >>= 1) if (value & 1) qemu_irq_lower(s->timer[i].irq); if (pxa2xx_timer_has_tm4(s) && !(s->events & 0xff0) && value) qemu_irq_lower(s->irq4); break; case OWER: /* XXX: Reset on OSMR3 match? */ s->reset3 = value; break; case OMCR7: tm ++; case OMCR6: tm ++; case OMCR5: tm ++; case OMCR4: if (!pxa2xx_timer_has_tm4(s)) goto badreg; s->tm4[tm].control = value & 0x0ff; /* XXX Stop if running (shouldn't happen) */ if ((value & (1 << 7)) || tm == 0) s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7]; else { s->tm4[tm].freq = 0; pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm); } break; case OMCR11: tm ++; case OMCR10: tm ++; case OMCR9: tm ++; case OMCR8: tm += 4; if (!pxa2xx_timer_has_tm4(s)) goto badreg; s->tm4[tm].control = value & 0x3ff; /* XXX Stop if running (shouldn't happen) */ if ((value & (1 << 7)) || !(tm & 1)) s->tm4[tm].freq = pxa2xx_timer4_freq[(value & (1 << 8)) ? 0 : (value & 7)]; else { s->tm4[tm].freq = 0; pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm); } break; default: badreg: hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset); } }
static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset, uint32_t value) { int i, tm = 0; pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque; offset -= s->base; switch (offset) { case OSMR3: tm ++; case OSMR2: tm ++; case OSMR1: tm ++; case OSMR0: s->timer[tm].value = value; pxa2xx_timer_update(s, qemu_get_clock(vm_clock)); break; case OSMR11: tm ++; case OSMR10: tm ++; case OSMR9: tm ++; case OSMR8: tm ++; case OSMR7: tm ++; case OSMR6: tm ++; case OSMR5: tm ++; case OSMR4: if (!s->tm4) goto badreg; s->tm4[tm].tm.value = value; pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm); break; case OSCR: s->oldclock = s->clock; s->lastload = qemu_get_clock(vm_clock); s->clock = value; pxa2xx_timer_update(s, s->lastload); break; case OSCR11: tm ++; case OSCR10: tm ++; case OSCR9: tm ++; case OSCR8: tm ++; case OSCR7: tm ++; case OSCR6: tm ++; case OSCR5: tm ++; case OSCR4: if (!s->tm4) goto badreg; s->tm4[tm].oldclock = s->tm4[tm].clock; s->tm4[tm].lastload = qemu_get_clock(vm_clock); s->tm4[tm].clock = value; pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm); break; case OIER: s->irq_enabled = value & 0xfff; break; case OSSR: /* Status register */ s->events &= ~value; for (i = 0; i < 4; i ++, value >>= 1) { if (s->timer[i].level && (value & 1)) { s->timer[i].level = 0; qemu_irq_lower(s->timer[i].irq); } } if (s->tm4) { for (i = 0; i < 8; i ++, value >>= 1) if (s->tm4[i].tm.level && (value & 1)) s->tm4[i].tm.level = 0; if (!(s->events & 0xff0)) qemu_irq_lower(s->tm4->tm.irq); } break; case OWER: /* XXX: Reset on OSMR3 match? */ s->reset3 = value; break; case OMCR7: tm ++; case OMCR6: tm ++; case OMCR5: tm ++; case OMCR4: if (!s->tm4) goto badreg; s->tm4[tm].control = value & 0x0ff; /* XXX Stop if running (shouldn't happen) */ if ((value & (1 << 7)) || tm == 0) s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7]; else { s->tm4[tm].freq = 0; pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm); } break; case OMCR11: tm ++; case OMCR10: tm ++; case OMCR9: tm ++; case OMCR8: tm += 4; if (!s->tm4) goto badreg; s->tm4[tm].control = value & 0x3ff; /* XXX Stop if running (shouldn't happen) */ if ((value & (1 << 7)) || !(tm & 1)) s->tm4[tm].freq = pxa2xx_timer4_freq[(value & (1 << 8)) ? 0 : (value & 7)]; else { s->tm4[tm].freq = 0; pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm); } break; default: badreg: cpu_abort(cpu_single_env, "pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset); } }