1/* 2 * Low-Level PCI and SB support for BCM47xx 3 * 4 * Copyright 2007, Broadcom Corporation 5 * All Rights Reserved. 6 * 7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY 8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM 9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS 10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. 11 * 12 * $Id: hndpci.c,v 1.1.1.1 2008/10/15 03:31:34 james26_jang Exp $ 13 */ 14 15#include <typedefs.h> 16#include <osl.h> 17#include <pcicfg.h> 18#include <bcmdevs.h> 19#include <sbconfig.h> 20#include <bcmutils.h> 21#include <sbutils.h> 22#include <sbpci.h> 23#include <bcmendian.h> 24#include <bcmnvram.h> 25#include <hndcpu.h> 26#include <hndmips.h> 27#include <hndpci.h> 28 29/* debug/trace */ 30#ifdef BCMDBG_PCI 31#define PCI_MSG(args) printf args 32#else 33#define PCI_MSG(args) 34#endif /* BCMDBG_PCI */ 35 36/* Can free sbpci_init() memory after boot */ 37#ifndef linux 38#define __init 39#endif /* linux */ 40 41/* Emulated configuration space */ 42typedef struct { 43 int n; 44 uint size0; 45 uint size1; 46 uint size2; 47 uint size3; 48} sb_bar_cfg_t; 49static pci_config_regs sb_config_regs[SB_MAXCORES]; 50static sb_bar_cfg_t sb_bar_cfg[SB_MAXCORES]; 51 52/* Links to emulated and real PCI configuration spaces */ 53#define MAXFUNCS 2 54typedef struct { 55 pci_config_regs *emu; /* emulated PCI config */ 56 pci_config_regs *pci; /* real PCI config */ 57 sb_bar_cfg_t *bar; /* region sizes */ 58} sb_pci_cfg_t; 59static sb_pci_cfg_t sb_pci_cfg[SB_MAXCORES][MAXFUNCS]; 60 61/* Special emulated config space for non-existing device */ 62static pci_config_regs sb_pci_null = { 0xffff, 0xffff }; 63 64/* Banned cores */ 65static uint16 pci_ban[SB_MAXCORES] = { 0 }; 66static uint pci_banned = 0; 67 68/* CardBus mode */ 69static bool cardbus = FALSE; 70 71/* Disable PCI host core */ 72static bool pci_disabled = FALSE; 73 74/* Host bridge slot #, default to 0 */ 75static uint8 pci_hbslot = 0; 76 77/* Internal macros */ 78#define PCI_SLOTAD_MAP 16 /* SLOT<n> mapps to AD<n+16> */ 79#define PCI_HBSBCFG_REV 8 /* MIN. core rev. required to 80 * access host bridge PCI cfg space 81 * from SB 82 */ 83 84/* 85 * Functions for accessing external PCI configuration space 86 */ 87 88/* Assume one-hot slot wiring */ 89#define PCI_SLOT_MAX 16 /* Max. PCI Slots */ 90 91static uint32 92config_cmd(sb_t *sbh, uint bus, uint dev, uint func, uint off) 93{ 94 uint coreidx; 95 sbpciregs_t *regs; 96 uint32 addr = 0; 97 osl_t *osh; 98 99 /* CardBusMode supports only one device */ 100 if (cardbus && dev > 1) 101 return 0; 102 103 osh = sb_osh(sbh); 104 105 coreidx = sb_coreidx(sbh); 106 regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0); 107 108 /* Type 0 transaction */ 109 if (bus == 1) { 110 /* Skip unwired slots */ 111 if (dev < PCI_SLOT_MAX) { 112 uint32 win; 113 114 /* Slide the PCI window to the appropriate slot */ 115 win = (SBTOPCI_CFG0 | ((1 << (dev + PCI_SLOTAD_MAP)) & SBTOPCI1_MASK)); 116 W_REG(osh, ®s->sbtopci1, win); 117 addr = SB_PCI_CFG | 118 ((1 << (dev + PCI_SLOTAD_MAP)) & ~SBTOPCI1_MASK) | 119 (func << PCICFG_FUN_SHIFT) | 120 (off & ~3); 121 } 122 } else { 123 /* Type 1 transaction */ 124 W_REG(osh, ®s->sbtopci1, SBTOPCI_CFG1); 125 addr = SB_PCI_CFG | 126 (bus << PCICFG_BUS_SHIFT) | 127 (dev << PCICFG_SLOT_SHIFT) | 128 (func << PCICFG_FUN_SHIFT) | 129 (off & ~3); 130 } 131 132 sb_setcoreidx(sbh, coreidx); 133 134 return addr; 135} 136 137/* 138 * Read host bridge PCI config registers from Silicon Backplane (>=rev8). 139 * 140 * It returns TRUE to indicate that access to the host bridge's pci config 141 * from SB is ok, and values in 'addr' and 'val' are valid. 142 * 143 * It can only read registers at multiple of 4-bytes. Callers must pick up 144 * needed bytes from 'val' based on 'off' value. Value in 'addr' reflects 145 * the register address where value in 'val' is read. 146 */ 147static bool 148sb_pcihb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, 149 uint32 **addr, uint32 *val) 150{ 151 sbpciregs_t *regs; 152 osl_t *osh; 153 uint coreidx; 154 bool ret = FALSE; 155 156 /* sanity check */ 157 ASSERT(bus == 1); 158 ASSERT(dev == pci_hbslot); 159 ASSERT(func == 0); 160 161 osh = sb_osh(sbh); 162 163 /* read pci config when core rev >= 8 */ 164 coreidx = sb_coreidx(sbh); 165 regs = (sbpciregs_t *)sb_setcore(sbh, SB_PCI, 0); 166 if (regs && sb_corerev(sbh) >= PCI_HBSBCFG_REV) { 167 *addr = (uint32 *)®s->pcicfg[func][off >> 2]; 168 *val = R_REG(osh, *addr); 169 ret = TRUE; 170 } 171 sb_setcoreidx(sbh, coreidx); 172 173 return ret; 174} 175 176int 177extpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) 178{ 179 uint32 addr = 0, *reg = NULL, val; 180 int ret = 0; 181 182 /* 183 * Set value to -1 when: 184 * flag 'pci_disabled' is true; 185 * value of 'addr' is zero; 186 * REG_MAP() fails; 187 * BUSPROBE() fails; 188 */ 189 if (pci_disabled) 190 val = 0xffffffff; 191 else if (bus == 1 && dev == pci_hbslot && func == 0 && 192 sb_pcihb_read_config(sbh, bus, dev, func, off, ®, &val)) 193 ; 194 else if (((addr = config_cmd(sbh, bus, dev, func, off)) == 0) || 195 ((reg = (uint32 *)REG_MAP(addr, len)) == 0) || 196 (BUSPROBE(val, reg) != 0)) { 197 PCI_MSG(("%s: Failed to read!\n", __FUNCTION__)); 198 val = 0xffffffff; 199 } 200 201 PCI_MSG(("%s: 0x%x <= 0x%p(0x%x), len %d, off 0x%x, buf 0x%p\n", 202 __FUNCTION__, val, reg, addr, len, off, buf)); 203 204 val >>= 8 * (off & 3); 205 if (len == 4) 206 *((uint32 *) buf) = val; 207 else if (len == 2) 208 *((uint16 *) buf) = (uint16) val; 209 else if (len == 1) 210 *((uint8 *) buf) = (uint8) val; 211 else 212 ret = -1; 213 214 if (reg && addr) 215 REG_UNMAP(reg); 216 217 return ret; 218} 219 220int 221extpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) 222{ 223 osl_t *osh; 224 uint32 addr = 0, *reg = NULL, val; 225 int ret = 0; 226 227 osh = sb_osh(sbh); 228 229 /* 230 * Ignore write attempt when: 231 * flag 'pci_disabled' is true; 232 * value of 'addr' is zero; 233 * REG_MAP() fails; 234 * BUSPROBE() fails; 235 */ 236 if (pci_disabled) 237 return 0; 238 else if (bus == 1 && dev == pci_hbslot && func == 0 && 239 sb_pcihb_read_config(sbh, bus, dev, func, off, ®, &val)) 240 ; 241 else if (((addr = config_cmd(sbh, bus, dev, func, off)) == 0) || 242 ((reg = (uint32 *) REG_MAP(addr, len)) == 0) || 243 (BUSPROBE(val, reg) != 0)) { 244 PCI_MSG(("%s: Failed to write!\n", __FUNCTION__)); 245 goto done; 246 } 247 248 if (len == 4) 249 val = *((uint32 *) buf); 250 else if (len == 2) { 251 val &= ~(0xffff << (8 * (off & 3))); 252 val |= *((uint16 *) buf) << (8 * (off & 3)); 253 } else if (len == 1) { 254 val &= ~(0xff << (8 * (off & 3))); 255 val |= *((uint8 *) buf) << (8 * (off & 3)); 256 } else { 257 ret = -1; 258 goto done; 259 } 260 261 PCI_MSG(("%s: 0x%x => 0x%p\n", __FUNCTION__, val, reg)); 262 263 W_REG(osh, reg, val); 264 265done: 266 if (reg && addr) 267 REG_UNMAP(reg); 268 269 return ret; 270} 271 272/* 273 * Must access emulated PCI configuration at these locations even when 274 * the real PCI config space exists and is accessible. 275 * 276 * PCI_CFG_VID (0x00) 277 * PCI_CFG_DID (0x02) 278 * PCI_CFG_PROGIF (0x09) 279 * PCI_CFG_SUBCL (0x0a) 280 * PCI_CFG_BASECL (0x0b) 281 * PCI_CFG_HDR (0x0e) 282 * PCI_CFG_INT (0x3c) 283 * PCI_CFG_PIN (0x3d) 284 */ 285#define FORCE_EMUCFG(off, len) \ 286 ((off == PCI_CFG_VID) || (off == PCI_CFG_DID) || \ 287 (off == PCI_CFG_PROGIF) || \ 288 (off == PCI_CFG_SUBCL) || (off == PCI_CFG_BASECL) || \ 289 (off == PCI_CFG_HDR) || \ 290 (off == PCI_CFG_INT) || (off == PCI_CFG_PIN)) 291 292/* Sync the emulation registers and the real PCI config registers. */ 293static void 294sb_pcid_read_config(sb_t *sbh, uint coreidx, sb_pci_cfg_t *cfg, 295 uint off, uint len) 296{ 297 osl_t *osh; 298 uint oldidx; 299 300 ASSERT(cfg); 301 ASSERT(cfg->emu); 302 ASSERT(cfg->pci); 303 304 /* decide if real PCI config register access is necessary */ 305 if (FORCE_EMUCFG(off, len)) 306 return; 307 308 osh = sb_osh(sbh); 309 310 /* access to the real pci config space only when the core is up */ 311 oldidx = sb_coreidx(sbh); 312 sb_setcoreidx(sbh, coreidx); 313 if (sb_iscoreup(sbh)) { 314 if (len == 4) 315 *(uint32 *)((ulong)cfg->emu + off) = 316 htol32(R_REG(osh, (uint32 *)((ulong)cfg->pci + off))); 317 else if (len == 2) 318 *(uint16 *)((ulong)cfg->emu + off) = 319 htol16(R_REG(osh, (uint16 *)((ulong)cfg->pci + off))); 320 else if (len == 1) 321 *(uint8 *)((ulong)cfg->emu + off) = 322 R_REG(osh, (uint8 *)((ulong)cfg->pci + off)); 323 } 324 sb_setcoreidx(sbh, oldidx); 325} 326 327static void 328sb_pcid_write_config(sb_t *sbh, uint coreidx, sb_pci_cfg_t *cfg, 329 uint off, uint len) 330{ 331 osl_t *osh; 332 uint oldidx; 333 334 ASSERT(cfg); 335 ASSERT(cfg->emu); 336 ASSERT(cfg->pci); 337 338 osh = sb_osh(sbh); 339 340 /* decide if real PCI config register access is necessary */ 341 if (FORCE_EMUCFG(off, len)) 342 return; 343 344 /* access to the real pci config space only when the core is up */ 345 oldidx = sb_coreidx(sbh); 346 sb_setcoreidx(sbh, coreidx); 347 if (sb_iscoreup(sbh)) { 348 if (len == 4) 349 W_REG(osh, (uint32 *)((ulong)cfg->pci + off), 350 ltoh32(*(uint32 *)((ulong)cfg->emu + off))); 351 else if (len == 2) 352 W_REG(osh, (uint16 *)((ulong)cfg->pci + off), 353 ltoh16(*(uint16 *)((ulong)cfg->emu + off))); 354 else if (len == 1) 355 W_REG(osh, (uint8 *)((ulong)cfg->pci + off), 356 *(uint8 *)((ulong)cfg->emu + off)); 357 } 358 sb_setcoreidx(sbh, oldidx); 359} 360 361/* 362 * Functions for accessing translated SB configuration space 363 */ 364static int 365sb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) 366{ 367 pci_config_regs *cfg; 368 369 if (dev >= SB_MAXCORES || func >= MAXFUNCS || (off + len) > sizeof(pci_config_regs)) 370 return -1; 371 cfg = sb_pci_cfg[dev][func].emu; 372 373 ASSERT(ISALIGNED(off, len)); 374 ASSERT(ISALIGNED((uintptr)buf, len)); 375 376 /* use special config space if the device does not exist */ 377 if (!cfg) 378 cfg = &sb_pci_null; 379 /* sync emulation with real PCI config if necessary */ 380 else if (sb_pci_cfg[dev][func].pci) 381 sb_pcid_read_config(sbh, dev, &sb_pci_cfg[dev][func], off, len); 382 383 if (len == 4) 384 *((uint32 *) buf) = ltoh32(*((uint32 *)((ulong) cfg + off))); 385 else if (len == 2) 386 *((uint16 *) buf) = ltoh16(*((uint16 *)((ulong) cfg + off))); 387 else if (len == 1) 388 *((uint8 *) buf) = *((uint8 *)((ulong) cfg + off)); 389 else 390 return -1; 391 392 return 0; 393} 394 395static int 396sb_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) 397{ 398 uint coreidx; 399 void *regs; 400 pci_config_regs *cfg; 401 osl_t *osh; 402 sb_bar_cfg_t *bar; 403 404 if (dev >= SB_MAXCORES || func >= MAXFUNCS || (off + len) > sizeof(pci_config_regs)) 405 return -1; 406 cfg = sb_pci_cfg[dev][func].emu; 407 if (!cfg) 408 return -1; 409 410 ASSERT(ISALIGNED(off, len)); 411 ASSERT(ISALIGNED((uintptr)buf, len)); 412 413 osh = sb_osh(sbh); 414 415 /* Emulate BAR sizing */ 416 if (off >= OFFSETOF(pci_config_regs, base[0]) && 417 off <= OFFSETOF(pci_config_regs, base[3]) && 418 len == 4 && *((uint32 *) buf) == ~0) { 419 coreidx = sb_coreidx(sbh); 420 if ((regs = sb_setcoreidx(sbh, dev))) { 421 bar = sb_pci_cfg[dev][func].bar; 422 /* Highest numbered address match register */ 423 if (off == OFFSETOF(pci_config_regs, base[0])) 424 cfg->base[0] = ~(bar->size0 - 1); 425 else if (off == OFFSETOF(pci_config_regs, base[1]) && bar->n >= 1) 426 cfg->base[1] = ~(bar->size1 - 1); 427 else if (off == OFFSETOF(pci_config_regs, base[2]) && bar->n >= 2) 428 cfg->base[2] = ~(bar->size2 - 1); 429 else if (off == OFFSETOF(pci_config_regs, base[3]) && bar->n >= 3) 430 cfg->base[3] = ~(bar->size3 - 1); 431 } 432 sb_setcoreidx(sbh, coreidx); 433 } else if (len == 4) 434 *((uint32 *)((ulong) cfg + off)) = htol32(*((uint32 *) buf)); 435 else if (len == 2) 436 *((uint16 *)((ulong) cfg + off)) = htol16(*((uint16 *) buf)); 437 else if (len == 1) 438 *((uint8 *)((ulong) cfg + off)) = *((uint8 *) buf); 439 else 440 return -1; 441 442 /* sync emulation with real PCI config if necessary */ 443 if (sb_pci_cfg[dev][func].pci) 444 sb_pcid_write_config(sbh, dev, &sb_pci_cfg[dev][func], off, len); 445 446 return 0; 447} 448 449int 450sbpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) 451{ 452 if (bus == 0) 453 return sb_read_config(sbh, bus, dev, func, off, buf, len); 454 else 455 return extpci_read_config(sbh, bus, dev, func, off, buf, len); 456} 457 458int 459sbpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len) 460{ 461 if (bus == 0) 462 return sb_write_config(sbh, bus, dev, func, off, buf, len); 463 else 464 return extpci_write_config(sbh, bus, dev, func, off, buf, len); 465} 466 467void 468sbpci_ban(uint16 core) 469{ 470 if (pci_banned < ARRAYSIZE(pci_ban)) 471 pci_ban[pci_banned++] = core; 472} 473 474/* 475 * Initiliaze PCI core. Return 0 after a successful initialization. 476 * Otherwise return -1 to indicate there is no PCI core and return 1 477 * to indicate PCI core is disabled. 478 */ 479int __init 480sbpci_init_pci(sb_t *sbh) 481{ 482 uint chip, chiprev, chippkg, host; 483 uint32 boardflags; 484 sbpciregs_t *pci; 485 sbconfig_t *sb; 486 uint32 val; 487 int ret = 0; 488 char *hbslot; 489 osl_t *osh; 490 491 chip = sb_chip(sbh); 492 chiprev = sb_chiprev(sbh); 493 chippkg = sb_chippkg(sbh); 494 495 osh = sb_osh(sbh); 496 497 if (!(pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0))) { 498 printf("PCI: no core\n"); 499 pci_disabled = TRUE; 500 return -1; 501 } 502 sb = (sbconfig_t *)((ulong) pci + SBCONFIGOFF); 503 504 boardflags = (uint32) getintvar(NULL, "boardflags"); 505 506 /* 507 * The 200-pin BCM4712 package does not bond out PCI. Even when 508 * PCI is bonded out, some boards may leave the pins 509 * floating. 510 */ 511 if (((chip == BCM4712_CHIP_ID) && 512 ((chippkg == BCM4712SMALL_PKG_ID) || 513 (chippkg == BCM4712MID_PKG_ID))) || 514 (boardflags & BFL_NOPCI)) 515 pci_disabled = TRUE; 516 517 /* Enable the core */ 518 sb_core_reset(sbh, 0, 0); 519 520 /* 521 * If the PCI core should not be touched (disabled, not bonded 522 * out, or pins floating), do not even attempt to access core 523 * registers. Otherwise, try to determine if it is in host 524 * mode. 525 */ 526 if (pci_disabled) 527 host = 0; 528 else 529 host = !BUSPROBE(val, &pci->control); 530 531 if (!host) { 532 ret = 1; 533 534 /* Disable PCI interrupts in client mode */ 535 W_REG(osh, &sb->sbintvec, 0); 536 537 /* Disable the PCI bridge in client mode */ 538 sbpci_ban(SB_PCI); 539 sb_core_disable(sbh, 0); 540 541 printf("PCI: Disabled\n"); 542 } else { 543 printf("PCI: Initializing host\n"); 544 545 /* Disable PCI SBReqeustTimeout for BCM4785 rev. < 2 */ 546 if (chip == BCM4785_CHIP_ID && chiprev < 2) { 547 AND_REG(osh, &sb->sbimconfiglow, ~0x00000070); 548 sb_commit(sbh); 549 } 550 551 /* Reset the external PCI bus and enable the clock */ 552 W_REG(osh, &pci->control, 0x5); /* enable the tristate drivers */ 553 W_REG(osh, &pci->control, 0xd); /* enable the PCI clock */ 554 OSL_DELAY(150); /* delay > 100 us */ 555 W_REG(osh, &pci->control, 0xf); /* deassert PCI reset */ 556 /* Use internal arbiter and park REQ/GRNT at external master 0 557 * We will set it later after the bus has been probed 558 */ 559 W_REG(osh, &pci->arbcontrol, PCI_INT_ARB); 560 OSL_DELAY(1); /* delay 1 us */ 561 562 /* Enable CardBusMode */ 563 cardbus = getintvar(NULL, "cardbus") == 1; 564 if (cardbus) { 565 printf("PCI: Enabling CardBus\n"); 566 /* GPIO 1 resets the CardBus device on bcm94710ap */ 567 sb_gpioout(sbh, 1, 1, GPIO_DRV_PRIORITY); 568 sb_gpioouten(sbh, 1, 1, GPIO_DRV_PRIORITY); 569 W_REG(osh, &pci->sprom[0], R_REG(osh, &pci->sprom[0]) | 0x400); 570 } 571 572 /* 64 MB I/O access window */ 573 W_REG(osh, &pci->sbtopci0, SBTOPCI_IO); 574 /* 64 MB configuration access window */ 575 W_REG(osh, &pci->sbtopci1, SBTOPCI_CFG0); 576 /* 1 GB memory access window */ 577 W_REG(osh, &pci->sbtopci2, SBTOPCI_MEM | SB_PCI_DMA); 578 579 /* Host bridge slot # nvram overwrite */ 580 if ((hbslot = nvram_get("pcihbslot"))) { 581 pci_hbslot = bcm_strtoul(hbslot, NULL, 0); 582 ASSERT(pci_hbslot < PCI_MAX_DEVICES); 583 } 584 585 /* Enable PCI bridge BAR0 prefetch and burst */ 586 val = 6; 587 sbpci_write_config(sbh, 1, pci_hbslot, 0, PCI_CFG_CMD, &val, sizeof(val)); 588 589 /* Enable PCI interrupts */ 590 W_REG(osh, &pci->intmask, PCI_INTA); 591 } 592 593 return ret; 594} 595 596void 597sbpci_arb_park(sb_t *sbh, uint parkid) 598{ 599 sbpciregs_t *pci; 600 uint pcirev; 601 uint32 arb; 602 603 if (!(pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0))) { 604 /* Should not happen */ 605 printf("%s: no PCI core\n", __FUNCTION__); 606 return; 607 } 608 609 pcirev = sb_corerev(sbh); 610 611 /* Nothing to do, not supported for these revs */ 612 if (pcirev < 8) 613 return; 614 615 /* Get parkid from NVRAM */ 616 if (parkid == PCI_PARK_NVRAM) { 617 parkid = getintvar(NULL, "parkid"); 618 if (getvar(NULL, "parkid") == NULL) 619 /* Not present in NVRAM use defaults */ 620 parkid = (pcirev >= 11) ? PCI11_PARKID_LAST : PCI_PARKID_LAST; 621 } 622 623 /* Check the parkid is valid, if not set it to default */ 624 if (parkid > ((pcirev >= 11) ? PCI11_PARKID_LAST : PCI_PARKID_LAST)) { 625 printf("%s: Invalid parkid %d\n", __FUNCTION__, parkid); 626 parkid = (pcirev >= 11) ? PCI11_PARKID_LAST : PCI_PARKID_LAST; 627 } 628 629 /* Now set the parkid */ 630 arb = R_REG(sb_osh(sbh), &pci->arbcontrol); 631 arb &= ~PCI_PARKID_MASK; 632 arb |= parkid << PCI_PARKID_SHIFT; 633 W_REG(sb_osh(sbh), &pci->arbcontrol, arb); 634 OSL_DELAY(1); 635} 636 637/* 638 * Get the PCI region address and size information. 639 */ 640static void __init 641sbpci_init_regions(sb_t *sbh, uint func, pci_config_regs *cfg, sb_bar_cfg_t *bar) 642{ 643 osl_t *osh; 644 uint16 coreid; 645 void *regs; 646 sbconfig_t *sb; 647 uint32 base; 648 649 osh = sb_osh(sbh); 650 coreid = sb_coreid(sbh); 651 regs = sb_coreregs(sbh); 652 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); 653 654 switch (coreid) { 655 case SB_USB20H: 656 base = htol32(sb_base(R_REG(osh, &sb->sbadmatch0))); 657 658 cfg->base[0] = func == 0 ? base : base + 0x800; /* OHCI/EHCI */ 659 cfg->base[1] = 0; 660 cfg->base[2] = 0; 661 cfg->base[3] = 0; 662 cfg->base[4] = 0; 663 cfg->base[5] = 0; 664 bar->n = 1; 665 bar->size0 = func == 0 ? 0x200 : 0x100; /* OHCI/EHCI */ 666 bar->size1 = 0; 667 bar->size2 = 0; 668 bar->size3 = 0; 669 break; 670 default: 671 cfg->base[0] = htol32(sb_base(R_REG(osh, &sb->sbadmatch0))); 672 cfg->base[1] = htol32(sb_base(R_REG(osh, &sb->sbadmatch1))); 673 cfg->base[2] = htol32(sb_base(R_REG(osh, &sb->sbadmatch2))); 674 cfg->base[3] = htol32(sb_base(R_REG(osh, &sb->sbadmatch3))); 675 cfg->base[4] = 0; 676 cfg->base[5] = 0; 677 bar->n = (R_REG(osh, &sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT; 678 bar->size0 = sb_size(R_REG(osh, &sb->sbadmatch0)); 679 bar->size1 = sb_size(R_REG(osh, &sb->sbadmatch1)); 680 bar->size2 = sb_size(R_REG(osh, &sb->sbadmatch2)); 681 bar->size3 = sb_size(R_REG(osh, &sb->sbadmatch3)); 682 break; 683 } 684} 685 686/* 687 * Construct PCI config spaces for SB cores so that they 688 * can be accessed as if they were PCI devices. 689 */ 690void __init 691sbpci_init_cores(sb_t *sbh) 692{ 693 uint chiprev, coreidx, i; 694 sbconfig_t *sb; 695 pci_config_regs *cfg, *pci; 696 sb_bar_cfg_t *bar; 697 void *regs; 698 osl_t *osh; 699 uint16 vendor, device; 700 uint16 coreid; 701 uint8 class, subclass, progif; 702 uint dev; 703 uint8 header; 704 uint func; 705 706 chiprev = sb_chiprev(sbh); 707 coreidx = sb_coreidx(sbh); 708 709 osh = sb_osh(sbh); 710 711 /* Scan the SB bus */ 712 bzero(sb_config_regs, sizeof(sb_config_regs)); 713 bzero(sb_bar_cfg, sizeof(sb_bar_cfg)); 714 bzero(sb_pci_cfg, sizeof(sb_pci_cfg)); 715 memset(&sb_pci_null, -1, sizeof(sb_pci_null)); 716 cfg = sb_config_regs; 717 bar = sb_bar_cfg; 718 for (dev = 0; dev < SB_MAXCORES; dev ++) { 719 /* Check if the core exists */ 720 if (!(regs = sb_setcoreidx(sbh, dev))) 721 continue; 722 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); 723 724 /* Check if this core is banned */ 725 coreid = sb_coreid(sbh); 726 for (i = 0; i < pci_banned; i++) 727 if (coreid == pci_ban[i]) 728 break; 729 if (i < pci_banned) 730 continue; 731 732 for (func = 0; func < MAXFUNCS; ++func) { 733 /* Make sure we won't go beyond the limit */ 734 if (cfg >= &sb_config_regs[SB_MAXCORES]) { 735 printf("PCI: too many emulated devices\n"); 736 goto done; 737 } 738 739 /* Convert core id to pci id */ 740 if (sb_corepciid(sbh, func, &vendor, &device, &class, &subclass, 741 &progif, &header)) 742 continue; 743 744 /* 745 * Differentiate real PCI config from emulated. 746 * non zero 'pci' indicate there is a real PCI config space 747 * for this device. 748 */ 749 switch (device) { 750 case BCM47XX_GIGETH_ID: 751 pci = (pci_config_regs *)((uint32)regs + 0x800); 752 break; 753 case BCM47XX_SATAXOR_ID: 754 pci = (pci_config_regs *)((uint32)regs + 0x400); 755 break; 756 case BCM47XX_ATA100_ID: 757 pci = (pci_config_regs *)((uint32)regs + 0x800); 758 break; 759 default: 760 pci = NULL; 761 break; 762 } 763 /* Supported translations */ 764 cfg->vendor = htol16(vendor); 765 cfg->device = htol16(device); 766 cfg->rev_id = chiprev; 767 cfg->prog_if = progif; 768 cfg->sub_class = subclass; 769 cfg->base_class = class; 770 cfg->header_type = header; 771 sbpci_init_regions(sbh, func, cfg, bar); 772 /* Save core interrupt flag */ 773 cfg->int_pin = R_REG(osh, &sb->sbtpsflag) & SBTPS_NUM0_MASK; 774 /* Save core interrupt assignment */ 775 cfg->int_line = sb_irq(sbh); 776 /* Indicate there is no SROM */ 777 *((uint32 *) &cfg->sprom_control) = 0xffffffff; 778 779 /* Point to the PCI config spaces */ 780 sb_pci_cfg[dev][func].emu = cfg; 781 sb_pci_cfg[dev][func].pci = pci; 782 sb_pci_cfg[dev][func].bar = bar; 783 cfg ++; 784 bar ++; 785 } 786 } 787 788done: 789 sb_setcoreidx(sbh, coreidx); 790} 791 792/* 793 * Initialize PCI core and construct PCI config spaces for SB cores. 794 * Must propagate sbpci_init_pci() return value to the caller to let 795 * them know the PCI core initialization status. 796 */ 797int __init 798sbpci_init(sb_t *sbh) 799{ 800 int status = sbpci_init_pci(sbh); 801 sbpci_init_cores(sbh); 802 return status; 803} 804