Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 4 Feb 2016 07:14:23 +0000
From:      "Sgalabov_gmail.com (Stanislav Galabov)" <phabric-noreply@FreeBSD.org>
To:        freebsd-mips@freebsd.org
Subject:   [Differential] [Request, 300 lines] D5182: Introduce INTRNG support for MIPS
Message-ID:  <differential-rev-PHID-DREV-muscnzpiloxhx7x5i5tj-req@FreeBSD.org>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
Sgalabov_gmail.com created this revision.
Sgalabov_gmail.com added reviewers: MIPS, adrian, kan.
Sgalabov_gmail.com added a subscriber: freebsd-mips-list.
Sgalabov_gmail.com set the repository for this revision to rS FreeBSD src repository.
Sgalabov_gmail.com added a project: MIPS.
Herald added a subscriber: imp.

REVISION SUMMARY
  This introduces INTRNG support for the MIPS platforms. It is taken from ARM and the work has been done by Alexander Kabaev as part of his CI20 port.
  
  I have tried to extract the INTRNG-related changes only and am also relying on this as part of the Ralink/Mediatek support.
  
  To follow:
  
  1. proper MIPS timer attachment when using INTRNG
  2. suggestion to remove bus_space_fdt on MIPS and have bus_space_generic do the right things when mapping/unmapping bus space.

REPOSITORY
  rS FreeBSD src repository

REVISION DETAIL
  https://reviews.freebsd.org/D5182

AFFECTED FILES
  sys/conf/options.mips
  sys/mips/include/intr.h
  sys/mips/include/smp.h
  sys/mips/mips/exception.S
  sys/mips/mips/nexus.c

EMAIL PREFERENCES
  https://reviews.freebsd.org/settings/panel/emailpreferences/

To: Sgalabov_gmail.com, MIPS, adrian, kan
Cc: imp, freebsd-mips-list

[-- Attachment #2 --]
diff --git a/sys/mips/mips/nexus.c
 b/sys/mips/mips/nexus.c
--- a/sys/mips/mips/nexus.c
+++ b/sys/mips/mips/nexus.c
@@ -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,22 @@
 #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 +117,19 @@
 		    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,7 +150,16 @@
 	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 }
 };
 
@@ -381,6 +413,7 @@
 	void *vaddr;
 	vm_paddr_t paddr;
 	vm_size_t psize;
+	int err;
 
 	/*
 	 * If this is a memory resource, use pmap_mapdev to map it.
@@ -388,10 +421,25 @@
 	if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
 		paddr = rman_get_start(r);
 		psize = rman_get_size(r);
-		vaddr = pmap_mapdev(paddr, psize);
+#ifdef FDT
+		err = bus_space_map(fdtbus_bs_tag, paddr, psize, 0,
+		    (bus_space_handle_t *)&vaddr);
+		if (err != 0) {
+			rman_deactivate_resource(r);
+			return (err);
+		}
+		rman_set_bustag(r, fdtbus_bs_tag);
+#else
+		vaddr = (bus_space_handle_t)pmap_mapdev(paddr,
+		    (vm_size_t)psize);
+		if (vaddr == 0) {
+			rman_deactivate_resource(r);
+			return (ENOMEM);
+		}
+		rman_set_bustag(r, mips_bus_space_generic);
+#endif
 
 		rman_set_virtual(r, vaddr);
-		rman_set_bustag(r, mips_bus_space_generic);
 		rman_set_bushandle(r, (bus_space_handle_t)(uintptr_t)vaddr);
 	}
 
@@ -402,11 +450,20 @@
 nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
 			  struct resource *r)
 {
-	vm_offset_t va;
-	
-	if (type == SYS_RES_MEMORY) {
-		va = (vm_offset_t)rman_get_virtual(r);
-		pmap_unmapdev(va, rman_get_size(r));
+	bus_space_handle_t vaddr;
+	bus_size_t psize;
+
+	vaddr = rman_get_bushandle(r);
+
+	if (type == SYS_RES_MEMORY && vaddr != 0) {
+		psize = (bus_size_t)rman_get_size(r);
+#ifdef FDT
+		bus_space_unmap(fdtbus_bs_tag, vaddr, psize);
+#else
+		pmap_unmapdev((vm_offset_t)vaddr, psize);
+#endif
+		rman_set_virtual(r, NULL);
+		rman_set_bushandle(r, 0);
 	}
 
 	return (rman_deactivate_resource(r));
@@ -416,9 +473,16 @@
 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 +493,7 @@
 	cpu_establish_hardintr(device_get_nameunit(child), filt, intr, arg,
 	    irq, flags, cookiep);
 	intr_restore(s);
+#endif
 	return (0);
 }
 
@@ -436,9 +501,53 @@
 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)
+{
+	int ret = ENODEV;
+
+#ifdef MIPS_INTRNG
+	ret = intr_irq_config(irq, trig, pol);
+#endif
+	return (ret);
+}
+
+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)
@@ -493,4 +602,5 @@
 	}
 }
 
-DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0);
+EARLY_DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0,
+    BUS_PASS_BUS + BUS_PASS_ORDER_EARLY);
diff --git a/sys/mips/mips/exception.S
 b/sys/mips/mips/exception.S
--- a/sys/mips/mips/exception.S
+++ b/sys/mips/mips/exception.S
@@ -640,7 +640,11 @@
  *  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
 
@@ -752,7 +756,11 @@
 /*
  * 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
 
@@ -1184,6 +1192,7 @@
 	PTR_ADDU sp, sp, CALLFRAME_SIZ
 END(MipsFPTrap)
 
+#ifndef MIPS_INTRNG
 /*
  * Interrupt counters for vmstat.
  */
@@ -1210,6 +1219,7 @@
 #else
 	.int  INTRCNT_COUNT * (_MIPS_SZLONG / 8) * 2
 #endif
+#endif /* MIPS_INTRNG */
 
 
 /*
diff --git a/sys/mips/include/smp.h
 b/sys/mips/include/smp.h
--- a/sys/mips/include/smp.h
+++ b/sys/mips/include/smp.h
@@ -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.
  */
diff --git a/sys/mips/include/intr.h b/sys/mips/include/intr.h
new file mode 100644
--- /dev/null
+++ b/sys/mips/include/intr.h
@@ -0,0 +1,149 @@
+/* 	$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 FDT
+#include <dev/ofw/openfirm.h>
+#endif
+
+#ifndef NIRQ
+#define	NIRQ		128	/* XXX - It should be an option and match size used in exception.S */
+#endif
+
+#ifdef notyet
+#define	INTR_SOLO	INTR_MD1
+typedef int intr_irq_filter_t(void *arg, struct trapframe *tf);
+#else
+typedef int intr_irq_filter_t(void *arg);
+#endif
+
+#define INTR_ISRC_NAMELEN	(MAXCOMLEN + 1)
+
+typedef void intr_ipi_filter_t(void *arg);
+
+enum intr_isrc_type {
+	INTR_ISRCT_NAMESPACE,
+	INTR_ISRCT_FDT
+};
+
+#define INTR_ISRCF_REGISTERED	0x01	/* registered in a controller */
+#define INTR_ISRCF_PERCPU	0x02	/* per CPU interrupt */
+#define INTR_ISRCF_BOUND		0x04	/* bound to a CPU */
+
+/* Interrupt source definition. */
+struct intr_irqsrc {
+	device_t		isrc_dev;	/* where isrc is mapped */
+	intptr_t		isrc_xref;	/* device reference key */
+	uintptr_t		isrc_data;	/* device data for isrc */
+	u_int			isrc_irq;	/* unique identificator */
+	enum intr_isrc_type	isrc_type;	/* how is isrc decribed */
+	u_int			isrc_flags;
+	char			isrc_name[INTR_ISRC_NAMELEN];
+	uint16_t		isrc_nspc_type;
+	uint16_t		isrc_nspc_num;
+	enum intr_trigger	isrc_trig;
+	enum intr_polarity	isrc_pol;
+	cpuset_t		isrc_cpu;	/* on which CPUs is enabled */
+	u_int			isrc_index;
+	u_long *		isrc_count;
+	u_int			isrc_handlers;
+	struct intr_event *	isrc_event;
+	intr_irq_filter_t *	isrc_filter;
+	intr_ipi_filter_t *	isrc_ipifilter;
+	void *			isrc_arg;
+#ifdef FDT
+	u_int			isrc_ncells;
+	pcell_t			isrc_cells[];	/* leave it last */
+#endif
+};
+
+void intr_irq_set_name(struct intr_irqsrc *isrc, const char *fmt, ...)
+    __printflike(2, 3);
+
+void intr_irq_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf);
+
+#define INTR_IRQ_NSPC_NONE	0
+#define INTR_IRQ_NSPC_PLAIN	1
+#define INTR_IRQ_NSPC_IRQ	2
+#define INTR_IRQ_NSPC_IPI	3
+#define INTR_IRQ_NSPC_SWI	4
+
+u_int intr_namespace_map_irq(device_t dev, uint16_t type, uint16_t num);
+#ifdef FDT
+u_int intr_fdt_map_irq(phandle_t, pcell_t *, u_int);
+#endif
+
+int intr_pic_register(device_t dev, intptr_t xref);
+int intr_pic_unregister(device_t dev, intptr_t xref);
+int intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
+    void *arg, u_int ipicount);
+
+int intr_irq_add_handler(device_t dev, driver_filter_t, driver_intr_t, void *,
+    u_int, int, void **);
+int intr_irq_remove_handler(device_t dev, u_int, void *);
+int intr_irq_config(u_int, enum intr_trigger, enum intr_polarity);
+int intr_irq_describe(u_int, void *, const char *);
+
+u_int intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask);
+
+#ifdef SMP
+int intr_irq_bind(u_int, int);
+
+void intr_ipi_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf);
+
+#define AISHF_NOALLOC	0x0001
+
+int intr_ipi_set_handler(u_int ipi, const char *name, intr_ipi_filter_t *filter,
+    void *arg, u_int flags);
+
+void intr_pic_init_secondary(void);
+#endif
+
+/* 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	/* _MACHINE_INTR_H */
diff --git a/sys/conf/options.mips
 b/sys/conf/options.mips
--- a/sys/conf/options.mips
+++ b/sys/conf/options.mips
@@ -136,3 +136,7 @@
 # Options that affect the pmap.
 #
 PV_STATS		opt_pmap.h
+#
+# Options to use ARM_INTRNG code
+#
+MIPS_INTRNG		opt_global.h


Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?differential-rev-PHID-DREV-muscnzpiloxhx7x5i5tj-req>