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>