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>
This commit is contained in:
committed by
Peter Maydell
parent
335870f28e
commit
fb3e0557a4
@@ -179,6 +179,8 @@ static void raspi_peripherals_base_init(Object *obj)
|
||||
&s->orgated_i2c_irq, TYPE_OR_IRQ);
|
||||
object_property_set_int(OBJECT(&s->orgated_i2c_irq), "num-lines",
|
||||
ORGATED_I2C_IRQ_COUNT, &error_abort);
|
||||
object_initialize_child(obj, "orgated-i2c-irq-splitter",
|
||||
&s->orgated_i2c_irq_splitter, TYPE_SPLIT_IRQ);
|
||||
}
|
||||
|
||||
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
|
||||
@@ -504,7 +506,14 @@ void bcm_soc_peripherals_common_realize(DeviceState *dev, Error **errp)
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[n]), 0,
|
||||
qdev_get_gpio_in(DEVICE(&s->orgated_i2c_irq), n));
|
||||
}
|
||||
|
||||
qdev_prop_set_uint32(DEVICE(&s->orgated_i2c_irq_splitter), "num-lines", 2);
|
||||
if (!qdev_realize(DEVICE(&s->orgated_i2c_irq_splitter), NULL, errp)) {
|
||||
return;
|
||||
}
|
||||
qdev_connect_gpio_out(DEVICE(&s->orgated_i2c_irq), 0,
|
||||
qdev_get_gpio_in(DEVICE(&s->orgated_i2c_irq_splitter), 0));
|
||||
qdev_connect_gpio_out(DEVICE(&s->orgated_i2c_irq_splitter), 0,
|
||||
qdev_get_gpio_in_named(DEVICE(&s->ic),
|
||||
BCM2835_IC_GPU_IRQ,
|
||||
INTERRUPT_I2C));
|
||||
|
||||
@@ -184,6 +184,10 @@ static void bcm2838_realize(DeviceState *dev, Error **errp)
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&ps_base->aux), 0,
|
||||
qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_AUX_UART1));
|
||||
|
||||
/* Connect the I2C interrupt to the interrupt controller */
|
||||
qdev_connect_gpio_out(DEVICE(&ps_base->orgated_i2c_irq_splitter), 1,
|
||||
qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_I2C));
|
||||
|
||||
/* Connect VC mailbox to the interrupt controller */
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&ps_base->mboxes), 0,
|
||||
qdev_get_gpio_in(gicdev, GIC_SPI_INTERRUPT_MBOX));
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "hw/usb/hcd-dwc2.h"
|
||||
#include "hw/ssi/bcm2835_spi.h"
|
||||
#include "hw/i2c/bcm2835_i2c.h"
|
||||
#include "hw/core/split-irq.h"
|
||||
#include "hw/nvram/bcm2835_otp.h"
|
||||
#include "hw/misc/unimp.h"
|
||||
#include "qom/object.h"
|
||||
@@ -72,6 +73,7 @@ struct BCMSocPeripheralBaseState {
|
||||
BCM2835SPIState spi[1];
|
||||
BCM2835I2CState i2c[3];
|
||||
OrIRQState orgated_i2c_irq;
|
||||
SplitIRQ orgated_i2c_irq_splitter;
|
||||
BCM2835OTPState otp;
|
||||
UnimplementedDeviceState dbus;
|
||||
UnimplementedDeviceState ave0;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#define GIC_SPI_INTERRUPT_DMA_7_8 87
|
||||
#define GIC_SPI_INTERRUPT_DMA_9_10 88
|
||||
#define GIC_SPI_INTERRUPT_AUX_UART1 93
|
||||
#define GIC_SPI_INTERRUPT_I2C 117
|
||||
#define GIC_SPI_INTERRUPT_SDHOST 120
|
||||
#define GIC_SPI_INTERRUPT_UART0 121
|
||||
#define GIC_SPI_INTERRUPT_RNG200 125
|
||||
|
||||
Reference in New Issue
Block a user