1/*
2 * Misc utility routines for accessing chip-specific features
3 * of the SiliconBackplane-based Broadcom chips.
4 *
5 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
14 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
16 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 * $Id: siutils.c,v 1.821.2.48 2011-02-11 20:59:28 Exp $
20 */
21
22#include <typedefs.h>
23#include <bcmdefs.h>
24#include <osl.h>
25#include <bcmutils.h>
26#include <siutils.h>
27#include <bcmdevs.h>
28#include <hndsoc.h>
29#include <sbchipc.h>
30#include <pci_core.h>
31#include <pcie_core.h>
32#include <nicpci.h>
33#include <bcmnvram.h>
34#include <bcmsrom.h>
35#include <hndtcam.h>
36#include <pcicfg.h>
37#include <sbpcmcia.h>
38#include <sbsocram.h>
39#include <bcmotp.h>
40#include <hndpmu.h>
41#ifdef BCMSPI
42#include <spid.h>
43#endif /* BCMSPI */
44
45#include "siutils_priv.h"
46
47/* local prototypes */
48static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
49                              uint bustype, void *sdh, char **vars, uint *varsz);
50static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh);
51static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
52	uint *origidx, void *regs);
53static void si_nvram_process(si_info_t *sii, char *pvars);
54#if !defined(_CFE_) || defined(CFG_WL)
55static void si_sromvars_fixup_4331(si_t *sih, char *pvars);
56#endif /* !_CFE_ || CFG_WL */
57
58/* dev path concatenation util */
59static char *si_devpathvar(si_t *sih, char *var, int len, const char *name);
60static bool _si_clkctl_cc(si_info_t *sii, uint mode);
61static bool si_ispcie(si_info_t *sii);
62static uint BCMINITFN(socram_banksize)(si_info_t *sii, sbsocramregs_t *r, uint8 idx, uint8 mtype);
63
64
65/* global variable to indicate reservation/release of gpio's */
66static uint32 si_gpioreservation = 0;
67
68/* global flag to prevent shared resources from being initialized multiple times in si_attach() */
69
70/*
71 * Allocate a si handle.
72 * devid - pci device id (used to determine chip#)
73 * osh - opaque OS handle
74 * regs - virtual address of initial core registers
75 * bustype - pci/pcmcia/sb/sdio/etc
76 * vars - pointer to a pointer area for "environment" variables
77 * varsz - pointer to int to return the size of the vars
78 */
79si_t *
80BCMATTACHFN(si_attach)(uint devid, osl_t *osh, void *regs,
81                       uint bustype, void *sdh, char **vars, uint *varsz)
82{
83	si_info_t *sii;
84
85	/* alloc si_info_t */
86	if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) {
87		SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
88		return (NULL);
89	}
90
91	if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) {
92		MFREE(osh, sii, sizeof(si_info_t));
93		return (NULL);
94	}
95	sii->vars = vars ? *vars : NULL;
96	sii->varsz = varsz ? *varsz : 0;
97
98	return (si_t *)sii;
99}
100
101/* global kernel resource */
102static si_info_t ksii;
103
104static uint32	wd_msticks;		/* watchdog timer ticks normalized to ms */
105
106/* generic kernel variant of si_attach() */
107si_t *
108BCMATTACHFN(si_kattach)(osl_t *osh)
109{
110	static bool ksii_attached = FALSE;
111
112	if (!ksii_attached) {
113		void *regs;
114#ifndef SI_ENUM_BASE_VARIABLE
115		regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
116#endif
117
118		if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs,
119		                SI_BUS, NULL,
120		                osh != SI_OSH ? &ksii.vars : NULL,
121		                osh != SI_OSH ? &ksii.varsz : NULL) == NULL) {
122			SI_ERROR(("si_kattach: si_doattach failed\n"));
123			REG_UNMAP(regs);
124			return NULL;
125		}
126		REG_UNMAP(regs);
127
128		/* save ticks normalized to ms for si_watchdog_ms() */
129		if (PMUCTL_ENAB(&ksii.pub)) {
130			if (CHIPID(ksii.pub.chip) == BCM4706_CHIP_ID) {
131				/* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */
132				wd_msticks = (si_alp_clock(&ksii.pub) / 4) / 1000;
133			}
134			else
135				/* based on 32KHz ILP clock */
136				wd_msticks = 32;
137		} else {
138			if (ksii.pub.ccrev < 18)
139				wd_msticks = si_clock(&ksii.pub) / 1000;
140			else
141				wd_msticks = si_alp_clock(&ksii.pub) / 1000;
142		}
143
144		ksii_attached = TRUE;
145		SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n",
146		        ksii.pub.ccrev, wd_msticks));
147	}
148
149	return &ksii.pub;
150}
151
152bool
153si_ldo_war(si_t *sih, uint devid)
154{
155	si_info_t *sii = SI_INFO(sih);
156	uint32 w;
157	chipcregs_t *cc;
158	void *regs = sii->curmap;
159	uint32 rev_id, ccst;
160
161	rev_id = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_REV, sizeof(uint32));
162	rev_id &= 0xff;
163	if (!(((CHIPID(devid) == BCM4322_CHIP_ID) ||
164	       (CHIPID(devid) == BCM4342_CHIP_ID) ||
165	       (CHIPID(devid) == BCM4322_D11N_ID) ||
166	       (CHIPID(devid) == BCM4322_D11N2G_ID) ||
167	       (CHIPID(devid) == BCM4322_D11N5G_ID)) &&
168	      (rev_id == 0)))
169		return TRUE;
170
171	SI_MSG(("si_ldo_war: PCI devid 0x%x rev %d, HACK to fix 4322a0 LDO/PMU\n", devid, rev_id));
172
173	/* switch to chipcommon */
174	w = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
175	OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), SI_ENUM_BASE);
176	cc = (chipcregs_t *)regs;
177
178	/* clear bit 7 to fix LDO
179	 * write to register *blindly* WITHOUT read since read may timeout
180	 *  because the default clock is 32k ILP
181	 */
182	W_REG(sii->osh, &cc->regcontrol_addr, 0);
183	/* AND_REG(sii->osh, &cc->regcontrol_data, ~0x80); */
184	W_REG(sii->osh, &cc->regcontrol_data, 0x3001);
185
186	OSL_DELAY(5000);
187
188	/* request ALP_AVAIL through PMU to move sb out of ILP */
189	W_REG(sii->osh, &cc->min_res_mask, 0x0d);
190
191	SPINWAIT(((ccst = OSL_PCI_READ_CONFIG(sii->osh, PCI_CLK_CTL_ST, 4)) & CCS_ALPAVAIL)
192		 == 0, PMU_MAX_TRANSITION_DLY);
193
194	if ((ccst & CCS_ALPAVAIL) == 0) {
195		SI_ERROR(("ALP never came up clk_ctl_st: 0x%x\n", ccst));
196		return FALSE;
197	}
198	SI_MSG(("si_ldo_war: 4322a0 HACK done\n"));
199
200	OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), w);
201
202	return TRUE;
203}
204
205static bool
206BCMATTACHFN(si_buscore_prep)(si_info_t *sii, uint bustype, uint devid, void *sdh)
207{
208	/* need to set memseg flag for CF card first before any sb registers access */
209	if (BUSTYPE(bustype) == PCMCIA_BUS)
210		sii->memseg = TRUE;
211
212	if (BUSTYPE(bustype) == PCI_BUS) {
213		if (!si_ldo_war((si_t *)sii, devid))
214			return FALSE;
215	}
216
217	/* kludge to enable the clock on the 4306 which lacks a slowclock */
218	if (BUSTYPE(bustype) == PCI_BUS && !si_ispcie(sii))
219		si_clkctl_xtal(&sii->pub, XTAL|PLL, ON);
220
221
222	return TRUE;
223}
224
225static bool
226BCMATTACHFN(si_buscore_setup)(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
227	uint *origidx, void *regs)
228{
229	bool pci, pcie;
230	uint i;
231	uint pciidx, pcieidx, pcirev, pcierev;
232
233	cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
234	ASSERT((uintptr)cc);
235
236	/* get chipcommon rev */
237	sii->pub.ccrev = (int)si_corerev(&sii->pub);
238
239	/* get chipcommon chipstatus */
240	if (sii->pub.ccrev >= 11)
241		sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
242
243	/* get chipcommon capabilites */
244	sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
245	/* get chipcommon extended capabilities */
246
247	if (sii->pub.ccrev >= 35)
248		sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
249
250	/* get pmu rev and caps */
251	if (sii->pub.cccaps & CC_CAP_PMU) {
252		sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
253		sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
254	}
255
256	SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
257		sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev,
258		sii->pub.pmucaps));
259
260	/* figure out bus/orignal core idx */
261	sii->pub.buscoretype = NODEV_CORE_ID;
262	sii->pub.buscorerev = NOREV;
263	sii->pub.buscoreidx = BADIDX;
264
265	pci = pcie = FALSE;
266	pcirev = pcierev = NOREV;
267	pciidx = pcieidx = BADIDX;
268
269	for (i = 0; i < sii->numcores; i++) {
270		uint cid, crev;
271
272		si_setcoreidx(&sii->pub, i);
273		cid = si_coreid(&sii->pub);
274		crev = si_corerev(&sii->pub);
275
276		/* Display cores found */
277		SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
278		        i, cid, crev, sii->coresba[i], sii->regs[i]));
279
280		if (BUSTYPE(bustype) == PCI_BUS) {
281			if (cid == PCI_CORE_ID) {
282				pciidx = i;
283				pcirev = crev;
284				pci = TRUE;
285			} else if (cid == PCIE_CORE_ID) {
286				pcieidx = i;
287				pcierev = crev;
288				pcie = TRUE;
289			}
290		} else if ((BUSTYPE(bustype) == PCMCIA_BUS) &&
291		           (cid == PCMCIA_CORE_ID)) {
292			sii->pub.buscorerev = crev;
293			sii->pub.buscoretype = cid;
294			sii->pub.buscoreidx = i;
295		}
296
297		/* find the core idx before entering this func. */
298		if ((savewin && (savewin == sii->coresba[i])) ||
299		    (regs == sii->regs[i]))
300			*origidx = i;
301	}
302
303	if (pci && pcie) {
304		if (si_ispcie(sii))
305			pci = FALSE;
306		else
307			pcie = FALSE;
308	}
309	if (pci) {
310		sii->pub.buscoretype = PCI_CORE_ID;
311		sii->pub.buscorerev = pcirev;
312		sii->pub.buscoreidx = pciidx;
313	} else if (pcie) {
314		sii->pub.buscoretype = PCIE_CORE_ID;
315		sii->pub.buscorerev = pcierev;
316		sii->pub.buscoreidx = pcieidx;
317	}
318
319	SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype,
320	         sii->pub.buscorerev));
321
322	if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) &&
323	    (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (CHIPREV(sii->pub.chiprev) <= 3))
324		OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL);
325
326	/* fixup necessary chip/core configurations */
327	if (BUSTYPE(sii->pub.bustype) == PCI_BUS) {
328		if (SI_FAST(sii)) {
329			if (!sii->pch &&
330			    ((sii->pch = (void *)(uintptr)pcicore_init(&sii->pub, sii->osh,
331				(void *)PCIEREGS(sii))) == NULL))
332				return FALSE;
333		}
334		if (si_pci_fixcfg(&sii->pub)) {
335			SI_ERROR(("si_doattach: si_pci_fixcfg failed\n"));
336			return FALSE;
337		}
338	}
339
340
341	/* return to the original core */
342	si_setcoreidx(&sii->pub, *origidx);
343
344	return TRUE;
345}
346
347static void
348BCMATTACHFN(si_nvram_process)(si_info_t *sii, char *pvars)
349{
350	uint w = 0;
351	if (BUSTYPE(sii->pub.bustype) == PCMCIA_BUS) {
352		w = getintvar(pvars, "regwindowsz");
353		sii->memseg = (w <= CFTABLE_REGWIN_2K) ? TRUE : FALSE;
354	}
355
356	/* get boardtype and boardrev */
357	switch (BUSTYPE(sii->pub.bustype)) {
358	case PCI_BUS:
359#if defined(BCMHOSTVARS)
360		sii->pub.boardvendor = VENDOR_BROADCOM;
361		sii->pub.boardtype = getintvar(pvars, "boardtype");
362#else /* !BCMHOSTVARS */
363		/* do a pci config read to get subsystem id and subvendor id */
364		w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_SVID, sizeof(uint32));
365		/* Let nvram variables override subsystem Vend/ID */
366		if ((sii->pub.boardvendor = (uint16)si_getdevpathintvar(&sii->pub, "boardvendor"))
367			== 0)
368			sii->pub.boardvendor = w & 0xffff;
369		else
370			SI_ERROR(("Overriding boardvendor: 0x%x instead of 0x%x\n",
371				sii->pub.boardvendor, w & 0xffff));
372		if ((sii->pub.boardtype = (uint16)si_getdevpathintvar(&sii->pub, "boardtype"))
373			== 0)
374			sii->pub.boardtype = (w >> 16) & 0xffff;
375		else
376			SI_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n",
377				sii->pub.boardtype, (w >> 16) & 0xffff));
378#endif /* BCMHOSTVARS */
379		break;
380
381	case PCMCIA_BUS:
382		sii->pub.boardvendor = getintvar(pvars, "manfid");
383		sii->pub.boardtype = getintvar(pvars, "prodid");
384		break;
385
386
387	case SI_BUS:
388	case JTAG_BUS:
389		sii->pub.boardvendor = VENDOR_BROADCOM;
390		if (pvars == NULL || ((sii->pub.boardtype = getintvar(pvars, "prodid")) == 0))
391			if ((sii->pub.boardtype = getintvar(NULL, "boardtype")) == 0)
392				sii->pub.boardtype = 0xffff;
393
394		if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
395			/* do a pci config read to get subsystem id and subvendor id */
396			w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_SVID, sizeof(uint32));
397			sii->pub.boardvendor = w & 0xffff;
398			sii->pub.boardtype = (w >> 16) & 0xffff;
399		}
400		break;
401	}
402
403	if (sii->pub.boardtype == 0) {
404		SI_ERROR(("si_doattach: unknown board type\n"));
405		ASSERT(sii->pub.boardtype);
406	}
407
408	sii->pub.boardrev = getintvar(pvars, "boardrev");
409	sii->pub.boardflags = getintvar(pvars, "boardflags");
410}
411
412#if !defined(_CFE_) || defined(CFG_WL)
413static void
414BCMATTACHFN(si_sromvars_fixup_4331)(si_t *sih, char *pvars)
415{
416
417	const char *sromvars[] =
418	        {"extpagain2g", "extpagain5g"};
419	int sromvars_size = sizeof(sromvars)/sizeof(char *);
420	int ii;
421	uint boardtype = sih->boardtype;
422	uint boardrev = sih->boardrev;
423	bool update = ((boardtype == BCM94331BU_SSID) ||
424	               (boardtype == BCM94331S9BU_SSID) ||
425	               (boardtype == BCM94331MCI_SSID) ||
426	               (boardtype == BCM94331MC_SSID) ||
427	               (boardtype == BCM94331PCIEBT4_SSID) ||
428	               (boardtype == BCM94331X19 && boardrev == 0x1100) ||
429	               (boardtype == BCM94331HM_SSID && boardrev < 0x1152));
430
431	if (pvars == NULL || !update) {
432		return;
433	}
434
435	for (ii = 0; ii < sromvars_size; ii++) {
436		char* val = getvar(pvars, sromvars[ii]);
437
438		while (val && *val) {
439			*val = '0';
440			val++;
441		}
442	}
443}
444#endif /* !_CFE_ || CFG_WL */
445
446#ifdef CONFIG_XIP
447extern uint8 patch_pair;
448#endif /* CONFIG_XIP */
449
450static si_info_t *
451BCMATTACHFN(si_doattach)(si_info_t *sii, uint devid, osl_t *osh, void *regs,
452                       uint bustype, void *sdh, char **vars, uint *varsz)
453{
454	struct si_pub *sih = &sii->pub;
455	uint32 w, savewin;
456	chipcregs_t *cc;
457	char *pvars = NULL;
458	uint origidx;
459
460	ASSERT(GOODREGS(regs));
461
462	bzero((uchar*)sii, sizeof(si_info_t));
463
464	savewin = 0;
465
466	sih->buscoreidx = BADIDX;
467
468	sii->curmap = regs;
469	sii->sdh = sdh;
470	sii->osh = osh;
471
472#ifdef SI_ENUM_BASE_VARIABLE
473	si_enum_base_init(sih, bustype);
474#endif /* SI_ENUM_BASE_VARIABLE */
475
476	/* check to see if we are a si core mimic'ing a pci core */
477	if ((bustype == PCI_BUS) &&
478	    (OSL_PCI_READ_CONFIG(sii->osh, PCI_SPROM_CONTROL, sizeof(uint32)) == 0xffffffff)) {
479		SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI "
480		          "devid:0x%x\n", __FUNCTION__, devid));
481		bustype = SI_BUS;
482	}
483
484	/* find Chipcommon address */
485	if (bustype == PCI_BUS) {
486		savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
487		if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
488			savewin = SI_ENUM_BASE;
489		OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE);
490		cc = (chipcregs_t *)regs;
491	} else {
492		cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
493	}
494
495	sih->bustype = bustype;
496	if (bustype != BUSTYPE(bustype)) {
497		SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n",
498			bustype, BUSTYPE(bustype)));
499		return NULL;
500	}
501
502	/* bus/core/clk setup for register access */
503	if (!si_buscore_prep(sii, bustype, devid, sdh)) {
504		SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype));
505		return NULL;
506	}
507
508	/* ChipID recognition.
509	 *   We assume we can read chipid at offset 0 from the regs arg.
510	 *   If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
511	 *   some way of recognizing them needs to be added here.
512	 */
513	w = R_REG(osh, &cc->chipid);
514	sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
515	/* Might as wll fill in chip id rev & pkg */
516	sih->chip = w & CID_ID_MASK;
517	sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
518	sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
519
520	if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) &&
521		(sih->chippkg != BCM4329_289PIN_PKG_ID)) {
522		sih->chippkg = BCM4329_182PIN_PKG_ID;
523	}
524	sih->issim = IS_SIM(sih->chippkg);
525
526	/* scan for cores */
527	if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) {
528		SI_MSG(("Found chip type SB (0x%08x)\n", w));
529		sb_scan(&sii->pub, regs, devid);
530	} else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) {
531		SI_MSG(("Found chip type AI (0x%08x)\n", w));
532		/* pass chipc address instead of original core base */
533		ai_scan(&sii->pub, (void *)(uintptr)cc, devid);
534	} else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
535		SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip));
536		/* pass chipc address instead of original core base */
537		ub_scan(&sii->pub, (void *)(uintptr)cc, devid);
538	} else {
539		SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
540		return NULL;
541	}
542	/* no cores found, bail out */
543	if (sii->numcores == 0) {
544		SI_ERROR(("si_doattach: could not find any cores\n"));
545		return NULL;
546	}
547	/* bus/core/clk setup */
548	origidx = SI_CC_IDX;
549	if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
550		SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
551		goto exit;
552	}
553
554#if !defined(_CFE_) || defined(CFG_WL)
555	if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK)
556		>> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT |
557		CST4322_SPROM_PRESENT))) {
558		SI_ERROR(("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__));
559		return NULL;
560	}
561
562	/* assume current core is CC */
563	if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID ||
564	                                  CHIPID(sih->chip) == BCM43235_CHIP_ID ||
565	                                  CHIPID(sih->chip) == BCM43234_CHIP_ID ||
566	                                  CHIPID(sih->chip) == BCM43238_CHIP_ID) &&
567	                                 (CHIPREV(sii->pub.chiprev) <= 2))) {
568
569		if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
570			uint clkdiv;
571			clkdiv = R_REG(osh, &cc->clkdiv);
572			/* otp_clk_div is even number, 120/14 < 9mhz */
573			clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
574			W_REG(osh, &cc->clkdiv, clkdiv);
575			SI_ERROR(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv));
576		}
577		OSL_DELAY(10);
578	}
579
580	if (bustype == PCI_BUS) {
581		if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
582		    (CHIPID(sih->chip) == BCM43431_CHIP_ID)) {
583			/* set default mux pin to SROM */
584			si_chipcontrl_epa4331(sih, FALSE);
585			si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, 100);
586			OSL_DELAY(20000);	/* Srom read takes ~12mS */
587		}
588	}
589#endif /* !_CFE_ || CFG_WL */
590#ifdef SI_SPROM_PROBE
591	si_sprom_init(sih);
592#endif /* SI_SPROM_PROBE */
593
594#if !defined(BCMHIGHSDIO)
595	/* Init nvram from flash if it exists */
596	nvram_init((void *)&(sii->pub));
597
598	/* Init nvram from sprom/otp if they exist */
599	if (srom_var_init(&sii->pub, BUSTYPE(bustype), regs, sii->osh, vars, varsz)) {
600		SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
601		goto exit;
602	}
603	pvars = vars ? *vars : NULL;
604	si_nvram_process(sii, pvars);
605
606#if !defined(_CFE_) || defined(CFG_WL)
607	if (bustype == PCI_BUS) {
608		if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
609		    (CHIPID(sih->chip) == BCM43431_CHIP_ID)) {
610			si_sromvars_fixup_4331(sih, pvars);
611		}
612	}
613#endif /* _!CFE_ || CFG_WL */
614
615	/* === NVRAM, clock is ready === */
616#else
617	pvars = NULL;
618#endif
619
620
621#ifdef CONFIG_XIP
622		/* patch the ROM if there are any patch pairs from OTP/SPROM */
623		if (patch_pair) {
624
625			hnd_tcam_bootloader_load(si_setcore(sih, SOCRAM_CORE_ID, 0), pvars);
626
627			si_setcoreidx(sih, origidx);
628		}
629#endif /* CONFIG_XIP */
630
631		if (sii->pub.ccrev >= 20) {
632			cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
633			W_REG(osh, &cc->gpiopullup, 0);
634			W_REG(osh, &cc->gpiopulldown, 0);
635			si_setcoreidx(sih, origidx);
636		}
637
638		/* PMU specific initializations */
639		if (PMUCTL_ENAB(sih)) {
640			uint32 xtalfreq;
641			si_pmu_init(sih, sii->osh);
642			si_pmu_chip_init(sih, sii->osh);
643			xtalfreq = getintvar(pvars, "xtalfreq");
644			/* If xtalfreq var not available, try to measure it */
645			if (xtalfreq == 0)
646				xtalfreq = si_pmu_measure_alpclk(sih, sii->osh);
647			si_pmu_pll_init(sih, sii->osh, xtalfreq);
648			si_pmu_res_init(sih, sii->osh);
649			si_pmu_swreg_init(sih, sii->osh);
650		}
651
652	/* setup the GPIO based LED powersave register */
653	if (sii->pub.ccrev >= 16) {
654		if ((w = getintvar(pvars, "leddc")) == 0)
655			w = DEFAULT_GPIOTIMERVAL;
656		si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
657	}
658
659	if (PCI_FORCEHT(sii)) {
660		SI_MSG(("si_doattach: force HT\n"));
661		sih->pci_pr32414 = TRUE;
662		si_clkctl_init(sih);
663		_si_clkctl_cc(sii, CLK_FAST);
664	}
665
666#if !defined(_CFE_) || defined(CFG_WL)
667	if (PCIE(sii)) {
668		ASSERT(sii->pch != NULL);
669
670		pcicore_attach(sii->pch, pvars, SI_DOATTACH);
671
672		if (((CHIPID(sih->chip) == BCM4311_CHIP_ID) && (CHIPREV(sih->chiprev) == 2)) ||
673		    (CHIPID(sih->chip) == BCM4312_CHIP_ID)) {
674			SI_MSG(("si_doattach: clear initiator timeout\n"));
675			sb_set_initiator_to(sih, 0x3, si_findcoreidx(sih, D11_CORE_ID, 0));
676		}
677	}
678
679	if ((CHIPID(sih->chip) == BCM43224_CHIP_ID) ||
680		(CHIPID(sih->chip) == BCM43421_CHIP_ID)) {
681		/* enable 12 mA drive strenth for 43224 and set chipControl register bit 15 */
682		if (CHIPREV(sih->chiprev) == 0) {
683			SI_MSG(("Applying 43224A0 WARs\n"));
684			si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol),
685			           CCTRL43224_GPIO_TOGGLE, CCTRL43224_GPIO_TOGGLE);
686			si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE,
687			                   CCTRL_43224A0_12MA_LED_DRIVE);
688		}
689		if (CHIPREV(sih->chiprev) >= 1) {
690			SI_MSG(("Applying 43224B0+ WARs\n"));
691			si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE,
692			                   CCTRL_43224B0_12MA_LED_DRIVE);
693		}
694	}
695
696	if (CHIPID(sih->chip) == BCM4313_CHIP_ID) {
697		/* enable 12 mA drive strenth for 4313 and set chipControl register bit 1 */
698		SI_MSG(("Applying 4313 WARs\n"));
699		si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE,	CCTRL_4313_12MA_LED_DRIVE);
700	}
701#endif /* !_CFE_ || CFG_WL */
702
703
704	return (sii);
705
706exit:
707	if (BUSTYPE(sih->bustype) == PCI_BUS) {
708		if (sii->pch)
709			pcicore_deinit(sii->pch);
710		sii->pch = NULL;
711	}
712
713	return NULL;
714}
715
716/* may be called with core in reset */
717void
718BCMATTACHFN(si_detach)(si_t *sih)
719{
720	si_info_t *sii;
721	uint idx;
722
723#if defined(STA)
724	struct si_pub *si_local = NULL;
725	bcopy(&sih, &si_local, sizeof(si_t**));
726#endif
727
728	sii = SI_INFO(sih);
729
730	if (sii == NULL)
731		return;
732
733	if (BUSTYPE(sih->bustype) == SI_BUS)
734		for (idx = 0; idx < SI_MAXCORES; idx++)
735			if (sii->regs[idx]) {
736				REG_UNMAP(sii->regs[idx]);
737				sii->regs[idx] = NULL;
738			}
739
740#if defined(STA)
741	nvram_exit((void *)si_local); /* free up nvram buffers */
742#endif
743
744	if (BUSTYPE(sih->bustype) == PCI_BUS) {
745		if (sii->pch)
746			pcicore_deinit(sii->pch);
747		sii->pch = NULL;
748	}
749
750#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
751	if (sii != &ksii)
752#endif	/* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
753		MFREE(sii->osh, sii, sizeof(si_info_t));
754}
755
756void *
757si_osh(si_t *sih)
758{
759	si_info_t *sii;
760
761	sii = SI_INFO(sih);
762	return sii->osh;
763}
764
765void
766si_setosh(si_t *sih, osl_t *osh)
767{
768	si_info_t *sii;
769
770	sii = SI_INFO(sih);
771	if (sii->osh != NULL) {
772		SI_ERROR(("osh is already set....\n"));
773		ASSERT(!sii->osh);
774	}
775	sii->osh = osh;
776}
777
778/* register driver interrupt disabling and restoring callback functions */
779void
780si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
781                          void *intrsenabled_fn, void *intr_arg)
782{
783	si_info_t *sii;
784
785	sii = SI_INFO(sih);
786	sii->intr_arg = intr_arg;
787	sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn;
788	sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn;
789	sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn;
790	/* save current core id.  when this function called, the current core
791	 * must be the core which provides driver functions(il, et, wl, etc.)
792	 */
793	sii->dev_coreid = sii->coreid[sii->curidx];
794}
795
796void
797si_deregister_intr_callback(si_t *sih)
798{
799	si_info_t *sii;
800
801	sii = SI_INFO(sih);
802	sii->intrsoff_fn = NULL;
803}
804
805uint
806si_intflag(si_t *sih)
807{
808	si_info_t *sii = SI_INFO(sih);
809
810	if (CHIPTYPE(sih->socitype) == SOCI_SB)
811		return sb_intflag(sih);
812	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
813		return R_REG(sii->osh, ((uint32 *)(uintptr)
814			    (sii->oob_router + OOB_STATUSA)));
815	else {
816		ASSERT(0);
817		return 0;
818	}
819}
820
821uint
822si_flag(si_t *sih)
823{
824	if (CHIPTYPE(sih->socitype) == SOCI_SB)
825		return sb_flag(sih);
826	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
827		return ai_flag(sih);
828	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
829		return ub_flag(sih);
830	else {
831		ASSERT(0);
832		return 0;
833	}
834}
835
836void
837si_setint(si_t *sih, int siflag)
838{
839	if (CHIPTYPE(sih->socitype) == SOCI_SB)
840		sb_setint(sih, siflag);
841	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
842		ai_setint(sih, siflag);
843	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
844		ub_setint(sih, siflag);
845	else
846		ASSERT(0);
847}
848
849uint
850si_coreid(si_t *sih)
851{
852	si_info_t *sii;
853
854	sii = SI_INFO(sih);
855	return sii->coreid[sii->curidx];
856}
857
858uint
859si_coreidx(si_t *sih)
860{
861	si_info_t *sii;
862
863	sii = SI_INFO(sih);
864	return sii->curidx;
865}
866
867/* return the core-type instantiation # of the current core */
868uint
869si_coreunit(si_t *sih)
870{
871	si_info_t *sii;
872	uint idx;
873	uint coreid;
874	uint coreunit;
875	uint i;
876
877	sii = SI_INFO(sih);
878	coreunit = 0;
879
880	idx = sii->curidx;
881
882	ASSERT(GOODREGS(sii->curmap));
883	coreid = si_coreid(sih);
884
885	/* count the cores of our type */
886	for (i = 0; i < idx; i++)
887		if (sii->coreid[i] == coreid)
888			coreunit++;
889
890	return (coreunit);
891}
892
893uint
894si_corevendor(si_t *sih)
895{
896	if (CHIPTYPE(sih->socitype) == SOCI_SB)
897		return sb_corevendor(sih);
898	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
899		return ai_corevendor(sih);
900	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
901		return ub_corevendor(sih);
902	else {
903		ASSERT(0);
904		return 0;
905	}
906}
907
908bool
909si_backplane64(si_t *sih)
910{
911	return ((sih->cccaps & CC_CAP_BKPLN64) != 0);
912}
913
914uint
915si_corerev(si_t *sih)
916{
917	if (CHIPTYPE(sih->socitype) == SOCI_SB)
918		return sb_corerev(sih);
919	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
920		return ai_corerev(sih);
921	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
922		return ub_corerev(sih);
923	else {
924		ASSERT(0);
925		return 0;
926	}
927}
928
929/* return index of coreid or BADIDX if not found */
930uint
931si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
932{
933	si_info_t *sii;
934	uint found;
935	uint i;
936
937	sii = SI_INFO(sih);
938
939	found = 0;
940
941	for (i = 0; i < sii->numcores; i++)
942		if (sii->coreid[i] == coreid) {
943			if (found == coreunit)
944				return (i);
945			found++;
946		}
947
948	return (BADIDX);
949}
950
951/* return list of found cores */
952uint
953si_corelist(si_t *sih, uint coreid[])
954{
955	si_info_t *sii;
956
957	sii = SI_INFO(sih);
958
959	bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint)));
960	return (sii->numcores);
961}
962
963/* return current register mapping */
964void *
965si_coreregs(si_t *sih)
966{
967	si_info_t *sii;
968
969	sii = SI_INFO(sih);
970	ASSERT(GOODREGS(sii->curmap));
971
972	return (sii->curmap);
973}
974
975/*
976 * This function changes logical "focus" to the indicated core;
977 * must be called with interrupts off.
978 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
979 */
980void *
981si_setcore(si_t *sih, uint coreid, uint coreunit)
982{
983	uint idx;
984
985	idx = si_findcoreidx(sih, coreid, coreunit);
986	if (!GOODIDX(idx))
987		return (NULL);
988
989	if (CHIPTYPE(sih->socitype) == SOCI_SB)
990		return sb_setcoreidx(sih, idx);
991	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
992		return ai_setcoreidx(sih, idx);
993	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
994		return ub_setcoreidx(sih, idx);
995	else {
996		ASSERT(0);
997		return NULL;
998	}
999}
1000
1001void *
1002si_setcoreidx(si_t *sih, uint coreidx)
1003{
1004	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1005		return sb_setcoreidx(sih, coreidx);
1006	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1007		return ai_setcoreidx(sih, coreidx);
1008	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1009		return ub_setcoreidx(sih, coreidx);
1010	else {
1011		ASSERT(0);
1012		return NULL;
1013	}
1014}
1015
1016/* Turn off interrupt as required by sb_setcore, before switch core */
1017void *
1018si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
1019{
1020	void *cc;
1021	si_info_t *sii;
1022
1023	sii = SI_INFO(sih);
1024
1025	if (SI_FAST(sii)) {
1026		/* Overloading the origidx variable to remember the coreid,
1027		 * this works because the core ids cannot be confused with
1028		 * core indices.
1029		 */
1030		*origidx = coreid;
1031		if (coreid == CC_CORE_ID)
1032			return (void *)CCREGS_FAST(sii);
1033		else if (coreid == sih->buscoretype)
1034			return (void *)PCIEREGS(sii);
1035	}
1036	INTR_OFF(sii, *intr_val);
1037	*origidx = sii->curidx;
1038	cc = si_setcore(sih, coreid, 0);
1039	ASSERT(cc != NULL);
1040
1041	return cc;
1042}
1043
1044/* restore coreidx and restore interrupt */
1045void
1046si_restore_core(si_t *sih, uint coreid, uint intr_val)
1047{
1048	si_info_t *sii;
1049
1050	sii = SI_INFO(sih);
1051	if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
1052		return;
1053
1054	si_setcoreidx(sih, coreid);
1055	INTR_RESTORE(sii, intr_val);
1056}
1057
1058int
1059si_numaddrspaces(si_t *sih)
1060{
1061	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1062		return sb_numaddrspaces(sih);
1063	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1064		return ai_numaddrspaces(sih);
1065	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1066		return ub_numaddrspaces(sih);
1067	else {
1068		ASSERT(0);
1069		return 0;
1070	}
1071}
1072
1073uint32
1074si_addrspace(si_t *sih, uint asidx)
1075{
1076	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1077		return sb_addrspace(sih, asidx);
1078	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1079		return ai_addrspace(sih, asidx);
1080	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1081		return ub_addrspace(sih, asidx);
1082	else {
1083		ASSERT(0);
1084		return 0;
1085	}
1086}
1087
1088uint32
1089si_addrspacesize(si_t *sih, uint asidx)
1090{
1091	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1092		return sb_addrspacesize(sih, asidx);
1093	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1094		return ai_addrspacesize(sih, asidx);
1095	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1096		return ub_addrspacesize(sih, asidx);
1097	else {
1098		ASSERT(0);
1099		return 0;
1100	}
1101}
1102
1103uint32
1104si_core_cflags(si_t *sih, uint32 mask, uint32 val)
1105{
1106	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1107		return sb_core_cflags(sih, mask, val);
1108	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1109		return ai_core_cflags(sih, mask, val);
1110	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1111		return ub_core_cflags(sih, mask, val);
1112	else {
1113		ASSERT(0);
1114		return 0;
1115	}
1116}
1117
1118void
1119si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
1120{
1121	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1122		sb_core_cflags_wo(sih, mask, val);
1123	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1124		ai_core_cflags_wo(sih, mask, val);
1125	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1126		ub_core_cflags_wo(sih, mask, val);
1127	else
1128		ASSERT(0);
1129}
1130
1131uint32
1132si_core_sflags(si_t *sih, uint32 mask, uint32 val)
1133{
1134	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1135		return sb_core_sflags(sih, mask, val);
1136	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1137		return ai_core_sflags(sih, mask, val);
1138	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1139		return ub_core_sflags(sih, mask, val);
1140	else {
1141		ASSERT(0);
1142		return 0;
1143	}
1144}
1145
1146bool
1147si_iscoreup(si_t *sih)
1148{
1149	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1150		return sb_iscoreup(sih);
1151	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1152		return ai_iscoreup(sih);
1153	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1154		return ub_iscoreup(sih);
1155	else {
1156		ASSERT(0);
1157		return FALSE;
1158	}
1159}
1160
1161void
1162si_write_wrapperreg(si_t *sih, uint32 offset, uint32 val)
1163{
1164	/* only for 4319, no requirement for SOCI_SB */
1165	if (CHIPTYPE(sih->socitype) == SOCI_AI) {
1166		ai_write_wrap_reg(sih, offset, val);
1167	}
1168	else
1169		return;
1170
1171	return;
1172}
1173
1174uint
1175si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
1176{
1177	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1178		return sb_corereg(sih, coreidx, regoff, mask, val);
1179	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1180		return ai_corereg(sih, coreidx, regoff, mask, val);
1181	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1182		return ub_corereg(sih, coreidx, regoff, mask, val);
1183	else {
1184		ASSERT(0);
1185		return 0;
1186	}
1187}
1188
1189void
1190si_core_disable(si_t *sih, uint32 bits)
1191{
1192	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1193		sb_core_disable(sih, bits);
1194	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1195		ai_core_disable(sih, bits);
1196	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1197		ub_core_disable(sih, bits);
1198}
1199
1200void
1201si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
1202{
1203	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1204		sb_core_reset(sih, bits, resetbits);
1205	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1206		ai_core_reset(sih, bits, resetbits);
1207	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1208		ub_core_reset(sih, bits, resetbits);
1209}
1210
1211/* Run bist on current core. Caller needs to take care of core-specific bist hazards */
1212int
1213si_corebist(si_t *sih)
1214{
1215	uint32 cflags;
1216	int result = 0;
1217
1218	/* Read core control flags */
1219	cflags = si_core_cflags(sih, 0, 0);
1220
1221	/* Set bist & fgc */
1222	si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC));
1223
1224	/* Wait for bist done */
1225	SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);
1226
1227	if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
1228		result = BCME_ERROR;
1229
1230	/* Reset core control flags */
1231	si_core_cflags(sih, 0xffff, cflags);
1232
1233	return result;
1234}
1235
1236static uint32
1237BCMINITFN(factor6)(uint32 x)
1238{
1239	switch (x) {
1240	case CC_F6_2:	return 2;
1241	case CC_F6_3:	return 3;
1242	case CC_F6_4:	return 4;
1243	case CC_F6_5:	return 5;
1244	case CC_F6_6:	return 6;
1245	case CC_F6_7:	return 7;
1246	default:	return 0;
1247	}
1248}
1249
1250/* calculate the speed the SI would run at given a set of clockcontrol values */
1251uint32
1252BCMINITFN(si_clock_rate)(uint32 pll_type, uint32 n, uint32 m)
1253{
1254	uint32 n1, n2, clock, m1, m2, m3, mc;
1255
1256	n1 = n & CN_N1_MASK;
1257	n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
1258
1259	if (pll_type == PLL_TYPE6) {
1260		if (m & CC_T6_MMASK)
1261			return CC_T6_M1;
1262		else
1263			return CC_T6_M0;
1264	} else if ((pll_type == PLL_TYPE1) ||
1265	           (pll_type == PLL_TYPE3) ||
1266	           (pll_type == PLL_TYPE4) ||
1267	           (pll_type == PLL_TYPE7)) {
1268		n1 = factor6(n1);
1269		n2 += CC_F5_BIAS;
1270	} else if (pll_type == PLL_TYPE2) {
1271		n1 += CC_T2_BIAS;
1272		n2 += CC_T2_BIAS;
1273		ASSERT((n1 >= 2) && (n1 <= 7));
1274		ASSERT((n2 >= 5) && (n2 <= 23));
1275	} else if (pll_type == PLL_TYPE5) {
1276		return (100000000);
1277	} else
1278		ASSERT(0);
1279	/* PLL types 3 and 7 use BASE2 (25Mhz) */
1280	if ((pll_type == PLL_TYPE3) ||
1281	    (pll_type == PLL_TYPE7)) {
1282		clock = CC_CLOCK_BASE2 * n1 * n2;
1283	} else
1284		clock = CC_CLOCK_BASE1 * n1 * n2;
1285
1286	if (clock == 0)
1287		return 0;
1288
1289	m1 = m & CC_M1_MASK;
1290	m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
1291	m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
1292	mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
1293
1294	if ((pll_type == PLL_TYPE1) ||
1295	    (pll_type == PLL_TYPE3) ||
1296	    (pll_type == PLL_TYPE4) ||
1297	    (pll_type == PLL_TYPE7)) {
1298		m1 = factor6(m1);
1299		if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
1300			m2 += CC_F5_BIAS;
1301		else
1302			m2 = factor6(m2);
1303		m3 = factor6(m3);
1304
1305		switch (mc) {
1306		case CC_MC_BYPASS:	return (clock);
1307		case CC_MC_M1:		return (clock / m1);
1308		case CC_MC_M1M2:	return (clock / (m1 * m2));
1309		case CC_MC_M1M2M3:	return (clock / (m1 * m2 * m3));
1310		case CC_MC_M1M3:	return (clock / (m1 * m3));
1311		default:		return (0);
1312		}
1313	} else {
1314		ASSERT(pll_type == PLL_TYPE2);
1315
1316		m1 += CC_T2_BIAS;
1317		m2 += CC_T2M2_BIAS;
1318		m3 += CC_T2_BIAS;
1319		ASSERT((m1 >= 2) && (m1 <= 7));
1320		ASSERT((m2 >= 3) && (m2 <= 10));
1321		ASSERT((m3 >= 2) && (m3 <= 7));
1322
1323		if ((mc & CC_T2MC_M1BYP) == 0)
1324			clock /= m1;
1325		if ((mc & CC_T2MC_M2BYP) == 0)
1326			clock /= m2;
1327		if ((mc & CC_T2MC_M3BYP) == 0)
1328			clock /= m3;
1329
1330		return (clock);
1331	}
1332}
1333
1334uint32
1335BCMINITFN(si_clock)(si_t *sih)
1336{
1337	si_info_t *sii;
1338	chipcregs_t *cc;
1339	uint32 n, m;
1340	uint idx;
1341	uint32 pll_type, rate;
1342	uint intr_val = 0;
1343
1344	sii = SI_INFO(sih);
1345	INTR_OFF(sii, intr_val);
1346	if (PMUCTL_ENAB(sih)) {
1347		rate = si_pmu_si_clock(sih, sii->osh);
1348		goto exit;
1349	}
1350
1351	idx = sii->curidx;
1352	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
1353	ASSERT(cc != NULL);
1354
1355	n = R_REG(sii->osh, &cc->clockcontrol_n);
1356	pll_type = sih->cccaps & CC_CAP_PLL_MASK;
1357	if (pll_type == PLL_TYPE6)
1358		m = R_REG(sii->osh, &cc->clockcontrol_m3);
1359	else if (pll_type == PLL_TYPE3)
1360		m = R_REG(sii->osh, &cc->clockcontrol_m2);
1361	else
1362		m = R_REG(sii->osh, &cc->clockcontrol_sb);
1363
1364	/* calculate rate */
1365	rate = si_clock_rate(pll_type, n, m);
1366
1367	if (pll_type == PLL_TYPE3)
1368		rate = rate / 2;
1369
1370	/* switch back to previous core */
1371	si_setcoreidx(sih, idx);
1372exit:
1373	INTR_RESTORE(sii, intr_val);
1374
1375	return rate;
1376}
1377
1378uint32
1379BCMINITFN(si_alp_clock)(si_t *sih)
1380{
1381	if (PMUCTL_ENAB(sih))
1382		return si_pmu_alp_clock(sih, si_osh(sih));
1383
1384	return ALP_CLOCK;
1385}
1386
1387uint32
1388BCMINITFN(si_ilp_clock)(si_t *sih)
1389{
1390	if (PMUCTL_ENAB(sih))
1391		return si_pmu_ilp_clock(sih, si_osh(sih));
1392
1393	return ILP_CLOCK;
1394}
1395
1396/* set chip watchdog reset timer to fire in 'ticks' */
1397void
1398si_watchdog(si_t *sih, uint ticks)
1399{
1400	uint nb, maxt;
1401
1402	if (PMUCTL_ENAB(sih)) {
1403
1404#if !defined(_CFE_) || defined(CFG_WL)
1405		if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) &&
1406		    (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) {
1407			si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2);
1408			si_setcore(sih, USB20D_CORE_ID, 0);
1409			si_core_disable(sih, 1);
1410			si_setcore(sih, CC_CORE_ID, 0);
1411		}
1412#endif /* !_CFE_ || CFG_WL */
1413
1414		if (CHIPID(sih->chip) == BCM4706_CHIP_ID)
1415			nb = 32;
1416		else
1417			nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24);
1418		/* The mips compiler uses the sllv instruction,
1419		 * so we specially handle the 32-bit case.
1420		 */
1421		if (nb == 32)
1422			maxt = 0xffffffff;
1423		else
1424			maxt = ((1 << nb) - 1);
1425
1426		if (ticks == 1)
1427			ticks = 2;
1428		else if (ticks > maxt)
1429			ticks = maxt;
1430
1431		si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog), ~0, ticks);
1432	} else {
1433		/* make sure we come up in fast clock mode; or if clearing, clear clock */
1434		si_clkctl_cc(sih, ticks ? CLK_FAST : CLK_DYNAMIC);
1435		maxt = (1 << 28) - 1;
1436		if (ticks > maxt)
1437			ticks = maxt;
1438
1439		si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks);
1440	}
1441}
1442
1443/* trigger watchdog reset after ms milliseconds */
1444void
1445si_watchdog_ms(si_t *sih, uint32 ms)
1446{
1447	si_watchdog(sih, wd_msticks * ms);
1448}
1449
1450#if defined(BCMASSERT_SUPPORT) || defined(BCMDBG_DUMP)
1451bool
1452si_taclear(si_t *sih, bool details)
1453{
1454	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1455		return sb_taclear(sih, details);
1456	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1457		return FALSE;
1458	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1459		return FALSE;
1460	else {
1461		ASSERT(0);
1462		return FALSE;
1463	}
1464}
1465#endif
1466
1467uint16
1468BCMATTACHFN(si_d11_devid)(si_t *sih)
1469{
1470	si_info_t *sii = SI_INFO(sih);
1471	uint16 device;
1472
1473	/* Fix device id for dual band BCM4328 */
1474	if (CHIPID(sih->chip) == BCM4328_CHIP_ID &&
1475	    (sih->chippkg == BCM4328USBDUAL_PKG_ID || sih->chippkg == BCM4328SDIODUAL_PKG_ID))
1476		device = BCM4328_D11DUAL_ID;
1477	else {
1478		/* normal case: nvram variable with devpath->devid->wl0id */
1479		if ((device = (uint16)si_getdevpathintvar(sih, "devid")) != 0)
1480			;
1481		/* Get devid from OTP/SPROM depending on where the SROM is read */
1482		else if ((device = (uint16)getintvar(sii->vars, "devid")) != 0)
1483			;
1484		/* no longer support wl0id, but keep the code here for backward compatibility. */
1485		else if ((device = (uint16)getintvar(sii->vars, "wl0id")) != 0)
1486			;
1487		else if (CHIPID(sih->chip) == BCM4712_CHIP_ID) {
1488			/* Chip specific conversion */
1489			if (sih->chippkg == BCM4712SMALL_PKG_ID)
1490				device = BCM4306_D11G_ID;
1491			else
1492				device = BCM4306_D11DUAL_ID;
1493		} else {
1494			/* ignore it */
1495			device = 0xffff;
1496		}
1497	}
1498	return device;
1499}
1500
1501int
1502BCMATTACHFN(si_corepciid)(si_t *sih, uint func, uint16 *pcivendor, uint16 *pcidevice,
1503                          uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif,
1504                          uint8 *pciheader)
1505{
1506	uint16 vendor = 0xffff, device = 0xffff;
1507	uint8 class, subclass, progif = 0;
1508	uint8 header = PCI_HEADER_NORMAL;
1509	uint32 core = si_coreid(sih);
1510
1511	/* Verify whether the function exists for the core */
1512	if (func >= (uint)(core == USB20H_CORE_ID ? 2 : 1))
1513		return BCME_ERROR;
1514
1515	/* Known vendor translations */
1516	switch (si_corevendor(sih)) {
1517	case SB_VEND_BCM:
1518	case MFGID_BRCM:
1519		vendor = VENDOR_BROADCOM;
1520		break;
1521	default:
1522		return BCME_ERROR;
1523	}
1524
1525	/* Determine class based on known core codes */
1526	switch (core) {
1527	case ENET_CORE_ID:
1528		class = PCI_CLASS_NET;
1529		subclass = PCI_NET_ETHER;
1530		device = BCM47XX_ENET_ID;
1531		break;
1532	case GIGETH_CORE_ID:
1533		class = PCI_CLASS_NET;
1534		subclass = PCI_NET_ETHER;
1535		device = BCM47XX_GIGETH_ID;
1536		break;
1537	case GMAC_CORE_ID:
1538		class = PCI_CLASS_NET;
1539		subclass = PCI_NET_ETHER;
1540		device = BCM47XX_GMAC_ID;
1541		break;
1542	case SDRAM_CORE_ID:
1543	case MEMC_CORE_ID:
1544	case DMEMC_CORE_ID:
1545	case SOCRAM_CORE_ID:
1546		class = PCI_CLASS_MEMORY;
1547		subclass = PCI_MEMORY_RAM;
1548		device = (uint16)core;
1549		break;
1550	case PCI_CORE_ID:
1551	case PCIE_CORE_ID:
1552		class = PCI_CLASS_BRIDGE;
1553		subclass = PCI_BRIDGE_PCI;
1554		device = (uint16)core;
1555		header = PCI_HEADER_BRIDGE;
1556		break;
1557	case MIPS33_CORE_ID:
1558	case MIPS74K_CORE_ID:
1559		class = PCI_CLASS_CPU;
1560		subclass = PCI_CPU_MIPS;
1561		device = (uint16)core;
1562		break;
1563	case CODEC_CORE_ID:
1564		class = PCI_CLASS_COMM;
1565		subclass = PCI_COMM_MODEM;
1566		device = BCM47XX_V90_ID;
1567		break;
1568	case I2S_CORE_ID:
1569		class = PCI_CLASS_MMEDIA;
1570		subclass = PCI_MMEDIA_AUDIO;
1571		device = BCM47XX_AUDIO_ID;
1572		break;
1573	case USB_CORE_ID:
1574	case USB11H_CORE_ID:
1575		class = PCI_CLASS_SERIAL;
1576		subclass = PCI_SERIAL_USB;
1577		progif = 0x10; /* OHCI */
1578		device = BCM47XX_USBH_ID;
1579		break;
1580	case USB20H_CORE_ID:
1581		class = PCI_CLASS_SERIAL;
1582		subclass = PCI_SERIAL_USB;
1583		progif = func == 0 ? 0x10 : 0x20; /* OHCI/EHCI */
1584		device = BCM47XX_USB20H_ID;
1585		header = 0x80; /* multifunction */
1586		break;
1587	case IPSEC_CORE_ID:
1588		class = PCI_CLASS_CRYPT;
1589		subclass = PCI_CRYPT_NETWORK;
1590		device = BCM47XX_IPSEC_ID;
1591		break;
1592	case ROBO_CORE_ID:
1593		/* Don't use class NETWORK, so wl/et won't attempt to recognize it */
1594		class = PCI_CLASS_COMM;
1595		subclass = PCI_COMM_OTHER;
1596		device = BCM47XX_ROBO_ID;
1597		break;
1598	case CC_CORE_ID:
1599		class = PCI_CLASS_MEMORY;
1600		subclass = PCI_MEMORY_FLASH;
1601		device = (uint16)core;
1602		break;
1603	case SATAXOR_CORE_ID:
1604		class = PCI_CLASS_XOR;
1605		subclass = PCI_XOR_QDMA;
1606		device = BCM47XX_SATAXOR_ID;
1607		break;
1608	case ATA100_CORE_ID:
1609		class = PCI_CLASS_DASDI;
1610		subclass = PCI_DASDI_IDE;
1611		device = BCM47XX_ATA100_ID;
1612		break;
1613	case USB11D_CORE_ID:
1614		class = PCI_CLASS_SERIAL;
1615		subclass = PCI_SERIAL_USB;
1616		device = BCM47XX_USBD_ID;
1617		break;
1618	case USB20D_CORE_ID:
1619		class = PCI_CLASS_SERIAL;
1620		subclass = PCI_SERIAL_USB;
1621		device = BCM47XX_USB20D_ID;
1622		break;
1623	case D11_CORE_ID:
1624		class = PCI_CLASS_NET;
1625		subclass = PCI_NET_OTHER;
1626		device = si_d11_devid(sih);
1627		break;
1628
1629	default:
1630		class = subclass = progif = 0xff;
1631		device = (uint16)core;
1632		break;
1633	}
1634
1635	*pcivendor = vendor;
1636	*pcidevice = device;
1637	*pciclass = class;
1638	*pcisubclass = subclass;
1639	*pciprogif = progif;
1640	*pciheader = header;
1641
1642	return 0;
1643}
1644
1645#if defined(BCMDBG_DUMP)
1646/* print interesting sbconfig registers */
1647void
1648si_dumpregs(si_t *sih, struct bcmstrbuf *b)
1649{
1650	si_info_t *sii;
1651	uint origidx, intr_val = 0;
1652
1653	sii = SI_INFO(sih);
1654	origidx = sii->curidx;
1655
1656	INTR_OFF(sii, intr_val);
1657	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1658		sb_dumpregs(sih, b);
1659	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
1660		ai_dumpregs(sih, b);
1661	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1662		ub_dumpregs(sih, b);
1663	else
1664		ASSERT(0);
1665
1666	si_setcoreidx(sih, origidx);
1667	INTR_RESTORE(sii, intr_val);
1668}
1669#endif
1670
1671
1672/* return the slow clock source - LPO, XTAL, or PCI */
1673static uint
1674si_slowclk_src(si_info_t *sii)
1675{
1676	chipcregs_t *cc;
1677
1678	ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1679
1680	if (sii->pub.ccrev < 6) {
1681		if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) &&
1682		    (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) &
1683		     PCI_CFG_GPIO_SCS))
1684			return (SCC_SS_PCI);
1685		else
1686			return (SCC_SS_XTAL);
1687	} else if (sii->pub.ccrev < 10) {
1688		cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx);
1689		return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
1690	} else	/* Insta-clock */
1691		return (SCC_SS_XTAL);
1692}
1693
1694/* return the ILP (slowclock) min or max frequency */
1695static uint
1696si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
1697{
1698	uint32 slowclk;
1699	uint div;
1700
1701	ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1702
1703	/* shouldn't be here unless we've established the chip has dynamic clk control */
1704	ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
1705
1706	slowclk = si_slowclk_src(sii);
1707	if (sii->pub.ccrev < 6) {
1708		if (slowclk == SCC_SS_PCI)
1709			return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64));
1710		else
1711			return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32));
1712	} else if (sii->pub.ccrev < 10) {
1713		div = 4 *
1714		        (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
1715		if (slowclk == SCC_SS_LPO)
1716			return (max_freq ? LPOMAXFREQ : LPOMINFREQ);
1717		else if (slowclk == SCC_SS_XTAL)
1718			return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div));
1719		else if (slowclk == SCC_SS_PCI)
1720			return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div));
1721		else
1722			ASSERT(0);
1723	} else {
1724		/* Chipc rev 10 is InstaClock */
1725		div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
1726		div = 4 * (div + 1);
1727		return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div));
1728	}
1729	return (0);
1730}
1731
1732static void
1733BCMINITFN(si_clkctl_setdelay)(si_info_t *sii, void *chipcregs)
1734{
1735	chipcregs_t *cc = (chipcregs_t *)chipcregs;
1736	uint slowmaxfreq, pll_delay, slowclk;
1737	uint pll_on_delay, fref_sel_delay;
1738
1739	pll_delay = PLL_DELAY;
1740
1741	/* If the slow clock is not sourced by the xtal then add the xtal_on_delay
1742	 * since the xtal will also be powered down by dynamic clk control logic.
1743	 */
1744
1745	slowclk = si_slowclk_src(sii);
1746	if (slowclk != SCC_SS_XTAL)
1747		pll_delay += XTAL_ON_DELAY;
1748
1749	/* Starting with 4318 it is ILP that is used for the delays */
1750	slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc);
1751
1752	pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
1753	fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
1754
1755	W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
1756	W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
1757}
1758
1759/* initialize power control delay registers */
1760void
1761BCMINITFN(si_clkctl_init)(si_t *sih)
1762{
1763	si_info_t *sii;
1764	uint origidx = 0;
1765	chipcregs_t *cc;
1766	bool fast;
1767
1768	if (!CCCTL_ENAB(sih))
1769		return;
1770
1771	sii = SI_INFO(sih);
1772	fast = SI_FAST(sii);
1773	if (!fast) {
1774		origidx = sii->curidx;
1775		if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
1776			return;
1777	} else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
1778		return;
1779	ASSERT(cc != NULL);
1780
1781	/* set all Instaclk chip ILP to 1 MHz */
1782	if (sih->ccrev >= 10)
1783		SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
1784		        (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
1785
1786	si_clkctl_setdelay(sii, (void *)(uintptr)cc);
1787
1788	if (!fast)
1789		si_setcoreidx(sih, origidx);
1790}
1791
1792/* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */
1793uint16
1794BCMINITFN(si_clkctl_fast_pwrup_delay)(si_t *sih)
1795{
1796	si_info_t *sii;
1797	uint origidx = 0;
1798	chipcregs_t *cc;
1799	uint slowminfreq;
1800	uint16 fpdelay;
1801	uint intr_val = 0;
1802	bool fast;
1803
1804	sii = SI_INFO(sih);
1805	if (PMUCTL_ENAB(sih)) {
1806		INTR_OFF(sii, intr_val);
1807		fpdelay = si_pmu_fast_pwrup_delay(sih, sii->osh);
1808		INTR_RESTORE(sii, intr_val);
1809		return fpdelay;
1810	}
1811
1812	if (!CCCTL_ENAB(sih))
1813		return 0;
1814
1815	fast = SI_FAST(sii);
1816	fpdelay = 0;
1817	if (!fast) {
1818		origidx = sii->curidx;
1819		INTR_OFF(sii, intr_val);
1820		if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
1821			goto done;
1822	}
1823	else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
1824		goto done;
1825	ASSERT(cc != NULL);
1826
1827	slowminfreq = si_slowclk_freq(sii, FALSE, cc);
1828	fpdelay = (((R_REG(sii->osh, &cc->pll_on_delay) + 2) * 1000000) +
1829	           (slowminfreq - 1)) / slowminfreq;
1830
1831done:
1832	if (!fast) {
1833		si_setcoreidx(sih, origidx);
1834		INTR_RESTORE(sii, intr_val);
1835	}
1836	return fpdelay;
1837}
1838
1839/* turn primary xtal and/or pll off/on */
1840int
1841si_clkctl_xtal(si_t *sih, uint what, bool on)
1842{
1843	si_info_t *sii;
1844	uint32 in, out, outen;
1845
1846	sii = SI_INFO(sih);
1847
1848	switch (BUSTYPE(sih->bustype)) {
1849
1850
1851	case PCMCIA_BUS:
1852		return (0);
1853
1854
1855	case PCI_BUS:
1856		/* pcie core doesn't have any mapping to control the xtal pu */
1857		if (PCIE(sii))
1858			return -1;
1859
1860		in = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_IN, sizeof(uint32));
1861		out = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32));
1862		outen = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUTEN, sizeof(uint32));
1863
1864		/*
1865		 * Avoid glitching the clock if GPRS is already using it.
1866		 * We can't actually read the state of the PLLPD so we infer it
1867		 * by the value of XTAL_PU which *is* readable via gpioin.
1868		 */
1869		if (on && (in & PCI_CFG_GPIO_XTAL))
1870			return (0);
1871
1872		if (what & XTAL)
1873			outen |= PCI_CFG_GPIO_XTAL;
1874		if (what & PLL)
1875			outen |= PCI_CFG_GPIO_PLL;
1876
1877		if (on) {
1878			/* turn primary xtal on */
1879			if (what & XTAL) {
1880				out |= PCI_CFG_GPIO_XTAL;
1881				if (what & PLL)
1882					out |= PCI_CFG_GPIO_PLL;
1883				OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
1884				                     sizeof(uint32), out);
1885				OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN,
1886				                     sizeof(uint32), outen);
1887				OSL_DELAY(XTAL_ON_DELAY);
1888			}
1889
1890			/* turn pll on */
1891			if (what & PLL) {
1892				out &= ~PCI_CFG_GPIO_PLL;
1893				OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
1894				                     sizeof(uint32), out);
1895				OSL_DELAY(2000);
1896			}
1897		} else {
1898			if (what & XTAL)
1899				out &= ~PCI_CFG_GPIO_XTAL;
1900			if (what & PLL)
1901				out |= PCI_CFG_GPIO_PLL;
1902			OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32), out);
1903			OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN, sizeof(uint32),
1904			                     outen);
1905		}
1906		return (0);
1907	default:
1908		return (-1);
1909	}
1910}
1911
1912/*
1913 *  clock control policy function throught chipcommon
1914 *
1915 *    set dynamic clk control mode (forceslow, forcefast, dynamic)
1916 *    returns true if we are forcing fast clock
1917 *    this is a wrapper over the next internal function
1918 *      to allow flexible policy settings for outside caller
1919 */
1920bool
1921si_clkctl_cc(si_t *sih, uint mode)
1922{
1923	si_info_t *sii;
1924
1925	sii = SI_INFO(sih);
1926
1927	/* chipcommon cores prior to rev6 don't support dynamic clock control */
1928	if (sih->ccrev < 6)
1929		return FALSE;
1930
1931	if (PCI_FORCEHT(sii))
1932		return (mode == CLK_FAST);
1933
1934	return _si_clkctl_cc(sii, mode);
1935}
1936
1937/* clk control mechanism through chipcommon, no policy checking */
1938static bool
1939_si_clkctl_cc(si_info_t *sii, uint mode)
1940{
1941	uint origidx = 0;
1942	chipcregs_t *cc;
1943	uint32 scc;
1944	uint intr_val = 0;
1945	bool fast = SI_FAST(sii);
1946
1947	/* chipcommon cores prior to rev6 don't support dynamic clock control */
1948	if (sii->pub.ccrev < 6)
1949		return (FALSE);
1950
1951	/* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */
1952	ASSERT(sii->pub.ccrev != 10);
1953
1954	if (!fast) {
1955		INTR_OFF(sii, intr_val);
1956		origidx = sii->curidx;
1957
1958		if ((BUSTYPE(sii->pub.bustype) == SI_BUS) &&
1959		    si_setcore(&sii->pub, MIPS33_CORE_ID, 0) &&
1960		    (si_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10))
1961			goto done;
1962
1963		cc = (chipcregs_t *) si_setcore(&sii->pub, CC_CORE_ID, 0);
1964	} else if ((cc = (chipcregs_t *) CCREGS_FAST(sii)) == NULL)
1965		goto done;
1966	ASSERT(cc != NULL);
1967
1968	if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20))
1969		goto done;
1970
1971	switch (mode) {
1972	case CLK_FAST:	/* FORCEHT, fast (pll) clock */
1973		if (sii->pub.ccrev < 10) {
1974			/* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
1975			si_clkctl_xtal(&sii->pub, XTAL, ON);
1976			SET_REG(sii->osh, &cc->slow_clk_ctl, (SCC_XC | SCC_FS | SCC_IP), SCC_IP);
1977		} else if (sii->pub.ccrev < 20) {
1978			OR_REG(sii->osh, &cc->system_clk_ctl, SYCC_HR);
1979		} else {
1980			OR_REG(sii->osh, &cc->clk_ctl_st, CCS_FORCEHT);
1981		}
1982
1983		/* wait for the PLL */
1984		if (PMUCTL_ENAB(&sii->pub)) {
1985			uint32 htavail = CCS_HTAVAIL;
1986			if (CHIPID(sii->pub.chip) == BCM4328_CHIP_ID)
1987				htavail = CCS0_HTAVAIL;
1988			SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail) == 0),
1989			         PMU_MAX_TRANSITION_DLY);
1990			ASSERT(R_REG(sii->osh, &cc->clk_ctl_st) & htavail);
1991		} else {
1992			OSL_DELAY(PLL_DELAY);
1993		}
1994		break;
1995
1996	case CLK_DYNAMIC:	/* enable dynamic clock control */
1997		if (sii->pub.ccrev < 10) {
1998			scc = R_REG(sii->osh, &cc->slow_clk_ctl);
1999			scc &= ~(SCC_FS | SCC_IP | SCC_XC);
2000			if ((scc & SCC_SS_MASK) != SCC_SS_XTAL)
2001				scc |= SCC_XC;
2002			W_REG(sii->osh, &cc->slow_clk_ctl, scc);
2003
2004			/* for dynamic control, we have to release our xtal_pu "force on" */
2005			if (scc & SCC_XC)
2006				si_clkctl_xtal(&sii->pub, XTAL, OFF);
2007		} else if (sii->pub.ccrev < 20) {
2008			/* Instaclock */
2009			AND_REG(sii->osh, &cc->system_clk_ctl, ~SYCC_HR);
2010		} else {
2011			AND_REG(sii->osh, &cc->clk_ctl_st, ~CCS_FORCEHT);
2012		}
2013		break;
2014
2015	default:
2016		ASSERT(0);
2017	}
2018
2019done:
2020	if (!fast) {
2021		si_setcoreidx(&sii->pub, origidx);
2022		INTR_RESTORE(sii, intr_val);
2023	}
2024	return (mode == CLK_FAST);
2025}
2026
2027/* Build device path. Support SI, PCI, and JTAG for now. */
2028int
2029BCMNMIATTACHFN(si_devpath)(si_t *sih, char *path, int size)
2030{
2031	int slen;
2032
2033	ASSERT(path != NULL);
2034	ASSERT(size >= SI_DEVPATH_BUFSZ);
2035
2036	if (!path || size <= 0)
2037		return -1;
2038
2039	switch (BUSTYPE(sih->bustype)) {
2040	case SI_BUS:
2041	case JTAG_BUS:
2042		slen = snprintf(path, (size_t)size, "sb/%u/", si_coreidx(sih));
2043		break;
2044	case PCI_BUS:
2045		ASSERT((SI_INFO(sih))->osh != NULL);
2046		slen = snprintf(path, (size_t)size, "pci/%u/%u/",
2047		                OSL_PCI_BUS((SI_INFO(sih))->osh),
2048		                OSL_PCI_SLOT((SI_INFO(sih))->osh));
2049		break;
2050	case PCMCIA_BUS:
2051		SI_ERROR(("si_devpath: OSL_PCMCIA_BUS() not implemented, bus 1 assumed\n"));
2052		SI_ERROR(("si_devpath: OSL_PCMCIA_SLOT() not implemented, slot 1 assumed\n"));
2053		slen = snprintf(path, (size_t)size, "pc/1/1/");
2054		break;
2055	default:
2056		slen = -1;
2057		ASSERT(0);
2058		break;
2059	}
2060
2061	if (slen < 0 || slen >= size) {
2062		path[0] = '\0';
2063		return -1;
2064	}
2065
2066	return 0;
2067}
2068
2069char *
2070BCMATTACHFN(si_coded_devpathvar)(si_t *sih, char *varname, int var_len, const char *name)
2071{
2072	char pathname[SI_DEVPATH_BUFSZ + 32];
2073	char devpath[SI_DEVPATH_BUFSZ + 32];
2074	char *p;
2075	int idx;
2076	int len;
2077
2078	/* try to get compact devpath if it exist */
2079	if (si_devpath(sih, devpath, SI_DEVPATH_BUFSZ) == 0) {
2080		len = strlen(devpath);
2081		devpath[len - 1] = '\0';
2082		for (idx = 0; idx < SI_MAXCORES; idx++) {
2083			snprintf(pathname, SI_DEVPATH_BUFSZ, "devpath%d", idx);
2084			if ((p = getvar(NULL, pathname)) == NULL)
2085				continue;
2086
2087			if (strncmp(p, devpath, len) == 0) {
2088				snprintf(varname, var_len, "%d:%s", idx, name);
2089				return varname;
2090			}
2091		}
2092	}
2093
2094	return NULL;
2095}
2096
2097/* Get a variable, but only if it has a devpath prefix */
2098char *
2099BCMATTACHFN(si_getdevpathvar)(si_t *sih, const char *name)
2100{
2101	char varname[SI_DEVPATH_BUFSZ + 32];
2102	char *val;
2103
2104	si_devpathvar(sih, varname, sizeof(varname), name);
2105
2106	if ((val = getvar(NULL, varname)) != NULL)
2107		return val;
2108
2109	/* try to get compact devpath if it exist */
2110	if (si_coded_devpathvar(sih, varname, sizeof(varname), name) == NULL)
2111		return NULL;
2112
2113	return (getvar(NULL, varname));
2114}
2115
2116/* Get a variable, but only if it has a devpath prefix */
2117int
2118BCMATTACHFN(si_getdevpathintvar)(si_t *sih, const char *name)
2119{
2120#if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS)
2121	return (getintvar(NULL, name));
2122#else
2123	char varname[SI_DEVPATH_BUFSZ + 32];
2124	int val;
2125
2126	si_devpathvar(sih, varname, sizeof(varname), name);
2127
2128	if ((val = getintvar(NULL, varname)) != 0)
2129		return val;
2130
2131	/* try to get compact devpath if it exist */
2132	if (si_coded_devpathvar(sih, varname, sizeof(varname), name) == NULL)
2133		return 0;
2134
2135	return (getintvar(NULL, varname));
2136#endif /* BCMBUSTYPE && BCMBUSTYPE == SI_BUS */
2137}
2138
2139#ifndef DONGLEBUILD
2140char *
2141si_getnvramflvar(si_t *sih, const char *name)
2142{
2143	return (getvar(NULL, name));
2144}
2145#endif /* DONGLEBUILD */
2146
2147/* Concatenate the dev path with a varname into the given 'var' buffer
2148 * and return the 'var' pointer.
2149 * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned.
2150 * On overflow, the first char will be set to '\0'.
2151 */
2152static char *
2153BCMATTACHFN(si_devpathvar)(si_t *sih, char *var, int len, const char *name)
2154{
2155	uint path_len;
2156
2157	if (!var || len <= 0)
2158		return var;
2159
2160	if (si_devpath(sih, var, len) == 0) {
2161		path_len = strlen(var);
2162
2163		if (strlen(name) + 1 > (uint)(len - path_len))
2164			var[0] = '\0';
2165		else
2166			strncpy(var + path_len, name, len - path_len - 1);
2167	}
2168
2169	return var;
2170}
2171
2172
2173uint32
2174si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint type)
2175{
2176	si_info_t *sii;
2177
2178	sii = SI_INFO(sih);
2179
2180	if (!PCIE(sii)) {
2181		SI_ERROR(("%s: Not a PCIE device\n", __FUNCTION__));
2182		return 0;
2183	}
2184
2185	return pcicore_pciereg(sii->pch, offset, mask, val, type);
2186}
2187
2188uint32
2189si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint32 mask, uint32 val)
2190{
2191	si_info_t *sii;
2192
2193	sii = SI_INFO(sih);
2194
2195	if (!PCIE(sii)) {
2196		SI_ERROR(("%s: Not a PCIE device\n", __FUNCTION__));
2197		return 0;
2198	}
2199
2200	return pcicore_pcieserdesreg(sii->pch, mdioslave, offset, mask, val);
2201
2202}
2203
2204/* return TRUE if PCIE capability exists in the pci config space */
2205static bool
2206si_ispcie(si_info_t *sii)
2207{
2208	uint8 cap_ptr;
2209
2210	if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
2211		return FALSE;
2212
2213	cap_ptr = pcicore_find_pci_capability(sii->osh, PCI_CAP_PCIECAP_ID, NULL, NULL);
2214	if (!cap_ptr)
2215		return FALSE;
2216
2217	return TRUE;
2218}
2219
2220/* Wake-on-wireless-LAN (WOWL) support functions */
2221/* Enable PME generation and disable clkreq */
2222void
2223si_pci_pmeen(si_t *sih)
2224{
2225	si_info_t *sii;
2226
2227	sii = SI_INFO(sih);
2228
2229	pcicore_pmeen(sii->pch);
2230}
2231
2232/* Return TRUE if PME status is set */
2233bool
2234si_pci_pmestat(si_t *sih)
2235{
2236	si_info_t *sii;
2237
2238	sii = SI_INFO(sih);
2239
2240	return pcicore_pmestat(sii->pch);
2241}
2242
2243/* Disable PME generation, clear the PME status bit if set */
2244void
2245si_pci_pmeclr(si_t *sih)
2246{
2247	si_info_t *sii;
2248
2249	sii = SI_INFO(sih);
2250
2251	pcicore_pmeclr(sii->pch);
2252}
2253
2254/* initialize the pcmcia core */
2255void
2256si_pcmcia_init(si_t *sih)
2257{
2258	si_info_t *sii;
2259	uint8 cor = 0;
2260
2261	sii = SI_INFO(sih);
2262
2263	/* enable d11 mac interrupts */
2264	OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1);
2265	cor |= COR_IRQEN | COR_FUNEN;
2266	OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1);
2267
2268}
2269
2270
2271bool
2272BCMATTACHFN(si_pci_war16165)(si_t *sih)
2273{
2274	si_info_t *sii;
2275
2276	sii = SI_INFO(sih);
2277
2278	return (PCI(sii) && (sih->buscorerev <= 10));
2279}
2280
2281/* Disable pcie_war_ovr for some platforms (sigh!)
2282 * This is for boards that have BFL2_PCIEWAR_OVR set
2283 * but are in systems that still want the benefits of ASPM
2284 * Note that this should be done AFTER si_doattach
2285 */
2286void
2287si_pcie_war_ovr_update(si_t *sih, uint8 aspm)
2288{
2289	si_info_t *sii;
2290
2291	sii = SI_INFO(sih);
2292
2293	if (!PCIE(sii))
2294		return;
2295
2296	pcie_war_ovr_aspm_update(sii->pch, aspm);
2297}
2298
2299void
2300si_pcie_power_save_enable(si_t *sih, bool enable)
2301{
2302	si_info_t *sii;
2303
2304	sii = SI_INFO(sih);
2305
2306	if (!PCIE(sii))
2307		return;
2308
2309	pcie_power_save_enable(sii->pch, enable);
2310}
2311
2312void
2313si_pcie_set_request_size(si_t *sih, uint16 size)
2314{
2315	si_info_t *sii;
2316
2317	sii = SI_INFO(sih);
2318
2319	if (!PCIE(sii))
2320		return;
2321
2322	pcie_set_request_size(sii->pch, size);
2323}
2324
2325uint16
2326si_pcie_get_request_size(si_t *sih)
2327{
2328	si_info_t *sii;
2329
2330	sii = SI_INFO(sih);
2331
2332	if (!PCIE(sii))
2333		return (0);
2334
2335	return pcie_get_request_size(sii->pch);
2336}
2337
2338/* back door for other module to override chippkg */
2339void
2340si_chippkg_set(si_t *sih, uint val)
2341{
2342	si_info_t *sii;
2343
2344	sii = SI_INFO(sih);
2345
2346	sii->pub.chippkg = val;
2347}
2348
2349void
2350BCMINITFN(si_pci_up)(si_t *sih)
2351{
2352	si_info_t *sii;
2353
2354	sii = SI_INFO(sih);
2355
2356	/* if not pci bus, we're done */
2357	if (BUSTYPE(sih->bustype) != PCI_BUS)
2358		return;
2359
2360	if (PCI_FORCEHT(sii))
2361		_si_clkctl_cc(sii, CLK_FAST);
2362
2363	if (PCIE(sii)) {
2364		pcicore_up(sii->pch, SI_PCIUP);
2365		if (((CHIPID(sih->chip) == BCM4311_CHIP_ID) && (CHIPREV(sih->chiprev) == 2)) ||
2366		    (CHIPID(sih->chip) == BCM4312_CHIP_ID))
2367			sb_set_initiator_to((void *)sii, 0x3,
2368			                    si_findcoreidx((void *)sii, D11_CORE_ID, 0));
2369	}
2370}
2371
2372/* Unconfigure and/or apply various WARs when system is going to sleep mode */
2373void
2374BCMUNINITFN(si_pci_sleep)(si_t *sih)
2375{
2376	si_info_t *sii;
2377
2378	sii = SI_INFO(sih);
2379
2380	pcicore_sleep(sii->pch);
2381}
2382
2383/* Unconfigure and/or apply various WARs when going down */
2384void
2385BCMINITFN(si_pci_down)(si_t *sih)
2386{
2387	si_info_t *sii;
2388
2389	sii = SI_INFO(sih);
2390
2391	/* if not pci bus, we're done */
2392	if (BUSTYPE(sih->bustype) != PCI_BUS)
2393		return;
2394
2395	/* release FORCEHT since chip is going to "down" state */
2396	if (PCI_FORCEHT(sii))
2397		_si_clkctl_cc(sii, CLK_DYNAMIC);
2398
2399	pcicore_down(sii->pch, SI_PCIDOWN);
2400}
2401
2402/*
2403 * Configure the pci core for pci client (NIC) action
2404 * coremask is the bitvec of cores by index to be enabled.
2405 */
2406void
2407BCMATTACHFN(si_pci_setup)(si_t *sih, uint coremask)
2408{
2409	si_info_t *sii;
2410	sbpciregs_t *pciregs = NULL;
2411	uint32 siflag = 0, w;
2412	uint idx = 0;
2413
2414	sii = SI_INFO(sih);
2415
2416	if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
2417		return;
2418
2419	ASSERT(PCI(sii) || PCIE(sii));
2420	ASSERT(sii->pub.buscoreidx != BADIDX);
2421
2422	if (PCI(sii)) {
2423		/* get current core index */
2424		idx = sii->curidx;
2425
2426		/* we interrupt on this backplane flag number */
2427		siflag = si_flag(sih);
2428
2429		/* switch over to pci core */
2430		pciregs = (sbpciregs_t *)si_setcoreidx(sih, sii->pub.buscoreidx);
2431	}
2432
2433	/*
2434	 * Enable sb->pci interrupts.  Assume
2435	 * PCI rev 2.3 support was added in pci core rev 6 and things changed..
2436	 */
2437	if (PCIE(sii) || (PCI(sii) && ((sii->pub.buscorerev) >= 6))) {
2438		/* pci config write to set this core bit in PCIIntMask */
2439		w = OSL_PCI_READ_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32));
2440		w |= (coremask << PCI_SBIM_SHIFT);
2441#ifdef USER_MODE
2442		/* User mode operate with interrupt disabled */
2443		w &= !(coremask << PCI_SBIM_SHIFT);
2444#endif
2445		OSL_PCI_WRITE_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32), w);
2446	} else {
2447		/* set sbintvec bit for our flag number */
2448		si_setint(sih, siflag);
2449	}
2450
2451	if (PCI(sii)) {
2452		OR_REG(sii->osh, &pciregs->sbtopci2, (SBTOPCI_PREF | SBTOPCI_BURST));
2453		if (sii->pub.buscorerev >= 11) {
2454			OR_REG(sii->osh, &pciregs->sbtopci2, SBTOPCI_RC_READMULTI);
2455			w = R_REG(sii->osh, &pciregs->clkrun);
2456			W_REG(sii->osh, &pciregs->clkrun, (w | PCI_CLKRUN_DSBL));
2457			w = R_REG(sii->osh, &pciregs->clkrun);
2458		}
2459
2460		/* switch back to previous core */
2461		si_setcoreidx(sih, idx);
2462	}
2463}
2464
2465uint8
2466si_pcieclkreq(si_t *sih, uint32 mask, uint32 val)
2467{
2468	si_info_t *sii;
2469
2470	sii = SI_INFO(sih);
2471
2472	if (!(PCIE(sii)))
2473		return 0;
2474	return pcie_clkreq(sii->pch, mask, val);
2475}
2476
2477uint32
2478si_pcielcreg(si_t *sih, uint32 mask, uint32 val)
2479{
2480	si_info_t *sii;
2481
2482	sii = SI_INFO(sih);
2483
2484	if (!PCIE(sii))
2485		return 0;
2486
2487	return pcie_lcreg(sii->pch, mask, val);
2488}
2489
2490/* indirect way to read pcie config regs */
2491uint
2492si_pcie_readreg(void *sih, uint addrtype, uint offset)
2493{
2494	return pcie_readreg(((si_info_t *)sih)->osh, (sbpcieregs_t *)PCIEREGS(((si_info_t *)sih)),
2495	                    addrtype, offset);
2496}
2497
2498
2499/*
2500 * Fixup SROMless PCI device's configuration.
2501 * The current core may be changed upon return.
2502 */
2503int
2504si_pci_fixcfg(si_t *sih)
2505{
2506	uint origidx, pciidx;
2507	sbpciregs_t *pciregs = NULL;
2508	sbpcieregs_t *pcieregs = NULL;
2509	void *regs = NULL;
2510	uint16 val16, *reg16 = NULL;
2511	uint32 w;
2512
2513	si_info_t *sii = SI_INFO(sih);
2514
2515	ASSERT(BUSTYPE(sii->pub.bustype) == PCI_BUS);
2516
2517	if ((CHIPID(sii->pub.chip) == BCM4321_CHIP_ID) && (CHIPREV(sii->pub.chiprev) < 2)) {
2518		w = (CHIPREV(sii->pub.chiprev) == 0) ?
2519		        CHIPCTRL_4321A0_DEFAULT : CHIPCTRL_4321A1_DEFAULT;
2520		si_corereg(&sii->pub, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol), ~0, w);
2521	}
2522
2523	/* Fixup PI in SROM shadow area to enable the correct PCI core access */
2524	/* save the current index */
2525	origidx = si_coreidx(&sii->pub);
2526
2527	/* check 'pi' is correct and fix it if not */
2528	if (sii->pub.buscoretype == PCIE_CORE_ID) {
2529		pcieregs = (sbpcieregs_t *)si_setcore(&sii->pub, PCIE_CORE_ID, 0);
2530		regs = pcieregs;
2531		ASSERT(pcieregs != NULL);
2532		reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
2533	} else if (sii->pub.buscoretype == PCI_CORE_ID) {
2534		pciregs = (sbpciregs_t *)si_setcore(&sii->pub, PCI_CORE_ID, 0);
2535		regs = pciregs;
2536		ASSERT(pciregs != NULL);
2537		reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
2538	}
2539	pciidx = si_coreidx(&sii->pub);
2540	val16 = R_REG(sii->osh, reg16);
2541	if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (uint16)pciidx) {
2542		val16 = (uint16)(pciidx << SRSH_PI_SHIFT) | (val16 & ~SRSH_PI_MASK);
2543		W_REG(sii->osh, reg16, val16);
2544	}
2545
2546	/* restore the original index */
2547	si_setcoreidx(&sii->pub, origidx);
2548
2549	pcicore_hwup(sii->pch);
2550	return 0;
2551}
2552
2553#if defined(BCMDBG_DUMP)
2554
2555void
2556si_dump(si_t *sih, struct bcmstrbuf *b)
2557{
2558	si_info_t *sii;
2559	uint i;
2560
2561	sii = SI_INFO(sih);
2562
2563	bcm_bprintf(b, "si %p chip 0x%x chiprev 0x%x boardtype 0x%x boardvendor 0x%x bus %d\n",
2564	            sii, sih->chip, sih->chiprev, sih->boardtype, sih->boardvendor, sih->bustype);
2565	bcm_bprintf(b, "osh %p curmap %p\n",
2566	            sii->osh, sii->curmap);
2567	if (CHIPTYPE(sih->socitype) == SOCI_SB)
2568		bcm_bprintf(b, "sonicsrev %d ", sih->socirev);
2569	bcm_bprintf(b, "ccrev %d buscoretype 0x%x buscorerev %d curidx %d\n",
2570	            sih->ccrev, sih->buscoretype, sih->buscorerev, sii->curidx);
2571
2572
2573	bcm_bprintf(b, "cores:  ");
2574	for (i = 0; i < sii->numcores; i++)
2575		bcm_bprintf(b, "0x%x ", sii->coreid[i]);
2576	bcm_bprintf(b, "\n");
2577}
2578
2579void
2580si_ccreg_dump(si_t *sih, struct bcmstrbuf *b)
2581{
2582	si_info_t *sii;
2583	uint origidx;
2584	uint i, intr_val = 0;
2585	chipcregs_t *cc;
2586
2587	sii = SI_INFO(sih);
2588	origidx = sii->curidx;
2589
2590	/* only support corerev 22 for now */
2591	if (sih->ccrev != 23)
2592		return;
2593
2594	INTR_OFF(sii, intr_val);
2595
2596	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2597
2598	bcm_bprintf(b, "\n===cc(rev %d) registers(offset val)===\n", sih->ccrev);
2599	for (i = 0; i <= 0xc4; i += 4) {
2600		if (i == 0x4c) {
2601			bcm_bprintf(b, "\n");
2602			continue;
2603		}
2604		bcm_bprintf(b, "0x%x\t0x%x\n", i, *(uint32 *)((uintptr)cc + i));
2605	}
2606
2607	bcm_bprintf(b, "\n");
2608
2609	for (i = 0x1e0; i <= 0x1e4; i += 4) {
2610		bcm_bprintf(b, "0x%x\t0x%x\n", i, *(uint32 *)((uintptr)cc + i));
2611	}
2612	bcm_bprintf(b, "\n");
2613
2614	if (sih->cccaps & CC_CAP_PMU) {
2615		for (i = 0x600; i <= 0x660; i += 4) {
2616			bcm_bprintf(b, "0x%x\t0x%x\n", i, *(uint32 *)((uintptr)cc + i));
2617		}
2618	}
2619	bcm_bprintf(b, "\n");
2620
2621	si_setcoreidx(sih, origidx);
2622	INTR_RESTORE(sii, intr_val);
2623}
2624
2625/* dump dynamic clock control related registers */
2626void
2627si_clkctl_dump(si_t *sih, struct bcmstrbuf *b)
2628{
2629	si_info_t *sii;
2630	chipcregs_t *cc;
2631	uint origidx;
2632	uint intr_val = 0;
2633
2634	if (!(sih->cccaps & CC_CAP_PWR_CTL))
2635		return;
2636
2637	sii = SI_INFO(sih);
2638	INTR_OFF(sii, intr_val);
2639	origidx = sii->curidx;
2640	if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
2641		goto done;
2642
2643	bcm_bprintf(b, "pll_on_delay 0x%x fref_sel_delay 0x%x ",
2644		cc->pll_on_delay, cc->fref_sel_delay);
2645	if ((sih->ccrev >= 6) && (sih->ccrev < 10))
2646		bcm_bprintf(b, "slow_clk_ctl 0x%x ", cc->slow_clk_ctl);
2647	if (sih->ccrev >= 10) {
2648		bcm_bprintf(b, "system_clk_ctl 0x%x ", cc->system_clk_ctl);
2649		bcm_bprintf(b, "clkstatestretch 0x%x ", cc->clkstatestretch);
2650	}
2651
2652	if (BUSTYPE(sih->bustype) == PCI_BUS)
2653		bcm_bprintf(b, "gpioout 0x%x gpioouten 0x%x ",
2654		            OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)),
2655		            OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUTEN, sizeof(uint32)));
2656
2657	if (sih->cccaps & CC_CAP_PMU) {
2658		/* dump some PMU register ? */
2659	}
2660	bcm_bprintf(b, "\n");
2661
2662	si_setcoreidx(sih, origidx);
2663done:
2664	INTR_RESTORE(sii, intr_val);
2665}
2666
2667int
2668si_dump_pcieregs(si_t *sih, struct bcmstrbuf *b)
2669{
2670	si_info_t *sii;
2671
2672	sii = SI_INFO(sih);
2673
2674	if (!PCIE(sii))
2675		return BCME_ERROR;
2676
2677	return pcicore_dump_pcieregs(sii->pch, b);
2678}
2679
2680int
2681si_gpiodump(si_t *sih, struct bcmstrbuf *b)
2682{
2683	si_info_t *sii;
2684	uint origidx;
2685	uint intr_val = 0;
2686	chipcregs_t *cc;
2687
2688	sii = SI_INFO(sih);
2689
2690	INTR_OFF(sii, intr_val);
2691
2692	origidx = si_coreidx(sih);
2693
2694	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2695	ASSERT(cc);
2696
2697	bcm_bprintf(b, "GPIOregs\t");
2698
2699	bcm_bprintf(b, "gpioin 0x%x ", R_REG(sii->osh, &cc->gpioin));
2700	bcm_bprintf(b, "gpioout 0x%x ", R_REG(sii->osh, &cc->gpioout));
2701	bcm_bprintf(b, "gpioouten 0x%x ", R_REG(sii->osh, &cc->gpioouten));
2702	bcm_bprintf(b, "gpiocontrol 0x%x ", R_REG(sii->osh, &cc->gpiocontrol));
2703	bcm_bprintf(b, "gpiointpolarity 0x%x ", R_REG(sii->osh, &cc->gpiointpolarity));
2704	bcm_bprintf(b, "gpiointmask 0x%x ", R_REG(sii->osh, &cc->gpiointmask));
2705
2706	if (sii->pub.ccrev >= 16) {
2707		bcm_bprintf(b, "gpiotimerval 0x%x ", R_REG(sii->osh, &cc->gpiotimerval));
2708		bcm_bprintf(b, "gpiotimeroutmask 0x%x", R_REG(sii->osh, &cc->gpiotimeroutmask));
2709	}
2710	bcm_bprintf(b, "\n");
2711
2712	/* restore the original index */
2713	si_setcoreidx(sih, origidx);
2714
2715	INTR_RESTORE(sii, intr_val);
2716	return 0;
2717
2718}
2719#endif
2720
2721/* change logical "focus" to the gpio core for optimized access */
2722void *
2723si_gpiosetcore(si_t *sih)
2724{
2725	return (si_setcoreidx(sih, SI_CC_IDX));
2726}
2727
2728/* mask&set gpiocontrol bits */
2729uint32
2730si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2731{
2732	uint regoff;
2733
2734	regoff = 0;
2735
2736	/* gpios could be shared on router platforms
2737	 * ignore reservation if it's high priority (e.g., test apps)
2738	 */
2739	if ((priority != GPIO_HI_PRIORITY) &&
2740	    (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2741		mask = priority ? (si_gpioreservation & mask) :
2742			((si_gpioreservation | mask) & ~(si_gpioreservation));
2743		val &= mask;
2744	}
2745
2746	regoff = OFFSETOF(chipcregs_t, gpiocontrol);
2747	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2748}
2749
2750/* mask&set gpio output enable bits */
2751uint32
2752si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2753{
2754	uint regoff;
2755
2756	regoff = 0;
2757
2758	/* gpios could be shared on router platforms
2759	 * ignore reservation if it's high priority (e.g., test apps)
2760	 */
2761	if ((priority != GPIO_HI_PRIORITY) &&
2762	    (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2763		mask = priority ? (si_gpioreservation & mask) :
2764			((si_gpioreservation | mask) & ~(si_gpioreservation));
2765		val &= mask;
2766	}
2767
2768	regoff = OFFSETOF(chipcregs_t, gpioouten);
2769	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2770}
2771
2772/* mask&set gpio output bits */
2773uint32
2774si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2775{
2776	uint regoff;
2777
2778	regoff = 0;
2779
2780	/* gpios could be shared on router platforms
2781	 * ignore reservation if it's high priority (e.g., test apps)
2782	 */
2783	if ((priority != GPIO_HI_PRIORITY) &&
2784	    (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2785		mask = priority ? (si_gpioreservation & mask) :
2786			((si_gpioreservation | mask) & ~(si_gpioreservation));
2787		val &= mask;
2788	}
2789
2790	regoff = OFFSETOF(chipcregs_t, gpioout);
2791	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2792}
2793
2794/* reserve one gpio */
2795uint32
2796si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority)
2797{
2798	si_info_t *sii;
2799
2800	sii = SI_INFO(sih);
2801
2802	/* only cores on SI_BUS share GPIO's and only applcation users need to
2803	 * reserve/release GPIO
2804	 */
2805	if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
2806		ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
2807		return 0xffffffff;
2808	}
2809	/* make sure only one bit is set */
2810	if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
2811		ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
2812		return 0xffffffff;
2813	}
2814
2815	/* already reserved */
2816	if (si_gpioreservation & gpio_bitmask)
2817		return 0xffffffff;
2818	/* set reservation */
2819	si_gpioreservation |= gpio_bitmask;
2820
2821	return si_gpioreservation;
2822}
2823
2824/* release one gpio */
2825/*
2826 * releasing the gpio doesn't change the current value on the GPIO last write value
2827 * persists till some one overwrites it
2828 */
2829
2830uint32
2831si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority)
2832{
2833	si_info_t *sii;
2834
2835	sii = SI_INFO(sih);
2836
2837	/* only cores on SI_BUS share GPIO's and only applcation users need to
2838	 * reserve/release GPIO
2839	 */
2840	if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
2841		ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
2842		return 0xffffffff;
2843	}
2844	/* make sure only one bit is set */
2845	if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
2846		ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
2847		return 0xffffffff;
2848	}
2849
2850	/* already released */
2851	if (!(si_gpioreservation & gpio_bitmask))
2852		return 0xffffffff;
2853
2854	/* clear reservation */
2855	si_gpioreservation &= ~gpio_bitmask;
2856
2857	return si_gpioreservation;
2858}
2859
2860/* return the current gpioin register value */
2861uint32
2862si_gpioin(si_t *sih)
2863{
2864	si_info_t *sii;
2865	uint regoff;
2866
2867	sii = SI_INFO(sih);
2868	regoff = 0;
2869
2870	regoff = OFFSETOF(chipcregs_t, gpioin);
2871	return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0));
2872}
2873
2874/* mask&set gpio interrupt polarity bits */
2875uint32
2876si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2877{
2878	si_info_t *sii;
2879	uint regoff;
2880
2881	sii = SI_INFO(sih);
2882	regoff = 0;
2883
2884	/* gpios could be shared on router platforms */
2885	if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2886		mask = priority ? (si_gpioreservation & mask) :
2887			((si_gpioreservation | mask) & ~(si_gpioreservation));
2888		val &= mask;
2889	}
2890
2891	regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
2892	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2893}
2894
2895/* mask&set gpio interrupt mask bits */
2896uint32
2897si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2898{
2899	si_info_t *sii;
2900	uint regoff;
2901
2902	sii = SI_INFO(sih);
2903	regoff = 0;
2904
2905	/* gpios could be shared on router platforms */
2906	if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2907		mask = priority ? (si_gpioreservation & mask) :
2908			((si_gpioreservation | mask) & ~(si_gpioreservation));
2909		val &= mask;
2910	}
2911
2912	regoff = OFFSETOF(chipcregs_t, gpiointmask);
2913	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2914}
2915
2916/* assign the gpio to an led */
2917uint32
2918si_gpioled(si_t *sih, uint32 mask, uint32 val)
2919{
2920	si_info_t *sii;
2921
2922	sii = SI_INFO(sih);
2923	if (sih->ccrev < 16)
2924		return 0xffffffff;
2925
2926	/* gpio led powersave reg */
2927	return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val));
2928}
2929
2930/* mask&set gpio timer val */
2931uint32
2932si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
2933{
2934	si_info_t *sii;
2935
2936	sii = SI_INFO(sih);
2937
2938	if (sih->ccrev < 16)
2939		return 0xffffffff;
2940
2941	return (si_corereg(sih, SI_CC_IDX,
2942		OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval));
2943}
2944
2945uint32
2946si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
2947{
2948	si_info_t *sii;
2949	uint offs;
2950
2951	sii = SI_INFO(sih);
2952	if (sih->ccrev < 20)
2953		return 0xffffffff;
2954
2955	offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup));
2956	return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
2957}
2958
2959uint32
2960si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
2961{
2962	si_info_t *sii;
2963	uint offs;
2964
2965	sii = SI_INFO(sih);
2966	if (sih->ccrev < 11)
2967		return 0xffffffff;
2968
2969	if (regtype == GPIO_REGEVT)
2970		offs = OFFSETOF(chipcregs_t, gpioevent);
2971	else if (regtype == GPIO_REGEVT_INTMSK)
2972		offs = OFFSETOF(chipcregs_t, gpioeventintmask);
2973	else if (regtype == GPIO_REGEVT_INTPOL)
2974		offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
2975	else
2976		return 0xffffffff;
2977
2978	return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
2979}
2980
2981void *
2982BCMATTACHFN(si_gpio_handler_register)(si_t *sih, uint32 event,
2983	bool level, gpio_handler_t cb, void *arg)
2984{
2985	si_info_t *sii;
2986	gpioh_item_t *gi;
2987
2988	ASSERT(event);
2989	ASSERT(cb != NULL);
2990
2991	sii = SI_INFO(sih);
2992	if (sih->ccrev < 11)
2993		return NULL;
2994
2995	if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL)
2996		return NULL;
2997
2998	bzero(gi, sizeof(gpioh_item_t));
2999	gi->event = event;
3000	gi->handler = cb;
3001	gi->arg = arg;
3002	gi->level = level;
3003
3004	gi->next = sii->gpioh_head;
3005	sii->gpioh_head = gi;
3006
3007	return (void *)(gi);
3008}
3009
3010void
3011BCMATTACHFN(si_gpio_handler_unregister)(si_t *sih, void *gpioh)
3012{
3013	si_info_t *sii;
3014	gpioh_item_t *p, *n;
3015
3016	sii = SI_INFO(sih);
3017	if (sih->ccrev < 11)
3018		return;
3019
3020	ASSERT(sii->gpioh_head != NULL);
3021	if ((void*)sii->gpioh_head == gpioh) {
3022		sii->gpioh_head = sii->gpioh_head->next;
3023		MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
3024		return;
3025	} else {
3026		p = sii->gpioh_head;
3027		n = p->next;
3028		while (n) {
3029			if ((void*)n == gpioh) {
3030				p->next = n->next;
3031				MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
3032				return;
3033			}
3034			p = n;
3035			n = n->next;
3036		}
3037	}
3038
3039	ASSERT(0); /* Not found in list */
3040}
3041
3042void
3043si_gpio_handler_process(si_t *sih)
3044{
3045	si_info_t *sii;
3046	gpioh_item_t *h;
3047	uint32 status;
3048	uint32 level = si_gpioin(sih);
3049	uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0);
3050
3051	sii = SI_INFO(sih);
3052	for (h = sii->gpioh_head; h != NULL; h = h->next) {
3053		if (h->handler) {
3054			status = (h->level ? level : edge);
3055
3056			if (status & h->event)
3057				h->handler(status, h->arg);
3058		}
3059	}
3060
3061	si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */
3062}
3063
3064uint32
3065si_gpio_int_enable(si_t *sih, bool enable)
3066{
3067	si_info_t *sii;
3068	uint offs;
3069
3070	sii = SI_INFO(sih);
3071	if (sih->ccrev < 11)
3072		return 0xffffffff;
3073
3074	offs = OFFSETOF(chipcregs_t, intmask);
3075	return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
3076}
3077
3078
3079/* Return the size of the specified SOCRAM bank */
3080static uint
3081socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 index, uint8 mem_type)
3082{
3083	uint banksize, bankinfo;
3084	uint bankidx = index | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
3085
3086	ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
3087
3088	W_REG(sii->osh, &regs->bankidx, bankidx);
3089	bankinfo = R_REG(sii->osh, &regs->bankinfo);
3090	banksize = SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
3091	return banksize;
3092}
3093
3094void
3095si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect)
3096{
3097	si_info_t *sii;
3098	uint origidx;
3099	uint intr_val = 0;
3100	sbsocramregs_t *regs;
3101	bool wasup;
3102	uint corerev;
3103
3104	sii = SI_INFO(sih);
3105
3106	/* Block ints and save current core */
3107	INTR_OFF(sii, intr_val);
3108	origidx = si_coreidx(sih);
3109
3110	if (!set)
3111		*enable = *protect = 0;
3112
3113	/* Switch to SOCRAM core */
3114	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
3115		goto done;
3116
3117	/* Get info for determining size */
3118	if (!(wasup = si_iscoreup(sih)))
3119		si_core_reset(sih, 0, 0);
3120
3121	corerev = si_corerev(sih);
3122	if (corerev >= 10) {
3123		uint32 extcinfo;
3124		uint8 nb;
3125		uint8 i;
3126		uint32 bankidx, bankinfo;
3127
3128		extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
3129		nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
3130		for (i = 0; i < nb; i++) {
3131			bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
3132			W_REG(sii->osh, &regs->bankidx, bankidx);
3133			bankinfo = R_REG(sii->osh, &regs->bankinfo);
3134			if (set) {
3135				bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK;
3136				bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK;
3137				if (*enable) {
3138					bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT);
3139					if (*protect)
3140						bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT);
3141				}
3142				W_REG(sii->osh, &regs->bankinfo, bankinfo);
3143			}
3144			else if (i == 0) {
3145				if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) {
3146					*enable = 1;
3147					if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK)
3148						*protect = 1;
3149				}
3150			}
3151		}
3152	}
3153
3154	/* Return to previous state and core */
3155	if (!wasup)
3156		si_core_disable(sih, 0);
3157	si_setcoreidx(sih, origidx);
3158
3159done:
3160	INTR_RESTORE(sii, intr_val);
3161}
3162
3163bool
3164si_socdevram_pkg(si_t *sih)
3165{
3166	if (si_socdevram_size(sih) > 0)
3167		return TRUE;
3168	else
3169		return FALSE;
3170}
3171
3172uint32
3173si_socdevram_size(si_t *sih)
3174{
3175	si_info_t *sii;
3176	uint origidx;
3177	uint intr_val = 0;
3178	uint32 memsize = 0;
3179	sbsocramregs_t *regs;
3180	bool wasup;
3181	uint corerev;
3182
3183	sii = SI_INFO(sih);
3184
3185	/* Block ints and save current core */
3186	INTR_OFF(sii, intr_val);
3187	origidx = si_coreidx(sih);
3188
3189	/* Switch to SOCRAM core */
3190	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
3191		goto done;
3192
3193	/* Get info for determining size */
3194	if (!(wasup = si_iscoreup(sih)))
3195		si_core_reset(sih, 0, 0);
3196
3197	corerev = si_corerev(sih);
3198	if (corerev >= 10) {
3199		uint32 extcinfo;
3200		uint8 nb;
3201		uint8 i;
3202
3203		extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
3204		nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
3205		for (i = 0; i < nb; i++)
3206			memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
3207	}
3208
3209	/* Return to previous state and core */
3210	if (!wasup)
3211		si_core_disable(sih, 0);
3212	si_setcoreidx(sih, origidx);
3213
3214done:
3215	INTR_RESTORE(sii, intr_val);
3216
3217	return memsize;
3218}
3219
3220/* Return the RAM size of the SOCRAM core */
3221uint32
3222si_socram_size(si_t *sih)
3223{
3224	si_info_t *sii;
3225	uint origidx;
3226	uint intr_val = 0;
3227
3228	sbsocramregs_t *regs;
3229	bool wasup;
3230	uint corerev;
3231	uint32 coreinfo;
3232	uint memsize = 0;
3233
3234	sii = SI_INFO(sih);
3235
3236	/* Block ints and save current core */
3237	INTR_OFF(sii, intr_val);
3238	origidx = si_coreidx(sih);
3239
3240	/* Switch to SOCRAM core */
3241	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
3242		goto done;
3243
3244	/* Get info for determining size */
3245	if (!(wasup = si_iscoreup(sih)))
3246		si_core_reset(sih, 0, 0);
3247	corerev = si_corerev(sih);
3248	coreinfo = R_REG(sii->osh, &regs->coreinfo);
3249
3250	/* Calculate size from coreinfo based on rev */
3251	if (corerev == 0)
3252		memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
3253	else if (corerev < 3) {
3254		memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
3255		memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
3256	} else if ((corerev <= 7) || (corerev == 12)) {
3257		uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
3258		uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
3259		uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
3260		if (lss != 0)
3261			nb --;
3262		memsize = nb * (1 << (bsz + SR_BSZ_BASE));
3263		if (lss != 0)
3264			memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
3265	} else {
3266		uint8 i;
3267		uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
3268		for (i = 0; i < nb; i++)
3269			memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
3270	}
3271
3272	/* Return to previous state and core */
3273	if (!wasup)
3274		si_core_disable(sih, 0);
3275	si_setcoreidx(sih, origidx);
3276
3277done:
3278	INTR_RESTORE(sii, intr_val);
3279
3280	return memsize;
3281}
3282
3283#ifdef BCMECICOEX
3284#define NOTIFY_BT_FM_DISABLE(sih, val) \
3285	si_eci_notify_bt((sih), ECI_OUT_FM_DISABLE_MASK(sih->ccrev), \
3286			 ((val) << ECI_OUT_FM_DISABLE_SHIFT(sih->ccrev)), FALSE)
3287
3288/* Query OTP to see if FM is disabled */
3289static int
3290BCMATTACHFN(si_query_FMDisabled_from_OTP)(si_t *sih, uint16 *FMDisabled)
3291{
3292	int error = BCME_OK;
3293	uint bitoff = 0;
3294	bool wasup;
3295	void *oh;
3296
3297	/* Determine the bit for the chip */
3298	switch (CHIPID(sih->chip)) {
3299	case BCM4325_CHIP_ID:
3300		if (CHIPREV(sih->chiprev) >= 6)
3301			bitoff = OTP4325_FM_DISABLED_OFFSET;
3302		break;
3303	default:
3304		break;
3305	}
3306
3307	/* If there is a bit for this chip, check it */
3308	if (bitoff) {
3309		if (!(wasup = si_is_otp_powered(sih))) {
3310			si_otp_power(sih, TRUE);
3311		}
3312
3313		if ((oh = otp_init(sih)) != NULL)
3314			*FMDisabled = !otp_read_bit(oh, OTP4325_FM_DISABLED_OFFSET);
3315		else
3316			error = BCME_NOTFOUND;
3317
3318		if (!wasup) {
3319			si_otp_power(sih, FALSE);
3320		}
3321	}
3322
3323	return error;
3324}
3325
3326bool
3327si_eci(si_t *sih)
3328{
3329	return (!!(sih->cccaps & CC_CAP_ECI));
3330}
3331
3332bool
3333si_seci(si_t *sih)
3334{
3335	return (sih->cccaps_ext & CC_CAP_EXT_SECI_PRESENT);
3336}
3337
3338/* ECI Init routine */
3339int
3340BCMATTACHFN(si_eci_init)(si_t *sih)
3341{
3342	uint32 origidx = 0;
3343	si_info_t *sii;
3344	chipcregs_t *cc;
3345	bool fast;
3346	uint16 FMDisabled = FALSE;
3347
3348	/* check for ECI capability */
3349	if (!(sih->cccaps & CC_CAP_ECI))
3350		return BCME_ERROR;
3351
3352	sii = SI_INFO(sih);
3353	fast = SI_FAST(sii);
3354	if (!fast) {
3355		origidx = sii->curidx;
3356		if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
3357			return BCME_ERROR;
3358	} else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
3359		return BCME_ERROR;
3360	ASSERT(cc);
3361
3362	/* disable level based interrupts */
3363	if (sih->ccrev < 35) {
3364		W_REG(sii->osh, &cc->eci.lt35.eci_intmaskhi, 0x0);
3365		W_REG(sii->osh, &cc->eci.lt35.eci_intmaskmi, 0x0);
3366		W_REG(sii->osh, &cc->eci.lt35.eci_intmasklo, 0x0);
3367	}
3368	else {
3369		W_REG(sii->osh, &cc->eci.ge35.eci_intmaskhi, 0x0);
3370		W_REG(sii->osh, &cc->eci.ge35.eci_intmasklo, 0x0);
3371	}
3372
3373	/* Assign eci_output bits between 'wl' and dot11mac */
3374	if (sih->ccrev < 35) {
3375		W_REG(sii->osh, &cc->eci.lt35.eci_control, ECI_MACCTRL_BITS);
3376	}
3377	else {
3378		W_REG(sii->osh, &cc->eci.ge35.eci_controllo, ECI_MACCTRLLO_BITS);
3379		W_REG(sii->osh, &cc->eci.ge35.eci_controlhi, ECI_MACCTRLHI_BITS);
3380	}
3381
3382	/* enable only edge based interrupts
3383	 * only toggle on bit 62 triggers an interrupt
3384	 */
3385	if (sih->ccrev < 35) {
3386		W_REG(sii->osh, &cc->eci.lt35.eci_eventmaskhi, 0x0);
3387		W_REG(sii->osh, &cc->eci.lt35.eci_eventmaskmi, 0x0);
3388		W_REG(sii->osh, &cc->eci.lt35.eci_eventmasklo, 0x0);
3389	}
3390	else {
3391		W_REG(sii->osh, &cc->eci.ge35.eci_eventmaskhi, 0x0);
3392		W_REG(sii->osh, &cc->eci.ge35.eci_eventmasklo, 0x0);
3393	}
3394
3395	/* restore previous core */
3396	if (!fast)
3397		si_setcoreidx(sih, origidx);
3398
3399	/* if FM disabled in OTP, let BT know */
3400	if (!si_query_FMDisabled_from_OTP(sih, &FMDisabled)) {
3401		if (FMDisabled) {
3402			NOTIFY_BT_FM_DISABLE(sih, 1);
3403		}
3404	}
3405
3406	return 0;
3407}
3408
3409/*
3410 * Write values to BT on eci_output.
3411 */
3412void
3413si_eci_notify_bt(si_t *sih, uint32 mask, uint32 val, bool interrupt)
3414{
3415	uint32 offset;
3416
3417	/* Nothing to do if there is no eci */
3418	if ((sih->cccaps & CC_CAP_ECI) == 0)
3419		return;
3420
3421	/* Clear interrupt bit by default */
3422	if (interrupt)
3423		si_corereg(sih, SI_CC_IDX, (sih->ccrev < 35 ?
3424			OFFSETOF(chipcregs_t, eci.lt35.eci_output) :
3425			OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo)),
3426			(1 << 30), 0);
3427
3428	if (sih->ccrev >= 35) {
3429		if ((mask & 0xFFFF0000) == ECI48_OUT_MASKMAGIC_HIWORD) {
3430			offset = OFFSETOF(chipcregs_t, eci.ge35.eci_outputhi);
3431			mask = mask & ~0xFFFF0000;
3432		}
3433		else {
3434			offset = OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo);
3435	mask = mask | (1<<30);
3436			val = val & ~(1 << 30);
3437		}
3438	}
3439	else {
3440		offset = OFFSETOF(chipcregs_t, eci.lt35.eci_output);
3441		val = val & ~(1 << 30);
3442	}
3443
3444	si_corereg(sih, SI_CC_IDX, offset, mask, val);
3445
3446	/* Set interrupt bit if needed */
3447	if (interrupt)
3448		si_corereg(sih, SI_CC_IDX,
3449		           (sih->ccrev < 35 ?
3450		            OFFSETOF(chipcregs_t, eci.lt35.eci_output) :
3451		            OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo)),
3452		           (1 << 30), (1 << 30));
3453}
3454
3455/* seci clock enable/disable */
3456static void
3457si_seci_clkreq(si_t *sih, bool enable)
3458{
3459	uint32 clk_ctl_st;
3460	uint32 offset;
3461	uint32 val;
3462
3463	if (!si_seci(sih))
3464		return;
3465
3466	if (enable)
3467		val = CLKCTL_STS_SECI_CLK_REQ;
3468	else
3469		val = 0;
3470
3471	offset = OFFSETOF(chipcregs_t, clk_ctl_st);
3472
3473	si_corereg(sih, SI_CC_IDX, offset, CLKCTL_STS_SECI_CLK_REQ, val);
3474
3475	if (!enable)
3476		return;
3477
3478	SPINWAIT((si_corereg(sih, 0, offset, 0, 0) & CLKCTL_STS_SECI_CLK_AVAIL), 100000);
3479
3480	clk_ctl_st = si_corereg(sih, 0, offset, 0, 0);
3481	if (enable) {
3482		if (!(clk_ctl_st & CLKCTL_STS_SECI_CLK_AVAIL)) {
3483			SI_ERROR(("SECI clock is still not available\n"));
3484	return;
3485}
3486	}
3487}
3488
3489void
3490BCMINITFN(si_seci_down)(si_t *sih)
3491{
3492	uint32 origidx = 0;
3493	si_info_t *sii;
3494	chipcregs_t *cc;
3495	bool fast;
3496	uint32 seci_conf;
3497
3498	if (!si_seci(sih))
3499		return;
3500
3501	sii = SI_INFO(sih);
3502	fast = SI_FAST(sii);
3503
3504	if (!fast) {
3505		origidx = sii->curidx;
3506		if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
3507			return;
3508	} else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
3509		return;
3510	ASSERT(cc);
3511
3512	/* put seci in reset */
3513	seci_conf = R_REG(sii->osh, &cc->SECI_config);
3514	seci_conf &= ~SECI_ENAB_SECI_ECI;
3515	W_REG(sii->osh, &cc->SECI_config, seci_conf);
3516	seci_conf |= SECI_RESET;
3517	W_REG(sii->osh, &cc->SECI_config, seci_conf);
3518
3519	/* bring down the clock if up */
3520	si_seci_clkreq(sih, FALSE);
3521
3522	/* restore previous core */
3523	if (!fast)
3524		si_setcoreidx(sih, origidx);
3525}
3526
3527/* SECI Init routine, pass in seci_mode */
3528void *
3529BCMINITFN(si_seci_init)(si_t *sih, uint8  seci_mode)
3530{
3531	uint32 origidx = 0;
3532	uint32 offset;
3533	si_info_t *sii;
3534	void *ptr;
3535	chipcregs_t *cc;
3536	bool fast;
3537	uint32 seci_conf;
3538	uint32 regval;
3539
3540	if (sih->ccrev < 35)
3541		return NULL;
3542
3543	if (!si_seci(sih))
3544		return NULL;
3545
3546	if (seci_mode > SECI_MODE_MASK)
3547		return NULL;
3548
3549	sii = SI_INFO(sih);
3550	fast = SI_FAST(sii);
3551	if (!fast) {
3552		origidx = sii->curidx;
3553		if ((ptr = si_setcore(sih, CC_CORE_ID, 0)) == NULL)
3554			return NULL;
3555	} else if ((ptr = CCREGS_FAST(sii)) == NULL)
3556		return NULL;
3557	cc = (chipcregs_t *)ptr;
3558	ASSERT(cc);
3559
3560
3561	/* 43236 (ccrev 36) muxes SECI on JTAG pins. Select SECI. */
3562	if (CHIPID(sih->chip) == BCM43236_CHIP_ID ||
3563	    CHIPID(sih->chip) == BCM4331_CHIP_ID) {
3564		regval = R_REG(sii->osh, &cc->chipcontrol);
3565		regval |= 0x2;
3566		W_REG(sii->osh, &cc->chipcontrol, regval);
3567
3568		regval = R_REG(sii->osh, &cc->jtagctrl);
3569		regval |= 0x1;
3570		W_REG(sii->osh, &cc->jtagctrl, regval);
3571	}
3572
3573	/* enable SECI clock */
3574	si_seci_clkreq(sih, TRUE);
3575
3576	/* put the SECI in reset */
3577	seci_conf = R_REG(sii->osh, &cc->SECI_config);
3578	seci_conf &= ~SECI_ENAB_SECI_ECI;
3579	W_REG(sii->osh, &cc->SECI_config, seci_conf);
3580	seci_conf = SECI_RESET;
3581	W_REG(sii->osh, &cc->SECI_config, seci_conf);
3582
3583	/* set force-low, and set EN_SECI for all non-legacy modes */
3584	seci_conf |= SECI_ENAB_SECIOUT_DIS;
3585	if ((seci_mode == SECI_MODE_UART) || (seci_mode == SECI_MODE_SECI) ||
3586		(seci_mode == SECI_MODE_HALF_SECI))
3587	{
3588		seci_conf |= SECI_ENAB_SECI_ECI;
3589	}
3590	W_REG(sii->osh, &cc->SECI_config, seci_conf);
3591
3592	/* take seci out of reset */
3593	seci_conf = R_REG(sii->osh, &cc->SECI_config);
3594	seci_conf &= ~(SECI_RESET);
3595	W_REG(sii->osh, &cc->SECI_config, seci_conf);
3596
3597	/* set UART/SECI baud rate */
3598	/* hard-coded at 4MBaud for now */
3599	if ((seci_mode == SECI_MODE_UART) || (seci_mode == SECI_MODE_SECI) ||
3600	    (seci_mode == SECI_MODE_HALF_SECI)) {
3601		offset = OFFSETOF(chipcregs_t, seci_uart_bauddiv);
3602		si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0xFF); /* 4MBaud */
3603		offset = OFFSETOF(chipcregs_t, seci_uart_baudadj);
3604		if (CHIPID(sih->chip) == BCM43236_CHIP_ID ||
3605		    CHIPID(sih->chip) == BCM4331_CHIP_ID) {
3606			/* 43236 ccrev = 36 and MAC clk = 96MHz */
3607			/* 4331 MAC clk = 96MHz */
3608			si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0x44);
3609		}
3610		else {
3611			/* 4336 MAC clk is 80MHz */
3612			si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0x22);
3613		}
3614
3615		/* LCR/MCR settings */
3616		offset = OFFSETOF(chipcregs_t, seci_uart_lcr);
3617		si_corereg(sih, SI_CC_IDX, offset, 0xFF,
3618			(SECI_UART_LCR_RX_EN | SECI_UART_LCR_TXO_EN)); /* 0x28 */
3619		offset = OFFSETOF(chipcregs_t, seci_uart_mcr);
3620		si_corereg(sih, SI_CC_IDX, offset,
3621			0xFF, (SECI_UART_MCR_TX_EN | SECI_UART_MCR_BAUD_ADJ_EN)); /* 0x81 */
3622
3623		/* Give control of ECI output regs to MAC core */
3624		offset = OFFSETOF(chipcregs_t, eci.ge35.eci_controllo);
3625		si_corereg(sih, SI_CC_IDX, offset, 0xFFFFFFFF, ECI_MACCTRLLO_BITS);
3626		offset = OFFSETOF(chipcregs_t, eci.ge35.eci_controlhi);
3627		si_corereg(sih, SI_CC_IDX, offset, 0xFFFF, ECI_MACCTRLHI_BITS);
3628	}
3629
3630	/* set the seci mode in seci conf register */
3631	seci_conf = R_REG(sii->osh, &cc->SECI_config);
3632	seci_conf &= ~(SECI_MODE_MASK << SECI_MODE_SHIFT);
3633	seci_conf |= (seci_mode << SECI_MODE_SHIFT);
3634	W_REG(sii->osh, &cc->SECI_config, seci_conf);
3635
3636	/* Clear force-low bit */
3637	seci_conf = R_REG(sii->osh, &cc->SECI_config);
3638	seci_conf &= ~SECI_ENAB_SECIOUT_DIS;
3639	W_REG(sii->osh, &cc->SECI_config, seci_conf);
3640
3641	/* restore previous core */
3642	if (!fast)
3643		si_setcoreidx(sih, origidx);
3644
3645	return ptr;
3646}
3647#endif /* BCMECICOEX */
3648
3649void
3650si_btcgpiowar(si_t *sih)
3651{
3652	si_info_t *sii;
3653	uint origidx;
3654	uint intr_val = 0;
3655	chipcregs_t *cc;
3656
3657	sii = SI_INFO(sih);
3658
3659	/* Make sure that there is ChipCommon core present &&
3660	 * UART_TX is strapped to 1
3661	 */
3662	if (!(sih->cccaps & CC_CAP_UARTGPIO))
3663		return;
3664
3665	/* si_corereg cannot be used as we have to guarantee 8-bit read/writes */
3666	INTR_OFF(sii, intr_val);
3667
3668	origidx = si_coreidx(sih);
3669
3670	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
3671	ASSERT(cc != NULL);
3672
3673	W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04);
3674
3675	/* restore the original index */
3676	si_setcoreidx(sih, origidx);
3677
3678	INTR_RESTORE(sii, intr_val);
3679}
3680
3681#if !defined(_CFE_) || defined(CFG_WL)
3682void
3683si_chipcontrl_epa4331_restore(si_t *sih, uint32 val)
3684{
3685	si_info_t *sii;
3686	chipcregs_t *cc;
3687	uint origidx;
3688
3689	sii = SI_INFO(sih);
3690	origidx = si_coreidx(sih);
3691	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
3692	W_REG(sii->osh, &cc->chipcontrol, val);
3693	si_setcoreidx(sih, origidx);
3694}
3695
3696uint32
3697si_chipcontrl_epa4331_read(si_t *sih)
3698{
3699	si_info_t *sii;
3700	chipcregs_t *cc;
3701	uint origidx;
3702	uint32 val;
3703
3704	sii = SI_INFO(sih);
3705	origidx = si_coreidx(sih);
3706	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
3707	val = R_REG(sii->osh, &cc->chipcontrol);
3708	si_setcoreidx(sih, origidx);
3709	return val;
3710}
3711
3712void
3713si_chipcontrl_epa4331(si_t *sih, bool on)
3714{
3715	si_info_t *sii;
3716	chipcregs_t *cc;
3717	uint origidx;
3718	uint32 val;
3719
3720	sii = SI_INFO(sih);
3721	origidx = si_coreidx(sih);
3722
3723	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
3724
3725	val = R_REG(sii->osh, &cc->chipcontrol);
3726
3727	if (on) {
3728		if (sih->chippkg == 9 || sih->chippkg == 0xb) {
3729			val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
3730			/* Ext PA Controls for 4331 12x9 Package */
3731			W_REG(sii->osh, &cc->chipcontrol, val);
3732		} else {
3733			/* Ext PA Controls for 4331 12x12 Package */
3734			if (sih->chiprev > 0) {
3735				W_REG(sii->osh, &cc->chipcontrol, val |
3736				      (CCTRL4331_EXTPA_EN) | (CCTRL4331_EXTPA_EN2));
3737			} else {
3738				W_REG(sii->osh, &cc->chipcontrol, val | (CCTRL4331_EXTPA_EN));
3739			}
3740		}
3741	} else {
3742		val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_EN2 | CCTRL4331_EXTPA_ON_GPIO2_5);
3743		W_REG(sii->osh, &cc->chipcontrol, val);
3744	}
3745
3746	si_setcoreidx(sih, origidx);
3747}
3748
3749void
3750si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl)
3751{
3752	si_info_t *sii;
3753	chipcregs_t *cc;
3754	uint origidx;
3755	uint32 val;
3756	bool sel_chip;
3757
3758	sel_chip = (CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
3759		(CHIPID(sih->chip) == BCM43431_CHIP_ID);
3760	sel_chip &= ((sih->chippkg == 9 || sih->chippkg == 0xb));
3761
3762	if (!sel_chip)
3763		return;
3764
3765	sii = SI_INFO(sih);
3766	origidx = si_coreidx(sih);
3767
3768	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
3769
3770	val = R_REG(sii->osh, &cc->chipcontrol);
3771
3772	if (enter_wowl) {
3773		val |= CCTRL4331_EXTPA_EN;
3774		W_REG(sii->osh, &cc->chipcontrol, val);
3775	} else {
3776		val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
3777		W_REG(sii->osh, &cc->chipcontrol, val);
3778	}
3779	si_setcoreidx(sih, origidx);
3780}
3781#endif /* !_CFE_ || CFG_WL */
3782
3783uint
3784si_pll_reset(si_t *sih)
3785{
3786	uint err = 0;
3787
3788	uint intr_val = 0;
3789	si_info_t *sii;
3790	sii = SI_INFO(sih);
3791	INTR_OFF(sii, intr_val);
3792	err = si_pll_minresmask_reset(sih, sii->osh);
3793	INTR_RESTORE(sii, intr_val);
3794	return (err);
3795}
3796
3797/* Enable BT-COEX & Ex-PA for 4313 */
3798void
3799si_epa_4313war(si_t *sih)
3800{
3801	si_info_t *sii;
3802	chipcregs_t *cc;
3803	uint origidx;
3804
3805	sii = SI_INFO(sih);
3806	origidx = si_coreidx(sih);
3807
3808	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
3809
3810	/* EPA Fix */
3811	W_REG(sii->osh, &cc->gpiocontrol,
3812		R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
3813
3814	si_setcoreidx(sih, origidx);
3815}
3816
3817void
3818si_clk_pmu_htavail_set(si_t *sih, bool set_clear)
3819{
3820	si_info_t *sii;
3821	sii = SI_INFO(sih);
3822
3823	si_pmu_minresmask_htavail_set(sih, sii->osh, set_clear);
3824}
3825
3826/* WL/BT control for 4313 btcombo boards >= P250 */
3827void
3828si_btcombo_p250_4313_war(si_t *sih)
3829{
3830	si_info_t *sii;
3831	chipcregs_t *cc;
3832	uint origidx;
3833
3834	sii = SI_INFO(sih);
3835	origidx = si_coreidx(sih);
3836
3837	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
3838	W_REG(sii->osh, &cc->gpiocontrol,
3839		R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_5_6_EN_MASK);
3840
3841	W_REG(sii->osh, &cc->gpioouten,
3842		R_REG(sii->osh, &cc->gpioouten) | GPIO_CTRL_5_6_EN_MASK);
3843
3844	si_setcoreidx(sih, origidx);
3845}
3846void
3847si_btc_enable_chipcontrol(si_t *sih)
3848{
3849	si_info_t *sii;
3850	chipcregs_t *cc;
3851	uint origidx;
3852
3853	sii = SI_INFO(sih);
3854	origidx = si_coreidx(sih);
3855
3856	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
3857
3858	/* BT fix */
3859	W_REG(sii->osh, &cc->chipcontrol,
3860		R_REG(sii->osh, &cc->chipcontrol) | CC_BTCOEX_EN_MASK);
3861
3862	si_setcoreidx(sih, origidx);
3863}
3864/* check if the device is removed */
3865bool
3866si_deviceremoved(si_t *sih)
3867{
3868	uint32 w;
3869	si_info_t *sii;
3870
3871	sii = SI_INFO(sih);
3872
3873	switch (BUSTYPE(sih->bustype)) {
3874	case PCI_BUS:
3875		ASSERT(sii->osh != NULL);
3876		w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32));
3877		if ((w & 0xFFFF) != VENDOR_BROADCOM)
3878			return TRUE;
3879		break;
3880	}
3881	return FALSE;
3882}
3883
3884bool
3885si_is_sprom_available(si_t *sih)
3886{
3887	if (sih->ccrev >= 31) {
3888		si_info_t *sii;
3889		uint origidx;
3890		chipcregs_t *cc;
3891		uint32 sromctrl;
3892
3893		if ((sih->cccaps & CC_CAP_SROM) == 0)
3894			return FALSE;
3895
3896		sii = SI_INFO(sih);
3897		origidx = sii->curidx;
3898		cc = si_setcoreidx(sih, SI_CC_IDX);
3899		sromctrl = R_REG(sii->osh, &cc->sromcontrol);
3900		si_setcoreidx(sih, origidx);
3901		return (sromctrl & SRC_PRESENT);
3902	}
3903
3904	switch (CHIPID(sih->chip)) {
3905	case BCM4312_CHIP_ID:
3906		return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL);
3907	case BCM4325_CHIP_ID:
3908		return (sih->chipst & CST4325_SPROM_SEL) != 0;
3909	case BCM4322_CHIP_ID:	case BCM43221_CHIP_ID:	case BCM43231_CHIP_ID:
3910	case BCM43222_CHIP_ID:	case BCM43111_CHIP_ID:	case BCM43112_CHIP_ID:
3911	case BCM43420_CHIP_ID:
3912	case BCM4342_CHIP_ID: {
3913		uint32 spromotp;
3914		spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
3915		        CST4322_SPROM_OTP_SEL_SHIFT;
3916		return (spromotp & CST4322_SPROM_PRESENT) != 0;
3917	}
3918	case BCM4329_CHIP_ID:
3919		return (sih->chipst & CST4329_SPROM_SEL) != 0;
3920	case BCM4315_CHIP_ID:
3921		return (sih->chipst & CST4315_SPROM_SEL) != 0;
3922	case BCM4319_CHIP_ID:
3923		return (sih->chipst & CST4319_SPROM_SEL) != 0;
3924	case BCM4336_CHIP_ID:
3925		return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
3926	case BCM4330_CHIP_ID:
3927		return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
3928	case BCM4313_CHIP_ID:
3929		return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
3930	case BCM4331_CHIP_ID:
3931	case BCM43431_CHIP_ID:
3932		return (sih->chipst & CST4331_SPROM_PRESENT) != 0;
3933	case BCM43228_CHIP_ID:
3934	case BCM43428_CHIP_ID:
3935		return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT;
3936	default:
3937		return TRUE;
3938	}
3939}
3940
3941bool
3942si_is_otp_disabled(si_t *sih)
3943{
3944	switch (CHIPID(sih->chip)) {
3945	case BCM4325_CHIP_ID:
3946		return (sih->chipst & CST4325_SPROM_OTP_SEL_MASK) == CST4325_OTP_PWRDN;
3947	case BCM4322_CHIP_ID:
3948	case BCM43221_CHIP_ID:
3949	case BCM43231_CHIP_ID:
3950	case BCM4342_CHIP_ID:
3951		return (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
3952			CST4322_SPROM_OTP_SEL_SHIFT) & CST4322_OTP_PRESENT) !=
3953			CST4322_OTP_PRESENT;
3954	case BCM4329_CHIP_ID:
3955		return (sih->chipst & CST4329_SPROM_OTP_SEL_MASK) == CST4329_OTP_PWRDN;
3956	case BCM4315_CHIP_ID:
3957		return (sih->chipst & CST4315_SPROM_OTP_SEL_MASK) == CST4315_OTP_PWRDN;
3958	case BCM4319_CHIP_ID:
3959		return (sih->chipst & CST4319_SPROM_OTP_SEL_MASK) == CST4319_OTP_PWRDN;
3960	case BCM4336_CHIP_ID:
3961		return ((sih->chipst & CST4336_OTP_PRESENT) == 0);
3962	case BCM4330_CHIP_ID:
3963		return ((sih->chipst & CST4330_OTP_PRESENT) == 0);
3964	case BCM4313_CHIP_ID:
3965		return (sih->chipst & CST4313_OTP_PRESENT) == 0;
3966	/* These chips always have their OTP on */
3967	case BCM43111_CHIP_ID:	case BCM43112_CHIP_ID:	case BCM43222_CHIP_ID:
3968	case BCM43224_CHIP_ID:	case BCM43225_CHIP_ID:  case BCM43420_CHIP_ID:
3969	case BCM43421_CHIP_ID:
3970	case BCM43226_CHIP_ID:
3971	case BCM43235_CHIP_ID:	case BCM43236_CHIP_ID:	case BCM43238_CHIP_ID:
3972	case BCM43234_CHIP_ID:	case BCM43237_CHIP_ID:
3973	case BCM4331_CHIP_ID:   case BCM43431_CHIP_ID:
3974	case BCM43228_CHIP_ID:  case BCM43428_CHIP_ID:
3975	default:
3976		return FALSE;
3977	}
3978}
3979
3980bool
3981si_is_otp_powered(si_t *sih)
3982{
3983	if (PMUCTL_ENAB(sih))
3984		return si_pmu_is_otp_powered(sih, si_osh(sih));
3985	return TRUE;
3986}
3987
3988void
3989si_otp_power(si_t *sih, bool on)
3990{
3991	if (PMUCTL_ENAB(sih))
3992		si_pmu_otp_power(sih, si_osh(sih), on);
3993	OSL_DELAY(1000);
3994}
3995
3996bool
3997#if defined(WLTEST)
3998si_is_sprom_enabled(si_t *sih)
3999#else
4000BCMATTACHFN(si_is_sprom_enabled)(si_t *sih)
4001#endif
4002{
4003	if (PMUCTL_ENAB(sih))
4004		return si_pmu_is_sprom_enabled(sih, si_osh(sih));
4005	return TRUE;
4006}
4007
4008void
4009#if defined(WLTEST)
4010si_sprom_enable(si_t *sih, bool enable)
4011#else
4012BCMATTACHFN(si_sprom_enable)(si_t *sih, bool enable)
4013#endif
4014{
4015	if (PMUCTL_ENAB(sih))
4016		si_pmu_sprom_enable(sih, si_osh(sih), enable);
4017}
4018
4019/* Return BCME_NOTFOUND if the card doesn't have CIS format nvram */
4020int
4021si_cis_source(si_t *sih)
4022{
4023	/* Many chips have the same mapping of their chipstatus field */
4024	static const uint cis_sel[] = { CIS_DEFAULT, CIS_SROM, CIS_OTP, CIS_SROM };
4025	static const uint cis_sel_1b[] = { CIS_DEFAULT, CIS_OTP };
4026	UNUSED_PARAMETER(cis_sel_1b);
4027
4028	/* PCI chips use SROM format instead of CIS */
4029	if (BUSTYPE(sih->bustype) == PCI_BUS)
4030		return BCME_NOTFOUND;
4031
4032	switch (CHIPID(sih->chip)) {
4033	case BCM4325_CHIP_ID:
4034		return ((sih->chipst & CST4325_SPROM_OTP_SEL_MASK) >= sizeof(cis_sel)) ?
4035		        CIS_DEFAULT : cis_sel[(sih->chipst & CST4325_SPROM_OTP_SEL_MASK)];
4036	case BCM4322_CHIP_ID:	case BCM43221_CHIP_ID:	case BCM43231_CHIP_ID:
4037	case BCM4342_CHIP_ID: {
4038		uint8 strap = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
4039			CST4322_SPROM_OTP_SEL_SHIFT;
4040		return ((strap >= ARRAYSIZE(cis_sel)) ?  CIS_DEFAULT : cis_sel[strap]);
4041	}
4042
4043	case BCM43235_CHIP_ID:	case BCM43236_CHIP_ID:	case BCM43238_CHIP_ID:
4044	case BCM43234_CHIP_ID: {
4045		uint8 strap = (sih->chipst & CST43236_OTP_SEL_MASK) >>
4046			CST43236_OTP_SEL_SHIFT;
4047		UNUSED_PARAMETER(strap);
4048		return CIS_OTP;
4049	}
4050
4051	case BCM43237_CHIP_ID: {
4052		uint8 strap = (sih->chipst & CST43237_OTP_SEL_MASK) >>
4053			CST43237_OTP_SEL_SHIFT;
4054		return  cis_sel_1b[strap];
4055	}
4056
4057	case BCM4329_CHIP_ID:
4058		return ((sih->chipst & CST4329_SPROM_OTP_SEL_MASK) >= sizeof(cis_sel)) ?
4059		        CIS_DEFAULT : cis_sel[(sih->chipst & CST4329_SPROM_OTP_SEL_MASK)];
4060	case BCM4315_CHIP_ID:
4061		return ((sih->chipst & CST4315_SPROM_OTP_SEL_MASK) >= sizeof(cis_sel)) ?
4062		        CIS_DEFAULT : cis_sel[(sih->chipst & CST4315_SPROM_OTP_SEL_MASK)];
4063	case BCM4319_CHIP_ID: {
4064		uint cis_sel4319 = ((sih->chipst & CST4319_SPROM_OTP_SEL_MASK) >>
4065		                    CST4319_SPROM_OTP_SEL_SHIFT);
4066		return (cis_sel4319 >= ARRAYSIZE(cis_sel)) ? CIS_DEFAULT : cis_sel[cis_sel4319];
4067	}
4068	case BCM4336_CHIP_ID: {
4069		if (sih->chipst & CST4336_SPROM_PRESENT)
4070			return CIS_SROM;
4071		if (sih->chipst & CST4336_OTP_PRESENT)
4072			return CIS_OTP;
4073		return CIS_DEFAULT;
4074	}
4075	case BCM4330_CHIP_ID: {
4076		if (sih->chipst & CST4330_SPROM_PRESENT)
4077			return CIS_SROM;
4078		if (sih->chipst & CST4330_OTP_PRESENT)
4079			return CIS_OTP;
4080		return CIS_DEFAULT;
4081	}
4082	default:
4083		return CIS_DEFAULT;
4084	}
4085}
4086
4087/* Read/write to OTP to find the FAB manf */
4088int
4089BCMINITFN(si_otp_fabid)(si_t *sih, uint16 *fabid, bool rw)
4090{
4091	int error = BCME_OK;
4092	uint offset = 0;
4093	uint16 data, mask = 0, shift = 0;
4094
4095	switch (CHIPID(sih->chip)) {
4096	case BCM4329_CHIP_ID:
4097		/* Bit locations 133-130 */
4098		if (sih->chiprev >= 3) {
4099			offset = 8;
4100			mask = 0x3c;
4101			shift = 2;
4102		}
4103		break;
4104	case BCM5356_CHIP_ID:
4105		/* Bit locations 133-130 */
4106		offset = 8;
4107		mask = 0x3c;
4108		shift = 2;
4109		break;
4110	default:
4111		error = BCME_EPERM;
4112		return error;
4113	}
4114
4115	if (rw == TRUE) {
4116		/* TRUE --> read */
4117		error = otp_read_word(sih, offset, &data);
4118		if (!error)
4119			*fabid = (data & mask) >> shift;
4120	} else {
4121		data = *fabid;
4122		data = (data << shift) & mask;
4123#ifdef BCMNVRAMW
4124		error = otp_write_word(sih, offset, data);
4125#endif /* BCMNVRAMW */
4126	}
4127
4128	return error;
4129}
4130
4131uint16 BCMINITFN(si_fabid)(si_t *sih)
4132{
4133	uint16 fabid = 0;
4134	if (si_otp_fabid(sih, &fabid, TRUE) != BCME_OK)
4135	{
4136		SI_ERROR(("si_fabid: reading fabid from otp failed.\n"));
4137	}
4138
4139	return fabid;
4140}
4141