Changeset View
Changeset View
Standalone View
Standalone View
sys/riscv/riscv/plic.c
Show All 36 Lines | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/ktr.h> | #include <sys/ktr.h> | ||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/rman.h> | #include <sys/rman.h> | ||||
#include <sys/smp.h> | |||||
#include <machine/bus.h> | #include <machine/bus.h> | ||||
#include <machine/intr.h> | #include <machine/intr.h> | ||||
#include <dev/ofw/openfirm.h> | #include <dev/ofw/openfirm.h> | ||||
#include <dev/ofw/ofw_bus.h> | #include <dev/ofw/ofw_bus.h> | ||||
#include <dev/ofw/ofw_bus_subr.h> | #include <dev/ofw/ofw_bus_subr.h> | ||||
Show All 24 Lines | struct plic_softc { | ||||
int ndev; | int ndev; | ||||
}; | }; | ||||
#define RD4(sc, reg) \ | #define RD4(sc, reg) \ | ||||
bus_read_4(sc->intc_res, (reg)) | bus_read_4(sc->intc_res, (reg)) | ||||
#define WR4(sc, reg, val) \ | #define WR4(sc, reg, val) \ | ||||
bus_write_4(sc->intc_res, (reg), (val)) | bus_write_4(sc->intc_res, (reg), (val)) | ||||
static inline void | static inline void | ||||
br: Is it static? | |||||
plic_irq_dispatch(struct plic_softc *sc, u_int irq, | plic_irq_dispatch(struct plic_softc *sc, u_int irq, | ||||
struct trapframe *tf) | struct trapframe *tf) | ||||
{ | { | ||||
struct plic_irqsrc *src; | struct plic_irqsrc *src; | ||||
src = &sc->isrcs[irq]; | src = &sc->isrcs[irq]; | ||||
if (intr_isrc_dispatch(&src->isrc, tf) != 0) | if (intr_isrc_dispatch(&src->isrc, tf) != 0) | ||||
Show All 27 Lines | plic_disable_intr(device_t dev, struct intr_irqsrc *isrc) | ||||
struct plic_softc *sc; | struct plic_softc *sc; | ||||
struct plic_irqsrc *src; | struct plic_irqsrc *src; | ||||
uint32_t reg; | uint32_t reg; | ||||
uint32_t cpu; | uint32_t cpu; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
src = (struct plic_irqsrc *)isrc; | src = (struct plic_irqsrc *)isrc; | ||||
cpu = PCPU_GET(cpuid); | CPU_FOREACH(cpu) { | ||||
reg = RD4(sc, PLIC_ENABLE(src->irq, cpu)); | reg = RD4(sc, PLIC_ENABLE(src->irq, cpu)); | ||||
reg &= ~(1 << (src->irq % 32)); | reg &= ~(1 << (src->irq % 32)); | ||||
WR4(sc, PLIC_ENABLE(src->irq, cpu), reg); | WR4(sc, PLIC_ENABLE(src->irq, cpu), reg); | ||||
} | } | ||||
} | |||||
static void | static void | ||||
plic_enable_intr(device_t dev, struct intr_irqsrc *isrc) | plic_enable_intr(device_t dev, struct intr_irqsrc *isrc) | ||||
{ | { | ||||
struct plic_softc *sc; | struct plic_softc *sc; | ||||
struct plic_irqsrc *src; | struct plic_irqsrc *src; | ||||
uint32_t reg; | uint32_t reg; | ||||
uint32_t cpu; | uint32_t cpu; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
src = (struct plic_irqsrc *)isrc; | src = (struct plic_irqsrc *)isrc; | ||||
WR4(sc, PLIC_PRIORITY(src->irq), 1); | CPU_FOREACH(cpu) { | ||||
cpu = PCPU_GET(cpuid); | |||||
reg = RD4(sc, PLIC_ENABLE(src->irq, cpu)); | reg = RD4(sc, PLIC_ENABLE(src->irq, cpu)); | ||||
reg |= (1 << (src->irq % 32)); | reg |= (1 << (src->irq % 32)); | ||||
WR4(sc, PLIC_ENABLE(src->irq, cpu), reg); | WR4(sc, PLIC_ENABLE(src->irq, cpu), reg); | ||||
} | } | ||||
} | |||||
static int | static int | ||||
plic_map_intr(device_t dev, struct intr_map_data *data, | plic_map_intr(device_t dev, struct intr_map_data *data, | ||||
struct intr_irqsrc **isrcp) | struct intr_irqsrc **isrcp) | ||||
{ | { | ||||
struct intr_map_data_fdt *daf; | struct intr_map_data_fdt *daf; | ||||
struct plic_softc *sc; | struct plic_softc *sc; | ||||
Show All 28 Lines | |||||
static int | static int | ||||
plic_attach(device_t dev) | plic_attach(device_t dev) | ||||
{ | { | ||||
struct plic_irqsrc *isrcs; | struct plic_irqsrc *isrcs; | ||||
struct plic_softc *sc; | struct plic_softc *sc; | ||||
struct intr_pic *pic; | struct intr_pic *pic; | ||||
uint32_t irq; | uint32_t irq; | ||||
uint32_t reg; | |||||
const char *name; | const char *name; | ||||
phandle_t node; | phandle_t node; | ||||
phandle_t xref; | phandle_t xref; | ||||
uint32_t cpu; | uint32_t cpu; | ||||
int error; | int error; | ||||
int rid; | int rid; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
Show All 21 Lines | plic_attach(device_t dev) | ||||
if (sc->intc_res == NULL) { | if (sc->intc_res == NULL) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"Error: could not allocate memory resources\n"); | "Error: could not allocate memory resources\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
isrcs = sc->isrcs; | isrcs = sc->isrcs; | ||||
name = device_get_nameunit(sc->dev); | name = device_get_nameunit(sc->dev); | ||||
cpu = PCPU_GET(cpuid); | |||||
for (irq = 1; irq <= sc->ndev; irq++) { | for (irq = 1; irq <= sc->ndev; irq++) { | ||||
isrcs[irq].irq = irq; | isrcs[irq].irq = irq; | ||||
error = intr_isrc_register(&isrcs[irq].isrc, sc->dev, | error = intr_isrc_register(&isrcs[irq].isrc, sc->dev, | ||||
0, "%s,%u", name, irq); | 0, "%s,%u", name, irq); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
/* | |||||
* Disable all interrupts by lowering the priority and clearing | |||||
* the enable bit. They will be enabled later on during | |||||
* plic_setup_intr() and plic_enable_intr(). | |||||
*/ | |||||
WR4(sc, PLIC_PRIORITY(irq), 0); | WR4(sc, PLIC_PRIORITY(irq), 0); | ||||
WR4(sc, PLIC_ENABLE(irq, cpu), 0); | CPU_FOREACH(cpu) { | ||||
reg = RD4(sc, PLIC_ENABLE(irq, cpu)); | |||||
reg &= ~(1 << (irq % 32)); | |||||
WR4(sc, PLIC_ENABLE(irq, cpu), reg); | |||||
} | } | ||||
} | |||||
CPU_FOREACH(cpu) | |||||
WR4(sc, PLIC_THRESHOLD(cpu), 0); | WR4(sc, PLIC_THRESHOLD(cpu), 0); | ||||
xref = OF_xref_from_node(node); | xref = OF_xref_from_node(node); | ||||
pic = intr_pic_register(sc->dev, xref); | pic = intr_pic_register(sc->dev, xref); | ||||
if (pic == NULL) | if (pic == NULL) | ||||
return (ENXIO); | return (ENXIO); | ||||
csr_set(sie, SIE_SEIE); | csr_set(sie, SIE_SEIE); | ||||
return (intr_pic_claim_root(sc->dev, xref, plic_intr, sc, 0)); | return (intr_pic_claim_root(sc->dev, xref, plic_intr, sc, 0)); | ||||
} | } | ||||
static void | static void | ||||
plic_pre_ithread(device_t dev, struct intr_irqsrc *isrc) | plic_pre_ithread(device_t dev, struct intr_irqsrc *isrc) | ||||
{ | { | ||||
struct plic_softc *sc; | struct plic_softc *sc; | ||||
Done Inline Actionsfrom style(9): br: from style(9):
/* Insert an empty line if the function has no local variables. */
| |||||
Done Inline ActionsThis was made optional recently, but I do prefer this style. mhorne: This was made optional recently, but I do prefer this style. | |||||
struct plic_irqsrc *src; | struct plic_irqsrc *src; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
src = (struct plic_irqsrc *)isrc; | src = (struct plic_irqsrc *)isrc; | ||||
WR4(sc, PLIC_PRIORITY(src->irq), 0); | WR4(sc, PLIC_PRIORITY(src->irq), 0); | ||||
} | } | ||||
static void | static void | ||||
plic_post_ithread(device_t dev, struct intr_irqsrc *isrc) | plic_post_ithread(device_t dev, struct intr_irqsrc *isrc) | ||||
{ | { | ||||
struct plic_softc *sc; | struct plic_softc *sc; | ||||
struct plic_irqsrc *src; | struct plic_irqsrc *src; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
src = (struct plic_irqsrc *)isrc; | src = (struct plic_irqsrc *)isrc; | ||||
WR4(sc, PLIC_PRIORITY(src->irq), 1); | WR4(sc, PLIC_PRIORITY(src->irq), 1); | ||||
} | } | ||||
static int | |||||
plic_setup_intr(device_t dev, struct intr_irqsrc *isrc, | |||||
struct resource *res, struct intr_map_data *data) | |||||
{ | |||||
struct plic_softc *sc; | |||||
struct plic_irqsrc *src; | |||||
if (isrc->isrc_handlers == 0) { | |||||
sc = device_get_softc(dev); | |||||
src = (struct plic_irqsrc *)isrc; | |||||
WR4(sc, PLIC_PRIORITY(src->irq), 1); | |||||
} | |||||
return (0); | |||||
} | |||||
static device_method_t plic_methods[] = { | static device_method_t plic_methods[] = { | ||||
DEVMETHOD(device_probe, plic_probe), | DEVMETHOD(device_probe, plic_probe), | ||||
DEVMETHOD(device_attach, plic_attach), | DEVMETHOD(device_attach, plic_attach), | ||||
DEVMETHOD(pic_disable_intr, plic_disable_intr), | DEVMETHOD(pic_disable_intr, plic_disable_intr), | ||||
DEVMETHOD(pic_enable_intr, plic_enable_intr), | DEVMETHOD(pic_enable_intr, plic_enable_intr), | ||||
DEVMETHOD(pic_map_intr, plic_map_intr), | DEVMETHOD(pic_map_intr, plic_map_intr), | ||||
DEVMETHOD(pic_pre_ithread, plic_pre_ithread), | DEVMETHOD(pic_pre_ithread, plic_pre_ithread), | ||||
DEVMETHOD(pic_post_ithread, plic_post_ithread), | DEVMETHOD(pic_post_ithread, plic_post_ithread), | ||||
DEVMETHOD(pic_setup_intr, plic_setup_intr), | |||||
DEVMETHOD_END | DEVMETHOD_END | ||||
}; | }; | ||||
static driver_t plic_driver = { | static driver_t plic_driver = { | ||||
"plic", | "plic", | ||||
plic_methods, | plic_methods, | ||||
sizeof(struct plic_softc), | sizeof(struct plic_softc), | ||||
}; | }; | ||||
static devclass_t plic_devclass; | static devclass_t plic_devclass; | ||||
EARLY_DRIVER_MODULE(plic, simplebus, plic_driver, plic_devclass, | EARLY_DRIVER_MODULE(plic, simplebus, plic_driver, plic_devclass, | ||||
0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); | 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); |
Is it static?