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>