diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2020-10-20 21:11:35 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2020-10-20 21:11:35 +0100 |
commit | ac793156f650ae2d77834932d72224175ee69086 (patch) | |
tree | 573940f3a8b5ad0e08ea71d2f210f776b7620909 /hw/timer/bcm2835_systmr.c | |
parent | 4c41341af76cfc85b5a6c0f87de4838672ab9f89 (diff) | |
parent | 8128c8e8cc9489a8387c74075974f86dc0222e7f (diff) |
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20201020-1' into staging
target-arm queue:
* Fix AArch32 SMLAD incorrect setting of Q bit
* AArch32 VCVT fixed-point to float is always round-to-nearest
* strongarm: Fix 'time to transmit a char' unit comment
* Restrict APEI tables generation to the 'virt' machine
* bcm2835: minor code cleanups
* bcm2835: connect all IRQs from SYS_timer device
* correctly flush TLBs when TBI is enabled
* tests/qtest: Add npcm7xx timer test
* loads-stores.rst: add footnote that clarifies GETPC usage
* Fix reported EL for mte_check_fail
* Ignore HCR_EL2.ATA when {E2H,TGE} != 11
* microbit_i2c: Fix coredump when dump-vmstate
* nseries: Fix loading kernel image on n8x0 machines
* Implement v8.1M low-overhead-loops
# gpg: Signature made Tue 20 Oct 2020 21:10:35 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-20201020-1: (29 commits)
target/arm: Implement FPSCR.LTPSIZE for M-profile LOB extension
target/arm: Allow M-profile CPUs with FP16 to set FPSCR.FP16
target/arm: Fix has_vfp/has_neon ID reg squashing for M-profile
target/arm: Implement v8.1M low-overhead-loop instructions
target/arm: Implement v8.1M branch-future insns (as NOPs)
target/arm: Don't allow BLX imm for M-profile
target/arm: Make the t32 insn[25:23]=111 group non-overlapping
target/arm: Implement v8.1M conditional-select insns
target/arm: Implement v8.1M NOCP handling
decodetree: Fix codegen for non-overlapping group inside overlapping group
hw/arm/nseries: Fix loading kernel image on n8x0 machines
microbit_i2c: Fix coredump when dump-vmstate
target/arm: Ignore HCR_EL2.ATA when {E2H,TGE} != 11
target/arm: Fix reported EL for mte_check_fail
target/arm: Remove redundant mmu_idx lookup
hw/intc/bcm2836_control: Use IRQ definitions instead of magic numbers
hw/intc/bcm2835_ic: Trace GPU/CPU IRQ handlers
loads-stores.rst: add footnote that clarifies GETPC usage
tests/qtest: Add npcm7xx timer test
target/arm: Use tlb_flush_page_bits_by_mmuidx*
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/timer/bcm2835_systmr.c')
-rw-r--r-- | hw/timer/bcm2835_systmr.c | 57 |
1 files changed, 36 insertions, 21 deletions
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c index 3387a6214a..67669a57ff 100644 --- a/hw/timer/bcm2835_systmr.c +++ b/hw/timer/bcm2835_systmr.c @@ -28,20 +28,13 @@ REG32(COMPARE1, 0x10) REG32(COMPARE2, 0x14) REG32(COMPARE3, 0x18) -static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s) +static void bcm2835_systmr_timer_expire(void *opaque) { - bool enable = !!s->reg.status; + BCM2835SystemTimerCompare *tmr = opaque; - 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); + trace_bcm2835_systmr_timer_expired(tmr->id); + tmr->state->reg.ctrl_status |= 1 << tmr->id; + qemu_set_irq(tmr->irq, 1); } static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset, @@ -52,7 +45,7 @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset, switch (offset) { case A_CTRL_STATUS: - r = s->reg.status; + r = s->reg.ctrl_status; break; case A_COMPARE0 ... A_COMPARE3: r = s->reg.compare[(offset - A_COMPARE0) >> 2]; @@ -75,19 +68,33 @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset, } static void bcm2835_systmr_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) + uint64_t value64, unsigned size) { BCM2835SystemTimerState *s = BCM2835_SYSTIMER(opaque); + int index; + uint32_t value = value64; + uint32_t triggers_delay_us; + uint64_t now; trace_bcm2835_systmr_write(offset, value); switch (offset) { case A_CTRL_STATUS: - s->reg.status &= ~value; /* Ack */ - bcm2835_systmr_update_irq(s); + s->reg.ctrl_status &= ~value; /* Ack */ + for (index = 0; index < ARRAY_SIZE(s->tmr); index++) { + if (extract32(value, index, 1)) { + trace_bcm2835_systmr_irq_ack(index); + qemu_set_irq(s->tmr[index].irq, 0); + } + } break; case A_COMPARE0 ... A_COMPARE3: - s->reg.compare[(offset - A_COMPARE0) >> 2] = value; - bcm2835_systmr_update_compare(s, (offset - A_COMPARE0) >> 2); + index = (offset - A_COMPARE0) >> 2; + s->reg.compare[index] = value; + now = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL); + /* Compare lower 32-bits of the free-running counter. */ + triggers_delay_us = value - now; + trace_bcm2835_systmr_run(index, triggers_delay_us); + timer_mod(&s->tmr[index].timer, now + triggers_delay_us); break; case A_COUNTER_LOW: case A_COUNTER_HIGH: @@ -125,7 +132,14 @@ static void bcm2835_systmr_realize(DeviceState *dev, Error **errp) 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); + + for (size_t i = 0; i < ARRAY_SIZE(s->tmr); i++) { + s->tmr[i].id = i; + s->tmr[i].state = s; + sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->tmr[i].irq); + timer_init_us(&s->tmr[i].timer, QEMU_CLOCK_VIRTUAL, + bcm2835_systmr_timer_expire, &s->tmr[i]); + } } static const VMStateDescription bcm2835_systmr_vmstate = { @@ -133,8 +147,9 @@ static const VMStateDescription bcm2835_systmr_vmstate = { .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_UINT32(reg.status, BCM2835SystemTimerState), - VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState, 4), + VMSTATE_UINT32(reg.ctrl_status, BCM2835SystemTimerState), + VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState, + BCM2835_SYSTIMER_COUNT), VMSTATE_END_OF_LIST() } }; |