aboutsummaryrefslogtreecommitdiff
path: root/hw/timer
diff options
context:
space:
mode:
Diffstat (limited to 'hw/timer')
-rw-r--r--hw/timer/Kconfig6
-rw-r--r--hw/timer/a9gtimer.c2
-rw-r--r--hw/timer/allwinner-a10-pit.c4
-rw-r--r--hw/timer/arm_mptimer.c2
-rw-r--r--hw/timer/arm_timer.c2
-rw-r--r--hw/timer/armv7m_systick.c2
-rw-r--r--hw/timer/aspeed_timer.c273
-rw-r--r--hw/timer/avr_timer16.c2
-rw-r--r--hw/timer/bcm2835_systmr.c2
-rw-r--r--hw/timer/cadence_ttc.c2
-rw-r--r--hw/timer/cmsdk-apb-dualtimer.c2
-rw-r--r--hw/timer/cmsdk-apb-timer.c2
-rw-r--r--hw/timer/digic-timer.c2
-rw-r--r--hw/timer/exynos4210_mct.c2
-rw-r--r--hw/timer/exynos4210_pwm.c2
-rw-r--r--hw/timer/grlib_gptimer.c2
-rw-r--r--hw/timer/hpet.c241
-rw-r--r--hw/timer/i8254.c2
-rw-r--r--hw/timer/i8254_common.c2
-rw-r--r--hw/timer/ibex_timer.c2
-rw-r--r--hw/timer/imx_epit.c2
-rw-r--r--hw/timer/imx_gpt.c31
-rw-r--r--hw/timer/meson.build2
-rw-r--r--hw/timer/mss-timer.c2
-rw-r--r--hw/timer/npcm7xx_timer.c2
-rw-r--r--hw/timer/nrf51_timer.c2
-rw-r--r--hw/timer/pxa2xx_timer.c82
-rw-r--r--hw/timer/renesas_cmt.c2
-rw-r--r--hw/timer/renesas_tmr.c2
-rw-r--r--hw/timer/sh_timer.c2
-rw-r--r--hw/timer/sifive_pwm.c2
-rw-r--r--hw/timer/slavio_timer.c2
-rw-r--r--hw/timer/sse-counter.c2
-rw-r--r--hw/timer/sse-timer.c2
-rw-r--r--hw/timer/stellaris-gptm.c2
-rw-r--r--hw/timer/stm32f2xx_timer.c2
-rw-r--r--hw/timer/trace-events2
-rw-r--r--hw/timer/xilinx_timer.c43
38 files changed, 505 insertions, 237 deletions
diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig
index c96fd5d..b3d823c 100644
--- a/hw/timer/Kconfig
+++ b/hw/timer/Kconfig
@@ -12,6 +12,12 @@ config A9_GTIMER
config HPET
bool
default y if PC
+ # The HPET has both a Rust and a C implementation
+ select HPET_C if !HAVE_RUST
+ select X_HPET_RUST if HAVE_RUST
+
+config HPET_C
+ bool
config I8254
bool
diff --git a/hw/timer/a9gtimer.c b/hw/timer/a9gtimer.c
index 9835c35..690140f 100644
--- a/hw/timer/a9gtimer.c
+++ b/hw/timer/a9gtimer.c
@@ -377,7 +377,7 @@ static const Property a9_gtimer_properties[] = {
DEFINE_PROP_UINT32("num-cpu", A9GTimerState, num_cpu, 0),
};
-static void a9_gtimer_class_init(ObjectClass *klass, void *data)
+static void a9_gtimer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/allwinner-a10-pit.c b/hw/timer/allwinner-a10-pit.c
index ddaf212..e4c3532 100644
--- a/hw/timer/allwinner-a10-pit.c
+++ b/hw/timer/allwinner-a10-pit.c
@@ -185,7 +185,7 @@ static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
static const MemoryRegionOps a10_pit_ops = {
.read = a10_pit_read,
.write = a10_pit_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .endianness = DEVICE_LITTLE_ENDIAN,
};
static const Property a10_pit_properties[] = {
@@ -288,7 +288,7 @@ static void a10_pit_finalize(Object *obj)
}
}
-static void a10_pit_class_init(ObjectClass *klass, void *data)
+static void a10_pit_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
index 803dad1..7cc5915 100644
--- a/hw/timer/arm_mptimer.c
+++ b/hw/timer/arm_mptimer.c
@@ -304,7 +304,7 @@ static const Property arm_mptimer_properties[] = {
DEFINE_PROP_UINT32("num-cpu", ARMMPTimerState, num_cpu, 0),
};
-static void arm_mptimer_class_init(ObjectClass *klass, void *data)
+static void arm_mptimer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c
index 1213b77..56638ff 100644
--- a/hw/timer/arm_timer.c
+++ b/hw/timer/arm_timer.c
@@ -392,7 +392,7 @@ static const Property sp804_properties[] = {
DEFINE_PROP_UINT32("freq1", SP804State, freq1, 1000000),
};
-static void sp804_class_init(ObjectClass *klass, void *data)
+static void sp804_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
diff --git a/hw/timer/armv7m_systick.c b/hw/timer/armv7m_systick.c
index a07febd..7e4ddcd 100644
--- a/hw/timer/armv7m_systick.c
+++ b/hw/timer/armv7m_systick.c
@@ -285,7 +285,7 @@ static const VMStateDescription vmstate_systick = {
}
};
-static void systick_class_init(ObjectClass *klass, void *data)
+static void systick_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c
index 4868651..57db035 100644
--- a/hw/timer/aspeed_timer.c
+++ b/hw/timer/aspeed_timer.c
@@ -239,9 +239,8 @@ static uint64_t aspeed_timer_get_value(AspeedTimer *t, int reg)
return value;
}
-static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size)
+static uint64_t aspeed_timer_read_common(AspeedTimerCtrlState *s, hwaddr offset)
{
- AspeedTimerCtrlState *s = opaque;
const int reg = (offset & 0xf) / 4;
uint64_t value;
@@ -256,10 +255,11 @@ static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size)
value = aspeed_timer_get_value(&s->timers[(offset >> 4) - 1], reg);
break;
default:
- value = ASPEED_TIMER_GET_CLASS(s)->read(s, offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ value = 0;
break;
}
- trace_aspeed_timer_read(offset, size, value);
return value;
}
@@ -431,12 +431,11 @@ static void aspeed_timer_set_ctrl2(AspeedTimerCtrlState *s, uint32_t value)
trace_aspeed_timer_set_ctrl2(value);
}
-static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value,
- unsigned size)
+static void aspeed_timer_write_common(AspeedTimerCtrlState *s, hwaddr offset,
+ uint64_t value)
{
const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF);
const int reg = (offset & 0xf) / 4;
- AspeedTimerCtrlState *s = opaque;
switch (offset) {
/* Control Registers */
@@ -451,11 +450,25 @@ static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value,
aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS) - 1, reg, tv);
break;
default:
- ASPEED_TIMER_GET_CLASS(s)->write(s, offset, value);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
break;
}
}
+static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size)
+{
+ AspeedTimerCtrlState *s = ASPEED_TIMER(opaque);
+ return ASPEED_TIMER_GET_CLASS(s)->read(s, offset);
+}
+
+static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value,
+ unsigned size)
+{
+ AspeedTimerCtrlState *s = ASPEED_TIMER(opaque);
+ ASPEED_TIMER_GET_CLASS(s)->write(s, offset, value);
+}
+
static const MemoryRegionOps aspeed_timer_ops = {
.read = aspeed_timer_read,
.write = aspeed_timer_write,
@@ -475,12 +488,15 @@ static uint64_t aspeed_2400_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
break;
case 0x38:
case 0x3C:
- default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
__func__, offset);
value = 0;
break;
+ default:
+ value = aspeed_timer_read_common(s, offset);
+ break;
}
+ trace_aspeed_timer_read(offset, value);
return value;
}
@@ -495,10 +511,12 @@ static void aspeed_2400_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
break;
case 0x38:
case 0x3C:
- default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
__func__, offset);
break;
+ default:
+ aspeed_timer_write_common(s, offset, value);
+ break;
}
}
@@ -514,12 +532,15 @@ static uint64_t aspeed_2500_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
value = s->ctrl3 & BIT(0);
break;
case 0x3C:
- default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
__func__, offset);
value = 0;
break;
+ default:
+ value = aspeed_timer_read_common(s, offset);
+ break;
}
+ trace_aspeed_timer_read(offset, value);
return value;
}
@@ -548,8 +569,7 @@ static void aspeed_2500_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
break;
default:
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
- __func__, offset);
+ aspeed_timer_write_common(s, offset, value);
break;
}
}
@@ -564,12 +584,15 @@ static uint64_t aspeed_2600_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
break;
case 0x38:
case 0x3C:
- default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
__func__, offset);
value = 0;
break;
+ default:
+ value = aspeed_timer_read_common(s, offset);
+ break;
}
+ trace_aspeed_timer_read(offset, value);
return value;
}
@@ -586,10 +609,203 @@ static void aspeed_2600_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
aspeed_timer_set_ctrl(s, s->ctrl & ~tv);
break;
case 0x38:
- default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
__func__, offset);
break;
+ default:
+ aspeed_timer_write_common(s, offset, value);
+ break;
+ }
+}
+
+static void aspeed_2700_timer_set_ctrl(AspeedTimerCtrlState *s, int index,
+ uint32_t reg)
+{
+ const uint8_t overflow_interrupt_mask = BIT(op_overflow_interrupt);
+ const uint8_t external_clock_mask = BIT(op_external_clock);
+ const uint8_t pulse_enable_mask = BIT(op_pulse_enable);
+ const uint8_t enable_mask = BIT(op_enable);
+ AspeedTimer *t;
+ uint8_t t_old;
+ uint8_t t_new;
+ int shift;
+
+ /*
+ * Only 1 will set the specific bits to 1
+ * Handle a dependency between the 'enable' and remaining three
+ * configuration bits - i.e. if more than one bit in the control set has
+ * set, including the 'enable' bit, perform configuration and then
+ * enable the timer.
+ * Interrupt Status bit should not be set.
+ */
+
+ t = &s->timers[index];
+ shift = index * TIMER_CTRL_BITS;
+
+ t_old = (s->ctrl >> shift) & TIMER_CTRL_MASK;
+ t_new = reg & TIMER_CTRL_MASK;
+
+ if (!(t_old & external_clock_mask) &&
+ (t_new & external_clock_mask)) {
+ aspeed_timer_ctrl_external_clock(t, true);
+ s->ctrl = deposit32(s->ctrl, shift + op_external_clock, 1, 1);
+ }
+
+ if (!(t_old & overflow_interrupt_mask) &&
+ (t_new & overflow_interrupt_mask)) {
+ aspeed_timer_ctrl_overflow_interrupt(t, true);
+ s->ctrl = deposit32(s->ctrl, shift + op_overflow_interrupt, 1, 1);
+ }
+
+
+ if (!(t_old & pulse_enable_mask) &&
+ (t_new & pulse_enable_mask)) {
+ aspeed_timer_ctrl_pulse_enable(t, true);
+ s->ctrl = deposit32(s->ctrl, shift + op_pulse_enable, 1, 1);
+ }
+
+ /* If we are enabling, do so last */
+ if (!(t_old & enable_mask) &&
+ (t_new & enable_mask)) {
+ aspeed_timer_ctrl_enable(t, true);
+ s->ctrl = deposit32(s->ctrl, shift + op_enable, 1, 1);
+ }
+}
+
+static void aspeed_2700_timer_clear_ctrl(AspeedTimerCtrlState *s, int index,
+ uint32_t reg)
+{
+ const uint8_t overflow_interrupt_mask = BIT(op_overflow_interrupt);
+ const uint8_t external_clock_mask = BIT(op_external_clock);
+ const uint8_t pulse_enable_mask = BIT(op_pulse_enable);
+ const uint8_t enable_mask = BIT(op_enable);
+ AspeedTimer *t;
+ uint8_t t_old;
+ uint8_t t_new;
+ int shift;
+
+ /*
+ * Only 1 will clear the specific bits to 0
+ * Handle a dependency between the 'enable' and remaining three
+ * configuration bits - i.e. if more than one bit in the control set has
+ * clear, including the 'enable' bit, then disable the timer and perform
+ * configuration
+ */
+
+ t = &s->timers[index];
+ shift = index * TIMER_CTRL_BITS;
+
+ t_old = (s->ctrl >> shift) & TIMER_CTRL_MASK;
+ t_new = reg & TIMER_CTRL_MASK;
+
+ /* If we are disabling, do so first */
+ if ((t_old & enable_mask) &&
+ (t_new & enable_mask)) {
+ aspeed_timer_ctrl_enable(t, false);
+ s->ctrl = deposit32(s->ctrl, shift + op_enable, 1, 0);
+ }
+
+ if ((t_old & external_clock_mask) &&
+ (t_new & external_clock_mask)) {
+ aspeed_timer_ctrl_external_clock(t, false);
+ s->ctrl = deposit32(s->ctrl, shift + op_external_clock, 1, 0);
+ }
+
+ if ((t_old & overflow_interrupt_mask) &&
+ (t_new & overflow_interrupt_mask)) {
+ aspeed_timer_ctrl_overflow_interrupt(t, false);
+ s->ctrl = deposit32(s->ctrl, shift + op_overflow_interrupt, 1, 0);
+ }
+
+ if ((t_old & pulse_enable_mask) &&
+ (t_new & pulse_enable_mask)) {
+ aspeed_timer_ctrl_pulse_enable(t, false);
+ s->ctrl = deposit32(s->ctrl, shift + op_pulse_enable, 1, 0);
+ }
+
+ /* Clear interrupt status */
+ if (reg & 0x10000) {
+ s->irq_sts = deposit32(s->irq_sts, index, 1, 0);
+ }
+}
+
+static uint64_t aspeed_2700_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
+{
+ uint32_t timer_offset = offset & 0x3f;
+ int timer_index = offset >> 6;
+ uint64_t value = 0;
+
+ if (timer_index >= ASPEED_TIMER_NR_TIMERS) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: offset 0x%" PRIx64 " out of bounds\n",
+ __func__, offset);
+ return 0;
+ }
+
+ switch (timer_offset) {
+ /*
+ * Counter Status
+ * Counter Reload
+ * Counter First Matching
+ * Counter Second Matching
+ */
+ case 0x00 ... 0x0C:
+ value = aspeed_timer_get_value(&s->timers[timer_index],
+ timer_offset >> 2);
+ break;
+ /* Counter Control and Interrupt Status */
+ case 0x10:
+ value = deposit64(value, 0, 4,
+ extract32(s->ctrl, timer_index * 4, 4));
+ value = deposit64(value, 16, 1,
+ extract32(s->irq_sts, timer_index, 1));
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: no getter for offset 0x%"
+ PRIx64"\n", __func__, offset);
+ value = 0;
+ break;
+ }
+ trace_aspeed_timer_read(offset, value);
+ return value;
+}
+
+static void aspeed_2700_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
+ uint64_t value)
+{
+ const uint32_t timer_value = (uint32_t)(value & 0xFFFFFFFF);
+ uint32_t timer_offset = offset & 0x3f;
+ int timer_index = offset >> 6;
+
+ if (timer_index >= ASPEED_TIMER_NR_TIMERS) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: offset 0x%" PRIx64 " out of bounds\n",
+ __func__, offset);
+ }
+
+ switch (timer_offset) {
+ /*
+ * Counter Status
+ * Counter Reload
+ * Counter First Matching
+ * Counter Second Matching
+ */
+ case 0x00 ... 0x0C:
+ aspeed_timer_set_value(s, timer_index, timer_offset >> 2,
+ timer_value);
+ break;
+ /* Counter Control Set and Interrupt Status */
+ case 0x10:
+ aspeed_2700_timer_set_ctrl(s, timer_index, timer_value);
+ break;
+ /* Counter Control Clear and Interrupr Status */
+ case 0x14:
+ aspeed_2700_timer_clear_ctrl(s, timer_index, timer_value);
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: no setter for offset 0x%"
+ PRIx64"\n", __func__, offset);
+ break;
}
}
@@ -679,7 +895,7 @@ static const Property aspeed_timer_properties[] = {
AspeedSCUState *),
};
-static void timer_class_init(ObjectClass *klass, void *data)
+static void timer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -699,7 +915,7 @@ static const TypeInfo aspeed_timer_info = {
.abstract = true,
};
-static void aspeed_2400_timer_class_init(ObjectClass *klass, void *data)
+static void aspeed_2400_timer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedTimerClass *awc = ASPEED_TIMER_CLASS(klass);
@@ -715,7 +931,7 @@ static const TypeInfo aspeed_2400_timer_info = {
.class_init = aspeed_2400_timer_class_init,
};
-static void aspeed_2500_timer_class_init(ObjectClass *klass, void *data)
+static void aspeed_2500_timer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedTimerClass *awc = ASPEED_TIMER_CLASS(klass);
@@ -731,7 +947,7 @@ static const TypeInfo aspeed_2500_timer_info = {
.class_init = aspeed_2500_timer_class_init,
};
-static void aspeed_2600_timer_class_init(ObjectClass *klass, void *data)
+static void aspeed_2600_timer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedTimerClass *awc = ASPEED_TIMER_CLASS(klass);
@@ -747,7 +963,7 @@ static const TypeInfo aspeed_2600_timer_info = {
.class_init = aspeed_2600_timer_class_init,
};
-static void aspeed_1030_timer_class_init(ObjectClass *klass, void *data)
+static void aspeed_1030_timer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedTimerClass *awc = ASPEED_TIMER_CLASS(klass);
@@ -763,6 +979,22 @@ static const TypeInfo aspeed_1030_timer_info = {
.class_init = aspeed_1030_timer_class_init,
};
+static void aspeed_2700_timer_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ AspeedTimerClass *awc = ASPEED_TIMER_CLASS(klass);
+
+ dc->desc = "ASPEED 2700 Timer";
+ awc->read = aspeed_2700_timer_read;
+ awc->write = aspeed_2700_timer_write;
+}
+
+static const TypeInfo aspeed_2700_timer_info = {
+ .name = TYPE_ASPEED_2700_TIMER,
+ .parent = TYPE_ASPEED_TIMER,
+ .class_init = aspeed_2700_timer_class_init,
+};
+
static void aspeed_timer_register_types(void)
{
type_register_static(&aspeed_timer_info);
@@ -770,6 +1002,7 @@ static void aspeed_timer_register_types(void)
type_register_static(&aspeed_2500_timer_info);
type_register_static(&aspeed_2600_timer_info);
type_register_static(&aspeed_1030_timer_info);
+ type_register_static(&aspeed_2700_timer_info);
}
type_init(aspeed_timer_register_types)
diff --git a/hw/timer/avr_timer16.c b/hw/timer/avr_timer16.c
index 96baf9c..012d829 100644
--- a/hw/timer/avr_timer16.c
+++ b/hw/timer/avr_timer16.c
@@ -595,7 +595,7 @@ static void avr_timer16_realize(DeviceState *dev, Error **errp)
s->enabled = true;
}
-static void avr_timer16_class_init(ObjectClass *klass, void *data)
+static void avr_timer16_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
index 2f0fee3..7929aaa 100644
--- a/hw/timer/bcm2835_systmr.c
+++ b/hw/timer/bcm2835_systmr.c
@@ -154,7 +154,7 @@ static const VMStateDescription bcm2835_systmr_vmstate = {
}
};
-static void bcm2835_systmr_class_init(ObjectClass *klass, void *data)
+static void bcm2835_systmr_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c
index 54dbd4c..9c7ba16 100644
--- a/hw/timer/cadence_ttc.c
+++ b/hw/timer/cadence_ttc.c
@@ -451,7 +451,7 @@ static const VMStateDescription vmstate_cadence_ttc = {
}
};
-static void cadence_ttc_class_init(ObjectClass *klass, void *data)
+static void cadence_ttc_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
index 2ecd8df..34c550a 100644
--- a/hw/timer/cmsdk-apb-dualtimer.c
+++ b/hw/timer/cmsdk-apb-dualtimer.c
@@ -534,7 +534,7 @@ static const VMStateDescription cmsdk_apb_dualtimer_vmstate = {
}
};
-static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, void *data)
+static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
index 16d0b21..4095267 100644
--- a/hw/timer/cmsdk-apb-timer.c
+++ b/hw/timer/cmsdk-apb-timer.c
@@ -261,7 +261,7 @@ static const VMStateDescription cmsdk_apb_timer_vmstate = {
}
};
-static void cmsdk_apb_timer_class_init(ObjectClass *klass, void *data)
+static void cmsdk_apb_timer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/digic-timer.c b/hw/timer/digic-timer.c
index 00c3297..355138d 100644
--- a/hw/timer/digic-timer.c
+++ b/hw/timer/digic-timer.c
@@ -161,7 +161,7 @@ static void digic_timer_finalize(Object *obj)
ptimer_free(s->ptimer);
}
-static void digic_timer_class_init(ObjectClass *klass, void *class_data)
+static void digic_timer_class_init(ObjectClass *klass, const void *class_data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index 5c6e139..bb0f9c8 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -1546,7 +1546,7 @@ static void exynos4210_mct_finalize(Object *obj)
}
}
-static void exynos4210_mct_class_init(ObjectClass *klass, void *data)
+static void exynos4210_mct_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c
index 703d1d2..69f737a 100644
--- a/hw/timer/exynos4210_pwm.c
+++ b/hw/timer/exynos4210_pwm.c
@@ -420,7 +420,7 @@ static void exynos4210_pwm_finalize(Object *obj)
}
}
-static void exynos4210_pwm_class_init(ObjectClass *klass, void *data)
+static void exynos4210_pwm_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/grlib_gptimer.c b/hw/timer/grlib_gptimer.c
index f0802b6..0e06fa0 100644
--- a/hw/timer/grlib_gptimer.c
+++ b/hw/timer/grlib_gptimer.c
@@ -409,7 +409,7 @@ static const Property grlib_gptimer_properties[] = {
DEFINE_PROP_UINT32("nr-timers", GPTimerUnit, nr_timers, 2),
};
-static void grlib_gptimer_class_init(ObjectClass *klass, void *data)
+static void grlib_gptimer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index 1c8c6c6..cb48cc1 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -36,10 +36,12 @@
#include "hw/rtc/mc146818rtc_regs.h"
#include "migration/vmstate.h"
#include "hw/timer/i8254.h"
-#include "exec/address-spaces.h"
+#include "system/address-spaces.h"
#include "qom/object.h"
#include "trace.h"
+struct hpet_fw_config hpet_fw_cfg = {.count = UINT8_MAX};
+
#define HPET_MSI_SUPPORT 0
OBJECT_DECLARE_SIMPLE_TYPE(HPETState, HPET)
@@ -75,6 +77,7 @@ struct HPETState {
uint8_t rtc_irq_level;
qemu_irq pit_enabled;
uint8_t num_timers;
+ uint8_t num_timers_save;
uint32_t intcap;
HPETTimer timer[HPET_MAX_TIMERS];
@@ -235,15 +238,12 @@ static int hpet_pre_save(void *opaque)
s->hpet_counter = hpet_get_ticks(s);
}
- return 0;
-}
-
-static int hpet_pre_load(void *opaque)
-{
- HPETState *s = opaque;
-
- /* version 1 only supports 3, later versions will load the actual value */
- s->num_timers = HPET_MIN_TIMERS;
+ /*
+ * The number of timers must match on source and destination, but it was
+ * also added to the migration stream. Check that it matches the value
+ * that was configured.
+ */
+ s->num_timers_save = s->num_timers;
return 0;
}
@@ -251,12 +251,7 @@ static bool hpet_validate_num_timers(void *opaque, int version_id)
{
HPETState *s = opaque;
- if (s->num_timers < HPET_MIN_TIMERS) {
- return false;
- } else if (s->num_timers > HPET_MAX_TIMERS) {
- return false;
- }
- return true;
+ return s->num_timers == s->num_timers_save;
}
static int hpet_post_load(void *opaque, int version_id)
@@ -275,16 +270,6 @@ static int hpet_post_load(void *opaque, int version_id)
- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
- /* Push number of timers into capability returned via HPET_ID */
- s->capability &= ~HPET_ID_NUM_TIM_MASK;
- s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
- hpet_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t)s->capability;
-
- /* Derive HPET_MSI_SUPPORT from the capability of the first timer. */
- s->flags &= ~(1 << HPET_MSI_SUPPORT);
- if (s->timer[0].config & HPET_TN_FSB_CAP) {
- s->flags |= 1 << HPET_MSI_SUPPORT;
- }
return 0;
}
@@ -343,17 +328,16 @@ static const VMStateDescription vmstate_hpet_timer = {
static const VMStateDescription vmstate_hpet = {
.name = "hpet",
.version_id = 2,
- .minimum_version_id = 1,
+ .minimum_version_id = 2,
.pre_save = hpet_pre_save,
- .pre_load = hpet_pre_load,
.post_load = hpet_post_load,
.fields = (const VMStateField[]) {
VMSTATE_UINT64(config, HPETState),
VMSTATE_UINT64(isr, HPETState),
VMSTATE_UINT64(hpet_counter, HPETState),
- VMSTATE_UINT8_V(num_timers, HPETState, 2),
- VMSTATE_VALIDATE("num_timers in range", hpet_validate_num_timers),
- VMSTATE_STRUCT_VARRAY_UINT8(timer, HPETState, num_timers, 0,
+ VMSTATE_UINT8(num_timers_save, HPETState),
+ VMSTATE_VALIDATE("num_timers must match", hpet_validate_num_timers),
+ VMSTATE_STRUCT_VARRAY_UINT8(timer, HPETState, num_timers_save, 0,
vmstate_hpet_timer, HPETTimer),
VMSTATE_END_OF_LIST()
},
@@ -442,30 +426,11 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
uint64_t cur_tick;
trace_hpet_ram_read(addr);
+ addr &= ~4;
- /*address range of all TN regs*/
- if (addr >= 0x100 && addr <= 0x3ff) {
- uint8_t timer_id = (addr - 0x100) / 0x20;
- HPETTimer *timer = &s->timer[timer_id];
-
- if (timer_id > s->num_timers) {
- trace_hpet_timer_id_out_of_range(timer_id);
- return 0;
- }
-
- switch (addr & 0x18) {
- case HPET_TN_CFG: // including interrupt capabilities
- return timer->config >> shift;
- case HPET_TN_CMP: // comparator register
- return timer->cmp >> shift;
- case HPET_TN_ROUTE:
- return timer->fsb >> shift;
- default:
- trace_hpet_ram_read_invalid();
- break;
- }
- } else {
- switch (addr & ~4) {
+ /*address range of all global regs*/
+ if (addr <= 0xff) {
+ switch (addr) {
case HPET_ID: // including HPET_PERIOD
return s->capability >> shift;
case HPET_CFG:
@@ -484,6 +449,26 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
trace_hpet_ram_read_invalid();
break;
}
+ } else {
+ uint8_t timer_id = (addr - 0x100) / 0x20;
+ HPETTimer *timer = &s->timer[timer_id];
+
+ if (timer_id > s->num_timers) {
+ trace_hpet_timer_id_out_of_range(timer_id);
+ return 0;
+ }
+
+ switch (addr & 0x1f) {
+ case HPET_TN_CFG: // including interrupt capabilities
+ return timer->config >> shift;
+ case HPET_TN_CMP: // comparator register
+ return timer->cmp >> shift;
+ case HPET_TN_ROUTE:
+ return timer->fsb >> shift;
+ default:
+ trace_hpet_ram_read_invalid();
+ break;
+ }
}
return 0;
}
@@ -498,9 +483,67 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
uint64_t old_val, new_val, cleared;
trace_hpet_ram_write(addr, value);
+ addr &= ~4;
- /*address range of all TN regs*/
- if (addr >= 0x100 && addr <= 0x3ff) {
+ /*address range of all global regs*/
+ if (addr <= 0xff) {
+ switch (addr) {
+ case HPET_ID:
+ return;
+ case HPET_CFG:
+ old_val = s->config;
+ new_val = deposit64(old_val, shift, len, value);
+ new_val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK);
+ s->config = new_val;
+ if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
+ /* Enable main counter and interrupt generation. */
+ s->hpet_offset =
+ ticks_to_ns(s->hpet_counter) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ for (i = 0; i < s->num_timers; i++) {
+ if (timer_enabled(&s->timer[i]) && (s->isr & (1 << i))) {
+ update_irq(&s->timer[i], 1);
+ }
+ hpet_set_timer(&s->timer[i]);
+ }
+ } else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
+ /* Halt main counter and disable interrupt generation. */
+ s->hpet_counter = hpet_get_ticks(s);
+ for (i = 0; i < s->num_timers; i++) {
+ hpet_del_timer(&s->timer[i]);
+ }
+ }
+ /* i8254 and RTC output pins are disabled
+ * when HPET is in legacy mode */
+ if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
+ qemu_set_irq(s->pit_enabled, 0);
+ qemu_irq_lower(s->irqs[0]);
+ qemu_irq_lower(s->irqs[RTC_ISA_IRQ]);
+ } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
+ qemu_irq_lower(s->irqs[0]);
+ qemu_set_irq(s->pit_enabled, 1);
+ qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level);
+ }
+ break;
+ case HPET_STATUS:
+ new_val = value << shift;
+ cleared = new_val & s->isr;
+ for (i = 0; i < s->num_timers; i++) {
+ if (cleared & (1 << i)) {
+ update_irq(&s->timer[i], 0);
+ }
+ }
+ break;
+ case HPET_COUNTER:
+ if (hpet_enabled(s)) {
+ trace_hpet_ram_write_counter_write_while_enabled();
+ }
+ s->hpet_counter = deposit64(s->hpet_counter, shift, len, value);
+ break;
+ default:
+ trace_hpet_ram_write_invalid();
+ break;
+ }
+ } else {
uint8_t timer_id = (addr - 0x100) / 0x20;
HPETTimer *timer = &s->timer[timer_id];
@@ -566,63 +609,6 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
break;
}
return;
- } else {
- switch (addr & ~4) {
- case HPET_ID:
- return;
- case HPET_CFG:
- old_val = s->config;
- new_val = deposit64(old_val, shift, len, value);
- new_val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK);
- s->config = new_val;
- if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
- /* Enable main counter and interrupt generation. */
- s->hpet_offset =
- ticks_to_ns(s->hpet_counter) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- for (i = 0; i < s->num_timers; i++) {
- if (timer_enabled(&s->timer[i]) && (s->isr & (1 << i))) {
- update_irq(&s->timer[i], 1);
- }
- hpet_set_timer(&s->timer[i]);
- }
- } else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
- /* Halt main counter and disable interrupt generation. */
- s->hpet_counter = hpet_get_ticks(s);
- for (i = 0; i < s->num_timers; i++) {
- hpet_del_timer(&s->timer[i]);
- }
- }
- /* i8254 and RTC output pins are disabled
- * when HPET is in legacy mode */
- if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
- qemu_set_irq(s->pit_enabled, 0);
- qemu_irq_lower(s->irqs[0]);
- qemu_irq_lower(s->irqs[RTC_ISA_IRQ]);
- } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
- qemu_irq_lower(s->irqs[0]);
- qemu_set_irq(s->pit_enabled, 1);
- qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level);
- }
- break;
- case HPET_STATUS:
- new_val = value << shift;
- cleared = new_val & s->isr;
- for (i = 0; i < s->num_timers; i++) {
- if (cleared & (1 << i)) {
- update_irq(&s->timer[i], 0);
- }
- }
- break;
- case HPET_COUNTER:
- if (hpet_enabled(s)) {
- trace_hpet_ram_write_counter_write_while_enabled();
- }
- s->hpet_counter = deposit64(s->hpet_counter, shift, len, value);
- break;
- default:
- trace_hpet_ram_write_invalid();
- break;
- }
}
}
@@ -665,8 +651,8 @@ static void hpet_reset(DeviceState *d)
s->hpet_counter = 0ULL;
s->hpet_offset = 0ULL;
s->config = 0ULL;
- hpet_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t)s->capability;
- hpet_cfg.hpet[s->hpet_id].address = sbd->mmio[0].addr;
+ hpet_fw_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t)s->capability;
+ hpet_fw_cfg.hpet[s->hpet_id].address = sbd->mmio[0].addr;
/* to document that the RTC lowers its output on reset as well */
s->rtc_irq_level = 0;
@@ -705,30 +691,31 @@ static void hpet_realize(DeviceState *dev, Error **errp)
int i;
HPETTimer *timer;
+ if (s->num_timers < HPET_MIN_TIMERS || s->num_timers > HPET_MAX_TIMERS) {
+ error_setg(errp, "hpet.num_timers must be between %d and %d",
+ HPET_MIN_TIMERS, HPET_MAX_TIMERS);
+ return;
+ }
if (!s->intcap) {
- warn_report("Hpet's intcap not initialized");
+ error_setg(errp, "hpet.hpet-intcap not initialized");
+ return;
}
- if (hpet_cfg.count == UINT8_MAX) {
+ if (hpet_fw_cfg.count == UINT8_MAX) {
/* first instance */
- hpet_cfg.count = 0;
+ hpet_fw_cfg.count = 0;
}
- if (hpet_cfg.count == 8) {
- error_setg(errp, "Only 8 instances of HPET is allowed");
+ if (hpet_fw_cfg.count == 8) {
+ error_setg(errp, "Only 8 instances of HPET are allowed");
return;
}
- s->hpet_id = hpet_cfg.count++;
+ s->hpet_id = hpet_fw_cfg.count++;
for (i = 0; i < HPET_NUM_IRQ_ROUTES; i++) {
sysbus_init_irq(sbd, &s->irqs[i]);
}
- if (s->num_timers < HPET_MIN_TIMERS) {
- s->num_timers = HPET_MIN_TIMERS;
- } else if (s->num_timers > HPET_MAX_TIMERS) {
- s->num_timers = HPET_MAX_TIMERS;
- }
for (i = 0; i < HPET_MAX_TIMERS; i++) {
timer = &s->timer[i];
timer->qemu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, hpet_timer, timer);
@@ -752,7 +739,7 @@ static const Property hpet_device_properties[] = {
DEFINE_PROP_BOOL("hpet-offset-saved", HPETState, hpet_offset_saved, true),
};
-static void hpet_device_class_init(ObjectClass *klass, void *data)
+static void hpet_device_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/i8254.c b/hw/timer/i8254.c
index 058fc61..4b25c48 100644
--- a/hw/timer/i8254.c
+++ b/hw/timer/i8254.c
@@ -350,7 +350,7 @@ static void pit_realizefn(DeviceState *dev, Error **errp)
pc->parent_realize(dev, errp);
}
-static void pit_class_initfn(ObjectClass *klass, void *data)
+static void pit_class_initfn(ObjectClass *klass, const void *data)
{
PITClass *pc = PIT_CLASS(klass);
PITCommonClass *k = PIT_COMMON_CLASS(klass);
diff --git a/hw/timer/i8254_common.c b/hw/timer/i8254_common.c
index 29105af..ad09159 100644
--- a/hw/timer/i8254_common.c
+++ b/hw/timer/i8254_common.c
@@ -242,7 +242,7 @@ static const Property pit_common_properties[] = {
DEFINE_PROP_UINT32("iobase", PITCommonState, iobase, -1),
};
-static void pit_common_class_init(ObjectClass *klass, void *data)
+static void pit_common_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/ibex_timer.c b/hw/timer/ibex_timer.c
index 3ebc870..c7320ef 100644
--- a/hw/timer/ibex_timer.c
+++ b/hw/timer/ibex_timer.c
@@ -286,7 +286,7 @@ static void ibex_timer_realize(DeviceState *dev, Error **errp)
}
-static void ibex_timer_class_init(ObjectClass *klass, void *data)
+static void ibex_timer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c
index f40ab16..6123321 100644
--- a/hw/timer/imx_epit.c
+++ b/hw/timer/imx_epit.c
@@ -427,7 +427,7 @@ static void imx_epit_dev_reset(DeviceState *dev)
imx_epit_reset(s, true);
}
-static void imx_epit_class_init(ObjectClass *klass, void *data)
+static void imx_epit_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
index 2663a9d..8c7cbfd 100644
--- a/hw/timer/imx_gpt.c
+++ b/hw/timer/imx_gpt.c
@@ -20,10 +20,6 @@
#include "qemu/log.h"
#include "trace.h"
-#ifndef DEBUG_IMX_GPT
-#define DEBUG_IMX_GPT 0
-#endif
-
static const char *imx_gpt_reg_name(uint32_t reg)
{
switch (reg) {
@@ -130,6 +126,17 @@ static const IMXClk imx7_gpt_clocks[] = {
CLK_NONE, /* 111 not defined */
};
+static const IMXClk imx8mp_gpt_clocks[] = {
+ CLK_NONE, /* 000 No clock source */
+ CLK_IPG, /* 001 ipg_clk, 532MHz */
+ CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */
+ CLK_EXT, /* 011 External clock */
+ CLK_32k, /* 100 ipg_clk_32k */
+ CLK_HIGH, /* 101 ipg_clk_16M */
+ CLK_NONE, /* 110 not defined */
+ CLK_NONE, /* 111 not defined */
+};
+
/* Must be called from within ptimer_transaction_begin/commit block */
static void imx_gpt_set_freq(IMXGPTState *s)
{
@@ -511,7 +518,7 @@ static void imx_gpt_realize(DeviceState *dev, Error **errp)
s->timer = ptimer_init(imx_gpt_timeout, s, PTIMER_POLICY_LEGACY);
}
-static void imx_gpt_class_init(ObjectClass *klass, void *data)
+static void imx_gpt_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -556,6 +563,13 @@ static void imx7_gpt_init(Object *obj)
s->clocks = imx7_gpt_clocks;
}
+static void imx8mp_gpt_init(Object *obj)
+{
+ IMXGPTState *s = IMX_GPT(obj);
+
+ s->clocks = imx8mp_gpt_clocks;
+}
+
static const TypeInfo imx25_gpt_info = {
.name = TYPE_IMX25_GPT,
.parent = TYPE_SYS_BUS_DEVICE,
@@ -588,6 +602,12 @@ static const TypeInfo imx7_gpt_info = {
.instance_init = imx7_gpt_init,
};
+static const TypeInfo imx8mp_gpt_info = {
+ .name = TYPE_IMX8MP_GPT,
+ .parent = TYPE_IMX25_GPT,
+ .instance_init = imx8mp_gpt_init,
+};
+
static void imx_gpt_register_types(void)
{
type_register_static(&imx25_gpt_info);
@@ -595,6 +615,7 @@ static void imx_gpt_register_types(void)
type_register_static(&imx6_gpt_info);
type_register_static(&imx6ul_gpt_info);
type_register_static(&imx7_gpt_info);
+ type_register_static(&imx8mp_gpt_info);
}
type_init(imx_gpt_register_types)
diff --git a/hw/timer/meson.build b/hw/timer/meson.build
index f5f9eed..178321c 100644
--- a/hw/timer/meson.build
+++ b/hw/timer/meson.build
@@ -13,7 +13,7 @@ system_ss.add(when: 'CONFIG_DIGIC', if_true: files('digic-timer.c'))
system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_mct.c'))
system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_pwm.c'))
system_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_gptimer.c'))
-system_ss.add(when: 'CONFIG_HPET', if_true: files('hpet.c'))
+system_ss.add(when: 'CONFIG_HPET_C', if_true: files('hpet.c'))
system_ss.add(when: 'CONFIG_I8254', if_true: files('i8254_common.c', 'i8254.c'))
system_ss.add(when: 'CONFIG_IMX', if_true: files('imx_epit.c'))
system_ss.add(when: 'CONFIG_IMX', if_true: files('imx_gpt.c'))
diff --git a/hw/timer/mss-timer.c b/hw/timer/mss-timer.c
index 594da64..2ce8211 100644
--- a/hw/timer/mss-timer.c
+++ b/hw/timer/mss-timer.c
@@ -285,7 +285,7 @@ static const Property mss_timer_properties[] = {
100 * 1000000),
};
-static void mss_timer_class_init(ObjectClass *klass, void *data)
+static void mss_timer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
index c55ba02..6a116ad 100644
--- a/hw/timer/npcm7xx_timer.c
+++ b/hw/timer/npcm7xx_timer.c
@@ -689,7 +689,7 @@ static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
},
};
-static void npcm7xx_timer_class_init(ObjectClass *klass, void *data)
+static void npcm7xx_timer_class_init(ObjectClass *klass, const void *data)
{
ResettableClass *rc = RESETTABLE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/nrf51_timer.c b/hw/timer/nrf51_timer.c
index 11ad8b5..e228fde 100644
--- a/hw/timer/nrf51_timer.c
+++ b/hw/timer/nrf51_timer.c
@@ -383,7 +383,7 @@ static const Property nrf51_timer_properties[] = {
DEFINE_PROP_UINT8("id", NRF51TimerState, id, 0),
};
-static void nrf51_timer_class_init(ObjectClass *klass, void *data)
+static void nrf51_timer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/pxa2xx_timer.c b/hw/timer/pxa2xx_timer.c
index 9e4dd0f..6d4ac31 100644
--- a/hw/timer/pxa2xx_timer.c
+++ b/hw/timer/pxa2xx_timer.c
@@ -19,41 +19,41 @@
#include "qom/object.h"
#include "system/watchdog.h"
-#define OSMR0 0x00
-#define OSMR1 0x04
-#define OSMR2 0x08
-#define OSMR3 0x0c
-#define OSMR4 0x80
-#define OSMR5 0x84
-#define OSMR6 0x88
-#define OSMR7 0x8c
-#define OSMR8 0x90
-#define OSMR9 0x94
-#define OSMR10 0x98
-#define OSMR11 0x9c
-#define OSCR 0x10 /* OS Timer Count */
-#define OSCR4 0x40
-#define OSCR5 0x44
-#define OSCR6 0x48
-#define OSCR7 0x4c
-#define OSCR8 0x50
-#define OSCR9 0x54
-#define OSCR10 0x58
-#define OSCR11 0x5c
-#define OSSR 0x14 /* Timer status register */
-#define OWER 0x18
-#define OIER 0x1c /* Interrupt enable register 3-0 to E3-E0 */
-#define OMCR4 0xc0 /* OS Match Control registers */
-#define OMCR5 0xc4
-#define OMCR6 0xc8
-#define OMCR7 0xcc
-#define OMCR8 0xd0
-#define OMCR9 0xd4
-#define OMCR10 0xd8
-#define OMCR11 0xdc
-#define OSNR 0x20
-
-#define PXA25X_FREQ 3686400 /* 3.6864 MHz */
+#define OSMR0 0x00
+#define OSMR1 0x04
+#define OSMR2 0x08
+#define OSMR3 0x0c
+#define OSMR4 0x80
+#define OSMR5 0x84
+#define OSMR6 0x88
+#define OSMR7 0x8c
+#define OSMR8 0x90
+#define OSMR9 0x94
+#define OSMR10 0x98
+#define OSMR11 0x9c
+#define OSCR 0x10 /* OS Timer Count */
+#define OSCR4 0x40
+#define OSCR5 0x44
+#define OSCR6 0x48
+#define OSCR7 0x4c
+#define OSCR8 0x50
+#define OSCR9 0x54
+#define OSCR10 0x58
+#define OSCR11 0x5c
+#define OSSR 0x14 /* Timer status register */
+#define OWER 0x18
+#define OIER 0x1c /* Interrupt enable register 3-0 to E3-E0 */
+#define OMCR4 0xc0 /* OS Match Control registers */
+#define OMCR5 0xc4
+#define OMCR6 0xc8
+#define OMCR7 0xcc
+#define OMCR8 0xd0
+#define OMCR9 0xd4
+#define OMCR10 0xd8
+#define OMCR11 0xdc
+#define OSNR 0x20
+
+#define PXA25X_FREQ 3686400 /* 3.6864 MHz */
static int pxa2xx_timer4_freq[8] = {
[0] = 0,
@@ -106,7 +106,7 @@ struct PXA2xxTimerInfo {
PXA2xxTimer4 tm4[8];
};
-#define PXA2XX_TIMER_HAVE_TM4 0
+#define PXA2XX_TIMER_HAVE_TM4 0
static inline int pxa2xx_timer_has_tm4(PXA2xxTimerInfo *s)
{
@@ -230,7 +230,7 @@ static uint64_t pxa2xx_timer_read(void *opaque, hwaddr offset,
NANOSECONDS_PER_SECOND);
case OIER:
return s->irq_enabled;
- case OSSR: /* Status register */
+ case OSSR: /* Status register */
return s->events;
case OWER:
return s->reset3;
@@ -336,7 +336,7 @@ static void pxa2xx_timer_write(void *opaque, hwaddr offset,
case OIER:
s->irq_enabled = value & 0xfff;
break;
- case OSSR: /* Status register */
+ case OSSR: /* Status register */
value &= s->events;
s->events &= ~value;
for (i = 0; i < 4; i ++, value >>= 1)
@@ -345,7 +345,7 @@ static void pxa2xx_timer_write(void *opaque, hwaddr offset,
if (pxa2xx_timer_has_tm4(s) && !(s->events & 0xff0) && value)
qemu_irq_lower(s->irq4);
break;
- case OWER: /* XXX: Reset on OSMR3 match? */
+ case OWER: /* XXX: Reset on OSMR3 match? */
s->reset3 = value;
break;
case OMCR7: tm ++;
@@ -555,7 +555,7 @@ static const Property pxa25x_timer_dev_properties[] = {
PXA2XX_TIMER_HAVE_TM4, false),
};
-static void pxa25x_timer_dev_class_init(ObjectClass *klass, void *data)
+static void pxa25x_timer_dev_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -570,7 +570,7 @@ static const TypeInfo pxa25x_timer_dev_info = {
.class_init = pxa25x_timer_dev_class_init,
};
-static void pxa2xx_timer_class_init(ObjectClass *oc, void *data)
+static void pxa2xx_timer_class_init(ObjectClass *oc, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
diff --git a/hw/timer/renesas_cmt.c b/hw/timer/renesas_cmt.c
index 93e7f58..cdff7f4 100644
--- a/hw/timer/renesas_cmt.c
+++ b/hw/timer/renesas_cmt.c
@@ -257,7 +257,7 @@ static const Property rcmt_properties[] = {
DEFINE_PROP_UINT64("input-freq", RCMTState, input_freq, 0),
};
-static void rcmt_class_init(ObjectClass *klass, void *data)
+static void rcmt_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/renesas_tmr.c b/hw/timer/renesas_tmr.c
index 884349c..95707f2 100644
--- a/hw/timer/renesas_tmr.c
+++ b/hw/timer/renesas_tmr.c
@@ -467,7 +467,7 @@ static const Property rtmr_properties[] = {
DEFINE_PROP_UINT64("input-freq", RTMRState, input_freq, 0),
};
-static void rtmr_class_init(ObjectClass *klass, void *data)
+static void rtmr_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/sh_timer.c b/hw/timer/sh_timer.c
index 7788939..d4fa32c 100644
--- a/hw/timer/sh_timer.c
+++ b/hw/timer/sh_timer.c
@@ -9,7 +9,7 @@
*/
#include "qemu/osdep.h"
-#include "exec/memory.h"
+#include "system/memory.h"
#include "qemu/log.h"
#include "hw/irq.h"
#include "hw/sh4/sh.h"
diff --git a/hw/timer/sifive_pwm.c b/hw/timer/sifive_pwm.c
index fc796e9..e85e389 100644
--- a/hw/timer/sifive_pwm.c
+++ b/hw/timer/sifive_pwm.c
@@ -441,7 +441,7 @@ static void sifive_pwm_realize(DeviceState *dev, Error **errp)
sifive_pwm_interrupt_3, s);
}
-static void sifive_pwm_class_init(ObjectClass *klass, void *data)
+static void sifive_pwm_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
index 65b24e4..3e071fb 100644
--- a/hw/timer/slavio_timer.c
+++ b/hw/timer/slavio_timer.c
@@ -424,7 +424,7 @@ static const Property slavio_timer_properties[] = {
DEFINE_PROP_UINT32("num_cpus", SLAVIO_TIMERState, num_cpus, 0),
};
-static void slavio_timer_class_init(ObjectClass *klass, void *data)
+static void slavio_timer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/sse-counter.c b/hw/timer/sse-counter.c
index f17064a..31f77ac 100644
--- a/hw/timer/sse-counter.c
+++ b/hw/timer/sse-counter.c
@@ -448,7 +448,7 @@ static const VMStateDescription sse_counter_vmstate = {
}
};
-static void sse_counter_class_init(ObjectClass *klass, void *data)
+static void sse_counter_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/sse-timer.c b/hw/timer/sse-timer.c
index e106739..866d5ee 100644
--- a/hw/timer/sse-timer.c
+++ b/hw/timer/sse-timer.c
@@ -444,7 +444,7 @@ static const Property sse_timer_properties[] = {
DEFINE_PROP_LINK("counter", SSETimer, counter, TYPE_SSE_COUNTER, SSECounter *),
};
-static void sse_timer_class_init(ObjectClass *klass, void *data)
+static void sse_timer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/stellaris-gptm.c b/hw/timer/stellaris-gptm.c
index f28958c..d97b2f8 100644
--- a/hw/timer/stellaris-gptm.c
+++ b/hw/timer/stellaris-gptm.c
@@ -308,7 +308,7 @@ static void stellaris_gptm_realize(DeviceState *dev, Error **errp)
s->timer[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[1]);
}
-static void stellaris_gptm_class_init(ObjectClass *klass, void *data)
+static void stellaris_gptm_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/stm32f2xx_timer.c b/hw/timer/stm32f2xx_timer.c
index 4707190..be844e7 100644
--- a/hw/timer/stm32f2xx_timer.c
+++ b/hw/timer/stm32f2xx_timer.c
@@ -320,7 +320,7 @@ static void stm32f2xx_timer_realize(DeviceState *dev, Error **errp)
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, stm32f2xx_timer_interrupt, s);
}
-static void stm32f2xx_timer_class_init(ObjectClass *klass, void *data)
+static void stm32f2xx_timer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
index 5cfc369..c5b6db4 100644
--- a/hw/timer/trace-events
+++ b/hw/timer/trace-events
@@ -31,7 +31,7 @@ aspeed_timer_ctrl_overflow_interrupt(uint8_t i, bool enable) "Timer %" PRIu8 ":
aspeed_timer_ctrl_pulse_enable(uint8_t i, bool enable) "Timer %" PRIu8 ": %d"
aspeed_timer_set_ctrl2(uint32_t value) "Value: 0x%" PRIx32
aspeed_timer_set_value(int timer, int reg, uint32_t value) "Timer %d register %d: 0x%" PRIx32
-aspeed_timer_read(uint64_t offset, unsigned size, uint64_t value) "From 0x%" PRIx64 ": of size %u: 0x%" PRIx64
+aspeed_timer_read(uint64_t offset, uint64_t value) "From 0x%" PRIx64 ": 0x%" PRIx64
# armv7m_systick.c
systick_reload(void) "systick reload"
diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
index 4955fe1..ff4a224 100644
--- a/hw/timer/xilinx_timer.c
+++ b/hw/timer/xilinx_timer.c
@@ -3,6 +3,9 @@
*
* Copyright (c) 2009 Edgar E. Iglesias.
*
+ * DS573: https://docs.amd.com/v/u/en-US/xps_timer
+ * LogiCORE IP XPS Timer/Counter (v1.02a)
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
@@ -23,10 +26,12 @@
*/
#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "hw/sysbus.h"
#include "hw/irq.h"
#include "hw/ptimer.h"
#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
#include "qemu/log.h"
#include "qemu/module.h"
#include "qom/object.h"
@@ -69,6 +74,7 @@ struct XpsTimerState
{
SysBusDevice parent_obj;
+ EndianMode model_endianness;
MemoryRegion mmio;
qemu_irq irq;
uint8_t one_timer_only;
@@ -189,14 +195,21 @@ timer_write(void *opaque, hwaddr addr,
timer_update_irq(t);
}
-static const MemoryRegionOps timer_ops = {
- .read = timer_read,
- .write = timer_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4
- }
+static const MemoryRegionOps timer_ops[2] = {
+ [0 ... 1] = {
+ .read = timer_read,
+ .write = timer_write,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+ },
+ [0].endianness = DEVICE_LITTLE_ENDIAN,
+ [1].endianness = DEVICE_BIG_ENDIAN,
};
static void timer_hit(void *opaque)
@@ -216,6 +229,12 @@ static void xilinx_timer_realize(DeviceState *dev, Error **errp)
XpsTimerState *t = XILINX_TIMER(dev);
unsigned int i;
+ if (t->model_endianness == ENDIAN_MODE_UNSPECIFIED) {
+ error_setg(errp, TYPE_XILINX_TIMER " property 'endianness'"
+ " must be set to 'big' or 'little'");
+ return;
+ }
+
/* Init all the ptimers. */
t->timers = g_malloc0(sizeof t->timers[0] * num_timers(t));
for (i = 0; i < num_timers(t); i++) {
@@ -229,8 +248,9 @@ static void xilinx_timer_realize(DeviceState *dev, Error **errp)
ptimer_transaction_commit(xt->ptimer);
}
- memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t, "xlnx.xps-timer",
- R_MAX * 4 * num_timers(t));
+ memory_region_init_io(&t->mmio, OBJECT(t),
+ &timer_ops[t->model_endianness == ENDIAN_MODE_BIG],
+ t, "xlnx.xps-timer", R_MAX * 4 * num_timers(t));
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &t->mmio);
}
@@ -243,11 +263,12 @@ static void xilinx_timer_init(Object *obj)
}
static const Property xilinx_timer_properties[] = {
+ DEFINE_PROP_ENDIAN_NODEFAULT("endianness", XpsTimerState, model_endianness),
DEFINE_PROP_UINT32("clock-frequency", XpsTimerState, freq_hz, 62 * 1000000),
DEFINE_PROP_UINT8("one-timer-only", XpsTimerState, one_timer_only, 0),
};
-static void xilinx_timer_class_init(ObjectClass *klass, void *data)
+static void xilinx_timer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);