svn commit: r295498 - in head/sys/mips: include mips

Adrian Chadd adrian at FreeBSD.org
Thu Feb 11 06:09:29 UTC 2016


Author: adrian
Date: Thu Feb 11 06:09:27 2016
New Revision: 295498
URL: https://svnweb.freebsd.org/changeset/base/295498

Log:
  Begin the MIPS_INTRNG support.
  
  This is a prelude to intr-ng support for MIPS boards that need it -
  notably the CI20 port from kan@ that's upcoming, but also work that
  Stanislav is doing for the Mediatek platforms.
  
  This is the initial platform dependent bits in include/intr.h, some
  #defines for the nexus code for the intrng initialisation/runtime
  bits, some changed naming (which I'll fix later to be the same, much
  like what I did for ARM intr-ng) in exception.S, and the first cut
  at a PIC.
  
  Stanislav and I refactored out the common code for intrng support,
  so the mips intrng definitions are quite small (sys/mips/include/intr.h.)
  
  This is all work done by kan@, which stanislav has been cherry picking
  into common code for his mediatek chipset work.
  
  Tested:
  
  * Carambola2 - no regressions (not intr-ng though!)
  
  Submitted by:	Stanislav Galabov <sgalabov at gmail.com>
  Reviewed by:	kan (original author)
  Differential Revision:	https://reviews.freebsd.org/D5182

Added:
  head/sys/mips/include/intr.h   (contents, props changed)
  head/sys/mips/mips/mips_pic.c   (contents, props changed)
Modified:
  head/sys/mips/include/smp.h
  head/sys/mips/mips/exception.S
  head/sys/mips/mips/nexus.c

Added: head/sys/mips/include/intr.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/mips/include/intr.h	Thu Feb 11 06:09:27 2016	(r295498)
@@ -0,0 +1,67 @@
+/* 	$NetBSD: intr.h,v 1.7 2003/06/16 20:01:00 thorpej Exp $	*/
+
+/*-
+ * Copyright (c) 1997 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Mark Brinicombe
+ *	for the NetBSD Project.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
+ *
+ * $FreeBSD$
+ *
+ */
+
+#ifndef _MACHINE_INTR_H_
+#define _MACHINE_INTR_H_
+
+#ifdef MIPS_INTRNG
+
+#ifdef FDT
+#include <dev/ofw/openfirm.h>
+#endif
+
+#include <sys/intr.h>
+
+#ifndef NIRQ
+#define	NIRQ		128
+#endif
+
+#define INTR_IRQ_NSPC_SWI	4
+
+/* MIPS compatibility for legacy mips code */
+void cpu_init_interrupts(void);
+void cpu_establish_hardintr(const char *, driver_filter_t *, driver_intr_t *,
+    void *, int, int, void **);
+void cpu_establish_softintr(const char *, driver_filter_t *, void (*)(void*),
+    void *, int, int, void **);
+/* MIPS interrupt C entry point */
+void cpu_intr(struct trapframe *);
+
+#endif /* MIPS_INTRNG */
+
+#endif	/* _MACHINE_INTR_H */

Modified: head/sys/mips/include/smp.h
==============================================================================
--- head/sys/mips/include/smp.h	Thu Feb 11 02:02:01 2016	(r295497)
+++ head/sys/mips/include/smp.h	Thu Feb 11 06:09:27 2016	(r295498)
@@ -21,6 +21,11 @@
 
 #include <machine/pcb.h>
 
+#ifdef MIPS_INTRNG
+# define MIPS_IPI_COUNT 	1
+# define INTR_IPI_COUNT 	MIPS_IPI_COUNT
+#endif
+
 /*
  * Interprocessor interrupts for SMP.
  */

Modified: head/sys/mips/mips/exception.S
==============================================================================
--- head/sys/mips/mips/exception.S	Thu Feb 11 02:02:01 2016	(r295497)
+++ head/sys/mips/mips/exception.S	Thu Feb 11 06:09:27 2016	(r295498)
@@ -646,7 +646,11 @@ NESTED_NOPROFILE(MipsKernIntr, KERN_EXC_
  *  Call the interrupt handler. a0 points at the saved frame.
  */
 	PTR_LA	gp, _C_LABEL(_gp)
+#ifdef MIPS_INTRNG
+	PTR_LA	k0, _C_LABEL(intr_irq_handler)
+#else
 	PTR_LA	k0, _C_LABEL(cpu_intr)
+#endif
 	jalr	k0
 	REG_S	a3, CALLFRAME_RA + KERN_REG_SIZE(sp)		# for debugging
 
@@ -758,7 +762,11 @@ NESTED_NOPROFILE(MipsUserIntr, CALLFRAME
 /*
  * Call the interrupt handler.
  */
+#ifdef MIPS_INTRNG
+	PTR_LA	k0, _C_LABEL(intr_irq_handler)
+#else
 	PTR_LA	k0, _C_LABEL(cpu_intr)
+#endif
 	jalr	k0
 	REG_S	a3, CALLFRAME_RA(sp)	# for debugging
 
@@ -1190,6 +1198,7 @@ FPReturn:
 	PTR_ADDU sp, sp, CALLFRAME_SIZ
 END(MipsFPTrap)
 
+#ifndef MIPS_INTRNG
 /*
  * Interrupt counters for vmstat.
  */
@@ -1216,6 +1225,7 @@ sintrcnt:
 #else
 	.int  INTRCNT_COUNT * (_MIPS_SZLONG / 8) * 2
 #endif
+#endif /* MIPS_INTRNG */
 
 
 /*

Added: head/sys/mips/mips/mips_pic.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/mips/mips/mips_pic.c	Thu Feb 11 06:09:27 2016	(r295498)
@@ -0,0 +1,512 @@
+/*-
+ * Copyright (c) 2015 Alexander Kabaev
+ * Copyright (c) 2006 Oleksandr Tymoshenko
+ * Copyright (c) 2002-2004 Juli Mallett <jmallett at FreeBSD.org>
+ * All rights reserved.
+ *
+ * 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,
+ *    without modification, immediately at the beginning of the file.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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 "opt_platform.h"
+#include "opt_hwpmc_hooks.h"
+
+#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/malloc.h>
+#include <sys/rman.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/cpuset.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/smp.h>
+#include <sys/sched.h>
+
+#include <machine/bus.h>
+#include <machine/hwfunc.h>
+#include <machine/intr.h>
+#include <machine/smp.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+#include "pic_if.h"
+
+#define NHARD_IRQS	6
+#define NSOFT_IRQS	2
+#define NREAL_IRQS	(NHARD_IRQS + NSOFT_IRQS)
+
+static int mips_pic_intr(void *);
+
+struct mips_pic_softc {
+	device_t		pic_dev;
+	struct intr_irqsrc *	pic_irqs[NREAL_IRQS];
+	struct mtx		mutex;
+	uint32_t		nirqs;
+};
+
+static struct mips_pic_softc *pic_sc;
+
+#ifdef FDT
+static struct ofw_compat_data compat_data[] = {
+	{"mti,cpu-interrupt-controller",	true},
+	{NULL,					false}
+};
+#endif
+
+#ifndef FDT
+static void
+mips_pic_identify(driver_t *drv, device_t parent)
+{
+
+	BUS_ADD_CHILD(parent, 0, "cpupic", 0);
+}
+#endif
+
+static int
+mips_pic_probe(device_t dev)
+{
+
+#ifdef FDT
+	if (!ofw_bus_status_okay(dev))
+		return (ENXIO);
+
+	if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+		return (ENXIO);
+#endif
+	device_set_desc(dev, "MIPS32 Interrupt Controller");
+	return (BUS_PROBE_DEFAULT);
+}
+
+static inline void
+pic_irq_unmask(struct mips_pic_softc *sc, u_int irq)
+{
+
+	mips_wr_status(mips_rd_status() | ((1 << irq) << 8));
+}
+
+static inline void
+pic_irq_mask(struct mips_pic_softc *sc, u_int irq)
+{
+
+	mips_wr_status(mips_rd_status() & ~((1 << irq) << 8));
+}
+
+#ifdef SMP
+static void
+mips_pic_init_secondary(device_t dev)
+{
+}
+#endif /* SMP */
+
+static inline intptr_t
+pic_xref(device_t dev)
+{
+#ifdef FDT
+	return (OF_xref_from_node(ofw_bus_get_node(dev)));
+#else
+	return (0);
+#endif
+}
+
+static int
+mips_pic_attach(device_t dev)
+{
+	struct		mips_pic_softc *sc;
+	intptr_t	xref = pic_xref(dev);
+
+	if (pic_sc)
+		return (ENXIO);
+
+	sc = device_get_softc(dev);
+
+	sc->pic_dev = dev;
+	pic_sc = sc;
+
+	/* Initialize mutex */
+	mtx_init(&sc->mutex, "PIC lock", "", MTX_SPIN);
+
+	/* Set the number of interrupts */
+	sc->nirqs = nitems(sc->pic_irqs);
+
+	/*
+	 * Now, when everything is initialized, it's right time to
+	 * register interrupt controller to interrupt framefork.
+	 */
+	if (intr_pic_register(dev, xref) != 0) {
+		device_printf(dev, "could not register PIC\n");
+		goto cleanup;
+	}
+
+	/* Claim our root controller role */
+	if (intr_pic_claim_root(dev, xref, mips_pic_intr, sc, 0) != 0) {
+		device_printf(dev, "could not set PIC as a root\n");
+		intr_pic_unregister(dev, xref);
+		goto cleanup;
+	}
+
+	return (0);
+
+cleanup:
+	return(ENXIO);
+}
+
+int
+mips_pic_intr(void *arg)
+{
+	struct mips_pic_softc *sc = arg;
+	register_t cause, status;
+	struct intr_irqsrc *isrc;
+	int i, intr;
+
+	cause = mips_rd_cause();
+	status = mips_rd_status();
+	intr = (cause & MIPS_INT_MASK) >> 8;
+	/*
+	 * Do not handle masked interrupts. They were masked by
+	 * pre_ithread function (mips_mask_XXX_intr) and will be
+	 * unmasked once ithread is through with handler
+	 */
+	intr &= (status & MIPS_INT_MASK) >> 8;
+	while ((i = fls(intr)) != 0) {
+		i--; /* Get a 0-offset interrupt. */
+		intr &= ~(1 << i);
+
+		isrc = sc->pic_irqs[i];
+		if (isrc == NULL) {
+			device_printf(sc->pic_dev,
+			    "Stray interrupt %u detected\n", i);
+			pic_irq_mask(sc, i);
+			continue;
+		}
+
+		intr_irq_dispatch(isrc, curthread->td_intr_frame);
+	}
+
+	KASSERT(i == 0, ("all interrupts handled"));
+
+#ifdef HWPMC_HOOKS
+	if (pmc_hook && (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN))
+		pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, tf);
+#endif
+	return (FILTER_HANDLED);
+}
+
+static int
+pic_attach_isrc(struct mips_pic_softc *sc, struct intr_irqsrc *isrc, u_int irq)
+{
+
+	/*
+	 * 1. The link between ISRC and controller must be set atomically.
+	 * 2. Just do things only once in rare case when consumers
+	 *    of shared interrupt came here at the same moment.
+	 */
+	mtx_lock_spin(&sc->mutex);
+	if (sc->pic_irqs[irq] != NULL) {
+		mtx_unlock_spin(&sc->mutex);
+		return (sc->pic_irqs[irq] == isrc ? 0 : EEXIST);
+	}
+	sc->pic_irqs[irq] = isrc;
+	isrc->isrc_data = irq;
+	mtx_unlock_spin(&sc->mutex);
+
+	if (irq < NSOFT_IRQS)
+		intr_irq_set_name(isrc, "sint%u", irq);
+	else if (irq < NREAL_IRQS)
+		intr_irq_set_name(isrc, "int%u", irq - NSOFT_IRQS);
+	else
+		panic("Invalid irq %u", irq);
+	return (0);
+}
+
+static int
+pic_detach_isrc(struct mips_pic_softc *sc, struct intr_irqsrc *isrc, u_int irq)
+{
+
+	mtx_lock_spin(&sc->mutex);
+	if (sc->pic_irqs[irq] != isrc) {
+		mtx_unlock_spin(&sc->mutex);
+		return (sc->pic_irqs[irq] == NULL ? 0 : EINVAL);
+	}
+	sc->pic_irqs[irq] = NULL;
+	isrc->isrc_data = 0;
+	mtx_unlock_spin(&sc->mutex);
+
+	intr_irq_set_name(isrc, "%s", "");
+	return (0);
+}
+
+static int
+pic_irq_from_nspc(struct mips_pic_softc *sc, u_int type, u_int num, u_int *irqp)
+{
+
+	switch (type) {
+	case INTR_IRQ_NSPC_PLAIN:
+		*irqp = num;
+		return (*irqp < sc->nirqs ? 0 : EINVAL);
+
+	case INTR_IRQ_NSPC_SWI:
+		*irqp = num;
+		return (num < NSOFT_IRQS ? 0 : EINVAL);
+
+	case INTR_IRQ_NSPC_IRQ:
+		*irqp = num + NSOFT_IRQS;
+		return (num < NHARD_IRQS ? 0 : EINVAL);
+
+	default:
+		return (EINVAL);
+	}
+}
+
+static int
+pic_map_nspc(struct mips_pic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp)
+{
+	int error;
+
+	error = pic_irq_from_nspc(sc, isrc->isrc_nspc_type, isrc->isrc_nspc_num,
+	    irqp);
+	if (error != 0)
+		return (error);
+	return (pic_attach_isrc(sc, isrc, *irqp));
+}
+
+#ifdef FDT
+static int
+pic_map_fdt(struct mips_pic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp)
+{
+	u_int irq;
+	int error;
+
+	irq = isrc->isrc_cells[0];
+
+	if (irq >= sc->nirqs)
+		return (EINVAL);
+
+	error = pic_attach_isrc(sc, isrc, irq);
+	if (error != 0)
+		return (error);
+
+	isrc->isrc_nspc_type = INTR_IRQ_NSPC_PLAIN;
+	isrc->isrc_nspc_num = irq;
+	isrc->isrc_trig = INTR_TRIGGER_CONFORM;
+	isrc->isrc_pol = INTR_POLARITY_CONFORM;
+
+	*irqp = irq;
+	return (0);
+}
+#endif
+
+static int
+mips_pic_register(device_t dev, struct intr_irqsrc *isrc, boolean_t *is_percpu)
+{
+	struct mips_pic_softc *sc = device_get_softc(dev);
+	u_int irq;
+	int error;
+
+	if (isrc->isrc_type == INTR_ISRCT_NAMESPACE)
+		error = pic_map_nspc(sc, isrc, &irq);
+#ifdef FDT
+	else if (isrc->isrc_type == INTR_ISRCT_FDT)
+		error = pic_map_fdt(sc, isrc, &irq);
+#endif
+	else
+		return (EINVAL);
+
+	if (error == 0)
+		*is_percpu = TRUE;
+	return (error);
+}
+
+static void
+mips_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+
+	if (isrc->isrc_trig == INTR_TRIGGER_CONFORM)
+		isrc->isrc_trig = INTR_TRIGGER_LEVEL;
+}
+
+static void
+mips_pic_enable_source(device_t dev, struct intr_irqsrc *isrc)
+{
+	struct mips_pic_softc *sc = device_get_softc(dev);
+	u_int irq = isrc->isrc_data;
+
+	pic_irq_unmask(sc, irq);
+}
+
+static void
+mips_pic_disable_source(device_t dev, struct intr_irqsrc *isrc)
+{
+	struct mips_pic_softc *sc = device_get_softc(dev);
+	u_int irq = isrc->isrc_data;
+
+	pic_irq_mask(sc, irq);
+}
+
+static int
+mips_pic_unregister(device_t dev, struct intr_irqsrc *isrc)
+{
+	struct mips_pic_softc *sc = device_get_softc(dev);
+	u_int irq = isrc->isrc_data;
+
+	return (pic_detach_isrc(sc, isrc, irq));
+}
+
+static void
+mips_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+
+	mips_pic_disable_source(dev, isrc);
+}
+
+static void
+mips_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+
+	mips_pic_enable_source(dev, isrc);
+}
+
+static void
+mips_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
+{
+}
+
+#ifdef SMP
+static int
+mips_pic_bind(device_t dev, struct intr_irqsrc *isrc)
+{
+	return (EOPNOTSUPP);
+}
+
+static void
+mips_pic_ipi_send(device_t dev, struct intr_irqsrc *isrc, cpuset_t cpus)
+{
+}
+#endif
+
+static device_method_t mips_pic_methods[] = {
+	/* Device interface */
+#ifndef FDT
+	DEVMETHOD(device_identify,	mips_pic_identify),
+#endif
+	DEVMETHOD(device_probe,		mips_pic_probe),
+	DEVMETHOD(device_attach,	mips_pic_attach),
+	/* Interrupt controller interface */
+	DEVMETHOD(pic_disable_source,	mips_pic_disable_source),
+	DEVMETHOD(pic_enable_intr,	mips_pic_enable_intr),
+	DEVMETHOD(pic_enable_source,	mips_pic_enable_source),
+	DEVMETHOD(pic_post_filter,	mips_pic_post_filter),
+	DEVMETHOD(pic_post_ithread,	mips_pic_post_ithread),
+	DEVMETHOD(pic_pre_ithread,	mips_pic_pre_ithread),
+	DEVMETHOD(pic_register,		mips_pic_register),
+	DEVMETHOD(pic_unregister,	mips_pic_unregister),
+#ifdef SMP
+	DEVMETHOD(pic_bind,		mips_pic_bind),
+	DEVMETHOD(pic_init_secondary,	mips_pic_init_secondary),
+	DEVMETHOD(pic_ipi_send,		mips_pic_ipi_send),
+#endif
+	{ 0, 0 }
+};
+
+static driver_t mips_pic_driver = {
+	"cpupic",
+	mips_pic_methods,
+	sizeof(struct mips_pic_softc),
+};
+
+static devclass_t mips_pic_devclass;
+
+#ifdef FDT
+DRIVER_MODULE(cpupic, ofwbus, mips_pic_driver, mips_pic_devclass, 0, 0);
+#else
+DRIVER_MODULE(cpupic, nexus, mips_pic_driver, mips_pic_devclass, 0, 0);
+#endif
+
+void
+cpu_init_interrupts(void)
+{
+}
+
+void
+cpu_establish_hardintr(const char *name, driver_filter_t *filt,
+    void (*handler)(void*), void *arg, int irq, int flags, void **cookiep)
+{
+	u_int vec;
+	int res;
+
+	/*
+	 * We have 6 levels, but thats 0 - 5 (not including 6)
+	 */
+	if (irq < 0 || irq >= NHARD_IRQS)
+		panic("%s called for unknown hard intr %d", __func__, irq);
+
+	KASSERT(pic_sc != NULL, ("%s: no pic", __func__));
+	vec = intr_namespace_map_irq(pic_sc->pic_dev, INTR_IRQ_NSPC_IRQ, irq);
+	KASSERT(vec != NIRQ, ("Unable to map hard IRQ %d\n", irq));
+
+	res = intr_irq_add_handler(pic_sc->pic_dev, filt, handler, arg, vec,
+	    flags, cookiep);
+	if (res != 0) panic("Unable to add hard IRQ %d handler", irq);
+
+	(void)pic_irq_from_nspc(pic_sc, INTR_IRQ_NSPC_IRQ, irq, &vec);
+	KASSERT(pic_sc->pic_irqs[vec] != NULL,
+	    ("Hard IRQ %d not registered\n", irq));
+	intr_irq_set_name(pic_sc->pic_irqs[vec], "%s", name);
+}
+
+void
+cpu_establish_softintr(const char *name, driver_filter_t *filt,
+    void (*handler)(void*), void *arg, int irq, int flags,
+    void **cookiep)
+{
+	u_int vec;
+	int res;
+
+	if (irq < 0 || irq > NSOFT_IRQS)
+		panic("%s called for unknown soft intr %d", __func__, irq);
+
+	KASSERT(pic_sc != NULL, ("%s: no pic", __func__));
+	vec = intr_namespace_map_irq(pic_sc->pic_dev, INTR_IRQ_NSPC_SWI, irq);
+	KASSERT(vec <= NIRQ, ("Unable to map soft IRQ %d\n", irq));
+
+	intr_irq_add_handler(pic_sc->pic_dev, filt, handler, arg, vec,
+	    flags, cookiep);
+	if (res != 0) panic("Unable to add soft IRQ %d handler", irq);
+
+	(void)pic_irq_from_nspc(pic_sc, INTR_IRQ_NSPC_SWI, irq, &vec);
+	KASSERT(pic_sc->pic_irqs[vec] != NULL,
+	    ("Soft IRQ %d not registered\n", irq));
+	intr_irq_set_name(pic_sc->pic_irqs[vec], "%s", name);
+}
+

Modified: head/sys/mips/mips/nexus.c
==============================================================================
--- head/sys/mips/mips/nexus.c	Thu Feb 11 02:02:01 2016	(r295497)
+++ head/sys/mips/mips/nexus.c	Thu Feb 11 06:09:27 2016	(r295498)
@@ -36,6 +36,7 @@
  * this code implements the core resource managers for interrupt
  * requests and memory address space.
  */
+#include "opt_platform.h"
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
@@ -53,13 +54,23 @@ __FBSDID("$FreeBSD$");
 #include <vm/pmap.h>
 
 #include <machine/bus.h>
-#include <machine/intr_machdep.h>
 #include <machine/pmap.h>
 #include <machine/resource.h>
 #include <machine/vmparam.h>
 
+#ifdef MIPS_INTRNG
+#include <machine/intr.h>
+#else
+#include <machine/intr_machdep.h>
+#endif
+
 #include "opt_platform.h"
 
+#ifdef FDT
+#include <machine/fdt.h>
+#include "ofw_bus_if.h"
+#endif
+
 #undef NEXUS_DEBUG
 #ifdef NEXUS_DEBUG
 #define dprintf printf
@@ -107,6 +118,19 @@ static int	nexus_setup_intr(device_t dev
 		    driver_intr_t *intr, void *arg, void **cookiep);
 static int	nexus_teardown_intr(device_t, device_t, struct resource *,
 		    void *);
+#ifdef MIPS_INTRNG
+#ifdef SMP
+static int	nexus_bind_intr(device_t, device_t, struct resource *, int);
+#endif
+#ifdef FDT
+static int	nexus_ofw_map_intr(device_t dev, device_t child,
+		    phandle_t iparent, int icells, pcell_t *intr);
+#endif
+static int	nexus_describe_intr(device_t dev, device_t child,
+		    struct resource *irq, void *cookie, const char *descr);
+static int	nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
+		    enum intr_polarity pol);
+#endif
 
 static device_method_t nexus_methods[] = {
 	/* Device interface */
@@ -127,6 +151,16 @@ static device_method_t nexus_methods[] =
 	DEVMETHOD(bus_activate_resource,nexus_activate_resource),
 	DEVMETHOD(bus_deactivate_resource,	nexus_deactivate_resource),
 	DEVMETHOD(bus_hinted_child,	nexus_hinted_child),
+#ifdef MIPS_INTRNG
+	DEVMETHOD(bus_config_intr,	nexus_config_intr),
+	DEVMETHOD(bus_describe_intr,	nexus_describe_intr),
+#ifdef SMP
+	DEVMETHOD(bus_bind_intr,	nexus_bind_intr),
+#endif
+#ifdef FDT
+	DEVMETHOD(ofw_bus_map_intr,	nexus_ofw_map_intr),
+#endif
+#endif
 
 	{ 0, 0 }
 };
@@ -416,9 +450,16 @@ static int
 nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
     driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep)
 {
-	register_t s;
 	int irq;
 
+#ifdef MIPS_INTRNG
+	for (irq = rman_get_start(res); irq <= rman_get_end(res); irq++) {
+		intr_irq_add_handler(child, filt, intr, arg, irq, flags,
+		    cookiep);
+	}
+#else
+	register_t s;
+
 	s = intr_disable();
 	irq = rman_get_start(res);
 	if (irq >= NUM_MIPS_IRQS) {
@@ -429,6 +470,7 @@ nexus_setup_intr(device_t dev, device_t 
 	cpu_establish_hardintr(device_get_nameunit(child), filt, intr, arg,
 	    irq, flags, cookiep);
 	intr_restore(s);
+#endif
 	return (0);
 }
 
@@ -436,9 +478,50 @@ static int
 nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
 {
 
+#ifdef MIPS_INTRNG
+	return (intr_irq_remove_handler(child, rman_get_start(r), ih));
+#else
 	printf("Unimplemented %s at %s:%d\n", __func__, __FILE__, __LINE__);
 	return (0);
+#endif
+}
+
+#ifdef MIPS_INTRNG
+static int
+nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
+    enum intr_polarity pol)
+{
+
+	return (intr_irq_config(irq, trig, pol));
+}
+
+static int
+nexus_describe_intr(device_t dev, device_t child, struct resource *irq,
+    void *cookie, const char *descr)
+{
+
+	return (intr_irq_describe(rman_get_start(irq), cookie, descr));
+}
+
+#ifdef SMP
+static int
+nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu)
+{
+
+	return (intr_irq_bind(rman_get_start(irq), cpu));
+}
+#endif
+
+#ifdef FDT
+static int
+nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells,
+    pcell_t *intr)
+{
+
+	return (intr_fdt_map_irq(iparent, intr, icells));
 }
+#endif
+#endif /* MIPS_INTRNG */
 
 static void
 nexus_hinted_child(device_t bus, const char *dname, int dunit)


More information about the svn-src-head mailing list