From owner-svn-src-all@freebsd.org Tue Jun 12 17:45:18 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 8023A100BDE5; Tue, 12 Jun 2018 17:45:18 +0000 (UTC) (envelope-from br@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 2CF3B70D64; Tue, 12 Jun 2018 17:45:18 +0000 (UTC) (envelope-from br@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id E823E5E88; Tue, 12 Jun 2018 17:45:17 +0000 (UTC) (envelope-from br@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w5CHjHuh030128; Tue, 12 Jun 2018 17:45:17 GMT (envelope-from br@FreeBSD.org) Received: (from br@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w5CHjFR7030117; Tue, 12 Jun 2018 17:45:15 GMT (envelope-from br@FreeBSD.org) Message-Id: <201806121745.w5CHjFR7030117@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: br set sender to br@FreeBSD.org using -f From: Ruslan Bukin Date: Tue, 12 Jun 2018 17:45:15 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r335007 - in head/sys: conf riscv/conf riscv/include riscv/riscv X-SVN-Group: head X-SVN-Commit-Author: br X-SVN-Commit-Paths: in head/sys: conf riscv/conf riscv/include riscv/riscv X-SVN-Commit-Revision: 335007 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Jun 2018 17:45:18 -0000 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 +#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 #include #include +#include +#include #include #include #include -#include +#include #include #include #include @@ -50,45 +52,23 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include +#include + #ifdef SMP #include #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 __FBSDID("$FreeBSD$"); @@ -48,22 +49,18 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include -#include -#include -#include -#include - +#include #include #include -#include "opt_platform.h" - -#include +#ifdef FDT +#include +#include #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 + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#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);