Broadcom SDK and wireless driver: another attempt to update to ver. 5.10.147.0
[tomato.git] / release / src-rt / shared / hndpci.c
blobafd2ba674747175bd8e88d72054f35d640eb8095
1 /*
2 * Low-Level PCI and SI support for BCM47xx
4 * Copyright (C) 2009, 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.
12 * $Id: hndpci.c,v 1.36.2.8 2009/06/16 22:41:34 Exp $
15 #include <typedefs.h>
16 #include <osl.h>
17 #include <pcicfg.h>
18 #include <bcmdevs.h>
19 #include <hndsoc.h>
20 #include <bcmutils.h>
21 #include <siutils.h>
22 #include <pci_core.h>
23 #include <pcie_core.h>
24 #include <bcmendian.h>
25 #include <bcmnvram.h>
26 #include <hndcpu.h>
27 #include <hndpci.h>
28 #include <nicpci.h>
30 /* For now we need some real Silicon Backplane utils */
31 #include "siutils_priv.h"
33 /* debug/trace */
34 #ifdef BCMDBG_PCI
35 #define PCI_MSG(args) printf args
36 #else
37 #define PCI_MSG(args)
38 #endif
40 /* to free some function memory after boot */
41 #ifndef linux
42 #define __init
43 #endif /* linux */
45 /* Emulated configuration space */
46 typedef struct {
47 int n;
48 uint size[PCI_BAR_MAX];
49 } si_bar_cfg_t;
50 static pci_config_regs si_config_regs[SI_MAXCORES];
51 static si_bar_cfg_t si_bar_cfg[SI_MAXCORES];
53 /* Links to emulated and real PCI configuration spaces */
54 #define MAXFUNCS 2
55 typedef struct {
56 pci_config_regs *emu; /* emulated PCI config */
57 pci_config_regs *pci; /* real PCI config */
58 si_bar_cfg_t *bar; /* region sizes */
59 } si_pci_cfg_t;
60 static si_pci_cfg_t si_pci_cfg[SI_MAXCORES][MAXFUNCS];
62 /* Special emulated config space for non-existing device */
63 static pci_config_regs si_pci_null = { 0xffff, 0xffff };
65 /* Banned cores */
66 static uint16 pci_ban[SI_MAXCORES] = { 0 };
67 static uint pci_banned = 0;
69 /* CardBus mode */
70 static bool cardbus = FALSE;
72 /* Disable PCI host core */
73 static bool pci_disabled = FALSE;
75 /* Host bridge slot #, default to 0 */
76 static uint8 pci_hbslot = 0;
78 /* Internal macros */
79 #define PCI_SLOTAD_MAP 16 /* SLOT<n> mapps to AD<n+16> */
80 #define PCI_HBSBCFG_REV 8 /* MIN corerev to access host bridge PCI cfg space from SB */
82 /* Functions for accessing external PCI configuration space, Assume one-hot slot wiring */
83 #define PCI_SLOT_MAX 16 /* Max. PCI Slots */
85 static uint32
86 config_cmd(si_t *sih, uint bus, uint dev, uint func, uint off)
88 uint coreidx;
89 sbpciregs_t *pci;
90 uint32 addr = 0, *sbtopci1;
91 osl_t *osh;
93 /* CardBusMode supports only one device */
94 if (cardbus && dev > 1)
95 return 0;
97 osh = si_osh(sih);
99 coreidx = si_coreidx(sih);
100 pci = (sbpciregs_t *)si_setcore(sih, PCI_CORE_ID, 0);
102 if (pci) {
103 sbtopci1 = &pci->sbtopci1;
104 } else {
105 sbpcieregs_t *pcie;
107 pcie = (sbpcieregs_t *)si_setcore(sih, PCIE_CORE_ID, 0);
109 /* Issue config commands only when the data link is up (atleast
110 * one external pcie device is present).
112 if (pcie && (dev < 2) &&
113 (pcie_readreg(osh, pcie, PCIE_PCIEREGS,
114 PCIE_DLLP_LSREG) & PCIE_DLLP_LSREG_LINKUP)) {
115 sbtopci1 = &pcie->sbtopcie1;
116 } else {
117 si_setcoreidx(sih, coreidx);
118 return 0;
123 /* Type 0 transaction */
124 if (bus == 1) {
125 /* Skip unwired slots */
126 if (dev < PCI_SLOT_MAX) {
127 /* Slide the PCI window to the appropriate slot */
128 if (pci) {
129 uint32 win;
131 win = (SBTOPCI_CFG0 |
132 ((1 << (dev + PCI_SLOTAD_MAP)) & SBTOPCI1_MASK));
133 W_REG(osh, sbtopci1, win);
134 addr = (SI_PCI_CFG |
135 ((1 << (dev + PCI_SLOTAD_MAP)) & ~SBTOPCI1_MASK) |
136 (func << PCICFG_FUN_SHIFT) |
137 (off & ~3));
138 } else {
139 W_REG(osh, sbtopci1, SBTOPCI_CFG0);
140 addr = (SI_PCI_CFG |
141 (dev << PCIECFG_SLOT_SHIFT) |
142 (func << PCIECFG_FUN_SHIFT) |
143 (off & ~3));
146 } else {
147 /* Type 1 transaction */
148 W_REG(osh, sbtopci1, SBTOPCI_CFG1);
149 addr = (SI_PCI_CFG |
150 (pci ? PCI_CONFIG_ADDR(bus, dev, func, (off & ~3)) :
151 PCIE_CONFIG_ADDR((bus - 1), dev, func, (off & ~3))));
154 si_setcoreidx(sih, coreidx);
156 return addr;
160 * Read host bridge PCI config registers from Silicon Backplane ( >= rev8 ).
162 * It returns TRUE to indicate that access to the host bridge's pci config
163 * from SI is ok, and values in 'addr' and 'val' are valid.
165 * It can only read registers at multiple of 4-bytes. Callers must pick up
166 * needed bytes from 'val' based on 'off' value. Value in 'addr' reflects
167 * the register address where value in 'val' is read.
169 static bool
170 si_pcihb_read_config(si_t *sih, uint bus, uint dev, uint func, uint off, uint32 **addr,
171 uint32 *val)
173 sbpciregs_t *pci;
174 osl_t *osh;
175 uint coreidx;
176 bool ret = FALSE;
178 /* sanity check */
179 ASSERT(bus == 1);
180 ASSERT(dev == pci_hbslot);
182 /* we support only two functions on device 0 */
183 if (func > 1)
184 return FALSE;
186 osh = si_osh(sih);
188 /* read pci config when core rev >= 8 */
189 coreidx = si_coreidx(sih);
190 pci = (sbpciregs_t *)si_setcore(sih, PCI_CORE_ID, 0);
191 if (pci) {
192 if (si_corerev(sih) >= PCI_HBSBCFG_REV) {
193 *addr = (uint32 *)&pci->pcicfg[func][off >> 2];
194 *val = R_REG(osh, *addr);
195 ret = TRUE;
197 } else {
198 sbpcieregs_t *pcie;
200 /* read pcie config */
201 pcie = (sbpcieregs_t *)si_setcore(sih, PCIE_CORE_ID, 0);
202 if (pcie != NULL) {
203 /* accesses to config registers with offsets >= 256
204 * requires indirect access.
206 if (off >= 256)
207 *val = pcie_readreg(osh, pcie, PCIE_CONFIGREGS,
208 PCIE_CONFIG_INDADDR(func, off));
209 else {
210 *addr = (uint32 *)&pcie->pciecfg[func][off >> 2];
211 *val = R_REG(osh, *addr);
213 ret = TRUE;
217 si_setcoreidx(sih, coreidx);
219 return ret;
223 extpci_read_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
225 uint32 addr = 0, *reg = NULL, val;
226 int ret = 0;
229 * Set value to -1 when:
230 * flag 'pci_disabled' is true;
231 * value of 'addr' is zero;
232 * REG_MAP() fails;
233 * BUSPROBE() fails;
235 if (pci_disabled)
236 val = 0xffffffff;
237 else if (bus == 1 && dev == pci_hbslot) {
238 if (!si_pcihb_read_config(sih, bus, dev, func, off, &reg, &val))
239 return -1;
240 } else if (((addr = config_cmd(sih, bus, dev, func, off)) == 0) ||
241 ((reg = (uint32 *)REG_MAP(addr, len)) == 0) ||
242 (BUSPROBE(val, reg) != 0)) {
243 PCI_MSG(("%s: Failed to read!\n", __FUNCTION__));
244 val = 0xffffffff;
247 PCI_MSG(("%s: 0x%x <= 0x%p(0x%x), len %d, off 0x%x, buf 0x%p\n",
248 __FUNCTION__, val, reg, addr, len, off, buf));
250 val >>= 8 * (off & 3);
251 if (len == 4)
252 *((uint32 *)buf) = val;
253 else if (len == 2)
254 *((uint16 *)buf) = (uint16) val;
255 else if (len == 1)
256 *((uint8 *)buf) = (uint8) val;
257 else
258 ret = -1;
260 if (reg && addr)
261 REG_UNMAP(reg);
263 return ret;
267 extpci_write_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
269 osl_t *osh;
270 uint32 addr = 0, *reg = NULL, val;
271 int ret = 0;
273 osh = si_osh(sih);
276 * Ignore write attempt when:
277 * flag 'pci_disabled' is true;
278 * value of 'addr' is zero;
279 * REG_MAP() fails;
280 * BUSPROBE() fails;
282 if (pci_disabled)
283 return 0;
284 else if (bus == 1 && dev == pci_hbslot) {
285 if (!si_pcihb_read_config(sih, bus, dev, func, off, &reg, &val))
286 return -1;
287 } else if (((addr = config_cmd(sih, bus, dev, func, off)) == 0) ||
288 ((reg = (uint32 *)REG_MAP(addr, len)) == 0) ||
289 (BUSPROBE(val, reg) != 0)) {
290 PCI_MSG(("%s: Failed to write!\n", __FUNCTION__));
291 goto done;
294 if (len == 4)
295 val = *((uint32 *)buf);
296 else if (len == 2) {
297 val &= ~(0xffff << (8 * (off & 3)));
298 val |= *((uint16 *)buf) << (8 * (off & 3));
299 } else if (len == 1) {
300 val &= ~(0xff << (8 * (off & 3)));
301 val |= *((uint8 *)buf) << (8 * (off & 3));
302 } else {
303 ret = -1;
304 goto done;
307 PCI_MSG(("%s: 0x%x => 0x%p\n", __FUNCTION__, val, reg));
309 if (bus == 1 && dev == pci_hbslot && reg == NULL) {
310 sbpcieregs_t *pcie;
311 uint coreidx;
313 coreidx = si_coreidx(sih);
315 /* read pcie config */
316 pcie = (sbpcieregs_t *)si_setcore(sih, PCIE_CORE_ID, 0);
317 if (pcie != NULL)
318 /* accesses to config registers with offsets >= 256
319 * requires indirect access.
321 pcie_writereg(osh, pcie, PCIE_CONFIGREGS,
322 PCIE_CONFIG_INDADDR(func, off), val);
324 si_setcoreidx(sih, coreidx);
325 } else {
326 W_REG(osh, reg, val);
328 if ((sih->chip == BCM4716_CHIP_ID) || (sih->chip == BCM4748_CHIP_ID))
329 (void)R_REG(osh, reg);
332 done:
333 if (reg && addr)
334 REG_UNMAP(reg);
336 return ret;
340 * Must access emulated PCI configuration at these locations even when
341 * the real PCI config space exists and is accessible.
343 * PCI_CFG_VID (0x00)
344 * PCI_CFG_DID (0x02)
345 * PCI_CFG_PROGIF (0x09)
346 * PCI_CFG_SUBCL (0x0a)
347 * PCI_CFG_BASECL (0x0b)
348 * PCI_CFG_HDR (0x0e)
349 * PCI_CFG_INT (0x3c)
350 * PCI_CFG_PIN (0x3d)
352 #define FORCE_EMUCFG(off, len) \
353 ((off == PCI_CFG_VID) || (off == PCI_CFG_DID) || \
354 (off == PCI_CFG_PROGIF) || \
355 (off == PCI_CFG_SUBCL) || (off == PCI_CFG_BASECL) || \
356 (off == PCI_CFG_HDR) || \
357 (off == PCI_CFG_INT) || (off == PCI_CFG_PIN))
359 /* Sync the emulation registers and the real PCI config registers. */
360 static void
361 si_pcid_read_config(si_t *sih, uint coreidx, si_pci_cfg_t *cfg, uint off, uint len)
363 osl_t *osh;
364 uint oldidx;
366 ASSERT(cfg);
367 ASSERT(cfg->emu);
368 ASSERT(cfg->pci);
370 /* decide if real PCI config register access is necessary */
371 if (FORCE_EMUCFG(off, len))
372 return;
374 osh = si_osh(sih);
376 /* access to the real pci config space only when the core is up */
377 oldidx = si_coreidx(sih);
378 si_setcoreidx(sih, coreidx);
379 if (si_iscoreup(sih)) {
380 if (len == 4)
381 *(uint32 *)((ulong)cfg->emu + off) =
382 htol32(R_REG(osh, (uint32 *)((ulong)cfg->pci + off)));
383 else if (len == 2)
384 *(uint16 *)((ulong)cfg->emu + off) =
385 htol16(R_REG(osh, (uint16 *)((ulong)cfg->pci + off)));
386 else if (len == 1)
387 *(uint8 *)((ulong)cfg->emu + off) =
388 R_REG(osh, (uint8 *)((ulong)cfg->pci + off));
390 si_setcoreidx(sih, oldidx);
393 static void
394 si_pcid_write_config(si_t *sih, uint coreidx, si_pci_cfg_t *cfg, uint off, uint len)
396 osl_t *osh;
397 uint oldidx;
399 ASSERT(cfg);
400 ASSERT(cfg->emu);
401 ASSERT(cfg->pci);
403 osh = si_osh(sih);
405 /* decide if real PCI config register access is necessary */
406 if (FORCE_EMUCFG(off, len))
407 return;
409 /* access to the real pci config space only when the core is up */
410 oldidx = si_coreidx(sih);
411 si_setcoreidx(sih, coreidx);
412 if (si_iscoreup(sih)) {
413 if (len == 4)
414 W_REG(osh, (uint32 *)((ulong)cfg->pci + off),
415 ltoh32(*(uint32 *)((ulong)cfg->emu + off)));
416 else if (len == 2)
417 W_REG(osh, (uint16 *)((ulong)cfg->pci + off),
418 ltoh16(*(uint16 *)((ulong)cfg->emu + off)));
419 else if (len == 1)
420 W_REG(osh, (uint8 *)((ulong)cfg->pci + off),
421 *(uint8 *)((ulong)cfg->emu + off));
423 si_setcoreidx(sih, oldidx);
427 * Functions for accessing translated SI configuration space
429 static int
430 si_read_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
432 pci_config_regs *cfg;
434 if (dev >= SI_MAXCORES || func >= MAXFUNCS || (off + len) > sizeof(pci_config_regs))
435 return -1;
437 cfg = si_pci_cfg[dev][func].emu;
439 ASSERT(ISALIGNED(off, len));
440 ASSERT(ISALIGNED((uintptr)buf, len));
442 /* use special config space if the device does not exist */
443 if (!cfg)
444 cfg = &si_pci_null;
445 /* sync emulation with real PCI config if necessary */
446 else if (si_pci_cfg[dev][func].pci)
447 si_pcid_read_config(sih, dev, &si_pci_cfg[dev][func], off, len);
449 if (len == 4)
450 *((uint32 *)buf) = ltoh32(*((uint32 *)((ulong) cfg + off)));
451 else if (len == 2)
452 *((uint16 *)buf) = ltoh16(*((uint16 *)((ulong) cfg + off)));
453 else if (len == 1)
454 *((uint8 *)buf) = *((uint8 *)((ulong) cfg + off));
455 else
456 return -1;
458 return 0;
461 static int
462 si_write_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
464 uint coreidx;
465 void *regs;
466 pci_config_regs *cfg;
467 osl_t *osh;
468 si_bar_cfg_t *bar;
470 if (dev >= SI_MAXCORES || func >= MAXFUNCS || (off + len) > sizeof(pci_config_regs))
471 return -1;
472 cfg = si_pci_cfg[dev][func].emu;
473 if (!cfg)
474 return -1;
476 ASSERT(ISALIGNED(off, len));
477 ASSERT(ISALIGNED((uintptr)buf, len));
479 osh = si_osh(sih);
481 /* Emulate BAR sizing */
482 if (off >= OFFSETOF(pci_config_regs, base[0]) &&
483 off <= OFFSETOF(pci_config_regs, base[3]) &&
484 len == 4 && *((uint32 *)buf) == ~0) {
485 coreidx = si_coreidx(sih);
486 if ((regs = si_setcoreidx(sih, dev))) {
487 bar = si_pci_cfg[dev][func].bar;
488 /* Highest numbered address match register */
489 if (off == OFFSETOF(pci_config_regs, base[0]))
490 cfg->base[0] = ~(bar->size[0] - 1);
491 else if (off == OFFSETOF(pci_config_regs, base[1]) && bar->n >= 1)
492 cfg->base[1] = ~(bar->size[1] - 1);
493 else if (off == OFFSETOF(pci_config_regs, base[2]) && bar->n >= 2)
494 cfg->base[2] = ~(bar->size[2] - 1);
495 else if (off == OFFSETOF(pci_config_regs, base[3]) && bar->n >= 3)
496 cfg->base[3] = ~(bar->size[3] - 1);
498 si_setcoreidx(sih, coreidx);
499 } else if (len == 4)
500 *((uint32 *)((ulong) cfg + off)) = htol32(*((uint32 *)buf));
501 else if (len == 2)
502 *((uint16 *)((ulong) cfg + off)) = htol16(*((uint16 *)buf));
503 else if (len == 1)
504 *((uint8 *)((ulong) cfg + off)) = *((uint8 *)buf);
505 else
506 return -1;
508 /* sync emulation with real PCI config if necessary */
509 if (si_pci_cfg[dev][func].pci)
510 si_pcid_write_config(sih, dev, &si_pci_cfg[dev][func], off, len);
512 return 0;
516 hndpci_read_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
518 if (bus == 0)
519 return si_read_config(sih, bus, dev, func, off, buf, len);
520 else
521 return extpci_read_config(sih, bus, dev, func, off, buf, len);
525 hndpci_write_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
527 if (bus == 0)
528 return si_write_config(sih, bus, dev, func, off, buf, len);
529 else
530 return extpci_write_config(sih, bus, dev, func, off, buf, len);
533 void
534 hndpci_ban(uint16 core)
536 if (pci_banned < ARRAYSIZE(pci_ban))
537 pci_ban[pci_banned++] = core;
540 /* return cap_offset if requested capability exists in the PCI config space */
541 uint8
542 hndpci_find_pci_capability(si_t *sih, uint bus, uint dev, uint func,
543 uint8 req_cap_id, uchar *buf, uint32 *buflen)
545 uint8 cap_id;
546 uint8 cap_ptr = 0;
547 uint32 bufsize;
548 uint8 byte_val;
550 /* check for Header type 0 */
551 hndpci_read_config(sih, bus, dev, func, PCI_CFG_HDR, &byte_val, sizeof(uint8));
552 if ((byte_val & 0x7f) != PCI_HEADER_NORMAL)
553 return (cap_ptr);
555 /* check if the capability pointer field exists */
556 hndpci_read_config(sih, bus, dev, func, PCI_CFG_STAT, &byte_val, sizeof(uint8));
557 if (!(byte_val & PCI_CAPPTR_PRESENT))
558 return (cap_ptr);
560 /* check if the capability pointer is 0x00 */
561 hndpci_read_config(sih, bus, dev, func, PCI_CFG_CAPPTR, &cap_ptr, sizeof(uint8));
562 if (cap_ptr == 0x00)
563 return (cap_ptr);
565 /* loop thr'u the capability list and see if the requested capabilty exists */
566 hndpci_read_config(sih, bus, dev, func, cap_ptr, &cap_id, sizeof(uint8));
567 while (cap_id != req_cap_id) {
568 hndpci_read_config(sih, bus, dev, func, cap_ptr + 1, &cap_ptr, sizeof(uint8));
569 if (cap_ptr == 0x00)
570 return (cap_ptr);
571 hndpci_read_config(sih, bus, dev, func, cap_ptr, &cap_id, sizeof(uint8));
574 /* found the caller requested capability */
575 if ((buf != NULL) && (buflen != NULL)) {
576 uint8 cap_data;
578 bufsize = *buflen;
579 if (!bufsize)
580 return (cap_ptr);
582 *buflen = 0;
584 /* copy the cpability data excluding cap ID and next ptr */
585 cap_data = cap_ptr + 2;
586 if ((bufsize + cap_data) > SZPCR)
587 bufsize = SZPCR - cap_data;
588 *buflen = bufsize;
589 while (bufsize--) {
590 hndpci_read_config(sih, bus, dev, func, cap_data, buf, sizeof(uint8));
591 cap_data++;
592 buf++;
596 return (cap_ptr);
601 * Initiliaze PCI core.
602 * Return 0 after a successful initialization.
603 * Otherwise return -1 to indicate there is no PCI core and
604 * return 1 to indicate PCI core is disabled.
606 int __init
607 hndpci_init_pci(si_t *sih)
609 uint chip, chiprev, chippkg, host;
610 uint32 boardflags;
611 sbpciregs_t *pci;
612 sbpcieregs_t *pcie = NULL;
613 uint32 val;
614 int ret = 0;
615 char *hbslot;
616 osl_t *osh;
618 chip = sih->chip;
619 chiprev = sih->chiprev;
620 chippkg = sih->chippkg;
622 osh = si_osh(sih);
624 pci = (sbpciregs_t *)si_setcore(sih, PCI_CORE_ID, 0);
625 if (pci == NULL) {
626 pcie = (sbpcieregs_t *)si_setcore(sih, PCIE_CORE_ID, 0);
627 if (pcie == NULL) {
628 printf("PCI: no core\n");
629 pci_disabled = TRUE;
630 return -1;
634 boardflags = (uint32)getintvar(NULL, "boardflags");
637 * The NOPCI boardflag indicates we should not touch the PCI core,
638 * it may not be bonded out or the pins may be floating.
639 * The 200-pin BCM4712 package does not bond out PCI, and routers
640 * based on it did not use the boardflag.
642 if ((boardflags & BFL_NOPCI) ||
643 ((chip == BCM4712_CHIP_ID) &&
644 ((chippkg == BCM4712SMALL_PKG_ID) || (chippkg == BCM4712MID_PKG_ID)))) {
645 pci_disabled = TRUE;
646 host = 0;
647 } else {
648 /* Enable the core */
649 si_core_reset(sih, 0, 0);
651 /* Figure out if it is in host mode */
652 host = !BUSPROBE(val, (pci ? &pci->control : &pcie->control));
655 if (!host) {
656 ret = 1;
658 /* Disable PCI interrupts in client mode */
659 si_setint(sih, -1);
661 /* Disable the PCI bridge in client mode */
662 hndpci_ban(PCI_CORE_ID);
664 /* Make sure the core is disabled */
665 si_core_disable(sih, 0);
667 /* On 4716 (and other AXI chips?) make sure the slave wrapper
668 * is also put in reset.
670 if ((chip == BCM4716_CHIP_ID) || (chip == BCM4748_CHIP_ID)) {
671 uint32 *resetctrl;
673 resetctrl = (uint32 *)OSL_UNCACHED(SI_WRAP_BASE + (9 * SI_CORE_SIZE) +
674 AI_RESETCTRL);
675 W_REG(osh, resetctrl, AIRC_RESET);
678 printf("PCI: Disabled\n");
679 } else {
680 printf("PCI: Initializing host\n");
682 /* Disable PCI SBReqeustTimeout for BCM4785 rev. < 2 */
683 if (chip == BCM4785_CHIP_ID && chiprev < 2) {
684 sbconfig_t *sb;
685 sb = (sbconfig_t *)((ulong) pci + SBCONFIGOFF);
686 AND_REG(osh, &sb->sbimconfiglow, ~0x00000070);
687 sb_commit(sih);
690 if (pci) {
691 /* Reset the external PCI bus and enable the clock */
692 W_REG(osh, &pci->control, 0x5); /* enable tristate drivers */
693 W_REG(osh, &pci->control, 0xd); /* enable the PCI clock */
694 OSL_DELAY(150); /* delay > 100 us */
695 W_REG(osh, &pci->control, 0xf); /* deassert PCI reset */
696 /* Use internal arbiter and park REQ/GRNT at external master 0
697 * We will set it later after the bus has been probed
699 W_REG(osh, &pci->arbcontrol, PCI_INT_ARB);
700 OSL_DELAY(1); /* delay 1 us */
701 } else {
702 printf("PCI: Reset RC\n");
703 OSL_DELAY(3000);
704 W_REG(osh, &pcie->control, PCIE_RST_OE);
705 OSL_DELAY(1000); /* delay 1 ms */
706 W_REG(osh, &pcie->control, PCIE_RST | PCIE_RST_OE);
709 /* Enable CardBusMode */
710 cardbus = getintvar(NULL, "cardbus") == 1;
711 if (cardbus) {
712 printf("PCI: Enabling CardBus\n");
713 /* GPIO 1 resets the CardBus device on bcm94710ap */
714 si_gpioout(sih, 1, 1, GPIO_DRV_PRIORITY);
715 si_gpioouten(sih, 1, 1, GPIO_DRV_PRIORITY);
716 W_REG(osh, &pci->sprom[0], R_REG(osh, &pci->sprom[0]) | 0x400);
719 /* Host bridge slot # nvram overwrite */
720 if ((hbslot = nvram_get("pcihbslot"))) {
721 pci_hbslot = bcm_strtoul(hbslot, NULL, 0);
722 ASSERT(pci_hbslot < PCI_MAX_DEVICES);
725 if (pci) {
726 /* 64 MB I/O access window */
727 W_REG(osh, &pci->sbtopci0, SBTOPCI_IO);
728 /* 64 MB configuration access window */
729 W_REG(osh, &pci->sbtopci1, SBTOPCI_CFG0);
730 /* 1 GB memory access window */
731 W_REG(osh, &pci->sbtopci2, SBTOPCI_MEM | SI_PCI_DMA);
732 } else {
733 uint8 cap_ptr, root_ctrl, root_cap, dev;
734 uint16 val16;
736 /* 64 MB I/O access window. On 4716, use
737 * sbtopcie0 to access the device registers. We
738 * can't use address match 2 (1 GB window) region
739 * as mips can't generate 64-bit address on the
740 * backplane.
742 if ((chip == BCM4716_CHIP_ID) || (chip == BCM4748_CHIP_ID))
743 W_REG(osh, &pcie->sbtopcie0, SBTOPCIE_MEM | SI_PCI_MEM);
744 else
745 W_REG(osh, &pcie->sbtopcie0, SBTOPCIE_IO);
747 /* 64 MB configuration access window */
748 W_REG(osh, &pcie->sbtopcie1, SBTOPCIE_CFG0);
750 /* 1 GB memory access window */
751 W_REG(osh, &pcie->sbtopcie2, SBTOPCIE_MEM | SI_PCI_DMA);
753 /* As per PCI Express Base Spec 1.1 we need to wait for
754 * at least 100 ms from the end of a reset (cold/warm/hot)
755 * before issuing configuration requests to PCI Express
756 * devices.
758 OSL_DELAY(100000);
760 /* If the root port is capable of returning Config Request
761 * Retry Status (CRS) Completion Status to software then
762 * enable the feature.
764 cap_ptr = hndpci_find_pci_capability(sih, 1, pci_hbslot, 0,
765 PCI_CAP_PCIECAP_ID, NULL, NULL);
766 ASSERT(cap_ptr);
768 root_cap = cap_ptr + OFFSETOF(pciconfig_cap_pcie, root_cap);
769 hndpci_read_config(sih, 1, pci_hbslot, 0, root_cap,
770 &val16, sizeof(uint16));
771 if (val16 & PCIE_RC_CRS_VISIBILITY) {
772 /* Enable CRS software visibility */
773 root_ctrl = cap_ptr + OFFSETOF(pciconfig_cap_pcie, root_ctrl);
774 val16 = PCIE_RC_CRS_EN;
775 hndpci_write_config(sih, 1, pci_hbslot, 0, root_ctrl,
776 &val16, sizeof(uint16));
778 /* Initiate a configuration request to read the vendor id
779 * field of the device function's config space header after
780 * 100 ms wait time from the end of Reset. If the device is
781 * not done with its internal initialization, it must at
782 * least return a completion TLP, with a completion status
783 * of "Configuration Request Retry Status (CRS)". The root
784 * complex must complete the request to the host by returning
785 * a read-data value of 0001h for the Vendor ID field and
786 * all 1s for any additional bytes included in the request.
787 * Poll using the config reads for max wait time of 1 sec or
788 * until we receive the successful completion status. Repeat
789 * the procedure for all the devices.
791 for (dev = pci_hbslot + 1; dev < PCI_MAX_DEVICES; dev++) {
792 SPINWAIT((hndpci_read_config(sih, 1, dev, 0,
793 PCI_CFG_VID, &val16, sizeof(val16)),
794 (val16 == 0x1)), 1000000);
795 if (val16 == 0x1)
796 printf("PCI: Broken device in slot %d\n", dev);
801 /* Enable PCI bridge BAR0 memory & master access */
802 val = PCI_CMD_MASTER | PCI_CMD_MEMORY;
803 hndpci_write_config(sih, 1, pci_hbslot, 0, PCI_CFG_CMD, &val, sizeof(val));
805 /* Enable PCI interrupts */
806 if (pci)
807 W_REG(osh, &pci->intmask, PCI_INTA);
808 else
809 W_REG(osh, &pcie->intmask, PCI_INTA);
812 return ret;
815 void
816 hndpci_arb_park(si_t *sih, uint parkid)
818 sbpciregs_t *pci;
819 uint pcirev;
820 uint32 arb;
822 pci = (sbpciregs_t *)si_setcore(sih, PCI_CORE_ID, 0);
823 if ((pci == NULL) || pci_disabled) {
824 /* Should not happen */
825 PCI_MSG(("%s: no PCI core\n", __FUNCTION__));
826 return;
829 pcirev = si_corerev(sih);
831 /* Nothing to do, not supported for these revs */
832 if (pcirev < 8)
833 return;
835 /* Get parkid from NVRAM */
836 if (parkid == PCI_PARK_NVRAM) {
837 parkid = getintvar(NULL, "parkid");
838 if (getvar(NULL, "parkid") == NULL)
839 /* Not present in NVRAM use defaults */
840 parkid = (pcirev >= 11) ? PCI11_PARKID_LAST : PCI_PARKID_LAST;
843 /* Check the parkid is valid, if not set it to default */
844 if (parkid > ((pcirev >= 11) ? PCI11_PARKID_LAST : PCI_PARKID_LAST)) {
845 printf("%s: Invalid parkid %d\n", __FUNCTION__, parkid);
846 parkid = (pcirev >= 11) ? PCI11_PARKID_LAST : PCI_PARKID_LAST;
849 /* Now set the parkid */
850 arb = R_REG(si_osh(sih), &pci->arbcontrol);
851 arb &= ~PCI_PARKID_MASK;
852 arb |= parkid << PCI_PARKID_SHIFT;
853 W_REG(si_osh(sih), &pci->arbcontrol, arb);
854 OSL_DELAY(1);
858 * Get the PCI region address and size information.
860 static void __init
861 hndpci_init_regions(si_t *sih, uint func, pci_config_regs *cfg, si_bar_cfg_t *bar)
863 bool issb = sih->socitype == SOCI_SB;
864 uint i, n;
866 if (si_coreid(sih) == USB20H_CORE_ID) {
867 uint32 base, base1;
869 base = htol32(si_addrspace(sih, 0));
870 if (issb) {
871 base1 = base + 0x800; /* OHCI/EHCI */
872 } else {
873 /* In AI chips EHCI is addrspace 0, OHCI is 1 */
874 base1 = base;
875 base = htol32(si_addrspace(sih, 1));
878 i = bar->n = 1;
879 cfg->base[0] = func == 0 ? base : base1;
880 bar->size[0] = issb ? 0x800 : 0x1000;
881 } else {
882 bar->n = n = si_numaddrspaces(sih);
883 for (i = 0; i < n; i++) {
884 int size = si_addrspacesize(sih, i);
886 if (size) {
887 cfg->base[i] = htol32(si_addrspace(sih, i));
888 bar->size[i] = size;
892 for (; i < PCI_BAR_MAX; i++) {
893 cfg->base[i] = 0;
894 bar->size[i] = 0;
899 * Construct PCI config spaces for SB cores to be accessed as if they were PCI devices.
901 void __init
902 hndpci_init_cores(si_t *sih)
904 uint chiprev, coreidx, i;
905 pci_config_regs *cfg, *pci;
906 si_bar_cfg_t *bar;
907 void *regs;
908 osl_t *osh;
909 uint16 vendor, device;
910 uint16 coreid;
911 uint8 class, subclass, progif;
912 uint dev;
913 uint8 header;
914 uint func;
916 chiprev = sih->chiprev;
917 coreidx = si_coreidx(sih);
919 osh = si_osh(sih);
921 /* Scan the SI bus */
922 bzero(si_config_regs, sizeof(si_config_regs));
923 bzero(si_bar_cfg, sizeof(si_bar_cfg));
924 bzero(si_pci_cfg, sizeof(si_pci_cfg));
925 memset(&si_pci_null, -1, sizeof(si_pci_null));
926 cfg = si_config_regs;
927 bar = si_bar_cfg;
928 for (dev = 0; dev < SI_MAXCORES; dev ++) {
929 /* Check if the core exists */
930 if (!(regs = si_setcoreidx(sih, dev)))
931 continue;
933 /* Check if this core is banned */
934 coreid = si_coreid(sih);
935 for (i = 0; i < pci_banned; i++)
936 if (coreid == pci_ban[i])
937 break;
938 if (i < pci_banned)
939 continue;
941 for (func = 0; func < MAXFUNCS; ++func) {
942 /* Make sure we won't go beyond the limit */
943 if (cfg >= &si_config_regs[SI_MAXCORES]) {
944 printf("PCI: too many emulated devices\n");
945 goto done;
948 /* Convert core id to pci id */
949 if (si_corepciid(sih, func, &vendor, &device, &class, &subclass,
950 &progif, &header))
951 continue;
954 * Differentiate real PCI config from emulated.
955 * non zero 'pci' indicate there is a real PCI config space
956 * for this device.
958 switch (device) {
959 case BCM47XX_GIGETH_ID:
960 pci = (pci_config_regs *)((uint32)regs + 0x800);
961 break;
962 case BCM47XX_SATAXOR_ID:
963 pci = (pci_config_regs *)((uint32)regs + 0x400);
964 break;
965 case BCM47XX_ATA100_ID:
966 pci = (pci_config_regs *)((uint32)regs + 0x800);
967 break;
968 default:
969 pci = NULL;
970 break;
972 /* Supported translations */
973 cfg->vendor = htol16(vendor);
974 cfg->device = htol16(device);
975 cfg->rev_id = chiprev;
976 cfg->prog_if = progif;
977 cfg->sub_class = subclass;
978 cfg->base_class = class;
979 cfg->header_type = header;
980 hndpci_init_regions(sih, func, cfg, bar);
981 /* Save core interrupt flag */
982 cfg->int_pin = si_flag(sih);
983 /* Save core interrupt assignment */
984 cfg->int_line = si_irq(sih);
985 /* Indicate there is no SROM */
986 *((uint32 *)&cfg->sprom_control) = 0xffffffff;
988 /* Point to the PCI config spaces */
989 si_pci_cfg[dev][func].emu = cfg;
990 si_pci_cfg[dev][func].pci = pci;
991 si_pci_cfg[dev][func].bar = bar;
992 cfg ++;
993 bar ++;
997 done:
998 si_setcoreidx(sih, coreidx);
1002 * Initialize PCI core and construct PCI config spaces for SI cores.
1003 * Must propagate hndpci_init_pci() return value to the caller to let
1004 * them know the PCI core initialization status.
1006 int __init
1007 hndpci_init(si_t *sih)
1009 int status = hndpci_init_pci(sih);
1010 hndpci_init_cores(sih);
1011 return status;