static void pl031_write(void * opaque, hwaddr offset, uint64_t value, unsigned size) { PL031State *s = (PL031State *)opaque; switch (offset) { case RTC_LR: s->tick_offset += value - pl031_get_count(s); pl031_set_alarm(s); break; case RTC_MR: s->mr = value; pl031_set_alarm(s); break; case RTC_IMSC: s->im = value & 1; DPRINTF("Interrupt mask %d\n", s->im); pl031_update(s); break; case RTC_ICR: /* The PL031 documentation (DDI0224B) states that the interrupt is cleared when bit 0 of the written value is set. However the arm926e documentation (DDI0287B) states that the interrupt is cleared when any value is written. */ DPRINTF("Interrupt cleared"); s->is = 0; pl031_update(s); break; case RTC_CR: /* Written value is ignored. */ break; case RTC_DR: case RTC_MIS: case RTC_RIS: qemu_log_mask(LOG_GUEST_ERROR, "pl031: write to read-only register at offset 0x%x\n", (int)offset); break; default: qemu_log_mask(LOG_GUEST_ERROR, "pl031_write: Bad offset 0x%x\n", (int)offset); break; } }
static void pl031_write(void * opaque, target_phys_addr_t offset, uint32_t value) { pl031_state *s = (pl031_state *)opaque; offset -= s->base; switch (offset) { case RTC_LR: s->tick_offset += value - pl031_get_count(s); pl031_set_alarm(s); break; case RTC_MR: s->mr = value; pl031_set_alarm(s); break; case RTC_IMSC: s->im = value & 1; DPRINTF("Interrupt mask %d\n", s->im); pl031_update(s); break; case RTC_ICR: /* The PL031 documentation (DDI0224B) states that the interupt is cleared when bit 0 of the written value is set. However the arm926e documentation (DDI0287B) states that the interrupt is cleared when any value is written. */ DPRINTF("Interrupt cleared"); s->is = 0; pl031_update(s); break; case RTC_CR: /* Written value is ignored. */ break; case RTC_DR: case RTC_MIS: case RTC_RIS: fprintf(stderr, "qemu: pl031_write: Unexpected offset 0x%x\n", (int)offset); break; default: cpu_abort(cpu_single_env, "pl031_write: Bad offset 0x%x\n", (int)offset); break; } }
static int pl031_post_load(void *opaque, int version_id) { PL031State *s = opaque; int64_t delta = qemu_clock_get_ns(rtc_clock) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); s->tick_offset = s->tick_offset_vmstate - delta / NANOSECONDS_PER_SECOND; pl031_set_alarm(s); return 0; }
static int pl031_post_load(void *opaque, int version_id) { pl031_state *s = opaque; int64_t delta = qemu_get_clock_ns(rtc_clock) - qemu_get_clock_ns(vm_clock); s->tick_offset = s->tick_offset_vmstate - delta / get_ticks_per_sec(); pl031_set_alarm(s); return 0; }