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