Index: sys/arm/arm/gic.h =================================================================== --- sys/arm/arm/gic.h +++ sys/arm/arm/gic.h @@ -76,6 +76,7 @@ u_int sc_spi_start; u_int sc_spi_end; u_int sc_spi_count; + int sc_spi_offset; }; DECLARE_CLASS(arm_gicv2m_driver); Index: sys/arm/arm/gic.c =================================================================== --- sys/arm/arm/gic.c +++ sys/arm/arm/gic.c @@ -1043,12 +1043,15 @@ #define MSI_TYPER_SPI_COUNT(x) (((x) >> 0) & 0x3ff) #define GICv2M_MSI_SETSPI_NS 0x040 #define GICV2M_MSI_IIDR 0xFCC +#define BCM_NS2_GICV2M_MSI_IIDR 0x0000013f + int arm_gicv2m_attach(device_t dev) { struct arm_gicv2m_softc *sc; uint32_t typer; + uint32_t iidr; int rid; #ifdef FDT phandle_t node; @@ -1101,6 +1104,24 @@ device_printf(dev, "using spi %u to %u\n", sc->sc_spi_start, sc->sc_spi_start + sc->sc_spi_count - 1); + /* Vendor-dependent quirks */ + iidr = bus_read_4(sc->sc_mem, GICV2M_MSI_IIDR); + switch (iidr) { + case BCM_NS2_GICV2M_MSI_IIDR: + /* + * Broadcom NS2 requires offset of -32 between SPI and + * MSI data value. + */ + sc->sc_spi_offset = -32; + if (bootverbose) + device_printf(dev, + "applying Broadcom NS2 erratum for MSI/MSIx mapping\n"); + break; + default: + sc->sc_spi_offset = 0; + break; + } + return (0); } @@ -1259,7 +1280,7 @@ struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc; *addr = vtophys(rman_get_virtual(sc->sc_mem)) + GICv2M_MSI_SETSPI_NS; - *data = gi->gi_irq; + *data = gi->gi_irq + sc->sc_spi_offset; return (0); }