Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 19 Mar 2017 18:30:39 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r315574 - in head/sys/arm: conf freescale/imx
Message-ID:  <201703191830.v2JIUd6A065146@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Sun Mar 19 18:30:38 2017
New Revision: 315574
URL: https://svnweb.freebsd.org/changeset/base/315574

Log:
  Convert the imx5 interrupt controller driver to INTRNG.

Modified:
  head/sys/arm/conf/IMX53
  head/sys/arm/freescale/imx/tzic.c

Modified: head/sys/arm/conf/IMX53
==============================================================================
--- head/sys/arm/conf/IMX53	Sun Mar 19 18:28:38 2017	(r315573)
+++ head/sys/arm/conf/IMX53	Sun Mar 19 18:30:38 2017	(r315574)
@@ -118,3 +118,5 @@ device		wlan_amrr		# AMRR transmit rate 
 # Flattened Device Tree
 options 	FDT			# Configure using FDT/DTB data
 makeoptions	MODULES_EXTRA=dtb/imx5
+
+options 	INTRNG

Modified: head/sys/arm/freescale/imx/tzic.c
==============================================================================
--- head/sys/arm/freescale/imx/tzic.c	Sun Mar 19 18:28:38 2017	(r315573)
+++ head/sys/arm/freescale/imx/tzic.c	Sun Mar 19 18:30:38 2017	(r315574)
@@ -34,14 +34,12 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/bus.h>
 #include <sys/kernel.h>
-#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>
 
@@ -51,26 +49,178 @@ __FBSDID("$FreeBSD$");
 
 #include <arm/freescale/imx/imx51_tzicreg.h>
 
-struct tzic_softc {
-	struct resource *	tzic_res[3];
-	bus_space_tag_t		tzic_bst;
-	bus_space_handle_t	tzic_bsh;
-	uint8_t			ver;
+#include "pic_if.h"
+
+#define	TZIC_NIRQS	128
+
+struct tzic_irqsrc {
+	struct intr_irqsrc	isrc;
+	u_int			irq;
 };
 
-static struct resource_spec tzic_spec[] = {
-	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
-	{ -1, 0 }
+struct tzic_softc {
+	device_t	   dev;
+	struct resource    *tzicregs;
+	struct tzic_irqsrc isrcs[TZIC_NIRQS];
 };
 
-static struct tzic_softc *tzic_sc = NULL;
+static struct tzic_softc *tzic_sc;
+
+static inline uint32_t
+tzic_read_4(struct tzic_softc *sc, int reg)
+{
+
+	return (bus_read_4(sc->tzicregs, reg));
+}
+
+static inline void
+tzic_write_4(struct tzic_softc *sc, int reg, uint32_t val)
+{
+
+    bus_write_4(sc->tzicregs, reg, val);
+}
+
+static inline void
+tzic_irq_eoi(struct tzic_softc *sc)
+{
+
+	tzic_write_4(sc, TZIC_PRIOMASK, 0xff);
+}
+
+static inline void
+tzic_irq_mask(struct tzic_softc *sc, u_int irq)
+{
+
+	tzic_write_4(sc, TZIC_ENCLEAR(irq >> 5), (1u << (irq & 0x1f)));
+}
 
-#define	tzic_read_4(reg)		\
-    bus_space_read_4(tzic_sc->tzic_bst, tzic_sc->tzic_bsh, reg)
-#define	tzic_write_4(reg, val)		\
-    bus_space_write_4(tzic_sc->tzic_bst, tzic_sc->tzic_bsh, reg, val)
+static inline void
+tzic_irq_unmask(struct tzic_softc *sc, u_int irq)
+{
 
-static void tzic_post_filter(void *);
+	tzic_write_4(sc, TZIC_ENSET(irq >> 5), (1u << (irq & 0x1f)));
+}
+
+static int
+tzic_intr(void *arg)
+{
+	struct tzic_softc *sc = arg;
+	int b, i, irq;
+	uint32_t pending;
+
+	/* Get active interrupt */
+	for (i = 0; i < TZIC_NIRQS / 32; ++i) {
+		pending = tzic_read_4(sc, TZIC_PND(i));
+		if ((b = 31 - __builtin_clz(pending)) < 0)
+			continue;
+		irq = i * 32 + b;
+		tzic_write_4(sc, TZIC_PRIOMASK, 0);
+		if (intr_isrc_dispatch(&sc->isrcs[irq].isrc,
+		    curthread->td_intr_frame) != 0) {
+			tzic_irq_mask(sc, irq);
+			tzic_irq_eoi(sc);
+			arm_irq_memory_barrier(irq);
+			if (bootverbose) {
+				device_printf(sc->dev, 
+				    "Stray irq %u disabled\n", irq);
+			}
+		}
+		return (FILTER_HANDLED);
+	}
+
+	if (bootverbose)
+		device_printf(sc->dev, "Spurious interrupt detected\n");
+
+	return (FILTER_HANDLED);
+}
+
+static void
+tzic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+	u_int irq = ((struct tzic_irqsrc *)isrc)->irq;
+	struct tzic_softc *sc = device_get_softc(dev);
+
+	arm_irq_memory_barrier(irq);
+	tzic_irq_unmask(sc, irq);
+}
+
+static void
+tzic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+	u_int irq = ((struct tzic_irqsrc *)isrc)->irq;
+	struct tzic_softc *sc = device_get_softc(dev);
+
+	tzic_irq_mask(sc, irq);
+}
+
+static int
+tzic_map_intr(device_t dev, struct intr_map_data *data,
+    struct intr_irqsrc **isrcp)
+{
+	struct intr_map_data_fdt *daf;
+	struct tzic_softc *sc;
+
+	if (data->type != INTR_MAP_DATA_FDT)
+		return (ENOTSUP);
+
+	daf = (struct intr_map_data_fdt *)data;
+	if (daf->ncells != 1 || daf->cells[0] >= TZIC_NIRQS)
+		return (EINVAL);
+
+	sc = device_get_softc(dev);
+	*isrcp = &sc->isrcs[daf->cells[0]].isrc;
+
+	return (0);
+}
+
+static void
+tzic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+	struct tzic_softc *sc = device_get_softc(dev);
+
+	tzic_irq_mask(sc, ((struct tzic_irqsrc *)isrc)->irq);
+	tzic_irq_eoi(sc);
+}
+
+static void
+tzic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+
+	tzic_enable_intr(dev, isrc);
+}
+
+static void
+tzic_post_filter(device_t dev, struct intr_irqsrc *isrc)
+{
+
+	tzic_irq_eoi(device_get_softc(dev));
+}
+
+static int
+tzic_pic_attach(struct tzic_softc *sc)
+{
+	struct intr_pic *pic;
+	const char *name;
+	intptr_t xref;
+	int error;
+	u_int irq;
+
+	name = device_get_nameunit(sc->dev);
+	for (irq = 0; irq < TZIC_NIRQS; irq++) {
+		sc->isrcs[irq].irq = irq;
+		error = intr_isrc_register(&sc->isrcs[irq].isrc,
+		    sc->dev, 0, "%s,%u", name, irq);
+		if (error != 0)
+			return (error);
+	}
+
+	xref = OF_xref_from_node(ofw_bus_get_node(sc->dev));
+	pic = intr_pic_register(sc->dev, xref);
+	if (pic == NULL)
+		return (ENXIO);
+
+	return (intr_pic_claim_root(sc->dev, xref, tzic_intr, sc, 0));
+}
 
 static int
 tzic_probe(device_t dev)
@@ -89,42 +239,47 @@ tzic_probe(device_t dev)
 static int
 tzic_attach(device_t dev)
 {
-	struct		tzic_softc *sc = device_get_softc(dev);
-	int		i;
-	uint32_t	reg;
+	struct tzic_softc *sc = device_get_softc(dev);
+	int i;
 
 	if (tzic_sc)
 		return (ENXIO);
+	tzic_sc = sc;
+	sc->dev = dev;
 
-	if (bus_alloc_resources(dev, tzic_spec, sc->tzic_res)) {
+	i = 0;
+	sc->tzicregs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i,
+	    RF_ACTIVE);
+	if (sc->tzicregs == NULL) {
 		device_printf(dev, "could not allocate resources\n");
 		return (ENXIO);
 	}
 
-	arm_post_filter = tzic_post_filter;
-
-	/* Distributor Interface */
-	sc->tzic_bst = rman_get_bustag(sc->tzic_res[0]);
-	sc->tzic_bsh = rman_get_bushandle(sc->tzic_res[0]);
-
-	tzic_sc = sc;
-
-	reg = tzic_read_4(TZIC_INTCNTL);
-	tzic_write_4(TZIC_INTCNTL, INTCNTL_NSEN_MASK|INTCNTL_NSEN|INTCNTL_EN);
-	reg = tzic_read_4(TZIC_INTCNTL);
-	tzic_write_4(TZIC_PRIOMASK, 0x1f);
-	reg = tzic_read_4(TZIC_PRIOMASK);
-
-	tzic_write_4(TZIC_SYNCCTRL, 0x02);
-	reg = tzic_read_4(TZIC_SYNCCTRL);
-
 	/* route all interrupts to IRQ.  secure interrupts are for FIQ */
 	for (i = 0; i < 4; i++)
-		tzic_write_4(TZIC_INTSEC(i), 0xffffffff);
+		tzic_write_4(sc, TZIC_INTSEC(i), 0xffffffff);
 
 	/* disable all interrupts */
 	for (i = 0; i < 4; i++)
-		tzic_write_4(TZIC_ENCLEAR(i), 0xffffffff);
+		tzic_write_4(sc, TZIC_ENCLEAR(i), 0xffffffff);
+
+	/* Set all interrupts to priority 0 (max). */
+	for (i = 0; i < 128 / 4; ++i)
+		tzic_write_4(sc, TZIC_PRIORITY(i), 0);
+
+	/*
+	 * Set priority mask to lowest (unmasked) prio, set synchronizer to
+	 * low-latency mode (as opposed to low-power), enable the controller.
+	 */
+	tzic_write_4(sc, TZIC_PRIOMASK, 0xff);
+	tzic_write_4(sc, TZIC_SYNCCTRL, 0);
+	tzic_write_4(sc, TZIC_INTCNTL, INTCNTL_NSEN_MASK|INTCNTL_NSEN|INTCNTL_EN);
+
+	/* Register as a root pic. */
+	if (tzic_pic_attach(sc) != 0) {
+		device_printf(dev, "could not attach PIC\n");
+		return (ENXIO);
+	}
 
 	return (0);
 }
@@ -132,7 +287,15 @@ tzic_attach(device_t dev)
 static device_method_t tzic_methods[] = {
 	DEVMETHOD(device_probe,		tzic_probe),
 	DEVMETHOD(device_attach,	tzic_attach),
-	{ 0, 0 }
+
+	DEVMETHOD(pic_disable_intr,	tzic_disable_intr),
+	DEVMETHOD(pic_enable_intr,	tzic_enable_intr),
+	DEVMETHOD(pic_map_intr,		tzic_map_intr),
+	DEVMETHOD(pic_post_filter,	tzic_post_filter),
+	DEVMETHOD(pic_post_ithread,	tzic_post_ithread),
+	DEVMETHOD(pic_pre_ithread,	tzic_pre_ithread),
+
+	DEVMETHOD_END
 };
 
 static driver_t tzic_driver = {
@@ -143,48 +306,5 @@ static driver_t tzic_driver = {
 
 static devclass_t tzic_devclass;
 
-/*
- * Memory space of controller located outside of device range, so let him to
- * attach not only to simplebus, but ofwbus also.
- */
 EARLY_DRIVER_MODULE(tzic, ofwbus, tzic_driver, tzic_devclass, 0, 0,
     BUS_PASS_INTERRUPT);
-EARLY_DRIVER_MODULE(tzic, simplebus, tzic_driver, tzic_devclass, 0, 0,
-    BUS_PASS_INTERRUPT);
-
-static void
-tzic_post_filter(void *arg)
-{
-
-}
-
-int
-arm_get_next_irq(int last_irq)
-{
-	uint32_t pending;
-	int i, b;
-
-	for (i = 0; i < 4; i++) {
-		pending = tzic_read_4(TZIC_PND(i));
-		for (b = 0; pending != 0 && b < 32; b++)
-			if (pending & (1 << b)) {
-				return (i * 32 + b);
-			}
-	}
-
-	return (-1);
-}
-
-void
-arm_mask_irq(uintptr_t nb)
-{
-
-	tzic_write_4(TZIC_ENCLEAR(nb / 32), (1UL <<(nb % 32)));
-}
-
-void
-arm_unmask_irq(uintptr_t nb)
-{
-
-	tzic_write_4(TZIC_ENSET(nb / 32), (1UL <<(nb % 32)));
-}



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