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, &regs->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, &regs->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 *)&regs->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, &reg, &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, &reg, &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