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/powerpc/powerpc/openpic.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  * Copyright (C) 2002 Benno Rice.
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
   15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   17  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   18  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   21  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   24  *
   25  * $FreeBSD: releng/6.4/sys/powerpc/powerpc/openpic.c 172427 2007-10-03 20:41:35Z jhb $
   26  */
   27 
   28 #include <sys/param.h>
   29 #include <sys/systm.h>
   30 #include <sys/bus.h>
   31 #include <sys/conf.h>
   32 #include <sys/kernel.h>
   33 
   34 #include <machine/bus.h>
   35 #include <machine/intr.h>
   36 #include <machine/intr_machdep.h>
   37 #include <machine/md_var.h>
   38 #include <machine/pio.h>
   39 #include <machine/resource.h>
   40 
   41 #include <vm/vm.h>
   42 #include <vm/pmap.h>
   43 
   44 #include <sys/rman.h>
   45 
   46 #include <machine/openpicreg.h>
   47 #include <machine/openpicvar.h>
   48 
   49 #include "pic_if.h"
   50 
   51 /*
   52  * Local routines
   53  */
   54 static u_int            openpic_read(struct openpic_softc *, int);
   55 static void             openpic_write(struct openpic_softc *, int, u_int);
   56 static int              openpic_read_irq(struct openpic_softc *, int);
   57 static void             openpic_eoi(struct openpic_softc *, int);
   58 static void             openpic_enable_irq(struct openpic_softc *, int, int);
   59 static void             openpic_disable_irq(struct openpic_softc *, int);
   60 static void             openpic_set_priority(struct openpic_softc *, int, int);
   61 static void             openpic_intr(void);
   62 static void             openpic_ext_enable_irq(uintptr_t);
   63 static void             openpic_ext_disable_irq(uintptr_t);
   64 
   65 /* XXX This limits us to one openpic */
   66 static struct   openpic_softc *openpic_softc;
   67 
   68 /*
   69  * Called at nexus-probe time to allow interrupts to be enabled by
   70  * devices that are probed before the OpenPIC h/w is probed.
   71  */
   72 int
   73 openpic_early_attach(device_t dev)
   74 {
   75         struct          openpic_softc *sc;
   76 
   77         sc = device_get_softc(dev);
   78         openpic_softc = sc;
   79 
   80         sc->sc_rman.rm_type = RMAN_ARRAY;
   81         sc->sc_rman.rm_descr = device_get_nameunit(dev);
   82 
   83         if (rman_init(&sc->sc_rman) != 0 ||
   84             rman_manage_region(&sc->sc_rman, 0, OPENPIC_IRQMAX-1) != 0) {
   85                 device_printf(dev, "could not set up resource management");
   86                 return (ENXIO);
   87         }       
   88 
   89         intr_init(openpic_intr, OPENPIC_IRQMAX, openpic_ext_enable_irq, 
   90             openpic_ext_disable_irq);
   91 
   92         sc->sc_early_done = 1;
   93 
   94         return (0);
   95 }
   96 
   97 int
   98 openpic_attach(device_t dev)
   99 {
  100         struct openpic_softc *sc;
  101         u_int     irq;
  102         u_int32_t x;
  103 
  104         sc = device_get_softc(dev);
  105         sc->sc_hwprobed = 1;
  106 
  107         if (!sc->sc_early_done)
  108                 openpic_early_attach(dev);
  109 
  110         x = openpic_read(sc, OPENPIC_FEATURE);
  111         switch (x & OPENPIC_FEATURE_VERSION_MASK) {
  112         case 1:
  113                 sc->sc_version = "1.0";
  114                 break;
  115         case 2:
  116                 sc->sc_version = "1.2";
  117                 break;
  118         case 3:
  119                 sc->sc_version = "1.3";
  120                 break;
  121         default:
  122                 sc->sc_version = "unknown";
  123                 break;
  124         }
  125 
  126         sc->sc_ncpu = ((x & OPENPIC_FEATURE_LAST_CPU_MASK) >>
  127             OPENPIC_FEATURE_LAST_CPU_SHIFT) + 1;
  128         sc->sc_nirq = ((x & OPENPIC_FEATURE_LAST_IRQ_MASK) >>
  129             OPENPIC_FEATURE_LAST_IRQ_SHIFT) + 1;
  130 
  131         /*
  132          * PSIM seems to report 1 too many IRQs
  133          */
  134         if (sc->sc_psim)
  135                 sc->sc_nirq--;
  136 
  137         if (bootverbose)
  138                 device_printf(dev,
  139                     "Version %s, supports %d CPUs and %d irqs\n",
  140                     sc->sc_version, sc->sc_ncpu, sc->sc_nirq);
  141 
  142         /* disable all interrupts */
  143         for (irq = 0; irq < sc->sc_nirq; irq++)
  144                 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK);
  145 
  146         openpic_set_priority(sc, 0, 15);
  147 
  148         /* we don't need 8259 passthrough mode */
  149         x = openpic_read(sc, OPENPIC_CONFIG);
  150         x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
  151         openpic_write(sc, OPENPIC_CONFIG, x);
  152 
  153         /* send all interrupts to cpu 0 */
  154         for (irq = 0; irq < sc->sc_nirq; irq++)
  155                 openpic_write(sc, OPENPIC_IDEST(irq), 1 << 0);
  156 
  157         for (irq = 0; irq < sc->sc_nirq; irq++) {
  158                 x = irq;
  159                 x |= OPENPIC_IMASK;
  160                 x |= OPENPIC_POLARITY_POSITIVE;
  161                 x |= OPENPIC_SENSE_LEVEL;
  162                 x |= 8 << OPENPIC_PRIORITY_SHIFT;
  163                 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
  164         }
  165 
  166         /* XXX IPI */
  167         /* XXX set spurious intr vector */
  168 
  169         openpic_set_priority(sc, 0, 0);
  170 
  171         /* clear all pending interrupts */
  172         for (irq = 0; irq < sc->sc_nirq; irq++) {
  173                 openpic_read_irq(sc, 0);
  174                 openpic_eoi(sc, 0);
  175         }
  176 
  177         /* enable pre-h/w reserved irqs, disable all others */
  178         for (irq = 0; irq < sc->sc_nirq; irq++)
  179                 if (sc->sc_irqrsv[irq])
  180                         openpic_enable_irq(sc, irq, IST_LEVEL);
  181                 else
  182                         openpic_disable_irq(sc, irq);
  183 
  184         return (0);
  185 }
  186 
  187 /*
  188  * PIC interface
  189  */
  190 
  191 struct resource *
  192 openpic_allocate_intr(device_t dev, device_t child, int *rid, u_long intr,
  193     u_int flags)
  194 {
  195         struct  openpic_softc *sc;
  196         struct  resource *rv;
  197         int     needactivate;
  198 
  199         sc = device_get_softc(dev);
  200         needactivate = flags & RF_ACTIVE;
  201         flags &= ~RF_ACTIVE;
  202 
  203         if (sc->sc_hwprobed && (intr > sc->sc_nirq)) {
  204                 device_printf(dev, "interrupt reservation %ld out of range\n",
  205                     intr);
  206                 return (NULL);
  207         }
  208 
  209         rv = rman_reserve_resource(&sc->sc_rman, intr, intr, 1, flags, child);
  210         if (rv == NULL) {
  211                 device_printf(dev, "interrupt reservation failed for %s\n",
  212                     device_get_nameunit(child));
  213                 return (NULL);
  214         }
  215         rman_set_rid(rv, *rid);
  216         if (needactivate) {
  217                 if (bus_activate_resource(child, SYS_RES_IRQ, *rid, rv) != 0) {
  218                         device_printf(dev,
  219                             "resource activation failed for %s\n",
  220                             device_get_nameunit(child));
  221                         rman_release_resource(rv);
  222                         return (NULL);
  223                 }
  224         }
  225 
  226         return (rv);
  227 }
  228 
  229 int
  230 openpic_setup_intr(device_t dev, device_t child, struct resource *res,
  231     int flags, driver_intr_t *intr, void *arg, void **cookiep)
  232 {
  233         struct  openpic_softc *sc;
  234         u_long  start;
  235         int     error;
  236 
  237         sc = device_get_softc(dev);
  238         start = rman_get_start(res);
  239 
  240         if (res == NULL) {
  241                 device_printf(dev, "null interrupt resource from %s\n",
  242                     device_get_nameunit(child));
  243                 return (EINVAL);
  244         }
  245 
  246         if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
  247                 flags |= INTR_EXCL;
  248 
  249         /*
  250          * We depend here on rman_activate_resource() being idempotent.
  251          */
  252         error = rman_activate_resource(res);
  253         if (error)
  254                 return (error);
  255 
  256         error = inthand_add(device_get_nameunit(child), start, intr, arg,
  257             flags, cookiep);
  258 
  259         if (sc->sc_hwprobed)
  260                 openpic_enable_irq(sc, start, IST_LEVEL);
  261         else
  262                 sc->sc_irqrsv[start] = 1;
  263 
  264         return (error);
  265 }
  266 
  267 int
  268 openpic_teardown_intr(device_t dev, device_t child, struct resource *res,
  269     void *ih)
  270 {
  271         int     error;
  272 
  273         error = rman_deactivate_resource(res);
  274         if (error)
  275                 return (error);
  276 
  277         error = inthand_remove(rman_get_start(res), ih);
  278 
  279         return (error);
  280 }
  281 
  282 int
  283 openpic_release_intr(device_t dev, device_t child, int rid,
  284     struct resource *res)
  285 {
  286         int     error;
  287 
  288         if (rman_get_flags(res) & RF_ACTIVE) {
  289                 error = bus_deactivate_resource(child, SYS_RES_IRQ, rid, res);
  290                 if (error)
  291                         return (error);
  292         }
  293 
  294         return (rman_release_resource(res));
  295 }
  296 
  297 /*
  298  * Local routines
  299  */
  300 
  301 static u_int
  302 openpic_read(struct openpic_softc *sc, int reg)
  303 {
  304         return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg));
  305 }
  306 
  307 static void
  308 openpic_write(struct openpic_softc *sc, int reg, u_int val)
  309 {
  310         bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val);
  311 }
  312 
  313 static int
  314 openpic_read_irq(struct openpic_softc *sc, int cpu)
  315 {
  316         return openpic_read(sc, OPENPIC_IACK(cpu)) & OPENPIC_VECTOR_MASK;
  317 }
  318 
  319 static void
  320 openpic_eoi(struct openpic_softc *sc, int cpu)
  321 {
  322         openpic_write(sc, OPENPIC_EOI(cpu), 0);
  323 }
  324 
  325 static void
  326 openpic_enable_irq(struct openpic_softc *sc, int irq, int type)
  327 {
  328         u_int   x;
  329 
  330         x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
  331         x &= ~(OPENPIC_IMASK | OPENPIC_SENSE_LEVEL | OPENPIC_SENSE_EDGE);
  332         if (type == IST_LEVEL)
  333                 x |= OPENPIC_SENSE_LEVEL;
  334         else
  335                 x |= OPENPIC_SENSE_EDGE;
  336         openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
  337 }
  338 
  339 static void
  340 openpic_disable_irq(struct openpic_softc *sc, int irq)
  341 {
  342         u_int   x;
  343 
  344         x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
  345         x |= OPENPIC_IMASK;
  346         openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
  347 }
  348 
  349 static void
  350 openpic_set_priority(struct openpic_softc *sc, int cpu, int pri)
  351 {
  352         u_int   x;
  353 
  354         x = openpic_read(sc, OPENPIC_CPU_PRIORITY(cpu));
  355         x &= ~OPENPIC_CPU_PRIORITY_MASK;
  356         x |= pri;
  357         openpic_write(sc, OPENPIC_CPU_PRIORITY(cpu), x);
  358 }
  359 
  360 static void
  361 openpic_intr(void)
  362 {
  363         struct openpic_softc *sc;
  364         int             irq;
  365         u_int32_t       msr;
  366 
  367         sc = openpic_softc;
  368         msr = mfmsr();
  369 
  370         irq = openpic_read_irq(sc, 0);
  371         if (irq == 255) {
  372                 return;
  373         }
  374 
  375 start:
  376         openpic_disable_irq(sc, irq);
  377         /*mtmsr(msr | PSL_EE);*/
  378 
  379         /* do the interrupt thang */
  380         intr_handle(irq);
  381 
  382         mtmsr(msr);
  383 
  384         openpic_eoi(sc, 0);
  385 
  386         irq = openpic_read_irq(sc, 0);
  387         if (irq != 255)
  388                 goto start;
  389 }
  390 
  391 static void
  392 openpic_ext_enable_irq(uintptr_t irq)
  393 {
  394         if (!openpic_softc->sc_hwprobed)
  395                 return;
  396 
  397         openpic_enable_irq(openpic_softc, irq, IST_LEVEL);
  398 }
  399 
  400 static void
  401 openpic_ext_disable_irq(uintptr_t irq)
  402 {
  403         if (!openpic_softc->sc_hwprobed)
  404                 return;
  405 
  406         openpic_disable_irq(openpic_softc, irq);
  407 }

Cache object: 3a353ec6dd8edef50dfeeb041ec1dd40


[ 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.