aboutsummaryrefslogtreecommitdiff
path: root/hw/timer
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-10-25 13:12:16 +0100
committerPeter Maydell <peter.maydell@linaro.org>2019-10-25 13:12:16 +0100
commit7bc8f9734213b76e76631a483be13d6737c2adbc (patch)
tree57158eb4d19eeec866bb7b0363164740ac0f1f42 /hw/timer
parent58560ad254fbda71d4daa6622d71683190070ee2 (diff)
parentf9469c1a01c333c08980e083e0ad3417256c8b9c (diff)
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20191025' into staging
target-arm queue: * raspi boards: some cleanup * raspi: implement the bcm2835 system timer device * raspi: implement a dummy thermal sensor * misc devices: switch to ptimer transaction API * cache TB flag state to improve performance of cpu_get_tb_cpu_state * aspeed: Add an AST2600 eval board # gpg: Signature made Fri 25 Oct 2019 13:11:25 BST # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20191025: (42 commits) hw/arm/highbank: Use AddressSpace when using write_secondary_boot() hw/arm/raspi: Use AddressSpace when using arm_boot::write_secondary_boot hw/arm/bcm2836: Rename cpus[] as cpu[].core hw/arm/bcm2836: Make the SoC code modular hw/arm/bcm2835_peripherals: Use the SYS_timer hw/timer/bcm2835: Add the BCM2835 SYS_timer hw/arm/bcm2835_peripherals: Use the thermal sensor block hw/misc/bcm2835_thermal: Add a dummy BCM2835 thermal sensor hw/watchdog/milkymist-sysctl.c: Switch to transaction-based ptimer API hw/m68k/mcf5206.c: Switch to transaction-based ptimer API hw/timer/grlib_gptimer.c: Switch to transaction-based ptimer API hw/timer/slavio_timer.c: Switch to transaction-based ptimer API hw/timer/slavio_timer: Remove useless check for NULL t->timer hw/dma/xilinx_axidma.c: Switch to transaction-based ptimer API hw/timer/xilinx_timer.c: Switch to transaction-based ptimer API hw/net/fsl_etsec/etsec.c: Switch to transaction-based ptimer API target/arm: Rely on hflags correct in cpu_get_tb_cpu_state linux-user/arm: Rebuild hflags for TARGET_WORDS_BIGENDIAN linux-user/aarch64: Rebuild hflags for TARGET_WORDS_BIGENDIAN target/arm: Rebuild hflags for M-profile NVIC ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/timer')
-rw-r--r--hw/timer/Makefile.objs1
-rw-r--r--hw/timer/bcm2835_systmr.c163
-rw-r--r--hw/timer/grlib_gptimer.c28
-rw-r--r--hw/timer/milkymist-sysctl.c25
-rw-r--r--hw/timer/slavio_timer.c32
-rw-r--r--hw/timer/trace-events5
-rw-r--r--hw/timer/xilinx_timer.c13
7 files changed, 240 insertions, 27 deletions
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
index 123d92c969..696cda5905 100644
--- a/hw/timer/Makefile.objs
+++ b/hw/timer/Makefile.objs
@@ -47,3 +47,4 @@ common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o
common-obj-$(CONFIG_CMSDK_APB_TIMER) += cmsdk-apb-timer.o
common-obj-$(CONFIG_CMSDK_APB_DUALTIMER) += cmsdk-apb-dualtimer.o
common-obj-$(CONFIG_MSF2) += mss-timer.o
+common-obj-$(CONFIG_RASPI) += bcm2835_systmr.o
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
new file mode 100644
index 0000000000..3387a6214a
--- /dev/null
+++ b/hw/timer/bcm2835_systmr.c
@@ -0,0 +1,163 @@
+/*
+ * BCM2835 SYS timer emulation
+ *
+ * Copyright (C) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Datasheet: BCM2835 ARM Peripherals (C6357-M-1398)
+ * https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
+ *
+ * Only the free running 64-bit counter is implemented.
+ * The 4 COMPARE registers and the interruption are not implemented.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/timer.h"
+#include "hw/timer/bcm2835_systmr.h"
+#include "hw/registerfields.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+REG32(CTRL_STATUS, 0x00)
+REG32(COUNTER_LOW, 0x04)
+REG32(COUNTER_HIGH, 0x08)
+REG32(COMPARE0, 0x0c)
+REG32(COMPARE1, 0x10)
+REG32(COMPARE2, 0x14)
+REG32(COMPARE3, 0x18)
+
+static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
+{
+ bool enable = !!s->reg.status;
+
+ trace_bcm2835_systmr_irq(enable);
+ qemu_set_irq(s->irq, enable);
+}
+
+static void bcm2835_systmr_update_compare(BCM2835SystemTimerState *s,
+ unsigned timer_index)
+{
+ /* TODO fow now, since neither Linux nor U-boot use these timers. */
+ qemu_log_mask(LOG_UNIMP, "COMPARE register %u not implemented\n",
+ timer_index);
+}
+
+static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
+ unsigned size)
+{
+ BCM2835SystemTimerState *s = BCM2835_SYSTIMER(opaque);
+ uint64_t r = 0;
+
+ switch (offset) {
+ case A_CTRL_STATUS:
+ r = s->reg.status;
+ break;
+ case A_COMPARE0 ... A_COMPARE3:
+ r = s->reg.compare[(offset - A_COMPARE0) >> 2];
+ break;
+ case A_COUNTER_LOW:
+ case A_COUNTER_HIGH:
+ /* Free running counter at 1MHz */
+ r = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL);
+ r >>= 8 * (offset - A_COUNTER_LOW);
+ r &= UINT32_MAX;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad offset 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ break;
+ }
+ trace_bcm2835_systmr_read(offset, r);
+
+ return r;
+}
+
+static void bcm2835_systmr_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ BCM2835SystemTimerState *s = BCM2835_SYSTIMER(opaque);
+
+ trace_bcm2835_systmr_write(offset, value);
+ switch (offset) {
+ case A_CTRL_STATUS:
+ s->reg.status &= ~value; /* Ack */
+ bcm2835_systmr_update_irq(s);
+ break;
+ case A_COMPARE0 ... A_COMPARE3:
+ s->reg.compare[(offset - A_COMPARE0) >> 2] = value;
+ bcm2835_systmr_update_compare(s, (offset - A_COMPARE0) >> 2);
+ break;
+ case A_COUNTER_LOW:
+ case A_COUNTER_HIGH:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: read-only ofs 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad offset 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ break;
+ }
+}
+
+static const MemoryRegionOps bcm2835_systmr_ops = {
+ .read = bcm2835_systmr_read,
+ .write = bcm2835_systmr_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
+
+static void bcm2835_systmr_reset(DeviceState *dev)
+{
+ BCM2835SystemTimerState *s = BCM2835_SYSTIMER(dev);
+
+ memset(&s->reg, 0, sizeof(s->reg));
+}
+
+static void bcm2835_systmr_realize(DeviceState *dev, Error **errp)
+{
+ BCM2835SystemTimerState *s = BCM2835_SYSTIMER(dev);
+
+ memory_region_init_io(&s->iomem, OBJECT(dev), &bcm2835_systmr_ops,
+ s, "bcm2835-sys-timer", 0x20);
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
+}
+
+static const VMStateDescription bcm2835_systmr_vmstate = {
+ .name = "bcm2835_sys_timer",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
+ VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState, 4),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void bcm2835_systmr_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = bcm2835_systmr_realize;
+ dc->reset = bcm2835_systmr_reset;
+ dc->vmsd = &bcm2835_systmr_vmstate;
+}
+
+static const TypeInfo bcm2835_systmr_info = {
+ .name = TYPE_BCM2835_SYSTIMER,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(BCM2835SystemTimerState),
+ .class_init = bcm2835_systmr_class_init,
+};
+
+static void bcm2835_systmr_register_types(void)
+{
+ type_register_static(&bcm2835_systmr_info);
+}
+
+type_init(bcm2835_systmr_register_types);
diff --git a/hw/timer/grlib_gptimer.c b/hw/timer/grlib_gptimer.c
index bb09268ea1..7a9371c0e3 100644
--- a/hw/timer/grlib_gptimer.c
+++ b/hw/timer/grlib_gptimer.c
@@ -29,7 +29,6 @@
#include "hw/irq.h"
#include "hw/ptimer.h"
#include "hw/qdev-properties.h"
-#include "qemu/main-loop.h"
#include "qemu/module.h"
#include "trace.h"
@@ -63,7 +62,6 @@ typedef struct GPTimer GPTimer;
typedef struct GPTimerUnit GPTimerUnit;
struct GPTimer {
- QEMUBH *bh;
struct ptimer_state *ptimer;
qemu_irq irq;
@@ -93,6 +91,17 @@ struct GPTimerUnit {
uint32_t config;
};
+static void grlib_gptimer_tx_begin(GPTimer *timer)
+{
+ ptimer_transaction_begin(timer->ptimer);
+}
+
+static void grlib_gptimer_tx_commit(GPTimer *timer)
+{
+ ptimer_transaction_commit(timer->ptimer);
+}
+
+/* Must be called within grlib_gptimer_tx_begin/commit block */
static void grlib_gptimer_enable(GPTimer *timer)
{
assert(timer != NULL);
@@ -115,6 +124,7 @@ static void grlib_gptimer_enable(GPTimer *timer)
ptimer_run(timer->ptimer, 1);
}
+/* Must be called within grlib_gptimer_tx_begin/commit block */
static void grlib_gptimer_restart(GPTimer *timer)
{
assert(timer != NULL);
@@ -141,7 +151,9 @@ static void grlib_gptimer_set_scaler(GPTimerUnit *unit, uint32_t scaler)
trace_grlib_gptimer_set_scaler(scaler, value);
for (i = 0; i < unit->nr_timers; i++) {
+ ptimer_transaction_begin(unit->timers[i].ptimer);
ptimer_set_freq(unit->timers[i].ptimer, value);
+ ptimer_transaction_commit(unit->timers[i].ptimer);
}
}
@@ -266,8 +278,10 @@ static void grlib_gptimer_write(void *opaque, hwaddr addr,
switch (timer_addr) {
case COUNTER_OFFSET:
trace_grlib_gptimer_writel(id, addr, value);
+ grlib_gptimer_tx_begin(&unit->timers[id]);
unit->timers[id].counter = value;
grlib_gptimer_enable(&unit->timers[id]);
+ grlib_gptimer_tx_commit(&unit->timers[id]);
return;
case COUNTER_RELOAD_OFFSET:
@@ -291,6 +305,7 @@ static void grlib_gptimer_write(void *opaque, hwaddr addr,
/* gptimer_restart calls gptimer_enable, so if "enable" and "load"
bits are present, we just have to call restart. */
+ grlib_gptimer_tx_begin(&unit->timers[id]);
if (value & GPTIMER_LOAD) {
grlib_gptimer_restart(&unit->timers[id]);
} else if (value & GPTIMER_ENABLE) {
@@ -301,6 +316,7 @@ static void grlib_gptimer_write(void *opaque, hwaddr addr,
value &= ~(GPTIMER_LOAD & GPTIMER_DEBUG_HALT);
unit->timers[id].config = value;
+ grlib_gptimer_tx_commit(&unit->timers[id]);
return;
default:
@@ -344,9 +360,11 @@ static void grlib_gptimer_reset(DeviceState *d)
timer->counter = 0;
timer->reload = 0;
timer->config = 0;
+ ptimer_transaction_begin(timer->ptimer);
ptimer_stop(timer->ptimer);
ptimer_set_count(timer->ptimer, 0);
ptimer_set_freq(timer->ptimer, unit->freq_hz);
+ ptimer_transaction_commit(timer->ptimer);
}
}
@@ -365,14 +383,16 @@ static void grlib_gptimer_realize(DeviceState *dev, Error **errp)
GPTimer *timer = &unit->timers[i];
timer->unit = unit;
- timer->bh = qemu_bh_new(grlib_gptimer_hit, timer);
- timer->ptimer = ptimer_init_with_bh(timer->bh, PTIMER_POLICY_DEFAULT);
+ timer->ptimer = ptimer_init(grlib_gptimer_hit, timer,
+ PTIMER_POLICY_DEFAULT);
timer->id = i;
/* One IRQ line for each timer */
sysbus_init_irq(sbd, &timer->irq);
+ ptimer_transaction_begin(timer->ptimer);
ptimer_set_freq(timer->ptimer, unit->freq_hz);
+ ptimer_transaction_commit(timer->ptimer);
}
memory_region_init_io(&unit->iomem, OBJECT(unit), &grlib_gptimer_ops,
diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c
index 5193c03850..7a62e212c3 100644
--- a/hw/timer/milkymist-sysctl.c
+++ b/hw/timer/milkymist-sysctl.c
@@ -31,7 +31,6 @@
#include "hw/ptimer.h"
#include "hw/qdev-properties.h"
#include "qemu/error-report.h"
-#include "qemu/main-loop.h"
#include "qemu/module.h"
enum {
@@ -71,8 +70,6 @@ struct MilkymistSysctlState {
MemoryRegion regs_region;
- QEMUBH *bh0;
- QEMUBH *bh1;
ptimer_state *ptimer0;
ptimer_state *ptimer1;
@@ -161,14 +158,19 @@ static void sysctl_write(void *opaque, hwaddr addr, uint64_t value,
s->regs[addr] = value;
break;
case R_TIMER0_COMPARE:
+ ptimer_transaction_begin(s->ptimer0);
ptimer_set_limit(s->ptimer0, value, 0);
s->regs[addr] = value;
+ ptimer_transaction_commit(s->ptimer0);
break;
case R_TIMER1_COMPARE:
+ ptimer_transaction_begin(s->ptimer1);
ptimer_set_limit(s->ptimer1, value, 0);
s->regs[addr] = value;
+ ptimer_transaction_commit(s->ptimer1);
break;
case R_TIMER0_CONTROL:
+ ptimer_transaction_begin(s->ptimer0);
s->regs[addr] = value;
if (s->regs[R_TIMER0_CONTROL] & CTRL_ENABLE) {
trace_milkymist_sysctl_start_timer0();
@@ -179,8 +181,10 @@ static void sysctl_write(void *opaque, hwaddr addr, uint64_t value,
trace_milkymist_sysctl_stop_timer0();
ptimer_stop(s->ptimer0);
}
+ ptimer_transaction_commit(s->ptimer0);
break;
case R_TIMER1_CONTROL:
+ ptimer_transaction_begin(s->ptimer1);
s->regs[addr] = value;
if (s->regs[R_TIMER1_CONTROL] & CTRL_ENABLE) {
trace_milkymist_sysctl_start_timer1();
@@ -191,6 +195,7 @@ static void sysctl_write(void *opaque, hwaddr addr, uint64_t value,
trace_milkymist_sysctl_stop_timer1();
ptimer_stop(s->ptimer1);
}
+ ptimer_transaction_commit(s->ptimer1);
break;
case R_ICAP:
sysctl_icap_write(s, value);
@@ -263,8 +268,12 @@ static void milkymist_sysctl_reset(DeviceState *d)
s->regs[i] = 0;
}
+ ptimer_transaction_begin(s->ptimer0);
ptimer_stop(s->ptimer0);
+ ptimer_transaction_commit(s->ptimer0);
+ ptimer_transaction_begin(s->ptimer1);
ptimer_stop(s->ptimer1);
+ ptimer_transaction_commit(s->ptimer1);
/* defaults */
s->regs[R_ICAP] = ICAP_READY;
@@ -292,13 +301,15 @@ static void milkymist_sysctl_realize(DeviceState *dev, Error **errp)
{
MilkymistSysctlState *s = MILKYMIST_SYSCTL(dev);
- s->bh0 = qemu_bh_new(timer0_hit, s);
- s->bh1 = qemu_bh_new(timer1_hit, s);
- s->ptimer0 = ptimer_init_with_bh(s->bh0, PTIMER_POLICY_DEFAULT);
- s->ptimer1 = ptimer_init_with_bh(s->bh1, PTIMER_POLICY_DEFAULT);
+ s->ptimer0 = ptimer_init(timer0_hit, s, PTIMER_POLICY_DEFAULT);
+ s->ptimer1 = ptimer_init(timer1_hit, s, PTIMER_POLICY_DEFAULT);
+ ptimer_transaction_begin(s->ptimer0);
ptimer_set_freq(s->ptimer0, s->freq_hz);
+ ptimer_transaction_commit(s->ptimer0);
+ ptimer_transaction_begin(s->ptimer1);
ptimer_set_freq(s->ptimer1, s->freq_hz);
+ ptimer_transaction_commit(s->ptimer1);
}
static const VMStateDescription vmstate_milkymist_sysctl = {
diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
index 692d213897..c55e8d0bf4 100644
--- a/hw/timer/slavio_timer.c
+++ b/hw/timer/slavio_timer.c
@@ -30,7 +30,6 @@
#include "hw/sysbus.h"
#include "migration/vmstate.h"
#include "trace.h"
-#include "qemu/main-loop.h"
#include "qemu/module.h"
/*
@@ -213,6 +212,7 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
saddr = addr >> 2;
switch (saddr) {
case TIMER_LIMIT:
+ ptimer_transaction_begin(t->timer);
if (slavio_timer_is_user(tc)) {
uint64_t count;
@@ -227,15 +227,14 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
// set limit, reset counter
qemu_irq_lower(t->irq);
t->limit = val & TIMER_MAX_COUNT32;
- if (t->timer) {
- if (t->limit == 0) { /* free-run */
- ptimer_set_limit(t->timer,
- LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
- } else {
- ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 1);
- }
+ if (t->limit == 0) { /* free-run */
+ ptimer_set_limit(t->timer,
+ LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
+ } else {
+ ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 1);
}
}
+ ptimer_transaction_commit(t->timer);
break;
case TIMER_COUNTER:
if (slavio_timer_is_user(tc)) {
@@ -247,7 +246,9 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
t->reached = 0;
count = ((uint64_t)t->counthigh) << 32 | t->count;
trace_slavio_timer_mem_writel_limit(timer_index, count);
+ ptimer_transaction_begin(t->timer);
ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
+ ptimer_transaction_commit(t->timer);
} else {
trace_slavio_timer_mem_writel_counter_invalid();
}
@@ -255,13 +256,16 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
case TIMER_COUNTER_NORST:
// set limit without resetting counter
t->limit = val & TIMER_MAX_COUNT32;
+ ptimer_transaction_begin(t->timer);
if (t->limit == 0) { /* free-run */
ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0);
} else {
ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 0);
}
+ ptimer_transaction_commit(t->timer);
break;
case TIMER_STATUS:
+ ptimer_transaction_begin(t->timer);
if (slavio_timer_is_user(tc)) {
// start/stop user counter
if (val & 1) {
@@ -273,6 +277,7 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
}
}
t->run = val & 1;
+ ptimer_transaction_commit(t->timer);
break;
case TIMER_MODE:
if (timer_index == 0) {
@@ -282,6 +287,7 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
unsigned int processor = 1 << i;
CPUTimerState *curr_timer = &s->cputimer[i + 1];
+ ptimer_transaction_begin(curr_timer->timer);
// check for a change in timer mode for this processor
if ((val & processor) != (s->cputimer_mode & processor)) {
if (val & processor) { // counter -> user timer
@@ -308,6 +314,7 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
trace_slavio_timer_mem_writel_mode_counter(timer_index);
}
}
+ ptimer_transaction_commit(curr_timer->timer);
}
} else {
trace_slavio_timer_mem_writel_mode_invalid();
@@ -367,10 +374,12 @@ static void slavio_timer_reset(DeviceState *d)
curr_timer->count = 0;
curr_timer->reached = 0;
if (i <= s->num_cpus) {
+ ptimer_transaction_begin(curr_timer->timer);
ptimer_set_limit(curr_timer->timer,
LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
ptimer_run(curr_timer->timer, 0);
curr_timer->run = 1;
+ ptimer_transaction_commit(curr_timer->timer);
}
}
s->cputimer_mode = 0;
@@ -380,7 +389,6 @@ static void slavio_timer_init(Object *obj)
{
SLAVIO_TIMERState *s = SLAVIO_TIMER(obj);
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
- QEMUBH *bh;
unsigned int i;
TimerContext *tc;
@@ -392,9 +400,11 @@ static void slavio_timer_init(Object *obj)
tc->s = s;
tc->timer_index = i;
- bh = qemu_bh_new(slavio_timer_irq, tc);
- s->cputimer[i].timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+ s->cputimer[i].timer = ptimer_init(slavio_timer_irq, tc,
+ PTIMER_POLICY_DEFAULT);
+ ptimer_transaction_begin(s->cputimer[i].timer);
ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
+ ptimer_transaction_commit(s->cputimer[i].timer);
size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE;
snprintf(timer_name, sizeof(timer_name), "timer-%i", i);
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
index db02a9142c..0aa399ac69 100644
--- a/hw/timer/trace-events
+++ b/hw/timer/trace-events
@@ -87,3 +87,8 @@ 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"
+
+# bcm2835_systmr.c
+bcm2835_systmr_irq(bool enable) "timer irq state %u"
+bcm2835_systmr_read(uint64_t offset, uint64_t data) "timer read: offset 0x%" PRIx64 " data 0x%" PRIx64
+bcm2835_systmr_write(uint64_t offset, uint64_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx64
diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
index 92dbff304d..7191ea54f5 100644
--- a/hw/timer/xilinx_timer.c
+++ b/hw/timer/xilinx_timer.c
@@ -28,7 +28,6 @@
#include "hw/ptimer.h"
#include "hw/qdev-properties.h"
#include "qemu/log.h"
-#include "qemu/main-loop.h"
#include "qemu/module.h"
#define D(x)
@@ -52,7 +51,6 @@
struct xlx_timer
{
- QEMUBH *bh;
ptimer_state *ptimer;
void *parent;
int nr; /* for debug. */
@@ -134,6 +132,7 @@ timer_read(void *opaque, hwaddr addr, unsigned int size)
return r;
}
+/* Must be called inside ptimer transaction block */
static void timer_enable(struct xlx_timer *xt)
{
uint64_t count;
@@ -174,8 +173,11 @@ timer_write(void *opaque, hwaddr addr,
value &= ~TCSR_TINT;
xt->regs[addr] = value & 0x7ff;
- if (value & TCSR_ENT)
+ if (value & TCSR_ENT) {
+ ptimer_transaction_begin(xt->ptimer);
timer_enable(xt);
+ ptimer_transaction_commit(xt->ptimer);
+ }
break;
default:
@@ -220,9 +222,10 @@ static void xilinx_timer_realize(DeviceState *dev, Error **errp)
xt->parent = t;
xt->nr = i;
- xt->bh = qemu_bh_new(timer_hit, xt);
- xt->ptimer = ptimer_init_with_bh(xt->bh, PTIMER_POLICY_DEFAULT);
+ xt->ptimer = ptimer_init(timer_hit, xt, PTIMER_POLICY_DEFAULT);
+ ptimer_transaction_begin(xt->ptimer);
ptimer_set_freq(xt->ptimer, t->freq_hz);
+ ptimer_transaction_commit(xt->ptimer);
}
memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t, "xlnx.xps-timer",