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/xscale/i8134x/i81342.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) 2006 Olivier Houchard
    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 THE AUTHOR ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   16  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR
   18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   24  * POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/10.1/sys/arm/xscale/i8134x/i81342.c 238545 2012-07-17 03:18:12Z gonzo $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/bus.h>
   33 #include <sys/kernel.h>
   34 #include <sys/module.h>
   35 
   36 #define _ARM32_BUS_DMA_PRIVATE
   37 #include <machine/bus.h>
   38 #include <machine/intr.h>
   39 
   40 #include <arm/xscale/i8134x/i81342reg.h>
   41 #include <arm/xscale/i8134x/i81342var.h>
   42 
   43 #define WDTCR_ENABLE1           0x1e1e1e1e
   44 #define WDTCR_ENABLE2           0xe1e1e1e1
   45 
   46 static volatile int intr_enabled0;
   47 static volatile int intr_enabled1;
   48 static volatile int intr_enabled2;
   49 static volatile int intr_enabled3;
   50 
   51 struct bus_space i81342_bs_tag;
   52 
   53 /* Read the interrupt pending register */
   54 
   55 static __inline
   56 uint32_t intpnd0_read(void)
   57 {
   58         uint32_t ret;
   59 
   60         __asm __volatile("mrc p6, 0, %0, c0, c3, 0"
   61             : "=r" (ret));
   62         return (ret);
   63 }
   64 
   65 static __inline
   66 uint32_t intpnd1_read(void)
   67 {
   68         uint32_t ret;
   69 
   70         __asm __volatile("mrc p6, 0, %0, c1, c3, 0"
   71             : "=r" (ret));
   72         return (ret);
   73 }
   74 
   75 static __inline
   76 uint32_t intpnd2_read(void)
   77 {
   78         uint32_t ret;
   79 
   80         __asm __volatile("mrc p6, 0, %0, c2, c3, 0"
   81             : "=r" (ret));
   82         return (ret);
   83 }
   84 
   85 static __inline
   86 uint32_t intpnd3_read(void)
   87 {
   88         uint32_t ret;
   89 
   90         __asm __volatile("mrc p6, 0, %0, c3, c3, 0"
   91             : "=r" (ret));
   92         return (ret);
   93 }
   94 
   95 /* Read the interrupt control register */
   96 /* 0 masked, 1 unmasked */
   97 static __inline
   98 uint32_t intctl0_read(void)
   99 {
  100         uint32_t ret;
  101 
  102         __asm __volatile("mrc p6, 0, %0, c0, c4, 0"
  103             : "=r" (ret));
  104         return (ret);
  105 }
  106 
  107 static __inline
  108 uint32_t intctl1_read(void)
  109 {
  110         uint32_t ret;
  111 
  112         __asm __volatile("mrc p6, 0, %0, c1, c4, 0"
  113             : "=r" (ret));
  114         return (ret);
  115 }
  116 
  117 static __inline
  118 uint32_t intctl2_read(void)
  119 {
  120         uint32_t ret;
  121 
  122         __asm __volatile("mrc p6, 0, %0, c2, c4, 0"
  123             : "=r" (ret));
  124         return (ret);
  125 }
  126 
  127 static __inline
  128 uint32_t intctl3_read(void)
  129 {
  130         uint32_t ret;
  131 
  132         __asm __volatile("mrc p6, 0, %0, c3, c4, 0"
  133             : "=r" (ret));
  134         return (ret);
  135 }
  136 
  137 /* Write the interrupt control register */
  138 
  139 static __inline
  140 void intctl0_write(uint32_t val)
  141 {
  142 
  143         __asm __volatile("mcr p6, 0, %0, c0, c4, 0"
  144             : : "r" (val));
  145 }
  146 
  147 static __inline
  148 void intctl1_write(uint32_t val)
  149 {
  150 
  151         __asm __volatile("mcr p6, 0, %0, c1, c4, 0"
  152             : : "r" (val));
  153 }
  154 
  155 static __inline
  156 void intctl2_write(uint32_t val)
  157 {
  158 
  159         __asm __volatile("mcr p6, 0, %0, c2, c4, 0"
  160             : : "r" (val));
  161 }
  162 
  163 static __inline
  164 void intctl3_write(uint32_t val)
  165 {
  166 
  167         __asm __volatile("mcr p6, 0, %0, c3, c4, 0"
  168             : : "r" (val));
  169 }
  170 
  171 /* Read the interrupt steering register */
  172 /* 0 IRQ 1 FIQ */
  173 static __inline
  174 uint32_t intstr0_read(void)
  175 {
  176         uint32_t ret;
  177 
  178         __asm __volatile("mrc p6, 0, %0, c0, c5, 0"
  179             : "=r" (ret));
  180         return (ret);
  181 }
  182 
  183 static __inline
  184 uint32_t intstr1_read(void)
  185 {
  186         uint32_t ret;
  187 
  188         __asm __volatile("mrc p6, 0, %0, c1, c5, 0"
  189             : "=r" (ret));
  190         return (ret);
  191 }
  192 
  193 static __inline
  194 uint32_t intstr2_read(void)
  195 {
  196         uint32_t ret;
  197 
  198         __asm __volatile("mrc p6, 0, %0, c2, c5, 0"
  199             : "=r" (ret));
  200         return (ret);
  201 }
  202 
  203 static __inline
  204 uint32_t intstr3_read(void)
  205 {
  206         uint32_t ret;
  207 
  208         __asm __volatile("mrc p6, 0, %0, c3, c5, 0"
  209             : "=r" (ret));
  210         return (ret);
  211 }
  212 
  213 /* Write the interrupt steering register */
  214 
  215 static __inline
  216 void intstr0_write(uint32_t val)
  217 {
  218 
  219         __asm __volatile("mcr p6, 0, %0, c0, c5, 0"
  220             : : "r" (val));
  221 }
  222 
  223 static __inline
  224 void intstr1_write(uint32_t val)
  225 {
  226 
  227         __asm __volatile("mcr p6, 0, %0, c1, c5, 0"
  228             : : "r" (val));
  229 }
  230 
  231 static __inline
  232 void intstr2_write(uint32_t val)
  233 {
  234 
  235         __asm __volatile("mcr p6, 0, %0, c2, c5, 0"
  236             : : "r" (val));
  237 }
  238 
  239 static __inline
  240 void intstr3_write(uint32_t val)
  241 {
  242 
  243         __asm __volatile("mcr p6, 0, %0, c3, c5, 0"
  244             : : "r" (val));
  245 }
  246 
  247 void
  248 cpu_reset(void)
  249 {
  250 
  251         disable_interrupts(I32_bit);
  252         /* XXX: Use the watchdog to reset for now */
  253         __asm __volatile("mcr p6, 0, %0, c8, c9, 0\n"
  254                          "mcr p6, 0, %1, c7, c9, 0\n"
  255                          "mcr p6, 0, %2, c7, c9, 0\n"
  256             : : "r" (1), "r" (WDTCR_ENABLE1), "r" (WDTCR_ENABLE2));
  257         while (1);
  258 }
  259 
  260 void
  261 arm_mask_irq(uintptr_t nb)
  262 {
  263 
  264         if (nb < 32) {
  265                 intr_enabled0 &= ~(1 << nb);
  266                 intctl0_write(intr_enabled0);
  267         } else if (nb < 64) {
  268                 intr_enabled1 &= ~(1 << (nb - 32));
  269                 intctl1_write(intr_enabled1);
  270         } else if (nb < 96) {
  271                 intr_enabled2 &= ~(1 << (nb - 64));
  272                 intctl2_write(intr_enabled2);
  273         } else {
  274                 intr_enabled3 &= ~(1 << (nb - 96));
  275                 intctl3_write(intr_enabled3);
  276         }
  277 }
  278 
  279 void
  280 arm_unmask_irq(uintptr_t nb)
  281 {
  282         if (nb < 32) {
  283                 intr_enabled0 |= (1 << nb);
  284                 intctl0_write(intr_enabled0);
  285         } else if (nb < 64) {
  286                 intr_enabled1 |= (1 << (nb - 32));
  287                 intctl1_write(intr_enabled1);
  288         } else if (nb < 96) {
  289                 intr_enabled2 |= (1 << (nb - 64));
  290                 intctl2_write(intr_enabled2);
  291         } else {
  292                 intr_enabled3 |= (1 << (nb - 96));
  293                 intctl3_write(intr_enabled3);
  294         }
  295 }
  296 
  297 int
  298 arm_get_next_irq(int last __unused)
  299 {
  300         uint32_t val;
  301         val = intpnd0_read() & intr_enabled0;
  302         if (val)
  303                 return (ffs(val) - 1);
  304         val = intpnd1_read() & intr_enabled1;
  305         if (val)
  306                 return (32 + ffs(val) - 1);
  307         val = intpnd2_read() & intr_enabled2;
  308         if (val)
  309                 return (64 + ffs(val) - 1);
  310         val = intpnd3_read() & intr_enabled3;
  311         if (val)
  312                 return (96 + ffs(val) - 1);
  313         return (-1);
  314 }
  315 
  316 int
  317 bus_dma_get_range_nb(void)
  318 {
  319         return (0);
  320 }
  321 
  322 struct arm32_dma_range *
  323 bus_dma_get_range(void)
  324 {
  325         return (NULL);
  326 }
  327 
  328 static int
  329 i81342_probe(device_t dev)
  330 {
  331         unsigned int freq;
  332 
  333         freq = *(volatile unsigned int *)(IOP34X_VADDR + IOP34X_PFR);
  334 
  335         switch (freq & IOP34X_FREQ_MASK) {
  336         case IOP34X_FREQ_600:
  337                 device_set_desc(dev, "Intel 81342 600MHz");
  338                 break;
  339         case IOP34X_FREQ_667:
  340                 device_set_desc(dev, "Intel 81342 667MHz");
  341                 break;
  342         case IOP34X_FREQ_800:
  343                 device_set_desc(dev, "Intel 81342 800MHz");
  344                 break;
  345         case IOP34X_FREQ_833:
  346                 device_set_desc(dev, "Intel 81342 833MHz");
  347                 break;
  348         case IOP34X_FREQ_1000:
  349                 device_set_desc(dev, "Intel 81342 1000MHz");
  350                 break;
  351         case IOP34X_FREQ_1200:
  352                 device_set_desc(dev, "Intel 81342 1200MHz");
  353                 break;
  354         default:
  355                 device_set_desc(dev, "Intel 81342 unknown frequency");
  356                 break;
  357         }
  358         return (0);
  359 }
  360 
  361 static void
  362 i81342_identify(driver_t *driver, device_t parent)
  363 {
  364         
  365         BUS_ADD_CHILD(parent, 0, "iq", 0);
  366 }
  367 
  368 static int
  369 i81342_attach(device_t dev)
  370 {
  371         struct i81342_softc *sc = device_get_softc(dev);
  372         uint32_t esstrsr;
  373 
  374         i81342_bs_init(&i81342_bs_tag, sc);
  375         sc->sc_st = &i81342_bs_tag;
  376         sc->sc_sh = IOP34X_VADDR;
  377         esstrsr = bus_space_read_4(sc->sc_st, sc->sc_sh, IOP34X_ESSTSR0);
  378         sc->sc_atux_sh = IOP34X_ATUX_ADDR(esstrsr) - IOP34X_HWADDR +
  379             IOP34X_VADDR;
  380         sc->sc_atue_sh = IOP34X_ATUE_ADDR(esstrsr) - IOP34X_HWADDR +
  381             IOP34X_VADDR;
  382         /* Disable all interrupts. */
  383         intctl0_write(0);
  384         intctl1_write(0);
  385         intctl2_write(0);
  386         intctl3_write(0);
  387         /* Defaults to IRQ */
  388         intstr0_write(0);
  389         intstr1_write(0);
  390         intstr2_write(0);
  391         intstr3_write(0);
  392         sc->sc_irq_rman.rm_type = RMAN_ARRAY;
  393         sc->sc_irq_rman.rm_descr = "i81342 IRQs";
  394         if (rman_init(&sc->sc_irq_rman) != 0 ||
  395             rman_manage_region(&sc->sc_irq_rman, 0, 127) != 0)
  396                 panic("i81342_attach: failed to set up IRQ rman");
  397 
  398         device_add_child(dev, "obio", 0);
  399         device_add_child(dev, "itimer", 0);
  400         device_add_child(dev, "iopwdog", 0);
  401         device_add_child(dev, "pcib", 0);
  402         device_add_child(dev, "pcib", 1);
  403         device_add_child(dev, "iqseg", 0);
  404         bus_generic_probe(dev);
  405         bus_generic_attach(dev);
  406         return (0);
  407 }
  408 
  409 static struct resource *
  410 i81342_alloc_resource(device_t dev, device_t child, int type, int *rid,
  411     u_long start, u_long end, u_long count, u_int flags)
  412 {
  413         struct i81342_softc *sc = device_get_softc(dev);
  414         struct resource *rv;
  415 
  416         if (type == SYS_RES_IRQ) {
  417                 rv = rman_reserve_resource(&sc->sc_irq_rman,
  418                     start, end, count, flags, child);
  419                 if (rv != NULL)
  420                         rman_set_rid(rv, *rid);
  421                 return (rv);
  422         }
  423         
  424         return (NULL);
  425 }
  426 
  427 static int
  428 i81342_setup_intr(device_t dev, device_t child, struct resource *ires,
  429     int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
  430     void **cookiep)
  431 {
  432         int error;
  433 
  434         error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
  435             filt, intr, arg, cookiep);
  436         if (error)
  437                 return (error);
  438         return (0);
  439 }
  440 
  441 static int
  442 i81342_teardown_intr(device_t dev, device_t child, struct resource *res,
  443     void *cookie)
  444 {
  445         return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
  446 }
  447 
  448 static device_method_t i81342_methods[] = {
  449         DEVMETHOD(device_probe, i81342_probe),
  450         DEVMETHOD(device_attach, i81342_attach),
  451         DEVMETHOD(device_identify, i81342_identify),
  452         DEVMETHOD(bus_alloc_resource, i81342_alloc_resource),
  453         DEVMETHOD(bus_setup_intr, i81342_setup_intr),
  454         DEVMETHOD(bus_teardown_intr, i81342_teardown_intr),
  455         {0, 0},
  456 };
  457 
  458 static driver_t i81342_driver = {
  459         "iq",
  460         i81342_methods,
  461         sizeof(struct i81342_softc),
  462 };
  463 static devclass_t i81342_devclass;
  464 
  465 DRIVER_MODULE(iq, nexus, i81342_driver, i81342_devclass, 0, 0);

Cache object: 172af80fb2ade55e70df53e9e78fbc24


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