1/* $NetBSD: i80321_pci.c,v 1.4 2003/07/15 00:24:54 lukem 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 * PCI configuration support for i80321 I/O Processor chip. 40 */ 41 42#include <sys/cdefs.h> 43__FBSDID("$FreeBSD$"); 44 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/malloc.h> 48#include <sys/bus.h> 49#include <sys/kernel.h> 50#include <sys/module.h> 51#include <sys/rman.h> 52 53#include <machine/bus.h> 54#include <machine/cpu.h> 55#include <machine/pcb.h> 56#include <vm/vm.h> 57#include <vm/pmap.h> 58#include <vm/vm_extern.h> 59#include <machine/pmap.h> 60 61#include <arm/xscale/i80321/i80321reg.h> 62#include <arm/xscale/i80321/i80321var.h> 63#include <arm/xscale/i80321/i80321_intr.h> 64 65#include <dev/pci/pcib_private.h> 66#include "pcib_if.h" 67 68#include <dev/pci/pcireg.h> 69extern struct i80321_softc *i80321_softc; 70 71static int 72i80321_pci_probe(device_t dev) 73{ 74 device_set_desc(dev, "i80321 PCI bus"); 75 return (0); 76} 77 78static int 79i80321_pci_attach(device_t dev) 80{ 81 82 uint32_t busno; 83 struct i80321_pci_softc *sc = device_get_softc(dev); 84 85 sc->sc_st = i80321_softc->sc_st; 86 sc->sc_atu_sh = i80321_softc->sc_atu_sh; 87 busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); 88 busno = PCIXSR_BUSNO(busno); 89 if (busno == 0xff) 90 busno = 0; 91 sc->sc_dev = dev; 92 sc->sc_busno = busno; 93 sc->sc_pciio = &i80321_softc->sc_pci_iot; 94 sc->sc_pcimem = &i80321_softc->sc_pci_memt; 95 sc->sc_mem = i80321_softc->sc_owin[0].owin_xlate_lo + 96 VERDE_OUT_XLATE_MEM_WIN_SIZE; 97 98 sc->sc_io = i80321_softc->sc_iow_vaddr; 99 /* Initialize memory and i/o rmans. */ 100 sc->sc_io_rman.rm_type = RMAN_ARRAY; 101 sc->sc_io_rman.rm_descr = "I80321 PCI I/O Ports"; 102 if (rman_init(&sc->sc_io_rman) != 0 || 103 rman_manage_region(&sc->sc_io_rman, 104 sc->sc_io, 105 sc->sc_io + 106 VERDE_OUT_XLATE_IO_WIN_SIZE) != 0) { 107 panic("i80321_pci_probe: failed to set up I/O rman"); 108 } 109 sc->sc_mem_rman.rm_type = RMAN_ARRAY; 110 sc->sc_mem_rman.rm_descr = "I80321 PCI Memory"; 111 if (rman_init(&sc->sc_mem_rman) != 0 || 112 rman_manage_region(&sc->sc_mem_rman, 113 0, VERDE_OUT_XLATE_MEM_WIN_SIZE) != 0) { 114 panic("i80321_pci_probe: failed to set up memory rman"); 115 } 116 sc->sc_irq_rman.rm_type = RMAN_ARRAY; 117 sc->sc_irq_rman.rm_descr = "i80321 PCI IRQs"; 118 if (rman_init(&sc->sc_irq_rman) != 0 || 119 rman_manage_region(&sc->sc_irq_rman, 26, 32) != 0) 120 panic("i80321_pci_probe: failed to set up IRQ rman"); 121 device_add_child(dev, "pci",busno); 122 return (bus_generic_attach(dev)); 123} 124 125static int 126i80321_pci_maxslots(device_t dev) 127{ 128 return (PCI_SLOTMAX); 129} 130 131 132 133static int 134i80321_pci_conf_setup(struct i80321_pci_softc *sc, int bus, int slot, int func, 135 int reg, uint32_t *addr) 136{ 137 uint32_t busno; 138 139 busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); 140 busno = PCIXSR_BUSNO(busno); 141 if (busno == 0xff) 142 busno = 0; 143 144 /* 145 * If the bus # is the same as our own, then use Type 0 cycles, 146 * else use Type 1. 147 * 148 * XXX We should filter out all non-private devices here! 149 * XXX How does private space interact with PCI-PCI bridges? 150 */ 151 if (bus == busno) { 152 if (slot > (31 - 16)) 153 return (1); 154 /* 155 * NOTE: PCI-X requires that that devices updated their 156 * PCIXSR on every config write with the device number 157 * specified in AD[15:11]. If we don't set this field, 158 * each device could end of thinking it is at device 0, 159 * which can cause a number of problems. Doing this 160 * unconditionally should be OK when only PCI devices 161 * are present. 162 */ 163 bus &= 0xff; 164 slot &= 0x1f; 165 func &= 0x07; 166 167 *addr = (1U << (slot + 16)) | 168 (slot << 11) | (func << 8) | reg; 169 } else { 170 *addr = (bus << 16) | (slot << 11) | (func << 8) | reg | 1; 171 } 172 173 return (0); 174} 175 176static u_int32_t 177i80321_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func, 178 u_int reg, int bytes) 179{ 180 struct i80321_pci_softc *sc = device_get_softc(dev); 181 uint32_t isr; 182 uint32_t addr; 183 u_int32_t ret = 0; 184 vm_offset_t va; 185 int err = 0; 186 if (i80321_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr)) 187 return (-1); 188 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCAR, 189 addr); 190 191 va = sc->sc_atu_sh; 192 switch (bytes) { 193 case 1: 194 err = badaddr_read((void*)(va + ATU_OCCDR + (reg & 3)), 1, &ret); 195 break; 196 case 2: 197 err = badaddr_read((void*)(va + ATU_OCCDR + (reg & 3)), 2, &ret); 198 break; 199 case 4: 200 err = badaddr_read((void *)(va + ATU_OCCDR), 4, &ret); 201 break; 202 default: 203 printf("i80321_read_config: invalid size %d\n", bytes); 204 ret = -1; 205 } 206 if (err) { 207 208 isr = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUISR); 209 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUISR, 210 isr & (ATUISR_P_SERR_DET|ATUISR_PMA|ATUISR_PTAM| 211 ATUISR_PTAT|ATUISR_PMPE)); 212 return (-1); 213 } 214 return (ret); 215} 216 217static void 218i80321_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func, 219 u_int reg, u_int32_t data, int bytes) 220{ 221 struct i80321_pci_softc *sc = device_get_softc(dev); 222 uint32_t addr; 223 224 if (i80321_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr)) 225 return; 226 227 228 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCAR, 229 addr); 230 switch (bytes) { 231 case 1: 232 bus_space_write_1(sc->sc_st, sc->sc_atu_sh, ATU_OCCDR + 233 (reg & 3), data); 234 break; 235 case 2: 236 bus_space_write_2(sc->sc_st, sc->sc_atu_sh, ATU_OCCDR + 237 (reg & 3), data); 238 break; 239 case 4: 240 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCDR, data); 241 break; 242 default: 243 printf("i80321_pci_write_config: Invalid size : %d\n", bytes); 244 } 245 246} 247 248static int 249i80321_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 250{ 251 struct i80321_pci_softc *sc = device_get_softc(dev); 252 switch (which) { 253 case PCIB_IVAR_DOMAIN: 254 *result = 0; 255 return (0); 256 case PCIB_IVAR_BUS: 257 *result = sc->sc_busno; 258 return (0); 259 260 } 261 return (ENOENT); 262} 263 264static int 265i80321_write_ivar(device_t dev, device_t child, int which, uintptr_t result) 266{ 267 struct i80321_pci_softc * sc = device_get_softc(dev); 268 269 switch (which) { 270 case PCIB_IVAR_DOMAIN: 271 return (EINVAL); 272 case PCIB_IVAR_BUS: 273 sc->sc_busno = result; 274 return (0); 275 } 276 return (ENOENT); 277} 278 279static struct resource * 280i80321_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, 281 u_long start, u_long end, u_long count, u_int flags) 282{ 283 struct i80321_pci_softc *sc = device_get_softc(bus); 284 struct resource *rv; 285 struct rman *rm; 286 bus_space_tag_t bt = NULL; 287 bus_space_handle_t bh = 0; 288 289 switch (type) { 290 case SYS_RES_IRQ: 291 rm = &sc->sc_irq_rman; 292 break; 293 case SYS_RES_MEMORY: 294 rm = &sc->sc_mem_rman; 295 bt = sc->sc_pcimem; 296 bh = (start >= 0x80000000 && start < 0x84000000) ? 0x80000000 : 297 sc->sc_mem; 298 start &= (0x1000000 - 1); 299 end &= (0x1000000 - 1); 300 break; 301 case SYS_RES_IOPORT: 302 rm = &sc->sc_io_rman; 303 bt = sc->sc_pciio; 304 bh = sc->sc_io; 305 if (start < sc->sc_io) { 306 start = start - 0x90000000 + sc->sc_io; 307 end = end - 0x90000000 + sc->sc_io; 308 } 309 break; 310 default: 311 return (NULL); 312 } 313 314 rv = rman_reserve_resource(rm, start, end, count, flags, child); 315 if (rv == NULL) 316 return (NULL); 317 rman_set_rid(rv, *rid); 318 if (type != SYS_RES_IRQ) { 319 if (type == SYS_RES_MEMORY) 320 bh += (rman_get_start(rv)); 321 rman_set_bustag(rv, bt); 322 rman_set_bushandle(rv, bh); 323 if (flags & RF_ACTIVE) { 324 if (bus_activate_resource(child, type, *rid, rv)) { 325 rman_release_resource(rv); 326 return (NULL); 327 } 328 } 329 } 330 return (rv); 331} 332 333static int 334i80321_pci_activate_resource(device_t bus, device_t child, int type, int rid, 335 struct resource *r) 336{ 337 u_long p; 338 int error; 339 340 if (type == SYS_RES_MEMORY) { 341 error = bus_space_map(rman_get_bustag(r), 342 rman_get_bushandle(r), rman_get_size(r), 0, &p); 343 if (error) 344 return (error); 345 rman_set_bushandle(r, p); 346 347 } 348 return (rman_activate_resource(r)); 349} 350 351static int 352i80321_pci_setup_intr(device_t dev, device_t child, 353 struct resource *ires, int flags, driver_filter_t *filt, 354 driver_intr_t *intr, void *arg, void **cookiep) 355{ 356 return (BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, 357 filt, intr, arg, cookiep)); 358} 359 360static int 361i80321_pci_teardown_intr(device_t dev, device_t child, struct resource *res, 362 void *cookie) 363{ 364 return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie)); 365} 366 367static device_method_t i80321_pci_methods[] = { 368 /* Device interface */ 369 DEVMETHOD(device_probe, i80321_pci_probe), 370 DEVMETHOD(device_attach, i80321_pci_attach), 371 DEVMETHOD(device_shutdown, bus_generic_shutdown), 372 DEVMETHOD(device_suspend, bus_generic_suspend), 373 DEVMETHOD(device_resume, bus_generic_resume), 374 375 /* Bus interface */ 376 DEVMETHOD(bus_read_ivar, i80321_read_ivar), 377 DEVMETHOD(bus_write_ivar, i80321_write_ivar), 378 DEVMETHOD(bus_alloc_resource, i80321_pci_alloc_resource), 379 DEVMETHOD(bus_release_resource, bus_generic_release_resource), 380 DEVMETHOD(bus_activate_resource, i80321_pci_activate_resource), 381 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 382 DEVMETHOD(bus_setup_intr, i80321_pci_setup_intr), 383 DEVMETHOD(bus_teardown_intr, i80321_pci_teardown_intr), 384 385 /* pcib interface */ 386 DEVMETHOD(pcib_maxslots, i80321_pci_maxslots), 387 DEVMETHOD(pcib_read_config, i80321_pci_read_config), 388 DEVMETHOD(pcib_write_config, i80321_pci_write_config), 389 DEVMETHOD(pcib_route_interrupt, machdep_pci_route_interrupt), 390 391 DEVMETHOD_END 392}; 393 394static driver_t i80321_pci_driver = { 395 "pcib", 396 i80321_pci_methods, 397 sizeof(struct i80321_pci_softc), 398}; 399 400static devclass_t i80321_pci_devclass; 401 402DRIVER_MODULE(ipci, iq, i80321_pci_driver, i80321_pci_devclass, 0, 0); 403