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

Cache object: 39e2102fbca5c8dac3201bcc2d8dc1ad


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