o Add driver for PLIC (Platform-Level Interrupt Controller) device.

o Convert interrupt machdep support to use INTRNG code.

Sponsored by:	DARPA, AFRL
This commit is contained in:
Ruslan Bukin 2018-06-12 17:45:15 +00:00
parent ebdf0baf3a
commit 2d53a67c2c
12 changed files with 354 additions and 139 deletions

View file

@ -9,8 +9,11 @@ dev/ofw/ofw_cpu.c optional fdt
dev/uart/uart_cpu_fdt.c optional uart fdt dev/uart/uart_cpu_fdt.c optional uart fdt
dev/xilinx/axi_quad_spi.c optional xilinx_spi dev/xilinx/axi_quad_spi.c optional xilinx_spi
kern/kern_clocksource.c standard kern/kern_clocksource.c standard
kern/msi_if.m standard
kern/pic_if.m standard
kern/subr_devmap.c standard kern/subr_devmap.c standard
kern/subr_dummy_vdso_tc.c standard kern/subr_dummy_vdso_tc.c standard
kern/subr_intr.c standard
libkern/bcmp.c standard libkern/bcmp.c standard
libkern/bcopy.c standard libkern/bcopy.c standard
libkern/ffs.c standard libkern/ffs.c standard
@ -44,6 +47,7 @@ riscv/riscv/mp_machdep.c optional smp
riscv/riscv/mem.c standard riscv/riscv/mem.c standard
riscv/riscv/nexus.c standard riscv/riscv/nexus.c standard
riscv/riscv/ofw_machdep.c optional fdt riscv/riscv/ofw_machdep.c optional fdt
riscv/riscv/plic.c standard
riscv/riscv/pmap.c standard riscv/riscv/pmap.c standard
riscv/riscv/riscv_console.c optional rcons riscv/riscv/riscv_console.c optional rcons
riscv/riscv/soc.c standard riscv/riscv/soc.c standard

View file

@ -2,3 +2,4 @@
RISCV opt_global.h RISCV opt_global.h
FPE opt_global.h FPE opt_global.h
INTRNG opt_global.h

View file

@ -76,6 +76,7 @@ options RACCT # Resource accounting framework
options RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default options RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default
options RCTL # Resource limits options RCTL # Resource limits
options SMP options SMP
options INTRNG
# RISC-V SBI console # RISC-V SBI console
device rcons device rcons

View file

@ -37,11 +37,19 @@
#ifndef _MACHINE_INTR_MACHDEP_H_ #ifndef _MACHINE_INTR_MACHDEP_H_
#define _MACHINE_INTR_MACHDEP_H_ #define _MACHINE_INTR_MACHDEP_H_
#define RISCV_NIRQ 1024
#ifndef NIRQ
#define NIRQ RISCV_NIRQ
#endif
#ifdef INTRNG
#include <sys/intr.h>
#endif
struct trapframe; struct trapframe;
void riscv_init_interrupts(void);
int riscv_teardown_intr(void *); int riscv_teardown_intr(void *);
int riscv_config_intr(u_int, enum intr_trigger, enum intr_polarity);
int riscv_setup_intr(const char *, driver_filter_t *, driver_intr_t *, int riscv_setup_intr(const char *, driver_filter_t *, driver_intr_t *,
void *, int, int, void **); void *, int, int, void **);
void riscv_cpu_intr(struct trapframe *); void riscv_cpu_intr(struct trapframe *);
@ -69,12 +77,7 @@ enum {
IRQ_EXTERNAL_SUPERVISOR, IRQ_EXTERNAL_SUPERVISOR,
IRQ_EXTERNAL_HYPERVISOR, IRQ_EXTERNAL_HYPERVISOR,
IRQ_EXTERNAL_MACHINE, IRQ_EXTERNAL_MACHINE,
#if 0 INTC_NIRQS
/* lowRISC TODO */
IRQ_COP, /* lowRISC only */
IRQ_UART, /* lowRISC only */
#endif
NIRQS
}; };
#endif /* !_MACHINE_INTR_MACHDEP_H_ */ #endif /* !_MACHINE_INTR_MACHDEP_H_ */

View file

@ -137,6 +137,8 @@
#define SIE_SSIE (1 << 1) #define SIE_SSIE (1 << 1)
#define SIE_UTIE (1 << 4) #define SIE_UTIE (1 << 4)
#define SIE_STIE (1 << 5) #define SIE_STIE (1 << 5)
#define SIE_UEIE (1 << 8)
#define SIE_SEIE (1 << 9)
#define MIP_SEIP (1 << 9) #define MIP_SEIP (1 << 9)

View file

@ -46,6 +46,8 @@
#define IPI_STOP_HARD (1 << 4) #define IPI_STOP_HARD (1 << 4)
#define IPI_HARDCLOCK (1 << 5) #define IPI_HARDCLOCK (1 << 5)
#define INTR_IPI_COUNT 1
void ipi_all_but_self(u_int ipi); void ipi_all_but_self(u_int ipi);
void ipi_cpu(int cpu, u_int ipi); void ipi_cpu(int cpu, u_int ipi);
void ipi_selected(cpuset_t cpus, u_int ipi); void ipi_selected(cpuset_t cpus, u_int ipi);

View file

@ -38,11 +38,13 @@ __FBSDID("$FreeBSD$");
#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/module.h>
#include <sys/cpuset.h> #include <sys/cpuset.h>
#include <sys/interrupt.h> #include <sys/interrupt.h>
#include <sys/smp.h> #include <sys/smp.h>
#include <sys/vmmeter.h>
#include <machine/bus.h>
#include <machine/clock.h> #include <machine/clock.h>
#include <machine/cpu.h> #include <machine/cpu.h>
#include <machine/cpufunc.h> #include <machine/cpufunc.h>
@ -50,44 +52,22 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h> #include <machine/intr.h>
#include <machine/sbi.h> #include <machine/sbi.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#ifdef SMP #ifdef SMP
#include <machine/smp.h> #include <machine/smp.h>
#endif #endif
u_long intrcnt[NIRQS]; void intr_irq_handler(struct trapframe *tf);
size_t sintrcnt = sizeof(intrcnt);
char intrnames[NIRQS * (MAXCOMLEN + 1) * 2]; struct intc_irqsrc {
size_t sintrnames = sizeof(intrnames); struct intr_irqsrc isrc;
u_int irq;
};
static struct intr_event *intr_events[NIRQS]; struct intc_irqsrc isrcs[INTC_NIRQS];
static riscv_intrcnt_t riscv_intr_counters[NIRQS];
static int intrcnt_index;
riscv_intrcnt_t
riscv_intrcnt_create(const char* name)
{
riscv_intrcnt_t counter;
counter = &intrcnt[intrcnt_index++];
riscv_intrcnt_setname(counter, name);
return (counter);
}
void
riscv_intrcnt_setname(riscv_intrcnt_t counter, const char *name)
{
int i;
i = (counter - intrcnt);
KASSERT(counter != NULL, ("riscv_intrcnt_setname: NULL counter"));
snprintf(intrnames + (MAXCOMLEN + 1) * i,
MAXCOMLEN + 1, "%-*s", MAXCOMLEN, name);
}
static void static void
riscv_mask_irq(void *source) riscv_mask_irq(void *source)
@ -102,15 +82,10 @@ riscv_mask_irq(void *source)
break; break;
case IRQ_SOFTWARE_USER: case IRQ_SOFTWARE_USER:
csr_clear(sie, SIE_USIE); csr_clear(sie, SIE_USIE);
break;
case IRQ_SOFTWARE_SUPERVISOR: case IRQ_SOFTWARE_SUPERVISOR:
csr_clear(sie, SIE_SSIE); csr_clear(sie, SIE_SSIE);
break; break;
#if 0
/* lowRISC TODO */
case IRQ_UART:
machine_command(ECALL_IO_IRQ_MASK, 0);
break;
#endif
default: default:
panic("Unknown irq %d\n", irq); panic("Unknown irq %d\n", irq);
} }
@ -133,60 +108,37 @@ riscv_unmask_irq(void *source)
case IRQ_SOFTWARE_SUPERVISOR: case IRQ_SOFTWARE_SUPERVISOR:
csr_set(sie, SIE_SSIE); csr_set(sie, SIE_SSIE);
break; break;
#if 0
/* lowRISC TODO */
case IRQ_UART:
machine_command(ECALL_IO_IRQ_MASK, 1);
break;
#endif
default: default:
panic("Unknown irq %d\n", irq); panic("Unknown irq %d\n", irq);
} }
} }
void
riscv_init_interrupts(void)
{
char name[MAXCOMLEN + 1];
int i;
for (i = 0; i < NIRQS; i++) {
snprintf(name, MAXCOMLEN + 1, "int%d:", i);
riscv_intr_counters[i] = riscv_intrcnt_create(name);
}
}
int int
riscv_setup_intr(const char *name, driver_filter_t *filt, riscv_setup_intr(const char *name, driver_filter_t *filt,
void (*handler)(void*), void *arg, int irq, int flags, void **cookiep) void (*handler)(void*), void *arg, int irq, int flags, void **cookiep)
{ {
struct intr_event *event; struct intr_irqsrc *isrc;
int error; int error;
if (irq < 0 || irq >= NIRQS) if (irq < 0 || irq >= INTC_NIRQS)
panic("%s: unknown intr %d", __func__, irq); panic("%s: unknown intr %d", __func__, irq);
event = intr_events[irq]; isrc = &isrcs[irq].isrc;
if (event == NULL) { if (isrc->isrc_event == NULL) {
error = intr_event_create(&event, (void *)(uintptr_t)irq, 0, error = intr_event_create(&isrc->isrc_event, isrc, 0, irq,
irq, riscv_mask_irq, riscv_unmask_irq, riscv_mask_irq, riscv_unmask_irq, NULL, NULL, "int%d", irq);
NULL, NULL, "int%d", irq);
if (error) if (error)
return (error); return (error);
intr_events[irq] = event;
riscv_unmask_irq((void*)(uintptr_t)irq); riscv_unmask_irq((void*)(uintptr_t)irq);
} }
error = intr_event_add_handler(event, name, filt, handler, arg, error = intr_event_add_handler(isrc->isrc_event, name,
intr_priority(flags), flags, cookiep); filt, handler, arg, intr_priority(flags), flags, cookiep);
if (error) { if (error) {
printf("Failed to setup intr: %d\n", irq); printf("Failed to setup intr: %d\n", irq);
return (error); return (error);
} }
riscv_intrcnt_setname(riscv_intr_counters[irq],
event->ie_fullname);
return (0); return (0);
} }
@ -199,19 +151,10 @@ riscv_teardown_intr(void *ih)
return (0); return (0);
} }
int
riscv_config_intr(u_int irq, enum intr_trigger trig, enum intr_polarity pol)
{
/* There is no configuration for interrupts */
return (0);
}
void void
riscv_cpu_intr(struct trapframe *frame) riscv_cpu_intr(struct trapframe *frame)
{ {
struct intr_event *event; struct intr_irqsrc *isrc;
int active_irq; int active_irq;
critical_enter(); critical_enter();
@ -222,26 +165,20 @@ riscv_cpu_intr(struct trapframe *frame)
active_irq = (frame->tf_scause & EXCP_MASK); active_irq = (frame->tf_scause & EXCP_MASK);
switch (active_irq) { switch (active_irq) {
#if 0
/* lowRISC TODO */
case IRQ_UART:
#endif
case IRQ_SOFTWARE_USER: case IRQ_SOFTWARE_USER:
case IRQ_SOFTWARE_SUPERVISOR: case IRQ_SOFTWARE_SUPERVISOR:
case IRQ_TIMER_SUPERVISOR: case IRQ_TIMER_SUPERVISOR:
event = intr_events[active_irq]; isrc = &isrcs[active_irq].isrc;
/* Update counters */ if (intr_isrc_dispatch(isrc, frame) != 0)
atomic_add_long(riscv_intr_counters[active_irq], 1); printf("stray interrupt %d\n", active_irq);
VM_CNT_INC(v_intr); break;
case IRQ_EXTERNAL_SUPERVISOR:
intr_irq_handler(frame);
break; break;
default: default:
event = NULL; break;
} }
if (!event || TAILQ_EMPTY(&event->ie_handlers) ||
(intr_event_handle(event, frame) != 0))
printf("stray interrupt %d\n", active_irq);
critical_exit(); critical_exit();
} }
@ -320,5 +257,22 @@ ipi_selected(cpuset_t cpus, u_int ipi)
} }
sbi_send_ipi(&mask); sbi_send_ipi(&mask);
} }
#endif #endif
/* Interrupt machdep initialization routine. */
static void
intc_init(void *dummy __unused)
{
int error;
int i;
for (i = 0; i < INTC_NIRQS; i++) {
isrcs[i].irq = i;
error = intr_isrc_register(&isrcs[i].isrc, NULL,
0, "intc,%u", i);
if (error != 0)
printf("Can't register interrupt %d\n", i);
}
}
SYSINIT(intc_init, SI_SUB_INTR, SI_ORDER_MIDDLE, intc_init, NULL);

View file

@ -872,8 +872,6 @@ initriscv(struct riscv_bootparams *rvbp)
init_param2(physmem); init_param2(physmem);
kdb_init(); kdb_init();
riscv_init_interrupts();
early_boot = 0; early_boot = 0;
} }

View file

@ -256,6 +256,9 @@ init_secondary(uint64_t cpu)
/* Enable interrupts */ /* Enable interrupts */
intr_enable(); intr_enable();
/* Enable external (PLIC) interrupts */
csr_set(sie, SIE_SEIE);
mtx_lock_spin(&ap_boot_mtx); mtx_lock_spin(&ap_boot_mtx);
atomic_add_rel_32(&smp_cpus, 1); atomic_add_rel_32(&smp_cpus, 1);

View file

@ -38,6 +38,7 @@
* ISA code but it's easier to do it here for now), I/O port addresses, * ISA code but it's easier to do it here for now), I/O port addresses,
* and I/O memory address space. * and I/O memory address space.
*/ */
#include "opt_platform.h"
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
@ -48,22 +49,18 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h> #include <sys/kernel.h>
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/module.h> #include <sys/module.h>
#include <machine/bus.h>
#include <sys/rman.h> #include <sys/rman.h>
#include <sys/interrupt.h> #include <sys/interrupt.h>
#include <machine/vmparam.h> #include <machine/bus.h>
#include <machine/pcb.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/resource.h> #include <machine/resource.h>
#include <machine/intr.h> #include <machine/intr.h>
#include "opt_platform.h" #ifdef FDT
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/fdt/fdt_common.h> #include <dev/ofw/openfirm.h>
#include "ofw_bus_if.h" #include "ofw_bus_if.h"
#endif
extern struct bus_space memmap_bus; extern struct bus_space memmap_bus;
@ -265,7 +262,7 @@ nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
enum intr_polarity pol) enum intr_polarity pol)
{ {
return (riscv_config_intr(irq, trig, pol)); return (EOPNOTSUPP);
} }
static int static int
@ -282,8 +279,7 @@ nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
if (error) if (error)
return (error); return (error);
error = riscv_setup_intr(device_get_nameunit(child), filt, intr, error = intr_setup_irq(child, res, filt, intr, arg, flags, cookiep);
arg, rman_get_start(res), flags, cookiep);
return (error); return (error);
} }
@ -292,7 +288,7 @@ static int
nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
{ {
return (riscv_teardown_intr(ih)); return (intr_teardown_irq(child, r, ih));
} }
static int static int
@ -321,7 +317,14 @@ nexus_activate_resource(device_t bus, device_t child, int type, int rid,
rman_set_bustag(r, &memmap_bus); rman_set_bustag(r, &memmap_bus);
rman_set_virtual(r, (void *)vaddr); rman_set_virtual(r, (void *)vaddr);
rman_set_bushandle(r, vaddr); rman_set_bushandle(r, vaddr);
} else if (type == SYS_RES_IRQ) {
err = intr_activate_irq(child, r);
if (err != 0) {
rman_deactivate_resource(r);
return (err);
}
} }
return (0); return (0);
} }
@ -375,16 +378,17 @@ static int
nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells,
pcell_t *intr) pcell_t *intr)
{ {
int irq; struct intr_map_data_fdt *fdt_data;
size_t len;
u_int irq;
if (icells == 3) { len = sizeof(*fdt_data) + icells * sizeof(pcell_t);
irq = intr[1]; fdt_data = (struct intr_map_data_fdt *)intr_alloc_map_data(
if (intr[0] == 0) INTR_MAP_DATA_FDT, len, M_WAITOK | M_ZERO);
irq += 32; /* SPI */ fdt_data->iparent = iparent;
else fdt_data->ncells = icells;
irq += 16; /* PPI */ memcpy(fdt_data->cells, intr, icells * sizeof(pcell_t));
} else irq = intr_map_irq(NULL, iparent, (struct intr_map_data *)fdt_data);
irq = intr[0];
return (irq); return (irq);
} }

254
sys/riscv/riscv/plic.c Normal file
View file

@ -0,0 +1,254 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
* ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/rman.h>
#include <machine/bus.h>
#include <machine/intr.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include "pic_if.h"
#define PLIC_NIRQS 32
#define PLIC_PRIORITY(n) (0x000000 + (n) * 0x4)
#define PLIC_ENABLE(n, h) (0x002000 + (h) * 0x80 + (n) / 32)
#define PLIC_THRESHOLD(h) (0x200000 + (h) * 0x1000 + 0x0)
#define PLIC_CLAIM(h) (0x200000 + (h) * 0x1000 + 0x4)
struct plic_irqsrc {
struct intr_irqsrc isrc;
u_int irq;
};
struct plic_softc {
device_t dev;
struct resource * intc_res;
struct plic_irqsrc isrcs[PLIC_NIRQS];
};
#define RD4(sc, reg) \
bus_read_4(sc->intc_res, (reg))
#define WR4(sc, reg, val) \
bus_write_4(sc->intc_res, (reg), (val))
static inline void
plic_irq_dispatch(struct plic_softc *sc, u_int irq,
struct trapframe *tf)
{
struct plic_irqsrc *src;
src = &sc->isrcs[irq];
if (intr_isrc_dispatch(&src->isrc, tf) != 0)
device_printf(sc->dev, "Stray irq %u detected\n", irq);
}
static int
plic_intr(void *arg)
{
struct plic_softc *sc;
struct trapframe *tf;
uint32_t pending;
uint32_t cpu;
sc = arg;
cpu = PCPU_GET(cpuid);
pending = RD4(sc, PLIC_CLAIM(cpu));
if (pending) {
tf = curthread->td_intr_frame;
plic_irq_dispatch(sc, pending, tf);
WR4(sc, PLIC_CLAIM(cpu), pending);
}
return (FILTER_HANDLED);
}
static void
plic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
{
struct plic_softc *sc;
struct plic_irqsrc *src;
uint32_t reg;
uint32_t cpu;
sc = device_get_softc(dev);
src = (struct plic_irqsrc *)isrc;
cpu = PCPU_GET(cpuid);
reg = RD4(sc, PLIC_ENABLE(src->irq, cpu));
reg &= ~(1 << (src->irq % 32));
WR4(sc, PLIC_ENABLE(src->irq, cpu), reg);
}
static void
plic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
{
struct plic_softc *sc;
struct plic_irqsrc *src;
uint32_t reg;
uint32_t cpu;
sc = device_get_softc(dev);
src = (struct plic_irqsrc *)isrc;
WR4(sc, PLIC_PRIORITY(src->irq), 1);
cpu = PCPU_GET(cpuid);
reg = RD4(sc, PLIC_ENABLE(src->irq, cpu));
reg |= (1 << (src->irq % 32));
WR4(sc, PLIC_ENABLE(src->irq, cpu), reg);
}
static int
plic_map_intr(device_t dev, struct intr_map_data *data,
struct intr_irqsrc **isrcp)
{
struct intr_map_data_fdt *daf;
struct plic_softc *sc;
sc = device_get_softc(dev);
if (data->type != INTR_MAP_DATA_FDT)
return (ENOTSUP);
daf = (struct intr_map_data_fdt *)data;
if (daf->ncells != 1 || daf->cells[0] >= PLIC_NIRQS)
return (EINVAL);
*isrcp = &sc->isrcs[daf->cells[0]].isrc;
return (0);
}
static int
plic_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "riscv,plic0"))
return (ENXIO);
device_set_desc(dev, "RISC-V PLIC");
return (BUS_PROBE_DEFAULT);
}
static int
plic_attach(device_t dev)
{
struct plic_irqsrc *isrcs;
struct plic_softc *sc;
struct intr_pic *pic;
uint32_t irq;
const char *name;
phandle_t xref;
uint32_t cpu;
int error;
int rid;
sc = device_get_softc(dev);
sc->dev = dev;
/* Request memory resources */
rid = 0;
sc->intc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
if (sc->intc_res == NULL) {
device_printf(dev,
"Error: could not allocate memory resources\n");
return (ENXIO);
}
isrcs = sc->isrcs;
name = device_get_nameunit(sc->dev);
cpu = PCPU_GET(cpuid);
for (irq = 0; irq < PLIC_NIRQS; irq++) {
isrcs[irq].irq = irq;
error = intr_isrc_register(&isrcs[irq].isrc, sc->dev,
0, "%s,%u", name, irq);
if (error != 0)
return (error);
WR4(sc, PLIC_ENABLE(irq, cpu), 0);
}
WR4(sc, PLIC_THRESHOLD(cpu), 0);
xref = OF_xref_from_node(ofw_bus_get_node(sc->dev));
pic = intr_pic_register(sc->dev, xref);
if (pic == NULL)
return (ENXIO);
csr_set(sie, SIE_SEIE);
return (intr_pic_claim_root(sc->dev, xref, plic_intr, sc, 0));
}
static device_method_t plic_methods[] = {
DEVMETHOD(device_probe, plic_probe),
DEVMETHOD(device_attach, plic_attach),
DEVMETHOD(pic_disable_intr, plic_disable_intr),
DEVMETHOD(pic_enable_intr, plic_enable_intr),
DEVMETHOD(pic_map_intr, plic_map_intr),
DEVMETHOD_END
};
static driver_t plic_driver = {
"plic",
plic_methods,
sizeof(struct plic_softc),
};
static devclass_t plic_devclass;
EARLY_DRIVER_MODULE(plic, simplebus, plic_driver, plic_devclass,
0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);

View file

@ -70,8 +70,6 @@ struct riscv_timer_softc {
void *ih; void *ih;
uint32_t clkfreq; uint32_t clkfreq;
struct eventtimer et; struct eventtimer et;
int intr_rid;
struct resource *intr_res;
}; };
static struct riscv_timer_softc *riscv_timer_sc = NULL; static struct riscv_timer_softc *riscv_timer_sc = NULL;
@ -188,18 +186,9 @@ riscv_timer_attach(device_t dev)
riscv_timer_sc = sc; riscv_timer_sc = sc;
sc->intr_rid = 0;
sc->intr_res = bus_alloc_resource(dev,
SYS_RES_IRQ, &sc->intr_rid, IRQ_TIMER_SUPERVISOR,
IRQ_TIMER_SUPERVISOR, 1, RF_ACTIVE);
if (sc->intr_res == NULL) {
device_printf(dev, "failed to allocate irq\n");
return (ENXIO);
}
/* Setup IRQs handler */ /* Setup IRQs handler */
error = bus_setup_intr(dev, sc->intr_res, INTR_TYPE_CLK, error = riscv_setup_intr(device_get_nameunit(dev), riscv_timer_intr,
riscv_timer_intr, NULL, sc, &sc->ih); NULL, sc, IRQ_TIMER_SUPERVISOR, INTR_TYPE_CLK, &sc->ih);
if (error) { if (error) {
device_printf(dev, "Unable to alloc int resource.\n"); device_printf(dev, "Unable to alloc int resource.\n");
return (ENXIO); return (ENXIO);