aboutsummaryrefslogtreecommitdiff
path: root/sys/arm64/arm64
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arm64/arm64')
-rw-r--r--sys/arm64/arm64/gic_v3.c57
-rw-r--r--sys/arm64/arm64/gic_v3_acpi.c33
-rw-r--r--sys/arm64/arm64/gic_v3_fdt.c111
-rw-r--r--sys/arm64/arm64/gic_v3_var.h3
4 files changed, 120 insertions, 84 deletions
diff --git a/sys/arm64/arm64/gic_v3.c b/sys/arm64/arm64/gic_v3.c
index 759d50f0941e..c26158e4035c 100644
--- a/sys/arm64/arm64/gic_v3.c
+++ b/sys/arm64/arm64/gic_v3.c
@@ -81,6 +81,7 @@ static bus_print_child_t gic_v3_print_child;
static bus_get_domain_t gic_v3_get_domain;
static bus_read_ivar_t gic_v3_read_ivar;
static bus_write_ivar_t gic_v3_write_ivar;
+static bus_alloc_resource_t gic_v3_alloc_resource;
static pic_disable_intr_t gic_v3_disable_intr;
static pic_enable_intr_t gic_v3_enable_intr;
@@ -124,6 +125,8 @@ static device_method_t gic_v3_methods[] = {
DEVMETHOD(bus_get_domain, gic_v3_get_domain),
DEVMETHOD(bus_read_ivar, gic_v3_read_ivar),
DEVMETHOD(bus_write_ivar, gic_v3_write_ivar),
+ DEVMETHOD(bus_alloc_resource, gic_v3_alloc_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
/* Interrupt controller interface */
DEVMETHOD(pic_disable_intr, gic_v3_disable_intr),
@@ -435,6 +438,7 @@ gic_v3_detach(device_t dev)
for (i = 0; i <= mp_maxid; i++)
free(sc->gic_redists.pcpu[i], M_GIC_V3);
+ free(sc->ranges, M_GIC_V3);
free(sc->gic_res, M_GIC_V3);
free(sc->gic_redists.regions, M_GIC_V3);
@@ -524,6 +528,59 @@ gic_v3_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
return (ENOENT);
}
+static struct resource *
+gic_v3_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
+{
+ struct gic_v3_softc *sc;
+ struct resource_list_entry *rle;
+ struct resource_list *rl;
+ int j;
+
+ /* We only allocate memory */
+ if (type != SYS_RES_MEMORY)
+ return (NULL);
+
+ sc = device_get_softc(bus);
+
+ if (RMAN_IS_DEFAULT_RANGE(start, end)) {
+ rl = BUS_GET_RESOURCE_LIST(bus, child);
+ if (rl == NULL)
+ return (NULL);
+
+ /* Find defaults for this rid */
+ rle = resource_list_find(rl, type, *rid);
+ if (rle == NULL)
+ return (NULL);
+
+ start = rle->start;
+ end = rle->end;
+ count = rle->count;
+ }
+
+ /* Remap through ranges property */
+ for (j = 0; j < sc->nranges; j++) {
+ if (start >= sc->ranges[j].bus && end <
+ sc->ranges[j].bus + sc->ranges[j].size) {
+ start -= sc->ranges[j].bus;
+ start += sc->ranges[j].host;
+ end -= sc->ranges[j].bus;
+ end += sc->ranges[j].host;
+ break;
+ }
+ }
+ if (j == sc->nranges && sc->nranges != 0) {
+ if (bootverbose)
+ device_printf(bus, "Could not map resource "
+ "%#jx-%#jx\n", (uintmax_t)start, (uintmax_t)end);
+
+ return (NULL);
+ }
+
+ return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
+ count, flags));
+}
+
int
arm_gic_v3_intr(void *arg)
{
diff --git a/sys/arm64/arm64/gic_v3_acpi.c b/sys/arm64/arm64/gic_v3_acpi.c
index f24662750da7..3d3cd3ba9ccd 100644
--- a/sys/arm64/arm64/gic_v3_acpi.c
+++ b/sys/arm64/arm64/gic_v3_acpi.c
@@ -59,7 +59,6 @@ struct gic_v3_acpi_devinfo {
static device_identify_t gic_v3_acpi_identify;
static device_probe_t gic_v3_acpi_probe;
static device_attach_t gic_v3_acpi_attach;
-static bus_alloc_resource_t gic_v3_acpi_bus_alloc_res;
static bus_get_resource_list_t gic_v3_acpi_get_resource_list;
static void gic_v3_acpi_bus_attach(device_t);
@@ -71,8 +70,6 @@ static device_method_t gic_v3_acpi_methods[] = {
DEVMETHOD(device_attach, gic_v3_acpi_attach),
/* Bus interface */
- DEVMETHOD(bus_alloc_resource, gic_v3_acpi_bus_alloc_res),
- DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_get_resource_list, gic_v3_acpi_get_resource_list),
/* End */
@@ -445,36 +442,6 @@ gic_v3_acpi_bus_attach(device_t dev)
bus_generic_attach(dev);
}
-static struct resource *
-gic_v3_acpi_bus_alloc_res(device_t bus, device_t child, int type, int *rid,
- rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
-{
- struct resource_list_entry *rle;
- struct resource_list *rl;
-
- /* We only allocate memory */
- if (type != SYS_RES_MEMORY)
- return (NULL);
-
- if (RMAN_IS_DEFAULT_RANGE(start, end)) {
- rl = BUS_GET_RESOURCE_LIST(bus, child);
- if (rl == NULL)
- return (NULL);
-
- /* Find defaults for this rid */
- rle = resource_list_find(rl, type, *rid);
- if (rle == NULL)
- return (NULL);
-
- start = rle->start;
- end = rle->end;
- count = rle->count;
- }
-
- return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
- count, flags));
-}
-
static struct resource_list *
gic_v3_acpi_get_resource_list(device_t bus, device_t child)
{
diff --git a/sys/arm64/arm64/gic_v3_fdt.c b/sys/arm64/arm64/gic_v3_fdt.c
index dc1445340943..2efdba68eae2 100644
--- a/sys/arm64/arm64/gic_v3_fdt.c
+++ b/sys/arm64/arm64/gic_v3_fdt.c
@@ -54,8 +54,6 @@ __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 *,
- rman_res_t, rman_res_t, rman_res_t, u_int);
static const struct ofw_bus_devinfo *gic_v3_ofw_get_devinfo(device_t, device_t);
static bus_get_resource_list_t gic_v3_fdt_get_resource_list;
@@ -65,8 +63,6 @@ static device_method_t gic_v3_fdt_methods[] = {
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),
DEVMETHOD(bus_get_resource_list, gic_v3_fdt_get_resource_list),
/* ofw_bus interface */
@@ -219,51 +215,64 @@ gic_v3_ofw_get_devinfo(device_t bus __unused, device_t child)
return (&di->di_dinfo);
}
-static struct resource *
-gic_v3_ofw_bus_alloc_res(device_t bus, device_t child, int type, int *rid,
- rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
+/* Helper functions */
+static int
+gic_v3_ofw_fill_ranges(phandle_t parent, struct gic_v3_softc *sc,
+ pcell_t *addr_cellsp, pcell_t *size_cellsp)
{
- struct resource_list_entry *rle;
- struct resource_list *rl;
- int ranges_len;
-
- /* We only allocate memory */
- if (type != SYS_RES_MEMORY)
- return (NULL);
-
- if (RMAN_IS_DEFAULT_RANGE(start, end)) {
- rl = BUS_GET_RESOURCE_LIST(bus, child);
- if (rl == NULL)
- return (NULL);
-
- /* Find defaults for this rid */
- rle = resource_list_find(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);
+ pcell_t addr_cells, host_cells, size_cells;
+ cell_t *base_ranges;
+ ssize_t nbase_ranges;
+ int i, j, k;
+
+ host_cells = 1;
+ OF_getencprop(OF_parent(parent), "#address-cells", &host_cells,
+ sizeof(host_cells));
+ 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));
+
+ *addr_cellsp = addr_cells;
+ *size_cellsp = size_cells;
+
+ nbase_ranges = OF_getproplen(parent, "ranges");
+ if (nbase_ranges < 0)
+ return (EINVAL);
+
+ sc->nranges = nbase_ranges / sizeof(cell_t) /
+ (addr_cells + host_cells + size_cells);
+ if (sc->nranges == 0)
+ return (0);
+
+ sc->ranges = malloc(sc->nranges * sizeof(sc->ranges[0]), M_GIC_V3,
+ M_WAITOK);
+ base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
+ OF_getencprop(parent, "ranges", base_ranges, nbase_ranges);
+
+ for (i = 0, j = 0; i < sc->nranges; i++) {
+ sc->ranges[i].bus = 0;
+ for (k = 0; k < addr_cells; k++) {
+ sc->ranges[i].bus <<= 32;
+ sc->ranges[i].bus |= base_ranges[j++];
+ }
+ sc->ranges[i].host = 0;
+ for (k = 0; k < host_cells; k++) {
+ sc->ranges[i].host <<= 32;
+ sc->ranges[i].host |= base_ranges[j++];
+ }
+ sc->ranges[i].size = 0;
+ for (k = 0; k < size_cells; k++) {
+ sc->ranges[i].size <<= 32;
+ sc->ranges[i].size |= base_ranges[j++];
}
}
- return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
- count, flags));
-}
-/* Helper functions */
+ free(base_ranges, M_DEVBUF);
+ return (0);
+}
/*
* Bus capability support for GICv3.
@@ -278,16 +287,16 @@ gic_v3_ofw_bus_attach(device_t dev)
device_t child;
phandle_t parent, node;
pcell_t addr_cells, size_cells;
+ int rv;
sc = device_get_softc(dev);
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));
+ rv = gic_v3_ofw_fill_ranges(parent, sc, &addr_cells,
+ &size_cells);
+ if (rv != 0)
+ return (rv);
+
/* Iterate through all GIC subordinates */
for (node = OF_child(parent); node > 0; node = OF_peer(node)) {
/*
diff --git a/sys/arm64/arm64/gic_v3_var.h b/sys/arm64/arm64/gic_v3_var.h
index b66fe6c57bb2..61c3ff0b61ae 100644
--- a/sys/arm64/arm64/gic_v3_var.h
+++ b/sys/arm64/arm64/gic_v3_var.h
@@ -84,6 +84,9 @@ struct gic_v3_softc {
device_t *gic_children;
struct intr_pic *gic_pic;
struct gic_v3_irqsrc *gic_irqs;
+
+ int nranges;
+ struct arm_gic_range * ranges;
};
struct gic_v3_devinfo {