The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arm/freescale/imx/tzic.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2012, 2013 The FreeBSD Foundation
    5  * All rights reserved.
    6  *
    7  * This software was developed by Oleksandr Rybalko under sponsorship
    8  * from the FreeBSD Foundation.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1.   Redistributions of source code must retain the above copyright
   14  *      notice, this list of conditions and the following disclaimer.
   15  * 2.   Redistributions in binary form must reproduce the above copyright
   16  *      notice, this list of conditions and the following disclaimer in the
   17  *      documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/bus.h>
   38 #include <sys/kernel.h>
   39 #include <sys/module.h>
   40 #include <sys/rman.h>
   41 #include <sys/proc.h>
   42 #include <sys/lock.h>
   43 #include <sys/mutex.h>
   44 
   45 #include <machine/bus.h>
   46 #include <machine/intr.h>
   47 
   48 #include <dev/ofw/openfirm.h>
   49 #include <dev/ofw/ofw_bus.h>
   50 #include <dev/ofw/ofw_bus_subr.h>
   51 
   52 #include <arm/freescale/imx/imx51_tzicreg.h>
   53 
   54 #include "pic_if.h"
   55 
   56 #define TZIC_NIRQS      128
   57 
   58 struct tzic_irqsrc {
   59         struct intr_irqsrc      isrc;
   60         u_int                   irq;
   61 };
   62 
   63 struct tzic_softc {
   64         device_t           dev;
   65         struct resource    *tzicregs;
   66         struct tzic_irqsrc isrcs[TZIC_NIRQS];
   67 };
   68 
   69 static struct tzic_softc *tzic_sc;
   70 
   71 static inline uint32_t
   72 tzic_read_4(struct tzic_softc *sc, int reg)
   73 {
   74 
   75         return (bus_read_4(sc->tzicregs, reg));
   76 }
   77 
   78 static inline void
   79 tzic_write_4(struct tzic_softc *sc, int reg, uint32_t val)
   80 {
   81 
   82     bus_write_4(sc->tzicregs, reg, val);
   83 }
   84 
   85 static inline void
   86 tzic_irq_eoi(struct tzic_softc *sc)
   87 {
   88 
   89         tzic_write_4(sc, TZIC_PRIOMASK, 0xff);
   90 }
   91 
   92 static inline void
   93 tzic_irq_mask(struct tzic_softc *sc, u_int irq)
   94 {
   95 
   96         tzic_write_4(sc, TZIC_ENCLEAR(irq >> 5), (1u << (irq & 0x1f)));
   97 }
   98 
   99 static inline void
  100 tzic_irq_unmask(struct tzic_softc *sc, u_int irq)
  101 {
  102 
  103         tzic_write_4(sc, TZIC_ENSET(irq >> 5), (1u << (irq & 0x1f)));
  104 }
  105 
  106 static int
  107 tzic_intr(void *arg)
  108 {
  109         struct tzic_softc *sc = arg;
  110         int b, i, irq;
  111         uint32_t pending;
  112 
  113         /* Get active interrupt */
  114         for (i = 0; i < TZIC_NIRQS / 32; ++i) {
  115                 pending = tzic_read_4(sc, TZIC_PND(i));
  116                 if ((b = 31 - __builtin_clz(pending)) < 0)
  117                         continue;
  118                 irq = i * 32 + b;
  119                 tzic_write_4(sc, TZIC_PRIOMASK, 0);
  120                 if (intr_isrc_dispatch(&sc->isrcs[irq].isrc,
  121                     curthread->td_intr_frame) != 0) {
  122                         tzic_irq_mask(sc, irq);
  123                         tzic_irq_eoi(sc);
  124                         arm_irq_memory_barrier(irq);
  125                         if (bootverbose) {
  126                                 device_printf(sc->dev, 
  127                                     "Stray irq %u disabled\n", irq);
  128                         }
  129                 }
  130                 return (FILTER_HANDLED);
  131         }
  132 
  133         if (bootverbose)
  134                 device_printf(sc->dev, "Spurious interrupt detected\n");
  135 
  136         return (FILTER_HANDLED);
  137 }
  138 
  139 static void
  140 tzic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
  141 {
  142         u_int irq = ((struct tzic_irqsrc *)isrc)->irq;
  143         struct tzic_softc *sc = device_get_softc(dev);
  144 
  145         arm_irq_memory_barrier(irq);
  146         tzic_irq_unmask(sc, irq);
  147 }
  148 
  149 static void
  150 tzic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
  151 {
  152         u_int irq = ((struct tzic_irqsrc *)isrc)->irq;
  153         struct tzic_softc *sc = device_get_softc(dev);
  154 
  155         tzic_irq_mask(sc, irq);
  156 }
  157 
  158 static int
  159 tzic_map_intr(device_t dev, struct intr_map_data *data,
  160     struct intr_irqsrc **isrcp)
  161 {
  162         struct intr_map_data_fdt *daf;
  163         struct tzic_softc *sc;
  164 
  165         if (data->type != INTR_MAP_DATA_FDT)
  166                 return (ENOTSUP);
  167 
  168         daf = (struct intr_map_data_fdt *)data;
  169         if (daf->ncells != 1 || daf->cells[0] >= TZIC_NIRQS)
  170                 return (EINVAL);
  171 
  172         sc = device_get_softc(dev);
  173         *isrcp = &sc->isrcs[daf->cells[0]].isrc;
  174 
  175         return (0);
  176 }
  177 
  178 static void
  179 tzic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
  180 {
  181         struct tzic_softc *sc = device_get_softc(dev);
  182 
  183         tzic_irq_mask(sc, ((struct tzic_irqsrc *)isrc)->irq);
  184         tzic_irq_eoi(sc);
  185 }
  186 
  187 static void
  188 tzic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
  189 {
  190 
  191         tzic_enable_intr(dev, isrc);
  192 }
  193 
  194 static void
  195 tzic_post_filter(device_t dev, struct intr_irqsrc *isrc)
  196 {
  197 
  198         tzic_irq_eoi(device_get_softc(dev));
  199 }
  200 
  201 static int
  202 tzic_pic_attach(struct tzic_softc *sc)
  203 {
  204         struct intr_pic *pic;
  205         const char *name;
  206         intptr_t xref;
  207         int error;
  208         u_int irq;
  209 
  210         name = device_get_nameunit(sc->dev);
  211         for (irq = 0; irq < TZIC_NIRQS; irq++) {
  212                 sc->isrcs[irq].irq = irq;
  213                 error = intr_isrc_register(&sc->isrcs[irq].isrc,
  214                     sc->dev, 0, "%s,%u", name, irq);
  215                 if (error != 0)
  216                         return (error);
  217         }
  218 
  219         xref = OF_xref_from_node(ofw_bus_get_node(sc->dev));
  220         pic = intr_pic_register(sc->dev, xref);
  221         if (pic == NULL)
  222                 return (ENXIO);
  223 
  224         return (intr_pic_claim_root(sc->dev, xref, tzic_intr, sc, 0));
  225 }
  226 
  227 static int
  228 tzic_probe(device_t dev)
  229 {
  230 
  231         if (!ofw_bus_status_okay(dev))
  232                 return (ENXIO);
  233 
  234         if (ofw_bus_is_compatible(dev, "fsl,tzic")) {
  235                 device_set_desc(dev, "TrustZone Interrupt Controller");
  236                 return (BUS_PROBE_DEFAULT);
  237         }
  238         return (ENXIO);
  239 }
  240 
  241 static int
  242 tzic_attach(device_t dev)
  243 {
  244         struct tzic_softc *sc = device_get_softc(dev);
  245         int i;
  246 
  247         if (tzic_sc)
  248                 return (ENXIO);
  249         tzic_sc = sc;
  250         sc->dev = dev;
  251 
  252         i = 0;
  253         sc->tzicregs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i,
  254             RF_ACTIVE);
  255         if (sc->tzicregs == NULL) {
  256                 device_printf(dev, "could not allocate resources\n");
  257                 return (ENXIO);
  258         }
  259 
  260         /* route all interrupts to IRQ.  secure interrupts are for FIQ */
  261         for (i = 0; i < 4; i++)
  262                 tzic_write_4(sc, TZIC_INTSEC(i), 0xffffffff);
  263 
  264         /* disable all interrupts */
  265         for (i = 0; i < 4; i++)
  266                 tzic_write_4(sc, TZIC_ENCLEAR(i), 0xffffffff);
  267 
  268         /* Set all interrupts to priority 0 (max). */
  269         for (i = 0; i < 128 / 4; ++i)
  270                 tzic_write_4(sc, TZIC_PRIORITY(i), 0);
  271 
  272         /*
  273          * Set priority mask to lowest (unmasked) prio, set synchronizer to
  274          * low-latency mode (as opposed to low-power), enable the controller.
  275          */
  276         tzic_write_4(sc, TZIC_PRIOMASK, 0xff);
  277         tzic_write_4(sc, TZIC_SYNCCTRL, 0);
  278         tzic_write_4(sc, TZIC_INTCNTL, INTCNTL_NSEN_MASK|INTCNTL_NSEN|INTCNTL_EN);
  279 
  280         /* Register as a root pic. */
  281         if (tzic_pic_attach(sc) != 0) {
  282                 device_printf(dev, "could not attach PIC\n");
  283                 return (ENXIO);
  284         }
  285 
  286         return (0);
  287 }
  288 
  289 static device_method_t tzic_methods[] = {
  290         DEVMETHOD(device_probe,         tzic_probe),
  291         DEVMETHOD(device_attach,        tzic_attach),
  292 
  293         DEVMETHOD(pic_disable_intr,     tzic_disable_intr),
  294         DEVMETHOD(pic_enable_intr,      tzic_enable_intr),
  295         DEVMETHOD(pic_map_intr,         tzic_map_intr),
  296         DEVMETHOD(pic_post_filter,      tzic_post_filter),
  297         DEVMETHOD(pic_post_ithread,     tzic_post_ithread),
  298         DEVMETHOD(pic_pre_ithread,      tzic_pre_ithread),
  299 
  300         DEVMETHOD_END
  301 };
  302 
  303 static driver_t tzic_driver = {
  304         "tzic",
  305         tzic_methods,
  306         sizeof(struct tzic_softc),
  307 };
  308 
  309 static devclass_t tzic_devclass;
  310 
  311 EARLY_DRIVER_MODULE(tzic, ofwbus, tzic_driver, tzic_devclass, 0, 0,
  312     BUS_PASS_INTERRUPT);

Cache object: a77fe389efb53286d191ae0a9c9e0dd9


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.