iq80321.c revision 278613
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: stable/10/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 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 (BUS_PROBE_NOWILDCARD); 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 107 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 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 311void 312arm_mask_irq(uintptr_t nb) 313{ 314 intr_enabled &= ~(1 << nb); 315 i80321_set_intrmask(); 316} 317 318void 319arm_unmask_irq(uintptr_t nb) 320{ 321 intr_enabled |= (1 << nb); 322 i80321_set_intrmask(); 323} 324 325 326void 327cpu_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 336static struct resource * 337iq80321_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 353static int 354iq80321_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 370static int 371iq80321_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 377static 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 387static driver_t iq80321_driver = { 388 "iq", 389 iq80321_methods, 390 sizeof(struct i80321_softc), 391}; 392static devclass_t iq80321_devclass; 393 394DRIVER_MODULE(iq, nexus, iq80321_driver, iq80321_devclass, 0, 0); 395