2 * Low-Level PCI and SB support for BCM47xx
4 * Copyright 2004, Broadcom Corporation
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.
21 #include <bcmendian.h>
27 /* Can free sbpci_init() memory after boot */
32 /* Emulated configuration space */
33 static pci_config_regs sb_config_regs[SB_MAXCORES];
36 static uint16 pci_ban[32] = { 0 };
37 static uint pci_banned = 0;
40 static bool cardbus = FALSE;
42 /* Disable PCI host core */
43 static bool pci_disabled = FALSE;
46 * Functions for accessing external PCI configuration space
49 /* Assume one-hot slot wiring */
50 #define PCI_SLOT_MAX 16
53 config_cmd(void *sbh, uint bus, uint dev, uint func, uint off)
59 /* CardBusMode supports only one device */
60 if (cardbus && dev > 1)
63 coreidx = sb_coreidx(sbh);
64 regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0);
66 /* Type 0 transaction */
68 /* Skip unwired slots */
69 if (dev < PCI_SLOT_MAX) {
70 /* Slide the PCI window to the appropriate slot */
71 W_REG(®s->sbtopci1, SBTOPCI_CFG0 | ((1 << (dev + 16)) & SBTOPCI1_MASK));
72 addr = SB_PCI_CFG | ((1 << (dev + 16)) & ~SBTOPCI1_MASK) |
73 (func << 8) | (off & ~3);
77 /* Type 1 transaction */
79 W_REG(®s->sbtopci1, SBTOPCI_CFG1);
80 addr = SB_PCI_CFG | (bus << 16) | (dev << 11) | (func << 8) | (off & ~3);
83 sb_setcoreidx(sbh, coreidx);
89 extpci_read_config(void *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
91 uint32 addr, *reg = NULL, val;
95 !(addr = config_cmd(sbh, bus, dev, func, off)) ||
96 !(reg = (uint32 *) REG_MAP(addr, len)) ||
100 val >>= 8 * (off & 3);
102 *((uint32 *) buf) = val;
104 *((uint16 *) buf) = (uint16) val;
106 *((uint8 *) buf) = (uint8) val;
117 extpci_write_config(void *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
119 uint32 addr, *reg = NULL, val;
123 !(addr = config_cmd(sbh, bus, dev, func, off)) ||
124 !(reg = (uint32 *) REG_MAP(addr, len)) ||
129 val = *((uint32 *) buf);
131 val &= ~(0xffff << (8 * (off & 3)));
132 val |= *((uint16 *) buf) << (8 * (off & 3));
133 } else if (len == 1) {
134 val &= ~(0xff << (8 * (off & 3)));
135 val |= *((uint8 *) buf) << (8 * (off & 3));
149 * Functions for accessing translated SB configuration space
153 sb_read_config(void *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
155 pci_config_regs *cfg;
157 if (dev >= SB_MAXCORES || (off + len) > sizeof(pci_config_regs))
159 cfg = &sb_config_regs[dev];
161 ASSERT(ISALIGNED(off, len));
162 ASSERT(ISALIGNED(buf, len));
165 *((uint32 *) buf) = ltoh32(*((uint32 *)((ulong) cfg + off)));
167 *((uint16 *) buf) = ltoh16(*((uint16 *)((ulong) cfg + off)));
169 *((uint8 *) buf) = *((uint8 *)((ulong) cfg + off));
177 sb_write_config(void *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
182 pci_config_regs *cfg;
184 if (dev >= SB_MAXCORES || (off + len) > sizeof(pci_config_regs))
186 cfg = &sb_config_regs[dev];
188 ASSERT(ISALIGNED(off, len));
189 ASSERT(ISALIGNED(buf, len));
191 /* Emulate BAR sizing */
192 if (off >= OFFSETOF(pci_config_regs, base[0]) && off <= OFFSETOF(pci_config_regs, base[3]) &&
193 len == 4 && *((uint32 *) buf) == ~0) {
194 coreidx = sb_coreidx(sbh);
195 if ((regs = sb_setcoreidx(sbh, dev))) {
196 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
197 /* Highest numbered address match register */
198 n = (R_REG(&sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT;
199 if (off == OFFSETOF(pci_config_regs, base[0]))
200 cfg->base[0] = ~(sb_size(R_REG(&sb->sbadmatch0)) - 1);
201 else if (off == OFFSETOF(pci_config_regs, base[1]) && n >= 1)
202 cfg->base[1] = ~(sb_size(R_REG(&sb->sbadmatch1)) - 1);
203 else if (off == OFFSETOF(pci_config_regs, base[2]) && n >= 2)
204 cfg->base[2] = ~(sb_size(R_REG(&sb->sbadmatch2)) - 1);
205 else if (off == OFFSETOF(pci_config_regs, base[3]) && n >= 3)
206 cfg->base[3] = ~(sb_size(R_REG(&sb->sbadmatch3)) - 1);
208 sb_setcoreidx(sbh, coreidx);
213 *((uint32 *)((ulong) cfg + off)) = htol32(*((uint32 *) buf));
215 *((uint16 *)((ulong) cfg + off)) = htol16(*((uint16 *) buf));
217 *((uint8 *)((ulong) cfg + off)) = *((uint8 *) buf);
225 sbpci_read_config(void *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
228 return sb_read_config(sbh, bus, dev, func, off, buf, len);
230 return extpci_read_config(sbh, bus, dev, func, off, buf, len);
234 sbpci_write_config(void *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
237 return sb_write_config(sbh, bus, dev, func, off, buf, len);
239 return extpci_write_config(sbh, bus, dev, func, off, buf, len);
243 sbpci_ban(uint16 core)
245 if (pci_banned < ARRAYSIZE(pci_ban))
246 pci_ban[pci_banned++] = core;
248 //#define CT4712_WR 1 /* Workaround for 4712 */
251 sbpci_init(void *sbh)
253 uint chip, chiprev, chippkg, coreidx, host, i;
257 pci_config_regs *cfg;
263 uint8 class, subclass, progif;
265 uint32 sbips_int_mask[] = { 0, SBIPS_INT1_MASK, SBIPS_INT2_MASK, SBIPS_INT3_MASK, SBIPS_INT4_MASK };
266 uint32 sbips_int_shift[] = { 0, 0, SBIPS_INT2_SHIFT, SBIPS_INT3_SHIFT, SBIPS_INT4_SHIFT };
269 chiprev = sb_chiprev(sbh);
270 chippkg = sb_chippkg(sbh);
271 coreidx = sb_coreidx(sbh);
273 if (!(pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0)))
275 sb_core_reset(sbh, 0);
278 if(nvram_match("boardtype", "bcm94710dev") || nvram_match("boardtype", "bcm94710ap")|| nvram_match("boardtype", "bcm94710r4")|| nvram_match("boardtype", "bcm94710r4")|| nvram_match("boardtype", "bcm95365r"))
283 boardflags = (uint32) getintvar(NULL, "boardflags");
285 if ((chip == BCM4310_DEVICE_ID) && (chiprev == 0))
289 * The 200-pin BCM4712 package does not bond out PCI. Even when
290 * PCI is bonded out, some boards may leave the pins
293 if (((chip == BCM4712_DEVICE_ID) && (chippkg == BCM4712SMALL_PKG_ID)) ||
294 (boardflags & BFL_NOPCI) || CT4712_WR)
298 * If the PCI core should not be touched (disabled, not bonded
299 * out, or pins floating), do not even attempt to access core
300 * registers. Otherwise, try to determine if it is in host
306 host = !BUSPROBE(val, &pci->control);
309 /* Disable PCI interrupts in client mode */
310 sb = (sbconfig_t *)((ulong) pci + SBCONFIGOFF);
311 W_REG(&sb->sbintvec, 0);
313 /* Disable the PCI bridge in client mode */
315 printf("PCI: Disabled\n");
317 /* Reset the external PCI bus and enable the clock */
318 W_REG(&pci->control, 0x5); /* enable the tristate drivers */
319 W_REG(&pci->control, 0xd); /* enable the PCI clock */
320 OSL_DELAY(150); /* delay > 100 us */
321 W_REG(&pci->control, 0xf); /* deassert PCI reset */
322 W_REG(&pci->arbcontrol, PCI_INT_ARB); /* use internal arbiter */
323 OSL_DELAY(1); /* delay 1 us */
325 /* Enable CardBusMode */
326 cardbus = nvram_match("cardbus", "1");
328 printf("PCI: Enabling CardBus\n");
329 /* GPIO 1 resets the CardBus device on bcm94710ap */
330 sb_gpioout(sbh, 1, 1);
331 sb_gpioouten(sbh, 1, 1);
332 W_REG(&pci->sprom[0], R_REG(&pci->sprom[0]) | 0x400);
335 /* 64 MB I/O access window */
336 W_REG(&pci->sbtopci0, SBTOPCI_IO);
337 /* 64 MB configuration access window */
338 W_REG(&pci->sbtopci1, SBTOPCI_CFG0);
339 /* 1 GB memory access window */
340 W_REG(&pci->sbtopci2, SBTOPCI_MEM | SB_PCI_DMA);
342 /* Enable PCI bridge BAR0 prefetch and burst */
344 sbpci_write_config(sbh, 1, 0, 0, PCI_CFG_CMD, &val, sizeof(val));
346 /* Enable PCI interrupts */
347 W_REG(&pci->intmask, PCI_INTA);
350 /* Scan the SB bus */
351 bzero(sb_config_regs, sizeof(sb_config_regs));
352 for (cfg = sb_config_regs; cfg < &sb_config_regs[SB_MAXCORES]; cfg++) {
353 cfg->vendor = 0xffff;
354 if (!(regs = sb_setcoreidx(sbh, cfg - sb_config_regs)))
356 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
358 /* Read ID register and parse vendor and core */
359 val = R_REG(&sb->sbidhigh);
360 vendor = (val & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT;
361 core = (val & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
364 /* Check if this core is banned */
365 for (i = 0; i < pci_banned; i++)
366 if (core == pci_ban[i])
371 /* Known vendor translations */
374 vendor = VENDOR_BROADCOM;
378 /* Determine class based on known core codes */
381 class = PCI_CLASS_NET;
382 subclass = PCI_NET_ETHER;
383 core = BCM47XX_ILINE_ID;
386 class = PCI_CLASS_NET;
387 subclass = PCI_NET_ETHER;
388 core = BCM4610_ILINE_ID;
391 class = PCI_CLASS_NET;
392 subclass = PCI_NET_ETHER;
393 core = BCM47XX_ENET_ID;
397 class = PCI_CLASS_MEMORY;
398 subclass = PCI_MEMORY_RAM;
401 class = PCI_CLASS_BRIDGE;
402 subclass = PCI_BRIDGE_PCI;
406 class = PCI_CLASS_CPU;
407 subclass = PCI_CPU_MIPS;
410 class = PCI_CLASS_COMM;
411 subclass = PCI_COMM_MODEM;
412 core = BCM47XX_V90_ID;
415 class = PCI_CLASS_SERIAL;
416 subclass = PCI_SERIAL_USB;
417 progif = 0x10; /* OHCI */
418 core = BCM47XX_USB_ID;
421 class = PCI_CLASS_SERIAL;
422 subclass = PCI_SERIAL_USB;
423 progif = 0x10; /* OHCI */
424 core = BCM47XX_USBH_ID;
427 class = PCI_CLASS_SERIAL;
428 subclass = PCI_SERIAL_USB;
429 core = BCM47XX_USBD_ID;
432 class = PCI_CLASS_CRYPT;
433 subclass = PCI_CRYPT_NETWORK;
434 core = BCM47XX_IPSEC_ID;
438 class = PCI_CLASS_MEMORY;
439 subclass = PCI_MEMORY_FLASH;
442 class = PCI_CLASS_NET;
443 subclass = PCI_NET_OTHER;
444 /* Let an nvram variable override this */
445 sprintf(varname, "wl%did", wlidx);
447 if ((core = getintvar(NULL, varname)) == 0) {
448 if (chip == BCM4712_DEVICE_ID) {
449 if (chippkg == BCM4712SMALL_PKG_ID)
450 core = BCM4306_D11G_ID;
452 core = BCM4306_D11DUAL_ID;
455 core = BCM4310_D11B_ID;
461 class = subclass = progif = 0xff;
465 /* Supported translations */
466 cfg->vendor = htol16(vendor);
467 cfg->device = htol16(core);
468 cfg->rev_id = chiprev;
469 cfg->prog_if = progif;
470 cfg->sub_class = subclass;
471 cfg->base_class = class;
472 cfg->base[0] = htol32(sb_base(R_REG(&sb->sbadmatch0)));
473 cfg->base[1] = htol32(sb_base(R_REG(&sb->sbadmatch1)));
474 cfg->base[2] = htol32(sb_base(R_REG(&sb->sbadmatch2)));
475 cfg->base[3] = htol32(sb_base(R_REG(&sb->sbadmatch3)));
478 if (class == PCI_CLASS_BRIDGE && subclass == PCI_BRIDGE_PCI)
479 cfg->header_type = PCI_HEADER_BRIDGE;
481 cfg->header_type = PCI_HEADER_NORMAL;
482 /* Save core interrupt flag */
483 cfg->int_pin = R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK;
484 /* Default to MIPS shared interrupt 0 */
486 /* MIPS sbipsflag maps core interrupt flags to interrupts 1 through 4 */
487 if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
488 (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
489 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
490 val = R_REG(&sb->sbipsflag);
491 for (cfg->int_line = 1; cfg->int_line <= 4; cfg->int_line++) {
492 if (((val & sbips_int_mask[cfg->int_line]) >> sbips_int_shift[cfg->int_line]) == cfg->int_pin)
495 if (cfg->int_line > 4)
499 *((uint32 *) &cfg->sprom_control) = 0xffffffff;
502 sb_setcoreidx(sbh, coreidx);
507 sbpci_check(void *sbh)
512 uint32 buf[64], *ptr, i;
516 coreidx = sb_coreidx(sbh);
517 pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0);
519 /* Clear the test array */
520 pa = (ulong) DMA_MAP(NULL, buf, sizeof(buf), DMA_RX, NULL);
521 ptr = (uint32 *) OSL_UNCACHED(&buf[0]);
522 memset(ptr, 0, sizeof(buf));
524 /* Point PCI window 1 to memory */
525 sbtopci1 = R_REG(&pci->sbtopci1);
526 W_REG(&pci->sbtopci1, SBTOPCI_MEM | (pa & SBTOPCI1_MASK));
528 /* Fill the test array via PCI window 1 */
529 ptr = (uint32 *) REG_MAP(SB_PCI_CFG + (pa & ~SBTOPCI1_MASK), sizeof(buf));
530 for (i = 0; i < ARRAYSIZE(buf); i++) {
531 for (j = 0; j < 2; j++);
536 /* Restore PCI window 1 */
537 W_REG(&pci->sbtopci1, sbtopci1);
539 /* Check the test array */
540 DMA_UNMAP(NULL, pa, sizeof(buf), DMA_RX, NULL);
541 ptr = (uint32 *) OSL_UNCACHED(&buf[0]);
542 for (i = 0; i < ARRAYSIZE(buf); i++) {
547 /* Change the clock if the test fails */
548 if (i < ARRAYSIZE(buf)) {
552 printf("PCI: Test failed at %d MHz\n", (cur + 500000) / 1000000);
553 for (req = 104000000; req < 176000000; req += 4000000) {
554 printf("PCI: Resetting to %d MHz\n", (req + 500000) / 1000000);
555 /* This will only reset if the clocks are valid and have changed */
556 sb_mips_setclock(sbh, req, 0, 0);
558 /* Should not reach here */
562 sb_setcoreidx(sbh, coreidx);