diff mbox series

[v2,15/19] hw/timer/arm_timer: Fix misuse of SysBus IRQ in IntegratorPIT

Message ID 20230704145012.49870-16-philmd@linaro.org
State New
Headers show
Series hw/timer/arm_timer: QOM'ify ARM_TIMER and correct sysbus/irq in ICP_PIT | expand

Commit Message

Philippe Mathieu-Daudé July 4, 2023, 2:50 p.m. UTC
SysBus IRQ are *output* IRQs. As some sort of simplification
to avoid to forward it, IntegratorPIT misuses it as ARM timer
input IRQ. Fix that by using a simple IRQ forwarder handler.

Note: sysbus_pass_irq() forwards GPIOs and IRQs from a container
to an inner device but only work with an entire set of IRQs, so
we can not use it here where we forward a single IRQ from each
timer.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/timer/arm_timer.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

Comments

Richard Henderson July 5, 2023, 3:40 p.m. UTC | #1
On 7/4/23 16:50, Philippe Mathieu-Daudé wrote:
> SysBus IRQ are*output*  IRQs. As some sort of simplification
> to avoid to forward it, IntegratorPIT misuses it as ARM timer
> input IRQ. Fix that by using a simple IRQ forwarder handler.
> 
> Note: sysbus_pass_irq() forwards GPIOs and IRQs from a container
> to an inner device but only work with an entire set of IRQs, so
> we can not use it here where we forward a single IRQ from each
> timer.
> 
> Signed-off-by: Philippe Mathieu-Daudé<philmd@linaro.org>
> Reviewed-by: Peter Maydell<peter.maydell@linaro.org>
> ---
>   hw/timer/arm_timer.c | 15 ++++++++++++++-
>   1 file changed, 14 insertions(+), 1 deletion(-)

Acked-by: Richard Henderson <richard.henderson@linaro.org>

r~
diff mbox series

Patch

diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c
index f6bec28884..aae7f3cf9d 100644
--- a/hw/timer/arm_timer.c
+++ b/hw/timer/arm_timer.c
@@ -344,6 +344,7 @@  struct IntegratorPIT {
     MemoryRegion iomem;
     ArmTimer *timer[3];
     qemu_irq irq_in[3];
+    qemu_irq irq[3];
 };
 
 static uint64_t icp_pit_read(void *opaque, hwaddr offset,
@@ -383,6 +384,13 @@  static const MemoryRegionOps icp_pit_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
+static void icp_pit_fwd_irq(void *opaque, int n, int level)
+{
+    IntegratorPIT *s = opaque;
+
+    qemu_set_irq(s->irq[n], level);
+}
+
 static void icp_pit_init(Object *obj)
 {
     static const uint32_t tmr_freq[] = {
@@ -394,9 +402,14 @@  static void icp_pit_init(Object *obj)
     IntegratorPIT *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,