Resync with broadcom drivers 5.100.138.20 and utilities.
[tomato.git] / release / src-rt / shared / hndpci.c
blob8c1a356ca70fbbc12d50faf8a18e8ca8966c1295
1 /*
2 * Low-Level PCI and SI support for BCM47xx
4 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $Id: hndpci.c,v 1.49.2.2 2010-11-16 21:44:41 Exp $
21 #include <typedefs.h>
22 #include <osl.h>
23 #include <pcicfg.h>
24 #include <bcmdevs.h>
25 #include <hndsoc.h>
26 #include <bcmutils.h>
27 #include <siutils.h>
28 #include <pci_core.h>
29 #include <pcie_core.h>
30 #include <bcmendian.h>
31 #include <bcmnvram.h>
32 #include <hndcpu.h>
33 #include <hndpci.h>
34 #include <nicpci.h>
35 #include <sbchipc.h>
37 /* For now we need some real Silicon Backplane utils */
38 #include "siutils_priv.h"
40 /* debug/trace */
41 #ifdef BCMDBG_PCI
42 #define PCI_MSG(args) printf args
43 #else
44 #define PCI_MSG(args)
45 #endif
47 /* to free some function memory after boot */
48 #ifndef linux
49 #define __init
50 #endif /* linux */
52 /* Emulated configuration space */
53 typedef struct {
54 int n;
55 uint size[PCI_BAR_MAX];
56 } si_bar_cfg_t;
57 static pci_config_regs si_config_regs[SI_MAXCORES];
58 static si_bar_cfg_t si_bar_cfg[SI_MAXCORES];
60 /* Links to emulated and real PCI configuration spaces */
61 #define MAXFUNCS 2
62 typedef struct {
63 pci_config_regs *emu; /* emulated PCI config */
64 pci_config_regs *pci; /* real PCI config */
65 si_bar_cfg_t *bar; /* region sizes */
66 } si_pci_cfg_t;
67 static si_pci_cfg_t si_pci_cfg[SI_MAXCORES][MAXFUNCS];
69 /* Special emulated config space for non-existing device */
70 static pci_config_regs si_pci_null = { 0xffff, 0xffff };
72 /* Banned cores */
73 static uint16 pci_ban[SI_MAXCORES] = { 0 };
74 static uint pci_banned = 0;
76 /* CardBus mode */
77 static bool cardbus = FALSE;
79 /* The OS's enumerated bus numbers for supported PCI/PCIe core units */
80 static uint pci_busid[SI_PCI_MAXCORES] = { 0, };
82 static uint32 pci_membase_cfg[SI_PCI_MAXCORES] = {
83 SI_PCI_CFG,
86 static uint32 pci_membase[SI_PCI_MAXCORES] = {
87 SI_PCI_DMA,
90 static uint32 pci_membase_1G[SI_PCI_MAXCORES] = {
91 SI_PCI_DMA,
94 /* Disable PCI host core */
95 static bool pci_disabled[SI_PCI_MAXCORES] = { FALSE };
97 /* Host bridge slot #, default to 0 */
98 static uint8 pci_hbslot = 0;
100 /* Internal macros */
101 #define PCI_SLOTAD_MAP 16 /* SLOT<n> mapps to AD<n+16> */
102 #define PCI_HBSBCFG_REV 8 /* MIN corerev to access host bridge PCI cfg space from SB */
104 /* Functions for accessing external PCI configuration space, Assume one-hot slot wiring */
105 #define PCI_SLOT_MAX 16 /* Max. PCI Slots */
107 static void
108 hndpci_set_busid(uint busid)
109 { int i;
111 for (i = 0; i < SI_PCI_MAXCORES; i++) {
112 if (pci_busid[i] == 0) {
113 pci_busid[i] = busid;
114 printf("PCI/PCIe coreunit %d is set to bus %d.\n", i, pci_busid[i]);
115 return;
117 if (busid == pci_busid[i])
118 return;
122 static int
123 hndpci_pci_coreunit(uint bus)
124 { uint i;
126 ASSERT(bus >= 1);
127 for (i = SI_PCI_MAXCORES - 1; i >= 0; i--) {
128 if (pci_busid[i] && bus >= pci_busid[i])
129 return i;
131 return -1;
134 bool
135 hndpci_is_hostbridge(uint bus, uint dev)
136 { uint i;
138 ASSERT(bus >= 1);
139 if (dev != pci_hbslot)
140 return FALSE;
142 for (i = 0; i < SI_PCI_MAXCORES; i++)
143 if (bus == pci_busid[i])
144 return TRUE;
146 return FALSE;
149 uint32 hndpci_get_membase(uint bus)
151 int coreunit;
153 coreunit = hndpci_pci_coreunit(bus);
154 ASSERT(coreunit >= 0);
155 ASSERT(pci_membase[coreunit]);
156 return pci_membase[coreunit];
159 static uint32
160 config_cmd(si_t *sih, uint coreunit, uint bus, uint dev, uint func, uint off)
162 uint coreidx;
163 sbpciregs_t *pci;
164 uint32 addr = 0, *sbtopci1;
165 osl_t *osh;
167 /* CardBusMode supports only one device */
168 if (cardbus && dev > 1)
169 return 0;
171 osh = si_osh(sih);
173 coreidx = si_coreidx(sih);
174 pci = (sbpciregs_t *)si_setcore(sih, PCI_CORE_ID, coreunit);
176 if (pci) {
177 sbtopci1 = &pci->sbtopci1;
178 } else {
179 sbpcieregs_t *pcie;
181 pcie = (sbpcieregs_t *)si_setcore(sih, PCIE_CORE_ID, coreunit);
183 /* Issue config commands only when the data link is up (atleast
184 * one external pcie device is present).
186 if (pcie && (dev < 2) &&
187 (pcie_readreg(osh, pcie, PCIE_PCIEREGS,
188 PCIE_DLLP_LSREG) & PCIE_DLLP_LSREG_LINKUP)) {
189 sbtopci1 = &pcie->sbtopcie1;
190 } else {
191 si_setcoreidx(sih, coreidx);
192 return 0;
197 /* Type 0 transaction */
198 if (!hndpci_is_hostbridge(bus, dev)) {
199 /* Skip unwired slots */
200 if (dev < PCI_SLOT_MAX) {
201 /* Slide the PCI window to the appropriate slot */
202 if (pci) {
203 uint32 win;
205 win = (SBTOPCI_CFG0 |
206 ((1 << (dev + PCI_SLOTAD_MAP)) & SBTOPCI1_MASK));
207 W_REG(osh, sbtopci1, win);
208 addr = (pci_membase_cfg[coreunit] |
209 ((1 << (dev + PCI_SLOTAD_MAP)) & ~SBTOPCI1_MASK) |
210 (func << PCICFG_FUN_SHIFT) |
211 (off & ~3));
212 } else {
213 W_REG(osh, sbtopci1, SBTOPCI_CFG0);
214 addr = (pci_membase_cfg[coreunit] |
215 (dev << PCIECFG_SLOT_SHIFT) |
216 (func << PCIECFG_FUN_SHIFT) |
217 (off & ~3));
220 } else {
221 /* Type 1 transaction */
222 W_REG(osh, sbtopci1, SBTOPCI_CFG1);
223 addr = (pci_membase_cfg[coreunit] |
224 (pci ? PCI_CONFIG_ADDR(bus, dev, func, (off & ~3)) :
225 PCIE_CONFIG_ADDR((bus - 1), dev, func, (off & ~3))));
228 si_setcoreidx(sih, coreidx);
230 return addr;
234 * Read host bridge PCI config registers from Silicon Backplane ( >= rev8 ).
236 * It returns TRUE to indicate that access to the host bridge's pci config
237 * from SI is ok, and values in 'addr' and 'val' are valid.
239 * It can only read registers at multiple of 4-bytes. Callers must pick up
240 * needed bytes from 'val' based on 'off' value. Value in 'addr' reflects
241 * the register address where value in 'val' is read.
243 static bool
244 si_pcihb_read_config(si_t *sih, uint coreunit, uint bus, uint dev, uint func,
245 uint off, uint32 **addr, uint32 *val)
247 sbpciregs_t *pci;
248 osl_t *osh;
249 uint coreidx;
250 bool ret = FALSE;
252 /* sanity check */
253 ASSERT(hndpci_is_hostbridge(bus, dev));
255 /* we support only two functions on device 0 */
256 if (func > 1)
257 return FALSE;
259 osh = si_osh(sih);
261 /* read pci config when core rev >= 8 */
262 coreidx = si_coreidx(sih);
263 pci = (sbpciregs_t *)si_setcore(sih, PCI_CORE_ID, coreunit);
264 if (pci) {
265 if (si_corerev(sih) >= PCI_HBSBCFG_REV) {
266 *addr = (uint32 *)&pci->pcicfg[func][off >> 2];
267 *val = R_REG(osh, *addr);
268 ret = TRUE;
270 } else {
271 sbpcieregs_t *pcie;
273 /* read pcie config */
274 pcie = (sbpcieregs_t *)si_setcore(sih, PCIE_CORE_ID, coreunit);
275 if (pcie != NULL) {
276 /* accesses to config registers with offsets >= 256
277 * requires indirect access.
279 if (off >= 256)
280 *val = pcie_readreg(osh, pcie, PCIE_CONFIGREGS,
281 PCIE_CONFIG_INDADDR(func, off));
282 else {
283 *addr = (uint32 *)&pcie->pciecfg[func][off >> 2];
284 *val = R_REG(osh, *addr);
286 ret = TRUE;
290 si_setcoreidx(sih, coreidx);
292 return ret;
296 extpci_read_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
298 uint32 addr = 0, *reg = NULL, val;
299 int ret = 0;
300 int coreunit = hndpci_pci_coreunit(bus);
302 if (coreunit < 0)
303 return -1;
306 * Set value to -1 when:
307 * flag 'pci_disabled' is true;
308 * value of 'addr' is zero;
309 * REG_MAP() fails;
310 * BUSPROBE() fails;
312 if (pci_disabled[coreunit])
313 val = 0xffffffff;
314 else if (hndpci_is_hostbridge(bus, dev)) {
315 if (!si_pcihb_read_config(sih, coreunit, bus, dev, func, off, &reg, &val))
316 return -1;
317 } else if (((addr = config_cmd(sih, coreunit, bus, dev, func, off)) == 0) ||
318 ((reg = (uint32 *)REG_MAP(addr, len)) == 0) ||
319 (BUSPROBE(val, reg) != 0)) {
320 PCI_MSG(("%s: Failed to read!\n", __FUNCTION__));
321 val = 0xffffffff;
324 PCI_MSG(("%s: 0x%x <= 0x%p(0x%x), len %d, off 0x%x, buf 0x%p\n",
325 __FUNCTION__, val, reg, addr, len, off, buf));
327 val >>= 8 * (off & 3);
328 if (len == 4)
329 *((uint32 *)buf) = val;
330 else if (len == 2)
331 *((uint16 *)buf) = (uint16) val;
332 else if (len == 1)
333 *((uint8 *)buf) = (uint8) val;
334 else
335 ret = -1;
337 if (reg && addr)
338 REG_UNMAP(reg);
340 return ret;
344 extpci_write_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
346 osl_t *osh;
347 uint32 addr = 0, *reg = NULL, val;
348 int ret = 0;
349 bool is_hostbridge;
350 int coreunit = hndpci_pci_coreunit(bus);
352 if (coreunit < 0)
353 return -1;
355 osh = si_osh(sih);
358 * Ignore write attempt when:
359 * flag 'pci_disabled' is true;
360 * value of 'addr' is zero;
361 * REG_MAP() fails;
362 * BUSPROBE() fails;
364 if (pci_disabled[coreunit])
365 return 0;
366 if ((is_hostbridge = hndpci_is_hostbridge(bus, dev))) {
367 if (!si_pcihb_read_config(sih, coreunit, bus, dev, func, off, &reg, &val))
368 return -1;
369 } else if (((addr = config_cmd(sih, coreunit, bus, dev, func, off)) == 0) ||
370 ((reg = (uint32 *)REG_MAP(addr, len)) == 0) ||
371 (BUSPROBE(val, reg) != 0)) {
372 PCI_MSG(("%s: Failed to write!\n", __FUNCTION__));
373 goto done;
376 if (len == 4)
377 val = *((uint32 *)buf);
378 else if (len == 2) {
379 val &= ~(0xffff << (8 * (off & 3)));
380 val |= *((uint16 *)buf) << (8 * (off & 3));
381 } else if (len == 1) {
382 val &= ~(0xff << (8 * (off & 3)));
383 val |= *((uint8 *)buf) << (8 * (off & 3));
384 } else {
385 ret = -1;
386 goto done;
389 PCI_MSG(("%s: 0x%x => 0x%p\n", __FUNCTION__, val, reg));
391 if (is_hostbridge && reg == NULL) {
392 sbpcieregs_t *pcie;
393 uint coreidx;
395 coreidx = si_coreidx(sih);
397 /* read pcie config */
398 pcie = (sbpcieregs_t *)si_setcore(sih, PCIE_CORE_ID, coreunit);
399 if (pcie != NULL)
400 /* accesses to config registers with offsets >= 256
401 * requires indirect access.
403 pcie_writereg(osh, pcie, PCIE_CONFIGREGS,
404 PCIE_CONFIG_INDADDR(func, off), val);
406 si_setcoreidx(sih, coreidx);
407 } else {
408 W_REG(osh, reg, val);
410 if ((CHIPID(sih->chip) == BCM4716_CHIP_ID) ||
411 (CHIPID(sih->chip) == BCM4748_CHIP_ID))
412 (void)R_REG(osh, reg);
416 done:
417 if (reg && addr)
418 REG_UNMAP(reg);
420 return ret;
424 * Must access emulated PCI configuration at these locations even when
425 * the real PCI config space exists and is accessible.
427 * PCI_CFG_VID (0x00)
428 * PCI_CFG_DID (0x02)
429 * PCI_CFG_PROGIF (0x09)
430 * PCI_CFG_SUBCL (0x0a)
431 * PCI_CFG_BASECL (0x0b)
432 * PCI_CFG_HDR (0x0e)
433 * PCI_CFG_INT (0x3c)
434 * PCI_CFG_PIN (0x3d)
436 #define FORCE_EMUCFG(off, len) \
437 ((off == PCI_CFG_VID) || (off == PCI_CFG_DID) || \
438 (off == PCI_CFG_PROGIF) || \
439 (off == PCI_CFG_SUBCL) || (off == PCI_CFG_BASECL) || \
440 (off == PCI_CFG_HDR) || \
441 (off == PCI_CFG_INT) || (off == PCI_CFG_PIN))
443 /* Sync the emulation registers and the real PCI config registers. */
444 static void
445 si_pcid_read_config(si_t *sih, uint coreidx, si_pci_cfg_t *cfg, uint off, uint len)
447 osl_t *osh;
448 uint oldidx;
450 ASSERT(cfg);
451 ASSERT(cfg->emu);
452 ASSERT(cfg->pci);
454 /* decide if real PCI config register access is necessary */
455 if (FORCE_EMUCFG(off, len))
456 return;
458 osh = si_osh(sih);
460 /* access to the real pci config space only when the core is up */
461 oldidx = si_coreidx(sih);
462 si_setcoreidx(sih, coreidx);
463 if (si_iscoreup(sih)) {
464 if (len == 4)
465 *(uint32 *)((ulong)cfg->emu + off) =
466 htol32(R_REG(osh, (uint32 *)((ulong)cfg->pci + off)));
467 else if (len == 2)
468 *(uint16 *)((ulong)cfg->emu + off) =
469 htol16(R_REG(osh, (uint16 *)((ulong)cfg->pci + off)));
470 else if (len == 1)
471 *(uint8 *)((ulong)cfg->emu + off) =
472 R_REG(osh, (uint8 *)((ulong)cfg->pci + off));
474 si_setcoreidx(sih, oldidx);
477 static void
478 si_pcid_write_config(si_t *sih, uint coreidx, si_pci_cfg_t *cfg, uint off, uint len)
480 osl_t *osh;
481 uint oldidx;
483 ASSERT(cfg);
484 ASSERT(cfg->emu);
485 ASSERT(cfg->pci);
487 osh = si_osh(sih);
489 /* decide if real PCI config register access is necessary */
490 if (FORCE_EMUCFG(off, len))
491 return;
493 /* access to the real pci config space only when the core is up */
494 oldidx = si_coreidx(sih);
495 si_setcoreidx(sih, coreidx);
496 if (si_iscoreup(sih)) {
497 if (len == 4)
498 W_REG(osh, (uint32 *)((ulong)cfg->pci + off),
499 ltoh32(*(uint32 *)((ulong)cfg->emu + off)));
500 else if (len == 2)
501 W_REG(osh, (uint16 *)((ulong)cfg->pci + off),
502 ltoh16(*(uint16 *)((ulong)cfg->emu + off)));
503 else if (len == 1)
504 W_REG(osh, (uint8 *)((ulong)cfg->pci + off),
505 *(uint8 *)((ulong)cfg->emu + off));
507 si_setcoreidx(sih, oldidx);
511 * Functions for accessing translated SI configuration space
513 static int
514 si_read_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
516 pci_config_regs *cfg;
518 if (dev >= SI_MAXCORES || func >= MAXFUNCS || (off + len) > sizeof(pci_config_regs))
519 return -1;
521 cfg = si_pci_cfg[dev][func].emu;
523 ASSERT(ISALIGNED(off, len));
524 ASSERT(ISALIGNED((uintptr)buf, len));
526 /* use special config space if the device does not exist */
527 if (!cfg)
528 cfg = &si_pci_null;
529 /* sync emulation with real PCI config if necessary */
530 else if (si_pci_cfg[dev][func].pci)
531 si_pcid_read_config(sih, dev, &si_pci_cfg[dev][func], off, len);
533 if (len == 4)
534 *((uint32 *)buf) = ltoh32(*((uint32 *)((ulong) cfg + off)));
535 else if (len == 2)
536 *((uint16 *)buf) = ltoh16(*((uint16 *)((ulong) cfg + off)));
537 else if (len == 1)
538 *((uint8 *)buf) = *((uint8 *)((ulong) cfg + off));
539 else
540 return -1;
542 return 0;
545 static int
546 si_write_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
548 uint coreidx;
549 void *regs;
550 pci_config_regs *cfg;
551 osl_t *osh;
552 si_bar_cfg_t *bar;
554 if (dev >= SI_MAXCORES || func >= MAXFUNCS || (off + len) > sizeof(pci_config_regs))
555 return -1;
556 cfg = si_pci_cfg[dev][func].emu;
557 if (!cfg)
558 return -1;
560 ASSERT(ISALIGNED(off, len));
561 ASSERT(ISALIGNED((uintptr)buf, len));
563 osh = si_osh(sih);
565 if (cfg->header_type == PCI_HEADER_BRIDGE) {
566 uint busid = 0;
567 if (off == OFFSETOF(ppb_config_regs, prim_bus) && len >= 2)
568 busid = (*((uint16 *)buf) & 0xff00) >> 8;
569 else if (off == OFFSETOF(ppb_config_regs, sec_bus))
570 busid = *((uint8 *)buf);
571 if (busid)
572 hndpci_set_busid(busid);
575 /* Emulate BAR sizing */
576 if (off >= OFFSETOF(pci_config_regs, base[0]) &&
577 off <= OFFSETOF(pci_config_regs, base[3]) &&
578 len == 4 && *((uint32 *)buf) == ~0) {
579 coreidx = si_coreidx(sih);
580 if ((regs = si_setcoreidx(sih, dev))) {
581 bar = si_pci_cfg[dev][func].bar;
582 /* Highest numbered address match register */
583 if (off == OFFSETOF(pci_config_regs, base[0]))
584 cfg->base[0] = ~(bar->size[0] - 1);
585 else if (off == OFFSETOF(pci_config_regs, base[1]) && bar->n >= 1)
586 cfg->base[1] = ~(bar->size[1] - 1);
587 else if (off == OFFSETOF(pci_config_regs, base[2]) && bar->n >= 2)
588 cfg->base[2] = ~(bar->size[2] - 1);
589 else if (off == OFFSETOF(pci_config_regs, base[3]) && bar->n >= 3)
590 cfg->base[3] = ~(bar->size[3] - 1);
592 si_setcoreidx(sih, coreidx);
593 } else if (len == 4)
594 *((uint32 *)((ulong) cfg + off)) = htol32(*((uint32 *)buf));
595 else if (len == 2)
596 *((uint16 *)((ulong) cfg + off)) = htol16(*((uint16 *)buf));
597 else if (len == 1)
598 *((uint8 *)((ulong) cfg + off)) = *((uint8 *)buf);
599 else
600 return -1;
602 /* sync emulation with real PCI config if necessary */
603 if (si_pci_cfg[dev][func].pci)
604 si_pcid_write_config(sih, dev, &si_pci_cfg[dev][func], off, len);
606 return 0;
610 hndpci_read_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
612 if (bus == 0)
613 return si_read_config(sih, bus, dev, func, off, buf, len);
614 else
615 return extpci_read_config(sih, bus, dev, func, off, buf, len);
619 hndpci_write_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
621 if (bus == 0)
622 return si_write_config(sih, bus, dev, func, off, buf, len);
623 else
624 return extpci_write_config(sih, bus, dev, func, off, buf, len);
627 void
628 hndpci_ban(uint16 core)
630 if (pci_banned < ARRAYSIZE(pci_ban))
631 pci_ban[pci_banned++] = core;
634 /* return cap_offset if requested capability exists in the PCI config space */
635 uint8
636 hndpci_find_pci_capability(si_t *sih, uint bus, uint dev, uint func,
637 uint8 req_cap_id, uchar *buf, uint32 *buflen)
639 uint8 cap_id;
640 uint8 cap_ptr = 0;
641 uint32 bufsize;
642 uint8 byte_val;
644 /* check for Header type 0 */
645 hndpci_read_config(sih, bus, dev, func, PCI_CFG_HDR, &byte_val, sizeof(uint8));
646 if ((byte_val & 0x7f) != PCI_HEADER_NORMAL)
647 return (cap_ptr);
649 /* check if the capability pointer field exists */
650 hndpci_read_config(sih, bus, dev, func, PCI_CFG_STAT, &byte_val, sizeof(uint8));
651 if (!(byte_val & PCI_CAPPTR_PRESENT))
652 return (cap_ptr);
654 /* check if the capability pointer is 0x00 */
655 hndpci_read_config(sih, bus, dev, func, PCI_CFG_CAPPTR, &cap_ptr, sizeof(uint8));
656 if (cap_ptr == 0x00)
657 return (cap_ptr);
659 /* loop thr'u the capability list and see if the requested capabilty exists */
660 hndpci_read_config(sih, bus, dev, func, cap_ptr, &cap_id, sizeof(uint8));
661 while (cap_id != req_cap_id) {
662 hndpci_read_config(sih, bus, dev, func, cap_ptr + 1, &cap_ptr, sizeof(uint8));
663 if (cap_ptr == 0x00)
664 return (cap_ptr);
665 hndpci_read_config(sih, bus, dev, func, cap_ptr, &cap_id, sizeof(uint8));
668 /* found the caller requested capability */
669 if ((buf != NULL) && (buflen != NULL)) {
670 uint8 cap_data;
672 bufsize = *buflen;
673 if (!bufsize)
674 return (cap_ptr);
676 *buflen = 0;
678 /* copy the cpability data excluding cap ID and next ptr */
679 cap_data = cap_ptr + 2;
680 if ((bufsize + cap_data) > SZPCR)
681 bufsize = SZPCR - cap_data;
682 *buflen = bufsize;
683 while (bufsize--) {
684 hndpci_read_config(sih, bus, dev, func, cap_data, buf, sizeof(uint8));
685 cap_data++;
686 buf++;
690 return (cap_ptr);
695 * Initiliaze PCI core.
696 * Return 0 after a successful initialization.
697 * Otherwise return -1 to indicate there is no PCI core and
698 * return 1 to indicate PCI core is disabled.
700 int __init
701 BCMATTACHFN(hndpci_init_pci)(si_t *sih, uint coreunit)
703 uint chip, chiprev, chippkg, host;
704 uint32 boardflags;
705 sbpciregs_t *pci;
706 sbpcieregs_t *pcie = NULL;
707 uint32 val;
708 int ret = 0;
709 char *hbslot;
710 osl_t *osh;
711 int bus;
713 chip = sih->chip;
714 chiprev = sih->chiprev;
715 chippkg = sih->chippkg;
717 osh = si_osh(sih);
719 pci = (sbpciregs_t *)si_setcore(sih, PCI_CORE_ID, coreunit);
720 if (pci == NULL) {
721 pcie = (sbpcieregs_t *)si_setcore(sih, PCIE_CORE_ID, coreunit);
722 if (pcie == NULL) {
723 printf("PCI: no core\n");
724 pci_disabled[coreunit] = TRUE;
725 return -1;
729 if ((CHIPID(chip) == BCM4706_CHIP_ID) && (coreunit == 1)) {
730 /* Check if PCIE 1 is disabled */
731 if (sih->chipst & CST4706_PCIE1_DISABLE) {
732 pci_disabled[coreunit] = TRUE;
733 host = 0;
734 PCI_MSG(("PCIE port %d is disabled\n", port));
738 boardflags = (uint32)getintvar(NULL, "boardflags");
741 * The NOPCI boardflag indicates we should not touch the PCI core,
742 * it may not be bonded out or the pins may be floating.
743 * The 200-pin BCM4712 package does not bond out PCI, and routers
744 * based on it did not use the boardflag.
746 if ((boardflags & BFL_NOPCI) ||
747 ((chip == BCM4712_CHIP_ID) &&
748 ((chippkg == BCM4712SMALL_PKG_ID) || (chippkg == BCM4712MID_PKG_ID)))) {
749 pci_disabled[coreunit] = TRUE;
750 host = 0;
751 } else {
752 /* Enable the core */
753 si_core_reset(sih, 0, 0);
755 /* Figure out if it is in host mode:
756 * In host mode, it returns 0, in client mode, this register access will trap
757 * Trap handler must be implemented to support this like hndrte_mips.c
759 host = !BUSPROBE(val, (pci ? &pci->control : &pcie->control));
762 if (!host) {
763 ret = 1;
765 /* Disable PCI interrupts in client mode */
766 si_setint(sih, -1);
768 /* Disable the PCI bridge in client mode */
769 hndpci_ban(pci? PCI_CORE_ID : PCIE_CORE_ID);
771 /* Make sure the core is disabled */
772 si_core_disable(sih, 0);
774 /* On 4716 (and other AXI chips?) make sure the slave wrapper
775 * is also put in reset.
777 if ((chip == BCM4716_CHIP_ID) || (chip == BCM4748_CHIP_ID) ||
778 (chip == BCM4706_CHIP_ID)) {
779 uint32 *resetctrl;
781 resetctrl = (uint32 *)OSL_UNCACHED(SI_WRAP_BASE + (9 * SI_CORE_SIZE) +
782 AI_RESETCTRL);
783 W_REG(osh, resetctrl, AIRC_RESET);
786 printf("PCI: Disabled\n");
787 } else {
788 printf("PCI: Initializing host\n");
790 /* Disable PCI SBReqeustTimeout for BCM4785 rev. < 2 */
791 if (chip == BCM4785_CHIP_ID && chiprev < 2) {
792 sbconfig_t *sb;
793 sb = (sbconfig_t *)((ulong) pci + SBCONFIGOFF);
794 AND_REG(osh, &sb->sbimconfiglow, ~0x00000070);
795 sb_commit(sih);
798 if (pci) {
799 /* Reset the external PCI bus and enable the clock */
800 W_REG(osh, &pci->control, 0x5); /* enable tristate drivers */
801 W_REG(osh, &pci->control, 0xd); /* enable the PCI clock */
802 OSL_DELAY(150); /* delay > 100 us */
803 W_REG(osh, &pci->control, 0xf); /* deassert PCI reset */
804 /* Use internal arbiter and park REQ/GRNT at external master 0
805 * We will set it later after the bus has been probed
807 W_REG(osh, &pci->arbcontrol, PCI_INT_ARB);
808 OSL_DELAY(1); /* delay 1 us */
809 } else {
810 printf("PCI: Reset RC\n");
811 OSL_DELAY(3000);
812 W_REG(osh, &pcie->control, PCIE_RST_OE);
813 OSL_DELAY(50000); /* delay 50 ms *//* for 4706 reboot issue*/
814 W_REG(osh, &pcie->control, PCIE_RST | PCIE_RST_OE);
817 /* Enable CardBusMode */
818 cardbus = getintvar(NULL, "cardbus") == 1;
819 if (cardbus) {
820 printf("PCI: Enabling CardBus\n");
821 /* GPIO 1 resets the CardBus device on bcm94710ap */
822 si_gpioout(sih, 1, 1, GPIO_DRV_PRIORITY);
823 si_gpioouten(sih, 1, 1, GPIO_DRV_PRIORITY);
824 W_REG(osh, &pci->sprom[0], R_REG(osh, &pci->sprom[0]) | 0x400);
827 /* Host bridge slot # nvram overwrite */
828 if ((hbslot = nvram_get("pcihbslot"))) {
829 pci_hbslot = bcm_strtoul(hbslot, NULL, 0);
830 ASSERT(pci_hbslot < PCI_MAX_DEVICES);
833 bus = pci_busid[coreunit] = coreunit + 1;
834 if (pci) {
835 /* 64 MB I/O access window */
836 W_REG(osh, &pci->sbtopci0, SBTOPCI_IO);
837 /* 64 MB configuration access window */
838 W_REG(osh, &pci->sbtopci1, SBTOPCI_CFG0);
839 /* 1 GB memory access window */
840 W_REG(osh, &pci->sbtopci2, SBTOPCI_MEM | SI_PCI_DMA);
841 } else {
842 uint8 cap_ptr, root_ctrl, root_cap, dev;
843 uint16 val16;
845 /* 64 MB I/O access window. On 4716, use
846 * sbtopcie0 to access the device registers. We
847 * can't use address match 2 (1 GB window) region
848 * as mips can't generate 64-bit address on the
849 * backplane.
851 if ((chip == BCM4716_CHIP_ID) || (chip == BCM4748_CHIP_ID))
852 W_REG(osh, &pcie->sbtopcie0, SBTOPCIE_MEM |
853 (pci_membase[coreunit] = SI_PCI_MEM));
854 else if (chip == BCM4706_CHIP_ID) {
855 if (coreunit == 0) {
856 pci_membase[coreunit] = SI_PCI_MEM;
857 pci_membase_1G[coreunit] = SI_PCIE_DMA_H32;
858 } else if (coreunit == 1) {
859 pci_membase_cfg[coreunit] = SI_PCI1_CFG;
860 pci_membase[coreunit] = SI_PCI1_MEM;
861 pci_membase_1G[coreunit] = SI_PCIE1_DMA_H32;
863 W_REG(osh, &pcie->sbtopcie0,
864 SBTOPCIE_MEM | SBTOPCIE_PF | SBTOPCIE_WR_BURST |
865 pci_membase[coreunit]);
867 else
868 W_REG(osh, &pcie->sbtopcie0, SBTOPCIE_IO);
870 /* 64 MB configuration access window */
871 W_REG(osh, &pcie->sbtopcie1, SBTOPCIE_CFG0);
873 /* 1 GB memory access window */
874 W_REG(osh, &pcie->sbtopcie2, SBTOPCIE_MEM |
875 pci_membase_1G[coreunit]);
877 /* As per PCI Express Base Spec 1.1 we need to wait for
878 * at least 100 ms from the end of a reset (cold/warm/hot)
879 * before issuing configuration requests to PCI Express
880 * devices.
882 OSL_DELAY(100000);
884 /* If the root port is capable of returning Config Request
885 * Retry Status (CRS) Completion Status to software then
886 * enable the feature.
888 cap_ptr = hndpci_find_pci_capability(sih, bus, pci_hbslot, 0,
889 PCI_CAP_PCIECAP_ID, NULL, NULL);
890 ASSERT(cap_ptr);
892 root_cap = cap_ptr + OFFSETOF(pciconfig_cap_pcie, root_cap);
893 hndpci_read_config(sih, bus, pci_hbslot, 0, root_cap,
894 &val16, sizeof(uint16));
895 if (val16 & PCIE_RC_CRS_VISIBILITY) {
896 /* Enable CRS software visibility */
897 root_ctrl = cap_ptr + OFFSETOF(pciconfig_cap_pcie, root_ctrl);
898 val16 = PCIE_RC_CRS_EN;
899 hndpci_write_config(sih, bus, pci_hbslot, 0, root_ctrl,
900 &val16, sizeof(uint16));
902 /* Initiate a configuration request to read the vendor id
903 * field of the device function's config space header after
904 * 100 ms wait time from the end of Reset. If the device is
905 * not done with its internal initialization, it must at
906 * least return a completion TLP, with a completion status
907 * of "Configuration Request Retry Status (CRS)". The root
908 * complex must complete the request to the host by returning
909 * a read-data value of 0001h for the Vendor ID field and
910 * all 1s for any additional bytes included in the request.
911 * Poll using the config reads for max wait time of 1 sec or
912 * until we receive the successful completion status. Repeat
913 * the procedure for all the devices.
915 for (dev = pci_hbslot + 1; dev < PCI_MAX_DEVICES; dev++) {
916 SPINWAIT((hndpci_read_config(sih, bus, dev, 0,
917 PCI_CFG_VID, &val16, sizeof(val16)),
918 (val16 == 0x1)), 1000000);
919 if (val16 == 0x1)
920 printf("PCI: Broken device in slot %d\n", dev);
925 /* Enable PCI bridge BAR0 memory & master access */
926 val = PCI_CMD_MASTER | PCI_CMD_MEMORY;
927 hndpci_write_config(sih, bus, pci_hbslot, 0, PCI_CFG_CMD, &val, sizeof(val));
929 /* Enable PCI interrupts */
930 if (pci)
931 W_REG(osh, &pci->intmask, PCI_INTA);
932 else
933 W_REG(osh, &pcie->intmask, PCI_INTA);
936 /* Reset busid to 0. Bus number will be assigned by OS later */
937 pci_busid[coreunit] = 0;
938 return ret;
941 void
942 hndpci_arb_park(si_t *sih, uint parkid)
944 sbpciregs_t *pci;
945 uint pcirev;
946 uint32 arb;
948 pci = (sbpciregs_t *)si_setcore(sih, PCI_CORE_ID, 0);
949 if ((pci == NULL) || pci_disabled[0]) {
950 /* Should not happen */
951 PCI_MSG(("%s: no PCI core\n", __FUNCTION__));
952 return;
955 pcirev = si_corerev(sih);
957 /* Nothing to do, not supported for these revs */
958 if (pcirev < 8)
959 return;
961 /* Get parkid from NVRAM */
962 if (parkid == PCI_PARK_NVRAM) {
963 parkid = getintvar(NULL, "parkid");
964 if (getvar(NULL, "parkid") == NULL)
965 /* Not present in NVRAM use defaults */
966 parkid = (pcirev >= 11) ? PCI11_PARKID_LAST : PCI_PARKID_LAST;
969 /* Check the parkid is valid, if not set it to default */
970 if (parkid > ((pcirev >= 11) ? PCI11_PARKID_LAST : PCI_PARKID_LAST)) {
971 printf("%s: Invalid parkid %d\n", __FUNCTION__, parkid);
972 parkid = (pcirev >= 11) ? PCI11_PARKID_LAST : PCI_PARKID_LAST;
975 /* Now set the parkid */
976 arb = R_REG(si_osh(sih), &pci->arbcontrol);
977 arb &= ~PCI_PARKID_MASK;
978 arb |= parkid << PCI_PARKID_SHIFT;
979 W_REG(si_osh(sih), &pci->arbcontrol, arb);
980 OSL_DELAY(1);
983 /*for 4706 reboot issue*/
985 hndpci_deinit_pci(si_t *sih, uint coreunit)
987 int coreidx;
988 sbpciregs_t *pci;
989 sbpcieregs_t *pcie = NULL;
991 if (pci_disabled[coreunit])
992 return 0;
994 coreidx = si_coreidx(sih);
995 pci = (sbpciregs_t *)si_setcore(sih, PCI_CORE_ID, coreunit);
996 if (pci == NULL) {
997 pcie = (sbpcieregs_t *)si_setcore(sih, PCIE_CORE_ID, coreunit);
998 if (pcie == NULL) {
999 printf("PCI: no core\n");
1000 return -1;
1004 if (pci)
1005 W_REG(osh, &pci->control, PCI_RST_OE);
1006 else
1007 W_REG(osh, &pcie->control, PCIE_RST_OE);
1009 si_core_disable(sih, 0);
1010 si_setcoreidx(sih, coreidx);
1011 return 0;
1015 * * Deinitialize PCI(e) cores
1016 * */
1017 void
1018 hndpci_deinit(si_t *sih)
1020 int coreunit;
1022 for (coreunit = 0; coreunit < SI_PCI_MAXCORES; coreunit++)
1023 hndpci_deinit_pci(sih, coreunit);
1026 * Get the PCI region address and size information.
1028 static void __init
1029 BCMATTACHFN(hndpci_init_regions)(si_t *sih, uint func, pci_config_regs *cfg, si_bar_cfg_t *bar)
1031 bool issb = sih->socitype == SOCI_SB;
1032 uint i, n;
1034 if (si_coreid(sih) == USB20H_CORE_ID) {
1035 uint32 base, base1;
1037 base = htol32(si_addrspace(sih, 0));
1038 if (issb) {
1039 base1 = base + 0x800; /* OHCI/EHCI */
1040 } else {
1041 /* In AI chips EHCI is addrspace 0, OHCI is 1 */
1042 base1 = base;
1043 if ((CHIPID(sih->chip) == BCM5357_CHIP_ID ||
1044 (CHIPID(sih->chip) == BCM4749_CHIP_ID)) &&
1045 CHIPREV(sih->chiprev) == 0)
1046 base = 0x18009000;
1047 else
1048 base = htol32(si_addrspace(sih, 1));
1051 i = bar->n = 1;
1052 cfg->base[0] = func == 0 ? base : base1;
1053 bar->size[0] = issb ? 0x800 : 0x1000;
1054 } else {
1055 bar->n = n = si_numaddrspaces(sih);
1056 for (i = 0; i < n; i++) {
1057 int size = si_addrspacesize(sih, i);
1059 if (size) {
1060 cfg->base[i] = htol32(si_addrspace(sih, i));
1061 bar->size[i] = size;
1065 for (; i < PCI_BAR_MAX; i++) {
1066 cfg->base[i] = 0;
1067 bar->size[i] = 0;
1072 * Construct PCI config spaces for SB cores to be accessed as if they were PCI devices.
1074 void __init
1075 BCMATTACHFN(hndpci_init_cores)(si_t *sih)
1077 uint chiprev, coreidx, i;
1078 pci_config_regs *cfg, *pci;
1079 si_bar_cfg_t *bar;
1080 void *regs;
1081 osl_t *osh;
1082 uint16 vendor, device;
1083 uint16 coreid;
1084 uint8 class, subclass, progif;
1085 uint dev;
1086 uint8 header;
1087 uint func;
1089 chiprev = sih->chiprev;
1090 coreidx = si_coreidx(sih);
1092 osh = si_osh(sih);
1094 /* Scan the SI bus */
1095 bzero(si_config_regs, sizeof(si_config_regs));
1096 bzero(si_bar_cfg, sizeof(si_bar_cfg));
1097 bzero(si_pci_cfg, sizeof(si_pci_cfg));
1098 memset(&si_pci_null, -1, sizeof(si_pci_null));
1099 cfg = si_config_regs;
1100 bar = si_bar_cfg;
1101 for (dev = 0; dev < SI_MAXCORES; dev ++) {
1102 /* Check if the core exists */
1103 if (!(regs = si_setcoreidx(sih, dev)))
1104 continue;
1106 /* Check if this core is banned */
1107 coreid = si_coreid(sih);
1108 for (i = 0; i < pci_banned; i++)
1109 if (coreid == pci_ban[i])
1110 break;
1111 if (i < pci_banned)
1112 continue;
1114 if (coreid == USB20H_CORE_ID) {
1115 if (((CHIPID(sih->chip) == BCM5357_CHIP_ID) ||
1116 (CHIPID(sih->chip) == BCM4749_CHIP_ID)) &&
1117 (sih->chippkg == BCM5357_PKG_ID)) {
1118 printf("PCI: skip disabled USB20H\n");
1119 continue;
1123 if ((CHIPID(sih->chip) == BCM4706_CHIP_ID)) {
1124 if (coreid == GMAC_CORE_ID) {
1125 /* Only GMAC core 0 is used by 4706 */
1126 if (si_coreunit(sih) > 0) {
1127 continue;
1132 for (func = 0; func < MAXFUNCS; ++func) {
1133 /* Make sure we won't go beyond the limit */
1134 if (cfg >= &si_config_regs[SI_MAXCORES]) {
1135 printf("PCI: too many emulated devices\n");
1136 goto done;
1139 /* Convert core id to pci id */
1140 if (si_corepciid(sih, func, &vendor, &device, &class, &subclass,
1141 &progif, &header))
1142 continue;
1145 * Differentiate real PCI config from emulated.
1146 * non zero 'pci' indicate there is a real PCI config space
1147 * for this device.
1149 switch (device) {
1150 case BCM47XX_GIGETH_ID:
1151 pci = (pci_config_regs *)((uint32)regs + 0x800);
1152 break;
1153 case BCM47XX_SATAXOR_ID:
1154 pci = (pci_config_regs *)((uint32)regs + 0x400);
1155 break;
1156 case BCM47XX_ATA100_ID:
1157 pci = (pci_config_regs *)((uint32)regs + 0x800);
1158 break;
1159 default:
1160 pci = NULL;
1161 break;
1163 /* Supported translations */
1164 cfg->vendor = htol16(vendor);
1165 cfg->device = htol16(device);
1166 cfg->rev_id = chiprev;
1167 cfg->prog_if = progif;
1168 cfg->sub_class = subclass;
1169 cfg->base_class = class;
1170 cfg->header_type = header;
1171 hndpci_init_regions(sih, func, cfg, bar);
1172 /* Save core interrupt flag */
1173 cfg->int_pin = si_flag(sih);
1174 /* Save core interrupt assignment */
1175 cfg->int_line = si_irq(sih);
1176 /* Indicate there is no SROM */
1177 *((uint32 *)&cfg->sprom_control) = 0xffffffff;
1179 /* Point to the PCI config spaces */
1180 si_pci_cfg[dev][func].emu = cfg;
1181 si_pci_cfg[dev][func].pci = pci;
1182 si_pci_cfg[dev][func].bar = bar;
1183 cfg ++;
1184 bar ++;
1188 done:
1189 si_setcoreidx(sih, coreidx);
1193 * Initialize PCI core and construct PCI config spaces for SI cores.
1194 * Must propagate hndpci_init_pci() return value to the caller to let
1195 * them know the PCI core initialization status.
1197 int __init
1198 BCMATTACHFN(hndpci_init)(si_t *sih)
1200 int coreunit, status = 0;
1202 for (coreunit = 0; coreunit < SI_PCI_MAXCORES; coreunit++)
1203 status |= hndpci_init_pci(sih, coreunit);
1204 hndpci_init_cores(sih);
1205 return status;