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 <b...@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);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to