@samitouri / QOSamiQemu / commits / fb3e0557a4

hw/arm/bcm2838: Route I2C interrupts to GIC

The I2C interrupts are only routed to the legacy interrupt controller. This means that for modern device trees that use the GIC, the interrupts don't work. This patch adds a splitter to route the I2C interrupt to both the legacy interrupt controller and the GIC. Testing Add these lines to QEMU invocation -drive if=none,id=i2c_storage,format=raw,file=eeprom.bin \ -device at24c-eeprom,bus=i2c-bus.1,address=0x50,drive=i2c_storage,rom-size=4096 \ note: eeprom.bin is all zeros Before this change, running i2c get to read from EEPROM would result in this i2cget -y 1 0x50 Error: Read failed After this change, running i2c to read from EEPROM results in this i2cget -y 1 0x50 0x00 The eeprom can now also be enabled in the device tree. Before the eeprom driver load would fail due to the read failing ls -l /sys/bus/i2c/devices/i2c-1/1-0050/ | grep -i eeprom -rw------- 1 root root 4096 May 17 16:57 eeprom Signed-off-by: Nicholas Righi <nicholasrighi@gmail.com> Message-id: 20260609024027.22140-1-nicholasrighi@gmail.com Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Nicholas Righi committed Jun 8, 2026 at 19:40 UTC fb3e0557a4cbd08f22770bbcee7498e013460d65
4 files changed +16
hw/arm/bcm2835_peripherals.c
+9
@@ -179,6 +179,8 @@ static void raspi_peripherals_base_init(Object *obj)
179 &s->orgated_i2c_irq, TYPE_OR_IRQ);
180 object_property_set_int(OBJECT(&s->orgated_i2c_irq), "num-lines",
181 ORGATED_I2C_IRQ_COUNT, &error_abort);
182 + object_initialize_child(obj, "orgated-i2c-irq-splitter",
183 + &s->orgated_i2c_irq_splitter, TYPE_SPLIT_IRQ);
184 }
185
186 static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
@@ -504,7 +506,14 @@ void bcm_soc_peripherals_common_realize(DeviceState *dev, Error **errp)
506 sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[n]), 0,
507 qdev_get_gpio_in(DEVICE(&s->orgated_i2c_irq), n));
508 }
509 +
510 + qdev_prop_set_uint32(DEVICE(&s->orgated_i2c_irq_splitter), "num-lines", 2);
511 + if (!qdev_realize(DEVICE(&s->orgated_i2c_irq_splitter), NULL, errp)) {
512 + return;
513 + }
514 qdev_connect_gpio_out(DEVICE(&s->orgated_i2c_irq), 0,
515 + qdev_get_gpio_in(DEVICE(&s->orgated_i2c_irq_splitter), 0));
516 + qdev_connect_gpio_out(DEVICE(&s->orgated_i2c_irq_splitter), 0,
517 qdev_get_gpio_in_named(DEVICE(&s->ic),
518 BCM2835_IC_GPU_IRQ,
519 INTERRUPT_I2C));
hw/arm/bcm2838.c
+4
@@ -184,6 +184,10 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
184 sysbus_connect_irq(SYS_BUS_DEVICE(&ps_base->aux), 0,
185 qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_AUX_UART1));
186
187 + /* Connect the I2C interrupt to the interrupt controller */
188 + qdev_connect_gpio_out(DEVICE(&ps_base->orgated_i2c_irq_splitter), 1,
189 + qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_I2C));
190 +
191 /* Connect VC mailbox to the interrupt controller */
192 sysbus_connect_irq(SYS_BUS_DEVICE(&ps_base->mboxes), 0,
193 qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_MBOX));
include/hw/arm/bcm2835_peripherals.h
+2
@@ -33,6 +33,7 @@
33 #include "hw/usb/hcd-dwc2.h"
34 #include "hw/ssi/bcm2835_spi.h"
35 #include "hw/i2c/bcm2835_i2c.h"
36 +#include "hw/core/split-irq.h"
37 #include "hw/nvram/bcm2835_otp.h"
38 #include "hw/misc/unimp.h"
39 #include "qom/object.h"
@@ -72,6 +73,7 @@ struct BCMSocPeripheralBaseState {
73 BCM2835SPIState spi[1];
74 BCM2835I2CState i2c[3];
75 OrIRQState orgated_i2c_irq;
76 + SplitIRQ orgated_i2c_irq_splitter;
77 BCM2835OTPState otp;
78 UnimplementedDeviceState dbus;
79 UnimplementedDeviceState ave0;
include/hw/arm/bcm2838_peripherals.h
+1
@@ -22,6 +22,7 @@
22 #define GIC_SPI_INTERRUPT_DMA_7_8 87
23 #define GIC_SPI_INTERRUPT_DMA_9_10 88
24 #define GIC_SPI_INTERRUPT_AUX_UART1 93
25 +#define GIC_SPI_INTERRUPT_I2C 117
26 #define GIC_SPI_INTERRUPT_SDHOST 120
27 #define GIC_SPI_INTERRUPT_UART0 121
28 #define GIC_SPI_INTERRUPT_RNG200 125