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/i80321/iq80321.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 /*      $NetBSD: i80321_mainbus.c,v 1.13 2003/12/17 22:03:24 abs Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
    5  * All rights reserved.
    6  *
    7  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. All advertising materials mentioning features or use of this software
   18  *    must display the following acknowledgement:
   19  *      This product includes software developed for the NetBSD Project by
   20  *      Wasabi Systems, Inc.
   21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
   22  *    or promote products derived from this software without specific prior
   23  *    written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
   29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   35  * POSSIBILITY OF SUCH DAMAGE.
   36  */
   37 
   38 /*
   39  * IQ80321 front-end for the i80321 I/O Processor.  We take care
   40  * of setting up the i80321 memory map, PCI interrupt routing, etc.,
   41  * which are all specific to the board the i80321 is wired up to.
   42  */
   43 
   44 #include <sys/cdefs.h>
   45 __FBSDID("$FreeBSD: releng/10.4/sys/arm/xscale/i80321/iq80321.c 278613 2015-02-12 03:50:33Z ian $");
   46 
   47 #define _ARM32_BUS_DMA_PRIVATE
   48 #include <sys/param.h>
   49 #include <sys/systm.h>
   50 #include <sys/bus.h>
   51 #include <sys/kernel.h>
   52 #include <sys/module.h>
   53 #include <sys/malloc.h>
   54 #include <sys/rman.h>
   55 #include <machine/armreg.h>
   56 #include <machine/bus.h>
   57 #include <machine/intr.h>
   58 
   59 #include <arm/xscale/i80321/i80321reg.h>
   60 #include <arm/xscale/i80321/i80321var.h>
   61 #include <arm/xscale/i80321/iq80321reg.h>
   62 #include <arm/xscale/i80321/iq80321var.h>
   63 #include <arm/xscale/i80321/i80321_intr.h>
   64 
   65 #include <dev/pci/pcireg.h>
   66 
   67 
   68 int     iq80321_probe(device_t);
   69 void    iq80321_identify(driver_t *, device_t);
   70 int     iq80321_attach(device_t);
   71 
   72 int
   73 iq80321_probe(device_t dev)
   74 {
   75         device_set_desc(dev, "Intel 80321");
   76         return (BUS_PROBE_NOWILDCARD);
   77 }
   78 
   79 void
   80 iq80321_identify(driver_t *driver, device_t parent)
   81 {
   82         
   83         BUS_ADD_CHILD(parent, 0, "iq", 0);
   84 }
   85 
   86 static struct arm32_dma_range i80321_dr;
   87 static int dma_range_init = 0;
   88 
   89 struct arm32_dma_range *
   90 bus_dma_get_range(void)
   91 {
   92         if (dma_range_init == 0)
   93                 return (NULL);
   94         return (&i80321_dr);
   95 }
   96 
   97 int
   98 bus_dma_get_range_nb(void)
   99 {
  100         if (dma_range_init == 0)
  101                 return (0);
  102         return (1);
  103 }
  104 
  105 #define PCI_MAPREG_MEM_PREFETCHABLE_MASK        0x00000008
  106 #define PCI_MAPREG_MEM_TYPE_64BIT               0x00000004
  107 
  108 int
  109 iq80321_attach(device_t dev)
  110 {
  111         struct i80321_softc *sc = device_get_softc(dev);
  112         int b0u, b0l, b1u, b1l;
  113         vm_paddr_t memstart = 0;
  114         vm_size_t memsize = 0;
  115         int busno;
  116 
  117         /*
  118          * Fill in the space tag for the i80321's own devices,
  119          * and hand-craft the space handle for it (the device
  120          * was mapped during early bootstrap).
  121          */
  122         i80321_bs_init(&i80321_bs_tag, sc);
  123         sc->sc_st = &i80321_bs_tag;
  124         sc->sc_sh = IQ80321_80321_VBASE;
  125         sc->dev = dev;
  126         sc->sc_is_host = 1;
  127 
  128         /*
  129          * Slice off a subregion for the Memory Controller -- we need it
  130          * here in order read the memory size.
  131          */
  132         if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_MCU_BASE,
  133             VERDE_MCU_SIZE, &sc->sc_mcu_sh))
  134                 panic("%s: unable to subregion MCU registers",
  135                     device_get_name(dev));
  136 
  137         if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE,
  138             VERDE_ATU_SIZE, &sc->sc_atu_sh))
  139                 panic("%s: unable to subregion ATU registers",
  140                     device_get_name(dev));
  141 
  142         /*
  143          * We have mapped the PCI I/O windows in the early
  144          * bootstrap phase.
  145          */
  146         sc->sc_iow_vaddr = IQ80321_IOW_VBASE;
  147 
  148         /*
  149          * Check the configuration of the ATU to see if another BIOS
  150          * has configured us.  If a PC BIOS didn't configure us, then:
  151          *      IQ80321: BAR0 00000000.0000000c BAR1 is 00000000.8000000c.
  152          *      IQ31244: BAR0 00000000.00000004 BAR1 is 00000000.0000000c.
  153          * If a BIOS has configured us, at least one of those should be
  154          * different.  This is pretty fragile, but it's not clear what
  155          * would work better.
  156          */
  157         b0l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x0);
  158         b0u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x4);
  159         b1l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x8);
  160         b1u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0xc);
  161 
  162 #ifdef VERBOSE_INIT_ARM 
  163         printf("i80321: BAR0 = %08x.%08x BAR1 = %08x.%08x\n",
  164                    b0l,b0u, b1l, b1u );
  165 #endif
  166 
  167 #define PCI_MAPREG_MEM_ADDR_MASK        0xfffffff0
  168         b0l &= PCI_MAPREG_MEM_ADDR_MASK;
  169         b0u &= PCI_MAPREG_MEM_ADDR_MASK;
  170         b1l &= PCI_MAPREG_MEM_ADDR_MASK;
  171         b1u &= PCI_MAPREG_MEM_ADDR_MASK;
  172 
  173 #ifdef VERBOSE_INIT_ARM 
  174         printf("i80219: BAR0 = %08x.%08x BAR1 = %08x.%08x\n",
  175                    b0l,b0u, b1l, b1u );
  176 #endif
  177 
  178         if ((b0u != b1u) || (b0l != 0) || ((b1l & ~0x80000000U) != 0))
  179                 sc->sc_is_host = 0;
  180         else
  181                 sc->sc_is_host = 1;
  182 
  183         /* FIXME: i force it's */       
  184 
  185 #ifdef CPU_XSCALE_80219
  186         sc->sc_is_host = 1;
  187 #endif
  188         
  189         i80321_sdram_bounds(sc->sc_st, sc->sc_mcu_sh, &memstart, &memsize);
  190         /*
  191          * We set up the Inbound Windows as follows:
  192          *
  193          *      0       Access to i80321 PMMRs
  194          *
  195          *      1       Reserve space for private devices
  196          *
  197          *      2       RAM access
  198          *
  199          *      3       Unused.
  200          *
  201          * This chunk needs to be customized for each IOP321 application.
  202          */
  203 #if 0
  204         sc->sc_iwin[0].iwin_base_lo = VERDE_PMMR_BASE;
  205         sc->sc_iwin[0].iwin_base_hi = 0;
  206         sc->sc_iwin[0].iwin_xlate = VERDE_PMMR_BASE;
  207         sc->sc_iwin[0].iwin_size = VERDE_PMMR_SIZE;
  208 #endif
  209         if (sc->sc_is_host) {
  210                 
  211                 /* Map PCI:Local 1:1. */
  212                 sc->sc_iwin[1].iwin_base_lo = VERDE_OUT_XLATE_MEM_WIN0_BASE |
  213                     PCI_MAPREG_MEM_PREFETCHABLE_MASK |
  214                     PCI_MAPREG_MEM_TYPE_64BIT;
  215                 sc->sc_iwin[1].iwin_base_hi = 0;
  216         } else {
  217                 
  218                 sc->sc_iwin[1].iwin_base_lo = 0;
  219                 sc->sc_iwin[1].iwin_base_hi = 0;
  220         }
  221         sc->sc_iwin[1].iwin_xlate = VERDE_OUT_XLATE_MEM_WIN0_BASE;
  222         sc->sc_iwin[1].iwin_size = VERDE_OUT_XLATE_MEM_WIN_SIZE;
  223         
  224         if (sc->sc_is_host) {
  225                 sc->sc_iwin[2].iwin_base_lo = memstart |
  226                     PCI_MAPREG_MEM_PREFETCHABLE_MASK |
  227                     PCI_MAPREG_MEM_TYPE_64BIT;
  228                 sc->sc_iwin[2].iwin_base_hi = 0;
  229         } else {
  230                 sc->sc_iwin[2].iwin_base_lo = 0;
  231                 sc->sc_iwin[2].iwin_base_hi = 0;
  232         }
  233         sc->sc_iwin[2].iwin_xlate = memstart;
  234         sc->sc_iwin[2].iwin_size = memsize;
  235 
  236         if (sc->sc_is_host) {
  237                 sc->sc_iwin[3].iwin_base_lo = 0 |
  238                     PCI_MAPREG_MEM_PREFETCHABLE_MASK |
  239                     PCI_MAPREG_MEM_TYPE_64BIT;
  240         } else {
  241                 sc->sc_iwin[3].iwin_base_lo = 0;
  242         }
  243         sc->sc_iwin[3].iwin_base_hi = 0;
  244         sc->sc_iwin[3].iwin_xlate = 0;
  245         sc->sc_iwin[3].iwin_size = 0;
  246         
  247 #ifdef  VERBOSE_INIT_ARM
  248         printf("i80321: Reserve space for private devices (Inbound Window 1) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n",
  249                    sc->sc_iwin[1].iwin_base_hi,
  250                    sc->sc_iwin[1].iwin_base_lo,
  251                    sc->sc_iwin[1].iwin_xlate,
  252                    sc->sc_iwin[1].iwin_size
  253                 );
  254         printf("i80321: RAM access (Inbound Window 2) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n",
  255                    sc->sc_iwin[2].iwin_base_hi,
  256                    sc->sc_iwin[2].iwin_base_lo,
  257                    sc->sc_iwin[2].iwin_xlate,
  258                    sc->sc_iwin[2].iwin_size
  259                 );
  260 #endif
  261 
  262         /*
  263          * We set up the Outbound Windows as follows:
  264          *
  265          *      0       Access to private PCI space.
  266          *
  267          *      1       Unused.
  268          */
  269 #define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0)
  270         sc->sc_owin[0].owin_xlate_lo =
  271             PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo);
  272         sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi;
  273         /*
  274          * Set the Secondary Outbound I/O window to map
  275          * to PCI address 0 for all 64K of the I/O space.
  276          */
  277         sc->sc_ioout_xlate = 0;
  278         i80321_attach(sc);
  279         i80321_dr.dr_sysbase = sc->sc_iwin[2].iwin_xlate;
  280         i80321_dr.dr_busbase = PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo);
  281         i80321_dr.dr_len = sc->sc_iwin[2].iwin_size;
  282         dma_range_init = 1;
  283         busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
  284         busno = PCIXSR_BUSNO(busno);
  285         if (busno == 0xff)
  286                 busno = 0;
  287         sc->sc_irq_rman.rm_type = RMAN_ARRAY;
  288         sc->sc_irq_rman.rm_descr = "i80321 IRQs";
  289         if (rman_init(&sc->sc_irq_rman) != 0 ||
  290             rman_manage_region(&sc->sc_irq_rman, 0, 25) != 0)
  291                 panic("i80321_attach: failed to set up IRQ rman");
  292 
  293         device_add_child(dev, "obio", 0);
  294         device_add_child(dev, "itimer", 0);
  295         device_add_child(dev, "iopwdog", 0);
  296 #ifndef         CPU_XSCALE_80219
  297         device_add_child(dev, "iqseg", 0);
  298 #endif  
  299         device_add_child(dev, "pcib", busno);
  300         device_add_child(dev, "i80321_dma", 0);
  301         device_add_child(dev, "i80321_dma", 1);
  302 #ifndef CPU_XSCALE_80219        
  303         device_add_child(dev, "i80321_aau", 0);
  304 #endif
  305         bus_generic_probe(dev);
  306         bus_generic_attach(dev);
  307 
  308         return (0);
  309 }
  310 
  311 void
  312 arm_mask_irq(uintptr_t nb)
  313 {
  314         intr_enabled &= ~(1 << nb);
  315         i80321_set_intrmask();
  316 }
  317 
  318 void
  319 arm_unmask_irq(uintptr_t nb)
  320 {
  321         intr_enabled |= (1 << nb);
  322         i80321_set_intrmask();
  323 }
  324 
  325 
  326 void
  327 cpu_reset()
  328 {
  329         (void) disable_interrupts(PSR_I|PSR_F);
  330         *(__volatile uint32_t *)(IQ80321_80321_VBASE + VERDE_ATU_BASE +
  331             ATU_PCSR) = PCSR_RIB | PCSR_RPB;
  332         printf("Reset failed!\n");
  333         for(;;);
  334 }
  335 
  336 static struct resource *
  337 iq80321_alloc_resource(device_t dev, device_t child, int type, int *rid,
  338     u_long start, u_long end, u_long count, u_int flags)
  339 {
  340         struct i80321_softc *sc = device_get_softc(dev);
  341         struct resource *rv;
  342 
  343         if (type == SYS_RES_IRQ) {
  344                 rv = rman_reserve_resource(&sc->sc_irq_rman,
  345                     start, end, count, flags, child);
  346                 if (rv != NULL)
  347                         rman_set_rid(rv, *rid);
  348                 return (rv);
  349         }
  350         return (NULL);
  351 }
  352 
  353 static int
  354 iq80321_setup_intr(device_t dev, device_t child,
  355     struct resource *ires, int flags, driver_filter_t *filt,
  356     driver_intr_t *intr, void *arg, void **cookiep)
  357 {
  358         int error;
  359 
  360         error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
  361             filt, intr, arg, cookiep);
  362         if (error)
  363                 return (error);
  364         intr_enabled |= 1 << rman_get_start(ires);
  365         i80321_set_intrmask();
  366         
  367         return (0);
  368 }
  369 
  370 static int
  371 iq80321_teardown_intr(device_t dev, device_t child, struct resource *res,
  372     void *cookie)
  373 {
  374         return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
  375 }
  376 
  377 static device_method_t iq80321_methods[] = {
  378         DEVMETHOD(device_probe, iq80321_probe),
  379         DEVMETHOD(device_attach, iq80321_attach),
  380         DEVMETHOD(device_identify, iq80321_identify),
  381         DEVMETHOD(bus_alloc_resource, iq80321_alloc_resource),
  382         DEVMETHOD(bus_setup_intr, iq80321_setup_intr),
  383         DEVMETHOD(bus_teardown_intr, iq80321_teardown_intr),
  384         {0, 0},
  385 };
  386 
  387 static driver_t iq80321_driver = {
  388         "iq",
  389         iq80321_methods,
  390         sizeof(struct i80321_softc),
  391 };
  392 static devclass_t iq80321_devclass;
  393 
  394 DRIVER_MODULE(iq, nexus, iq80321_driver, iq80321_devclass, 0, 0);

Cache object: b29d2bd80d19de152176c6262efd08ff


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