Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 3 Mar 2012 01:24:19 +0000 (UTC)
From:      Olivier Houchard <cognet@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r232424 - in projects/armv6/sys/arm: include ti
Message-ID:  <201203030124.q231OJXw056432@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: cognet
Date: Sat Mar  3 01:24:19 2012
New Revision: 232424
URL: http://svn.freebsd.org/changeset/base/232424

Log:
  Add SMP bits to gic.

Modified:
  projects/armv6/sys/arm/include/intr.h
  projects/armv6/sys/arm/ti/gic.c

Modified: projects/armv6/sys/arm/include/intr.h
==============================================================================
--- projects/armv6/sys/arm/include/intr.h	Sat Mar  3 01:22:46 2012	(r232423)
+++ projects/armv6/sys/arm/include/intr.h	Sat Mar  3 01:24:19 2012	(r232424)
@@ -65,4 +65,7 @@ void arm_setup_irqhandler(const char *, 
     void *, int, int, void **);    
 int arm_remove_irqhandler(int, void *);
 extern void (*arm_post_filter)(void *);
+
+void gic_init_secondary(void);
+
 #endif	/* _MACHINE_INTR_H */

Modified: projects/armv6/sys/arm/ti/gic.c
==============================================================================
--- projects/armv6/sys/arm/ti/gic.c	Sat Mar  3 01:22:46 2012	(r232423)
+++ projects/armv6/sys/arm/ti/gic.c	Sat Mar  3 01:24:19 2012	(r232424)
@@ -41,8 +41,14 @@ __FBSDID("$FreeBSD$");
 #include <sys/ktr.h>
 #include <sys/module.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 <machine/bus.h>
 #include <machine/intr.h>
+#include <machine/smp.h>
 
 #include <dev/fdt/fdt_common.h>
 #include <dev/ofw/openfirm.h>
@@ -103,6 +109,8 @@ static struct arm_gic_softc *arm_gic_sc 
 #define	gic_d_write_4(reg, val)		\
     bus_space_write_4(arm_gic_sc->gic_d_bst, arm_gic_sc->gic_d_bsh, reg, val)
 
+static void gic_post_filter(void *);
+
 static int
 arm_gic_probe(device_t dev)
 {
@@ -112,6 +120,27 @@ arm_gic_probe(device_t dev)
 	return (BUS_PROBE_DEFAULT);
 }
 
+void
+gic_init_secondary(void)
+{
+	int nirqs;
+	
+  	/* Get the number of interrupts */
+	nirqs = gic_d_read_4(GICD_TYPER);
+	nirqs = 32 * ((nirqs & 0x1f) + 1);
+			
+	for (int i = 0; i < nirqs; i += 4)
+		gic_d_write_4(GICD_IPRIORITYR(i >> 2), 0);
+	/* Enable CPU interface */
+	gic_c_write_4(GICC_CTLR, 1);
+
+	/* Enable interrupt distribution */
+	gic_d_write_4(GICD_CTLR, 0x01);
+		
+	/* Activate IRQ 29, ie private timer IRQ*/
+	gic_d_write_4(GICD_ISENABLER(29 >> 5), (1UL << (29 & 0x1F)));
+}
+
 static int
 arm_gic_attach(device_t dev)
 {
@@ -128,6 +157,8 @@ arm_gic_attach(device_t dev)
 		return (ENXIO);
 	}
 
+	arm_post_filter = gic_post_filter;
+
 	/* Distributor Interface */
 	sc->gic_d_bst = rman_get_bustag(sc->gic_res[0]);
 	sc->gic_d_bsh = rman_get_bushandle(sc->gic_res[0]);
@@ -160,10 +191,9 @@ arm_gic_attach(device_t dev)
 		gic_d_write_4(GICD_ICENABLER(i >> 5), 0xFFFFFFFF);
 	}
 
-	/* Route all interrupts to CPU0 and set priority to 0 */
-	for (i = 32; i < nirqs; i += 4) {
-		gic_d_write_4(GICD_IPRIORITYR(i >> 2), 0x00000000);
-		gic_d_write_4(GICD_ITARGETSR(i >> 2), 0x01010101);
+	for (i = 0; i < nirqs; i += 4) {
+		gic_d_write_4(GICD_IPRIORITYR(i >> 2),  0);
+		gic_d_write_4(GICD_ITARGETSR(i >> 2), 0xffffffff);
 	}
 
 	/* Enable CPU interface */
@@ -172,7 +202,6 @@ arm_gic_attach(device_t dev)
 	/* Enable interrupt distribution */
 	gic_d_write_4(GICD_CTLR, 0x01);
 
-
 	return (0);
 }
 
@@ -192,17 +221,29 @@ static devclass_t arm_gic_devclass;
 
 DRIVER_MODULE(gic, simplebus, arm_gic_driver, arm_gic_devclass, 0, 0);
 
+static void
+gic_post_filter(void *arg)
+{
+	uintptr_t irq = (uintptr_t) arg;
+
+	gic_c_write_4(GICC_EOIR, irq);
+}
+
 int
 arm_get_next_irq(int last_irq)
 {
 	uint32_t active_irq;
 
-	/* clean-up the last IRQ */
-	if (last_irq != -1) {
-		gic_c_write_4(GICC_EOIR, last_irq);
-	}
-
 	active_irq = gic_c_read_4(GICC_IAR);
+
+	/* 
+	 * Immediatly EOIR the SGIs, because doing so requires the other
+	 * bits (ie CPU number), not just the IRQ number, and we do not
+	 * have this information later.
+	 */
+	   
+	if ((active_irq & 0x3ff) < 16)
+		gic_c_write_4(GICC_EOIR, active_irq);
 	active_irq &= 0x3FF;
 
 	if (active_irq == 0x3FF) {
@@ -210,6 +251,7 @@ arm_get_next_irq(int last_irq)
 			printf("Spurious interrupt detected [0x%08x]\n", active_irq);
 		return -1;
 	}
+	        gic_c_write_4(GICC_EOIR, active_irq);
 
 	return active_irq;
 }
@@ -223,5 +265,43 @@ arm_mask_irq(uintptr_t nb)
 void
 arm_unmask_irq(uintptr_t nb)
 {
+	
+	gic_c_write_4(GICC_EOIR, nb);
 	gic_d_write_4(GICD_ISENABLER(nb >> 5), (1UL << (nb & 0x1F)));
 }
+
+#ifdef SMP
+void
+pic_ipi_send(cpuset_t cpus, u_int ipi)
+{
+	uint32_t val = 0, i;
+
+	for (i = 0; i < MAXCPU; i++)
+		if (CPU_ISSET(i, &cpus))
+			val |= 1 << (16 + i);
+	gic_d_write_4(GICD_SGIR(0), val | ipi);
+	
+}
+
+int
+pic_ipi_get(int i)
+{
+	
+	if (i != -1) {
+		/*
+		 * The intr code will automagically give the frame pointer
+		 * if the interrupt argument is 0.
+		 */
+		if ((unsigned int)i > 16) 
+			return (0);
+		return (i);
+	}
+	return (0x3ff);
+}
+
+void
+pic_ipi_clear(int ipi)
+{
+}
+#endif
+



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203030124.q231OJXw056432>