1/*
2 * Low-Level PCI and SI support for BCM47xx
3 *
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.
17 *
18 * $Id: hndpci.c,v 1.49.2.2 2010/11/16 21:44:41 Exp $
19 */
20
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>
36
37/* For now we need some real Silicon Backplane utils */
38#include "siutils_priv.h"
39
40/* debug/trace */
41#ifdef BCMDBG_PCI
42#define	PCI_MSG(args)	printf args
43#else
44#define	PCI_MSG(args)
45#endif
46
47/* to free some function memory after boot */
48#ifndef linux
49#define __init
50#endif /* linux */
51
52/* Emulated configuration space */
53typedef struct {
54	int	n;
55	uint	size[PCI_BAR_MAX];
56} si_bar_cfg_t;
57static pci_config_regs si_config_regs[SI_MAXCORES];
58static si_bar_cfg_t si_bar_cfg[SI_MAXCORES];
59
60/* Links to emulated and real PCI configuration spaces */
61#define MAXFUNCS	2
62typedef 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;
67static si_pci_cfg_t si_pci_cfg[SI_MAXCORES][MAXFUNCS];
68
69/* Special emulated config space for non-existing device */
70static pci_config_regs si_pci_null = { 0xffff, 0xffff };
71
72/* Banned cores */
73static uint16 pci_ban[SI_MAXCORES] = { 0 };
74static uint pci_banned = 0;
75
76/* CardBus mode */
77static bool cardbus = FALSE;
78
79/* The OS's enumerated bus numbers for supported PCI/PCIe core units */
80static uint pci_busid[SI_PCI_MAXCORES] = { 0, };
81
82static uint32 pci_membase_cfg[SI_PCI_MAXCORES] = {
83	SI_PCI_CFG,
84};
85
86static uint32 pci_membase[SI_PCI_MAXCORES] = {
87	SI_PCI_DMA,
88};
89
90static uint32 pci_membase_1G[SI_PCI_MAXCORES] = {
91	SI_PCI_DMA,
92};
93
94/* Disable PCI host core */
95static bool pci_disabled[SI_PCI_MAXCORES] = {	FALSE };
96
97/* Host bridge slot #, default to 0 */
98static uint8 pci_hbslot = 0;
99
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 */
103
104/* Functions for accessing external PCI configuration space, Assume one-hot slot wiring */
105#define PCI_SLOT_MAX	16	/* Max. PCI Slots */
106
107static void
108hndpci_set_busid(uint busid)
109{	int i;
110
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;
116		}
117		if (busid == pci_busid[i])
118			return;
119	}
120}
121
122static int
123hndpci_pci_coreunit(uint bus)
124{	uint i;
125
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;
130	}
131	return -1;
132}
133
134bool
135hndpci_is_hostbridge(uint bus, uint dev)
136{	uint i;
137
138	ASSERT(bus >= 1);
139	if (dev != pci_hbslot)
140		return FALSE;
141
142	for (i = 0; i < SI_PCI_MAXCORES; i++)
143		if (bus == pci_busid[i])
144			return TRUE;
145
146	return FALSE;
147}
148
149uint32 hndpci_get_membase(uint bus)
150{
151	int coreunit;
152
153	coreunit = hndpci_pci_coreunit(bus);
154	ASSERT(coreunit >= 0);
155	ASSERT(pci_membase[coreunit]);
156	return pci_membase[coreunit];
157}
158
159static uint32
160config_cmd(si_t *sih, uint coreunit, uint bus, uint dev, uint func, uint off)
161{
162	uint coreidx;
163	sbpciregs_t *pci;
164	uint32 addr = 0, *sbtopci1;
165	osl_t *osh;
166
167	/* CardBusMode supports only one device */
168	if (cardbus && dev > 1)
169		return 0;
170
171	osh = si_osh(sih);
172
173	coreidx = si_coreidx(sih);
174	pci = (sbpciregs_t *)si_setcore(sih, PCI_CORE_ID, coreunit);
175
176	if (pci) {
177		sbtopci1 = &pci->sbtopci1;
178	} else {
179		sbpcieregs_t *pcie;
180
181		pcie = (sbpcieregs_t *)si_setcore(sih, PCIE_CORE_ID, coreunit);
182
183		/* Issue config commands only when the data link is up (atleast
184		 * one external pcie device is present).
185		 */
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;
193		}
194	}
195
196
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;
204
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));
218			}
219		}
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))));
226	}
227
228	si_setcoreidx(sih, coreidx);
229
230	return addr;
231}
232
233/*
234 * Read host bridge PCI config registers from Silicon Backplane ( >= rev8 ).
235 *
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.
238 *
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.
242 */
243static bool
244si_pcihb_read_config(si_t *sih, uint coreunit, uint bus, uint dev, uint func,
245	uint off, uint32 **addr, uint32 *val)
246{
247	sbpciregs_t *pci;
248	osl_t *osh;
249	uint coreidx;
250	bool ret = FALSE;
251
252	/* sanity check */
253	ASSERT(hndpci_is_hostbridge(bus, dev));
254
255	/* we support only two functions on device 0 */
256	if (func > 1)
257		return FALSE;
258
259	osh = si_osh(sih);
260
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;
269		}
270	} else {
271		sbpcieregs_t *pcie;
272
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.
278			 */
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);
285			}
286			ret = TRUE;
287		}
288	}
289
290	si_setcoreidx(sih, coreidx);
291
292	return ret;
293}
294
295int
296extpci_read_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
297{
298	uint32 addr = 0, *reg = NULL, val;
299	int ret = 0;
300	int coreunit = hndpci_pci_coreunit(bus);
301
302	if (coreunit < 0)
303		return -1;
304
305	/*
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;
311	 */
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;
322	}
323
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));
326
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;
336
337	if (reg && addr)
338		REG_UNMAP(reg);
339
340	return ret;
341}
342
343int
344extpci_write_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
345{
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);
351
352	if (coreunit < 0)
353		return -1;
354
355	osh = si_osh(sih);
356
357	/*
358	 * Ignore write attempt when:
359	 *	flag 'pci_disabled' is true;
360	 *	value of 'addr' is zero;
361	 *	REG_MAP() fails;
362	 *	BUSPROBE() fails;
363	 */
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;
374	}
375
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;
387	}
388
389	PCI_MSG(("%s: 0x%x => 0x%p\n", __FUNCTION__, val, reg));
390
391	if (is_hostbridge && reg == NULL) {
392		sbpcieregs_t *pcie;
393		uint coreidx;
394
395		coreidx = si_coreidx(sih);
396
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.
402			 */
403			pcie_writereg(osh, pcie, PCIE_CONFIGREGS,
404			              PCIE_CONFIG_INDADDR(func, off), val);
405
406		si_setcoreidx(sih, coreidx);
407	} else {
408		W_REG(osh, reg, val);
409
410		if ((CHIPID(sih->chip) == BCM4716_CHIP_ID) ||
411		    (CHIPID(sih->chip) == BCM4748_CHIP_ID))
412			(void)R_REG(osh, reg);
413	}
414
415
416done:
417	if (reg && addr)
418		REG_UNMAP(reg);
419
420	return ret;
421}
422
423/*
424 * Must access emulated PCI configuration at these locations even when
425 * the real PCI config space exists and is accessible.
426 *
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)
435 */
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))
442
443/* Sync the emulation registers and the real PCI config registers. */
444static void
445si_pcid_read_config(si_t *sih, uint coreidx, si_pci_cfg_t *cfg, uint off, uint len)
446{
447	osl_t *osh;
448	uint oldidx;
449
450	ASSERT(cfg);
451	ASSERT(cfg->emu);
452	ASSERT(cfg->pci);
453
454	/* decide if real PCI config register access is necessary */
455	if (FORCE_EMUCFG(off, len))
456		return;
457
458	osh = si_osh(sih);
459
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));
473	}
474	si_setcoreidx(sih, oldidx);
475}
476
477static void
478si_pcid_write_config(si_t *sih, uint coreidx, si_pci_cfg_t *cfg, uint off, uint len)
479{
480	osl_t *osh;
481	uint oldidx;
482
483	ASSERT(cfg);
484	ASSERT(cfg->emu);
485	ASSERT(cfg->pci);
486
487	osh = si_osh(sih);
488
489	/* decide if real PCI config register access is necessary */
490	if (FORCE_EMUCFG(off, len))
491		return;
492
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));
506	}
507	si_setcoreidx(sih, oldidx);
508}
509
510/*
511 * Functions for accessing translated SI configuration space
512 */
513static int
514si_read_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
515{
516	pci_config_regs *cfg;
517
518	if (dev >= SI_MAXCORES || func >= MAXFUNCS || (off + len) > sizeof(pci_config_regs))
519		return -1;
520
521	cfg = si_pci_cfg[dev][func].emu;
522
523	ASSERT(ISALIGNED(off, len));
524	ASSERT(ISALIGNED((uintptr)buf, len));
525
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);
532
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;
541
542	return 0;
543}
544
545static int
546si_write_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
547{
548	uint coreidx;
549	void *regs;
550	pci_config_regs *cfg;
551	osl_t *osh;
552	si_bar_cfg_t *bar;
553
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;
559
560	ASSERT(ISALIGNED(off, len));
561	ASSERT(ISALIGNED((uintptr)buf, len));
562
563	osh = si_osh(sih);
564
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);
573	}
574
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);
591		}
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;
601
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);
605
606	return 0;
607}
608
609int
610hndpci_read_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
611{
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);
616}
617
618int
619hndpci_write_config(si_t *sih, uint bus, uint dev, uint func, uint off, void *buf, int len)
620{
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);
625}
626
627void
628hndpci_ban(uint16 core)
629{
630	if (pci_banned < ARRAYSIZE(pci_ban))
631		pci_ban[pci_banned++] = core;
632}
633
634/* return cap_offset if requested capability exists in the PCI config space */
635uint8
636hndpci_find_pci_capability(si_t *sih, uint bus, uint dev, uint func,
637                           uint8 req_cap_id, uchar *buf, uint32 *buflen)
638{
639	uint8 cap_id;
640	uint8 cap_ptr = 0;
641	uint32 bufsize;
642	uint8 byte_val;
643
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);
648
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);
653
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);
658
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));
666	}
667
668	/* found the caller requested capability */
669	if ((buf != NULL) && (buflen != NULL)) {
670		uint8 cap_data;
671
672		bufsize = *buflen;
673		if (!bufsize)
674			return (cap_ptr);
675
676		*buflen = 0;
677
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++;
687		}
688	}
689
690	return (cap_ptr);
691}
692
693
694/*
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.
699 */
700int __init
701BCMATTACHFN(hndpci_init_pci)(si_t *sih, uint coreunit)
702{
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;
712
713	chip = sih->chip;
714	chiprev = sih->chiprev;
715	chippkg = sih->chippkg;
716
717	osh = si_osh(sih);
718
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;
726		}
727	}
728
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));
735		}
736	}
737
738	boardflags = (uint32)getintvar(NULL, "boardflags");
739
740	/*
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.
745	 */
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);
754
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
758		 */
759		host = !BUSPROBE(val, (pci ? &pci->control : &pcie->control));
760	}
761
762	if (!host) {
763		ret = 1;
764
765		/* Disable PCI interrupts in client mode */
766		si_setint(sih, -1);
767
768		/* Disable the PCI bridge in client mode */
769		hndpci_ban(pci? PCI_CORE_ID : PCIE_CORE_ID);
770
771		/* Make sure the core is disabled */
772		si_core_disable(sih, 0);
773
774		/* On 4716 (and other AXI chips?) make sure the slave wrapper
775		 * is also put in reset.
776		 */
777		if ((chip == BCM4716_CHIP_ID) || (chip == BCM4748_CHIP_ID) ||
778			(chip == BCM4706_CHIP_ID)) {
779			uint32 *resetctrl;
780
781			resetctrl = (uint32 *)OSL_UNCACHED(SI_WRAP_BASE + (9 * SI_CORE_SIZE) +
782			                                   AI_RESETCTRL);
783			W_REG(osh, resetctrl, AIRC_RESET);
784		}
785
786		printf("PCI: Disabled\n");
787	} else {
788		printf("PCI: Initializing host\n");
789
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);
796		}
797
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
806			 */
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 *//*borg, for 4706 reboot issue*/
814			W_REG(osh, &pcie->control, PCIE_RST | PCIE_RST_OE);
815		}
816
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);
825		}
826
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);
831		}
832
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;
844
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.
850			 */
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;
862				}
863				W_REG(osh, &pcie->sbtopcie0,
864					SBTOPCIE_MEM | SBTOPCIE_PF | SBTOPCIE_WR_BURST |
865					pci_membase[coreunit]);
866			}
867			else
868				W_REG(osh, &pcie->sbtopcie0, SBTOPCIE_IO);
869
870			/* 64 MB configuration access window */
871			W_REG(osh, &pcie->sbtopcie1, SBTOPCIE_CFG0);
872
873			/* 1 GB memory access window */
874			W_REG(osh, &pcie->sbtopcie2, SBTOPCIE_MEM |
875				pci_membase_1G[coreunit]);
876
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.
881			 */
882			OSL_DELAY(100000);
883
884			/* If the root port is capable of returning Config Request
885			 * Retry Status (CRS) Completion Status to software then
886			 * enable the feature.
887			 */
888			cap_ptr = hndpci_find_pci_capability(sih, bus, pci_hbslot, 0,
889			                                     PCI_CAP_PCIECAP_ID, NULL, NULL);
890			ASSERT(cap_ptr);
891
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));
901
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.
914				 */
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);
921				}
922			}
923		}
924
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));
928
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);
934	}
935
936	/* Reset busid to 0. Bus number will be assigned by OS later */
937	pci_busid[coreunit] = 0;
938	return ret;
939}
940
941void
942hndpci_arb_park(si_t *sih, uint parkid)
943{
944	sbpciregs_t *pci;
945	uint pcirev;
946	uint32  arb;
947
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;
953	}
954
955	pcirev = si_corerev(sih);
956
957	/* Nothing to do, not supported for these revs */
958	if (pcirev < 8)
959		return;
960
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;
967	}
968
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;
973	}
974
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);
981}
982
983/*borg, for 4706 reboot issue*/
984int
985hndpci_deinit_pci(si_t *sih, uint coreunit)
986{
987	int coreidx;
988	sbpciregs_t *pci;
989	sbpcieregs_t *pcie = NULL;
990
991	if (pci_disabled[coreunit])
992		return 0;
993
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;
1001		}
1002	}
1003
1004	if (pci)
1005			W_REG(osh, &pci->control, PCI_RST_OE);
1006	else
1007			W_REG(osh, &pcie->control, PCIE_RST_OE);
1008
1009	si_core_disable(sih, 0);
1010	si_setcoreidx(sih, coreidx);
1011	return 0;
1012}
1013
1014/*
1015 * Deinitialize PCI(e) cores
1016 */
1017void
1018hndpci_deinit(si_t *sih)
1019{
1020	int coreunit;
1021
1022	for (coreunit = 0; coreunit < SI_PCI_MAXCORES; coreunit++)
1023		hndpci_deinit_pci(sih, coreunit);
1024}
1025
1026/*
1027 * Get the PCI region address and size information.
1028 */
1029static void __init
1030BCMATTACHFN(hndpci_init_regions)(si_t *sih, uint func, pci_config_regs *cfg, si_bar_cfg_t *bar)
1031{
1032	bool issb = sih->socitype == SOCI_SB;
1033	uint i, n;
1034
1035	if (si_coreid(sih) == USB20H_CORE_ID) {
1036		uint32 base, base1;
1037
1038		base = htol32(si_addrspace(sih, 0));
1039		if (issb) {
1040			base1 = base + 0x800;	/* OHCI/EHCI */
1041		} else {
1042			/* In AI chips EHCI is addrspace 0, OHCI is 1 */
1043			base1 = base;
1044			if ((CHIPID(sih->chip) == BCM5357_CHIP_ID ||
1045				(CHIPID(sih->chip) == BCM4749_CHIP_ID)) &&
1046			    CHIPREV(sih->chiprev) == 0)
1047				base = 0x18009000;
1048			else
1049				base = htol32(si_addrspace(sih, 1));
1050		}
1051
1052		i = bar->n = 1;
1053		cfg->base[0] = func == 0 ? base : base1;
1054		bar->size[0] = issb ? 0x800 : 0x1000;
1055	} else {
1056		bar->n = n = si_numaddrspaces(sih);
1057		for (i = 0; i < n; i++) {
1058			int size = si_addrspacesize(sih, i);
1059
1060			if (size) {
1061				cfg->base[i] = htol32(si_addrspace(sih, i));
1062				bar->size[i] = size;
1063			}
1064		}
1065	}
1066	for (; i < PCI_BAR_MAX; i++) {
1067		cfg->base[i] = 0;
1068		bar->size[i] = 0;
1069	}
1070}
1071
1072/*
1073 * Construct PCI config spaces for SB cores to be accessed as if they were PCI devices.
1074 */
1075void __init
1076BCMATTACHFN(hndpci_init_cores)(si_t *sih)
1077{
1078	uint chiprev, coreidx, i;
1079	pci_config_regs *cfg, *pci;
1080	si_bar_cfg_t *bar;
1081	void *regs;
1082	osl_t *osh;
1083	uint16 vendor, device;
1084	uint16 coreid;
1085	uint8 class, subclass, progif;
1086	uint dev;
1087	uint8 header;
1088	uint func;
1089
1090	chiprev = sih->chiprev;
1091	coreidx = si_coreidx(sih);
1092
1093	osh = si_osh(sih);
1094
1095	/* Scan the SI bus */
1096	bzero(si_config_regs, sizeof(si_config_regs));
1097	bzero(si_bar_cfg, sizeof(si_bar_cfg));
1098	bzero(si_pci_cfg, sizeof(si_pci_cfg));
1099	memset(&si_pci_null, -1, sizeof(si_pci_null));
1100	cfg = si_config_regs;
1101	bar = si_bar_cfg;
1102	for (dev = 0; dev < SI_MAXCORES; dev ++) {
1103		/* Check if the core exists */
1104		if (!(regs = si_setcoreidx(sih, dev)))
1105			continue;
1106
1107		/* Check if this core is banned */
1108		coreid = si_coreid(sih);
1109		for (i = 0; i < pci_banned; i++)
1110			if (coreid == pci_ban[i])
1111				break;
1112		if (i < pci_banned)
1113			continue;
1114
1115		if (coreid == USB20H_CORE_ID) {
1116			if (((CHIPID(sih->chip) == BCM5357_CHIP_ID) ||
1117				(CHIPID(sih->chip) == BCM4749_CHIP_ID)) &&
1118				(sih->chippkg == BCM5357_PKG_ID)) {
1119				printf("PCI: skip disabled USB20H\n");
1120				continue;
1121			}
1122		}
1123
1124		if ((CHIPID(sih->chip) == BCM4706_CHIP_ID)) {
1125			if (coreid == GMAC_CORE_ID) {
1126				/* Only GMAC core 0 is used by 4706 */
1127				if (si_coreunit(sih) > 0) {
1128					continue;
1129				}
1130			}
1131		}
1132
1133		for (func = 0; func < MAXFUNCS; ++func) {
1134			/* Make sure we won't go beyond the limit */
1135			if (cfg >= &si_config_regs[SI_MAXCORES]) {
1136				printf("PCI: too many emulated devices\n");
1137				goto done;
1138			}
1139
1140			/* Convert core id to pci id */
1141			if (si_corepciid(sih, func, &vendor, &device, &class, &subclass,
1142			                 &progif, &header))
1143				continue;
1144
1145			/*
1146			 * Differentiate real PCI config from emulated.
1147			 * non zero 'pci' indicate there is a real PCI config space
1148			 * for this device.
1149			 */
1150			switch (device) {
1151			case BCM47XX_GIGETH_ID:
1152				pci = (pci_config_regs *)((uint32)regs + 0x800);
1153				break;
1154			case BCM47XX_SATAXOR_ID:
1155				pci = (pci_config_regs *)((uint32)regs + 0x400);
1156				break;
1157			case BCM47XX_ATA100_ID:
1158				pci = (pci_config_regs *)((uint32)regs + 0x800);
1159				break;
1160			default:
1161				pci = NULL;
1162				break;
1163			}
1164			/* Supported translations */
1165			cfg->vendor = htol16(vendor);
1166			cfg->device = htol16(device);
1167			cfg->rev_id = chiprev;
1168			cfg->prog_if = progif;
1169			cfg->sub_class = subclass;
1170			cfg->base_class = class;
1171			cfg->header_type = header;
1172			hndpci_init_regions(sih, func, cfg, bar);
1173			/* Save core interrupt flag */
1174			cfg->int_pin = si_flag(sih);
1175			/* Save core interrupt assignment */
1176			cfg->int_line = si_irq(sih);
1177			/* Indicate there is no SROM */
1178			*((uint32 *)&cfg->sprom_control) = 0xffffffff;
1179
1180			/* Point to the PCI config spaces */
1181			si_pci_cfg[dev][func].emu = cfg;
1182			si_pci_cfg[dev][func].pci = pci;
1183			si_pci_cfg[dev][func].bar = bar;
1184			cfg ++;
1185			bar ++;
1186		}
1187	}
1188
1189done:
1190	si_setcoreidx(sih, coreidx);
1191}
1192
1193/*
1194 * Initialize PCI core and construct PCI config spaces for SI cores.
1195 * Must propagate hndpci_init_pci() return value to the caller to let
1196 * them know the PCI core initialization status.
1197 */
1198int __init
1199BCMATTACHFN(hndpci_init)(si_t *sih)
1200{
1201	int coreunit, status = 0;
1202
1203	for (coreunit = 0; coreunit < SI_PCI_MAXCORES; coreunit++)
1204		status |= hndpci_init_pci(sih, coreunit);
1205	hndpci_init_cores(sih);
1206	return status;
1207}
1208