Add support for MSI interrupts to the gicv2m controller. The allocation

is still quite simplistic, it just increments a counter to use the next
interrupt.

Obtained from:	ABT Systems Ltd
Sponsored by:	SoftIron Inc
This commit is contained in:
Andrew Turner 2015-12-14 16:07:20 +00:00
parent 9f9d157d82
commit 68fe2d8f70

View File

@ -431,6 +431,39 @@ gicv2m_alloc_msix(device_t dev, device_t pci_dev, int *pirq)
return (0);
}
static int
gicv2m_alloc_msi(device_t dev, device_t pci_dev, int count, int *irqs)
{
struct arm_gic_softc *psc;
struct gicv2m_softc *sc;
uint32_t reg;
int i, irq;
psc = device_get_softc(device_get_parent(dev));
sc = device_get_softc(dev);
mtx_lock(&sc->sc_mutex);
KASSERT(sc->sc_spi_offset + count <= sc->sc_spi_count,
("No free SPIs for %d MSI interrupts", count));
/* Find an unused interrupt */
for (i = 0; i < count; i++) {
irq = sc->sc_spi_start + sc->sc_spi_offset;
sc->sc_spi_offset++;
/* Interrupts need to be edge triggered, set this */
reg = gic_d_read_4(psc, GICD_ICFGR(irq >> 4));
reg |= (GICD_ICFGR_TRIG_EDGE | GICD_ICFGR_POL_HIGH) <<
((irq & 0xf) * 2);
gic_d_write_4(psc, GICD_ICFGR(irq >> 4), reg);
irqs[i] = irq;
}
mtx_unlock(&sc->sc_mutex);
return (0);
}
static int
gicv2m_map_msi(device_t dev, device_t pci_dev, int irq, uint64_t *addr,
uint32_t *data)
@ -448,8 +481,9 @@ static device_method_t arm_gicv2m_methods[] = {
DEVMETHOD(device_probe, gicv2m_probe),
DEVMETHOD(device_attach, gicv2m_attach),
/* MSI-X */
/* MSI/MSI-X */
DEVMETHOD(pic_alloc_msix, gicv2m_alloc_msix),
DEVMETHOD(pic_alloc_msi, gicv2m_alloc_msi),
DEVMETHOD(pic_map_msi, gicv2m_map_msi),
{ 0, 0 }