1/*
2 * Misc utility routines for accessing chip-specific features
3 * of the SiliconBackplane-based Broadcom chips.
4 *
5 * Copyright (C) 2015, 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 505047 2014-09-26 07:54:55Z $
20 */
21
22#include <bcm_cfg.h>
23#include <typedefs.h>
24#include <bcmdefs.h>
25#include <osl.h>
26#include <bcmutils.h>
27#include <siutils.h>
28#include <bcmdevs.h>
29#include <hndsoc.h>
30#include <sbchipc.h>
31#include <pci_core.h>
32#include <pcie_core.h>
33#include <nicpci.h>
34#include <bcmnvram.h>
35#include <bcmsrom.h>
36#include <hndtcam.h>
37#include <pcicfg.h>
38#include <sbpcmcia.h>
39#include <sbsocram.h>
40#include <bcmotp.h>
41#include <hndpmu.h>
42#ifdef BCMSPI
43#include <spid.h>
44#endif /* BCMSPI */
45#if !defined(BCM_BOOTLOADER) && defined(SR_ESSENTIALS)
46#include <saverestore.h>
47#endif /* BCM_BOOTLOADER / SR_ESSENTIALS */
48
49#ifdef BCM_SDRBL
50#include <hndcpu.h>
51#endif /* BCM_SDRBL */
52
53#include "siutils_priv.h"
54
55/* local prototypes */
56static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
57                              uint bustype, void *sdh, char **vars, uint *varsz);
58static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh);
59static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
60	uint *origidx, void *regs);
61
62static void si_nvram_process(si_info_t *sii, char *pvars);
63#if (!defined(_CFE_) && !defined(_CFEZ_)) || defined(CFG_WL)
64static void si_sromvars_fixup_4331(si_t *sih, char *pvars);
65#endif /* (!_CFE_ && !_CFEZ_) || CFG_WL */
66
67/* dev path concatenation util */
68static char *si_devpathvar(si_t *sih, char *var, int len, const char *name);
69static bool _si_clkctl_cc(si_info_t *sii, uint mode);
70static bool si_ispcie(si_info_t *sii);
71static uint BCMINITFN(socram_banksize)(si_info_t *sii, sbsocramregs_t *r, uint8 idx, uint8 mtype);
72
73void si_gci_chipctrl_overrides(osl_t *osh, si_t *sih, char *pvars);
74
75
76/* global variable to indicate reservation/release of gpio's */
77static uint32 si_gpioreservation = 0;
78
79/* global flag to prevent shared resources from being initialized multiple times in si_attach() */
80
81int do_4360_pcie2_war = 0;
82
83/**
84 * Allocate a si handle.
85 * devid - pci device id (used to determine chip#)
86 * osh - opaque OS handle
87 * regs - virtual address of initial core registers
88 * bustype - pci/pcmcia/sb/sdio/etc
89 * vars - pointer to a pointer area for "environment" variables
90 * varsz - pointer to int to return the size of the vars
91 */
92si_t *
93BCMATTACHFN(si_attach)(uint devid, osl_t *osh, void *regs,
94                       uint bustype, void *sdh, char **vars, uint *varsz)
95{
96	si_info_t *sii;
97
98	/* alloc si_info_t */
99	if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) {
100		SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
101		return (NULL);
102	}
103
104	if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) {
105		MFREE(osh, sii, sizeof(si_info_t));
106		return (NULL);
107	}
108	sii->vars = vars ? *vars : NULL;
109	sii->varsz = varsz ? *varsz : 0;
110
111	return (si_t *)sii;
112}
113
114/* global kernel resource */
115static si_info_t ksii;
116
117static uint32	wd_msticks;		/* watchdog timer ticks normalized to ms */
118
119/** generic kernel variant of si_attach() */
120si_t *
121BCMATTACHFN(si_kattach)(osl_t *osh)
122{
123	static bool ksii_attached = FALSE;
124
125	if (!ksii_attached) {
126		void *regs;
127#ifndef SI_ENUM_BASE_VARIABLE
128		regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
129#endif
130
131		if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs,
132		                SI_BUS, NULL,
133		                osh != SI_OSH ? &ksii.vars : NULL,
134		                osh != SI_OSH ? &ksii.varsz : NULL) == NULL) {
135			SI_ERROR(("si_kattach: si_doattach failed\n"));
136			REG_UNMAP(regs);
137			return NULL;
138		}
139		REG_UNMAP(regs);
140
141		/* save ticks normalized to ms for si_watchdog_ms() */
142		if (PMUCTL_ENAB(&ksii.pub)) {
143			if (CHIPID(ksii.pub.chip) == BCM4706_CHIP_ID) {
144				/* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */
145				wd_msticks = (si_alp_clock(&ksii.pub) / 4) / 1000;
146			}
147			else
148				/* based on 32KHz ILP clock */
149				wd_msticks = 32;
150		} else {
151			if (ksii.pub.ccrev < 18)
152				wd_msticks = si_clock(&ksii.pub) / 1000;
153			else
154				wd_msticks = si_alp_clock(&ksii.pub) / 1000;
155		}
156
157		ksii_attached = TRUE;
158		SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n",
159		        ksii.pub.ccrev, wd_msticks));
160	}
161
162	return &ksii.pub;
163}
164
165bool
166si_ldo_war(si_t *sih, uint devid)
167{
168	si_info_t *sii = SI_INFO(sih);
169	uint32 w;
170	chipcregs_t *cc;
171	void *regs = sii->curmap;
172	uint32 rev_id, ccst;
173
174	rev_id = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_REV, sizeof(uint32));
175	rev_id &= 0xff;
176	if (!(((CHIPID(devid) == BCM4322_CHIP_ID) ||
177	       (CHIPID(devid) == BCM4342_CHIP_ID) ||
178	       (CHIPID(devid) == BCM4322_D11N_ID) ||
179	       (CHIPID(devid) == BCM4322_D11N2G_ID) ||
180	       (CHIPID(devid) == BCM4322_D11N5G_ID)) &&
181	      (rev_id == 0)))
182		return TRUE;
183
184	SI_MSG(("si_ldo_war: PCI devid 0x%x rev %d, HACK to fix 4322a0 LDO/PMU\n", devid, rev_id));
185
186	/* switch to chipcommon */
187	w = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
188	OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), SI_ENUM_BASE);
189	cc = (chipcregs_t *)regs;
190
191	/* clear bit 7 to fix LDO
192	 * write to register *blindly* WITHOUT read since read may timeout
193	 *  because the default clock is 32k ILP
194	 */
195	W_REG(sii->osh, &cc->regcontrol_addr, 0);
196	/* AND_REG(sii->osh, &cc->regcontrol_data, ~0x80); */
197	W_REG(sii->osh, &cc->regcontrol_data, 0x3001);
198
199	OSL_DELAY(5000);
200
201	/* request ALP_AVAIL through PMU to move sb out of ILP */
202	W_REG(sii->osh, &cc->min_res_mask, 0x0d);
203
204	SPINWAIT(((ccst = OSL_PCI_READ_CONFIG(sii->osh, PCI_CLK_CTL_ST, 4)) & CCS_ALPAVAIL)
205		 == 0, PMU_MAX_TRANSITION_DLY);
206
207	if ((ccst & CCS_ALPAVAIL) == 0) {
208		SI_ERROR(("ALP never came up clk_ctl_st: 0x%x\n", ccst));
209		return FALSE;
210	}
211	SI_MSG(("si_ldo_war: 4322a0 HACK done\n"));
212
213	OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), w);
214
215	return TRUE;
216}
217
218static bool
219BCMATTACHFN(si_buscore_prep)(si_info_t *sii, uint bustype, uint devid, void *sdh)
220{
221	/* need to set memseg flag for CF card first before any sb registers access */
222	if (BUSTYPE(bustype) == PCMCIA_BUS)
223		sii->memseg = TRUE;
224
225	if (BUSTYPE(bustype) == PCI_BUS) {
226		if (!si_ldo_war((si_t *)sii, devid))
227			return FALSE;
228	}
229
230	/* kludge to enable the clock on the 4306 which lacks a slowclock */
231	if (BUSTYPE(bustype) == PCI_BUS && !si_ispcie(sii))
232		si_clkctl_xtal(&sii->pub, XTAL|PLL, ON);
233
234
235	return TRUE;
236}
237
238static bool
239BCMATTACHFN(si_buscore_setup)(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
240	uint *origidx, void *regs)
241{
242	bool pci, pcie, pcie_gen2 = FALSE;
243	uint i;
244	uint pciidx, pcieidx, pcirev, pcierev;
245
246	cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
247	ASSERT((uintptr)cc);
248
249	/* get chipcommon rev */
250	sii->pub.ccrev = (int)si_corerev(&sii->pub);
251
252	/* get chipcommon chipstatus */
253	if (sii->pub.ccrev >= 11)
254		sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
255
256	/* get chipcommon capabilites */
257	sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
258	/* get chipcommon extended capabilities */
259
260	if (sii->pub.ccrev >= 35)
261		sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
262
263	/* get pmu rev and caps */
264	if (sii->pub.cccaps & CC_CAP_PMU) {
265		sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
266		sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
267	}
268
269	SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
270		sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev,
271		sii->pub.pmucaps));
272
273	/* figure out bus/orignal core idx */
274	sii->pub.buscoretype = NODEV_CORE_ID;
275	sii->pub.buscorerev = (uint)NOREV;
276	sii->pub.buscoreidx = BADIDX;
277
278	pci = pcie = FALSE;
279	pcirev = pcierev = (uint)NOREV;
280	pciidx = pcieidx = BADIDX;
281
282	for (i = 0; i < sii->numcores; i++) {
283		uint cid, crev;
284
285		si_setcoreidx(&sii->pub, i);
286		cid = si_coreid(&sii->pub);
287		crev = si_corerev(&sii->pub);
288
289		/* Display cores found */
290		SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
291		        i, cid, crev, sii->coresba[i], sii->regs[i]));
292
293		if (BUSTYPE(bustype) == PCI_BUS) {
294			if (cid == PCI_CORE_ID) {
295				pciidx = i;
296				pcirev = crev;
297				pci = TRUE;
298			} else if ((cid == PCIE_CORE_ID) || (cid == PCIE2_CORE_ID)) {
299				pcieidx = i;
300				pcierev = crev;
301				pcie = TRUE;
302				if (cid == PCIE2_CORE_ID)
303					pcie_gen2 = TRUE;
304			}
305		} else if ((BUSTYPE(bustype) == PCMCIA_BUS) &&
306		           (cid == PCMCIA_CORE_ID)) {
307			sii->pub.buscorerev = crev;
308			sii->pub.buscoretype = cid;
309			sii->pub.buscoreidx = i;
310		}
311
312		/* find the core idx before entering this func. */
313		if ((savewin && (savewin == sii->coresba[i])) ||
314		    (regs == sii->regs[i]))
315			*origidx = i;
316	}
317
318	if (pci && pcie) {
319		if (si_ispcie(sii))
320			pci = FALSE;
321		else
322			pcie = FALSE;
323	}
324	if (pci) {
325		sii->pub.buscoretype = PCI_CORE_ID;
326		sii->pub.buscorerev = pcirev;
327		sii->pub.buscoreidx = pciidx;
328	} else if (pcie) {
329		if (pcie_gen2)
330			sii->pub.buscoretype = PCIE2_CORE_ID;
331		else
332			sii->pub.buscoretype = PCIE_CORE_ID;
333		sii->pub.buscorerev = pcierev;
334		sii->pub.buscoreidx = pcieidx;
335	}
336
337	SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype,
338	         sii->pub.buscorerev));
339
340	if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) &&
341	    (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (CHIPREV(sii->pub.chiprev) <= 3))
342		OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL);
343
344	/* fixup necessary chip/core configurations */
345	if (BUSTYPE(sii->pub.bustype) == PCI_BUS) {
346		if (SI_FAST(sii)) {
347			if (!sii->pch &&
348			    ((sii->pch = (void *)(uintptr)pcicore_init(&sii->pub, sii->osh,
349				(void *)PCIEREGS(sii))) == NULL))
350				return FALSE;
351		}
352		if (si_pci_fixcfg(&sii->pub)) {
353			SI_ERROR(("si_doattach: si_pci_fixcfg failed\n"));
354			return FALSE;
355		}
356	}
357
358
359	/* return to the original core */
360	si_setcoreidx(&sii->pub, *origidx);
361
362	return TRUE;
363}
364
365static uint32
366si_fixup_vid(si_info_t *sii, char *pvars, uint32 conf_vid)
367{
368	struct si_pub *sih = &sii->pub;
369	uint32 srom_vid;
370
371	if (BUSTYPE(sih->bustype) != PCI_BUS)
372		return conf_vid;
373
374	if ((CHIPID(sih->chip) != BCM4331_CHIP_ID) && (CHIPID(sih->chip) != BCM43431_CHIP_ID))
375		return conf_vid;
376
377	/* Ext PA Controls for 4331 12x9 Package */
378	if (sih->chippkg != 9)
379		return conf_vid;
380
381	srom_vid = (getintvar(pvars, "boardtype") << 16) | getintvar(pvars, "subvid");
382	if (srom_vid != conf_vid) {
383		SI_ERROR(("%s: Override mismatch conf_vid(0x%04x) with srom_vid(0x%04x)\n",
384			__FUNCTION__, conf_vid, srom_vid));
385		conf_vid = srom_vid;
386	}
387
388	return conf_vid;
389}
390
391static void
392BCMATTACHFN(si_nvram_process)(si_info_t *sii, char *pvars)
393{
394	uint w = 0;
395	if (BUSTYPE(sii->pub.bustype) == PCMCIA_BUS) {
396		w = getintvar(pvars, "regwindowsz");
397		sii->memseg = (w <= CFTABLE_REGWIN_2K) ? TRUE : FALSE;
398	}
399
400	/* get boardtype and boardrev */
401	switch (BUSTYPE(sii->pub.bustype)) {
402	case PCI_BUS:
403		/* do a pci config read to get subsystem id and subvendor id */
404		w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_SVID, sizeof(uint32));
405		w = si_fixup_vid(sii, pvars, w);
406
407		/* Let nvram variables override subsystem Vend/ID */
408		if ((sii->pub.boardvendor = (uint16)si_getdevpathintvar(&sii->pub, "boardvendor"))
409			== 0) {
410#ifdef BCMHOSTVARS
411			if ((w & 0xffff) == 0)
412				sii->pub.boardvendor = VENDOR_BROADCOM;
413			else
414#endif /* !BCMHOSTVARS */
415				sii->pub.boardvendor = w & 0xffff;
416		}
417		else
418			SI_ERROR(("Overriding boardvendor: 0x%x instead of 0x%x\n",
419				sii->pub.boardvendor, w & 0xffff));
420		if ((sii->pub.boardtype = (uint16)si_getdevpathintvar(&sii->pub, "boardtype"))
421			== 0) {
422			if ((sii->pub.boardtype = getintvar(pvars, "boardtype")) == 0)
423				sii->pub.boardtype = (w >> 16) & 0xffff;
424		}
425		else
426			SI_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n",
427				sii->pub.boardtype, (w >> 16) & 0xffff));
428		break;
429
430	case PCMCIA_BUS:
431		sii->pub.boardvendor = getintvar(pvars, "manfid");
432		sii->pub.boardtype = getintvar(pvars, "prodid");
433		break;
434
435
436	case SI_BUS:
437	case JTAG_BUS:
438		sii->pub.boardvendor = VENDOR_BROADCOM;
439		if (pvars == NULL || ((sii->pub.boardtype = getintvar(pvars, "prodid")) == 0))
440			if ((sii->pub.boardtype = getintvar(NULL, "boardtype")) == 0)
441				sii->pub.boardtype = 0xffff;
442
443		if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
444			/* do a pci config read to get subsystem id and subvendor id */
445			w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_SVID, sizeof(uint32));
446			sii->pub.boardvendor = w & 0xffff;
447			sii->pub.boardtype = (w >> 16) & 0xffff;
448		}
449		break;
450	}
451
452	if (sii->pub.boardtype == 0) {
453		SI_ERROR(("si_doattach: unknown board type\n"));
454		ASSERT(sii->pub.boardtype);
455	}
456
457	sii->pub.boardrev = getintvar(pvars, "boardrev");
458	sii->pub.boardflags = getintvar(pvars, "boardflags");
459#ifdef BCM_SDRBL
460	sii->pub.boardflags2 |= ((!CHIP_HOSTIF_USB(&(sii->pub))) ? ((si_arm_sflags(&(sii->pub))
461				 & SISF_SDRENABLE) ?  BFL2_SDR_EN:0):
462				 (((uint)getintvar(pvars, "boardflags2")) & BFL2_SDR_EN));
463#endif /* BCM_SDRBL */
464}
465
466#if (!defined(_CFE_) && !defined(_CFEZ_)) || defined(CFG_WL)
467static void
468BCMATTACHFN(si_sromvars_fixup_4331)(si_t *sih, char *pvars)
469{
470
471	const char *sromvars[] =
472	        {"extpagain2g", "extpagain5g"};
473	int sromvars_size = sizeof(sromvars)/sizeof(char *);
474	int ii;
475	uint boardtype = sih->boardtype;
476	uint boardrev = sih->boardrev;
477	bool update = ((boardtype == BCM94331BU_SSID) ||
478	               (boardtype == BCM94331S9BU_SSID) ||
479	               (boardtype == BCM94331MCI_SSID) ||
480	               (boardtype == BCM94331MC_SSID) ||
481	               (boardtype == BCM94331PCIEBT4_SSID) ||
482	               (boardtype == BCM94331X19 && boardrev == 0x1100) ||
483	               (boardtype == BCM94331HM_SSID && boardrev < 0x1152));
484
485	if (pvars == NULL || !update) {
486		return;
487	}
488
489	for (ii = 0; ii < sromvars_size; ii++) {
490		char* val = getvar(pvars, sromvars[ii]);
491
492		while (val && *val) {
493			*val = '0';
494			val++;
495		}
496	}
497}
498#endif /* (!_CFE_ && !_CFEZ_) || CFG_WL */
499
500#if defined(CONFIG_XIP) && defined(BCMTCAM)
501extern uint8 patch_pair;
502#endif /* CONFIG_XIP && BCMTCAM */
503
504typedef struct {
505	uint8 uart_tx;
506	uint32 uart_rx;
507} si_mux_uartopt_t;
508
509/* note: each index corr to MUXENAB4335_UART mask >> shift - 1 */
510static const si_mux_uartopt_t BCMATTACHDATA(mux4335_uartopt)[] = {
511		{CC4335_PIN_GPIO_06, CC4335_PIN_GPIO_02},
512		{CC4335_PIN_GPIO_12, CC4335_PIN_GPIO_13},
513		{CC4335_PIN_SDIO_DATA0, CC4335_PIN_SDIO_CMD},
514		{CC4335_PIN_RF_SW_CTRL_9, CC4335_PIN_RF_SW_CTRL_8}
515};
516
517/* note: each index corr to MUXENAB4335_HOSTWAKE mask > shift - 1 */
518static const uint8 BCMATTACHDATA(mux4335_hostwakeopt)[] = {
519		CC4335_PIN_GPIO_00,
520		CC4335_PIN_GPIO_05,
521		CC4335_PIN_GPIO_09
522};
523
524static const si_mux_uartopt_t BCMATTACHDATA(mux4350_uartopt)[] = {
525		{CC4350_PIN_GPIO_00, CC4350_PIN_GPIO_01},
526		{CC4350_PIN_GPIO_05, CC4350_PIN_GPIO_04},
527		{CC4350_PIN_GPIO_15, CC4350_PIN_GPIO_14},
528};
529
530/* note: each index corr to MUXENAB4350_HOSTWAKE mask >> shift - 1 */
531static const uint8 BCMATTACHDATA(mux4350_hostwakeopt)[] = {
532		CC4335_PIN_GPIO_00,
533};
534
535
536/** want to have this available all the time to switch mux for debugging */
537void
538BCMATTACHFN(si_muxenab)(si_t *sih, uint32 w)
539{
540	uint32 chipcontrol, pmu_chipcontrol;
541
542	pmu_chipcontrol = si_pmu_chipcontrol(sih, 1, 0, 0);
543	chipcontrol = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol),
544	                         0, 0);
545
546	switch (CHIPID(sih->chip)) {
547	case BCM4330_CHIP_ID:
548		/* clear the bits */
549		chipcontrol &= ~(CCTRL_4330_JTAG_DISABLE | CCTRL_4330_ERCX_SEL |
550		                 CCTRL_4330_GPIO_SEL | CCTRL_4330_SDIO_HOST_WAKE);
551		pmu_chipcontrol &= ~PCTL_4330_SERIAL_ENAB;
552
553		/* 4330 default is to have jtag enabled */
554		if (!(w & MUXENAB_JTAG))
555			chipcontrol |= CCTRL_4330_JTAG_DISABLE;
556		if (w & MUXENAB_UART)
557			pmu_chipcontrol |= PCTL_4330_SERIAL_ENAB;
558		if (w & MUXENAB_GPIO)
559			chipcontrol |= CCTRL_4330_GPIO_SEL;
560		if (w & MUXENAB_ERCX)
561			chipcontrol |= CCTRL_4330_ERCX_SEL;
562		if (w & MUXENAB_HOST_WAKE)
563			chipcontrol |= CCTRL_4330_SDIO_HOST_WAKE;
564		break;
565	case BCM4336_CHIP_ID:
566		if (w & MUXENAB_UART)
567			pmu_chipcontrol |= PCTL_4336_SERIAL_ENAB;
568		else
569			pmu_chipcontrol &= ~PCTL_4336_SERIAL_ENAB;
570		break;
571	case BCM4360_CHIP_ID:
572	case BCM43460_CHIP_ID:
573	case BCM4352_CHIP_ID:
574	case BCM43526_CHIP_ID:
575		if (w & MUXENAB_UART)
576			chipcontrol |= CCTRL4360_UART_MODE;
577		break;
578	case BCM43143_CHIP_ID:
579		chipcontrol = 0;
580		/* 43143 does not support ERCX */
581		if (!(w & MUXENAB_UART))
582			chipcontrol |= CCTRL_43143_RF_XSWCTRL;
583		/* JTAG is enabled when SECI is disabled */
584		if (w & MUXENAB_SECI)
585			chipcontrol |= CCTRL_43143_SECI;
586		if (w & MUXENAB_BT_LEGACY)
587			chipcontrol |= CCTRL_43143_BT_LEGACY;
588		if (w & MUXENAB_I2S_EN)
589			chipcontrol |= CCTRL_43143_I2S_MODE;
590		if (w & MUXENAB_I2S_MASTER)
591			chipcontrol |= CCTRL_43143_I2S_MASTER;
592		if (w & MUXENAB_I2S_FULL)
593			chipcontrol |= CCTRL_43143_I2S_FULL;
594		if (!(w & MUXENAB_SFLASH))
595			chipcontrol |= CCTRL_43143_GSIO;
596		if (w & MUXENAB_RFSWCTRL0)
597			chipcontrol |= CCTRL_43143_RF_SWCTRL_0;
598		if (w & MUXENAB_RFSWCTRL1)
599			chipcontrol |= CCTRL_43143_RF_SWCTRL_1;
600		if (w & MUXENAB_RFSWCTRL2)
601			chipcontrol |= CCTRL_43143_RF_SWCTRL_2;
602		if (w & MUXENAB_HOST_WAKE)
603			chipcontrol |= CCTRL_43143_HOST_WAKE0;
604		if (w & MUXENAB_HOST_WAKE1)
605			chipcontrol |= CCTRL_43143_HOST_WAKE1;
606		break;
607	case BCM43242_CHIP_ID:
608	case BCM43243_CHIP_ID:
609		/* clear the bits */
610		pmu_chipcontrol &= ~CCTRL1_4324_GPIO_SEL;
611		if (w & MUXENAB_GPIO)
612			pmu_chipcontrol |= CCTRL1_4324_GPIO_SEL;
613		break;
614
615	case BCM4335_CHIP_ID:
616		/* drive default pins for UART. Note: 15 values possible;
617		* 0 means disabled; 1 means index to 0 in mux4335_uartopt
618		* array, etc.
619		*/
620		if (w & MUXENAB4335_UART_MASK) {
621			uint32 uart_rx = 0, uart_tx = 0;
622			uint8 uartopt_ix = MUXENAB4335_GETIX(w, UART);
623
624			uart_rx = mux4335_uartopt[uartopt_ix].uart_rx;
625			uart_tx = mux4335_uartopt[uartopt_ix].uart_tx;
626
627			if (uartopt_ix >
628				sizeof(mux4335_uartopt)/sizeof(mux4335_uartopt[0]) - 1) {
629				SI_ERROR(("%s: wrong index %d for uart\n",
630					__FUNCTION__, uartopt_ix));
631				break;
632			}
633
634			si_gci_set_functionsel(sih, uart_rx, CC4335_FNSEL_UART);
635			si_gci_set_functionsel(sih, uart_tx, CC4335_FNSEL_UART);
636
637			if ((uart_rx == CC4335_PIN_GPIO_02) && (uart_tx == CC4335_PIN_GPIO_06))
638				si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_06,
639					CC_GCI_06_JTAG_SEL_MASK,
640					(1 << CC_GCI_06_JTAG_SEL_SHIFT));
641		}
642		/*
643		* 0x10 : use GPIO0 as host wake up pin
644		* 0x20 : use GPIO5 as host wake up pin
645		* 0x30 : use GPIO9 as host wake up pin
646		* 0x40 ~ 0xf0: Reserved
647		*/
648		if (w & MUXENAB4335_HOSTWAKE_MASK) {
649			uint8 hostwake = 0;
650			uint8 hostwake_ix = MUXENAB4335_GETIX(w, HOSTWAKE);
651
652			if (hostwake_ix >
653				sizeof(mux4335_hostwakeopt)/sizeof(mux4335_hostwakeopt[0]) - 1) {
654				SI_ERROR(("%s: wrong index %d for hostwake\n",
655					__FUNCTION__, hostwake_ix));
656				break;
657			}
658
659			hostwake = mux4335_hostwakeopt[hostwake_ix];
660			si_gci_set_functionsel(sih, hostwake, CC4335_FNSEL_MISC1);
661		}
662		break;
663
664	case BCM4350_CHIP_ID:
665		if (w & MUXENAB4350_UART_MASK) {
666			uint32 uart_rx = 0, uart_tx = 0;
667			uint8 uartopt_idx = (w & MUXENAB4350_UART_MASK) - 1;
668			uint8 uartopt_size = sizeof(mux4350_uartopt)/sizeof(mux4350_uartopt[0]);
669
670			if (uartopt_idx < uartopt_size) {
671				uart_rx = mux4350_uartopt[uartopt_idx].uart_rx;
672				uart_tx = mux4350_uartopt[uartopt_idx].uart_tx;
673				si_gci_set_functionsel(sih, uart_rx, CC4350_FNSEL_UART);
674				si_gci_set_functionsel(sih, uart_tx, CC4350_FNSEL_UART);
675			} else {
676				SI_MSG(("si_muxenab: Invalid uart OTP setting\n"));
677			}
678		}
679
680		if (w & MUXENAB4350_HOSTWAKE_MASK) {
681			uint8 hostwake = 0;
682			uint8 hostwake_ix =
683				((w & MUXENAB4350_HOSTWAKE_MASK)>>MUXENAB4350_HOSTWAKE_SHIFT)- 1;
684
685			if (hostwake_ix >
686				sizeof(mux4350_hostwakeopt)/sizeof(mux4350_hostwakeopt[0]) - 1) {
687				SI_ERROR(("%s: wrong index %d for hostwake\n",
688					__FUNCTION__, hostwake_ix));
689				break;
690			}
691
692			hostwake = mux4350_hostwakeopt[hostwake_ix];
693			si_gci_set_functionsel(sih, hostwake, CC4350_FNSEL_MISC1);
694		}
695
696		break;
697	default:
698		/* muxenab specified for an unsupported chip */
699		ASSERT(0);
700		break;
701	}
702
703	/* write both updated values to hw */
704	si_pmu_chipcontrol(sih, 1, ~0, pmu_chipcontrol);
705	si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol),
706	           ~0, chipcontrol);
707}
708
709/* ltecx GCI reg access */
710uint32
711si_gci_direct(si_t *sih, uint offset, uint32 mask, uint32 val)
712{
713	/* gci direct reg access */
714	return si_corereg(sih, SI_CC_IDX, offset, mask, val);
715}
716uint32
717si_gci_indirect(si_t *sih, uint regidx, uint offset, uint32 mask, uint32 val)
718{
719	/* gci indirect reg access */
720	si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gci_indirect_addr), ~0, regidx);
721	return si_corereg(sih, SI_CC_IDX, offset, mask, val);
722}
723uint32
724si_gci_input(si_t *sih, uint reg)
725{
726	/* gci_input[] */
727	return si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gci_input[reg]), 0, 0);
728}
729uint32
730si_gci_output(si_t *sih, uint reg, uint32 mask, uint32 val)
731{
732	/* gci_output[] */
733	return si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gci_output[reg]), mask, val);
734}
735uint32
736si_gci_int_enable(si_t *sih, bool enable)
737{
738	uint offs;
739
740	/* enable GCI interrupt */
741	offs = OFFSETOF(chipcregs_t, intmask);
742	return (si_corereg(sih, SI_CC_IDX, offs, CI_ECI, (enable ? CI_ECI : 0)));
743}
744void
745si_gci_reset(si_t *sih)
746{
747	int i;
748
749	/* reset SECI block */
750	si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_corectrl), 0xFFFFFFFF, 0x01);
751	for (i = 0; i < 100; i++);
752	si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_corectrl), 0xFFFFFFFF, 0x00);
753
754	/* clear events */
755	for (i = 0; i < 32; i++)
756		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_event[i]), 0xFFFFFFFF, 0x00);
757}
758void
759si_ercx_init(si_t *sih)
760{
761	if (CHIPID(sih->chip) == BCM4334_CHIP_ID) {
762		/* enable ERCX: jtagSel bit=0, gpio as ercx bit=1 */
763		si_pmu_chipcontrol(sih, PMU1_PLL0_CHIPCTL1, 0x0000000F, 0x0000000A);
764	}
765	else if (CHIPID(sih->chip) == BCM4335_CHIP_ID ||
766		0) {
767		/* reset GCI block */
768		si_gci_reset(sih);
769
770		/* enable ERCX (pure gpio) mode */
771		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_corectrl), 0xFFFFFFFF, 0x30);
772
773		/* GPIO config for 4335b0 ref board */
774		/* config GPIO 2-3-4-5-6 as pure GPIO for ERCX */
775		si_gci_set_functionsel(sih, CC4335_PIN_GPIO_02, CC4335_FNSEL_GCI0);
776		si_gci_set_functionsel(sih, CC4335_PIN_GPIO_03, CC4335_FNSEL_GCI0);
777		si_gci_set_functionsel(sih, CC4335_PIN_GPIO_04, CC4335_FNSEL_GCI0);
778		si_gci_set_functionsel(sih, CC4335_PIN_GPIO_05, CC4335_FNSEL_GCI0);
779		si_gci_set_functionsel(sih, CC4335_PIN_GPIO_06, CC4335_FNSEL_GCI0);
780		/* enable gpio0 for debug */
781		si_gci_set_functionsel(sih, CC4335_PIN_GPIO_00, CC4335_FNSEL_SAMEASPIN);
782		si_gpiocontrol(sih, 0x01, 0x01, GPIO_DRV_PRIORITY);
783
784	/* gpio-2/7 as output & gpio-0/1/6 as input */
785		si_gci_indirect(sih, 0,
786			OFFSETOF(chipcregs_t, gci_gpioctl), 0xFFFFFFFF, 0x00020101);
787		si_gci_indirect(sih, 1,
788			OFFSETOF(chipcregs_t, gci_gpioctl), 0xFFFFFFFF, 0x02010000);
789		/* gpio mapping:
790		 * wlan_prio(gpio5(7)),frmsync(gpio2(1)),
791		 * mws_tx(gpio3(0)),mws_rx(gpio4(6))
792		 */
793		si_gci_indirect(sih, 0x10010,
794			OFFSETOF(chipcregs_t, gci_gpiomask), 0xFFFFFFFF, 0x00000001);
795		si_gci_indirect(sih, 0x60010,
796			OFFSETOF(chipcregs_t, gci_gpiomask), 0xFFFFFFFF, 0x00000002);
797		si_gci_indirect(sih, 0x00010,
798			OFFSETOF(chipcregs_t, gci_gpiomask), 0xFFFFFFFF, 0x00000004);
799		si_gci_indirect(sih, 0x70000,
800			OFFSETOF(chipcregs_t, gci_gpiomask), 0xFFFFFFFF, 0x00000010);
801		si_gci_indirect(sih, 0x20000,
802			OFFSETOF(chipcregs_t, gci_gpiomask), 0xFFFFFFFF, 0x00000040);
803	}
804}
805void
806si_wci2_init(si_t *sih)
807{
808	if (CHIPID(sih->chip) == BCM4335_CHIP_ID ||
809		0) {
810		/* reset GCI block */
811		si_gci_reset(sih);
812
813		/* enable BT-SIG mode */
814		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_corectrl), 0xFFFFFFFF, 0x24);
815		/* config GPIO pins 4/5 as SECI_IN/SECI_OUT */
816		si_gci_set_functionsel(sih, CC4335_PIN_GPIO_04, CC4335_FNSEL_GCI0);
817		si_gci_set_functionsel(sih, CC4335_PIN_GPIO_05, CC4335_FNSEL_GCI0);
818		/* baudrate:3mbps, escseq:0xdb, high baudrate, enable seci_tx/rx */
819		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_miscctl), 0x000F, 0x0000);
820		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_secibauddiv), 0xFFFFFFFF, 0xF4);
821		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_secifcr), 0xFFFFFFFF, 0x00);
822		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_secimcr), 0xFFFFFFFF, 0x89);
823		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_secilcr), 0xFFFFFFFF, 0x28);
824		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_uartescval), 0xFFFFFFFF, 0xDB);
825		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_baudadj), 0xFFFFFFFF, 0x22);
826
827		/* GPIO 3-7 as BT_SIG complaint */
828		/* config GPIO pins 3-7 as input */
829		si_gci_indirect(sih, 0,
830			OFFSETOF(chipcregs_t, gci_gpioctl), 0x20000000, 0x20000000);
831		si_gci_indirect(sih, 1,
832			OFFSETOF(chipcregs_t, gci_gpioctl), 0x20202020, 0x20202020);
833		/* gpio mapping: frmsync-gpio7, mws_rx-gpio6, mws_tx-gpio5,
834		 * pat[0]-gpio4, pat[1]-gpio3
835		 */
836		si_gci_indirect(sih, 0x70010,
837			OFFSETOF(chipcregs_t, gci_gpiomask), 0x00000001, 0x00000001);
838		si_gci_indirect(sih, 0x60010,
839			OFFSETOF(chipcregs_t, gci_gpiomask), 0x00000002, 0x00000002);
840		si_gci_indirect(sih, 0x50010,
841			OFFSETOF(chipcregs_t, gci_gpiomask), 0x00000004, 0x00000004);
842		si_gci_indirect(sih, 0x40010,
843			OFFSETOF(chipcregs_t, gci_gpiomask), 0x06000000, 0x06000000);
844		si_gci_indirect(sih, 0x30010,
845			OFFSETOF(chipcregs_t, gci_gpiomask), 0x08000000, 0x08000000);
846		/* gpio mapping: wlan_rx_prio-gpio5, wlan_tx_on-gpio4 */
847		si_gci_indirect(sih, 0x50000,
848			OFFSETOF(chipcregs_t, gci_gpiomask), 0x00000010, 0x00000010);
849		si_gci_indirect(sih, 0x40000,
850			OFFSETOF(chipcregs_t, gci_gpiomask), 0x00000020, 0x00000020);
851		/* enable gpio out on gpio4(wlanrxprio), gpio5(wlantxon) */
852		si_gci_direct(sih,
853			OFFSETOF(chipcregs_t, gci_control_0), 0x00000030, 0x00000030);
854	}
855}
856
857uint16
858si_cc_get_reg16(uint32 reg_offs)
859{
860	return (*((volatile uint16 *)((char *)SI_ENUM_BASE + reg_offs)));
861}
862
863uint32
864si_cc_get_reg32(uint32 reg_offs)
865{
866	return (*((volatile uint32 *)((char *)SI_ENUM_BASE + reg_offs)));
867}
868
869uint32
870si_cc_set_reg32(uint32 reg_offs, uint32 val)
871{
872	*((volatile uint32 *)((char *)SI_ENUM_BASE + reg_offs)) = val;
873	return si_cc_get_reg32(reg_offs);
874}
875
876uint32
877si_gci_preinit_upd_indirect(uint32 regidx, uint32 setval, uint32 mask)
878{
879	uint32 val = 0;
880
881	si_cc_set_reg32(CC_GCI_INDIRECT_ADDR_REG, regidx);
882	val = si_cc_get_reg32(CC_GCI_CHIP_CTRL_REG);
883
884	val &= ~mask;
885	val |= setval;
886
887	return si_cc_set_reg32(CC_GCI_CHIP_CTRL_REG, val);
888}
889
890void
891si_gci_seci_init(si_t *sih)
892{
893	if (CHIPID(sih->chip) == BCM4335_CHIP_ID ||
894		0) {
895		/* reset GCI block */
896		si_gci_reset(sih);
897
898		/* enable SECI mode */
899		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_corectrl), 0xFFFFFFFF, 0x14);
900		/* config GPIO pins 4/5 as SECI_IN/SECI_OUT */
901		si_gci_set_functionsel(sih, CC4335_PIN_GPIO_04, CC4335_FNSEL_GCI0);
902		si_gci_set_functionsel(sih, CC4335_PIN_GPIO_05, CC4335_FNSEL_GCI0);
903		/* baudrate:3mbps, escseq:0xdb, high baudrate, enable seci_tx/rx */
904		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_miscctl), 0x0000000F, 0x0000);
905		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_secibauddiv), 0xFFFFFFFF, 0xF4);
906		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_secifcr), 0xFFFFFFFF, 0x00);
907		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_secimcr), 0xFFFFFFFF, 0x89);
908		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_secilcr), 0xFFFFFFFF, 0x28);
909		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_uartescval), 0xFFFFFFFF, 0xDB);
910		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_baudadj), 0xFFFFFFFF, 0x22);
911
912		/* map nibble from IP=4 (LTE) with addr 0-11 to LTE space
913		 * (lower nibble addr; upper nibble IP)
914		 */
915		si_gci_indirect(sih, 0,
916			OFFSETOF(chipcregs_t, gci_secif0rx_offset), 0xFFFFFFFF, 0x43424140);
917		si_gci_indirect(sih, 1,
918			OFFSETOF(chipcregs_t, gci_secif0rx_offset), 0xFFFFFFFF, 0x47464544);
919		si_gci_indirect(sih, 2,
920			OFFSETOF(chipcregs_t, gci_secif0rx_offset), 0xFFFFFFFF, 0x4b4a4948);
921
922		/* select nibbles to be communicated using format-I: wlan nibble 1/4, bt nibble 1 */
923		/* note: we can only select 1st 12 nibbles of each IP for format_0 */
924		si_gci_indirect(sih, 0,
925			OFFSETOF(chipcregs_t, gci_seciusef0tx_reg), 0xFFFFFFFF, 0x00000012);
926		si_gci_indirect(sih, 1,
927			OFFSETOF(chipcregs_t, gci_seciusef0tx_reg), 0xFFFFFFFF, 0x00000002);
928
929		/* assigns address to To LTE nibbles from BT-WLAN IP space (addr 0 to 11) */
930		/* wlan nibble1: addr0, wlan nibble4: addr1, wlan nibble12: can't be communicated */
931		/* bt nibble1: addr2, bt nibble12/13: can't be communicated */
932		si_gci_indirect(sih, 0,
933			OFFSETOF(chipcregs_t, gci_secif0tx_offset), 0x000F00F0, 0x00010000);
934		si_gci_indirect(sih, 4,
935			OFFSETOF(chipcregs_t, gci_secif0tx_offset), 0x000000F0, 0x00000020);
936
937		/* enable wlan nibble 1 and 4 control bits */
938		/* NOTE: BT should enable bits for nibble 1 */
939		si_gci_direct(sih,
940			OFFSETOF(chipcregs_t, gci_control_0), 0xFFFFFFFF, 0x000F00F0);
941
942		/* mailbox 1 to 1 mapping:
943		 * mailbox data generated by an IP goes to its own mailbox space in peer GCI chip
944		 */
945		si_gci_direct(sih,
946			OFFSETOF(chipcregs_t, gci_secif1tx_offset), 0xFFFFFFFF, 0x00043210);
947	}
948}
949
950
951/** write 'val' to the gci chip control register indexed by 'reg' */
952uint32
953si_gci_chipcontrol(si_t *sih, uint reg, uint32 mask, uint32 val)
954{
955	/* because NFLASH and GCI clashes in 0xC00 */
956#ifndef NFLASH_SUPPORT
957	si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gci_indirect_addr), ~0, reg);
958	return si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gci_chipctrl), mask, val);
959#else /* NFLASH_SUPPORT */
960	ASSERT(0);
961	return 0xFFFFFFFF;
962#endif
963}
964
965/* input: pin number
966* output: chipcontrol reg and bits to shift for pin fn-sel's first regbit.
967* eg: gpio9 will give regidx: 1 and pos 4
968*/
969uint8
970si_gci_get_chipctrlreg_idx(uint32 pin, uint32 *regidx, uint32 *pos)
971{
972	*regidx = (pin / 8);
973	*pos = (pin % 8)*4;
974
975	SI_MSG(("si_gci_get_chipctrlreg_idx:%d:%d:%d\n", pin, *regidx, *pos));
976
977	return 0;
978}
979
980/** setup a given pin for fnsel function */
981void
982si_gci_set_functionsel(si_t *sih, uint32 pin, uint8 fnsel)
983{
984	uint32 reg = 0, pos = 0;
985
986	SI_MSG(("si_gci_set_functionsel:%d\n", pin));
987
988	si_gci_get_chipctrlreg_idx(pin, &reg, &pos);
989	si_gci_chipcontrol(sih, reg, GCIMASK(pos), GCIPOSVAL(fnsel, pos));
990}
991
992void
993BCMATTACHFN(si_gci_chipctrl_overrides)(osl_t *osh, si_t *sih, char *pvars)
994{
995	uint8 num_cc = 0;
996	char gciccstr[16];
997	const char *otp_val;
998	uint32 gciccval = 0, cap1 = 0;
999	int i = 0;
1000
1001/* because NFLASH and GCI clashes in 0xC00 */
1002#ifndef NFLASH_SUPPORT
1003	cap1 = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gci_corecaps1), 0, 0);
1004#else /* NFLASH_SUPPORT */
1005	ASSERT(0);
1006#endif
1007	num_cc = CC_GCI_NUMCHIPCTRLREGS(cap1);
1008
1009	for (i = 0; i < num_cc; i++) {
1010		snprintf(gciccstr, sizeof(gciccstr), "gcr%d", i);
1011
1012		if ((otp_val = getvar(NULL, gciccstr)) == NULL)
1013			continue;
1014
1015		gciccval = (uint32) getintvar(pvars, gciccstr);
1016		si_gci_chipcontrol(sih, i, ~0, gciccval);
1017	}
1018}
1019
1020static si_info_t *
1021BCMATTACHFN(si_doattach)(si_info_t *sii, uint devid, osl_t *osh, void *regs,
1022                       uint bustype, void *sdh, char **vars, uint *varsz)
1023{
1024	struct si_pub *sih = &sii->pub;
1025	uint32 w, savewin;
1026	chipcregs_t *cc;
1027	char *pvars = NULL;
1028	uint origidx;
1029#if (!defined(_CFE_) && !defined(_CFEZ_)) || defined(CFG_WL)
1030	bool fixup_boardtype = FALSE;
1031#endif /* (!_CFE_ && !_CFEZ_) || CFG_WL */
1032	ASSERT(GOODREGS(regs));
1033
1034	bzero((uchar*)sii, sizeof(si_info_t));
1035
1036	savewin = 0;
1037
1038	sih->buscoreidx = BADIDX;
1039
1040	sii->curmap = regs;
1041	sii->sdh = sdh;
1042	sii->osh = osh;
1043
1044#ifdef SI_ENUM_BASE_VARIABLE
1045	si_enum_base_init(sih, bustype);
1046#endif /* SI_ENUM_BASE_VARIABLE */
1047
1048	/* check to see if we are a si core mimic'ing a pci core */
1049	if ((bustype == PCI_BUS) &&
1050	    (OSL_PCI_READ_CONFIG(sii->osh, PCI_SPROM_CONTROL, sizeof(uint32)) == 0xffffffff)) {
1051		SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI "
1052		          "devid:0x%x\n", __FUNCTION__, devid));
1053		bustype = SI_BUS;
1054	}
1055
1056	/* find Chipcommon address */
1057	if (bustype == PCI_BUS) {
1058		savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
1059		if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
1060			savewin = SI_ENUM_BASE;
1061		OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE);
1062		if (!regs)
1063			return NULL;
1064		cc = (chipcregs_t *)regs;
1065	} else {
1066		cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
1067	}
1068
1069	sih->bustype = bustype;
1070	if (bustype != BUSTYPE(bustype)) {
1071		SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n",
1072			bustype, BUSTYPE(bustype)));
1073		return NULL;
1074	}
1075
1076	/* bus/core/clk setup for register access */
1077	if (!si_buscore_prep(sii, bustype, devid, sdh)) {
1078		SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype));
1079		return NULL;
1080	}
1081
1082	/* ChipID recognition.
1083	 *   We assume we can read chipid at offset 0 from the regs arg.
1084	 *   If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
1085	 *   some way of recognizing them needs to be added here.
1086	 */
1087	if (!cc) {
1088		SI_ERROR(("%s: chipcommon register space is null \n", __FUNCTION__));
1089		return NULL;
1090	}
1091	w = R_REG(osh, &cc->chipid);
1092	sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
1093	/* Might as wll fill in chip id rev & pkg */
1094	sih->chip = w & CID_ID_MASK;
1095	sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
1096	sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
1097
1098	if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) &&
1099		(sih->chippkg != BCM4329_289PIN_PKG_ID)) {
1100		sih->chippkg = BCM4329_182PIN_PKG_ID;
1101	}
1102	sih->issim = IS_SIM(sih->chippkg);
1103
1104	/* scan for cores */
1105	if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) {
1106		SI_MSG(("Found chip type SB (0x%08x)\n", w));
1107		sb_scan(&sii->pub, regs, devid);
1108	} else if ((CHIPTYPE(sii->pub.socitype) == SOCI_AI) ||
1109		(CHIPTYPE(sii->pub.socitype) == SOCI_NAI)) {
1110		if (CHIPTYPE(sii->pub.socitype) == SOCI_AI)
1111			SI_MSG(("Found chip type AI (0x%08x)\n", w));
1112		else
1113			SI_MSG(("Found chip type NAI (0x%08x)\n", w));
1114		/* pass chipc address instead of original core base */
1115		ai_scan(&sii->pub, (void *)(uintptr)cc, devid);
1116	} else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
1117		SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip));
1118		/* pass chipc address instead of original core base */
1119		ub_scan(&sii->pub, (void *)(uintptr)cc, devid);
1120	} else {
1121		SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
1122		return NULL;
1123	}
1124	/* no cores found, bail out */
1125	if (sii->numcores == 0) {
1126		SI_ERROR(("si_doattach: could not find any cores\n"));
1127		return NULL;
1128	}
1129	/* bus/core/clk setup */
1130	origidx = SI_CC_IDX;
1131	if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
1132		SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
1133		goto exit;
1134	}
1135
1136#if (!defined(_CFE_) && !defined(_CFEZ_)) || defined(CFG_WL)
1137	if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK)
1138		>> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT |
1139		CST4322_SPROM_PRESENT))) {
1140		SI_ERROR(("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__));
1141		return NULL;
1142	}
1143
1144	/* assume current core is CC */
1145	if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID ||
1146	                                  CHIPID(sih->chip) == BCM43235_CHIP_ID ||
1147	                                  CHIPID(sih->chip) == BCM43234_CHIP_ID ||
1148	                                  CHIPID(sih->chip) == BCM43238_CHIP_ID) &&
1149	                                 (CHIPREV(sii->pub.chiprev) <= 2))) {
1150
1151		if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
1152			uint clkdiv;
1153			clkdiv = R_REG(osh, &cc->clkdiv);
1154			/* otp_clk_div is even number, 120/14 < 9mhz */
1155			clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
1156			W_REG(osh, &cc->clkdiv, clkdiv);
1157			SI_ERROR(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv));
1158		}
1159		OSL_DELAY(10);
1160	}
1161
1162	if (bustype == PCI_BUS) {
1163		if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
1164		    (CHIPID(sih->chip) == BCM43431_CHIP_ID)) {
1165			/* Check Ext PA Controls for 4331 12x9 Package before the fixup */
1166			if (sih->chippkg == 9) {
1167				uint32 val = si_chipcontrl_read(sih);
1168				fixup_boardtype = ((val & CCTRL4331_EXTPA_ON_GPIO2_5) ==
1169					CCTRL4331_EXTPA_ON_GPIO2_5);
1170			}
1171			/* set default mux pin to SROM */
1172			si_chipcontrl_epa4331(sih, FALSE);
1173			si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, 100);
1174			OSL_DELAY(20000);	/* Srom read takes ~12mS */
1175		}
1176
1177		if (((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
1178		     (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
1179		     (CHIPID(sih->chip) == BCM4352_CHIP_ID)) &&
1180		    (CHIPREV(sih->chiprev) <= 2)) {
1181			pcie_disable_TL_clk_gating(sii->pch);
1182			pcie_set_L1_entry_time(sii->pch, 0x40);
1183		}
1184
1185#ifdef BCMQT
1186		/* Set OTPClkDiv to smaller value otherwise OTP always reads 0xFFFF.
1187		 * For real-chip we shouldn't set OTPClkDiv to 2 because 20/2 = 10 > 9Mhz
1188		 * but for 4314 QT if we set it to 4. OTP reads 0xFFFF every two words.
1189		 */
1190		{
1191			uint otpclkdiv = 0;
1192
1193			if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) ||
1194				(CHIPID(sih->chip) == BCM43142_CHIP_ID)) {
1195				otpclkdiv = 2;
1196			} else if ((CHIPID(sih->chip) == BCM43131_CHIP_ID) ||
1197				(CHIPID(sih->chip) == BCM43217_CHIP_ID) ||
1198				(CHIPID(sih->chip) == BCM43227_CHIP_ID) ||
1199				(CHIPID(sih->chip) == BCM43228_CHIP_ID)) {
1200				otpclkdiv = 4;
1201			}
1202
1203			if (otpclkdiv != 0) {
1204				uint clkdiv, savecore;
1205				savecore = si_coreidx(sih);
1206				si_setcore(sih, CC_CORE_ID, 0);
1207
1208				clkdiv = R_REG(osh, &cc->clkdiv);
1209				clkdiv = (clkdiv & ~CLKD_OTP) | (otpclkdiv << CLKD_OTP_SHIFT);
1210				W_REG(osh, &cc->clkdiv, clkdiv);
1211
1212				SI_ERROR(("%s: set clkdiv to 0x%x for QT\n", __FUNCTION__, clkdiv));
1213				si_setcoreidx(sih, savecore);
1214			}
1215		}
1216#endif /* BCMQT */
1217	}
1218#endif /* (!_CFE_ && !_CFEZ_) || CFG_WL */
1219#ifdef BCM_SDRBL
1220	/* 4360 rom bootloader in PCIE case, if the SDR is enabled, But protection is
1221	 * not turned on, then we want to hold arm in reset.
1222	 * Bottomline: In sdrenable case, we allow arm to boot only when protection is
1223	 * turned on.
1224	 */
1225	if (CHIP_HOSTIF_PCIE(&(sii->pub))) {
1226		uint32 sflags = si_arm_sflags(&(sii->pub));
1227
1228		/* If SDR is enabled but protection is not turned on
1229		* then we want to force arm to WFI.
1230		*/
1231		if ((sflags & (SISF_SDRENABLE | SISF_TCMPROT)) == SISF_SDRENABLE) {
1232			disable_arm_irq();
1233			while (1) {
1234				hnd_cpu_wait(sih);
1235			}
1236		}
1237	}
1238#endif /* BCM_SDRBL */
1239#ifdef SI_SPROM_PROBE
1240	si_sprom_init(sih);
1241#endif /* SI_SPROM_PROBE */
1242
1243#if !defined(BCMHIGHSDIO)
1244	/* Init nvram from flash if it exists */
1245	nvram_init((void *)&(sii->pub));
1246
1247#if defined(_CFE_) && defined(BCM_DEVINFO)
1248	devinfo_nvram_init((void *)&(sii->pub));
1249#endif
1250
1251	/* Init nvram from sprom/otp if they exist */
1252	if (srom_var_init(&sii->pub, BUSTYPE(bustype), regs, sii->osh, vars, varsz)) {
1253		SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
1254		goto exit;
1255	}
1256	pvars = vars ? *vars : NULL;
1257
1258	si_nvram_process(sii, pvars);
1259
1260#if (!defined(_CFE_) && !defined(_CFEZ_)) || defined(CFG_WL)
1261	if (bustype == PCI_BUS) {
1262		if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
1263		    (CHIPID(sih->chip) == BCM43431_CHIP_ID)) {
1264			si_sromvars_fixup_4331(sih, pvars);
1265			if (fixup_boardtype)
1266				sii->pub.boardtype = getintvar(pvars, "boardtype");
1267		}
1268	}
1269#endif /* (!_CFE_ && !_CFEZ_) || CFG_WL */
1270
1271	/* === NVRAM, clock is ready === */
1272#else
1273	pvars = NULL;
1274	BCM_REFERENCE(pvars);
1275#endif
1276
1277
1278#if defined(CONFIG_XIP) && defined(BCMTCAM)
1279		/* patch the ROM if there are any patch pairs from OTP/SPROM */
1280		if (patch_pair) {
1281
1282#if defined(__ARM_ARCH_7R__)
1283			hnd_tcam_bootloader_load(si_setcore(sih, ARMCR4_CORE_ID, 0), pvars);
1284#else
1285			hnd_tcam_bootloader_load(si_setcore(sih, SOCRAM_CORE_ID, 0), pvars);
1286#endif
1287			si_setcoreidx(sih, origidx);
1288		}
1289#endif /* CONFIG_XIP && BCMTCAM */
1290
1291		/* bootloader should retain default pulls */
1292#ifndef BCM_BOOTLOADER
1293		if (sii->pub.ccrev >= 20) {
1294			uint32 gpiopullup = 0, gpiopulldown = 0;
1295			cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
1296			ASSERT(cc != NULL);
1297
1298			/* 4314/43142 has pin muxing, don't clear gpio bits */
1299			if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) ||
1300				(CHIPID(sih->chip) == BCM43142_CHIP_ID)) {
1301				gpiopullup |= 0x402e0;
1302				gpiopulldown |= 0x20500;
1303			}
1304
1305			W_REG(osh, &cc->gpiopullup, gpiopullup);
1306			W_REG(osh, &cc->gpiopulldown, gpiopulldown);
1307			si_setcoreidx(sih, origidx);
1308		}
1309#endif /* !BCM_BOOTLOADER */
1310
1311		/* PMU specific initializations */
1312		if (PMUCTL_ENAB(sih)) {
1313			uint32 xtalfreq, mode;
1314			si_pmu_init(sih, sii->osh);
1315			si_pmu_chip_init(sih, sii->osh);
1316			xtalfreq = getintvar(pvars, "xtalfreq");
1317			switch (CHIPID(sih->chip)) {
1318				case BCM43242_CHIP_ID:
1319				case BCM43243_CHIP_ID:
1320					xtalfreq = 37400;
1321					break;
1322				case BCM43143_CHIP_ID:
1323					xtalfreq = 20000;
1324					break;
1325				case BCM4350_CHIP_ID:
1326					if (xtalfreq == 0) {
1327						mode = CST4350_IFC_MODE(sih->chipst);
1328						if ((mode == CST4350_IFC_MODE_USB20D) ||
1329							(mode == CST4350_IFC_MODE_USB30D) ||
1330							(mode == CST4350_IFC_MODE_USB30D_WL))
1331							xtalfreq = 40000;
1332						else
1333							xtalfreq = 37400;
1334					}
1335					break;
1336				default:
1337					break;
1338			}
1339			/* If xtalfreq var not available, try to measure it */
1340			if (xtalfreq == 0)
1341				xtalfreq = si_pmu_measure_alpclk(sih, sii->osh);
1342#if !defined(BCMHIGHSDIO)
1343			si_pmu_pll_init(sih, sii->osh, xtalfreq);
1344#endif
1345
1346#if defined(SR_ESSENTIALS)
1347			/* Only needs to be done once.
1348			 * Needs this before si_pmu_res_init() to use sr_isenab()
1349			 */
1350			if (SR_ESSENTIALS_ENAB())
1351				sr_save_restore_init(sih);
1352#endif /* SR_ESSENTIALS */
1353#if !defined(BCMHIGHSDIO)
1354			si_pmu_res_init(sih, sii->osh);
1355#endif
1356			si_pmu_swreg_init(sih, sii->osh);
1357		}
1358
1359#ifdef WLLED
1360	/* setup the GPIO based LED powersave register */
1361	if (sii->pub.ccrev >= 16) {
1362		if ((w = getintvar(pvars, "leddc")) == 0)
1363			w = DEFAULT_GPIOTIMERVAL;
1364		si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
1365	}
1366#endif
1367	if (PCI_FORCEHT(sii)) {
1368		SI_MSG(("si_doattach: force HT\n"));
1369		sih->pci_pr32414 = TRUE;
1370		si_clkctl_init(sih);
1371		_si_clkctl_cc(sii, CLK_FAST);
1372	}
1373
1374#if (!defined(_CFE_) && !defined(_CFEZ_)) || defined(CFG_WL)
1375	if (PCIE(sii)) {
1376		ASSERT(sii->pch != NULL);
1377
1378		pcicore_attach(sii->pch, pvars, SI_DOATTACH);
1379
1380		if (((CHIPID(sih->chip) == BCM4311_CHIP_ID) && (CHIPREV(sih->chiprev) == 2)) ||
1381		    (CHIPID(sih->chip) == BCM4312_CHIP_ID)) {
1382			SI_MSG(("si_doattach: clear initiator timeout\n"));
1383			sb_set_initiator_to(sih, 0x3, si_findcoreidx(sih, D11_CORE_ID, 0));
1384		}
1385	}
1386
1387	if ((CHIPID(sih->chip) == BCM43224_CHIP_ID) ||
1388		(CHIPID(sih->chip) == BCM43421_CHIP_ID)) {
1389		/* enable 12 mA drive strenth for 43224 and set chipControl register bit 15 */
1390		if (CHIPREV(sih->chiprev) == 0) {
1391			SI_MSG(("Applying 43224A0 WARs\n"));
1392			si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol),
1393			           CCTRL43224_GPIO_TOGGLE, CCTRL43224_GPIO_TOGGLE);
1394			si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE,
1395			                   CCTRL_43224A0_12MA_LED_DRIVE);
1396		}
1397		if (CHIPREV(sih->chiprev) >= 1) {
1398			SI_MSG(("Applying 43224B0+ WARs\n"));
1399			si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE,
1400			                   CCTRL_43224B0_12MA_LED_DRIVE);
1401		}
1402	}
1403
1404	/* configure default pinmux enables for the chip */
1405	if (getvar(pvars, "muxenab") != NULL) {
1406		w = getintvar(pvars, "muxenab");
1407		si_muxenab((si_t *)sii, w);
1408	}
1409
1410	/* enable GPIO interrupts when clocks are off */
1411	if (sii->pub.ccrev >= 21) {
1412		uint32 corecontrol;
1413		corecontrol = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, corecontrol),
1414		                         0, 0);
1415		corecontrol |= CC_ASYNCGPIO;
1416		si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, corecontrol),
1417		           corecontrol, corecontrol);
1418	}
1419
1420	if (CHIPID(sih->chip) == BCM4313_CHIP_ID) {
1421		/* enable 12 mA drive strenth for 4313 and set chipControl register bit 1 */
1422		SI_MSG(("Applying 4313 WARs\n"));
1423		si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE,	CCTRL_4313_12MA_LED_DRIVE);
1424	}
1425#endif /* (!_CFE_ && !_CFEZ_) || CFG_WL */
1426	/* clear any previous epidiag-induced target abort */
1427	ASSERT(!si_taclear(sih, FALSE));
1428
1429	if ((CHIPID(sih->chip) == BCM4335_CHIP_ID) ||
1430#ifndef BCM4350_FPGA
1431	(CHIPID(sih->chip) == BCM4350_CHIP_ID) ||
1432#endif
1433	0) {
1434		si_gci_chipctrl_overrides(osh, sih, pvars);
1435	}
1436
1437	return (sii);
1438
1439exit:
1440	if (BUSTYPE(sih->bustype) == PCI_BUS) {
1441		if (sii->pch)
1442			pcicore_deinit(sii->pch);
1443		sii->pch = NULL;
1444	}
1445
1446	return NULL;
1447}
1448
1449/** may be called with core in reset */
1450void
1451BCMATTACHFN(si_detach)(si_t *sih)
1452{
1453	si_info_t *sii;
1454	uint idx;
1455
1456#if defined(STA)
1457	struct si_pub *si_local = NULL;
1458	bcopy(&sih, &si_local, sizeof(si_t*));
1459#endif
1460
1461	sii = SI_INFO(sih);
1462
1463	if (sii == NULL)
1464		return;
1465
1466	if (BUSTYPE(sih->bustype) == SI_BUS)
1467		for (idx = 0; idx < SI_MAXCORES; idx++)
1468			if (sii->regs[idx]) {
1469				REG_UNMAP(sii->regs[idx]);
1470				sii->regs[idx] = NULL;
1471			}
1472
1473#if defined(STA)
1474#if !defined(BCMHIGHSDIO)
1475	srom_var_deinit((void *)si_local);
1476#endif
1477	nvram_exit((void *)si_local); /* free up nvram buffers */
1478#endif
1479
1480#if defined(STB)
1481	nvram_exit((void *)sih);
1482#endif /* defined(STB) */
1483
1484	if (BUSTYPE(sih->bustype) == PCI_BUS) {
1485		if (sii->pch)
1486			pcicore_deinit(sii->pch);
1487		sii->pch = NULL;
1488	}
1489
1490#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
1491	if (sii != &ksii)
1492#endif	/* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
1493		MFREE(sii->osh, sii, sizeof(si_info_t));
1494}
1495
1496void *
1497si_osh(si_t *sih)
1498{
1499	si_info_t *sii;
1500
1501	sii = SI_INFO(sih);
1502	return sii->osh;
1503}
1504
1505void
1506si_setosh(si_t *sih, osl_t *osh)
1507{
1508	si_info_t *sii;
1509
1510	sii = SI_INFO(sih);
1511	if (sii->osh != NULL) {
1512		SI_ERROR(("osh is already set....\n"));
1513		ASSERT(!sii->osh);
1514	}
1515	sii->osh = osh;
1516}
1517
1518/** register driver interrupt disabling and restoring callback functions */
1519void
1520si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
1521                          void *intrsenabled_fn, void *intr_arg)
1522{
1523	si_info_t *sii;
1524
1525	sii = SI_INFO(sih);
1526	sii->intr_arg = intr_arg;
1527	sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn;
1528	sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn;
1529	sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn;
1530	/* save current core id.  when this function called, the current core
1531	 * must be the core which provides driver functions(il, et, wl, etc.)
1532	 */
1533	sii->dev_coreid = sii->coreid[sii->curidx];
1534}
1535
1536void
1537si_deregister_intr_callback(si_t *sih)
1538{
1539	si_info_t *sii;
1540
1541	sii = SI_INFO(sih);
1542	sii->intrsoff_fn = NULL;
1543}
1544
1545uint
1546si_intflag(si_t *sih)
1547{
1548	si_info_t *sii = SI_INFO(sih);
1549
1550	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1551		return sb_intflag(sih);
1552	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1553		return R_REG(sii->osh, ((uint32 *)(uintptr)
1554			    (sii->oob_router + OOB_STATUSA)));
1555	else {
1556		ASSERT(0);
1557		return 0;
1558	}
1559}
1560
1561uint
1562si_flag(si_t *sih)
1563{
1564	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1565		return sb_flag(sih);
1566	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1567		return ai_flag(sih);
1568	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1569		return ub_flag(sih);
1570	else {
1571		ASSERT(0);
1572		return 0;
1573	}
1574}
1575
1576uint
1577si_flag_alt(si_t *sih)
1578{
1579	if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1580		return ai_flag_alt(sih);
1581	else {
1582		ASSERT(0);
1583		return 0;
1584	}
1585}
1586
1587void
1588si_setint(si_t *sih, int siflag)
1589{
1590	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1591		sb_setint(sih, siflag);
1592	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1593		ai_setint(sih, siflag);
1594	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1595		ub_setint(sih, siflag);
1596	else
1597		ASSERT(0);
1598}
1599
1600uint
1601si_coreid(si_t *sih)
1602{
1603	si_info_t *sii;
1604
1605	sii = SI_INFO(sih);
1606	return sii->coreid[sii->curidx];
1607}
1608
1609uint
1610si_coreidx(si_t *sih)
1611{
1612	si_info_t *sii;
1613
1614	sii = SI_INFO(sih);
1615	return sii->curidx;
1616}
1617
1618/** return the core-type instantiation # of the current core */
1619uint
1620si_coreunit(si_t *sih)
1621{
1622	si_info_t *sii;
1623	uint idx;
1624	uint coreid;
1625	uint coreunit;
1626	uint i;
1627
1628	sii = SI_INFO(sih);
1629	coreunit = 0;
1630
1631	idx = sii->curidx;
1632
1633	ASSERT(GOODREGS(sii->curmap));
1634	coreid = si_coreid(sih);
1635
1636	/* count the cores of our type */
1637	for (i = 0; i < idx; i++)
1638		if (sii->coreid[i] == coreid)
1639			coreunit++;
1640
1641	return (coreunit);
1642}
1643
1644uint
1645si_corevendor(si_t *sih)
1646{
1647	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1648		return sb_corevendor(sih);
1649	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1650		return ai_corevendor(sih);
1651	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1652		return ub_corevendor(sih);
1653	else {
1654		ASSERT(0);
1655		return 0;
1656	}
1657}
1658
1659bool
1660si_backplane64(si_t *sih)
1661{
1662	return ((sih->cccaps & CC_CAP_BKPLN64) != 0);
1663}
1664
1665uint
1666si_corerev(si_t *sih)
1667{
1668	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1669		return sb_corerev(sih);
1670	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1671		return ai_corerev(sih);
1672	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1673		return ub_corerev(sih);
1674	else {
1675		ASSERT(0);
1676		return 0;
1677	}
1678}
1679
1680/** return index of coreid or BADIDX if not found */
1681uint
1682si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
1683{
1684	si_info_t *sii;
1685	uint found;
1686	uint i;
1687
1688	sii = SI_INFO(sih);
1689
1690	found = 0;
1691
1692	for (i = 0; i < sii->numcores; i++)
1693		if (sii->coreid[i] == coreid) {
1694			if (found == coreunit)
1695				return (i);
1696			found++;
1697		}
1698
1699	return (BADIDX);
1700}
1701
1702/** return list of found cores */
1703uint
1704si_corelist(si_t *sih, uint coreid[])
1705{
1706	si_info_t *sii;
1707
1708	sii = SI_INFO(sih);
1709
1710	bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint)));
1711	return (sii->numcores);
1712}
1713
1714/** return current wrapper mapping */
1715void *
1716si_wrapperregs(si_t *sih)
1717{
1718	si_info_t *sii;
1719
1720	sii = SI_INFO(sih);
1721	ASSERT(GOODREGS(sii->curwrap));
1722
1723	return (sii->curwrap);
1724}
1725
1726/** return current register mapping */
1727void *
1728si_coreregs(si_t *sih)
1729{
1730	si_info_t *sii;
1731
1732	sii = SI_INFO(sih);
1733	ASSERT(GOODREGS(sii->curmap));
1734
1735	return (sii->curmap);
1736}
1737
1738/**
1739 * This function changes logical "focus" to the indicated core;
1740 * must be called with interrupts off.
1741 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
1742 */
1743void *
1744si_setcore(si_t *sih, uint coreid, uint coreunit)
1745{
1746	uint idx;
1747
1748	idx = si_findcoreidx(sih, coreid, coreunit);
1749	if (!GOODIDX(idx))
1750		return (NULL);
1751
1752	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1753		return sb_setcoreidx(sih, idx);
1754	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1755		return ai_setcoreidx(sih, idx);
1756	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1757		return ub_setcoreidx(sih, idx);
1758	else {
1759		ASSERT(0);
1760		return NULL;
1761	}
1762}
1763
1764void *
1765si_setcoreidx(si_t *sih, uint coreidx)
1766{
1767	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1768		return sb_setcoreidx(sih, coreidx);
1769	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1770		return ai_setcoreidx(sih, coreidx);
1771	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1772		return ub_setcoreidx(sih, coreidx);
1773	else {
1774		ASSERT(0);
1775		return NULL;
1776	}
1777}
1778
1779/** Turn off interrupt as required by sb_setcore, before switch core */
1780void *
1781si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
1782{
1783	void *cc;
1784	si_info_t *sii;
1785
1786	sii = SI_INFO(sih);
1787
1788	if (SI_FAST(sii)) {
1789		/* Overloading the origidx variable to remember the coreid,
1790		 * this works because the core ids cannot be confused with
1791		 * core indices.
1792		 */
1793		*origidx = coreid;
1794		if (coreid == CC_CORE_ID)
1795			return (void *)CCREGS_FAST(sii);
1796		else if (coreid == sih->buscoretype)
1797			return (void *)PCIEREGS(sii);
1798	}
1799	INTR_OFF(sii, *intr_val);
1800	*origidx = sii->curidx;
1801	cc = si_setcore(sih, coreid, 0);
1802	ASSERT(cc != NULL);
1803
1804	return cc;
1805}
1806
1807/* restore coreidx and restore interrupt */
1808void
1809si_restore_core(si_t *sih, uint coreid, uint intr_val)
1810{
1811	si_info_t *sii;
1812
1813	sii = SI_INFO(sih);
1814	if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
1815		return;
1816
1817	si_setcoreidx(sih, coreid);
1818	INTR_RESTORE(sii, intr_val);
1819}
1820
1821int
1822si_numaddrspaces(si_t *sih)
1823{
1824	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1825		return sb_numaddrspaces(sih);
1826	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1827		return ai_numaddrspaces(sih);
1828	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1829		return ub_numaddrspaces(sih);
1830	else {
1831		ASSERT(0);
1832		return 0;
1833	}
1834}
1835
1836uint32
1837si_addrspace(si_t *sih, uint asidx)
1838{
1839	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1840		return sb_addrspace(sih, asidx);
1841	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1842		return ai_addrspace(sih, asidx);
1843	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1844		return ub_addrspace(sih, asidx);
1845	else {
1846		ASSERT(0);
1847		return 0;
1848	}
1849}
1850
1851uint32
1852si_addrspacesize(si_t *sih, uint asidx)
1853{
1854	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1855		return sb_addrspacesize(sih, asidx);
1856	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1857		return ai_addrspacesize(sih, asidx);
1858	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1859		return ub_addrspacesize(sih, asidx);
1860	else {
1861		ASSERT(0);
1862		return 0;
1863	}
1864}
1865
1866void
1867si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
1868{
1869	/* Only supported for SOCI_AI */
1870	if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1871		ai_coreaddrspaceX(sih, asidx, addr, size);
1872	else
1873		*size = 0;
1874}
1875
1876uint32
1877si_core_cflags(si_t *sih, uint32 mask, uint32 val)
1878{
1879	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1880		return sb_core_cflags(sih, mask, val);
1881	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1882		return ai_core_cflags(sih, mask, val);
1883	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1884		return ub_core_cflags(sih, mask, val);
1885	else {
1886		ASSERT(0);
1887		return 0;
1888	}
1889}
1890
1891void
1892si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
1893{
1894	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1895		sb_core_cflags_wo(sih, mask, val);
1896	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1897		ai_core_cflags_wo(sih, mask, val);
1898	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1899		ub_core_cflags_wo(sih, mask, val);
1900	else
1901		ASSERT(0);
1902}
1903
1904uint32
1905si_core_sflags(si_t *sih, uint32 mask, uint32 val)
1906{
1907	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1908		return sb_core_sflags(sih, mask, val);
1909	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1910		return ai_core_sflags(sih, mask, val);
1911	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1912		return ub_core_sflags(sih, mask, val);
1913	else {
1914		ASSERT(0);
1915		return 0;
1916	}
1917}
1918
1919bool
1920si_iscoreup(si_t *sih)
1921{
1922	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1923		return sb_iscoreup(sih);
1924	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1925		return ai_iscoreup(sih);
1926	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1927		return ub_iscoreup(sih);
1928	else {
1929		ASSERT(0);
1930		return FALSE;
1931	}
1932}
1933
1934uint
1935si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
1936{
1937	/* only for AI back plane chips */
1938	if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1939		return (ai_wrap_reg(sih, offset, mask, val));
1940	return 0;
1941}
1942
1943uint
1944si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
1945{
1946	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1947		return sb_corereg(sih, coreidx, regoff, mask, val);
1948	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1949		return ai_corereg(sih, coreidx, regoff, mask, val);
1950	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1951		return ub_corereg(sih, coreidx, regoff, mask, val);
1952	else {
1953		ASSERT(0);
1954		return 0;
1955	}
1956}
1957
1958void
1959si_core_disable(si_t *sih, uint32 bits)
1960{
1961	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1962		sb_core_disable(sih, bits);
1963	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1964		ai_core_disable(sih, bits);
1965	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1966		ub_core_disable(sih, bits);
1967}
1968
1969void
1970si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
1971{
1972	if (CHIPTYPE(sih->socitype) == SOCI_SB)
1973		sb_core_reset(sih, bits, resetbits);
1974	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
1975		ai_core_reset(sih, bits, resetbits);
1976	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1977		ub_core_reset(sih, bits, resetbits);
1978}
1979
1980/** Run bist on current core. Caller needs to take care of core-specific bist hazards */
1981int
1982si_corebist(si_t *sih)
1983{
1984	uint32 cflags;
1985	int result = 0;
1986
1987	/* Read core control flags */
1988	cflags = si_core_cflags(sih, 0, 0);
1989
1990	/* Set bist & fgc */
1991	si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC));
1992
1993	/* Wait for bist done */
1994	SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);
1995
1996	if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
1997		result = BCME_ERROR;
1998
1999	/* Reset core control flags */
2000	si_core_cflags(sih, 0xffff, cflags);
2001
2002	return result;
2003}
2004
2005static uint32
2006BCMINITFN(factor6)(uint32 x)
2007{
2008	switch (x) {
2009	case CC_F6_2:	return 2;
2010	case CC_F6_3:	return 3;
2011	case CC_F6_4:	return 4;
2012	case CC_F6_5:	return 5;
2013	case CC_F6_6:	return 6;
2014	case CC_F6_7:	return 7;
2015	default:	return 0;
2016	}
2017}
2018
2019/** calculate the speed the SI would run at given a set of clockcontrol values */
2020uint32
2021BCMINITFN(si_clock_rate)(uint32 pll_type, uint32 n, uint32 m)
2022{
2023	uint32 n1, n2, clock, m1, m2, m3, mc;
2024
2025	n1 = n & CN_N1_MASK;
2026	n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
2027
2028	if (pll_type == PLL_TYPE6) {
2029		if (m & CC_T6_MMASK)
2030			return CC_T6_M1;
2031		else
2032			return CC_T6_M0;
2033	} else if ((pll_type == PLL_TYPE1) ||
2034	           (pll_type == PLL_TYPE3) ||
2035	           (pll_type == PLL_TYPE4) ||
2036	           (pll_type == PLL_TYPE7)) {
2037		n1 = factor6(n1);
2038		n2 += CC_F5_BIAS;
2039	} else if (pll_type == PLL_TYPE2) {
2040		n1 += CC_T2_BIAS;
2041		n2 += CC_T2_BIAS;
2042		ASSERT((n1 >= 2) && (n1 <= 7));
2043		ASSERT((n2 >= 5) && (n2 <= 23));
2044	} else if (pll_type == PLL_TYPE5) {
2045		return (100000000);
2046	} else
2047		ASSERT(0);
2048	/* PLL types 3 and 7 use BASE2 (25Mhz) */
2049	if ((pll_type == PLL_TYPE3) ||
2050	    (pll_type == PLL_TYPE7)) {
2051		clock = CC_CLOCK_BASE2 * n1 * n2;
2052	} else
2053		clock = CC_CLOCK_BASE1 * n1 * n2;
2054
2055	if (clock == 0)
2056		return 0;
2057
2058	m1 = m & CC_M1_MASK;
2059	m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
2060	m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
2061	mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
2062
2063	if ((pll_type == PLL_TYPE1) ||
2064	    (pll_type == PLL_TYPE3) ||
2065	    (pll_type == PLL_TYPE4) ||
2066	    (pll_type == PLL_TYPE7)) {
2067		m1 = factor6(m1);
2068		if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
2069			m2 += CC_F5_BIAS;
2070		else
2071			m2 = factor6(m2);
2072		m3 = factor6(m3);
2073
2074		switch (mc) {
2075		case CC_MC_BYPASS:	return (clock);
2076		case CC_MC_M1:		return (clock / m1);
2077		case CC_MC_M1M2:	return (clock / (m1 * m2));
2078		case CC_MC_M1M2M3:	return (clock / (m1 * m2 * m3));
2079		case CC_MC_M1M3:	return (clock / (m1 * m3));
2080		default:		return (0);
2081		}
2082	} else {
2083		ASSERT(pll_type == PLL_TYPE2);
2084
2085		m1 += CC_T2_BIAS;
2086		m2 += CC_T2M2_BIAS;
2087		m3 += CC_T2_BIAS;
2088		ASSERT((m1 >= 2) && (m1 <= 7));
2089		ASSERT((m2 >= 3) && (m2 <= 10));
2090		ASSERT((m3 >= 2) && (m3 <= 7));
2091
2092		if ((mc & CC_T2MC_M1BYP) == 0)
2093			clock /= m1;
2094		if ((mc & CC_T2MC_M2BYP) == 0)
2095			clock /= m2;
2096		if ((mc & CC_T2MC_M3BYP) == 0)
2097			clock /= m3;
2098
2099		return (clock);
2100	}
2101}
2102
2103/* Some chips could have multiple host interfaces, however only one will be active.
2104 * For a given chip. Depending pkgopt and cc_chipst return the active host interface.
2105 */
2106uint
2107si_chip_hostif(si_t *sih)
2108{
2109	uint hosti = 0;
2110
2111	switch (CHIPID(sih->chip)) {
2112	case BCM4360_CHIP_ID:
2113	case BCM43460_CHIP_ID:
2114	case BCM43526_CHIP_ID:
2115		/* chippkg bit-0 == 0 is PCIE only pkgs
2116		 * chippkg bit-0 == 1 has both PCIE and USB cores enabled
2117		 */
2118		if ((sih->chippkg & 0x1) && (sih->chipst & CST4360_MODE_USB))
2119			hosti = CHIP_HOSTIF_USBMODE;
2120		else
2121			hosti = CHIP_HOSTIF_PCIEMODE;
2122
2123		break;
2124
2125	case BCM4335_CHIP_ID:
2126		/* TBD: like in 4360, do we need to check pkg? */
2127		if (CST4335_CHIPMODE_USB20D(sih->chipst))
2128			hosti = CHIP_HOSTIF_USBMODE;
2129		else if (CST4335_CHIPMODE_SDIOD(sih->chipst))
2130			hosti = CHIP_HOSTIF_SDIOMODE;
2131		else if (CST4335_CHIPMODE_PCIE(sih->chipst))
2132			hosti = CHIP_HOSTIF_PCIEMODE;
2133		break;
2134
2135
2136	default:
2137		break;
2138	}
2139
2140	return hosti;
2141}
2142
2143bool si_read_pmu_autopll(si_t *sih)
2144{
2145	si_info_t *sii;
2146	sii = SI_INFO(sih);
2147	return (si_pmu_is_autoresetphyclk_disabled(sih, sii->osh));
2148}
2149
2150uint32
2151BCMINITFN(si_clock)(si_t *sih)
2152{
2153	si_info_t *sii;
2154	chipcregs_t *cc;
2155	uint32 n, m;
2156	uint idx;
2157	uint32 pll_type, rate;
2158	uint intr_val = 0;
2159
2160	if (BCM4707_CHIP(CHIPID(sih->chip))) {
2161		if (sih->chippkg == BCM4709_PKG_ID) {
2162			return NS_SI_CLOCK;
2163		} else
2164			return NS_SLOW_SI_CLOCK;
2165	}
2166
2167	sii = SI_INFO(sih);
2168	INTR_OFF(sii, intr_val);
2169	if (PMUCTL_ENAB(sih)) {
2170		rate = si_pmu_si_clock(sih, sii->osh);
2171		goto exit;
2172	}
2173
2174	idx = sii->curidx;
2175	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2176	ASSERT(cc != NULL);
2177
2178	n = R_REG(sii->osh, &cc->clockcontrol_n);
2179	pll_type = sih->cccaps & CC_CAP_PLL_MASK;
2180	if (pll_type == PLL_TYPE6)
2181		m = R_REG(sii->osh, &cc->clockcontrol_m3);
2182	else if (pll_type == PLL_TYPE3)
2183		m = R_REG(sii->osh, &cc->clockcontrol_m2);
2184	else
2185		m = R_REG(sii->osh, &cc->clockcontrol_sb);
2186
2187	/* calculate rate */
2188	rate = si_clock_rate(pll_type, n, m);
2189
2190	if (pll_type == PLL_TYPE3)
2191		rate = rate / 2;
2192
2193	/* switch back to previous core */
2194	si_setcoreidx(sih, idx);
2195exit:
2196	INTR_RESTORE(sii, intr_val);
2197
2198	return rate;
2199}
2200
2201/** returns value in [Hz] units */
2202static uint32
2203BCMINITFN(si_ns_alp_clock)(si_t *sih)
2204{
2205	osl_t *osh;
2206	uint32 *genpll_base;
2207	uint32 val;
2208	uint32 pdiv, ndiv_int, mdiv, clkrate;
2209
2210	osh = si_osh(sih);
2211
2212	/* reg map for genpll base address */
2213	genpll_base = (uint32 *)REG_MAP(0x1800C140, 4096);
2214
2215	/* get divider integer from the cru_genpll_control5 */
2216	val = R_REG(osh, (genpll_base + 0x5));
2217	ndiv_int = (val >> 20) & 0x3ff;
2218	if (ndiv_int == 0)
2219		ndiv_int = 1 << 10;
2220
2221	/* get pdiv from the cru_genpll_control6 */
2222	val = R_REG(osh, (genpll_base + 0x6));
2223	pdiv = (val >> 24) & 0x7;
2224	if (pdiv == 0)
2225		pdiv = 1 << 3;
2226
2227	/* get mdiv from the cru_genpll_control7 */
2228	val = R_REG(osh, (genpll_base + 0x7));
2229	mdiv = val & 0xff;
2230	if (mdiv == 0)
2231		mdiv = 1 << 8;
2232
2233	/* caculate clock rate based on 25MHz reference clock */
2234	clkrate = (25000000 / (pdiv * mdiv)) * ndiv_int;
2235
2236	/* round to the nearest Hz */
2237	clkrate = ((clkrate + 500000) / 1000000) * 1000000;
2238
2239	/* reg unmap */
2240	REG_UNMAP((void *)genpll_base);
2241
2242	return clkrate;
2243}
2244
2245uint32
2246BCMINITFN(si_alp_clock)(si_t *sih)
2247{
2248	if (PMUCTL_ENAB(sih))
2249		return si_pmu_alp_clock(sih, si_osh(sih));
2250	else if (BCM4707_CHIP(CHIPID(sih->chip)))
2251		return si_ns_alp_clock(sih);
2252
2253	return ALP_CLOCK;
2254}
2255
2256uint32
2257BCMINITFN(si_ilp_clock)(si_t *sih)
2258{
2259	if (PMUCTL_ENAB(sih))
2260		return si_pmu_ilp_clock(sih, si_osh(sih));
2261
2262	return ILP_CLOCK;
2263}
2264
2265/** set chip watchdog reset timer to fire in 'ticks' */
2266void
2267si_watchdog(si_t *sih, uint ticks)
2268{
2269	uint nb, maxt;
2270
2271	if (PMUCTL_ENAB(sih)) {
2272
2273#if (!defined(_CFE_) && !defined(_CFEZ_)) || defined(CFG_WL)
2274		if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) &&
2275		    (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) {
2276			si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2);
2277			si_setcore(sih, USB20D_CORE_ID, 0);
2278			si_core_disable(sih, 1);
2279			si_setcore(sih, CC_CORE_ID, 0);
2280		}
2281#endif /* (!_CFE_ && !_CFEZ_) || CFG_WL */
2282
2283		if (CHIPID(sih->chip) == BCM4706_CHIP_ID)
2284			nb = 32;
2285		else
2286			nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24);
2287		/* The mips compiler uses the sllv instruction,
2288		 * so we specially handle the 32-bit case.
2289		 */
2290		if (nb == 32)
2291			maxt = 0xffffffff;
2292		else
2293			maxt = ((1 << nb) - 1);
2294
2295		if (ticks == 1)
2296			ticks = 2;
2297		else if (ticks > maxt)
2298			ticks = maxt;
2299
2300		si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog), ~0, ticks);
2301	} else {
2302		if (!BCM4707_CHIP(CHIPID(sih->chip))) {
2303			/* make sure we come up in fast clock mode; or if clearing, clear clock */
2304			si_clkctl_cc(sih, ticks ? CLK_FAST : CLK_DYNAMIC);
2305		}
2306		maxt = (1 << 28) - 1;
2307		if (ticks > maxt)
2308			ticks = maxt;
2309
2310		si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks);
2311	}
2312}
2313
2314/** trigger watchdog reset after ms milliseconds */
2315void
2316si_watchdog_ms(si_t *sih, uint32 ms)
2317{
2318	si_watchdog(sih, wd_msticks * ms);
2319}
2320
2321uint32
2322si_watchdog_msticks(void)
2323{
2324	return wd_msticks;
2325}
2326
2327bool
2328si_taclear(si_t *sih, bool details)
2329{
2330#if defined(BCMDBG_ERR) || defined(BCMASSERT_SUPPORT)
2331	if (CHIPTYPE(sih->socitype) == SOCI_SB)
2332		return sb_taclear(sih, details);
2333	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
2334		return FALSE;
2335	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
2336		return FALSE;
2337	else {
2338		ASSERT(0);
2339		return FALSE;
2340	}
2341#else
2342	return FALSE;
2343#endif
2344}
2345
2346uint16
2347BCMATTACHFN(si_d11_devid)(si_t *sih)
2348{
2349	si_info_t *sii = SI_INFO(sih);
2350	uint16 device;
2351
2352	/* Fix device id for dual band BCM4328 */
2353	if (CHIPID(sih->chip) == BCM4328_CHIP_ID &&
2354	    (sih->chippkg == BCM4328USBDUAL_PKG_ID || sih->chippkg == BCM4328SDIODUAL_PKG_ID)) {
2355		device = BCM4328_D11DUAL_ID;
2356	}
2357#ifdef BCMPCIDEV
2358	else if (CHIPID(sih->chip) == BCM4352_CHIP_ID) {
2359		device = BCM4352_D11AC_ID;
2360	} else if (CHIPID(sih->chip) == BCM4360_CHIP_ID) {
2361		device = BCM4360_D11AC_ID;
2362	} else if (CHIPID(sih->chip) == BCM4350_CHIP_ID) {
2363		device = BCM4350_D11AC_ID;
2364	}
2365#endif
2366	else {
2367		/* normal case: nvram variable with devpath->devid->wl0id */
2368		if ((device = (uint16)si_getdevpathintvar(sih, "devid")) != 0)
2369			;
2370		/* Get devid from OTP/SPROM depending on where the SROM is read */
2371		else if ((device = (uint16)getintvar(sii->vars, "devid")) != 0)
2372			;
2373		/* no longer support wl0id, but keep the code here for backward compatibility. */
2374		else if ((device = (uint16)getintvar(sii->vars, "wl0id")) != 0)
2375			;
2376		else if (CHIPID(sih->chip) == BCM4712_CHIP_ID) {
2377			/* Chip specific conversion */
2378			if (sih->chippkg == BCM4712SMALL_PKG_ID)
2379				device = BCM4306_D11G_ID;
2380			else
2381				device = BCM4306_D11DUAL_ID;
2382		} else {
2383			/* ignore it */
2384			device = 0xffff;
2385		}
2386	}
2387	return device;
2388}
2389
2390int
2391BCMATTACHFN(si_corepciid)(si_t *sih, uint func, uint16 *pcivendor, uint16 *pcidevice,
2392                          uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif,
2393                          uint8 *pciheader)
2394{
2395	uint16 vendor = 0xffff, device = 0xffff;
2396	uint8 class, subclass, progif = 0;
2397	uint8 header = PCI_HEADER_NORMAL;
2398	uint32 core = si_coreid(sih);
2399
2400	/* Verify whether the function exists for the core */
2401	if (func >= (uint)((core == USB20H_CORE_ID) || (core == NS_USB20_CORE_ID) ? 2 : 1))
2402		return BCME_ERROR;
2403
2404	/* Known vendor translations */
2405	switch (si_corevendor(sih)) {
2406	case SB_VEND_BCM:
2407	case MFGID_BRCM:
2408		vendor = VENDOR_BROADCOM;
2409		break;
2410	default:
2411		return BCME_ERROR;
2412	}
2413
2414	/* Determine class based on known core codes */
2415	switch (core) {
2416	case ENET_CORE_ID:
2417		class = PCI_CLASS_NET;
2418		subclass = PCI_NET_ETHER;
2419		device = BCM47XX_ENET_ID;
2420		break;
2421	case GIGETH_CORE_ID:
2422		class = PCI_CLASS_NET;
2423		subclass = PCI_NET_ETHER;
2424		device = BCM47XX_GIGETH_ID;
2425		break;
2426	case GMAC_CORE_ID:
2427		class = PCI_CLASS_NET;
2428		subclass = PCI_NET_ETHER;
2429		device = BCM47XX_GMAC_ID;
2430		break;
2431	case SDRAM_CORE_ID:
2432	case MEMC_CORE_ID:
2433	case DMEMC_CORE_ID:
2434	case SOCRAM_CORE_ID:
2435		class = PCI_CLASS_MEMORY;
2436		subclass = PCI_MEMORY_RAM;
2437		device = (uint16)core;
2438		break;
2439	case PCI_CORE_ID:
2440	case PCIE_CORE_ID:
2441	case PCIE2_CORE_ID:
2442		class = PCI_CLASS_BRIDGE;
2443		subclass = PCI_BRIDGE_PCI;
2444		device = (uint16)core;
2445		header = PCI_HEADER_BRIDGE;
2446		break;
2447	case MIPS33_CORE_ID:
2448	case MIPS74K_CORE_ID:
2449		class = PCI_CLASS_CPU;
2450		subclass = PCI_CPU_MIPS;
2451		device = (uint16)core;
2452		break;
2453	case CODEC_CORE_ID:
2454		class = PCI_CLASS_COMM;
2455		subclass = PCI_COMM_MODEM;
2456		device = BCM47XX_V90_ID;
2457		break;
2458	case I2S_CORE_ID:
2459		class = PCI_CLASS_MMEDIA;
2460		subclass = PCI_MMEDIA_AUDIO;
2461		device = BCM47XX_AUDIO_ID;
2462		break;
2463	case USB_CORE_ID:
2464	case USB11H_CORE_ID:
2465		class = PCI_CLASS_SERIAL;
2466		subclass = PCI_SERIAL_USB;
2467		progif = 0x10; /* OHCI */
2468		device = BCM47XX_USBH_ID;
2469		break;
2470	case USB20H_CORE_ID:
2471	case NS_USB20_CORE_ID:
2472		class = PCI_CLASS_SERIAL;
2473		subclass = PCI_SERIAL_USB;
2474		progif = func == 0 ? 0x10 : 0x20; /* OHCI/EHCI value defined in spec */
2475		device = BCM47XX_USB20H_ID;
2476		header = PCI_HEADER_MULTI; /* multifunction */
2477		break;
2478	case IPSEC_CORE_ID:
2479		class = PCI_CLASS_CRYPT;
2480		subclass = PCI_CRYPT_NETWORK;
2481		device = BCM47XX_IPSEC_ID;
2482		break;
2483	case NS_USB30_CORE_ID:
2484		class = PCI_CLASS_SERIAL;
2485		subclass = PCI_SERIAL_USB;
2486		progif = 0x30; /* XHCI */
2487		device = BCM47XX_USB30H_ID;
2488		break;
2489	case ROBO_CORE_ID:
2490		/* Don't use class NETWORK, so wl/et won't attempt to recognize it */
2491		class = PCI_CLASS_COMM;
2492		subclass = PCI_COMM_OTHER;
2493		device = BCM47XX_ROBO_ID;
2494		break;
2495	case CC_CORE_ID:
2496		class = PCI_CLASS_MEMORY;
2497		subclass = PCI_MEMORY_FLASH;
2498		device = (uint16)core;
2499		break;
2500	case SATAXOR_CORE_ID:
2501		class = PCI_CLASS_XOR;
2502		subclass = PCI_XOR_QDMA;
2503		device = BCM47XX_SATAXOR_ID;
2504		break;
2505	case ATA100_CORE_ID:
2506		class = PCI_CLASS_DASDI;
2507		subclass = PCI_DASDI_IDE;
2508		device = BCM47XX_ATA100_ID;
2509		break;
2510	case USB11D_CORE_ID:
2511		class = PCI_CLASS_SERIAL;
2512		subclass = PCI_SERIAL_USB;
2513		device = BCM47XX_USBD_ID;
2514		break;
2515	case USB20D_CORE_ID:
2516		class = PCI_CLASS_SERIAL;
2517		subclass = PCI_SERIAL_USB;
2518		device = BCM47XX_USB20D_ID;
2519		break;
2520	case D11_CORE_ID:
2521		class = PCI_CLASS_NET;
2522		subclass = PCI_NET_OTHER;
2523		device = si_d11_devid(sih);
2524		break;
2525
2526	default:
2527		class = subclass = progif = 0xff;
2528		device = (uint16)core;
2529		break;
2530	}
2531
2532	*pcivendor = vendor;
2533	*pcidevice = device;
2534	*pciclass = class;
2535	*pcisubclass = subclass;
2536	*pciprogif = progif;
2537	*pciheader = header;
2538
2539	return 0;
2540}
2541
2542#if defined(BCMDBG)
2543/** print interesting sbconfig registers */
2544void
2545si_dumpregs(si_t *sih, struct bcmstrbuf *b)
2546{
2547	si_info_t *sii;
2548	uint origidx, intr_val = 0;
2549
2550	sii = SI_INFO(sih);
2551	origidx = sii->curidx;
2552
2553	INTR_OFF(sii, intr_val);
2554	if (CHIPTYPE(sih->socitype) == SOCI_SB)
2555		sb_dumpregs(sih, b);
2556	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
2557		ai_dumpregs(sih, b);
2558	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
2559		ub_dumpregs(sih, b);
2560	else
2561		ASSERT(0);
2562
2563	si_setcoreidx(sih, origidx);
2564	INTR_RESTORE(sii, intr_val);
2565}
2566#endif
2567
2568#ifdef BCMDBG
2569void
2570si_view(si_t *sih, bool verbose)
2571{
2572	if (CHIPTYPE(sih->socitype) == SOCI_SB)
2573		sb_view(sih, verbose);
2574	else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
2575		ai_view(sih, verbose);
2576	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
2577		ub_view(sih, verbose);
2578	else
2579		ASSERT(0);
2580}
2581
2582void
2583si_viewall(si_t *sih, bool verbose)
2584{
2585	si_info_t *sii;
2586	uint curidx, i;
2587	uint intr_val = 0;
2588
2589	sii = SI_INFO(sih);
2590	curidx = sii->curidx;
2591
2592	INTR_OFF(sii, intr_val);
2593	if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))
2594		ai_viewall(sih, verbose);
2595	else {
2596		SI_ERROR(("si_viewall: num_cores %d\n", sii->numcores));
2597		for (i = 0; i < sii->numcores; i++) {
2598			si_setcoreidx(sih, i);
2599			si_view(sih, verbose);
2600		}
2601	}
2602	si_setcoreidx(sih, curidx);
2603	INTR_RESTORE(sii, intr_val);
2604}
2605#endif	/* BCMDBG */
2606
2607/** return the slow clock source - LPO, XTAL, or PCI */
2608static uint
2609si_slowclk_src(si_info_t *sii)
2610{
2611	chipcregs_t *cc;
2612
2613	ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
2614
2615	if (sii->pub.ccrev < 6) {
2616		if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) &&
2617		    (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) &
2618		     PCI_CFG_GPIO_SCS))
2619			return (SCC_SS_PCI);
2620		else
2621			return (SCC_SS_XTAL);
2622	} else if (sii->pub.ccrev < 10) {
2623		cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx);
2624		return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
2625	} else	/* Insta-clock */
2626		return (SCC_SS_XTAL);
2627}
2628
2629/** return the ILP (slowclock) min or max frequency */
2630static uint
2631si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
2632{
2633	uint32 slowclk;
2634	uint div;
2635
2636	ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
2637
2638	/* shouldn't be here unless we've established the chip has dynamic clk control */
2639	ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
2640
2641	slowclk = si_slowclk_src(sii);
2642	if (sii->pub.ccrev < 6) {
2643		if (slowclk == SCC_SS_PCI)
2644			return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64));
2645		else
2646			return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32));
2647	} else if (sii->pub.ccrev < 10) {
2648		div = 4 *
2649		        (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
2650		if (slowclk == SCC_SS_LPO)
2651			return (max_freq ? LPOMAXFREQ : LPOMINFREQ);
2652		else if (slowclk == SCC_SS_XTAL)
2653			return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div));
2654		else if (slowclk == SCC_SS_PCI)
2655			return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div));
2656		else
2657			ASSERT(0);
2658	} else {
2659		/* Chipc rev 10 is InstaClock */
2660		div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
2661		div = 4 * (div + 1);
2662		return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div));
2663	}
2664	return (0);
2665}
2666
2667static void
2668BCMINITFN(si_clkctl_setdelay)(si_info_t *sii, void *chipcregs)
2669{
2670	chipcregs_t *cc = (chipcregs_t *)chipcregs;
2671	uint slowmaxfreq, pll_delay, slowclk;
2672	uint pll_on_delay, fref_sel_delay;
2673
2674	pll_delay = PLL_DELAY;
2675
2676	/* If the slow clock is not sourced by the xtal then add the xtal_on_delay
2677	 * since the xtal will also be powered down by dynamic clk control logic.
2678	 */
2679
2680	slowclk = si_slowclk_src(sii);
2681	if (slowclk != SCC_SS_XTAL)
2682		pll_delay += XTAL_ON_DELAY;
2683
2684	/* Starting with 4318 it is ILP that is used for the delays */
2685	slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc);
2686
2687	pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
2688	fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
2689
2690	W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
2691	W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
2692}
2693
2694/** initialize power control delay registers */
2695void
2696BCMINITFN(si_clkctl_init)(si_t *sih)
2697{
2698	si_info_t *sii;
2699	uint origidx = 0;
2700	chipcregs_t *cc;
2701	bool fast;
2702
2703	if (!CCCTL_ENAB(sih))
2704		return;
2705
2706	sii = SI_INFO(sih);
2707	fast = SI_FAST(sii);
2708	if (!fast) {
2709		origidx = sii->curidx;
2710		if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
2711			return;
2712	} else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
2713		return;
2714	ASSERT(cc != NULL);
2715
2716	/* set all Instaclk chip ILP to 1 MHz */
2717	if (sih->ccrev >= 10)
2718		SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
2719		        (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
2720
2721	si_clkctl_setdelay(sii, (void *)(uintptr)cc);
2722
2723	OSL_DELAY(20000);
2724
2725	if (!fast)
2726		si_setcoreidx(sih, origidx);
2727}
2728
2729/** return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */
2730uint16
2731BCMINITFN(si_clkctl_fast_pwrup_delay)(si_t *sih)
2732{
2733	si_info_t *sii;
2734	uint origidx = 0;
2735	chipcregs_t *cc;
2736	uint slowminfreq;
2737	uint16 fpdelay;
2738	uint intr_val = 0;
2739	bool fast;
2740
2741	sii = SI_INFO(sih);
2742	if (PMUCTL_ENAB(sih)) {
2743		INTR_OFF(sii, intr_val);
2744		fpdelay = si_pmu_fast_pwrup_delay(sih, sii->osh);
2745		INTR_RESTORE(sii, intr_val);
2746		return fpdelay;
2747	}
2748
2749	if (!CCCTL_ENAB(sih))
2750		return 0;
2751
2752	fast = SI_FAST(sii);
2753	fpdelay = 0;
2754	if (!fast) {
2755		origidx = sii->curidx;
2756		INTR_OFF(sii, intr_val);
2757		if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
2758			goto done;
2759	}
2760	else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
2761		goto done;
2762	ASSERT(cc != NULL);
2763
2764	slowminfreq = si_slowclk_freq(sii, FALSE, cc);
2765	fpdelay = (((R_REG(sii->osh, &cc->pll_on_delay) + 2) * 1000000) +
2766	           (slowminfreq - 1)) / slowminfreq;
2767
2768done:
2769	if (!fast) {
2770		si_setcoreidx(sih, origidx);
2771		INTR_RESTORE(sii, intr_val);
2772	}
2773	return fpdelay;
2774}
2775
2776/** turn primary xtal and/or pll off/on */
2777int
2778si_clkctl_xtal(si_t *sih, uint what, bool on)
2779{
2780	si_info_t *sii;
2781	uint32 in, out, outen;
2782
2783	sii = SI_INFO(sih);
2784
2785	switch (BUSTYPE(sih->bustype)) {
2786
2787
2788	case PCMCIA_BUS:
2789		return (0);
2790
2791
2792	case PCI_BUS:
2793		/* pcie core doesn't have any mapping to control the xtal pu */
2794		if (PCIE(sii))
2795			return -1;
2796
2797		in = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_IN, sizeof(uint32));
2798		out = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32));
2799		outen = OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUTEN, sizeof(uint32));
2800
2801		/*
2802		 * Avoid glitching the clock if GPRS is already using it.
2803		 * We can't actually read the state of the PLLPD so we infer it
2804		 * by the value of XTAL_PU which *is* readable via gpioin.
2805		 */
2806		if (on && (in & PCI_CFG_GPIO_XTAL))
2807			return (0);
2808
2809		if (what & XTAL)
2810			outen |= PCI_CFG_GPIO_XTAL;
2811		if (what & PLL)
2812			outen |= PCI_CFG_GPIO_PLL;
2813
2814		if (on) {
2815			/* turn primary xtal on */
2816			if (what & XTAL) {
2817				out |= PCI_CFG_GPIO_XTAL;
2818				if (what & PLL)
2819					out |= PCI_CFG_GPIO_PLL;
2820				OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
2821				                     sizeof(uint32), out);
2822				OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN,
2823				                     sizeof(uint32), outen);
2824				OSL_DELAY(XTAL_ON_DELAY);
2825			}
2826
2827			/* turn pll on */
2828			if (what & PLL) {
2829				out &= ~PCI_CFG_GPIO_PLL;
2830				OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT,
2831				                     sizeof(uint32), out);
2832				OSL_DELAY(2000);
2833			}
2834		} else {
2835			if (what & XTAL)
2836				out &= ~PCI_CFG_GPIO_XTAL;
2837			if (what & PLL)
2838				out |= PCI_CFG_GPIO_PLL;
2839			OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32), out);
2840			OSL_PCI_WRITE_CONFIG(sii->osh, PCI_GPIO_OUTEN, sizeof(uint32),
2841			                     outen);
2842		}
2843		return 0;
2844
2845	default:
2846		return (-1);
2847	}
2848
2849	return (0);
2850}
2851
2852/**
2853 *  clock control policy function throught chipcommon
2854 *
2855 *    set dynamic clk control mode (forceslow, forcefast, dynamic)
2856 *    returns true if we are forcing fast clock
2857 *    this is a wrapper over the next internal function
2858 *      to allow flexible policy settings for outside caller
2859 */
2860bool
2861si_clkctl_cc(si_t *sih, uint mode)
2862{
2863	si_info_t *sii;
2864
2865	sii = SI_INFO(sih);
2866
2867	/* chipcommon cores prior to rev6 don't support dynamic clock control */
2868	if (sih->ccrev < 6)
2869		return FALSE;
2870
2871	if (PCI_FORCEHT(sii))
2872		return (mode == CLK_FAST);
2873
2874	return _si_clkctl_cc(sii, mode);
2875}
2876
2877/* clk control mechanism through chipcommon, no policy checking */
2878static bool
2879_si_clkctl_cc(si_info_t *sii, uint mode)
2880{
2881	uint origidx = 0;
2882	chipcregs_t *cc;
2883	uint32 scc;
2884	uint intr_val = 0;
2885	bool fast = SI_FAST(sii);
2886
2887	/* chipcommon cores prior to rev6 don't support dynamic clock control */
2888	if (sii->pub.ccrev < 6)
2889		return (FALSE);
2890
2891	/* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */
2892	ASSERT(sii->pub.ccrev != 10);
2893
2894	if (!fast) {
2895		INTR_OFF(sii, intr_val);
2896		origidx = sii->curidx;
2897
2898		if ((BUSTYPE(sii->pub.bustype) == SI_BUS) &&
2899		    si_setcore(&sii->pub, MIPS33_CORE_ID, 0) &&
2900		    (si_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10))
2901			goto done;
2902
2903		cc = (chipcregs_t *) si_setcore(&sii->pub, CC_CORE_ID, 0);
2904	} else if ((cc = (chipcregs_t *) CCREGS_FAST(sii)) == NULL)
2905		goto done;
2906	ASSERT(cc != NULL);
2907
2908	if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20))
2909		goto done;
2910
2911	switch (mode) {
2912	case CLK_FAST:	/* FORCEHT, fast (pll) clock */
2913		if (sii->pub.ccrev < 10) {
2914			/* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
2915			si_clkctl_xtal(&sii->pub, XTAL, ON);
2916			SET_REG(sii->osh, &cc->slow_clk_ctl, (SCC_XC | SCC_FS | SCC_IP), SCC_IP);
2917		} else if (sii->pub.ccrev < 20) {
2918			OR_REG(sii->osh, &cc->system_clk_ctl, SYCC_HR);
2919		} else {
2920			OR_REG(sii->osh, &cc->clk_ctl_st, CCS_FORCEHT);
2921		}
2922
2923		/* wait for the PLL */
2924		if (PMUCTL_ENAB(&sii->pub)) {
2925			uint32 htavail = CCS_HTAVAIL;
2926			if (CHIPID(sii->pub.chip) == BCM4328_CHIP_ID)
2927				htavail = CCS0_HTAVAIL;
2928			SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail) == 0),
2929			         PMU_MAX_TRANSITION_DLY);
2930			ASSERT(R_REG(sii->osh, &cc->clk_ctl_st) & htavail);
2931		} else {
2932			OSL_DELAY(PLL_DELAY);
2933		}
2934		break;
2935
2936	case CLK_DYNAMIC:	/* enable dynamic clock control */
2937		if (sii->pub.ccrev < 10) {
2938			scc = R_REG(sii->osh, &cc->slow_clk_ctl);
2939			scc &= ~(SCC_FS | SCC_IP | SCC_XC);
2940			if ((scc & SCC_SS_MASK) != SCC_SS_XTAL)
2941				scc |= SCC_XC;
2942			W_REG(sii->osh, &cc->slow_clk_ctl, scc);
2943
2944			/* for dynamic control, we have to release our xtal_pu "force on" */
2945			if (scc & SCC_XC)
2946				si_clkctl_xtal(&sii->pub, XTAL, OFF);
2947		} else if (sii->pub.ccrev < 20) {
2948			/* Instaclock */
2949			AND_REG(sii->osh, &cc->system_clk_ctl, ~SYCC_HR);
2950		} else {
2951			AND_REG(sii->osh, &cc->clk_ctl_st, ~CCS_FORCEHT);
2952		}
2953
2954		/* wait for the PLL */
2955		if (PMUCTL_ENAB(&sii->pub)) {
2956			uint32 htavail = CCS_HTAVAIL;
2957			if (CHIPID(sii->pub.chip) == BCM4328_CHIP_ID)
2958				htavail = CCS0_HTAVAIL;
2959			SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail) != 0),
2960			         PMU_MAX_TRANSITION_DLY);
2961			ASSERT(!(R_REG(sii->osh, &cc->clk_ctl_st) & htavail));
2962		} else {
2963			OSL_DELAY(PLL_DELAY);
2964		}
2965
2966		break;
2967
2968	default:
2969		ASSERT(0);
2970	}
2971
2972done:
2973	if (!fast) {
2974		si_setcoreidx(&sii->pub, origidx);
2975		INTR_RESTORE(sii, intr_val);
2976	}
2977	return (mode == CLK_FAST);
2978}
2979
2980/** Build device path. Support SI, PCI, and JTAG for now. */
2981int
2982BCMNMIATTACHFN(si_devpath)(si_t *sih, char *path, int size)
2983{
2984	int slen;
2985
2986	ASSERT(path != NULL);
2987	ASSERT(size >= SI_DEVPATH_BUFSZ);
2988
2989	if (!path || size <= 0)
2990		return -1;
2991
2992	switch (BUSTYPE(sih->bustype)) {
2993	case SI_BUS:
2994	case JTAG_BUS:
2995		slen = snprintf(path, (size_t)size, "sb/%u/", si_coreidx(sih));
2996		break;
2997	case PCI_BUS:
2998		ASSERT((SI_INFO(sih))->osh != NULL);
2999		slen = snprintf(path, (size_t)size, "pci/%u/%u/",
3000		                OSL_PCI_BUS((SI_INFO(sih))->osh),
3001		                OSL_PCI_SLOT((SI_INFO(sih))->osh));
3002		break;
3003	case PCMCIA_BUS:
3004		SI_ERROR(("si_devpath: OSL_PCMCIA_BUS() not implemented, bus 1 assumed\n"));
3005		SI_ERROR(("si_devpath: OSL_PCMCIA_SLOT() not implemented, slot 1 assumed\n"));
3006		slen = snprintf(path, (size_t)size, "pc/1/1/");
3007		break;
3008	default:
3009		slen = -1;
3010		ASSERT(0);
3011		break;
3012	}
3013
3014	if (slen < 0 || slen >= size) {
3015		path[0] = '\0';
3016		return -1;
3017	}
3018
3019	return 0;
3020}
3021
3022char *
3023BCMATTACHFN(si_coded_devpathvar)(si_t *sih, char *varname, int var_len, const char *name)
3024{
3025	char pathname[SI_DEVPATH_BUFSZ + 32];
3026	char devpath[SI_DEVPATH_BUFSZ + 32];
3027	char devpath_pcie[SI_DEVPATH_BUFSZ + 32];
3028	char *p;
3029	int idx;
3030	int len1;
3031	int len2;
3032	int len3 = 0;
3033
3034	if (BUSTYPE(sih->bustype) == PCI_BUS) {
3035		snprintf(devpath_pcie, SI_DEVPATH_BUFSZ, "pcie/%u/%u",
3036			OSL_PCIE_DOMAIN((SI_INFO(sih))->osh),
3037			OSL_PCIE_BUS((SI_INFO(sih))->osh));
3038		len3 = strlen(devpath_pcie);
3039	}
3040	/* try to get compact devpath if it exist */
3041	if (si_devpath(sih, devpath, SI_DEVPATH_BUFSZ) == 0) {
3042		/* eliminate ending '/' (if present) */
3043		len1 = strlen(devpath);
3044		if (devpath[len1 - 1] == '/')
3045			len1--;
3046
3047		for (idx = 0; idx < SI_MAXCORES; idx++) {
3048			snprintf(pathname, SI_DEVPATH_BUFSZ, "devpath%d", idx);
3049			if ((p = getvar(NULL, pathname)) == NULL)
3050				continue;
3051
3052			/* eliminate ending '/' (if present) */
3053			len2 = strlen(p);
3054			if (p[len2 - 1] == '/')
3055				len2--;
3056
3057			/* check that both lengths match and if so compare */
3058			/* the strings (minus trailing '/'s if present */
3059			if ((len1 == len2) && (memcmp(p, devpath, len1) == 0)) {
3060				snprintf(varname, var_len, "%d:%s", idx, name);
3061				return varname;
3062			}
3063
3064			/* try the new PCIe devpath format if it exists */
3065			if (len3 && (len3 == len2) && (memcmp(p, devpath_pcie, len3) == 0)) {
3066				snprintf(varname, var_len, "%d:%s", idx, name);
3067				return varname;
3068			}
3069		}
3070	}
3071
3072	return NULL;
3073}
3074
3075/** Get a variable, but only if it has a devpath prefix */
3076char *
3077BCMATTACHFN(si_getdevpathvar)(si_t *sih, const char *name)
3078{
3079	char varname[SI_DEVPATH_BUFSZ + 32];
3080	char *val;
3081
3082	si_devpathvar(sih, varname, sizeof(varname), name);
3083
3084	if ((val = getvar(NULL, varname)) != NULL)
3085		return val;
3086
3087	/* try to get compact devpath if it exist */
3088	if (si_coded_devpathvar(sih, varname, sizeof(varname), name) == NULL)
3089		return NULL;
3090
3091	return (getvar(NULL, varname));
3092}
3093
3094/** Get a variable, but only if it has a devpath prefix */
3095int
3096BCMATTACHFN(si_getdevpathintvar)(si_t *sih, const char *name)
3097{
3098#if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS)
3099	return (getintvar(NULL, name));
3100#else
3101	char varname[SI_DEVPATH_BUFSZ + 32];
3102	int val;
3103
3104	si_devpathvar(sih, varname, sizeof(varname), name);
3105
3106	if ((val = getintvar(NULL, varname)) != 0)
3107		return val;
3108
3109	/* try to get compact devpath if it exist */
3110	if (si_coded_devpathvar(sih, varname, sizeof(varname), name) == NULL)
3111		return 0;
3112
3113	return (getintvar(NULL, varname));
3114#endif /* BCMBUSTYPE && BCMBUSTYPE == SI_BUS */
3115}
3116
3117#ifndef DONGLEBUILD
3118char *
3119si_getnvramflvar(si_t *sih, const char *name)
3120{
3121	return (getvar(NULL, name));
3122}
3123#endif /* DONGLEBUILD */
3124
3125/**
3126 * Concatenate the dev path with a varname into the given 'var' buffer
3127 * and return the 'var' pointer.
3128 * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned.
3129 * On overflow, the first char will be set to '\0'.
3130 */
3131static char *
3132BCMATTACHFN(si_devpathvar)(si_t *sih, char *var, int len, const char *name)
3133{
3134	uint path_len;
3135
3136	if (!var || len <= 0)
3137		return var;
3138
3139	if (si_devpath(sih, var, len) == 0) {
3140		path_len = strlen(var);
3141
3142		if (strlen(name) + 1 > (uint)(len - path_len))
3143			var[0] = '\0';
3144		else
3145			strncpy(var + path_len, name, len - path_len - 1);
3146	}
3147
3148	return var;
3149}
3150
3151/* Function to write a chipcommon register */
3152uint32
3153write_ccreg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
3154{
3155	si_info_t *sii;
3156	uint32 reg_val = 0;
3157
3158	sii = SI_INFO(sih);
3159
3160	/* abort for invalid offset */
3161	if (offset > sizeof(chipcregs_t))
3162		return 0;
3163
3164	reg_val = si_corereg(&sii->pub, SI_CC_IDX, offset, mask, val);
3165
3166	return reg_val;
3167}
3168uint32
3169si_ccreg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
3170{
3171	si_info_t *sii;
3172	uint32 reg_val = 0;
3173
3174	sii = SI_INFO(sih);
3175
3176	/* abort for invalid offset */
3177	if (offset > sizeof(chipcregs_t))
3178		return 0;
3179
3180	reg_val = si_corereg(&sii->pub, SI_CC_IDX, offset, mask, val);
3181
3182	return reg_val;
3183}
3184
3185
3186uint32
3187si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint type)
3188{
3189	si_info_t *sii;
3190
3191	sii = SI_INFO(sih);
3192
3193	if (!PCIE(sii)) {
3194		SI_ERROR(("%s: Not a PCIE device\n", __FUNCTION__));
3195		return 0;
3196	}
3197
3198	return pcicore_pciereg(sii->pch, offset, mask, val, type);
3199}
3200
3201uint32
3202si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint32 mask, uint32 val)
3203{
3204	si_info_t *sii;
3205
3206	sii = SI_INFO(sih);
3207
3208	if (!PCIE(sii)) {
3209		SI_ERROR(("%s: Not a PCIE device\n", __FUNCTION__));
3210		return 0;
3211	}
3212
3213	return pcicore_pcieserdesreg(sii->pch, mdioslave, offset, mask, val);
3214
3215}
3216
3217/** return TRUE if PCIE capability exists in the pci config space */
3218static bool
3219si_ispcie(si_info_t *sii)
3220{
3221	uint8 cap_ptr;
3222
3223	if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
3224		return FALSE;
3225
3226	cap_ptr = pcicore_find_pci_capability(sii->osh, PCI_CAP_PCIECAP_ID, NULL, NULL);
3227	if (!cap_ptr)
3228		return FALSE;
3229
3230	return TRUE;
3231}
3232
3233/* Wake-on-wireless-LAN (WOWL) support functions */
3234/** Enable PME generation and disable clkreq */
3235void
3236si_pci_pmeen(si_t *sih)
3237{
3238	si_info_t *sii;
3239
3240	sii = SI_INFO(sih);
3241
3242	pcicore_pmeen(sii->pch);
3243}
3244
3245/** Return TRUE if PME status is set */
3246bool
3247si_pci_pmestat(si_t *sih)
3248{
3249	si_info_t *sii;
3250
3251	sii = SI_INFO(sih);
3252
3253	return pcicore_pmestat(sii->pch);
3254}
3255
3256/** Disable PME generation, clear the PME status bit if set */
3257void
3258si_pci_pmeclr(si_t *sih)
3259{
3260	si_info_t *sii;
3261
3262	sii = SI_INFO(sih);
3263
3264	pcicore_pmeclr(sii->pch);
3265}
3266
3267void
3268si_pci_pmestatclr(si_t *sih)
3269{
3270	si_info_t *sii;
3271
3272	sii = SI_INFO(sih);
3273
3274	pcicore_pmestatclr(sii->pch);
3275}
3276
3277/** initialize the pcmcia core */
3278void
3279si_pcmcia_init(si_t *sih)
3280{
3281	si_info_t *sii;
3282	uint8 cor = 0;
3283
3284	sii = SI_INFO(sih);
3285
3286	/* enable d11 mac interrupts */
3287	OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1);
3288	cor |= COR_IRQEN | COR_FUNEN;
3289	OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1);
3290
3291}
3292
3293
3294bool
3295BCMATTACHFN(si_pci_war16165)(si_t *sih)
3296{
3297	si_info_t *sii;
3298
3299	sii = SI_INFO(sih);
3300
3301	return (PCI(sii) && (sih->buscorerev <= 10));
3302}
3303
3304/**
3305 * Disable pcie_war_ovr for some platforms (sigh!)
3306 * This is for boards that have BFL2_PCIEWAR_OVR set
3307 * but are in systems that still want the benefits of ASPM
3308 * Note that this should be done AFTER si_doattach
3309 */
3310void
3311si_pcie_war_ovr_update(si_t *sih, uint8 aspm)
3312{
3313	si_info_t *sii;
3314
3315	sii = SI_INFO(sih);
3316
3317	if (!PCIE_GEN1(sii))
3318		return;
3319
3320	pcie_war_ovr_aspm_update(sii->pch, aspm);
3321}
3322
3323void
3324si_pcie_power_save_enable(si_t *sih, bool enable)
3325{
3326	si_info_t *sii;
3327
3328	sii = SI_INFO(sih);
3329
3330	if (!PCIE_GEN1(sii))
3331		return;
3332
3333	pcie_power_save_enable(sii->pch, enable);
3334}
3335
3336void
3337si_pcie_set_maxpayload_size(si_t *sih, uint16 size)
3338{
3339	si_info_t *sii;
3340
3341	sii = SI_INFO(sih);
3342
3343	if (!PCIE(sii))
3344		return;
3345
3346	pcie_set_maxpayload_size(sii->pch, size);
3347}
3348
3349uint16
3350si_pcie_get_maxpayload_size(si_t *sih)
3351{
3352	si_info_t *sii;
3353
3354	sii = SI_INFO(sih);
3355
3356	if (!PCIE(sii))
3357		return (0);
3358
3359	return pcie_get_maxpayload_size(sii->pch);
3360}
3361
3362void
3363si_pcie_set_request_size(si_t *sih, uint16 size)
3364{
3365	si_info_t *sii;
3366
3367	sii = SI_INFO(sih);
3368
3369	if (!PCIE(sii))
3370		return;
3371
3372	pcie_set_request_size(sii->pch, size);
3373}
3374
3375uint16
3376si_pcie_get_request_size(si_t *sih)
3377{
3378	si_info_t *sii;
3379
3380	sii = SI_INFO(sih);
3381
3382	if (!PCIE_GEN1(sii))
3383		return (0);
3384
3385	return pcie_get_request_size(sii->pch);
3386}
3387
3388
3389uint16
3390si_pcie_get_ssid(si_t *sih)
3391{
3392	si_info_t *sii;
3393
3394	sii = SI_INFO(sih);
3395
3396	if (!PCIE_GEN1(sii))
3397		return (0);
3398
3399	return pcie_get_ssid(sii->pch);
3400}
3401
3402uint32
3403si_pcie_get_bar0(si_t *sih)
3404{
3405	si_info_t *sii;
3406
3407	sii = SI_INFO(sih);
3408
3409	if (!PCIE(sii))
3410		return (0);
3411
3412	return pcie_get_bar0(sii->pch);
3413}
3414
3415int
3416si_pcie_configspace_cache(si_t *sih)
3417{
3418	si_info_t *sii;
3419
3420	sii = SI_INFO(sih);
3421
3422	if (!PCIE(sii))
3423		return -1;
3424
3425	return pcie_configspace_cache(sii->pch);
3426}
3427
3428int
3429si_pcie_configspace_restore(si_t *sih)
3430{
3431	si_info_t *sii;
3432
3433	sii = SI_INFO(sih);
3434
3435	if (!PCIE(sii))
3436		return -1;
3437
3438	return pcie_configspace_restore(sii->pch);
3439}
3440
3441int
3442si_pcie_configspace_get(si_t *sih, uint8 *buf, uint size)
3443{
3444	si_info_t *sii;
3445
3446	sii = SI_INFO(sih);
3447
3448	if (!PCIE(sii) || size > PCI_CONFIG_SPACE_SIZE)
3449		return -1;
3450
3451	return pcie_configspace_get(sii->pch, buf, size);
3452}
3453
3454/** back door for other module to override chippkg */
3455void
3456si_chippkg_set(si_t *sih, uint val)
3457{
3458	si_info_t *sii;
3459
3460	sii = SI_INFO(sih);
3461
3462	sii->pub.chippkg = val;
3463}
3464
3465void
3466BCMINITFN(si_pci_up)(si_t *sih)
3467{
3468	si_info_t *sii;
3469
3470	sii = SI_INFO(sih);
3471
3472	/* if not pci bus, we're done */
3473	if (BUSTYPE(sih->bustype) != PCI_BUS)
3474		return;
3475
3476	if (PCI_FORCEHT(sii))
3477		_si_clkctl_cc(sii, CLK_FAST);
3478
3479	if (PCIE(sii)) {
3480		pcicore_up(sii->pch, SI_PCIUP);
3481		if (((CHIPID(sih->chip) == BCM4311_CHIP_ID) && (CHIPREV(sih->chiprev) == 2)) ||
3482		    (CHIPID(sih->chip) == BCM4312_CHIP_ID))
3483			sb_set_initiator_to((void *)sii, 0x3,
3484			                    si_findcoreidx((void *)sii, D11_CORE_ID, 0));
3485	}
3486}
3487
3488/** Unconfigure and/or apply various WARs when system is going to sleep mode */
3489void
3490BCMUNINITFN(si_pci_sleep)(si_t *sih)
3491{
3492	si_info_t *sii;
3493
3494	do_4360_pcie2_war = 0;
3495
3496	sii = SI_INFO(sih);
3497
3498	pcicore_sleep(sii->pch);
3499}
3500
3501/** Unconfigure and/or apply various WARs when going down */
3502void
3503BCMINITFN(si_pci_down)(si_t *sih)
3504{
3505	si_info_t *sii;
3506
3507	sii = SI_INFO(sih);
3508
3509	/* if not pci bus, we're done */
3510	if (BUSTYPE(sih->bustype) != PCI_BUS)
3511		return;
3512
3513	/* release FORCEHT since chip is going to "down" state */
3514	if (PCI_FORCEHT(sii))
3515		_si_clkctl_cc(sii, CLK_DYNAMIC);
3516
3517	pcicore_down(sii->pch, SI_PCIDOWN);
3518}
3519
3520/**
3521 * Configure the pci core for pci client (NIC) action
3522 * coremask is the bitvec of cores by index to be enabled.
3523 */
3524void
3525BCMATTACHFN(si_pci_setup)(si_t *sih, uint coremask)
3526{
3527	si_info_t *sii;
3528	sbpciregs_t *pciregs = NULL;
3529	uint32 siflag = 0, w;
3530	uint idx = 0;
3531
3532	sii = SI_INFO(sih);
3533
3534	if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
3535		return;
3536
3537	ASSERT(PCI(sii) || PCIE(sii));
3538	ASSERT(sii->pub.buscoreidx != BADIDX);
3539
3540	if (PCI(sii)) {
3541		/* get current core index */
3542		idx = sii->curidx;
3543
3544		/* we interrupt on this backplane flag number */
3545		siflag = si_flag(sih);
3546
3547		/* switch over to pci core */
3548		pciregs = (sbpciregs_t *)si_setcoreidx(sih, sii->pub.buscoreidx);
3549	}
3550
3551	/*
3552	 * Enable sb->pci interrupts.  Assume
3553	 * PCI rev 2.3 support was added in pci core rev 6 and things changed..
3554	 */
3555	if (PCIE(sii) || (PCI(sii) && ((sii->pub.buscorerev) >= 6))) {
3556		/* pci config write to set this core bit in PCIIntMask */
3557		w = OSL_PCI_READ_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32));
3558		w |= (coremask << PCI_SBIM_SHIFT);
3559#ifdef USER_MODE
3560		/* User mode operate with interrupt disabled */
3561		w &= !(coremask << PCI_SBIM_SHIFT);
3562#endif
3563		OSL_PCI_WRITE_CONFIG(sii->osh, PCI_INT_MASK, sizeof(uint32), w);
3564	} else {
3565		/* set sbintvec bit for our flag number */
3566		si_setint(sih, siflag);
3567	}
3568
3569	if (PCI(sii)) {
3570		OR_REG(sii->osh, &pciregs->sbtopci2, (SBTOPCI_PREF | SBTOPCI_BURST));
3571		if (sii->pub.buscorerev >= 11) {
3572			OR_REG(sii->osh, &pciregs->sbtopci2, SBTOPCI_RC_READMULTI);
3573			w = R_REG(sii->osh, &pciregs->clkrun);
3574			W_REG(sii->osh, &pciregs->clkrun, (w | PCI_CLKRUN_DSBL));
3575			w = R_REG(sii->osh, &pciregs->clkrun);
3576		}
3577
3578		/* switch back to previous core */
3579		si_setcoreidx(sih, idx);
3580	}
3581}
3582
3583uint8
3584si_pcieclkreq(si_t *sih, uint32 mask, uint32 val)
3585{
3586	si_info_t *sii;
3587
3588	sii = SI_INFO(sih);
3589
3590	if (!(PCIE(sii)))
3591		return 0;
3592
3593	return pcie_clkreq(sii->pch, mask, val);
3594}
3595
3596uint32
3597si_pcielcreg(si_t *sih, uint32 mask, uint32 val)
3598{
3599	si_info_t *sii;
3600
3601	sii = SI_INFO(sih);
3602
3603	if (!PCIE(sii))
3604		return 0;
3605
3606	return pcie_lcreg(sii->pch, mask, val);
3607}
3608
3609uint8
3610si_pcieltrenable(si_t *sih, uint32 mask, uint32 val)
3611{
3612	si_info_t *sii;
3613
3614	sii = SI_INFO(sih);
3615
3616	if (!(PCIE(sii)))
3617		return 0;
3618
3619	return pcie_ltrenable(sii->pch, mask, val);
3620}
3621
3622uint8
3623si_pcieobffenable(si_t *sih, uint32 mask, uint32 val)
3624{
3625	si_info_t *sii;
3626
3627	sii = SI_INFO(sih);
3628
3629	if (!(PCIE(sii)))
3630		return 0;
3631
3632	return pcie_obffenable(sii->pch, mask, val);
3633}
3634
3635uint32
3636si_pcieltr_reg(si_t *sih, uint32 reg, uint32 mask, uint32 val)
3637{
3638	si_info_t *sii;
3639
3640	sii = SI_INFO(sih);
3641
3642	if (!(PCIE(sii)))
3643		return 0;
3644
3645	return pcie_ltr_reg(sii->pch, reg, mask, val);
3646}
3647
3648uint32
3649si_pcieltrspacing_reg(si_t *sih, uint32 mask, uint32 val)
3650{
3651	si_info_t *sii;
3652
3653	sii = SI_INFO(sih);
3654
3655	if (!(PCIE(sii)))
3656		return 0;
3657
3658	return pcieltrspacing_reg(sii->pch, mask, val);
3659}
3660
3661uint32
3662si_pcieltrhysteresiscnt_reg(si_t *sih, uint32 mask, uint32 val)
3663{
3664	si_info_t *sii;
3665
3666	sii = SI_INFO(sih);
3667
3668	if (!(PCIE(sii)))
3669		return 0;
3670
3671	return pcieltrhysteresiscnt_reg(sii->pch, mask, val);
3672}
3673
3674void
3675si_pcie_set_error_injection(si_t *sih, uint32 mode)
3676{
3677	si_info_t *sii;
3678
3679	sii = SI_INFO(sih);
3680
3681	if (!PCIE(sii))
3682		return;
3683
3684	pcie_set_error_injection(sii->pch, mode);
3685}
3686
3687void
3688si_pcie_set_L1substate(si_t *sih, uint32 substate)
3689{
3690	si_info_t *sii;
3691
3692	sii = SI_INFO(sih);
3693
3694	if (!PCIE_GEN2(sii))
3695		return;
3696
3697	pcie_set_L1substate(sii->pch, substate);
3698}
3699
3700uint32
3701si_pcie_get_L1substate(si_t *sih)
3702{
3703	si_info_t *sii;
3704
3705	sii = SI_INFO(sih);
3706
3707	if (!PCIE_GEN2(sii))
3708		return 0;
3709
3710	return pcie_get_L1substate(sii->pch);
3711}
3712
3713/** indirect way to read pcie config regs */
3714uint
3715si_pcie_readreg(void *sih, uint addrtype, uint offset)
3716{
3717	return pcie_readreg(sih, (sbpcieregs_t *)PCIEREGS(((si_info_t *)sih)),
3718	                    addrtype, offset);
3719}
3720
3721/* indirect way to write pcie config regs */
3722uint
3723si_pcie_writereg(void *sih, uint addrtype, uint offset, uint val)
3724{
3725	return pcie_writereg(sih, (sbpcieregs_t *)PCIEREGS(((si_info_t *)sih)),
3726	                    addrtype, offset, val);
3727}
3728
3729
3730/**
3731 * Fixup SROMless PCI device's configuration.
3732 * The current core may be changed upon return.
3733 */
3734int
3735si_pci_fixcfg(si_t *sih)
3736{
3737	uint origidx, pciidx;
3738	sbpciregs_t *pciregs = NULL;
3739	sbpcieregs_t *pcieregs = NULL;
3740	uint16 val16, *reg16 = NULL;
3741	uint32 w;
3742
3743	si_info_t *sii = SI_INFO(sih);
3744
3745	ASSERT(BUSTYPE(sii->pub.bustype) == PCI_BUS);
3746
3747	if ((CHIPID(sii->pub.chip) == BCM4321_CHIP_ID) && (CHIPREV(sii->pub.chiprev) < 2)) {
3748		w = (CHIPREV(sii->pub.chiprev) == 0) ?
3749		        CHIPCTRL_4321A0_DEFAULT : CHIPCTRL_4321A1_DEFAULT;
3750		si_corereg(&sii->pub, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol), ~0, w);
3751	}
3752
3753	/* Fixup PI in SROM shadow area to enable the correct PCI core access */
3754	/* save the current index */
3755	origidx = si_coreidx(&sii->pub);
3756
3757	/* check 'pi' is correct and fix it if not */
3758	if (sii->pub.buscoretype == PCIE2_CORE_ID) {
3759		pcieregs = (sbpcieregs_t *)si_setcore(&sii->pub, PCIE2_CORE_ID, 0);
3760		ASSERT(pcieregs != NULL);
3761		reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
3762	} else if (sii->pub.buscoretype == PCIE_CORE_ID) {
3763		pcieregs = (sbpcieregs_t *)si_setcore(&sii->pub, PCIE_CORE_ID, 0);
3764		ASSERT(pcieregs != NULL);
3765		reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
3766	} else if (sii->pub.buscoretype == PCI_CORE_ID) {
3767		pciregs = (sbpciregs_t *)si_setcore(&sii->pub, PCI_CORE_ID, 0);
3768		ASSERT(pciregs != NULL);
3769		reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
3770	}
3771	pciidx = si_coreidx(&sii->pub);
3772
3773	if (!reg16) return -1;
3774
3775	val16 = R_REG(sii->osh, reg16);
3776	if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (uint16)pciidx) {
3777		val16 = (uint16)(pciidx << SRSH_PI_SHIFT) | (val16 & ~SRSH_PI_MASK);
3778		W_REG(sii->osh, reg16, val16);
3779	}
3780
3781	/* restore the original index */
3782	si_setcoreidx(&sii->pub, origidx);
3783
3784	pcicore_hwup(sii->pch);
3785	return 0;
3786}
3787
3788#if defined(BCMDBG) || defined(WLTEST)
3789int
3790si_dump_pcieinfo(si_t *sih, struct bcmstrbuf *b)
3791{
3792	si_info_t *sii;
3793
3794	sii = SI_INFO(sih);
3795
3796	if (!PCIE_GEN1(sii) && !PCIE_GEN2(sii))
3797		return BCME_ERROR;
3798
3799	return pcicore_dump_pcieinfo(sii->pch, b);
3800}
3801#endif
3802
3803#if defined(BCMDBG)
3804#endif
3805
3806/** change logical "focus" to the gpio core for optimized access */
3807void *
3808si_gpiosetcore(si_t *sih)
3809{
3810	return (si_setcoreidx(sih, SI_CC_IDX));
3811}
3812
3813/**
3814 * mask & set gpiocontrol bits.
3815 * If a gpiocontrol bit is set to 0, chipcommon controls the corresponding GPIO pin.
3816 * If a gpiocontrol bit is set to 1, the GPIO pin is no longer a GPIO and becomes dedicated
3817 *   to some chip-specific purpose.
3818 */
3819uint32
3820si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority)
3821{
3822	uint regoff;
3823
3824	regoff = 0;
3825
3826	/* gpios could be shared on router platforms
3827	 * ignore reservation if it's high priority (e.g., test apps)
3828	 */
3829	if ((priority != GPIO_HI_PRIORITY) &&
3830	    (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
3831		mask = priority ? (si_gpioreservation & mask) :
3832			((si_gpioreservation | mask) & ~(si_gpioreservation));
3833		val &= mask;
3834	}
3835
3836	regoff = OFFSETOF(chipcregs_t, gpiocontrol);
3837	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
3838}
3839
3840/** mask&set gpio output enable bits */
3841uint32
3842si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority)
3843{
3844	uint regoff;
3845
3846	regoff = 0;
3847
3848	/* gpios could be shared on router platforms
3849	 * ignore reservation if it's high priority (e.g., test apps)
3850	 */
3851	if ((priority != GPIO_HI_PRIORITY) &&
3852	    (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
3853		mask = priority ? (si_gpioreservation & mask) :
3854			((si_gpioreservation | mask) & ~(si_gpioreservation));
3855		val &= mask;
3856	}
3857
3858	regoff = OFFSETOF(chipcregs_t, gpioouten);
3859	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
3860}
3861
3862/** mask&set gpio output bits */
3863uint32
3864si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority)
3865{
3866	uint regoff;
3867
3868	regoff = 0;
3869
3870	/* gpios could be shared on router platforms
3871	 * ignore reservation if it's high priority (e.g., test apps)
3872	 */
3873	if ((priority != GPIO_HI_PRIORITY) &&
3874	    (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
3875		mask = priority ? (si_gpioreservation & mask) :
3876			((si_gpioreservation | mask) & ~(si_gpioreservation));
3877		val &= mask;
3878	}
3879
3880	regoff = OFFSETOF(chipcregs_t, gpioout);
3881	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
3882}
3883
3884/** reserve one gpio */
3885uint32
3886si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority)
3887{
3888	/* only cores on SI_BUS share GPIO's and only applcation users need to
3889	 * reserve/release GPIO
3890	 */
3891	if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
3892		ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
3893		return 0xffffffff;
3894	}
3895	/* make sure only one bit is set */
3896	if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
3897		ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
3898		return 0xffffffff;
3899	}
3900
3901	/* already reserved */
3902	if (si_gpioreservation & gpio_bitmask)
3903		return 0xffffffff;
3904	/* set reservation */
3905	si_gpioreservation |= gpio_bitmask;
3906
3907	return si_gpioreservation;
3908}
3909
3910/**
3911 * release one gpio.
3912 *
3913 * releasing the gpio doesn't change the current value on the GPIO last write value
3914 * persists till someone overwrites it.
3915 */
3916uint32
3917si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority)
3918{
3919	/* only cores on SI_BUS share GPIO's and only applcation users need to
3920	 * reserve/release GPIO
3921	 */
3922	if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
3923		ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
3924		return 0xffffffff;
3925	}
3926	/* make sure only one bit is set */
3927	if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
3928		ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
3929		return 0xffffffff;
3930	}
3931
3932	/* already released */
3933	if (!(si_gpioreservation & gpio_bitmask))
3934		return 0xffffffff;
3935
3936	/* clear reservation */
3937	si_gpioreservation &= ~gpio_bitmask;
3938
3939	return si_gpioreservation;
3940}
3941
3942/* return the current gpioin register value */
3943uint32
3944si_gpioin(si_t *sih)
3945{
3946	uint regoff;
3947
3948	regoff = OFFSETOF(chipcregs_t, gpioin);
3949	return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0));
3950}
3951
3952/* mask&set gpio interrupt polarity bits */
3953uint32
3954si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority)
3955{
3956	uint regoff;
3957
3958	/* gpios could be shared on router platforms */
3959	if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
3960		mask = priority ? (si_gpioreservation & mask) :
3961			((si_gpioreservation | mask) & ~(si_gpioreservation));
3962		val &= mask;
3963	}
3964
3965	regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
3966	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
3967}
3968
3969/* mask&set gpio interrupt mask bits */
3970uint32
3971si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority)
3972{
3973	uint regoff;
3974
3975	/* gpios could be shared on router platforms */
3976	if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
3977		mask = priority ? (si_gpioreservation & mask) :
3978			((si_gpioreservation | mask) & ~(si_gpioreservation));
3979		val &= mask;
3980	}
3981
3982	regoff = OFFSETOF(chipcregs_t, gpiointmask);
3983	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
3984}
3985
3986/* assign the gpio to an led */
3987uint32
3988si_gpioled(si_t *sih, uint32 mask, uint32 val)
3989{
3990	if (sih->ccrev < 16)
3991		return 0xffffffff;
3992
3993	/* gpio led powersave reg */
3994	return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val));
3995}
3996
3997/* mask&set gpio timer val */
3998uint32
3999si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
4000{
4001	if (sih->ccrev < 16)
4002		return 0xffffffff;
4003
4004	return (si_corereg(sih, SI_CC_IDX,
4005		OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval));
4006}
4007
4008uint32
4009si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
4010{
4011	uint offs;
4012
4013	if (sih->ccrev < 20)
4014		return 0xffffffff;
4015
4016	offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup));
4017	return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
4018}
4019
4020uint32
4021si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
4022{
4023	uint offs;
4024
4025	if (sih->ccrev < 11)
4026		return 0xffffffff;
4027
4028	if (regtype == GPIO_REGEVT)
4029		offs = OFFSETOF(chipcregs_t, gpioevent);
4030	else if (regtype == GPIO_REGEVT_INTMSK)
4031		offs = OFFSETOF(chipcregs_t, gpioeventintmask);
4032	else if (regtype == GPIO_REGEVT_INTPOL)
4033		offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
4034	else
4035		return 0xffffffff;
4036
4037	return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
4038}
4039
4040void *
4041BCMATTACHFN(si_gpio_handler_register)(si_t *sih, uint32 event,
4042	bool level, gpio_handler_t cb, void *arg)
4043{
4044	si_info_t *sii;
4045	gpioh_item_t *gi;
4046
4047	ASSERT(event);
4048	ASSERT(cb != NULL);
4049
4050	sii = SI_INFO(sih);
4051	if (sih->ccrev < 11)
4052		return NULL;
4053
4054	if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL)
4055		return NULL;
4056
4057	bzero(gi, sizeof(gpioh_item_t));
4058	gi->event = event;
4059	gi->handler = cb;
4060	gi->arg = arg;
4061	gi->level = level;
4062
4063	gi->next = sii->gpioh_head;
4064	sii->gpioh_head = gi;
4065
4066#ifdef BCMDBG_ERR
4067	{
4068		gpioh_item_t *h = sii->gpioh_head;
4069		int cnt = 0;
4070
4071		for (; h; h = h->next) {
4072			cnt++;
4073			SI_ERROR(("gpiohdler=%p cb=%p event=0x%x\n",
4074				h, h->handler, h->event));
4075		}
4076		SI_ERROR(("gpiohdler total=%d\n", cnt));
4077	}
4078#endif
4079	return (void *)(gi);
4080}
4081
4082void
4083BCMATTACHFN(si_gpio_handler_unregister)(si_t *sih, void *gpioh)
4084{
4085	si_info_t *sii;
4086	gpioh_item_t *p, *n;
4087
4088	sii = SI_INFO(sih);
4089	if (sih->ccrev < 11)
4090		return;
4091
4092	ASSERT(sii->gpioh_head != NULL);
4093	if ((void*)sii->gpioh_head == gpioh) {
4094		sii->gpioh_head = sii->gpioh_head->next;
4095		MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
4096		return;
4097	} else {
4098		p = sii->gpioh_head;
4099		n = p->next;
4100		while (n) {
4101			if ((void*)n == gpioh) {
4102				p->next = n->next;
4103				MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
4104				return;
4105			}
4106			p = n;
4107			n = n->next;
4108		}
4109	}
4110
4111#ifdef BCMDBG_ERR
4112	{
4113		gpioh_item_t *h = sii->gpioh_head;
4114		int cnt = 0;
4115
4116		for (; h; h = h->next) {
4117			cnt++;
4118			SI_ERROR(("gpiohdler=%p cb=%p event=0x%x\n",
4119				h, h->handler, h->event));
4120		}
4121		SI_ERROR(("gpiohdler total=%d\n", cnt));
4122	}
4123#endif
4124	ASSERT(0); /* Not found in list */
4125}
4126
4127void
4128si_gpio_handler_process(si_t *sih)
4129{
4130	si_info_t *sii;
4131	gpioh_item_t *h;
4132	uint32 level = si_gpioin(sih);
4133	uint32 levelp = si_gpiointpolarity(sih, 0, 0, 0);
4134	uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0);
4135	uint32 edgep = si_gpioevent(sih, GPIO_REGEVT_INTPOL, 0, 0);
4136
4137	sii = SI_INFO(sih);
4138	for (h = sii->gpioh_head; h != NULL; h = h->next) {
4139		if (h->handler) {
4140			uint32 status = (h->level ? level : edge) & h->event;
4141			uint32 polarity = (h->level ? levelp : edgep) & h->event;
4142
4143			/* polarity bitval is opposite of status bitval */
4144			if (status ^ polarity)
4145				h->handler(status, h->arg);
4146		}
4147	}
4148
4149	si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */
4150}
4151
4152uint32
4153si_gpio_int_enable(si_t *sih, bool enable)
4154{
4155	uint offs;
4156
4157	if (sih->ccrev < 11)
4158		return 0xffffffff;
4159
4160	offs = OFFSETOF(chipcregs_t, intmask);
4161	return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
4162}
4163
4164
4165/** Return the size of the specified SOCRAM bank */
4166static uint
4167socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 idx, uint8 mem_type)
4168{
4169	uint banksize, bankinfo;
4170	uint bankidx = idx | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
4171
4172	ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
4173
4174	W_REG(sii->osh, &regs->bankidx, bankidx);
4175	bankinfo = R_REG(sii->osh, &regs->bankinfo);
4176	banksize = SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
4177	return banksize;
4178}
4179
4180void
4181si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect, uint8 *remap)
4182{
4183	si_info_t *sii;
4184	uint origidx;
4185	uint intr_val = 0;
4186	sbsocramregs_t *regs;
4187	bool wasup;
4188	uint corerev;
4189
4190	sii = SI_INFO(sih);
4191
4192	/* Block ints and save current core */
4193	INTR_OFF(sii, intr_val);
4194	origidx = si_coreidx(sih);
4195
4196	if (!set)
4197		*enable = *protect = *remap = 0;
4198
4199	/* Switch to SOCRAM core */
4200	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
4201		goto done;
4202
4203	/* Get info for determining size */
4204	if (!(wasup = si_iscoreup(sih)))
4205		si_core_reset(sih, 0, 0);
4206
4207	corerev = si_corerev(sih);
4208	if (corerev >= 10) {
4209		uint32 extcinfo;
4210		uint8 nb;
4211		uint8 i;
4212		uint32 bankidx, bankinfo;
4213
4214		extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
4215		nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
4216		for (i = 0; i < nb; i++) {
4217			bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
4218			W_REG(sii->osh, &regs->bankidx, bankidx);
4219			bankinfo = R_REG(sii->osh, &regs->bankinfo);
4220			if (set) {
4221				bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK;
4222				bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK;
4223				bankinfo &= ~SOCRAM_BANKINFO_DEVRAMREMAP_MASK;
4224				if (*enable) {
4225					bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT);
4226					if (*protect)
4227						bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT);
4228					if ((corerev >= 16) && *remap)
4229						bankinfo |=
4230							(1 << SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT);
4231				}
4232				W_REG(sii->osh, &regs->bankinfo, bankinfo);
4233			}
4234			else if (i == 0) {
4235				if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) {
4236					*enable = 1;
4237					if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK)
4238						*protect = 1;
4239					if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK)
4240						*remap = 1;
4241				}
4242			}
4243		}
4244	}
4245
4246	/* Return to previous state and core */
4247	if (!wasup)
4248		si_core_disable(sih, 0);
4249	si_setcoreidx(sih, origidx);
4250
4251done:
4252	INTR_RESTORE(sii, intr_val);
4253}
4254
4255bool
4256si_socdevram_remap_isenb(si_t *sih)
4257{
4258	si_info_t *sii;
4259	uint origidx;
4260	uint intr_val = 0;
4261	sbsocramregs_t *regs;
4262	bool wasup, remap = FALSE;
4263	uint corerev;
4264	uint32 extcinfo;
4265	uint8 nb;
4266	uint8 i;
4267	uint32 bankidx, bankinfo;
4268
4269	sii = SI_INFO(sih);
4270
4271	/* Block ints and save current core */
4272	INTR_OFF(sii, intr_val);
4273	origidx = si_coreidx(sih);
4274
4275	/* Switch to SOCRAM core */
4276	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
4277		goto done;
4278
4279	/* Get info for determining size */
4280	if (!(wasup = si_iscoreup(sih)))
4281		si_core_reset(sih, 0, 0);
4282
4283	corerev = si_corerev(sih);
4284	if (corerev >= 16) {
4285		extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
4286		nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
4287		for (i = 0; i < nb; i++) {
4288			bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
4289			W_REG(sii->osh, &regs->bankidx, bankidx);
4290			bankinfo = R_REG(sii->osh, &regs->bankinfo);
4291			if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) {
4292				remap = TRUE;
4293				break;
4294			}
4295		}
4296	}
4297
4298	/* Return to previous state and core */
4299	if (!wasup)
4300		si_core_disable(sih, 0);
4301	si_setcoreidx(sih, origidx);
4302
4303done:
4304	INTR_RESTORE(sii, intr_val);
4305	return remap;
4306}
4307
4308bool
4309si_socdevram_pkg(si_t *sih)
4310{
4311	if (si_socdevram_size(sih) > 0)
4312		return TRUE;
4313	else
4314		return FALSE;
4315}
4316
4317uint32
4318si_socdevram_size(si_t *sih)
4319{
4320	si_info_t *sii;
4321	uint origidx;
4322	uint intr_val = 0;
4323	uint32 memsize = 0;
4324	sbsocramregs_t *regs;
4325	bool wasup;
4326	uint corerev;
4327
4328	sii = SI_INFO(sih);
4329
4330	/* Block ints and save current core */
4331	INTR_OFF(sii, intr_val);
4332	origidx = si_coreidx(sih);
4333
4334	/* Switch to SOCRAM core */
4335	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
4336		goto done;
4337
4338	/* Get info for determining size */
4339	if (!(wasup = si_iscoreup(sih)))
4340		si_core_reset(sih, 0, 0);
4341
4342	corerev = si_corerev(sih);
4343	if (corerev >= 10) {
4344		uint32 extcinfo;
4345		uint8 nb;
4346		uint8 i;
4347
4348		extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
4349		nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
4350		for (i = 0; i < nb; i++)
4351			memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
4352	}
4353
4354	/* Return to previous state and core */
4355	if (!wasup)
4356		si_core_disable(sih, 0);
4357	si_setcoreidx(sih, origidx);
4358
4359done:
4360	INTR_RESTORE(sii, intr_val);
4361
4362	return memsize;
4363}
4364
4365uint32
4366si_socdevram_remap_size(si_t *sih)
4367{
4368	si_info_t *sii;
4369	uint origidx;
4370	uint intr_val = 0;
4371	uint32 memsize = 0, banksz;
4372	sbsocramregs_t *regs;
4373	bool wasup;
4374	uint corerev;
4375	uint32 extcinfo;
4376	uint8 nb;
4377	uint8 i;
4378	uint32 bankidx, bankinfo;
4379
4380	sii = SI_INFO(sih);
4381
4382	/* Block ints and save current core */
4383	INTR_OFF(sii, intr_val);
4384	origidx = si_coreidx(sih);
4385
4386	/* Switch to SOCRAM core */
4387	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
4388		goto done;
4389
4390	/* Get info for determining size */
4391	if (!(wasup = si_iscoreup(sih)))
4392		si_core_reset(sih, 0, 0);
4393
4394	corerev = si_corerev(sih);
4395	if (corerev >= 16) {
4396		extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
4397		nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
4398
4399		/*
4400		 * FIX: A0 Issue: Max addressable is 512KB, instead 640KB
4401		 * Only four banks are accessible to ARM
4402		 */
4403		if ((corerev == 16) && (nb == 5))
4404			nb = 4;
4405
4406		for (i = 0; i < nb; i++) {
4407			bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
4408			W_REG(sii->osh, &regs->bankidx, bankidx);
4409			bankinfo = R_REG(sii->osh, &regs->bankinfo);
4410			if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) {
4411				banksz = socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
4412				memsize += banksz;
4413			} else {
4414				/* Account only consecutive banks for now */
4415				break;
4416			}
4417		}
4418	}
4419
4420	/* Return to previous state and core */
4421	if (!wasup)
4422		si_core_disable(sih, 0);
4423	si_setcoreidx(sih, origidx);
4424
4425done:
4426	INTR_RESTORE(sii, intr_val);
4427
4428	return memsize;
4429}
4430
4431/** Return the RAM size of the SOCRAM core */
4432uint32
4433si_socram_size(si_t *sih)
4434{
4435	si_info_t *sii;
4436	uint origidx;
4437	uint intr_val = 0;
4438
4439	sbsocramregs_t *regs;
4440	bool wasup;
4441	uint corerev;
4442	uint32 coreinfo;
4443	uint memsize = 0;
4444
4445	sii = SI_INFO(sih);
4446
4447	/* Block ints and save current core */
4448	INTR_OFF(sii, intr_val);
4449	origidx = si_coreidx(sih);
4450
4451	/* Switch to SOCRAM core */
4452	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
4453		goto done;
4454
4455	/* Get info for determining size */
4456	if (!(wasup = si_iscoreup(sih)))
4457		si_core_reset(sih, 0, 0);
4458	corerev = si_corerev(sih);
4459	coreinfo = R_REG(sii->osh, &regs->coreinfo);
4460
4461	/* Calculate size from coreinfo based on rev */
4462	if (corerev == 0)
4463		memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
4464	else if (corerev < 3) {
4465		memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
4466		memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
4467	} else if ((corerev <= 7) || (corerev == 12)) {
4468		uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
4469		uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
4470		uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
4471		if (lss != 0)
4472			nb --;
4473		memsize = nb * (1 << (bsz + SR_BSZ_BASE));
4474		if (lss != 0)
4475			memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
4476	} else {
4477		uint8 i;
4478		uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
4479		for (i = 0; i < nb; i++)
4480			memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
4481	}
4482
4483	/* Return to previous state and core */
4484	if (!wasup)
4485		si_core_disable(sih, 0);
4486	si_setcoreidx(sih, origidx);
4487
4488done:
4489	INTR_RESTORE(sii, intr_val);
4490
4491	return memsize;
4492}
4493
4494#if defined(WLOFFLD)
4495
4496/** Return the TCM-RAM size of the ARMCR4 core. */
4497uint32
4498si_tcm_size(si_t *sih)
4499{
4500	si_info_t *sii;
4501	uint origidx;
4502	uint intr_val = 0;
4503	uint8 *regs;
4504	bool wasup;
4505	uint32 corecap;
4506	uint memsize = 0;
4507	uint32 nab = 0;
4508	uint32 nbb = 0;
4509	uint32 totb = 0;
4510	uint32 bxinfo = 0;
4511	uint32 idx = 0;
4512	uint32 *arm_cap_reg;
4513	uint32 *arm_bidx;
4514	uint32 *arm_binfo;
4515
4516	sii = SI_INFO(sih);
4517
4518	/* Block ints and save current core */
4519	INTR_OFF(sii, intr_val);
4520	origidx = si_coreidx(sih);
4521
4522	/* Switch to CR4 core */
4523	if (!(regs = si_setcore(sih, ARMCR4_CORE_ID, 0)))
4524		goto done;
4525
4526	/* Get info for determining size. If in reset, come out of reset,
4527	 * but remain in halt
4528	 */
4529	if (!(wasup = si_iscoreup(sih)))
4530		si_core_reset(sih, SICF_CPUHALT, SICF_CPUHALT);
4531
4532	arm_cap_reg = (uint32 *)(regs + SI_CR4_CAP);
4533	corecap = R_REG(sii->osh, arm_cap_reg);
4534
4535	nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT;
4536	nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT;
4537	totb = nab + nbb;
4538
4539	arm_bidx = (uint32 *)(regs + SI_CR4_BANKIDX);
4540	arm_binfo = (uint32 *)(regs + SI_CR4_BANKINFO);
4541	for (idx = 0; idx < totb; idx++) {
4542		W_REG(sii->osh, arm_bidx, idx);
4543
4544		bxinfo = R_REG(sii->osh, arm_binfo);
4545		memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * ARMCR4_BSZ_MULT;
4546	}
4547
4548	/* Return to previous state and core */
4549	if (!wasup)
4550		si_core_disable(sih, 0);
4551	si_setcoreidx(sih, origidx);
4552
4553done:
4554	INTR_RESTORE(sii, intr_val);
4555
4556	return memsize;
4557}
4558
4559bool
4560si_has_flops(si_t *sih)
4561{
4562	uint origidx, cr4_rev;
4563
4564	/* Find out CR4 core revision */
4565	origidx = si_coreidx(sih);
4566	if (si_setcore(sih, ARMCR4_CORE_ID, 0)) {
4567		cr4_rev = si_corerev(sih);
4568		si_setcoreidx(sih, origidx);
4569
4570		if (cr4_rev == 1 || cr4_rev >= 3)
4571			return TRUE;
4572	}
4573	return FALSE;
4574}
4575#endif
4576
4577#ifdef BCMECICOEX
4578#define NOTIFY_BT_FM_DISABLE(sih, val) \
4579	si_eci_notify_bt((sih), ECI_OUT_FM_DISABLE_MASK(sih->ccrev), \
4580			 ((val) << ECI_OUT_FM_DISABLE_SHIFT(sih->ccrev)), FALSE)
4581
4582/** Query OTP to see if FM is disabled */
4583static int
4584BCMINITFN(si_query_FMDisabled_from_OTP)(si_t *sih, uint16 *FMDisabled)
4585{
4586	int error = BCME_OK;
4587	uint bitoff = 0;
4588	bool wasup;
4589	void *oh;
4590	uint32 min_res_mask = 0;
4591
4592	/* Determine the bit for the chip */
4593	switch (CHIPID(sih->chip)) {
4594	case BCM4325_CHIP_ID:
4595		if (CHIPREV(sih->chiprev) >= 6)
4596			bitoff = OTP4325_FM_DISABLED_OFFSET;
4597		break;
4598	default:
4599		break;
4600	}
4601
4602	/* If there is a bit for this chip, check it */
4603	if (bitoff) {
4604		if (!(wasup = si_is_otp_powered(sih))) {
4605			si_otp_power(sih, TRUE, &min_res_mask);
4606		}
4607
4608		if ((oh = otp_init(sih)) != NULL)
4609			*FMDisabled = !otp_read_bit(oh, OTP4325_FM_DISABLED_OFFSET);
4610		else
4611			error = BCME_NOTFOUND;
4612
4613		if (!wasup) {
4614			si_otp_power(sih, FALSE, &min_res_mask);
4615		}
4616	}
4617
4618	return error;
4619}
4620
4621bool
4622si_eci(si_t *sih)
4623{
4624	return (!!(sih->cccaps & CC_CAP_ECI));
4625}
4626
4627bool
4628si_seci(si_t *sih)
4629{
4630	return (sih->cccaps_ext & CC_CAP_EXT_SECI_PRESENT);
4631}
4632
4633bool
4634si_gci(si_t *sih)
4635{
4636	return (sih->cccaps_ext & CC_CAP_EXT_GCI_PRESENT);
4637}
4638
4639/** ECI Init routine */
4640int
4641BCMINITFN(si_eci_init)(si_t *sih)
4642{
4643	uint32 origidx = 0;
4644	si_info_t *sii;
4645	chipcregs_t *cc;
4646	bool fast;
4647	uint16 FMDisabled = FALSE;
4648
4649	/* check for ECI capability */
4650	if (!(sih->cccaps & CC_CAP_ECI))
4651		return BCME_ERROR;
4652
4653	sii = SI_INFO(sih);
4654	fast = SI_FAST(sii);
4655	if (!fast) {
4656		origidx = sii->curidx;
4657		if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
4658			return BCME_ERROR;
4659	} else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
4660		return BCME_ERROR;
4661	ASSERT(cc);
4662
4663	/* disable level based interrupts */
4664	if (sih->ccrev < 35) {
4665		W_REG(sii->osh, &cc->eci.lt35.eci_intmaskhi, 0x0);
4666		W_REG(sii->osh, &cc->eci.lt35.eci_intmaskmi, 0x0);
4667		W_REG(sii->osh, &cc->eci.lt35.eci_intmasklo, 0x0);
4668	}
4669	else {
4670		W_REG(sii->osh, &cc->eci.ge35.eci_intmaskhi, 0x0);
4671		W_REG(sii->osh, &cc->eci.ge35.eci_intmasklo, 0x0);
4672	}
4673
4674	/* Assign eci_output bits between 'wl' and dot11mac */
4675	if (sih->ccrev < 35) {
4676		W_REG(sii->osh, &cc->eci.lt35.eci_control, ECI_MACCTRL_BITS);
4677	}
4678	else {
4679		W_REG(sii->osh, &cc->eci.ge35.eci_controllo, ECI_MACCTRLLO_BITS);
4680		W_REG(sii->osh, &cc->eci.ge35.eci_controlhi, ECI_MACCTRLHI_BITS);
4681	}
4682
4683	/* enable only edge based interrupts
4684	 * only toggle on bit 62 triggers an interrupt
4685	 */
4686	if (sih->ccrev < 35) {
4687		W_REG(sii->osh, &cc->eci.lt35.eci_eventmaskhi, 0x0);
4688		W_REG(sii->osh, &cc->eci.lt35.eci_eventmaskmi, 0x0);
4689		W_REG(sii->osh, &cc->eci.lt35.eci_eventmasklo, 0x0);
4690	}
4691	else {
4692		W_REG(sii->osh, &cc->eci.ge35.eci_eventmaskhi, 0x0);
4693		W_REG(sii->osh, &cc->eci.ge35.eci_eventmasklo, 0x0);
4694	}
4695
4696	/* restore previous core */
4697	if (!fast)
4698		si_setcoreidx(sih, origidx);
4699
4700	/* if FM disabled in OTP, let BT know */
4701	if (!si_query_FMDisabled_from_OTP(sih, &FMDisabled)) {
4702		if (FMDisabled) {
4703			NOTIFY_BT_FM_DISABLE(sih, 1);
4704		}
4705	}
4706
4707	return 0;
4708}
4709
4710/** Write values to BT on eci_output. */
4711void
4712si_eci_notify_bt(si_t *sih, uint32 mask, uint32 val, bool interrupt)
4713{
4714	uint32 offset;
4715
4716	if ((sih->cccaps & CC_CAP_ECI) ||
4717		(si_seci(sih)))
4718	{
4719		/* ECI or SECI mode */
4720		/* Clear interrupt bit by default */
4721		if (interrupt)
4722			si_corereg(sih, SI_CC_IDX,
4723			   (sih->ccrev < 35 ?
4724			    OFFSETOF(chipcregs_t, eci.lt35.eci_output) :
4725			    OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo)),
4726			   (1 << 30), 0);
4727
4728		if (sih->ccrev >= 35) {
4729			if ((mask & 0xFFFF0000) == ECI48_OUT_MASKMAGIC_HIWORD) {
4730				offset = OFFSETOF(chipcregs_t, eci.ge35.eci_outputhi);
4731				mask = mask & ~0xFFFF0000;
4732			}
4733			else {
4734				offset = OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo);
4735		mask = mask | (1<<30);
4736				val = val & ~(1 << 30);
4737			}
4738		}
4739		else {
4740			offset = OFFSETOF(chipcregs_t, eci.lt35.eci_output);
4741			val = val & ~(1 << 30);
4742		}
4743
4744		si_corereg(sih, SI_CC_IDX, offset, mask, val);
4745
4746		/* Set interrupt bit if needed */
4747		if (interrupt)
4748			si_corereg(sih, SI_CC_IDX,
4749			   (sih->ccrev < 35 ?
4750			    OFFSETOF(chipcregs_t, eci.lt35.eci_output) :
4751			    OFFSETOF(chipcregs_t, eci.ge35.eci_outputlo)),
4752			   (1 << 30), (1 << 30));
4753	}
4754	else if (sih->cccaps_ext & CC_CAP_EXT_GCI_PRESENT)
4755	{
4756		/* GCI Mode */
4757		if ((mask & 0xFFFF0000) == ECI48_OUT_MASKMAGIC_HIWORD) {
4758			mask = mask & ~0xFFFF0000;
4759			si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_output[1]), mask, val);
4760		}
4761	}
4762}
4763
4764/** seci clock enable/disable */
4765static void
4766si_seci_clkreq(si_t *sih, bool enable)
4767{
4768	uint32 clk_ctl_st;
4769	uint32 offset;
4770	uint32 val;
4771
4772	if (!si_seci(sih))
4773		return;
4774
4775	if (enable)
4776		val = CLKCTL_STS_SECI_CLK_REQ;
4777	else
4778		val = 0;
4779
4780	offset = OFFSETOF(chipcregs_t, clk_ctl_st);
4781
4782	si_corereg(sih, SI_CC_IDX, offset, CLKCTL_STS_SECI_CLK_REQ, val);
4783
4784	if (!enable)
4785		return;
4786
4787	SPINWAIT(!(si_corereg(sih, 0, offset, 0, 0) & CLKCTL_STS_SECI_CLK_AVAIL),
4788	    PMU_MAX_TRANSITION_DLY);
4789
4790	clk_ctl_st = si_corereg(sih, 0, offset, 0, 0);
4791	if (enable) {
4792		if (!(clk_ctl_st & CLKCTL_STS_SECI_CLK_AVAIL)) {
4793			SI_ERROR(("SECI clock is still not available\n"));
4794			return;
4795		}
4796	}
4797}
4798
4799void
4800BCMINITFN(si_seci_down)(si_t *sih)
4801{
4802	uint32 origidx = 0;
4803	si_info_t *sii;
4804	chipcregs_t *cc;
4805	bool fast;
4806	uint32 seci_conf;
4807
4808	if (!si_seci(sih))
4809		return;
4810
4811	sii = SI_INFO(sih);
4812	fast = SI_FAST(sii);
4813
4814	if (!fast) {
4815		origidx = sii->curidx;
4816		if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
4817			return;
4818	} else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
4819		return;
4820	ASSERT(cc);
4821	/* 4331 X28 sign off seci */
4822	if (CHIPID(sih->chip) == BCM4331_CHIP_ID) {
4823		/* flush seci */
4824		seci_conf = R_REG(sii->osh, &cc->SECI_config);
4825		seci_conf |= SECI_UPD_SECI;
4826		W_REG(sii->osh, &cc->SECI_config, seci_conf);
4827		SPINWAIT((R_REG(sii->osh, &cc->SECI_config) & SECI_UPD_SECI), 1000);
4828
4829		/* SECI sign off */
4830		W_REG(sii->osh, &cc->seci_uart_data, SECI_SIGNOFF_0);
4831		W_REG(sii->osh, &cc->seci_uart_data, SECI_SIGNOFF_1);
4832		SPINWAIT((R_REG(sii->osh, &cc->seci_uart_lsr) & (1 << 2)), 1000);
4833		/* put seci in reset */
4834		seci_conf = R_REG(sii->osh, &cc->SECI_config);
4835		seci_conf &= ~SECI_ENAB_SECI_ECI;
4836		W_REG(sii->osh, &cc->SECI_config, seci_conf);
4837		seci_conf |= SECI_RESET;
4838		W_REG(sii->osh, &cc->SECI_config, seci_conf);
4839	}
4840
4841	/* bring down the clock if up */
4842	si_seci_clkreq(sih, FALSE);
4843
4844	/* restore previous core */
4845	if (!fast)
4846		si_setcoreidx(sih, origidx);
4847}
4848
4849void
4850si_seci_upd(si_t *sih, bool enable)
4851{
4852	uint32 origidx = 0;
4853	si_info_t *sii;
4854	chipcregs_t *cc;
4855	bool fast;
4856	uint32 regval, seci_ctrl;
4857	uint intr_val = 0;
4858
4859	if (!si_seci(sih))
4860		return;
4861
4862	sii = SI_INFO(sih);
4863	fast = SI_FAST(sii);
4864	INTR_OFF(sii, intr_val);
4865	if (!fast) {
4866		origidx = sii->curidx;
4867		if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
4868			goto exit;
4869	} else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
4870		goto exit;
4871
4872	ASSERT(cc);
4873
4874	/* Select SECI based on enable input */
4875	if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
4876	    (CHIPID(sih->chip) == BCM4352_CHIP_ID) ||
4877	    (CHIPID(sih->chip) == BCM4360_CHIP_ID)) {
4878		regval = R_REG(sii->osh, &cc->chipcontrol);
4879
4880		if (CHIPID(sih->chip) == BCM4331_CHIP_ID) {
4881			seci_ctrl = CCTRL4331_SECI;
4882		} else {
4883			seci_ctrl = CCTRL4360_SECI_ON_GPIO01;
4884		}
4885
4886		if (enable) {
4887			regval |= seci_ctrl;
4888		} else {
4889			regval &= ~seci_ctrl;
4890		}
4891		W_REG(sii->osh, &cc->chipcontrol, regval);
4892
4893		if (enable) {
4894			/* Send ECI update to BT */
4895			regval = R_REG(sii->osh, &cc->SECI_config);
4896			regval |= SECI_UPD_SECI;
4897			W_REG(sii->osh, &cc->SECI_config, regval);
4898			SPINWAIT((R_REG(sii->osh, &cc->SECI_config) & SECI_UPD_SECI), 1000);
4899			/* Request ECI update from BT */
4900			W_REG(sii->osh, &cc->seci_uart_data, SECI_SLIP_ESC_CHAR);
4901			W_REG(sii->osh, &cc->seci_uart_data, SECI_REFRESH_REQ);
4902		}
4903	}
4904
4905exit:
4906	/* restore previous core */
4907	if (!fast)
4908		si_setcoreidx(sih, origidx);
4909
4910	INTR_RESTORE(sii, intr_val);
4911}
4912
4913/** SECI Init routine, pass in seci_mode */
4914void *
4915BCMINITFN(si_seci_init)(si_t *sih, uint8  seci_mode)
4916{
4917	uint32 origidx = 0;
4918	uint32 offset;
4919	si_info_t *sii;
4920	void *ptr;
4921	chipcregs_t *cc;
4922	bool fast;
4923	uint32 seci_conf;
4924	uint32 regval;
4925
4926	if (sih->ccrev < 35)
4927		return NULL;
4928
4929	if (!si_seci(sih))
4930		return NULL;
4931
4932	if (seci_mode > SECI_MODE_MASK)
4933		return NULL;
4934
4935	sii = SI_INFO(sih);
4936	fast = SI_FAST(sii);
4937	if (!fast) {
4938		origidx = sii->curidx;
4939		if ((ptr = si_setcore(sih, CC_CORE_ID, 0)) == NULL)
4940			return NULL;
4941	} else if ((ptr = CCREGS_FAST(sii)) == NULL)
4942		return NULL;
4943	cc = (chipcregs_t *)ptr;
4944	ASSERT(cc);
4945
4946
4947	/* 43236 (ccrev 36) muxes SECI on JTAG pins. Select SECI. */
4948	if (CHIPID(sih->chip) == BCM43236_CHIP_ID ||
4949	    CHIPID(sih->chip) == BCM4331_CHIP_ID) {
4950		regval = R_REG(sii->osh, &cc->chipcontrol);
4951		regval |= CCTRL4331_SECI;
4952		W_REG(sii->osh, &cc->chipcontrol, regval);
4953	}
4954
4955	/* 43143 (ccrev 43) mux SECI on JTAG pins. Select SECI. */
4956	if (CHIPID(sih->chip) == BCM43143_CHIP_ID) {
4957		regval = R_REG(sii->osh, &cc->chipcontrol);
4958		regval &= ~(CCTRL_43143_SECI | CCTRL_43143_BT_LEGACY);
4959		switch (seci_mode) {
4960			case SECI_MODE_LEGACY_3WIRE_WLAN:
4961				regval |= CCTRL_43143_BT_LEGACY;
4962				break;
4963			case SECI_MODE_SECI:
4964				regval |= CCTRL_43143_SECI;
4965				break;
4966			default:
4967				ASSERT(0);
4968		}
4969		W_REG(sii->osh, &cc->chipcontrol, regval);
4970	}
4971
4972	if ((CHIPID(sih->chip) == BCM43236_CHIP_ID) ||
4973	    (CHIPID(sih->chip) == BCM43143_CHIP_ID)) {
4974		regval = R_REG(sii->osh, &cc->jtagctrl);
4975		regval |= 0x1;
4976		W_REG(sii->osh, &cc->jtagctrl, regval);
4977	}
4978
4979	/* enable SECI clock */
4980	si_seci_clkreq(sih, TRUE);
4981
4982	/* put the SECI in reset */
4983	seci_conf = R_REG(sii->osh, &cc->SECI_config);
4984	seci_conf &= ~SECI_ENAB_SECI_ECI;
4985	W_REG(sii->osh, &cc->SECI_config, seci_conf);
4986	seci_conf = SECI_RESET;
4987	W_REG(sii->osh, &cc->SECI_config, seci_conf);
4988
4989	/* set force-low, and set EN_SECI for all non-legacy modes */
4990	seci_conf |= SECI_ENAB_SECIOUT_DIS;
4991	if ((seci_mode == SECI_MODE_UART) || (seci_mode == SECI_MODE_SECI) ||
4992	    (seci_mode == SECI_MODE_HALF_SECI))
4993	{
4994		seci_conf |= SECI_ENAB_SECI_ECI;
4995	}
4996	W_REG(sii->osh, &cc->SECI_config, seci_conf);
4997
4998	/* take seci out of reset */
4999	seci_conf = R_REG(sii->osh, &cc->SECI_config);
5000	seci_conf &= ~(SECI_RESET);
5001	W_REG(sii->osh, &cc->SECI_config, seci_conf);
5002
5003	/* set UART/SECI baud rate */
5004	/* hard-coded at 4MBaud for now */
5005	if ((seci_mode == SECI_MODE_UART) || (seci_mode == SECI_MODE_SECI) ||
5006	    (seci_mode == SECI_MODE_HALF_SECI)) {
5007		if ((CHIPID(sih->chip) == BCM43236_CHIP_ID) ||
5008		    (CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
5009		    (CHIPID(sih->chip) == BCM43143_CHIP_ID)) {
5010			/* 43236 ccrev = 36 and MAC clk = 96MHz */
5011			/* 4331,43143 MAC clk = 96MHz */
5012			offset = OFFSETOF(chipcregs_t, seci_uart_bauddiv);
5013			si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0xFF);
5014			offset = OFFSETOF(chipcregs_t, seci_uart_baudadj);
5015			si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0x44);
5016		}
5017		else if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
5018			(CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
5019			(CHIPID(sih->chip) == BCM43526_CHIP_ID) ||
5020			(CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
5021			/* MAC clk is 160MHz */
5022			offset = OFFSETOF(chipcregs_t, seci_uart_bauddiv);
5023			si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0xFE);
5024			offset = OFFSETOF(chipcregs_t, seci_uart_baudadj);
5025			si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0x44);
5026		}
5027		else {
5028			/* 4336 MAC clk is 80MHz */
5029			offset = OFFSETOF(chipcregs_t, seci_uart_bauddiv);
5030			si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0xFF);
5031			offset = OFFSETOF(chipcregs_t, seci_uart_baudadj);
5032			si_corereg(sih, SI_CC_IDX, offset, 0xFF, 0x22);
5033		}
5034
5035		/* LCR/MCR settings */
5036		offset = OFFSETOF(chipcregs_t, seci_uart_lcr);
5037		si_corereg(sih, SI_CC_IDX, offset, 0xFF,
5038			(SECI_UART_LCR_RX_EN | SECI_UART_LCR_TXO_EN)); /* 0x28 */
5039		offset = OFFSETOF(chipcregs_t, seci_uart_mcr);
5040		si_corereg(sih, SI_CC_IDX, offset,
5041			0xFF, (SECI_UART_MCR_TX_EN | SECI_UART_MCR_BAUD_ADJ_EN)); /* 0x81 */
5042
5043		/* Give control of ECI output regs to MAC core */
5044		offset = OFFSETOF(chipcregs_t, eci.ge35.eci_controllo);
5045		si_corereg(sih, SI_CC_IDX, offset, 0xFFFFFFFF, ECI_MACCTRLLO_BITS);
5046		offset = OFFSETOF(chipcregs_t, eci.ge35.eci_controlhi);
5047		si_corereg(sih, SI_CC_IDX, offset, 0xFFFF, ECI_MACCTRLHI_BITS);
5048	}
5049
5050	/* set the seci mode in seci conf register */
5051	seci_conf = R_REG(sii->osh, &cc->SECI_config);
5052	seci_conf &= ~(SECI_MODE_MASK << SECI_MODE_SHIFT);
5053	seci_conf |= (seci_mode << SECI_MODE_SHIFT);
5054	W_REG(sii->osh, &cc->SECI_config, seci_conf);
5055
5056	/* Clear force-low bit */
5057	seci_conf = R_REG(sii->osh, &cc->SECI_config);
5058	seci_conf &= ~SECI_ENAB_SECIOUT_DIS;
5059	W_REG(sii->osh, &cc->SECI_config, seci_conf);
5060
5061	/* restore previous core */
5062	if (!fast)
5063		si_setcoreidx(sih, origidx);
5064
5065	return ptr;
5066}
5067
5068void *
5069BCMINITFN(si_gci_init)(si_t *sih)
5070{
5071	if (sih->cccaps_ext & CC_CAP_EXT_GCI_PRESENT)
5072	{
5073		si_gci_reset(sih);
5074		/* Set GCI Control bits 40 - 47 to be SW Controlled. These bits
5075		contain WL channel info and are sent to BT.
5076		*/
5077		si_gci_direct(sih, OFFSETOF(chipcregs_t, gci_control_1),
5078			GCI_WL_CHN_INFO_MASK, GCI_WL_CHN_INFO_MASK);
5079	}
5080	return (NULL);
5081}
5082#endif /* BCMECICOEX */
5083
5084#if (!defined(_CFE_) && !defined(_CFEZ_)) || defined(CFG_WL)
5085void
5086si_btcgpiowar(si_t *sih)
5087{
5088	si_info_t *sii;
5089	uint origidx;
5090	uint intr_val = 0;
5091	chipcregs_t *cc;
5092
5093	sii = SI_INFO(sih);
5094
5095	/* Make sure that there is ChipCommon core present &&
5096	 * UART_TX is strapped to 1
5097	 */
5098	if (!(sih->cccaps & CC_CAP_UARTGPIO))
5099		return;
5100
5101	/* si_corereg cannot be used as we have to guarantee 8-bit read/writes */
5102	INTR_OFF(sii, intr_val);
5103
5104	origidx = si_coreidx(sih);
5105
5106	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
5107	ASSERT(cc != NULL);
5108
5109	W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04);
5110
5111	/* restore the original index */
5112	si_setcoreidx(sih, origidx);
5113
5114	INTR_RESTORE(sii, intr_val);
5115}
5116
5117void
5118si_chipcontrl_btshd0_4331(si_t *sih, bool on)
5119{
5120	si_info_t *sii;
5121	chipcregs_t *cc;
5122	uint origidx;
5123	uint32 val;
5124	uint intr_val = 0;
5125
5126	sii = SI_INFO(sih);
5127
5128	INTR_OFF(sii, intr_val);
5129
5130	origidx = si_coreidx(sih);
5131
5132	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
5133
5134	val = R_REG(sii->osh, &cc->chipcontrol);
5135
5136	/* bt_shd0 controls are same for 4331 chiprevs 0 and 1, packages 12x9 and 12x12 */
5137	if (on) {
5138		/* Enable bt_shd0 on gpio4: */
5139		val |= (CCTRL4331_BT_SHD0_ON_GPIO4);
5140		W_REG(sii->osh, &cc->chipcontrol, val);
5141	} else {
5142		val &= ~(CCTRL4331_BT_SHD0_ON_GPIO4);
5143		W_REG(sii->osh, &cc->chipcontrol, val);
5144	}
5145
5146	/* restore the original index */
5147	si_setcoreidx(sih, origidx);
5148
5149	INTR_RESTORE(sii, intr_val);
5150}
5151
5152void
5153si_chipcontrl_restore(si_t *sih, uint32 val)
5154{
5155	si_info_t *sii;
5156	chipcregs_t *cc;
5157	uint origidx;
5158
5159	sii = SI_INFO(sih);
5160	origidx = si_coreidx(sih);
5161	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
5162	W_REG(sii->osh, &cc->chipcontrol, val);
5163	si_setcoreidx(sih, origidx);
5164}
5165
5166uint32
5167si_chipcontrl_read(si_t *sih)
5168{
5169	si_info_t *sii;
5170	chipcregs_t *cc;
5171	uint origidx;
5172	uint32 val;
5173
5174	sii = SI_INFO(sih);
5175	origidx = si_coreidx(sih);
5176	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
5177	val = R_REG(sii->osh, &cc->chipcontrol);
5178	si_setcoreidx(sih, origidx);
5179	return val;
5180}
5181
5182void
5183si_chipcontrl_epa4331(si_t *sih, bool on)
5184{
5185	si_info_t *sii;
5186	chipcregs_t *cc;
5187	uint origidx;
5188	uint32 val;
5189
5190	sii = SI_INFO(sih);
5191	origidx = si_coreidx(sih);
5192
5193	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
5194
5195	val = R_REG(sii->osh, &cc->chipcontrol);
5196
5197	if (on) {
5198		if (sih->chippkg == 9 || sih->chippkg == 0xb) {
5199			val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
5200			/* Ext PA Controls for 4331 12x9 Package */
5201			W_REG(sii->osh, &cc->chipcontrol, val);
5202		} else {
5203			/* Ext PA Controls for 4331 12x12 Package */
5204			if (sih->chiprev > 0) {
5205				W_REG(sii->osh, &cc->chipcontrol, val |
5206				      (CCTRL4331_EXTPA_EN) | (CCTRL4331_EXTPA_EN2));
5207			} else {
5208				W_REG(sii->osh, &cc->chipcontrol, val | (CCTRL4331_EXTPA_EN));
5209			}
5210		}
5211	} else {
5212		val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_EN2 | CCTRL4331_EXTPA_ON_GPIO2_5);
5213		W_REG(sii->osh, &cc->chipcontrol, val);
5214	}
5215
5216	si_setcoreidx(sih, origidx);
5217}
5218
5219/** switch muxed pins, on: SROM, off: FEMCTRL. Called for a family of ac chips, not just 4360. */
5220void
5221si_chipcontrl_srom4360(si_t *sih, bool on)
5222{
5223	si_info_t *sii;
5224	chipcregs_t *cc;
5225	uint origidx;
5226	uint32 val;
5227
5228	sii = SI_INFO(sih);
5229	origidx = si_coreidx(sih);
5230
5231	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
5232
5233	val = R_REG(sii->osh, &cc->chipcontrol);
5234
5235	if (on) {
5236		val &= ~(CCTRL4360_SECI_MODE |
5237			CCTRL4360_BTSWCTRL_MODE |
5238			CCTRL4360_EXTRA_FEMCTRL_MODE |
5239			CCTRL4360_BT_LGCY_MODE |
5240			CCTRL4360_CORE2FEMCTRL4_ON);
5241
5242		W_REG(sii->osh, &cc->chipcontrol, val);
5243	} else {
5244	}
5245
5246	si_setcoreidx(sih, origidx);
5247}
5248
5249void
5250si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl)
5251{
5252	si_info_t *sii;
5253	chipcregs_t *cc;
5254	uint origidx;
5255	uint32 val;
5256	bool sel_chip;
5257
5258	sel_chip = (CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
5259		(CHIPID(sih->chip) == BCM43431_CHIP_ID);
5260	sel_chip &= ((sih->chippkg == 9 || sih->chippkg == 0xb));
5261
5262	if (!sel_chip)
5263		return;
5264
5265	sii = SI_INFO(sih);
5266	origidx = si_coreidx(sih);
5267
5268	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
5269
5270	val = R_REG(sii->osh, &cc->chipcontrol);
5271
5272	if (enter_wowl) {
5273		val |= CCTRL4331_EXTPA_EN;
5274		W_REG(sii->osh, &cc->chipcontrol, val);
5275	} else {
5276		val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
5277		W_REG(sii->osh, &cc->chipcontrol, val);
5278	}
5279	si_setcoreidx(sih, origidx);
5280}
5281#endif /* (!_CFE_ && !_CFEZ_) || CFG_WL */
5282
5283uint
5284si_pll_reset(si_t *sih)
5285{
5286	uint err = 0;
5287
5288	uint intr_val = 0;
5289	si_info_t *sii;
5290	sii = SI_INFO(sih);
5291	INTR_OFF(sii, intr_val);
5292	err = si_pll_minresmask_reset(sih, sii->osh);
5293	INTR_RESTORE(sii, intr_val);
5294	return (err);
5295}
5296
5297/** Enable BT-COEX & Ex-PA for 4313 */
5298void
5299si_epa_4313war(si_t *sih)
5300{
5301	si_info_t *sii;
5302	chipcregs_t *cc;
5303	uint origidx;
5304
5305	sii = SI_INFO(sih);
5306	origidx = si_coreidx(sih);
5307
5308	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
5309
5310	/* EPA Fix */
5311	W_REG(sii->osh, &cc->gpiocontrol,
5312		R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
5313
5314	si_setcoreidx(sih, origidx);
5315}
5316
5317void
5318si_clk_pmu_htavail_set(si_t *sih, bool set_clear)
5319{
5320	si_info_t *sii;
5321	sii = SI_INFO(sih);
5322
5323	si_pmu_minresmask_htavail_set(sih, sii->osh, set_clear);
5324}
5325
5326/** Re-enable synth_pwrsw resource in min_res_mask for 4313 */
5327void
5328si_pmu_synth_pwrsw_4313_war(si_t *sih)
5329{
5330	si_info_t *sii;
5331	chipcregs_t *cc;
5332	uint origidx;
5333
5334	sii = SI_INFO(sih);
5335	origidx = si_coreidx(sih);
5336
5337	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
5338	if (!(cc->min_res_mask & PMURES_BIT(RES4313_SYNTH_PWRSW_RSRC)))
5339		OR_REG(sii->osh, &cc->min_res_mask, PMURES_BIT(RES4313_SYNTH_PWRSW_RSRC));
5340
5341	si_setcoreidx(sih, origidx);
5342}
5343
5344/** WL/BT control for 4313 btcombo boards >= P250 */
5345void
5346si_btcombo_p250_4313_war(si_t *sih)
5347{
5348	si_info_t *sii;
5349	chipcregs_t *cc;
5350	uint origidx;
5351
5352	sii = SI_INFO(sih);
5353	origidx = si_coreidx(sih);
5354
5355	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
5356	W_REG(sii->osh, &cc->gpiocontrol,
5357		R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_5_6_EN_MASK);
5358
5359	W_REG(sii->osh, &cc->gpioouten,
5360		R_REG(sii->osh, &cc->gpioouten) | GPIO_CTRL_5_6_EN_MASK);
5361
5362	si_setcoreidx(sih, origidx);
5363}
5364void
5365si_btc_enable_chipcontrol(si_t *sih)
5366{
5367	si_info_t *sii;
5368	chipcregs_t *cc;
5369	uint origidx;
5370
5371	sii = SI_INFO(sih);
5372	origidx = si_coreidx(sih);
5373
5374	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
5375
5376	/* BT fix */
5377	W_REG(sii->osh, &cc->chipcontrol,
5378		R_REG(sii->osh, &cc->chipcontrol) | CC_BTCOEX_EN_MASK);
5379
5380	si_setcoreidx(sih, origidx);
5381}
5382void
5383si_btcombo_43228_war(si_t *sih)
5384{
5385	si_info_t *sii;
5386	chipcregs_t *cc;
5387	uint origidx;
5388
5389	sii = SI_INFO(sih);
5390	origidx = si_coreidx(sih);
5391
5392	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
5393
5394	W_REG(sii->osh, &cc->gpioouten, GPIO_CTRL_7_6_EN_MASK);
5395	W_REG(sii->osh, &cc->gpioout, GPIO_OUT_7_EN_MASK);
5396
5397	si_setcoreidx(sih, origidx);
5398}
5399
5400/** check if the device is removed */
5401bool
5402si_deviceremoved(si_t *sih)
5403{
5404	uint32 w;
5405	si_info_t *sii;
5406
5407	sii = SI_INFO(sih);
5408
5409	switch (BUSTYPE(sih->bustype)) {
5410	case PCI_BUS:
5411		ASSERT(sii->osh != NULL);
5412		w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32));
5413		if ((w & 0xFFFF) != VENDOR_BROADCOM)
5414			return TRUE;
5415		break;
5416	}
5417	return FALSE;
5418}
5419
5420bool
5421si_is_sprom_available(si_t *sih)
5422{
5423	if (sih->ccrev >= 31) {
5424		si_info_t *sii;
5425		uint origidx;
5426		chipcregs_t *cc;
5427		uint32 sromctrl;
5428
5429		if ((sih->cccaps & CC_CAP_SROM) == 0)
5430			return FALSE;
5431
5432		sii = SI_INFO(sih);
5433		origidx = sii->curidx;
5434		cc = si_setcoreidx(sih, SI_CC_IDX);
5435		sromctrl = R_REG(sii->osh, &cc->sromcontrol);
5436		si_setcoreidx(sih, origidx);
5437		return (sromctrl & SRC_PRESENT);
5438	}
5439
5440	switch (CHIPID(sih->chip)) {
5441	case BCM4312_CHIP_ID:
5442		return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL);
5443	case BCM4325_CHIP_ID:
5444		return (sih->chipst & CST4325_SPROM_SEL) != 0;
5445	case BCM4322_CHIP_ID:	case BCM43221_CHIP_ID:	case BCM43231_CHIP_ID:
5446	case BCM43222_CHIP_ID:	case BCM43111_CHIP_ID:	case BCM43112_CHIP_ID:
5447	case BCM4342_CHIP_ID: {
5448		uint32 spromotp;
5449		spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
5450		        CST4322_SPROM_OTP_SEL_SHIFT;
5451		return (spromotp & CST4322_SPROM_PRESENT) != 0;
5452	}
5453	case BCM4329_CHIP_ID:
5454		return (sih->chipst & CST4329_SPROM_SEL) != 0;
5455	case BCM4315_CHIP_ID:
5456		return (sih->chipst & CST4315_SPROM_SEL) != 0;
5457	case BCM4319_CHIP_ID:
5458		return (sih->chipst & CST4319_SPROM_SEL) != 0;
5459	case BCM4336_CHIP_ID:
5460	case BCM43362_CHIP_ID:
5461		return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
5462	case BCM4330_CHIP_ID:
5463		return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
5464	case BCM4313_CHIP_ID:
5465		return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
5466	case BCM4331_CHIP_ID:
5467	case BCM43431_CHIP_ID:
5468		return (sih->chipst & CST4331_SPROM_PRESENT) != 0;
5469	case BCM43239_CHIP_ID:
5470		return ((sih->chipst & CST43239_SPROM_MASK) &&
5471			!(sih->chipst & CST43239_SFLASH_MASK));
5472	case BCM4324_CHIP_ID:
5473	case BCM43242_CHIP_ID:
5474		return ((sih->chipst & CST4324_SPROM_MASK) &&
5475			!(sih->chipst & CST4324_SFLASH_MASK));
5476	case BCM4335_CHIP_ID:
5477		return ((sih->chipst & CST4335_SPROM_MASK) &&
5478			!(sih->chipst & CST4335_SFLASH_MASK));
5479
5480	case BCM4350_CHIP_ID:
5481		return (sih->chipst & CST4350_SPROM_PRESENT) != 0;
5482	case BCM43131_CHIP_ID:
5483	case BCM43217_CHIP_ID:
5484	case BCM43227_CHIP_ID:
5485	case BCM43228_CHIP_ID:
5486	case BCM43428_CHIP_ID:
5487		return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT;
5488	default:
5489		return TRUE;
5490	}
5491}
5492
5493bool
5494si_is_otp_disabled(si_t *sih)
5495{
5496	switch (CHIPID(sih->chip)) {
5497	case BCM4325_CHIP_ID:
5498		return (sih->chipst & CST4325_SPROM_OTP_SEL_MASK) == CST4325_OTP_PWRDN;
5499	case BCM4322_CHIP_ID:
5500	case BCM43221_CHIP_ID:
5501	case BCM43231_CHIP_ID:
5502	case BCM4342_CHIP_ID:
5503		return (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
5504			CST4322_SPROM_OTP_SEL_SHIFT) & CST4322_OTP_PRESENT) !=
5505			CST4322_OTP_PRESENT;
5506	case BCM4329_CHIP_ID:
5507		return (sih->chipst & CST4329_SPROM_OTP_SEL_MASK) == CST4329_OTP_PWRDN;
5508	case BCM4315_CHIP_ID:
5509		return (sih->chipst & CST4315_SPROM_OTP_SEL_MASK) == CST4315_OTP_PWRDN;
5510	case BCM4319_CHIP_ID:
5511		return (sih->chipst & CST4319_SPROM_OTP_SEL_MASK) == CST4319_OTP_PWRDN;
5512	case BCM4336_CHIP_ID:
5513	case BCM43362_CHIP_ID:
5514		return ((sih->chipst & CST4336_OTP_PRESENT) == 0);
5515	case BCM4330_CHIP_ID:
5516		return ((sih->chipst & CST4330_OTP_PRESENT) == 0);
5517	case BCM43237_CHIP_ID:
5518		return FALSE;
5519	case BCM4313_CHIP_ID:
5520		return (sih->chipst & CST4313_OTP_PRESENT) == 0;
5521	case BCM4331_CHIP_ID:
5522		return (sih->chipst & CST4331_OTP_PRESENT) != CST4331_OTP_PRESENT;
5523	case BCM4360_CHIP_ID:
5524	case BCM43526_CHIP_ID:
5525	case BCM43460_CHIP_ID:
5526	case BCM4352_CHIP_ID:
5527		/* 4360 OTP is always powered and enabled */
5528		return FALSE;
5529	/* These chips always have their OTP on */
5530	case BCM43111_CHIP_ID:	case BCM43112_CHIP_ID:	case BCM43222_CHIP_ID:
5531	case BCM43224_CHIP_ID:	case BCM43225_CHIP_ID:
5532	case BCM43421_CHIP_ID:
5533	case BCM43226_CHIP_ID:
5534	case BCM43235_CHIP_ID:	case BCM43236_CHIP_ID:	case BCM43238_CHIP_ID:
5535	case BCM43234_CHIP_ID:	case BCM43239_CHIP_ID:	case BCM4324_CHIP_ID:
5536	case BCM43431_CHIP_ID:
5537	case BCM43131_CHIP_ID:
5538	case BCM43217_CHIP_ID:
5539	case BCM43227_CHIP_ID:
5540	case BCM43228_CHIP_ID:
5541	case BCM43428_CHIP_ID: case BCM4335_CHIP_ID:
5542	case BCM4350_CHIP_ID:
5543	case BCM43143_CHIP_ID:
5544	case BCM43242_CHIP_ID:
5545	case BCM43243_CHIP_ID:
5546	default:
5547		return FALSE;
5548	}
5549}
5550
5551bool
5552si_is_otp_powered(si_t *sih)
5553{
5554	if (PMUCTL_ENAB(sih))
5555		return si_pmu_is_otp_powered(sih, si_osh(sih));
5556	return TRUE;
5557}
5558
5559void
5560si_otp_power(si_t *sih, bool on, uint32* min_res_mask)
5561{
5562	if (PMUCTL_ENAB(sih))
5563		si_pmu_otp_power(sih, si_osh(sih), on, min_res_mask);
5564	OSL_DELAY(1000);
5565}
5566
5567bool
5568#if defined(BCMDBG) || defined(WLTEST) || defined(BCMDBG_ERR)
5569si_is_sprom_enabled(si_t *sih)
5570#else
5571BCMATTACHFN(si_is_sprom_enabled)(si_t *sih)
5572#endif
5573{
5574	if (PMUCTL_ENAB(sih))
5575		return si_pmu_is_sprom_enabled(sih, si_osh(sih));
5576	return TRUE;
5577}
5578
5579void
5580#if defined(BCMDBG) || defined(WLTEST) || defined(BCMDBG_ERR)
5581si_sprom_enable(si_t *sih, bool enable)
5582#else
5583BCMATTACHFN(si_sprom_enable)(si_t *sih, bool enable)
5584#endif
5585{
5586	if (PMUCTL_ENAB(sih))
5587		si_pmu_sprom_enable(sih, si_osh(sih), enable);
5588}
5589
5590/* Return BCME_NOTFOUND if the card doesn't have CIS format nvram */
5591int
5592si_cis_source(si_t *sih)
5593{
5594	/* Many chips have the same mapping of their chipstatus field */
5595	static const uint cis_sel[] = { CIS_DEFAULT, CIS_SROM, CIS_OTP, CIS_SROM };
5596	static const uint cis_43236_sel[] = { CIS_DEFAULT, CIS_OTP };
5597
5598	/* PCI chips use SROM format instead of CIS */
5599	if (BUSTYPE(sih->bustype) == PCI_BUS)
5600		return BCME_NOTFOUND;
5601
5602	switch (CHIPID(sih->chip)) {
5603	case BCM4325_CHIP_ID:
5604		return ((sih->chipst & CST4325_SPROM_OTP_SEL_MASK) >= ARRAYSIZE(cis_sel)) ?
5605		        CIS_DEFAULT : cis_sel[(sih->chipst & CST4325_SPROM_OTP_SEL_MASK)];
5606	case BCM4322_CHIP_ID:	case BCM43221_CHIP_ID:	case BCM43231_CHIP_ID:
5607	case BCM4342_CHIP_ID: {
5608		uint8 strap = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
5609			CST4322_SPROM_OTP_SEL_SHIFT;
5610
5611		return ((strap >= ARRAYSIZE(cis_sel)) ?  CIS_DEFAULT : cis_sel[strap]);
5612
5613	}
5614
5615	case BCM43235_CHIP_ID:	case BCM43236_CHIP_ID:	case BCM43238_CHIP_ID:
5616	case BCM43234_CHIP_ID: {
5617		uint8 strap = (sih->chipst & CST43236_OTP_SEL_MASK) >>
5618			CST43236_OTP_SEL_SHIFT;
5619		return ((strap >= ARRAYSIZE(cis_43236_sel)) ?  CIS_DEFAULT : cis_43236_sel[strap]);
5620	}
5621
5622	case BCM4329_CHIP_ID:
5623		return ((sih->chipst & CST4329_SPROM_OTP_SEL_MASK) >= ARRAYSIZE(cis_sel)) ?
5624		        CIS_DEFAULT : cis_sel[(sih->chipst & CST4329_SPROM_OTP_SEL_MASK)];
5625
5626	case BCM4315_CHIP_ID:
5627
5628		return ((sih->chipst & CST4315_SPROM_OTP_SEL_MASK) >= ARRAYSIZE(cis_sel)) ?
5629		        CIS_DEFAULT : cis_sel[(sih->chipst & CST4315_SPROM_OTP_SEL_MASK)];
5630
5631	case BCM4319_CHIP_ID: {
5632		uint cis_sel4319 = ((sih->chipst & CST4319_SPROM_OTP_SEL_MASK) >>
5633		                    CST4319_SPROM_OTP_SEL_SHIFT);
5634		return (cis_sel4319 >= ARRAYSIZE(cis_sel)) ? CIS_DEFAULT : cis_sel[cis_sel4319];
5635	}
5636	case BCM4336_CHIP_ID:
5637	case BCM43362_CHIP_ID: {
5638		if (sih->chipst & CST4336_SPROM_PRESENT)
5639			return CIS_SROM;
5640		if (sih->chipst & CST4336_OTP_PRESENT)
5641			return CIS_OTP;
5642		return CIS_DEFAULT;
5643	}
5644	case BCM4330_CHIP_ID: {
5645		if (sih->chipst & CST4330_SPROM_PRESENT)
5646			return CIS_SROM;
5647		if (sih->chipst & CST4330_OTP_PRESENT)
5648			return CIS_OTP;
5649		return CIS_DEFAULT;
5650	}
5651	case BCM43239_CHIP_ID: {
5652		if ((sih->chipst & CST43239_SPROM_MASK) && !(sih->chipst & CST43239_SFLASH_MASK))
5653			return CIS_SROM;
5654		return CIS_OTP;
5655	}
5656	case BCM4324_CHIP_ID:
5657	{
5658		if ((sih->chipst & CST4324_SPROM_MASK) && !(sih->chipst & CST4324_SFLASH_MASK))
5659			return CIS_SROM;
5660		return CIS_OTP;
5661	}
5662	case BCM4335_CHIP_ID:
5663	{
5664		if ((sih->chipst & CST4335_SPROM_MASK) && !(sih->chipst & CST4335_SFLASH_MASK))
5665			return CIS_SROM;
5666		return CIS_OTP;
5667	}
5668	case BCM4350_CHIP_ID:
5669	{
5670		if (sih->chipst & CST4350_SPROM_PRESENT)
5671			return CIS_SROM;
5672		return CIS_OTP;
5673	}
5674	case BCM43237_CHIP_ID: {
5675		uint8 strap = (sih->chipst & CST43237_OTP_SEL_MASK) >>
5676			CST43237_OTP_SEL_SHIFT;
5677		return ((strap >= ARRAYSIZE(cis_43236_sel)) ?  CIS_DEFAULT : cis_43236_sel[strap]);
5678	}
5679	case BCM43143_CHIP_ID: {
5680		return CIS_OTP; /* BCM43143 does not support SROM nor OTP strappings */
5681	}
5682	case BCM43242_CHIP_ID:
5683	case BCM43243_CHIP_ID:
5684	{
5685		return CIS_OTP; /* BCM43242 does not support SPROM */
5686	}
5687	case BCM4360_CHIP_ID:
5688	case BCM43460_CHIP_ID:
5689	case BCM4352_CHIP_ID:
5690	case BCM43526_CHIP_ID: {
5691		if ((sih->chipst & CST4360_OTP_ENABLED))
5692			return CIS_OTP;
5693		return CIS_DEFAULT;
5694	}
5695	default:
5696		return CIS_DEFAULT;
5697	}
5698}
5699
5700/** Read/write to OTP to find the FAB manf */
5701int
5702BCMINITFN(si_otp_fabid)(si_t *sih, uint16 *fabid, bool rw)
5703{
5704	int error = BCME_OK;
5705	uint offset = 0;
5706	uint16 data, mask = 0, shift = 0;
5707
5708	switch (CHIPID(sih->chip)) {
5709	case BCM4329_CHIP_ID:
5710		/* Bit locations 133-130 */
5711		if (sih->chiprev >= 3) {
5712			offset = 8;
5713			mask = 0x3c;
5714			shift = 2;
5715		}
5716		break;
5717	case BCM43362_CHIP_ID:
5718		/* Bit locations 134-130 */
5719		offset = 8;
5720		mask = 0x7c;
5721		shift = 2;
5722		break;
5723	case BCM5356_CHIP_ID:
5724		/* Bit locations 133-130 */
5725		offset = 8;
5726		mask = 0x3c;
5727		shift = 2;
5728		break;
5729	default:
5730		error = BCME_EPERM;
5731		return error;
5732	}
5733
5734	if (rw == TRUE) {
5735		/* TRUE --> read */
5736		error = otp_read_word(sih, offset, &data);
5737		if (!error)
5738			*fabid = (data & mask) >> shift;
5739	} else {
5740		data = *fabid;
5741		data = (data << shift) & mask;
5742#ifdef BCMNVRAMW
5743		error = otp_write_word(sih, offset, data);
5744#endif /* BCMNVRAMW */
5745	}
5746
5747	return error;
5748}
5749
5750uint16 BCMATTACHFN(si_fabid)(si_t *sih)
5751{
5752	uint32 data;
5753	uint16 fabid = 0;
5754
5755	switch (CHIPID(sih->chip)) {
5756		case BCM4329_CHIP_ID:
5757		case BCM43362_CHIP_ID:
5758		case BCM5356_CHIP_ID:
5759			if (si_otp_fabid(sih, &fabid, TRUE) != BCME_OK)
5760			{
5761				SI_ERROR(("si_fabid: reading fabid from otp failed.\n"));
5762			}
5763			break;
5764
5765		case BCM4330_CHIP_ID:
5766			data = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol),
5767				0, 0);
5768			fabid = ((data & 0xc0000000) >> 30)+((data & 0x20000000) >> 27);
5769			break;
5770
5771		case BCM4334_CHIP_ID:
5772			data = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, fabid),	0, 0);
5773			fabid = data & 0xf;
5774			break;
5775
5776		case BCM4324_CHIP_ID:
5777		case BCM4335_CHIP_ID:
5778		case BCM4350_CHIP_ID:
5779		case BCM43143_CHIP_ID:
5780		case BCM43242_CHIP_ID:
5781		case BCM43243_CHIP_ID:
5782			/* intentional fallthrough */
5783			data = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, fabid),	0, 0);
5784			fabid = data & 0xf;
5785			break;
5786
5787		default:
5788			break;
5789	}
5790
5791	return fabid;
5792}
5793
5794uint32 BCMATTACHFN(si_get_sromctl)(si_t *sih)
5795{
5796	chipcregs_t *cc;
5797	uint origidx;
5798	uint32 sromctl;
5799	osl_t *osh;
5800
5801	osh = si_osh(sih);
5802	origidx = si_coreidx(sih);
5803	cc = si_setcoreidx(sih, SI_CC_IDX);
5804	ASSERT((uintptr)cc);
5805
5806	sromctl = R_REG(osh, &cc->sromcontrol);
5807
5808	/* return to the original core */
5809	si_setcoreidx(sih, origidx);
5810	return sromctl;
5811}
5812
5813int BCMATTACHFN(si_set_sromctl)(si_t *sih, uint32 value)
5814{
5815	chipcregs_t *cc;
5816	uint origidx;
5817	osl_t *osh;
5818
5819	osh = si_osh(sih);
5820	origidx = si_coreidx(sih);
5821	cc = si_setcoreidx(sih, SI_CC_IDX);
5822	ASSERT((uintptr)cc);
5823
5824	/* get chipcommon rev */
5825	if (si_corerev(sih) < 32)
5826		return BCME_UNSUPPORTED;
5827
5828	W_REG(osh, &cc->sromcontrol, value);
5829
5830	/* return to the original core */
5831	si_setcoreidx(sih, origidx);
5832	return BCME_OK;
5833
5834}
5835
5836uint
5837si_core_wrapperreg(si_t *sih, uint32 coreidx, uint32 offset, uint32 mask, uint32 val)
5838{
5839	uint origidx;
5840	uint ret_val;
5841
5842	origidx = si_coreidx(sih);
5843
5844	si_setcoreidx(sih, coreidx);
5845
5846	ret_val = si_wrapperreg(sih, offset, mask, val);
5847
5848	/* return to the original core */
5849	si_setcoreidx(sih, origidx);
5850	return ret_val;
5851}
5852
5853#ifdef WLC_LOW
5854/**
5855 * To make sure that, res mask is minimal to save power and also, to indicate
5856 * specifically for 4335 host about the SR logic.
5857 */
5858void
5859si_update_masks(si_t *sih)
5860{
5861	si_info_t *sii = SI_INFO(sih);
5862
5863	switch (CHIPID(sih->chip)) {
5864	case BCM4350_CHIP_ID:
5865		if (PMUCTL_ENAB(sih))
5866			si_pmu_res_minmax_update(sih, sii->osh);
5867		break;
5868	case BCM4335_CHIP_ID: {
5869#if defined(SAVERESTORE)
5870		if (PMUCTL_ENAB(sih))
5871			si_pmu_res_minmax_update(sih, sii->osh);
5872#endif
5873#if defined(PMU_OPT)
5874		/* set max res mask */
5875		si_ccreg(sih, MAXRESMASKREG, ~0, 0x7fff3fff);
5876
5877		/* Moved from ucode to driver for 4335 */
5878		si_ccreg(sih, PMUREG_RESREQ_MASK, ~0, 0x7ffb3e77);
5879#else
5880		si_ccreg(sih, PMUREG_RESREQ_MASK, ~0, 0x7ffbfff);
5881#endif
5882		/* set_sdio_aos_wakeup_mask */
5883		si_pmu_chipcontrol(sih, CHIPCTRLREG2, 0x01000000, 0x01000000);
5884
5885		/* Enable BBPLL power down */
5886		si_pmu_chipcontrol(sih, CHIPCTRLREG1, 0x10, 0x10);
5887
5888		/* BBPLL closed loop lock time = 1 (default=4) */
5889		si_pmu_chipcontrol(sih, CHIPCTRLREG1, 0xf0000, 0x10000);
5890#if defined(PMU_OPT)
5891#if defined(USE_MEMLPLDO)
5892		/* Set MEMLPDO=0.88125V (bits 20:18=0x7) */
5893		si_pmu_regcontrol(sih, REGCTRLREG4, 0x1c0000, 0x1c0000);
5894#endif
5895		/* Disable BBPLL openloop mode */
5896		si_pmu_chipcontrol(sih, CHIPCTRLREG1, 0x80, 0x0);
5897
5898		/* 0 LQ clks with pmu-mem-disable-for-sleep */
5899		si_pmu_chipcontrol(sih, CHIPCTRLREG5, 0x1f00, 0x0);
5900
5901		/* Enable pmu-mem-disable-for-sleep */
5902		si_pmu_chipcontrol(sih, CHIPCTRLREG5, 0x2000, 0x2000);
5903#if defined(PMU_OPT_REV6)
5904		if ((CHIPREV(sih->chiprev) >= 2)) {
5905			/* mac_res_req_mask for rev6 */
5906			si_ccreg(sih, PMUREG_RESREQ_MASK, ~0, 0x7ffb3647);
5907
5908			/* Make all "higher" clock requests, request for "lower" clocks also.
5909			 * Like HT_AVAIL/MAC_CLK/PHY_CLK etc requests (all "higher" than ALP_AVAIL)
5910			 * also requests for ALP_AVAIL (bits 22:20=0x7)
5911			 */
5912			si_pmu_chipcontrol(sih, CHIPCTRLREG6, (0x7 << 20), (0x7 << 20));
5913
5914			/* Set HQRequired to avoid using LQ clocks (bit 24=0x1) */
5915			si_pmu_chipcontrol(sih, CHIPCTRLREG6, (1 << 24), (1 << 24));
5916
5917			/* Start clocks earlier */
5918			si_pmu_chipcontrol(sih, CHIPCTRLREG6, (1 << 18), (1 << 18));
5919		}
5920#endif /* defined(PMU_OPT_REV6) */
5921#endif /* defined(PMU_OPT) */
5922	} break;
5923	default:
5924		ASSERT(0);
5925	break;
5926	}
5927}
5928
5929void
5930si_force_islanding(si_t *sih, bool enable)
5931{
5932	switch (CHIPID(sih->chip)) {
5933	case BCM4335_CHIP_ID: {
5934		if (enable) {
5935			/* Turn on the islands */
5936			si_pmu_chipcontrol(sih, CHIPCTRLREG2, 0x1c0000, 0x0);
5937#if !defined(USE_MEMLPLDO)
5938			/* Force vddm pwrsw always on */
5939			si_pmu_chipcontrol(sih, CHIPCTRLREG2, 0x100000, 0x100000);
5940#endif
5941		} else {
5942			/* Turn off the islands */
5943			si_pmu_chipcontrol(sih, CHIPCTRLREG2, 0x3c0000, 0x3c0000);
5944		}
5945	} break;
5946	default:
5947		ASSERT(0);
5948	break;
5949	}
5950}
5951#endif /* WLC_LOW */
5952
5953/**
5954 * cleanup the hndrte timer from the host when ARM is been halted
5955 * without a chance for ARM cleanup its resources
5956 * If left not cleanup, Intr from a software timer can still
5957 * request HT clk when ARM is halted.
5958 */
5959uint32
5960si_pmu_res_req_timer_clr(si_t *sih)
5961{
5962	uint32 mask;
5963
5964	mask = PRRT_REQ_ACTIVE | PRRT_INTEN;
5965	if (CHIPID(sih->chip) != BCM4328_CHIP_ID)
5966		mask <<= 14;
5967	/* clear mask bits */
5968	si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, res_req_timer), mask, 0);
5969	/* readback to ensure write completes */
5970	return si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, res_req_timer), 0, 0);
5971}
5972
5973/** turn on/off rfldo */
5974void
5975si_pmu_rfldo(si_t *sih, bool on)
5976{
5977	switch (CHIPID(sih->chip)) {
5978	case BCM4360_CHIP_ID:
5979	case BCM4352_CHIP_ID:
5980	case BCM43526_CHIP_ID: {
5981		si_pmu_regcontrol(sih, 0, RCTRL4360_RFLDO_PWR_DOWN,
5982			on ? 0 : RCTRL4360_RFLDO_PWR_DOWN);
5983		break;
5984	}
5985	default:
5986		ASSERT(0);
5987	break;
5988	}
5989}
5990
5991uint
5992si_chipid_override(si_t *sih)
5993{
5994	uint chipid = 0;
5995	switch (CHIPID(sih->chip)) {
5996		case BCM4335_CHIP_ID:
5997			if (CHIPREV(sih->chip) == 2) {
5998				chipid = BCM4339_CHIP_ID;
5999			} else {
6000				chipid = sih->chip;
6001			}
6002			break;
6003		default:
6004			chipid = sih->chip;
6005			break;
6006	}
6007	return chipid;
6008}
6009
6010uint
6011si_chiprev_override(si_t *sih)
6012{
6013	uint chiprev = 0;
6014	switch (CHIPID(sih->chip)) {
6015		case BCM4335_CHIP_ID:
6016			if (CHIPREV(sih->chip) == 2) {
6017				chiprev = 1;
6018			} else {
6019				chiprev = sih->chiprev;
6020			}
6021			break;
6022		default:
6023			chiprev = sih->chiprev;
6024			break;
6025	}
6026	return chiprev;
6027}
6028
6029#ifdef SURVIVE_PERST_ENAB
6030static uint32
6031si_pcie_survive_perst(si_t *sih, uint32 mask, uint32 val)
6032{
6033	si_info_t *sii;
6034
6035	sii = SI_INFO(sih);
6036
6037	if (!PCIE(sii))
6038		return (0);
6039
6040	return pcie_survive_perst(sii->pch, mask, val);
6041}
6042
6043static void
6044si_watchdog_reset(si_t *sih)
6045{
6046	si_info_t *sii = SI_INFO(sih);
6047	chipcregs_t *cc;
6048	uint32 origidx, i;
6049
6050	origidx = si_coreidx(sih);
6051	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
6052	/* issue a watchdog reset */
6053	W_REG(sii->osh, &cc->pmuwatchdog, 2);
6054	/* do busy wait for 20ms */
6055	for (i = 0; i < 2000; i++) {
6056		OSL_DELAY(10);
6057	}
6058	si_setcoreidx(sih, origidx);
6059	BCM_REFERENCE(sii);
6060}
6061#endif /* SURVIVE_PERST_ENAB */
6062
6063void
6064si_survive_perst_war(si_t *sih, bool reset, uint32 sperst_mask, uint32 sperst_val)
6065{
6066#ifdef SURVIVE_PERST_ENAB
6067	if ((BUSTYPE(sih->bustype) != PCI_BUS) ||
6068	    ((CHIPID(sih->chip) != BCM4360_CHIP_ID) &&
6069	     (CHIPID(sih->chip) != BCM4352_CHIP_ID)))
6070		return;
6071	if (reset) {
6072		si_info_t *sii = SI_INFO(sih);
6073		uint32 bar0win, bar0win_after;
6074
6075		/* save the bar0win */
6076		bar0win = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
6077
6078		si_watchdog_reset(sih);
6079
6080		bar0win_after = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
6081		if (bar0win_after != bar0win) {
6082			SI_ERROR(("%s: bar0win before %08x, bar0win after %08x\n",
6083				__FUNCTION__, bar0win, bar0win_after));
6084			OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), bar0win);
6085		}
6086	}
6087	if (sperst_mask) {
6088		/* enable survive perst */
6089		si_pcie_survive_perst(sih, sperst_mask, sperst_val);
6090	}
6091#endif /* SURVIVE_PERST_ENAB */
6092}
6093
6094void
6095si_pcie_ltr_war(si_t *sih)
6096{
6097	if (BUSTYPE(sih->bustype) == PCI_BUS) {
6098		if ((sih->buscoretype == PCIE2_CORE_ID) &&
6099		(sih->buscorerev == 1)) {
6100			if (!si_pcieltrenable(sih, 0, 0)) {
6101				uint origidx = si_coreidx(sih);
6102				si_setcore(sih, D11_CORE_ID, 0);
6103
6104				si_wrapperreg(sih, AI_OOBSELOUTD30, ~0, 0x2848180);
6105				si_wrapperreg(sih, AI_OOBSELOUTD74, ~0, 0x3);
6106
6107				si_setcoreidx(sih, origidx);
6108			} else {
6109				uint origidx = si_coreidx(sih);
6110				si_setcore(sih, D11_CORE_ID, 0);
6111
6112				si_wrapperreg(sih, AI_OOBSELOUTD30, ~0, 0x02838280);
6113				si_wrapperreg(sih, AI_OOBSELOUTD74, ~0, 0x3);
6114
6115				si_setcoreidx(sih, origidx);
6116			}
6117		}
6118	}
6119}
6120
6121#ifdef WLC_LOW
6122uint
6123si_corereg_ifup(si_t *sih, uint core_id, uint regoff, uint mask, uint val)
6124{
6125	bool isup;
6126	void *regs;
6127	uint origidx, ret_val, coreidx;
6128
6129	/* Remember original core before switch to chipc */
6130	origidx = si_coreidx(sih);
6131	regs = si_setcore(sih, core_id, 0);
6132	ASSERT(regs != NULL);
6133
6134	coreidx = si_coreidx(sih);
6135
6136	isup = si_iscoreup(sih);
6137	if (isup == TRUE) {
6138		ret_val = si_corereg(sih, coreidx, regoff, mask, val);
6139	} else {
6140		ret_val = 0;
6141	}
6142
6143	/* Return to original core */
6144	si_setcoreidx(sih, origidx);
6145	return ret_val;
6146}
6147
6148void
6149si_lowpwr_opt(si_t *sih)
6150{
6151	uint hosti = 0;
6152	uint origidx, mask, val;
6153	void *regs;
6154
6155	/* 4335 chip (all revision) related changes */
6156	if (CHIPID(sih->chip) == BCM4335_CHIP_ID) {
6157
6158		/* Remember original core before switch to new core */
6159		origidx = si_coreidx(sih);
6160
6161		/* Find the current host interface */
6162		if (CST4335_CHIPMODE_USB20D(sih->chipst))
6163			hosti = CHIP_HOSTIF_USBMODE;
6164		else if (CST4335_CHIPMODE_SDIOD(sih->chipst))
6165			hosti = CHIP_HOSTIF_SDIOMODE;
6166		else if (CST4335_CHIPMODE_PCIE(sih->chipst))
6167			hosti = CHIP_HOSTIF_PCIEMODE;
6168
6169		regs = si_setcore(sih, CC_CORE_ID, 0);
6170		ASSERT(regs != NULL);
6171		/* disable usb app clk */
6172		/* Can be done any time. If it is not USB, then do it. In case */
6173		/* of USB, do not write it */
6174		if (hosti != CHIP_HOSTIF_USBMODE) {
6175			si_pmu_chipcontrol(sih, PMU_CHIPCTL5, (1 << USBAPP_CLK_BIT), 0);
6176		}
6177		/* disable pcie clks */
6178		if (hosti != CHIP_HOSTIF_PCIEMODE) {
6179			si_pmu_chipcontrol(sih, PMU_CHIPCTL5, (1 << PCIE_CLK_BIT), 0);
6180		}
6181
6182		/* disable armcr4 debug clk */
6183		/* Can be done anytime as long as driver is functional. */
6184		/* In TCL, dhalt commands needs to change to undo this */
6185		si_pmu_chipcontrol(sih, PMU_CHIPCTL5, (1 << ARMCR4_DBG_CLK_BIT), 0);
6186		/* Power down unused BBPLL ch-6(pcie_tl_clk) and ch-5(sample-sync-clk), */
6187		/* valid in all modes, ch-5 needs to be reenabled for sample-capture */
6188		/* this needs to be done in the pmu init path, at the beginning. Should not be */
6189		/* a pcie driver. Enable the sample-sync-clk in the sample capture function */
6190		mask = (0x1 << SAMPLE_SYNC_CLK_BIT) | (0x1 << PCIE_TL_CLK_BIT);
6191		val = (0x1 << SAMPLE_SYNC_CLK_BIT) | (0x1 << PCIE_TL_CLK_BIT);
6192		si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL0, mask, val);
6193		si_pmu_pllupd(sih);
6194
6195		/* 4335C0 specific changes */
6196		if (CHIPREV(sih->chiprev) >= 2) {
6197			/* Enable mem clk gating */
6198			mask = (0x1 << MEM_CLK_GATE_BIT);
6199			val = (0x1 << MEM_CLK_GATE_BIT);
6200
6201			/* d11 core neets to be out of reset */
6202			si_corereg_ifup(sih, D11_CORE_ID, SI_PWR_CTL_ST, mask, val);
6203
6204#if defined(__ARM_ARCH_7R__)
6205			/* ARM needs to be out of reset. It is, if driver is running */
6206			si_corereg_ifup(sih, ARMCR4_CORE_ID, SI_PWR_CTL_ST, mask, val);
6207#endif	/* __ARM_ARCH_7R__ */
6208
6209			/* SDIO needs to be out of reset. In the wl up path, check if SDIO is up, */
6210			/* only then do the register write */
6211			si_corereg_ifup(sih, SDIOD_CORE_ID, SI_PWR_CTL_ST, mask, val);
6212
6213			/* enable clk gating for usb20d core */
6214			si_corereg_ifup(sih, USB20D_CORE_ID, SI_PWR_CTL_ST, mask, val);
6215
6216			/* enable clk gating for pciegen2 core */
6217			si_corereg_ifup(sih, PCIE2_CORE_ID, SI_PWR_CTL_ST, mask, val);
6218
6219			/* enable gci_clk gating */
6220			/* GCI is always up. Can be done any time. */
6221			mask = (0x1<< GCI_CLK_GATE_BIT);
6222			val = 0;
6223			si_corereg_ifup(sih, CC_CORE_ID, 0xc0c, mask, val);
6224
6225			/* Set HQRequired */
6226			/* This can be done anytime */
6227			mask = (0x1 << HQ_REQ_BIT);
6228			val = (0x1 << HQ_REQ_BIT);
6229			si_pmu_chipcontrol(sih, PMU_CHIPCTL6, mask, val);
6230
6231			/* Disable PLL div2 outputs, valid in all modes */
6232			/* make sure AVB clk in mac is not used, lq_clk is not used */
6233			/* (set HQRequired) */
6234			/* Initialize the tcl, load the driver, do "checkclk ccs all" in tcl. */
6235			/* if AVB request is zero, then this bit can be set statically */
6236			/* in the driver */
6237			si_pmu_chipcontrol(sih, PMU_CHIPCTL6, PLL_DIV2_MASK, PLL_DIV2_DIS_OP);
6238		}
6239
6240		/* Return to original core */
6241		si_setcoreidx(sih, origidx);
6242	}
6243}
6244#endif /* WLC_LOW */
6245
6246#if defined(WLTEST)
6247/* access internal jtag user reg */
6248#define JTAGM_RETRIES	        10000 /* # of retries for Jtag master */
6249#define	LV_IR_SIZE		32
6250#define	LV_DR_SIZE		32
6251#define	LV_BASE			0xfe03ff3a
6252#define	LV_REG_MASK		0x01f00000
6253#define	LV_REG_SHIFT		20
6254#define LV_RO			0x00080000
6255#define	LV_USER_BASE		0x10
6256#define LV_REG_IR(reg, base)    (base | (((reg) << LV_REG_SHIFT) & LV_REG_MASK))
6257
6258static uint32
6259jtagm_rreg(osl_t *osh, chipcregs_t *cc, uint reg)
6260{
6261	switch (reg) {
6262	case CC_JTAGCMD:
6263		return R_REG(osh, &cc->jtagcmd);
6264	case CC_JTAGIR:
6265		return R_REG(osh, &cc->jtagir);
6266	case CC_JTAGDR:
6267		return R_REG(osh, &cc->jtagdr);
6268	case CC_JTAGCTRL:
6269		return R_REG(osh, &cc->jtagctrl);
6270	default:
6271		return 0;
6272	}
6273	return 0;
6274}
6275
6276static void
6277jtagm_wreg(osl_t *osh, chipcregs_t *cc, uint reg, uint32 data)
6278{
6279	switch (reg) {
6280	case CC_JTAGCMD:
6281		W_REG(osh, &cc->jtagcmd, data);
6282		break;
6283	case CC_JTAGIR:
6284		W_REG(osh, &cc->jtagir, data);
6285		break;
6286	case CC_JTAGDR:
6287		W_REG(osh, &cc->jtagdr, data);
6288		break;
6289	case CC_JTAGCTRL:
6290		W_REG(osh, &cc->jtagctrl, data);
6291		break;
6292	default:
6293		return;
6294	}
6295}
6296
6297static uint
6298jtagm_scmd(si_t *sih, uint ir, uint irw, uint dr, uint drw)
6299{
6300	uint32 data, i;
6301	chipcregs_t *cc;
6302	uint origidx;
6303	osl_t *osh;
6304
6305	osh = si_osh(sih);
6306	origidx = si_coreidx(sih);
6307	cc = si_setcoreidx(sih, SI_CC_IDX);
6308	ASSERT((uintptr)cc);
6309
6310	data = jtagm_rreg(osh, cc, CC_JTAGCTRL);
6311	data &= ~JCTRL_EXT_EN;	/* ExternalEnable, clear it to access internal TAP */
6312	data |= JCTRL_EN;	/* JtagEnable (JE) */
6313	jtagm_wreg(osh, cc, CC_JTAGCTRL, data);
6314
6315	jtagm_wreg(osh, cc, CC_JTAGIR, ir);
6316	jtagm_wreg(osh, cc, CC_JTAGDR, dr);
6317	jtagm_wreg(osh, cc, CC_JTAGCMD,
6318		(JCMD_START | JCMD_ACC_IRDR | ((irw - 1) << JCMD_IRW_SHIFT) | (drw - 1)));
6319
6320	i = 0;
6321	while ((i < JTAGM_RETRIES) &&
6322	       ((jtagm_rreg(osh, cc, CC_JTAGCMD) & JCMD_BUSY) == JCMD_BUSY)) {
6323		OSL_DELAY(1);
6324		i++;
6325	}
6326
6327	if (i == JTAGM_RETRIES) {
6328		data = 0xffffffff;
6329		ASSERT(0);
6330	}
6331	else
6332		data = jtagm_rreg(osh, cc, CC_JTAGDR);
6333
6334	/* return to the original core */
6335	si_setcoreidx(sih, origidx);
6336
6337	return data;
6338}
6339
6340uint
6341si_jtag_ureg_read(si_t *sih, uint num)
6342{
6343	SI_MSG(("si_jtag_ureg_read %d\n", num));
6344	return jtagm_scmd(sih, LV_REG_IR(LV_USER_BASE + num, LV_BASE) | LV_RO, 32, 0, 32);
6345}
6346
6347void
6348si_jtag_ureg_write(si_t *sih, uint num, uint data)
6349{
6350	SI_MSG(("si_jtag_ureg_write %d %08x\n", num, data));
6351	jtagm_scmd(sih, LV_REG_IR(LV_USER_BASE + num, LV_BASE), 32, data, 32);
6352}
6353#endif
6354
6355#ifdef BBPLL_WAR
6356uint
6357si_bbpll_war(si_t *sih, uint state)
6358{
6359	uint32 data;
6360
6361	if ((CHIPID(sih->chip) != BCM4360_CHIP_ID) || (CHIPREV(sih->chiprev) > 3))
6362		return 0;
6363
6364	/* if ovr bit is set, don't apply WAR */
6365	if ((si_jtag_ureg_read(sih, 3) & 0x00010000) != 0) {
6366		/* Check if PLL still Lock */
6367		/* ccreg 0x2c Bit[11] = 1  ; Assert if it is not */
6368		data = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipstatus), 0, 0);
6369		ASSERT(data & CST4360_BBPLL_LOCK);
6370
6371		/* set MaxRsrcMax */
6372		si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, max_res_mask), ~0, 0x1ff);
6373		/* Wait 200us . */
6374		OSL_DELAY(200);
6375		return 1;
6376	}
6377
6378	/* pll up seq on Up Path (state 0) and Down Path (state 1) */
6379	switch (state) {
6380	case 0:
6381		/* Write BBPLL Defaults (mdiv, ndiv, frac). */
6382		si_jtag_ureg_write(sih, 5, 0x06060c03);
6383		si_jtag_ureg_write(sih, 6, 0x16180606);
6384		si_jtag_ureg_write(sih, 7, 0x0000100e);
6385		ASSERT(si_jtag_ureg_read(sih, 5) == 0x06060c03);
6386		ASSERT(si_jtag_ureg_read(sih, 6) == 0x16180606);
6387		ASSERT(si_jtag_ureg_read(sih, 7) == 0x0000100e);
6388
6389		/* bbpll_pwrdn 1 , areset 1, dreset 1, ovr 0 */
6390		si_jtag_ureg_write(sih, 3, 0x000c0010);
6391		ASSERT(si_jtag_ureg_read(sih, 3) == 0x000c0010);
6392
6393		/* bbpll_pwrdn 1 , areset 1, dreset 1, ovr 1 */
6394		si_jtag_ureg_write(sih, 3, 0x000d0010);
6395		ASSERT(si_jtag_ureg_read(sih, 3) == 0x000d0010);
6396
6397		/* bbpll_pwrdn 0, areset 1, dreset 1 , ovr 1 */
6398		si_jtag_ureg_write(sih, 3, 0x000d0000);
6399		ASSERT(si_jtag_ureg_read(sih, 3) == 0x000d0000);
6400
6401		/* Wait 30us */
6402		OSL_DELAY(30);
6403
6404		/* bbpll_pwrdn 0, areset 0, dreset 1 , ovr 1 */
6405		si_jtag_ureg_write(sih, 3, 0x00090000);
6406		ASSERT(si_jtag_ureg_read(sih, 3) == 0x00090000);
6407
6408		/* Wait 100 us */
6409		OSL_DELAY(100);
6410
6411		/* Check if PLL Lock */
6412		/* ccreg 0x2c  Bit[11] = 1  ; Assert if it is not */
6413		data = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipstatus), 0, 0);
6414		ASSERT(data & CST4360_BBPLL_LOCK);
6415
6416		/* take out of dreset; bbpll_pwrdn 0, areset 0, dreset 0 , ovr 1 */
6417		si_jtag_ureg_write(sih, 3, 0x00010000);
6418		ASSERT(si_jtag_ureg_read(sih, 3) == 0x00010000);
6419
6420		/* set MaxRsrcMax */
6421		si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, max_res_mask), ~0, 0x1ff);
6422
6423		/* Wait 200us . */
6424		OSL_DELAY(200);
6425		break;
6426	case 1:
6427		si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, min_res_mask), ~0, 0x13b);
6428		break;
6429	default:
6430		ASSERT(0);
6431	}
6432	return 1;
6433}
6434#endif /* BBPLL_WAR */
6435