Changeset View
Changeset View
Standalone View
Standalone View
sys/arm64/arm64/gic_v3.c
Show First 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | |||||
#include "msi_if.h" | #include "msi_if.h" | ||||
#include <arm/arm/gic_common.h> | #include <arm/arm/gic_common.h> | ||||
#include "gic_v3_reg.h" | #include "gic_v3_reg.h" | ||||
#include "gic_v3_var.h" | #include "gic_v3_var.h" | ||||
static bus_get_domain_t gic_v3_get_domain; | static bus_get_domain_t gic_v3_get_domain; | ||||
static bus_read_ivar_t gic_v3_read_ivar; | static bus_read_ivar_t gic_v3_read_ivar; | ||||
static bus_write_ivar_t gic_v3_write_ivar; | |||||
static pic_disable_intr_t gic_v3_disable_intr; | static pic_disable_intr_t gic_v3_disable_intr; | ||||
static pic_enable_intr_t gic_v3_enable_intr; | static pic_enable_intr_t gic_v3_enable_intr; | ||||
static pic_map_intr_t gic_v3_map_intr; | static pic_map_intr_t gic_v3_map_intr; | ||||
static pic_setup_intr_t gic_v3_setup_intr; | static pic_setup_intr_t gic_v3_setup_intr; | ||||
static pic_teardown_intr_t gic_v3_teardown_intr; | static pic_teardown_intr_t gic_v3_teardown_intr; | ||||
static pic_post_filter_t gic_v3_post_filter; | static pic_post_filter_t gic_v3_post_filter; | ||||
static pic_post_ithread_t gic_v3_post_ithread; | static pic_post_ithread_t gic_v3_post_ithread; | ||||
Show All 19 Lines | |||||
static device_method_t gic_v3_methods[] = { | static device_method_t gic_v3_methods[] = { | ||||
/* Device interface */ | /* Device interface */ | ||||
DEVMETHOD(device_detach, gic_v3_detach), | DEVMETHOD(device_detach, gic_v3_detach), | ||||
/* Bus interface */ | /* Bus interface */ | ||||
DEVMETHOD(bus_get_domain, gic_v3_get_domain), | DEVMETHOD(bus_get_domain, gic_v3_get_domain), | ||||
DEVMETHOD(bus_read_ivar, gic_v3_read_ivar), | DEVMETHOD(bus_read_ivar, gic_v3_read_ivar), | ||||
DEVMETHOD(bus_write_ivar, gic_v3_write_ivar), | |||||
/* Interrupt controller interface */ | /* Interrupt controller interface */ | ||||
DEVMETHOD(pic_disable_intr, gic_v3_disable_intr), | DEVMETHOD(pic_disable_intr, gic_v3_disable_intr), | ||||
DEVMETHOD(pic_enable_intr, gic_v3_enable_intr), | DEVMETHOD(pic_enable_intr, gic_v3_enable_intr), | ||||
DEVMETHOD(pic_map_intr, gic_v3_map_intr), | DEVMETHOD(pic_map_intr, gic_v3_map_intr), | ||||
DEVMETHOD(pic_setup_intr, gic_v3_setup_intr), | DEVMETHOD(pic_setup_intr, gic_v3_setup_intr), | ||||
DEVMETHOD(pic_teardown_intr, gic_v3_teardown_intr), | DEVMETHOD(pic_teardown_intr, gic_v3_teardown_intr), | ||||
DEVMETHOD(pic_post_filter, gic_v3_post_filter), | DEVMETHOD(pic_post_filter, gic_v3_post_filter), | ||||
▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Lines | gic_r_write_8(device_t dev, bus_size_t offset, uint64_t val) | ||||
struct gic_v3_softc *sc; | struct gic_v3_softc *sc; | ||||
struct resource *rdist; | struct resource *rdist; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
rdist = &sc->gic_redists.pcpu[PCPU_GET(cpuid)]->res; | rdist = &sc->gic_redists.pcpu[PCPU_GET(cpuid)]->res; | ||||
bus_write_8(rdist, offset, val); | bus_write_8(rdist, offset, val); | ||||
} | } | ||||
static void | |||||
gic_v3_reserve_msi_range(device_t dev, u_int start, u_int count) | |||||
{ | |||||
struct gic_v3_softc *sc; | |||||
int i; | |||||
sc = device_get_softc(dev); | |||||
KASSERT((start + count) < sc->gic_nirqs, | |||||
("%s: Trying to allocate too many MSI IRQs: %d + %d > %d", __func__, | |||||
start, count, sc->gic_nirqs)); | |||||
for (i = 0; i < count; i++) { | |||||
KASSERT(sc->gic_irqs[start + i].gi_isrc.isrc_handlers == 0, | |||||
("%s: MSI interrupt %d already has a handler", __func__, | |||||
count + i)); | |||||
KASSERT(sc->gic_irqs[start + i].gi_pol == INTR_POLARITY_CONFORM, | |||||
("%s: MSI interrupt %d already has a polarity", __func__, | |||||
count + i)); | |||||
KASSERT(sc->gic_irqs[start + i].gi_trig == INTR_TRIGGER_CONFORM, | |||||
("%s: MSI interrupt %d already has a trigger", __func__, | |||||
count + i)); | |||||
sc->gic_irqs[start + i].gi_pol = INTR_POLARITY_HIGH; | |||||
sc->gic_irqs[start + i].gi_trig = INTR_TRIGGER_EDGE; | |||||
sc->gic_irqs[start + i].gi_flags |= GI_FLAG_MSI; | |||||
} | |||||
} | |||||
/* | /* | ||||
* Device interface. | * Device interface. | ||||
*/ | */ | ||||
int | int | ||||
gic_v3_attach(device_t dev) | gic_v3_attach(device_t dev) | ||||
{ | { | ||||
struct gic_v3_softc *sc; | struct gic_v3_softc *sc; | ||||
gic_v3_initseq_t *init_func; | gic_v3_initseq_t *init_func; | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | for (irq = 0; irq < sc->gic_nirqs; irq++) { | ||||
} | } | ||||
if (err != 0) { | if (err != 0) { | ||||
/* XXX call intr_isrc_deregister() */ | /* XXX call intr_isrc_deregister() */ | ||||
free(sc->gic_irqs, M_DEVBUF); | free(sc->gic_irqs, M_DEVBUF); | ||||
return (err); | return (err); | ||||
} | } | ||||
} | } | ||||
mtx_init(&sc->gic_mbi_mtx, "GICv3 mbi lock", NULL, MTX_DEF); | |||||
if (sc->gic_mbi_start > 0) { | if (sc->gic_mbi_start > 0) { | ||||
/* Reserve these interrupts for MSI/MSI-X use */ | gic_v3_reserve_msi_range(dev, sc->gic_mbi_start, | ||||
for (irq = sc->gic_mbi_start; irq <= sc->gic_mbi_end; irq++) { | sc->gic_mbi_end - sc->gic_mbi_start); | ||||
sc->gic_irqs[irq].gi_pol = INTR_POLARITY_HIGH; | |||||
sc->gic_irqs[irq].gi_trig = INTR_TRIGGER_EDGE; | |||||
sc->gic_irqs[irq].gi_flags |= GI_FLAG_MSI; | |||||
} | |||||
mtx_init(&sc->gic_mbi_mtx, "GICv3 mbi lock", NULL, MTX_DEF); | |||||
if (bootverbose) { | if (bootverbose) { | ||||
device_printf(dev, "using spi %u to %u\n", sc->gic_mbi_start, | device_printf(dev, "using spi %u to %u\n", sc->gic_mbi_start, | ||||
sc->gic_mbi_end); | sc->gic_mbi_end); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Read the Peripheral ID2 register. This is an implementation | * Read the Peripheral ID2 register. This is an implementation | ||||
▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | case GIC_IVAR_HW_REV: | ||||
*result = GICR_PIDR2_ARCH(sc->gic_pidr2); | *result = GICR_PIDR2_ARCH(sc->gic_pidr2); | ||||
return (0); | return (0); | ||||
case GIC_IVAR_BUS: | case GIC_IVAR_BUS: | ||||
KASSERT(sc->gic_bus != GIC_BUS_UNKNOWN, | KASSERT(sc->gic_bus != GIC_BUS_UNKNOWN, | ||||
("gic_v3_read_ivar: Unknown bus type")); | ("gic_v3_read_ivar: Unknown bus type")); | ||||
KASSERT(sc->gic_bus <= GIC_BUS_MAX, | KASSERT(sc->gic_bus <= GIC_BUS_MAX, | ||||
("gic_v3_read_ivar: Invalid bus type %u", sc->gic_bus)); | ("gic_v3_read_ivar: Invalid bus type %u", sc->gic_bus)); | ||||
*result = sc->gic_bus; | *result = sc->gic_bus; | ||||
return (0); | |||||
case GIC_IVAR_MBI_START: | |||||
*result = sc->gic_mbi_start; | |||||
return (0); | |||||
case GIC_IVAR_MBI_COUNT: | |||||
*result = sc->gic_mbi_end - sc->gic_mbi_start; | |||||
return (0); | |||||
} | |||||
return (ENOENT); | |||||
} | |||||
static int | |||||
gic_v3_write_ivar(device_t dev, device_t child, int which, uintptr_t value) | |||||
{ | |||||
struct gic_v3_softc *sc; | |||||
sc = device_get_softc(dev); | |||||
switch(which) { | |||||
case GICV3_IVAR_NIRQS: | |||||
case GICV3_IVAR_REDIST: | |||||
case GIC_IVAR_HW_REV: | |||||
case GIC_IVAR_BUS: | |||||
return (EINVAL); | |||||
case GIC_IVAR_MBI_START: | |||||
/* | |||||
* GIC_IVAR_MBI_START must be set once and first. This allows | |||||
* us to reserve the registers when GIC_IVAR_MBI_COUNT is set. | |||||
*/ | |||||
MPASS(sc->gic_mbi_start == 0); | |||||
MPASS(sc->gic_mbi_end == 0); | |||||
MPASS(value >= GIC_FIRST_SPI); | |||||
MPASS(value < sc->gic_nirqs); | |||||
sc->gic_mbi_start = value; | |||||
return (0); | |||||
case GIC_IVAR_MBI_COUNT: | |||||
MPASS(sc->gic_mbi_start != 0); | |||||
MPASS(sc->gic_mbi_end == 0); | |||||
MPASS(value >= sc->gic_mbi_start); | |||||
MPASS(value >= GIC_FIRST_SPI); | |||||
sc->gic_mbi_end = value - sc->gic_mbi_start; | |||||
MPASS(sc->gic_mbi_end <= sc->gic_nirqs); | |||||
/* Reserve these interrupts for MSI/MSI-X use */ | |||||
gic_v3_reserve_msi_range(dev, sc->gic_mbi_start, value); | |||||
return (0); | return (0); | ||||
} | } | ||||
return (ENOENT); | return (ENOENT); | ||||
} | } | ||||
int | int | ||||
arm_gic_v3_intr(void *arg) | arm_gic_v3_intr(void *arg) | ||||
▲ Show 20 Lines • Show All 1,016 Lines • Show Last 20 Lines |