svn commit: r323403 - in stable/11/sys: arm/conf arm/freescale/imx boot/fdt/dts/arm
Ian Lepore
ian at FreeBSD.org
Sun Sep 10 23:41:25 UTC 2017
Author: ian
Date: Sun Sep 10 23:41:23 2017
New Revision: 323403
URL: https://svnweb.freebsd.org/changeset/base/323403
Log:
MFC r315574, r315576, r315577:
Convert the imx5 interrupt controller driver to INTRNG.
Add INTRNG option to EFIKA_MX config, it is an imx5-based platform.
Delete our local imx53-qsb.dts file; the code now runs fine using the
standard vendor-supplied file in sys/gnu/dts/arm.
Deleted:
stable/11/sys/boot/fdt/dts/arm/imx53-qsb.dts
Modified:
stable/11/sys/arm/conf/EFIKA_MX
stable/11/sys/arm/conf/IMX53
stable/11/sys/arm/freescale/imx/tzic.c
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/sys/arm/conf/EFIKA_MX
==============================================================================
--- stable/11/sys/arm/conf/EFIKA_MX Sun Sep 10 23:31:21 2017 (r323402)
+++ stable/11/sys/arm/conf/EFIKA_MX Sun Sep 10 23:41:23 2017 (r323403)
@@ -130,3 +130,5 @@ options SC_DFLT_FONT # compile font in
makeoptions SC_DFLT_FONT=cp437
device ukbd # Allow keyboard like HIDs to control console
device ums
+
+options INTRNG
Modified: stable/11/sys/arm/conf/IMX53
==============================================================================
--- stable/11/sys/arm/conf/IMX53 Sun Sep 10 23:31:21 2017 (r323402)
+++ stable/11/sys/arm/conf/IMX53 Sun Sep 10 23:41:23 2017 (r323403)
@@ -118,3 +118,5 @@ device wlan_amrr # AMRR transmit rate control algori
# Flattened Device Tree
options FDT # Configure using FDT/DTB data
makeoptions MODULES_EXTRA=dtb/imx5
+
+options INTRNG
Modified: stable/11/sys/arm/freescale/imx/tzic.c
==============================================================================
--- stable/11/sys/arm/freescale/imx/tzic.c Sun Sep 10 23:31:21 2017 (r323402)
+++ stable/11/sys/arm/freescale/imx/tzic.c Sun Sep 10 23:41:23 2017 (r323403)
@@ -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>
@@ -52,28 +50,180 @@ __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;
-#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 uint32_t
+tzic_read_4(struct tzic_softc *sc, int reg)
+{
-static void tzic_post_filter(void *);
+ 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)));
+}
+
+static inline void
+tzic_irq_unmask(struct tzic_softc *sc, u_int irq)
+{
+
+ 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)
{
@@ -90,50 +240,63 @@ 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);
}
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 = {
@@ -144,48 +307,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)));
-}
More information about the svn-src-stable
mailing list