svn commit: r335007 - in head/sys: conf riscv/conf riscv/include riscv/riscv

Ruslan Bukin br at FreeBSD.org
Tue Jun 12 17:45:18 UTC 2018


Author: br
Date: Tue Jun 12 17:45:15 2018
New Revision: 335007
URL: https://svnweb.freebsd.org/changeset/base/335007

Log:
  o Add driver for PLIC (Platform-Level Interrupt Controller) device.
  o Convert interrupt machdep support to use INTRNG code.
  
  Sponsored by:	DARPA, AFRL

Added:
  head/sys/riscv/riscv/plic.c   (contents, props changed)
Modified:
  head/sys/conf/files.riscv
  head/sys/conf/options.riscv
  head/sys/riscv/conf/GENERIC
  head/sys/riscv/include/intr.h
  head/sys/riscv/include/riscvreg.h
  head/sys/riscv/include/smp.h
  head/sys/riscv/riscv/intr_machdep.c
  head/sys/riscv/riscv/machdep.c
  head/sys/riscv/riscv/mp_machdep.c
  head/sys/riscv/riscv/nexus.c
  head/sys/riscv/riscv/timer.c

Modified: head/sys/conf/files.riscv
==============================================================================
--- head/sys/conf/files.riscv	Tue Jun 12 17:07:30 2018	(r335006)
+++ head/sys/conf/files.riscv	Tue Jun 12 17:45:15 2018	(r335007)
@@ -9,8 +9,11 @@ dev/ofw/ofw_cpu.c		optional	fdt
 dev/uart/uart_cpu_fdt.c		optional	uart fdt
 dev/xilinx/axi_quad_spi.c	optional	xilinx_spi
 kern/kern_clocksource.c		standard
+kern/msi_if.m			standard
+kern/pic_if.m			standard
 kern/subr_devmap.c		standard
 kern/subr_dummy_vdso_tc.c	standard
+kern/subr_intr.c		standard
 libkern/bcmp.c			standard
 libkern/bcopy.c			standard
 libkern/ffs.c			standard
@@ -44,6 +47,7 @@ riscv/riscv/mp_machdep.c	optional	smp
 riscv/riscv/mem.c		standard
 riscv/riscv/nexus.c		standard
 riscv/riscv/ofw_machdep.c	optional	fdt
+riscv/riscv/plic.c		standard
 riscv/riscv/pmap.c		standard
 riscv/riscv/riscv_console.c	optional	rcons
 riscv/riscv/soc.c		standard

Modified: head/sys/conf/options.riscv
==============================================================================
--- head/sys/conf/options.riscv	Tue Jun 12 17:07:30 2018	(r335006)
+++ head/sys/conf/options.riscv	Tue Jun 12 17:45:15 2018	(r335007)
@@ -2,3 +2,4 @@
 
 RISCV				opt_global.h
 FPE				opt_global.h
+INTRNG				opt_global.h

Modified: head/sys/riscv/conf/GENERIC
==============================================================================
--- head/sys/riscv/conf/GENERIC	Tue Jun 12 17:07:30 2018	(r335006)
+++ head/sys/riscv/conf/GENERIC	Tue Jun 12 17:45:15 2018	(r335007)
@@ -76,6 +76,7 @@ options 	RACCT			# Resource accounting framework
 options 	RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default
 options 	RCTL			# Resource limits
 options 	SMP
+options 	INTRNG
 
 # RISC-V SBI console
 device		rcons

Modified: head/sys/riscv/include/intr.h
==============================================================================
--- head/sys/riscv/include/intr.h	Tue Jun 12 17:07:30 2018	(r335006)
+++ head/sys/riscv/include/intr.h	Tue Jun 12 17:45:15 2018	(r335007)
@@ -37,11 +37,19 @@
 #ifndef	_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;
 
-void riscv_init_interrupts(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 *,
     void *, int, int, void **);
 void riscv_cpu_intr(struct trapframe *);
@@ -69,12 +77,7 @@ enum {
 	IRQ_EXTERNAL_SUPERVISOR,
 	IRQ_EXTERNAL_HYPERVISOR,
 	IRQ_EXTERNAL_MACHINE,
-#if 0
-	/* lowRISC TODO */
-	IRQ_COP,	/* lowRISC only */
-	IRQ_UART,	/* lowRISC only */
-#endif
-	NIRQS
+	INTC_NIRQS
 };
 
 #endif /* !_MACHINE_INTR_MACHDEP_H_ */

Modified: head/sys/riscv/include/riscvreg.h
==============================================================================
--- head/sys/riscv/include/riscvreg.h	Tue Jun 12 17:07:30 2018	(r335006)
+++ head/sys/riscv/include/riscvreg.h	Tue Jun 12 17:45:15 2018	(r335007)
@@ -137,6 +137,8 @@
 #define	SIE_SSIE	(1 << 1)
 #define	SIE_UTIE	(1 << 4)
 #define	SIE_STIE	(1 << 5)
+#define	SIE_UEIE	(1 << 8)
+#define	SIE_SEIE	(1 << 9)
 
 #define	MIP_SEIP	(1 << 9)
 

Modified: head/sys/riscv/include/smp.h
==============================================================================
--- head/sys/riscv/include/smp.h	Tue Jun 12 17:07:30 2018	(r335006)
+++ head/sys/riscv/include/smp.h	Tue Jun 12 17:45:15 2018	(r335007)
@@ -46,6 +46,8 @@
 #define	IPI_STOP_HARD	(1 << 4)
 #define	IPI_HARDCLOCK	(1 << 5)
 
+#define	INTR_IPI_COUNT	1
+
 void ipi_all_but_self(u_int ipi);
 void ipi_cpu(int cpu, u_int ipi);
 void ipi_selected(cpuset_t cpus, u_int ipi);

Modified: head/sys/riscv/riscv/intr_machdep.c
==============================================================================
--- head/sys/riscv/riscv/intr_machdep.c	Tue Jun 12 17:07:30 2018	(r335006)
+++ head/sys/riscv/riscv/intr_machdep.c	Tue Jun 12 17:45:15 2018	(r335007)
@@ -38,11 +38,13 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
 #include <sys/cpuset.h>
 #include <sys/interrupt.h>
 #include <sys/smp.h>
-#include <sys/vmmeter.h>
 
+#include <machine/bus.h>
 #include <machine/clock.h>
 #include <machine/cpu.h>
 #include <machine/cpufunc.h>
@@ -50,45 +52,23 @@ __FBSDID("$FreeBSD$");
 #include <machine/intr.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
 #include <machine/smp.h>
 #endif
 
-u_long intrcnt[NIRQS];
-size_t sintrcnt = sizeof(intrcnt);
+void intr_irq_handler(struct trapframe *tf);
 
-char intrnames[NIRQS * (MAXCOMLEN + 1) * 2];
-size_t sintrnames = sizeof(intrnames);
+struct intc_irqsrc {
+	struct intr_irqsrc	isrc;
+	u_int			irq;
+};
 
-static struct intr_event *intr_events[NIRQS];
-static riscv_intrcnt_t riscv_intr_counters[NIRQS];
+struct intc_irqsrc isrcs[INTC_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
 riscv_mask_irq(void *source)
 {
@@ -102,15 +82,10 @@ riscv_mask_irq(void *source)
 		break;
 	case IRQ_SOFTWARE_USER:
 		csr_clear(sie, SIE_USIE);
+		break;
 	case IRQ_SOFTWARE_SUPERVISOR:
 		csr_clear(sie, SIE_SSIE);
 		break;
-#if 0
-	/* lowRISC TODO */
-	case IRQ_UART:
-		machine_command(ECALL_IO_IRQ_MASK, 0);
-		break;
-#endif
 	default:
 		panic("Unknown irq %d\n", irq);
 	}
@@ -133,60 +108,37 @@ riscv_unmask_irq(void *source)
 	case IRQ_SOFTWARE_SUPERVISOR:
 		csr_set(sie, SIE_SSIE);
 		break;
-#if 0
-	/* lowRISC TODO */
-	case IRQ_UART:
-		machine_command(ECALL_IO_IRQ_MASK, 1);
-		break;
-#endif
 	default:
 		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
 riscv_setup_intr(const char *name, driver_filter_t *filt,
     void (*handler)(void*), void *arg, int irq, int flags, void **cookiep)
 {
-	struct intr_event *event;
+	struct intr_irqsrc *isrc;
 	int error;
 
-	if (irq < 0 || irq >= NIRQS)
+	if (irq < 0 || irq >= INTC_NIRQS)
 		panic("%s: unknown intr %d", __func__, irq);
 
-	event = intr_events[irq];
-	if (event == NULL) {
-		error = intr_event_create(&event, (void *)(uintptr_t)irq, 0,
-		    irq, riscv_mask_irq, riscv_unmask_irq,
-		    NULL, NULL, "int%d", irq);
+	isrc = &isrcs[irq].isrc;
+	if (isrc->isrc_event == NULL) {
+		error = intr_event_create(&isrc->isrc_event, isrc, 0, irq,
+		    riscv_mask_irq, riscv_unmask_irq, NULL, NULL, "int%d", irq);
 		if (error)
 			return (error);
-		intr_events[irq] = event;
 		riscv_unmask_irq((void*)(uintptr_t)irq);
 	}
 
-	error = intr_event_add_handler(event, name, filt, handler, arg,
-	    intr_priority(flags), flags, cookiep);
+	error = intr_event_add_handler(isrc->isrc_event, name,
+	    filt, handler, arg, intr_priority(flags), flags, cookiep);
 	if (error) {
 		printf("Failed to setup intr: %d\n", irq);
 		return (error);
 	}
 
-	riscv_intrcnt_setname(riscv_intr_counters[irq],
-			     event->ie_fullname);
-
 	return (0);
 }
 
@@ -199,19 +151,10 @@ riscv_teardown_intr(void *ih)
 	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
 riscv_cpu_intr(struct trapframe *frame)
 {
-	struct intr_event *event;
+	struct intr_irqsrc *isrc;
 	int active_irq;
 
 	critical_enter();
@@ -222,26 +165,20 @@ riscv_cpu_intr(struct trapframe *frame)
 	active_irq = (frame->tf_scause & EXCP_MASK);
 
 	switch (active_irq) {
-#if 0
-	/* lowRISC TODO */
-	case IRQ_UART:
-#endif
 	case IRQ_SOFTWARE_USER:
 	case IRQ_SOFTWARE_SUPERVISOR:
 	case IRQ_TIMER_SUPERVISOR:
-		event = intr_events[active_irq];
-		/* Update counters */
-		atomic_add_long(riscv_intr_counters[active_irq], 1);
-		VM_CNT_INC(v_intr);
+		isrc = &isrcs[active_irq].isrc;
+		if (intr_isrc_dispatch(isrc, frame) != 0)
+			printf("stray interrupt %d\n", active_irq);
 		break;
+	case IRQ_EXTERNAL_SUPERVISOR:
+		intr_irq_handler(frame);
+		break;
 	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();
 }
 
@@ -320,5 +257,22 @@ ipi_selected(cpuset_t cpus, u_int ipi)
 	}
 	sbi_send_ipi(&mask);
 }
-
 #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);

Modified: head/sys/riscv/riscv/machdep.c
==============================================================================
--- head/sys/riscv/riscv/machdep.c	Tue Jun 12 17:07:30 2018	(r335006)
+++ head/sys/riscv/riscv/machdep.c	Tue Jun 12 17:45:15 2018	(r335007)
@@ -872,8 +872,6 @@ initriscv(struct riscv_bootparams *rvbp)
 	init_param2(physmem);
 	kdb_init();
 
-	riscv_init_interrupts();
-
 	early_boot = 0;
 }
 

Modified: head/sys/riscv/riscv/mp_machdep.c
==============================================================================
--- head/sys/riscv/riscv/mp_machdep.c	Tue Jun 12 17:07:30 2018	(r335006)
+++ head/sys/riscv/riscv/mp_machdep.c	Tue Jun 12 17:45:15 2018	(r335007)
@@ -256,6 +256,9 @@ init_secondary(uint64_t cpu)
 	/* Enable interrupts */
 	intr_enable();
 
+	/* Enable external (PLIC) interrupts */
+	csr_set(sie, SIE_SEIE);
+
 	mtx_lock_spin(&ap_boot_mtx);
 
 	atomic_add_rel_32(&smp_cpus, 1);

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

Added: head/sys/riscv/riscv/plic.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/riscv/riscv/plic.c	Tue Jun 12 17:45:15 2018	(r335007)
@@ -0,0 +1,254 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018 Ruslan Bukin <br at 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);

Modified: head/sys/riscv/riscv/timer.c
==============================================================================
--- head/sys/riscv/riscv/timer.c	Tue Jun 12 17:07:30 2018	(r335006)
+++ head/sys/riscv/riscv/timer.c	Tue Jun 12 17:45:15 2018	(r335007)
@@ -70,8 +70,6 @@ struct riscv_timer_softc {
 	void			*ih;
 	uint32_t		clkfreq;
 	struct eventtimer	et;
-	int			intr_rid;
-	struct resource		*intr_res;
 };
 
 static struct riscv_timer_softc *riscv_timer_sc = NULL;
@@ -188,18 +186,9 @@ riscv_timer_attach(device_t dev)
 
 	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 */
-	error = bus_setup_intr(dev, sc->intr_res, INTR_TYPE_CLK,
-	    riscv_timer_intr, NULL, sc, &sc->ih);
+	error = riscv_setup_intr(device_get_nameunit(dev), riscv_timer_intr,
+	    NULL, sc, IRQ_TIMER_SUPERVISOR, INTR_TYPE_CLK, &sc->ih);
 	if (error) {
 		device_printf(dev, "Unable to alloc int resource.\n");
 		return (ENXIO);


More information about the svn-src-all mailing list