From: Philippe Mathieu-Daudé Date: Thu, 3 Oct 2019 23:03:52 +0000 (+0200) Subject: hw: Move PL031 device from hw/timer/ to hw/rtc/ subdirectory X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=877c181cd41e024ba1d076f96efe3c5777938846;p=qemu.git hw: Move PL031 device from hw/timer/ to hw/rtc/ subdirectory The PL031 is a Real Time Clock, not a timer. Move it under the hw/rtc/ subdirectory. Reviewed-by: Alistair Francis Signed-off-by: Philippe Mathieu-Daudé Acked-by: Peter Maydell Message-Id: <20191003230404.19384-3-philmd@redhat.com> Signed-off-by: Laurent Vivier --- diff --git a/MAINTAINERS b/MAINTAINERS index ed41d7d1b6..2e13ba4628 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -495,8 +495,8 @@ F: hw/intc/pl190.c F: hw/sd/pl181.c F: hw/ssi/pl022.c F: include/hw/ssi/pl022.h -F: hw/timer/pl031.c -F: include/hw/timer/pl031.h +F: hw/rtc/pl031.c +F: include/hw/rtc/pl031.h F: include/hw/arm/primecell.h F: hw/timer/cmsdk-apb-timer.c F: include/hw/timer/cmsdk-apb-timer.h diff --git a/Makefile.objs b/Makefile.objs index abcbd89654..11ba1a36bd 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -173,6 +173,7 @@ trace-events-subdirs += hw/pci-host trace-events-subdirs += hw/ppc trace-events-subdirs += hw/rdma trace-events-subdirs += hw/rdma/vmw +trace-events-subdirs += hw/rtc trace-events-subdirs += hw/s390x trace-events-subdirs += hw/scsi trace-events-subdirs += hw/sd diff --git a/hw/Kconfig b/hw/Kconfig index b45db3c813..4b53fee4d0 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -27,6 +27,7 @@ source pci-host/Kconfig source pcmcia/Kconfig source pci/Kconfig source rdma/Kconfig +source rtc/Kconfig source scsi/Kconfig source sd/Kconfig source semihosting/Kconfig diff --git a/hw/Makefile.objs b/hw/Makefile.objs index ece6cc3755..fd9750e5f2 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -26,6 +26,7 @@ devices-dirs-y += nvram/ devices-dirs-y += pci/ devices-dirs-$(CONFIG_PCI) += pci-bridge/ pci-host/ devices-dirs-y += pcmcia/ +devices-dirs-y += rtc/ devices-dirs-$(CONFIG_SCSI) += scsi/ devices-dirs-y += sd/ devices-dirs-y += ssi/ diff --git a/hw/arm/musca.c b/hw/arm/musca.c index 68db4b5b38..ba99dd1941 100644 --- a/hw/arm/musca.c +++ b/hw/arm/musca.c @@ -32,7 +32,7 @@ #include "hw/misc/tz-mpc.h" #include "hw/misc/tz-ppc.h" #include "hw/misc/unimp.h" -#include "hw/timer/pl031.h" +#include "hw/rtc/pl031.h" #define MUSCA_NUMIRQ_MAX 96 #define MUSCA_PPC_MAX 3 diff --git a/hw/rtc/Kconfig b/hw/rtc/Kconfig new file mode 100644 index 0000000000..8a4383bca9 --- /dev/null +++ b/hw/rtc/Kconfig @@ -0,0 +1,2 @@ +config PL031 + bool diff --git a/hw/rtc/Makefile.objs b/hw/rtc/Makefile.objs new file mode 100644 index 0000000000..3e1eb42563 --- /dev/null +++ b/hw/rtc/Makefile.objs @@ -0,0 +1 @@ +common-obj-$(CONFIG_PL031) += pl031.o diff --git a/hw/rtc/pl031.c b/hw/rtc/pl031.c new file mode 100644 index 0000000000..3a982752a2 --- /dev/null +++ b/hw/rtc/pl031.c @@ -0,0 +1,344 @@ +/* + * ARM AMBA PrimeCell PL031 RTC + * + * Copyright (c) 2007 CodeSourcery + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "hw/rtc/pl031.h" +#include "migration/vmstate.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/sysbus.h" +#include "qemu/timer.h" +#include "sysemu/sysemu.h" +#include "qemu/cutils.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "trace.h" + +#define RTC_DR 0x00 /* Data read register */ +#define RTC_MR 0x04 /* Match register */ +#define RTC_LR 0x08 /* Data load register */ +#define RTC_CR 0x0c /* Control register */ +#define RTC_IMSC 0x10 /* Interrupt mask and set register */ +#define RTC_RIS 0x14 /* Raw interrupt status register */ +#define RTC_MIS 0x18 /* Masked interrupt status register */ +#define RTC_ICR 0x1c /* Interrupt clear register */ + +static const unsigned char pl031_id[] = { + 0x31, 0x10, 0x14, 0x00, /* Device ID */ + 0x0d, 0xf0, 0x05, 0xb1 /* Cell ID */ +}; + +static void pl031_update(PL031State *s) +{ + uint32_t flags = s->is & s->im; + + trace_pl031_irq_state(flags); + qemu_set_irq(s->irq, flags); +} + +static void pl031_interrupt(void * opaque) +{ + PL031State *s = (PL031State *)opaque; + + s->is = 1; + trace_pl031_alarm_raised(); + pl031_update(s); +} + +static uint32_t pl031_get_count(PL031State *s) +{ + int64_t now = qemu_clock_get_ns(rtc_clock); + return s->tick_offset + now / NANOSECONDS_PER_SECOND; +} + +static void pl031_set_alarm(PL031State *s) +{ + uint32_t ticks; + + /* The timer wraps around. This subtraction also wraps in the same way, + and gives correct results when alarm < now_ticks. */ + ticks = s->mr - pl031_get_count(s); + trace_pl031_set_alarm(ticks); + if (ticks == 0) { + timer_del(s->timer); + pl031_interrupt(s); + } else { + int64_t now = qemu_clock_get_ns(rtc_clock); + timer_mod(s->timer, now + (int64_t)ticks * NANOSECONDS_PER_SECOND); + } +} + +static uint64_t pl031_read(void *opaque, hwaddr offset, + unsigned size) +{ + PL031State *s = (PL031State *)opaque; + uint64_t r; + + switch (offset) { + case RTC_DR: + r = pl031_get_count(s); + break; + case RTC_MR: + r = s->mr; + break; + case RTC_IMSC: + r = s->im; + break; + case RTC_RIS: + r = s->is; + break; + case RTC_LR: + r = s->lr; + break; + case RTC_CR: + /* RTC is permanently enabled. */ + r = 1; + break; + case RTC_MIS: + r = s->is & s->im; + break; + case 0xfe0 ... 0xfff: + r = pl031_id[(offset - 0xfe0) >> 2]; + break; + case RTC_ICR: + qemu_log_mask(LOG_GUEST_ERROR, + "pl031: read of write-only register at offset 0x%x\n", + (int)offset); + r = 0; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "pl031_read: Bad offset 0x%x\n", (int)offset); + r = 0; + break; + } + + trace_pl031_read(offset, r); + return r; +} + +static void pl031_write(void * opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + PL031State *s = (PL031State *)opaque; + + trace_pl031_write(offset, value); + + 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; + 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. */ + 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 const MemoryRegionOps pl031_ops = { + .read = pl031_read, + .write = pl031_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void pl031_init(Object *obj) +{ + PL031State *s = PL031(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); + struct tm tm; + + memory_region_init_io(&s->iomem, obj, &pl031_ops, s, "pl031", 0x1000); + sysbus_init_mmio(dev, &s->iomem); + + sysbus_init_irq(dev, &s->irq); + qemu_get_timedate(&tm, 0); + s->tick_offset = mktimegm(&tm) - + qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND; + + s->timer = timer_new_ns(rtc_clock, pl031_interrupt, s); +} + +static int pl031_pre_save(void *opaque) +{ + PL031State *s = opaque; + + /* + * The PL031 device model code uses the tick_offset field, which is + * the offset between what the guest RTC should read and what the + * QEMU rtc_clock reads: + * guest_rtc = rtc_clock + tick_offset + * and so + * tick_offset = guest_rtc - rtc_clock + * + * We want to migrate this offset, which sounds straightforward. + * Unfortunately older versions of QEMU migrated a conversion of this + * offset into an offset from the vm_clock. (This was in turn an + * attempt to be compatible with even older QEMU versions, but it + * has incorrect behaviour if the rtc_clock is not the same as the + * vm_clock.) So we put the actual tick_offset into a migration + * subsection, and the backwards-compatible time-relative-to-vm_clock + * in the main migration state. + * + * Calculate base time relative to QEMU_CLOCK_VIRTUAL: + */ + int64_t delta = qemu_clock_get_ns(rtc_clock) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + s->tick_offset_vmstate = s->tick_offset + delta / NANOSECONDS_PER_SECOND; + + return 0; +} + +static int pl031_pre_load(void *opaque) +{ + PL031State *s = opaque; + + s->tick_offset_migrated = false; + return 0; +} + +static int pl031_post_load(void *opaque, int version_id) +{ + PL031State *s = opaque; + + /* + * If we got the tick_offset subsection, then we can just use + * the value in that. Otherwise the source is an older QEMU and + * has given us the offset from the vm_clock; convert it back to + * an offset from the rtc_clock. This will cause time to incorrectly + * go backwards compared to the host RTC, but this is unavoidable. + */ + + if (!s->tick_offset_migrated) { + 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_tick_offset_post_load(void *opaque, int version_id) +{ + PL031State *s = opaque; + + s->tick_offset_migrated = true; + return 0; +} + +static bool pl031_tick_offset_needed(void *opaque) +{ + PL031State *s = opaque; + + return s->migrate_tick_offset; +} + +static const VMStateDescription vmstate_pl031_tick_offset = { + .name = "pl031/tick-offset", + .version_id = 1, + .minimum_version_id = 1, + .needed = pl031_tick_offset_needed, + .post_load = pl031_tick_offset_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT32(tick_offset, PL031State), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_pl031 = { + .name = "pl031", + .version_id = 1, + .minimum_version_id = 1, + .pre_save = pl031_pre_save, + .pre_load = pl031_pre_load, + .post_load = pl031_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT32(tick_offset_vmstate, PL031State), + VMSTATE_UINT32(mr, PL031State), + VMSTATE_UINT32(lr, PL031State), + VMSTATE_UINT32(cr, PL031State), + VMSTATE_UINT32(im, PL031State), + VMSTATE_UINT32(is, PL031State), + VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription*[]) { + &vmstate_pl031_tick_offset, + NULL + } +}; + +static Property pl031_properties[] = { + /* + * True to correctly migrate the tick offset of the RTC. False to + * obtain backward migration compatibility with older QEMU versions, + * at the expense of the guest RTC going backwards compared with the + * host RTC when the VM is saved/restored if using -rtc host. + * (Even if set to 'true' older QEMU can migrate forward to newer QEMU; + * 'false' also permits newer QEMU to migrate to older QEMU.) + */ + DEFINE_PROP_BOOL("migrate-tick-offset", + PL031State, migrate_tick_offset, true), + DEFINE_PROP_END_OF_LIST() +}; + +static void pl031_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->vmsd = &vmstate_pl031; + dc->props = pl031_properties; +} + +static const TypeInfo pl031_info = { + .name = TYPE_PL031, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(PL031State), + .instance_init = pl031_init, + .class_init = pl031_class_init, +}; + +static void pl031_register_types(void) +{ + type_register_static(&pl031_info); +} + +type_init(pl031_register_types) diff --git a/hw/rtc/trace-events b/hw/rtc/trace-events new file mode 100644 index 0000000000..54c94ac557 --- /dev/null +++ b/hw/rtc/trace-events @@ -0,0 +1,8 @@ +# See docs/devel/tracing.txt for syntax documentation. + +# pl031.c +pl031_irq_state(int level) "irq state %d" +pl031_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" +pl031_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" +pl031_alarm_raised(void) "alarm raised" +pl031_set_alarm(uint32_t ticks) "alarm set for %u ticks" diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig index eefc95f35e..27c5dce09e 100644 --- a/hw/timer/Kconfig +++ b/hw/timer/Kconfig @@ -27,9 +27,6 @@ config M41T80 config M48T59 bool -config PL031 - bool - config TWL92230 bool depends on I2C diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs index f407523aa4..9f64f6e11e 100644 --- a/hw/timer/Makefile.objs +++ b/hw/timer/Makefile.objs @@ -11,7 +11,6 @@ common-obj-$(CONFIG_M48T59) += m48t59.o ifeq ($(CONFIG_ISA_BUS),y) common-obj-$(CONFIG_M48T59) += m48t59-isa.o endif -common-obj-$(CONFIG_PL031) += pl031.o common-obj-$(CONFIG_PUV3) += puv3_ost.o common-obj-$(CONFIG_TWL92230) += twl92230.o common-obj-$(CONFIG_XILINX) += xilinx_timer.o diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c deleted file mode 100644 index 2b3e261006..0000000000 --- a/hw/timer/pl031.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * ARM AMBA PrimeCell PL031 RTC - * - * Copyright (c) 2007 CodeSourcery - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ - -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "hw/timer/pl031.h" -#include "migration/vmstate.h" -#include "hw/irq.h" -#include "hw/qdev-properties.h" -#include "hw/sysbus.h" -#include "qemu/timer.h" -#include "sysemu/sysemu.h" -#include "qemu/cutils.h" -#include "qemu/log.h" -#include "qemu/module.h" -#include "trace.h" - -#define RTC_DR 0x00 /* Data read register */ -#define RTC_MR 0x04 /* Match register */ -#define RTC_LR 0x08 /* Data load register */ -#define RTC_CR 0x0c /* Control register */ -#define RTC_IMSC 0x10 /* Interrupt mask and set register */ -#define RTC_RIS 0x14 /* Raw interrupt status register */ -#define RTC_MIS 0x18 /* Masked interrupt status register */ -#define RTC_ICR 0x1c /* Interrupt clear register */ - -static const unsigned char pl031_id[] = { - 0x31, 0x10, 0x14, 0x00, /* Device ID */ - 0x0d, 0xf0, 0x05, 0xb1 /* Cell ID */ -}; - -static void pl031_update(PL031State *s) -{ - uint32_t flags = s->is & s->im; - - trace_pl031_irq_state(flags); - qemu_set_irq(s->irq, flags); -} - -static void pl031_interrupt(void * opaque) -{ - PL031State *s = (PL031State *)opaque; - - s->is = 1; - trace_pl031_alarm_raised(); - pl031_update(s); -} - -static uint32_t pl031_get_count(PL031State *s) -{ - int64_t now = qemu_clock_get_ns(rtc_clock); - return s->tick_offset + now / NANOSECONDS_PER_SECOND; -} - -static void pl031_set_alarm(PL031State *s) -{ - uint32_t ticks; - - /* The timer wraps around. This subtraction also wraps in the same way, - and gives correct results when alarm < now_ticks. */ - ticks = s->mr - pl031_get_count(s); - trace_pl031_set_alarm(ticks); - if (ticks == 0) { - timer_del(s->timer); - pl031_interrupt(s); - } else { - int64_t now = qemu_clock_get_ns(rtc_clock); - timer_mod(s->timer, now + (int64_t)ticks * NANOSECONDS_PER_SECOND); - } -} - -static uint64_t pl031_read(void *opaque, hwaddr offset, - unsigned size) -{ - PL031State *s = (PL031State *)opaque; - uint64_t r; - - switch (offset) { - case RTC_DR: - r = pl031_get_count(s); - break; - case RTC_MR: - r = s->mr; - break; - case RTC_IMSC: - r = s->im; - break; - case RTC_RIS: - r = s->is; - break; - case RTC_LR: - r = s->lr; - break; - case RTC_CR: - /* RTC is permanently enabled. */ - r = 1; - break; - case RTC_MIS: - r = s->is & s->im; - break; - case 0xfe0 ... 0xfff: - r = pl031_id[(offset - 0xfe0) >> 2]; - break; - case RTC_ICR: - qemu_log_mask(LOG_GUEST_ERROR, - "pl031: read of write-only register at offset 0x%x\n", - (int)offset); - r = 0; - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, - "pl031_read: Bad offset 0x%x\n", (int)offset); - r = 0; - break; - } - - trace_pl031_read(offset, r); - return r; -} - -static void pl031_write(void * opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - PL031State *s = (PL031State *)opaque; - - trace_pl031_write(offset, value); - - 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; - 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. */ - 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 const MemoryRegionOps pl031_ops = { - .read = pl031_read, - .write = pl031_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void pl031_init(Object *obj) -{ - PL031State *s = PL031(obj); - SysBusDevice *dev = SYS_BUS_DEVICE(obj); - struct tm tm; - - memory_region_init_io(&s->iomem, obj, &pl031_ops, s, "pl031", 0x1000); - sysbus_init_mmio(dev, &s->iomem); - - sysbus_init_irq(dev, &s->irq); - qemu_get_timedate(&tm, 0); - s->tick_offset = mktimegm(&tm) - - qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND; - - s->timer = timer_new_ns(rtc_clock, pl031_interrupt, s); -} - -static int pl031_pre_save(void *opaque) -{ - PL031State *s = opaque; - - /* - * The PL031 device model code uses the tick_offset field, which is - * the offset between what the guest RTC should read and what the - * QEMU rtc_clock reads: - * guest_rtc = rtc_clock + tick_offset - * and so - * tick_offset = guest_rtc - rtc_clock - * - * We want to migrate this offset, which sounds straightforward. - * Unfortunately older versions of QEMU migrated a conversion of this - * offset into an offset from the vm_clock. (This was in turn an - * attempt to be compatible with even older QEMU versions, but it - * has incorrect behaviour if the rtc_clock is not the same as the - * vm_clock.) So we put the actual tick_offset into a migration - * subsection, and the backwards-compatible time-relative-to-vm_clock - * in the main migration state. - * - * Calculate base time relative to QEMU_CLOCK_VIRTUAL: - */ - int64_t delta = qemu_clock_get_ns(rtc_clock) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - s->tick_offset_vmstate = s->tick_offset + delta / NANOSECONDS_PER_SECOND; - - return 0; -} - -static int pl031_pre_load(void *opaque) -{ - PL031State *s = opaque; - - s->tick_offset_migrated = false; - return 0; -} - -static int pl031_post_load(void *opaque, int version_id) -{ - PL031State *s = opaque; - - /* - * If we got the tick_offset subsection, then we can just use - * the value in that. Otherwise the source is an older QEMU and - * has given us the offset from the vm_clock; convert it back to - * an offset from the rtc_clock. This will cause time to incorrectly - * go backwards compared to the host RTC, but this is unavoidable. - */ - - if (!s->tick_offset_migrated) { - 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_tick_offset_post_load(void *opaque, int version_id) -{ - PL031State *s = opaque; - - s->tick_offset_migrated = true; - return 0; -} - -static bool pl031_tick_offset_needed(void *opaque) -{ - PL031State *s = opaque; - - return s->migrate_tick_offset; -} - -static const VMStateDescription vmstate_pl031_tick_offset = { - .name = "pl031/tick-offset", - .version_id = 1, - .minimum_version_id = 1, - .needed = pl031_tick_offset_needed, - .post_load = pl031_tick_offset_post_load, - .fields = (VMStateField[]) { - VMSTATE_UINT32(tick_offset, PL031State), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription vmstate_pl031 = { - .name = "pl031", - .version_id = 1, - .minimum_version_id = 1, - .pre_save = pl031_pre_save, - .pre_load = pl031_pre_load, - .post_load = pl031_post_load, - .fields = (VMStateField[]) { - VMSTATE_UINT32(tick_offset_vmstate, PL031State), - VMSTATE_UINT32(mr, PL031State), - VMSTATE_UINT32(lr, PL031State), - VMSTATE_UINT32(cr, PL031State), - VMSTATE_UINT32(im, PL031State), - VMSTATE_UINT32(is, PL031State), - VMSTATE_END_OF_LIST() - }, - .subsections = (const VMStateDescription*[]) { - &vmstate_pl031_tick_offset, - NULL - } -}; - -static Property pl031_properties[] = { - /* - * True to correctly migrate the tick offset of the RTC. False to - * obtain backward migration compatibility with older QEMU versions, - * at the expense of the guest RTC going backwards compared with the - * host RTC when the VM is saved/restored if using -rtc host. - * (Even if set to 'true' older QEMU can migrate forward to newer QEMU; - * 'false' also permits newer QEMU to migrate to older QEMU.) - */ - DEFINE_PROP_BOOL("migrate-tick-offset", - PL031State, migrate_tick_offset, true), - DEFINE_PROP_END_OF_LIST() -}; - -static void pl031_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->vmsd = &vmstate_pl031; - dc->props = pl031_properties; -} - -static const TypeInfo pl031_info = { - .name = TYPE_PL031, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(PL031State), - .instance_init = pl031_init, - .class_init = pl031_class_init, -}; - -static void pl031_register_types(void) -{ - type_register_static(&pl031_info); -} - -type_init(pl031_register_types) diff --git a/hw/timer/trace-events b/hw/timer/trace-events index db02a9142c..6936fe8573 100644 --- a/hw/timer/trace-events +++ b/hw/timer/trace-events @@ -80,10 +80,3 @@ xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec # nrf51_timer.c nrf51_timer_read(uint64_t addr, uint32_t value, unsigned size) "read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" nrf51_timer_write(uint64_t addr, uint32_t value, unsigned size) "write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" - -# pl031.c -pl031_irq_state(int level) "irq state %d" -pl031_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -pl031_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" -pl031_alarm_raised(void) "alarm raised" -pl031_set_alarm(uint32_t ticks) "alarm set for %u ticks" diff --git a/include/hw/rtc/pl031.h b/include/hw/rtc/pl031.h new file mode 100644 index 0000000000..e3cb1d646f --- /dev/null +++ b/include/hw/rtc/pl031.h @@ -0,0 +1,47 @@ +/* + * ARM AMBA PrimeCell PL031 RTC + * + * Copyright (c) 2007 CodeSourcery + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ + +#ifndef HW_RTC_PL031_H +#define HW_RTC_PL031_H + +#include "hw/sysbus.h" +#include "qemu/timer.h" + +#define TYPE_PL031 "pl031" +#define PL031(obj) OBJECT_CHECK(PL031State, (obj), TYPE_PL031) + +typedef struct PL031State { + SysBusDevice parent_obj; + + MemoryRegion iomem; + QEMUTimer *timer; + qemu_irq irq; + + /* + * Needed to preserve the tick_count across migration, even if the + * absolute value of the rtc_clock is different on the source and + * destination. + */ + uint32_t tick_offset_vmstate; + uint32_t tick_offset; + bool tick_offset_migrated; + bool migrate_tick_offset; + + uint32_t mr; + uint32_t lr; + uint32_t cr; + uint32_t im; + uint32_t is; +} PL031State; + +#endif diff --git a/include/hw/timer/pl031.h b/include/hw/timer/pl031.h deleted file mode 100644 index 8c3f555ee2..0000000000 --- a/include/hw/timer/pl031.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * ARM AMBA PrimeCell PL031 RTC - * - * Copyright (c) 2007 CodeSourcery - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ - -#ifndef HW_TIMER_PL031_H -#define HW_TIMER_PL031_H - -#include "hw/sysbus.h" - -#define TYPE_PL031 "pl031" -#define PL031(obj) OBJECT_CHECK(PL031State, (obj), TYPE_PL031) - -typedef struct PL031State { - SysBusDevice parent_obj; - - MemoryRegion iomem; - QEMUTimer *timer; - qemu_irq irq; - - /* - * Needed to preserve the tick_count across migration, even if the - * absolute value of the rtc_clock is different on the source and - * destination. - */ - uint32_t tick_offset_vmstate; - uint32_t tick_offset; - bool tick_offset_migrated; - bool migrate_tick_offset; - - uint32_t mr; - uint32_t lr; - uint32_t cr; - uint32_t im; - uint32_t is; -} PL031State; - -#endif