Introduce ITS support for ARM64
Add ARM ITS (Interrupt Translation Services) support required to bring-up message signalled interrupts on some ARM64 platforms. Obtained from: Semihalf Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
88db72c33d
commit
5265baf791
@ -236,19 +236,18 @@ gic_v3_dispatch(device_t dev, struct trapframe *frame)
|
||||
break;
|
||||
|
||||
if (__predict_true((active_irq >= GIC_FIRST_PPI &&
|
||||
active_irq <= GIC_LAST_SPI))) {
|
||||
active_irq <= GIC_LAST_SPI) || active_irq >= GIC_FIRST_LPI)) {
|
||||
arm_dispatch_intr(active_irq, frame);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (active_irq <= GIC_LAST_SGI || active_irq >= GIC_FIRST_LPI) {
|
||||
if (active_irq <= GIC_LAST_SGI) {
|
||||
/*
|
||||
* TODO: Implement proper SGI/LPI handling.
|
||||
* TODO: Implement proper SGI handling.
|
||||
* Mask it if such is received for some reason.
|
||||
*/
|
||||
device_printf(dev,
|
||||
"Received unsupported interrupt type: %s\n",
|
||||
active_irq >= GIC_FIRST_LPI ? "LPI" : "SGI");
|
||||
"Received unsupported interrupt type: SGI\n");
|
||||
PIC_MASK(dev, active_irq);
|
||||
}
|
||||
}
|
||||
@ -275,6 +274,8 @@ gic_v3_mask_irq(device_t dev, u_int irq)
|
||||
} else if (irq >= GIC_FIRST_SPI && irq <= GIC_LAST_SPI) { /* SPIs in distributor */
|
||||
gic_r_write(sc, 4, GICD_ICENABLER(irq), GICD_I_MASK(irq));
|
||||
gic_v3_wait_for_rwp(sc, DIST);
|
||||
} else if (irq >= GIC_FIRST_LPI) { /* LPIs */
|
||||
lpi_mask_irq(dev, irq);
|
||||
} else
|
||||
panic("%s: Unsupported IRQ number %u", __func__, irq);
|
||||
}
|
||||
@ -293,6 +294,8 @@ gic_v3_unmask_irq(device_t dev, u_int irq)
|
||||
} else if (irq >= GIC_FIRST_SPI && irq <= GIC_LAST_SPI) { /* SPIs in distributor */
|
||||
gic_d_write(sc, 4, GICD_ISENABLER(irq), GICD_I_MASK(irq));
|
||||
gic_v3_wait_for_rwp(sc, DIST);
|
||||
} else if (irq >= GIC_FIRST_LPI) { /* LPIs */
|
||||
lpi_unmask_irq(dev, irq);
|
||||
} else
|
||||
panic("%s: Unsupported IRQ number %u", __func__, irq);
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
@ -51,11 +53,27 @@ __FBSDID("$FreeBSD$");
|
||||
static int gic_v3_fdt_probe(device_t);
|
||||
static int gic_v3_fdt_attach(device_t);
|
||||
|
||||
static struct resource *gic_v3_ofw_bus_alloc_res(device_t, device_t, int, int *,
|
||||
u_long, u_long, u_long, u_int);
|
||||
static const struct ofw_bus_devinfo *gic_v3_ofw_get_devinfo(device_t, device_t);
|
||||
|
||||
static device_method_t gic_v3_fdt_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, gic_v3_fdt_probe),
|
||||
DEVMETHOD(device_attach, gic_v3_fdt_attach),
|
||||
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_alloc_resource, gic_v3_ofw_bus_alloc_res),
|
||||
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
||||
|
||||
/* ofw_bus interface */
|
||||
DEVMETHOD(ofw_bus_get_devinfo, gic_v3_ofw_get_devinfo),
|
||||
DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
|
||||
DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
|
||||
DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
|
||||
DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
|
||||
DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
|
||||
|
||||
/* End */
|
||||
DEVMETHOD_END
|
||||
};
|
||||
@ -70,6 +88,11 @@ EARLY_DRIVER_MODULE(gic_v3, simplebus, gic_v3_fdt_driver, gic_v3_fdt_devclass,
|
||||
EARLY_DRIVER_MODULE(gic_v3, ofwbus, gic_v3_fdt_driver, gic_v3_fdt_devclass,
|
||||
0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
|
||||
|
||||
/*
|
||||
* Helper functions declarations.
|
||||
*/
|
||||
static int gic_v3_ofw_bus_attach(device_t);
|
||||
|
||||
/*
|
||||
* Device interface.
|
||||
*/
|
||||
@ -109,6 +132,17 @@ gic_v3_fdt_attach(device_t dev)
|
||||
err = gic_v3_attach(dev);
|
||||
if (err)
|
||||
goto error;
|
||||
/*
|
||||
* Try to register ITS to this GIC.
|
||||
* GIC will act as a bus in that case.
|
||||
* Failure here will not affect main GIC functionality.
|
||||
*/
|
||||
if (gic_v3_ofw_bus_attach(dev) != 0) {
|
||||
if (bootverbose) {
|
||||
device_printf(dev,
|
||||
"Failed to attach ITS to this GIC\n");
|
||||
}
|
||||
}
|
||||
|
||||
return (err);
|
||||
|
||||
@ -122,3 +156,155 @@ gic_v3_fdt_attach(device_t dev)
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
/* OFW bus interface */
|
||||
struct gic_v3_ofw_devinfo {
|
||||
struct ofw_bus_devinfo di_dinfo;
|
||||
struct resource_list di_rl;
|
||||
};
|
||||
|
||||
static const struct ofw_bus_devinfo *
|
||||
gic_v3_ofw_get_devinfo(device_t bus __unused, device_t child)
|
||||
{
|
||||
struct gic_v3_ofw_devinfo *di;
|
||||
|
||||
di = device_get_ivars(child);
|
||||
return (&di->di_dinfo);
|
||||
}
|
||||
|
||||
static struct resource *
|
||||
gic_v3_ofw_bus_alloc_res(device_t bus, device_t child, int type, int *rid,
|
||||
u_long start, u_long end, u_long count, u_int flags)
|
||||
{
|
||||
struct gic_v3_ofw_devinfo *di;
|
||||
struct resource_list_entry *rle;
|
||||
int ranges_len;
|
||||
|
||||
if ((start == 0UL) && (end == ~0UL)) {
|
||||
if ((di = device_get_ivars(child)) == NULL)
|
||||
return (NULL);
|
||||
if (type != SYS_RES_MEMORY)
|
||||
return (NULL);
|
||||
|
||||
/* Find defaults for this rid */
|
||||
rle = resource_list_find(&di->di_rl, type, *rid);
|
||||
if (rle == NULL)
|
||||
return (NULL);
|
||||
|
||||
start = rle->start;
|
||||
end = rle->end;
|
||||
count = rle->count;
|
||||
}
|
||||
/*
|
||||
* XXX: No ranges remap!
|
||||
* Absolute address is expected.
|
||||
*/
|
||||
if (ofw_bus_has_prop(bus, "ranges")) {
|
||||
ranges_len = OF_getproplen(ofw_bus_get_node(bus), "ranges");
|
||||
if (ranges_len != 0) {
|
||||
if (bootverbose) {
|
||||
device_printf(child,
|
||||
"Ranges remap not supported\n");
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
|
||||
count, flags));
|
||||
}
|
||||
|
||||
/* Helper functions */
|
||||
|
||||
/*
|
||||
* Bus capability support for GICv3.
|
||||
* Collects and configures device informations and finally
|
||||
* adds ITS device as a child of GICv3 in Newbus hierarchy.
|
||||
*/
|
||||
static int
|
||||
gic_v3_ofw_bus_attach(device_t dev)
|
||||
{
|
||||
struct gic_v3_ofw_devinfo *di;
|
||||
device_t child;
|
||||
phandle_t parent, node;
|
||||
pcell_t addr_cells, size_cells;
|
||||
|
||||
parent = ofw_bus_get_node(dev);
|
||||
if (parent > 0) {
|
||||
addr_cells = 2;
|
||||
OF_getencprop(parent, "#address-cells", &addr_cells,
|
||||
sizeof(addr_cells));
|
||||
size_cells = 2;
|
||||
OF_getencprop(parent, "#size-cells", &size_cells,
|
||||
sizeof(size_cells));
|
||||
/* Iterate through all GIC subordinates */
|
||||
for (node = OF_child(parent); node > 0; node = OF_peer(node)) {
|
||||
/* Allocate and populate devinfo. */
|
||||
di = malloc(sizeof(*di), M_GIC_V3, M_WAITOK | M_ZERO);
|
||||
if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node)) {
|
||||
if (bootverbose) {
|
||||
device_printf(dev,
|
||||
"Could not set up devinfo for ITS\n");
|
||||
}
|
||||
free(di, M_GIC_V3);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Initialize and populate resource list. */
|
||||
resource_list_init(&di->di_rl);
|
||||
ofw_bus_reg_to_rl(dev, node, addr_cells, size_cells,
|
||||
&di->di_rl);
|
||||
|
||||
/* Should not have any interrupts, so don't add any */
|
||||
|
||||
/* Add newbus device for this FDT node */
|
||||
child = device_add_child(dev, NULL, -1);
|
||||
if (!child) {
|
||||
if (bootverbose) {
|
||||
device_printf(dev,
|
||||
"Could not add child: %s\n",
|
||||
di->di_dinfo.obd_name);
|
||||
}
|
||||
resource_list_free(&di->di_rl);
|
||||
ofw_bus_gen_destroy_devinfo(&di->di_dinfo);
|
||||
free(di, M_GIC_V3);
|
||||
continue;
|
||||
}
|
||||
|
||||
device_set_ivars(child, di);
|
||||
}
|
||||
}
|
||||
|
||||
return (bus_generic_attach(dev));
|
||||
}
|
||||
|
||||
static int gic_v3_its_fdt_probe(device_t dev);
|
||||
|
||||
static device_method_t gic_v3_its_fdt_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, gic_v3_its_fdt_probe),
|
||||
|
||||
/* End */
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_1(gic_v3_its, gic_v3_its_fdt_driver, gic_v3_its_fdt_methods,
|
||||
sizeof(struct gic_v3_its_softc), gic_v3_its_driver);
|
||||
|
||||
static devclass_t gic_v3_its_fdt_devclass;
|
||||
|
||||
EARLY_DRIVER_MODULE(gic_v3_its, gic_v3, gic_v3_its_fdt_driver,
|
||||
gic_v3_its_fdt_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
|
||||
|
||||
static int
|
||||
gic_v3_its_fdt_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, GIC_V3_ITS_COMPSTR))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, GIC_V3_ITS_DEVSTR);
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
1448
sys/arm64/arm64/gic_v3_its.c
Normal file
1448
sys/arm64/arm64/gic_v3_its.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -101,17 +101,100 @@
|
||||
#define GICR_PIDR2_ARCH_GICv4 (0x40)
|
||||
|
||||
/* Redistributor registers */
|
||||
#define GICR_CTLR GICD_CTLR
|
||||
#define GICR_CTLR_LPI_ENABLE (1 << 0)
|
||||
|
||||
#define GICR_PIDR2 GICD_PIDR2
|
||||
|
||||
#define GICR_TYPER (0x0008)
|
||||
#define GICR_TYPER_PLPIS (1 << 0)
|
||||
#define GICR_TYPER_VLPIS (1 << 1)
|
||||
#define GICR_TYPER_LAST (1 << 4)
|
||||
#define GICR_TYPER_CPUNUM_SHIFT (8)
|
||||
#define GICR_TYPER_CPUNUM_MASK (0xFFFUL << GICR_TYPER_CPUNUM_SHIFT)
|
||||
#define GICR_TYPER_CPUNUM(x) \
|
||||
(((x) & GICR_TYPER_CPUNUM_MASK) >> GICR_TYPER_CPUNUM_SHIFT)
|
||||
#define GICR_TYPER_AFF_SHIFT (32)
|
||||
|
||||
#define GICR_WAKER (0x0014)
|
||||
#define GICR_WAKER_PS (1 << 1) /* Processor sleep */
|
||||
#define GICR_WAKER_CA (1 << 2) /* Children asleep */
|
||||
|
||||
#define GICR_PROPBASER (0x0070)
|
||||
#define GICR_PROPBASER_IDBITS_MASK 0x1FUL
|
||||
/*
|
||||
* Cacheability
|
||||
* 0x0 - Device-nGnRnE
|
||||
* 0x1 - Normal Inner Non-cacheable
|
||||
* 0x2 - Normal Inner Read-allocate, Write-through
|
||||
* 0x3 - Normal Inner Read-allocate, Write-back
|
||||
* 0x4 - Normal Inner Write-allocate, Write-through
|
||||
* 0x5 - Normal Inner Write-allocate, Write-back
|
||||
* 0x6 - Normal Inner Read-allocate, Write-allocate, Write-through
|
||||
* 0x7 - Normal Inner Read-allocate, Write-allocate, Write-back
|
||||
*/
|
||||
#define GICR_PROPBASER_CACHE_SHIFT 7
|
||||
#define GICR_PROPBASER_CACHE_DnGnRnE 0x0UL
|
||||
#define GICR_PROPBASER_CACHE_NIN 0x1UL
|
||||
#define GICR_PROPBASER_CACHE_NIRAWT 0x2UL
|
||||
#define GICR_PROPBASER_CACHE_NIRAWB 0x3UL
|
||||
#define GICR_PROPBASER_CACHE_NIWAWT 0x4UL
|
||||
#define GICR_PROPBASER_CACHE_NIWAWB 0x5UL
|
||||
#define GICR_PROPBASER_CACHE_NIRAWAWT 0x6UL
|
||||
#define GICR_PROPBASER_CACHE_NIRAWAWB 0x7UL
|
||||
|
||||
/*
|
||||
* Shareability
|
||||
* 0x0 - Non-shareable
|
||||
* 0x1 - Inner-shareable
|
||||
* 0x2 - Outer-shareable
|
||||
* 0x3 - Reserved. Threated as 0x0
|
||||
*/
|
||||
#define GICR_PROPBASER_SHARE_SHIFT 10
|
||||
#define GICR_PROPBASER_SHARE_NS 0x0UL
|
||||
#define GICR_PROPBASER_SHARE_IS 0x1UL
|
||||
#define GICR_PROPBASER_SHARE_OS 0x2UL
|
||||
#define GICR_PROPBASER_SHARE_RES 0x3UL
|
||||
#define GICR_PROPBASER_SHARE_MASK \
|
||||
(0x3UL << GICR_PROPBASER_SHARE_SHIFT)
|
||||
|
||||
#define GICR_PENDBASER (0x0078)
|
||||
/*
|
||||
* Cacheability
|
||||
* 0x0 - Device-nGnRnE
|
||||
* 0x1 - Normal Inner Non-cacheable
|
||||
* 0x2 - Normal Inner Read-allocate, Write-through
|
||||
* 0x3 - Normal Inner Read-allocate, Write-back
|
||||
* 0x4 - Normal Inner Write-allocate, Write-through
|
||||
* 0x5 - Normal Inner Write-allocate, Write-back
|
||||
* 0x6 - Normal Inner Read-allocate, Write-allocate, Write-through
|
||||
* 0x7 - Normal Inner Read-allocate, Write-allocate, Write-back
|
||||
*/
|
||||
#define GICR_PENDBASER_CACHE_SHIFT 7
|
||||
#define GICR_PENDBASER_CACHE_DnGnRnE 0x0UL
|
||||
#define GICR_PENDBASER_CACHE_NIN 0x1UL
|
||||
#define GICR_PENDBASER_CACHE_NIRAWT 0x2UL
|
||||
#define GICR_PENDBASER_CACHE_NIRAWB 0x3UL
|
||||
#define GICR_PENDBASER_CACHE_NIWAWT 0x4UL
|
||||
#define GICR_PENDBASER_CACHE_NIWAWB 0x5UL
|
||||
#define GICR_PENDBASER_CACHE_NIRAWAWT 0x6UL
|
||||
#define GICR_PENDBASER_CACHE_NIRAWAWB 0x7UL
|
||||
|
||||
/*
|
||||
* Shareability
|
||||
* 0x0 - Non-shareable
|
||||
* 0x1 - Inner-shareable
|
||||
* 0x2 - Outer-shareable
|
||||
* 0x3 - Reserved. Threated as 0x0
|
||||
*/
|
||||
#define GICR_PENDBASER_SHARE_SHIFT 10
|
||||
#define GICR_PENDBASER_SHARE_NS 0x0UL
|
||||
#define GICR_PENDBASER_SHARE_IS 0x1UL
|
||||
#define GICR_PENDBASER_SHARE_OS 0x2UL
|
||||
#define GICR_PENDBASER_SHARE_RES 0x3UL
|
||||
#define GICR_PENDBASER_SHARE_MASK \
|
||||
(0x3UL << GICR_PENDBASER_SHARE_SHIFT)
|
||||
|
||||
/* Re-distributor registers for SGIs and PPIs */
|
||||
#define GICR_RD_BASE_SIZE PAGE_SIZE_64K
|
||||
#define GICR_SGI_BASE_SIZE PAGE_SIZE_64K
|
||||
@ -125,6 +208,151 @@
|
||||
|
||||
#define GICR_I_PER_IPRIORITYn (GICD_I_PER_IPRIORITYn)
|
||||
|
||||
/* ITS registers */
|
||||
#define GITS_PIDR2 GICR_PIDR2
|
||||
#define GITS_PIDR2_ARCH_MASK GICR_PIDR2_ARCH_MASK
|
||||
#define GITS_PIDR2_ARCH_GICv3 GICR_PIDR2_ARCH_GICv3
|
||||
#define GITS_PIDR2_ARCH_GICv4 GICR_PIDR2_ARCH_GICv4
|
||||
|
||||
#define GITS_CTLR (0x0000)
|
||||
#define GITS_CTLR_EN (1 << 0)
|
||||
|
||||
#define GITS_CBASER (0x0080)
|
||||
#define GITS_CBASER_VALID (1UL << 63)
|
||||
/*
|
||||
* Cacheability
|
||||
* 0x0 - Device-nGnRnE
|
||||
* 0x1 - Normal Inner Non-cacheable
|
||||
* 0x2 - Normal Inner Read-allocate, Write-through
|
||||
* 0x3 - Normal Inner Read-allocate, Write-back
|
||||
* 0x4 - Normal Inner Write-allocate, Write-through
|
||||
* 0x5 - Normal Inner Write-allocate, Write-back
|
||||
* 0x6 - Normal Inner Read-allocate, Write-allocate, Write-through
|
||||
* 0x7 - Normal Inner Read-allocate, Write-allocate, Write-back
|
||||
*/
|
||||
#define GITS_CBASER_CACHE_SHIFT 59
|
||||
#define GITS_CBASER_CACHE_DnGnRnE 0x0UL
|
||||
#define GITS_CBASER_CACHE_NIN 0x1UL
|
||||
#define GITS_CBASER_CACHE_NIRAWT 0x2UL
|
||||
#define GITS_CBASER_CACHE_NIRAWB 0x3UL
|
||||
#define GITS_CBASER_CACHE_NIWAWT 0x4UL
|
||||
#define GITS_CBASER_CACHE_NIWAWB 0x5UL
|
||||
#define GITS_CBASER_CACHE_NIRAWAWT 0x6UL
|
||||
#define GITS_CBASER_CACHE_NIRAWAWB 0x7UL
|
||||
#define GITS_CBASER_CACHE_MASK (0x7UL << GITS_CBASER_TYPE_SHIFT)
|
||||
/*
|
||||
* Shareability
|
||||
* 0x0 - Non-shareable
|
||||
* 0x1 - Inner-shareable
|
||||
* 0x2 - Outer-shareable
|
||||
* 0x3 - Reserved. Threated as 0x0
|
||||
*/
|
||||
#define GITS_CBASER_SHARE_SHIFT 10
|
||||
#define GITS_CBASER_SHARE_NS 0x0UL
|
||||
#define GITS_CBASER_SHARE_IS 0x1UL
|
||||
#define GITS_CBASER_SHARE_OS 0x2UL
|
||||
#define GITS_CBASER_SHARE_RES 0x3UL
|
||||
#define GITS_CBASER_SHARE_MASK \
|
||||
(0x3UL << GITS_CBASER_SHARE_SHIFT)
|
||||
|
||||
#define GITS_CBASER_PA_SHIFT 12
|
||||
#define GITS_CBASER_PA_MASK (0xFFFFFFFFFUL << GITS_CBASER_PA_SHIFT)
|
||||
|
||||
#define GITS_CWRITER (0x0088)
|
||||
#define GITS_CREADR (0x0090)
|
||||
|
||||
#define GITS_BASER_BASE (0x0100)
|
||||
#define GITS_BASER(x) (GITS_BASER_BASE + (x) * 8)
|
||||
|
||||
#define GITS_BASER_VALID (1UL << 63)
|
||||
|
||||
#define GITS_BASER_TYPE_SHIFT 56
|
||||
#define GITS_BASER_TYPE(x) \
|
||||
(((x) & GITS_BASER_TYPE_MASK) >> GITS_BASER_TYPE_SHIFT)
|
||||
#define GITS_BASER_TYPE_UNIMPL 0x0UL /* Unimplemented */
|
||||
#define GITS_BASER_TYPE_DEV 0x1UL /* Devices */
|
||||
#define GITS_BASER_TYPE_VP 0x2UL /* Virtual Processors */
|
||||
#define GITS_BASER_TYPE_PP 0x3UL /* Physical Processors */
|
||||
#define GITS_BASER_TYPE_IC 0x4UL /* Interrupt Collections */
|
||||
#define GITS_BASER_TYPE_RES5 0x5UL /* Reserved */
|
||||
#define GITS_BASER_TYPE_RES6 0x6UL /* Reserved */
|
||||
#define GITS_BASER_TYPE_RES7 0x7UL /* Reserved */
|
||||
#define GITS_BASER_TYPE_MASK (0x7UL << GITS_BASER_TYPE_SHIFT)
|
||||
/*
|
||||
* Cacheability
|
||||
* 0x0 - Non-cacheable, non-bufferable
|
||||
* 0x1 - Non-cacheable
|
||||
* 0x2 - Read-allocate, Write-through
|
||||
* 0x3 - Read-allocate, Write-back
|
||||
* 0x4 - Write-allocate, Write-through
|
||||
* 0x5 - Write-allocate, Write-back
|
||||
* 0x6 - Read-allocate, Write-allocate, Write-through
|
||||
* 0x7 - Read-allocate, Write-allocate, Write-back
|
||||
*/
|
||||
#define GITS_BASER_CACHE_SHIFT 59
|
||||
#define GITS_BASER_CACHE_NCNB 0x0UL
|
||||
#define GITS_BASER_CACHE_NC 0x1UL
|
||||
#define GITS_BASER_CACHE_RAWT 0x2UL
|
||||
#define GITS_BASER_CACHE_RAWB 0x3UL
|
||||
#define GITS_BASER_CACHE_WAWT 0x4UL
|
||||
#define GITS_BASER_CACHE_WAWB 0x5UL
|
||||
#define GITS_BASER_CACHE_RAWAWT 0x6UL
|
||||
#define GITS_BASER_CACHE_RAWAWB 0x7UL
|
||||
#define GITS_BASER_CACHE_MASK (0x7UL << GITS_BASER_CACHE_SHIFT)
|
||||
|
||||
#define GITS_BASER_ESIZE_SHIFT 48
|
||||
#define GITS_BASER_ESIZE_MASK (0x1FUL << GITS_BASER_ESIZE_SHIFT)
|
||||
#define GITS_BASER_ESIZE(x) \
|
||||
((((x) & GITS_BASER_ESIZE_MASK) >> GITS_BASER_ESIZE_SHIFT) + 1)
|
||||
|
||||
#define GITS_BASER_PA_SHIFT 12
|
||||
#define GITS_BASER_PA_MASK (0xFFFFFFFFFUL << GITS_BASER_PA_SHIFT)
|
||||
|
||||
/*
|
||||
* Shareability
|
||||
* 0x0 - Non-shareable
|
||||
* 0x1 - Inner-shareable
|
||||
* 0x2 - Outer-shareable
|
||||
* 0x3 - Reserved. Threated as 0x0
|
||||
*/
|
||||
#define GITS_BASER_SHARE_SHIFT 10
|
||||
#define GITS_BASER_SHARE_NS 0x0UL
|
||||
#define GITS_BASER_SHARE_IS 0x1UL
|
||||
#define GITS_BASER_SHARE_OS 0x2UL
|
||||
#define GITS_BASER_SHARE_RES 0x3UL
|
||||
#define GITS_BASER_SHARE_MASK (0x3UL << GITS_BASER_SHARE_SHIFT)
|
||||
|
||||
#define GITS_BASER_PSZ_SHIFT 8
|
||||
#define GITS_BASER_PSZ_4K 0x0UL
|
||||
#define GITS_BASER_PSZ_16K 0x1UL
|
||||
#define GITS_BASER_PSZ_64K 0x2UL
|
||||
#define GITS_BASER_PSZ_MASK (0x3UL << GITS_BASER_PSZ_SHIFT)
|
||||
|
||||
#define GITS_BASER_SIZE_MASK 0xFFUL
|
||||
|
||||
#define GITS_BASER_NUM 8
|
||||
|
||||
#define GITS_TYPER (0x0008)
|
||||
#define GITS_TYPER_PTA (1UL << 19)
|
||||
#define GITS_TYPER_DEVB_SHIFT 13
|
||||
#define GITS_TYPER_DEVB_MASK (0x1FUL << GITS_TYPER_DEVB_SHIFT)
|
||||
/* Number of device identifiers implemented */
|
||||
#define GITS_TYPER_DEVB(x) \
|
||||
((((x) & GITS_TYPER_DEVB_MASK) >> GITS_TYPER_DEVB_SHIFT) + 1)
|
||||
#define GITS_TYPER_ITTES_SHIFT 4
|
||||
#define GITS_TYPER_ITTES_MASK (0xFUL << GITS_TYPER_ITTES_SHIFT)
|
||||
/* Number of bytes per ITT Entry */
|
||||
#define GITS_TYPER_ITTES(x) \
|
||||
((((x) & GITS_TYPER_ITTES_MASK) >> GITS_TYPER_ITTES_SHIFT) + 1)
|
||||
|
||||
#define GITS_TRANSLATER (0x10040)
|
||||
/*
|
||||
* LPI related
|
||||
*/
|
||||
#define LPI_CONF_PRIO_MASK (0xFC)
|
||||
#define LPI_CONF_GROUP1 (1 << 1)
|
||||
#define LPI_CONF_ENABLE (1 << 0)
|
||||
|
||||
/*
|
||||
* CPU interface
|
||||
*/
|
||||
|
@ -36,6 +36,17 @@
|
||||
|
||||
DECLARE_CLASS(gic_v3_driver);
|
||||
|
||||
#define LPI_FLAGS_CONF_FLUSH (1UL << 0)
|
||||
#define LPI_CONFTAB_SIZE PAGE_SIZE_64K
|
||||
/* 1 bit per LPI + 1 KB more for the obligatory PPI, SGI, SPI stuff */
|
||||
#define LPI_PENDTAB_SIZE ((LPI_CONFTAB_SIZE / 8) + 0x400)
|
||||
|
||||
struct redist_lpis {
|
||||
vm_offset_t conf_base;
|
||||
vm_offset_t pend_base[MAXCPU];
|
||||
uint64_t flags;
|
||||
};
|
||||
|
||||
struct gic_redists {
|
||||
/*
|
||||
* Re-Distributor region description.
|
||||
@ -47,6 +58,8 @@ struct gic_redists {
|
||||
u_int nregions;
|
||||
/* Per-CPU Re-Distributor handler */
|
||||
struct resource * pcpu[MAXCPU];
|
||||
/* LPIs data */
|
||||
struct redist_lpis lpis;
|
||||
};
|
||||
|
||||
struct gic_v3_softc {
|
||||
@ -70,6 +83,167 @@ MALLOC_DECLARE(M_GIC_V3);
|
||||
int gic_v3_attach(device_t dev);
|
||||
int gic_v3_detach(device_t dev);
|
||||
|
||||
/*
|
||||
* ITS
|
||||
*/
|
||||
#define GIC_V3_ITS_DEVSTR "ARM GIC Interrupt Translation Service"
|
||||
#define GIC_V3_ITS_COMPSTR "arm,gic-v3-its"
|
||||
|
||||
DECLARE_CLASS(gic_v3_its_driver);
|
||||
|
||||
/* LPI chunk owned by ITS device */
|
||||
struct lpi_chunk {
|
||||
u_int lpi_base;
|
||||
u_int lpi_num;
|
||||
u_int lpi_free; /* First free LPI in set */
|
||||
};
|
||||
|
||||
/* ITS device */
|
||||
struct its_dev {
|
||||
TAILQ_ENTRY(its_dev) entry;
|
||||
/* PCI device */
|
||||
device_t pci_dev;
|
||||
/* Device ID (i.e. PCI device ID) */
|
||||
uint32_t devid;
|
||||
/* List of assigned LPIs */
|
||||
struct lpi_chunk lpis;
|
||||
/* Virtual address of ITT */
|
||||
vm_offset_t itt;
|
||||
/* Interrupt collection */
|
||||
struct its_col * col;
|
||||
};
|
||||
TAILQ_HEAD(its_dev_list, its_dev);
|
||||
|
||||
/* ITS private table description */
|
||||
struct its_ptab {
|
||||
vm_offset_t ptab_vaddr; /* Virtual Address of table */
|
||||
size_t ptab_pgsz; /* Page size */
|
||||
size_t ptab_npages; /* Number of pages */
|
||||
};
|
||||
|
||||
/* ITS collection description. */
|
||||
struct its_col {
|
||||
uint64_t col_target; /* Target Re-Distributor */
|
||||
uint64_t col_id; /* Collection ID */
|
||||
};
|
||||
|
||||
/* ITS command. Each command is 32 bytes long */
|
||||
struct its_cmd {
|
||||
uint64_t cmd_dword[4]; /* ITS command double word */
|
||||
};
|
||||
|
||||
/* ITS commands encoding */
|
||||
#define ITS_CMD_SYNC (0x05)
|
||||
#define ITS_CMD_MAPD (0x08)
|
||||
#define ITS_CMD_MAPC (0x09)
|
||||
#define ITS_CMD_MAPVI (0x0a)
|
||||
#define ITS_CMD_MAPI (0x0b)
|
||||
#define ITS_CMD_INV (0x0c)
|
||||
#define ITS_CMD_INVALL (0x0d)
|
||||
/* Command */
|
||||
#define CMD_COMMAND_MASK (0xFFUL)
|
||||
/* PCI device ID */
|
||||
#define CMD_DEVID_SHIFT (32)
|
||||
#define CMD_DEVID_MASK (0xFFFFFFFFUL << CMD_DEVID_SHIFT)
|
||||
/* Size of IRQ ID bitfield */
|
||||
#define CMD_SIZE_MASK (0xFFUL)
|
||||
/* Virtual LPI ID */
|
||||
#define CMD_ID_MASK (0xFFFFFFFFUL)
|
||||
/* Physical LPI ID */
|
||||
#define CMD_PID_SHIFT (32)
|
||||
#define CMD_PID_MASK (0xFFFFFFFFUL << CMD_PID_SHIFT)
|
||||
/* Collection */
|
||||
#define CMD_COL_MASK (0xFFFFUL)
|
||||
/* Target (CPU or Re-Distributor) */
|
||||
#define CMD_TARGET_SHIFT (16)
|
||||
#define CMD_TARGET_MASK (0xFFFFFFFFUL << CMD_TARGET_SHIFT)
|
||||
/* Interrupt Translation Table address */
|
||||
#define CMD_ITT_MASK (0xFFFFFFFFFF00UL)
|
||||
/* Valid command bit */
|
||||
#define CMD_VALID_SHIFT (63)
|
||||
#define CMD_VALID_MASK (1UL << CMD_VALID_SHIFT)
|
||||
|
||||
/*
|
||||
* ITS command descriptor.
|
||||
* Idea for command description passing taken from Linux.
|
||||
*/
|
||||
struct its_cmd_desc {
|
||||
uint8_t cmd_type;
|
||||
|
||||
union {
|
||||
struct {
|
||||
struct its_col *col;
|
||||
} cmd_desc_sync;
|
||||
|
||||
struct {
|
||||
struct its_col *col;
|
||||
uint8_t valid;
|
||||
} cmd_desc_mapc;
|
||||
|
||||
struct {
|
||||
struct its_dev *its_dev;
|
||||
uint32_t pid;
|
||||
uint32_t id;
|
||||
} cmd_desc_mapvi;
|
||||
|
||||
struct {
|
||||
struct its_dev *its_dev;
|
||||
uint32_t lpinum;
|
||||
} cmd_desc_mapi;
|
||||
|
||||
struct {
|
||||
struct its_dev *its_dev;
|
||||
uint8_t valid;
|
||||
} cmd_desc_mapd;
|
||||
|
||||
struct {
|
||||
struct its_dev *its_dev;
|
||||
uint32_t lpinum;
|
||||
} cmd_desc_inv;
|
||||
|
||||
struct {
|
||||
struct its_col *col;
|
||||
} cmd_desc_invall;
|
||||
};
|
||||
};
|
||||
|
||||
#define ITS_CMDQ_SIZE PAGE_SIZE_64K
|
||||
#define ITS_CMDQ_NENTRIES (ITS_CMDQ_SIZE / sizeof(struct its_cmd))
|
||||
|
||||
#define ITS_FLAGS_CMDQ_FLUSH (1UL << 0)
|
||||
|
||||
#define ITS_TARGET_NONE 0xFBADBEEF
|
||||
|
||||
struct gic_v3_its_softc {
|
||||
device_t dev;
|
||||
struct resource * its_res;
|
||||
|
||||
struct its_cmd * its_cmdq_base; /* ITS command queue base */
|
||||
struct its_cmd * its_cmdq_write; /* ITS command queue write ptr */
|
||||
struct its_ptab its_ptabs[GITS_BASER_NUM];/* ITS private tables */
|
||||
struct its_col * its_cols; /* Per-CPU collections */
|
||||
|
||||
uint64_t its_flags;
|
||||
|
||||
struct its_dev_list its_dev_list;
|
||||
|
||||
unsigned long * its_lpi_bitmap;
|
||||
uint32_t its_lpi_maxid;
|
||||
|
||||
struct mtx its_mtx;
|
||||
struct mtx its_spin_mtx;
|
||||
};
|
||||
|
||||
extern devclass_t gic_v3_its_devclass;
|
||||
|
||||
int gic_v3_its_detach(device_t);
|
||||
|
||||
int gic_v3_its_alloc_msix(device_t, device_t, int *);
|
||||
int gic_v3_its_alloc_msi(device_t, device_t, int, int *);
|
||||
int gic_v3_its_map_msix(device_t, device_t, int, uint64_t *, uint32_t *);
|
||||
|
||||
void lpi_unmask_irq(device_t, uint32_t);
|
||||
void lpi_mask_irq(device_t, uint32_t);
|
||||
/*
|
||||
* GIC Distributor accessors.
|
||||
* Notice that only GIC sofc can be passed.
|
||||
@ -103,4 +277,28 @@ int gic_v3_detach(device_t dev);
|
||||
reg, val); \
|
||||
})
|
||||
|
||||
#define PCI_DEVID(pci_dev) \
|
||||
({ \
|
||||
(((pci_get_domain(pci_dev) >> 2) << 19) | \
|
||||
((pci_get_domain(pci_dev) % 4) << 16) | \
|
||||
(pci_get_bus(pci_dev) << 8) | \
|
||||
(pci_get_slot(pci_dev) << 3) | \
|
||||
(pci_get_function(pci_dev) << 0)); \
|
||||
})
|
||||
|
||||
/*
|
||||
* Request number of maximum MSI-X vectors for this device.
|
||||
* Device can ask for less vectors than maximum supported but not more.
|
||||
*/
|
||||
#define PCI_MSIX_NUM(pci_dev) \
|
||||
({ \
|
||||
struct pci_devinfo *dinfo; \
|
||||
pcicfgregs *cfg; \
|
||||
\
|
||||
dinfo = device_get_ivars(pci_dev); \
|
||||
cfg = &dinfo->cfg; \
|
||||
\
|
||||
cfg->msix.msix_msgnum; \
|
||||
})
|
||||
|
||||
#endif /* _GIC_V3_VAR_H_ */
|
||||
|
@ -82,6 +82,10 @@
|
||||
#define PAGE_SIZE (1 << PAGE_SHIFT) /* Page size */
|
||||
#define PAGE_MASK (PAGE_SIZE - 1)
|
||||
|
||||
#define PAGE_SHIFT_16K 14
|
||||
#define PAGE_SIZE_16K (1 << PAGE_SHIFT_16K)
|
||||
#define PAGE_MASK_16K (PAGE_SIZE_16K - 1)
|
||||
|
||||
#define PAGE_SHIFT_64K 16
|
||||
#define PAGE_SIZE_64K (1 << PAGE_SHIFT_64K)
|
||||
#define PAGE_MASK_64K (PAGE_SIZE_64K - 1)
|
||||
|
@ -27,6 +27,7 @@ arm64/arm64/gic_acpi.c optional acpi
|
||||
arm64/arm64/gic_fdt.c optional fdt
|
||||
arm64/arm64/gic_v3.c standard
|
||||
arm64/arm64/gic_v3_fdt.c optional fdt
|
||||
arm64/arm64/gic_v3_its.c standard
|
||||
arm64/arm64/identcpu.c standard
|
||||
arm64/arm64/intr_machdep.c standard
|
||||
arm64/arm64/in_cksum.c optional inet | inet6
|
||||
|
Loading…
Reference in New Issue
Block a user