SysBus IRQ are *output* IRQs. As some sort of simplification to avoid to forward it, IcpPitState misuses it as ARM timer input IRQ. Fix that by using a simple IRQ forwarder handler.
Signed-off-by: Philippe Mathieu-Daudé <phi...@linaro.org> --- hw/timer/arm_timer.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c index 6f444e1789..874f9b63bc 100644 --- a/hw/timer/arm_timer.c +++ b/hw/timer/arm_timer.c @@ -352,6 +352,7 @@ struct IntegratorPitState { MemoryRegion iomem; ArmTimerState *timer[3]; qemu_irq irq_in[3]; + qemu_irq irq[3]; }; static uint64_t icp_pit_read(void *opaque, hwaddr offset, @@ -391,6 +392,13 @@ static const MemoryRegionOps icp_pit_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; +static void icp_pit_fwd_irq(void *opaque, int n, int level) +{ + IntegratorPitState *s = opaque; + + qemu_set_irq(s->irq[n], level); +} + static void icp_pit_init(Object *obj) { static const uint32_t tmr_freq[] = { @@ -402,9 +410,14 @@ static void icp_pit_init(Object *obj) IntegratorPitState *s = INTEGRATOR_PIT(obj); SysBusDevice *dev = SYS_BUS_DEVICE(obj); + qdev_init_gpio_in_named(DEVICE(obj), icp_pit_fwd_irq, + "timer-in", ARRAY_SIZE(s->timer)); + for (unsigned i = 0; i < ARRAY_SIZE(s->timer); i++) { s->timer[i] = arm_timer_new(tmr_freq[i], s->irq_in[i]); - sysbus_init_irq(dev, &s->irq_in[i]); + sysbus_init_irq(dev, &s->irq[i]); + sysbus_connect_irq(dev, i, + qdev_get_gpio_in_named(DEVICE(obj), "timer-in", i)); } memory_region_init_io(&s->iomem, obj, &icp_pit_ops, s, -- 2.38.1