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: head/sys/arm/xscale/i80321/iq80321.c 140304 2005-01-15 16:56:22Z cognet $");
|
45__FBSDID("$FreeBSD: head/sys/arm/xscale/i80321/iq80321.c 140308 2005-01-15 18:55:22Z cognet $"); |
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#define __RMAN_RESOURCE_VISIBLE 55#include <sys/rman.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 68int iq80321_probe(device_t); 69void iq80321_identify(driver_t *, device_t); 70int iq80321_attach(device_t); 71 72int 73iq80321_probe(device_t dev) 74{ 75 device_set_desc(dev, "Intel 80321"); 76 return (0); 77} 78 79void 80iq80321_identify(driver_t *driver, device_t parent) 81{ 82 83 BUS_ADD_CHILD(parent, 0, "iq", 0); 84} 85 86static struct arm32_dma_range i80321_dr; 87static int dma_range_init = 0; 88 89struct arm32_dma_range * 90bus_dma_get_range(void) 91{ 92 if (dma_range_init == 0) 93 return (NULL); 94 return (&i80321_dr); 95} 96 97int 98bus_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 107void pmap_kenter(vm_offset_t, vm_offset_t); 108int 109iq80321_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 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_MAPS+0x0); 158 b0u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_MAPS+0x4); 159 b1l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_MAPS+0x8); 160 b1u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_MAPS+0xc); 161#define PCI_MAPREG_MEM_ADDR_MASK 0xfffffff0 162 b0l &= PCI_MAPREG_MEM_ADDR_MASK; 163 b0u &= PCI_MAPREG_MEM_ADDR_MASK; 164 b1l &= PCI_MAPREG_MEM_ADDR_MASK; 165 b1u &= PCI_MAPREG_MEM_ADDR_MASK; 166 167 if ((b0u != b1u) || (b0l != 0) || ((b1l & ~0x80000000U) != 0)) 168 sc->sc_is_host = 0; 169 else 170 sc->sc_is_host = 1; 171 i80321_sdram_bounds(sc->sc_st, sc->sc_mcu_sh, &memstart, &memsize); 172 /* 173 * We set up the Inbound Windows as follows: 174 * 175 * 0 Access to i80321 PMMRs 176 * 177 * 1 Reserve space for private devices 178 * 179 * 2 RAM access 180 * 181 * 3 Unused. 182 * 183 * This chunk needs to be customized for each IOP321 application. 184 */ 185#if 0 186 sc->sc_iwin[0].iwin_base_lo = VERDE_PMMR_BASE; 187 sc->sc_iwin[0].iwin_base_hi = 0; 188 sc->sc_iwin[0].iwin_xlate = VERDE_PMMR_BASE; 189 sc->sc_iwin[0].iwin_size = VERDE_PMMR_SIZE; 190#endif 191 if (sc->sc_is_host) { 192 193 /* Map PCI:Local 1:1. */ 194 sc->sc_iwin[1].iwin_base_lo = VERDE_OUT_XLATE_MEM_WIN0_BASE | 195 PCI_MAPREG_MEM_PREFETCHABLE_MASK | 196 PCI_MAPREG_MEM_TYPE_64BIT; 197 sc->sc_iwin[1].iwin_base_hi = 0; 198 } else { 199 200 sc->sc_iwin[1].iwin_base_lo = 0; 201 sc->sc_iwin[1].iwin_base_hi = 0; 202 } 203 sc->sc_iwin[1].iwin_xlate = VERDE_OUT_XLATE_MEM_WIN0_BASE; 204 sc->sc_iwin[1].iwin_size = VERDE_OUT_XLATE_MEM_WIN_SIZE; 205 206 if (sc->sc_is_host) { 207 sc->sc_iwin[2].iwin_base_lo = memstart | 208 PCI_MAPREG_MEM_PREFETCHABLE_MASK | 209 PCI_MAPREG_MEM_TYPE_64BIT; 210 sc->sc_iwin[2].iwin_base_hi = 0; 211 } else { 212 sc->sc_iwin[2].iwin_base_lo = 0; 213 sc->sc_iwin[2].iwin_base_hi = 0; 214 } 215 sc->sc_iwin[2].iwin_xlate = memstart; 216 sc->sc_iwin[2].iwin_size = memsize; 217 218 if (sc->sc_is_host) { 219 sc->sc_iwin[3].iwin_base_lo = 0 | 220 PCI_MAPREG_MEM_PREFETCHABLE_MASK | 221 PCI_MAPREG_MEM_TYPE_64BIT; 222 } else { 223 sc->sc_iwin[3].iwin_base_lo = 0; 224 } 225 sc->sc_iwin[3].iwin_base_hi = 0; 226 sc->sc_iwin[3].iwin_xlate = 0; 227 sc->sc_iwin[3].iwin_size = 0; 228 229 /* 230 * We set up the Outbound Windows as follows: 231 * 232 * 0 Access to private PCI space. 233 * 234 * 1 Unused. 235 */ 236#define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0) 237 sc->sc_owin[0].owin_xlate_lo = 238 PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo); 239 sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi; 240 /* 241 * Set the Secondary Outbound I/O window to map 242 * to PCI address 0 for all 64K of the I/O space. 243 */ 244 sc->sc_ioout_xlate = 0; 245 i80321_attach(sc); 246 i80321_dr.dr_sysbase = sc->sc_iwin[2].iwin_xlate; 247 i80321_dr.dr_busbase = PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo); 248 i80321_dr.dr_len = sc->sc_iwin[2].iwin_size; 249 dma_range_init = 1; 250 busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); 251 busno = PCIXSR_BUSNO(busno); 252 if (busno == 0xff) 253 busno = 0; 254 device_add_child(dev, "obio", 0); 255 device_add_child(dev, "itimer", 0); 256 device_add_child(dev, "iopwdog", 0);
|
257 device_add_child(dev, "iqseg", 0); |
258 device_add_child(dev, "pcib", busno); 259 bus_generic_probe(dev); 260 bus_generic_attach(dev); 261 262 return (0); 263} 264 265void 266arm_mask_irqs(int nb) 267{ 268 intr_enabled &= ~nb; 269 i80321_set_intrmask(); 270} 271 272void 273arm_unmask_irqs(int nb) 274{ 275 intr_enabled |= nb; 276 i80321_set_intrmask(); 277} 278 279void 280cpu_reset() 281{ 282 (void) disable_interrupts(I32_bit|F32_bit); 283 *(__volatile uint32_t *)(IQ80321_80321_VBASE + VERDE_ATU_BASE + 284 ATU_PCSR) = PCSR_RIB | PCSR_RPB; 285 printf("Reset failed :'(\n"); 286 for(;;); 287} 288 289static struct resource * 290iq80321_alloc_resource(device_t dev, device_t child, int type, int *rid, 291 u_long start, u_long end, u_long count, u_int flags) 292{ 293 if (type == SYS_RES_IRQ) { 294 struct resource *res = malloc(sizeof(*res), M_DEVBUF, M_WAITOK); 295 res->r_start = start; 296 res->r_end = end; 297 return (res); 298 } 299 return (NULL); 300} 301 302static int 303iq80321_setup_intr(device_t dev, device_t child, 304 struct resource *ires, int flags, driver_intr_t *intr, void *arg, 305 void **cookiep) 306{ 307 BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, intr, arg, 308 cookiep); 309 intr_enabled |= 1 << ires->r_start; 310 i80321_set_intrmask(); 311 312 return (0); 313} 314static device_method_t iq80321_methods[] = { 315 DEVMETHOD(device_probe, iq80321_probe), 316 DEVMETHOD(device_attach, iq80321_attach), 317 DEVMETHOD(device_identify, iq80321_identify), 318 DEVMETHOD(bus_alloc_resource, iq80321_alloc_resource), 319 DEVMETHOD(bus_setup_intr, iq80321_setup_intr), 320 {0, 0}, 321}; 322 323static driver_t iq80321_driver = { 324 "iq", 325 iq80321_methods, 326 sizeof(struct i80321_softc), 327}; 328static devclass_t iq80321_devclass; 329 330DRIVER_MODULE(iq, nexus, iq80321_driver, iq80321_devclass, 0, 0);
|