git: 24558f289dd3 - main - riscv intc: convert to a bus.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 02 Nov 2026 12:21:26 UTC
The branch main has been updated by br:
URL: https://cgit.FreeBSD.org/src/commit/?id=24558f289dd3b0a2a2372123186455e449d60abf
commit 24558f289dd3b0a2a2372123186455e449d60abf
Author: Ruslan Bukin <br@FreeBSD.org>
AuthorDate: 2026-11-02 11:31:38 +0000
Commit: Ruslan Bukin <br@FreeBSD.org>
CommitDate: 2026-11-02 12:18:44 +0000
riscv intc: convert to a bus.
Convert the RISC-V Interrupt Controller (INTC) device to a bus;
try to find and attach Incoming Message Signalling Interrupt Controller
(IMSIC) device.
This allows to establish parent-child relationships between two and
to propagate PIC_INIT_SECONDARY call from the INTC (parent) to the
IMSIC (child).
Reviewed by: mhorne, mmel
Sponsored by: EPSRC ("UKRI3001: CHERI Research Centre")
Differential Revision: https://reviews.freebsd.org/D59813
---
sys/riscv/riscv/intc.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 115 insertions(+), 2 deletions(-)
diff --git a/sys/riscv/riscv/intc.c b/sys/riscv/riscv/intc.c
index b700b9c97793..70836adf7c2e 100644
--- a/sys/riscv/riscv/intc.c
+++ b/sys/riscv/riscv/intc.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2015-2017 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2015-2017,2026 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
* Copyright (c) 2021 Jessica Clarke <jrtc27@FreeBSD.org>
*
@@ -58,6 +58,7 @@
#include <dev/ofw/ofw_bus_subr.h>
#include "pic_if.h"
+#include "ofw_bus_if.h"
#define INTC_NIRQS 16
@@ -69,6 +70,12 @@ struct intc_irqsrc {
struct intc_softc {
device_t dev;
struct intc_irqsrc isrcs[INTC_NIRQS];
+ device_t imsic;
+};
+
+struct intc_devinfo {
+ struct resource_list di_rl;
+ struct ofw_bus_devinfo di_dinfo;
};
static int intc_intr(void *arg);
@@ -139,6 +146,61 @@ intc_identify(driver_t *driver, device_t parent)
device_printf(parent, "Can't add intc child\n");
}
+static int
+intc_add_imsic(device_t dev)
+{
+ struct intc_softc *sc;
+ struct intc_devinfo *di;
+ pcell_t addr_cells, size_cells;
+ phandle_t parent;
+ phandle_t child;
+
+ sc = device_get_softc(dev);
+
+ child = ofw_bus_find_compatible(OF_finddevice("/"), "riscv,imsics");
+ if (child == 0)
+ return (0);
+
+ parent = OF_parent(child);
+
+ if (OF_getencprop(parent, "#address-cells", &addr_cells,
+ sizeof(addr_cells)) == -1) {
+ device_printf(dev, "Unable to read #address-cells\n");
+ return (ENXIO);
+ }
+
+ if (OF_getencprop(parent, "#size-cells", &size_cells,
+ sizeof(size_cells)) == -1) {
+ device_printf(dev, "Unable to read #size-cells\n");
+ return (ENXIO);
+ }
+
+ di = malloc(sizeof(*di), M_DEVBUF, M_WAITOK | M_ZERO);
+ if (di == NULL)
+ return (ENOMEM);
+
+ if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, child)) {
+ if (bootverbose)
+ device_printf(dev, "Could not set up devinfo\n");
+ free(di, M_DEVBUF);
+ return (ENXIO);
+ }
+
+ sc->imsic = device_add_child(dev, "imsic", DEVICE_UNIT_ANY);
+ if (sc->imsic == NULL) {
+ free(di, M_DEVBUF);
+ return (ENXIO);
+ }
+
+ /* Initialize and populate resource list. */
+ resource_list_init(&di->di_rl);
+ ofw_bus_reg_to_rl(dev, child, addr_cells, size_cells, &di->di_rl);
+ ofw_bus_intr_to_rl(dev, child, &di->di_rl, NULL);
+ device_set_ivars(sc->imsic, di);
+
+ return (0);
+}
+
static int
intc_probe(device_t dev)
{
@@ -181,6 +243,8 @@ intc_attach(device_t dev)
if (pic == NULL)
return (ENXIO);
+ intc_add_imsic(dev);
+
return (intr_pic_claim_root(sc->dev, xref, intc_intr, sc, INTR_ROOT_IRQ));
}
@@ -250,7 +314,18 @@ intc_init_secondary(device_t dev, uint32_t rootnum)
sc = device_get_softc(dev);
cpu = PCPU_GET(cpuid);
- /* Unmask attached interrupts */
+ /* Mask attached interrupts. */
+ for (irq = 0; irq < INTC_NIRQS; irq++) {
+ isrc = &sc->isrcs[irq].isrc;
+ if (intr_isrc_init_on_cpu(isrc, cpu))
+ intc_disable_intr(dev, isrc);
+ }
+
+ /* Initialize the child PIC. */
+ if (sc->imsic != NULL)
+ PIC_INIT_SECONDARY(sc->imsic, rootnum);
+
+ /* Unmask attached interrupts. */
for (irq = 0; irq < INTC_NIRQS; irq++) {
isrc = &sc->isrcs[irq].isrc;
if (intr_isrc_init_on_cpu(isrc, cpu))
@@ -288,12 +363,44 @@ intc_intr(void *arg)
return (FILTER_HANDLED);
}
+static const struct ofw_bus_devinfo *
+intc_get_devinfo(device_t bus __unused, device_t child)
+{
+ struct intc_devinfo *di;
+
+ di = device_get_ivars(child);
+ if (di == NULL)
+ return (NULL);
+ return (&di->di_dinfo);
+}
+
+static struct resource_list *
+intc_get_resource_list(device_t bus, device_t child)
+{
+ struct intc_devinfo *di;
+
+ di = device_get_ivars(child);
+ KASSERT(di != NULL, ("%s: No devinfo", __func__));
+
+ return (&di->di_rl);
+}
+
static device_method_t intc_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, intc_identify),
DEVMETHOD(device_probe, intc_probe),
DEVMETHOD(device_attach, intc_attach),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_get_resource_list, intc_get_resource_list),
+ DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
+ DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
+ DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+
/* Interrupt controller interface */
DEVMETHOD(pic_disable_intr, intc_disable_intr),
DEVMETHOD(pic_enable_intr, intc_enable_intr),
@@ -302,6 +409,12 @@ static device_method_t intc_methods[] = {
#ifdef SMP
DEVMETHOD(pic_init_secondary, intc_init_secondary),
#endif
+ DEVMETHOD(ofw_bus_get_devinfo, intc_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),
DEVMETHOD_END
};