PageRenderTime 92ms CodeModel.GetById 24ms app.highlight 59ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/net/wireless/bcmdhd_29/siutils.c

https://bitbucket.org/cyanogenmod/android_kernel_asus_tf300t
C | 1915 lines | 1416 code | 320 blank | 179 comment | 508 complexity | 0a496f5b2db014c90a6f25eba2e494e8 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
   1/*
   2 * Misc utility routines for accessing chip-specific features
   3 * of the SiliconBackplane-based Broadcom chips.
   4 *
   5 * Copyright (C) 1999-2011, Broadcom Corporation
   6 * 
   7 *         Unless you and Broadcom execute a separate written software license
   8 * agreement governing use of this software, this software is licensed to you
   9 * under the terms of the GNU General Public License version 2 (the "GPL"),
  10 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
  11 * following added to such license:
  12 * 
  13 *      As a special exception, the copyright holders of this software give you
  14 * permission to link this software with independent modules, and to copy and
  15 * distribute the resulting executable under terms of your choice, provided that
  16 * you also meet, for each linked independent module, the terms and conditions of
  17 * the license of that module.  An independent module is a module which is not
  18 * derived from this software.  The special exception does not apply to any
  19 * modifications of the software.
  20 * 
  21 *      Notwithstanding the above, under no circumstances may you combine this
  22 * software in any way with any other Broadcom software provided under a license
  23 * other than the GPL, without Broadcom's express prior written consent.
  24 *
  25 * $Id: siutils.c,v 1.813.2.36 2011-02-10 23:43:55 $
  26 */
  27
  28#include <typedefs.h>
  29#include <bcmdefs.h>
  30#include <osl.h>
  31#include <bcmutils.h>
  32#include <siutils.h>
  33#include <bcmdevs.h>
  34#include <hndsoc.h>
  35#include <sbchipc.h>
  36#include <pcicfg.h>
  37#include <sbpcmcia.h>
  38#include <sbsocram.h>
  39#include <bcmsdh.h>
  40#include <sdio.h>
  41#include <sbsdio.h>
  42#include <sbhnddma.h>
  43#include <sbsdpcmdev.h>
  44#include <bcmsdpcm.h>
  45#include <hndpmu.h>
  46
  47#include "siutils_priv.h"
  48
  49/* local prototypes */
  50static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
  51                              uint bustype, void *sdh, char **vars, uint *varsz);
  52static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh);
  53static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
  54	uint *origidx, void *regs);
  55
  56
  57/* global variable to indicate reservation/release of gpio's */
  58static uint32 si_gpioreservation = 0;
  59
  60/* global flag to prevent shared resources from being initialized multiple times in si_attach() */
  61
  62/*
  63 * Allocate a si handle.
  64 * devid - pci device id (used to determine chip#)
  65 * osh - opaque OS handle
  66 * regs - virtual address of initial core registers
  67 * bustype - pci/pcmcia/sb/sdio/etc
  68 * vars - pointer to a pointer area for "environment" variables
  69 * varsz - pointer to int to return the size of the vars
  70 */
  71si_t *
  72si_attach(uint devid, osl_t *osh, void *regs,
  73                       uint bustype, void *sdh, char **vars, uint *varsz)
  74{
  75	si_info_t *sii;
  76
  77	/* alloc si_info_t */
  78	if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) {
  79		SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
  80		return (NULL);
  81	}
  82
  83	if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) {
  84		MFREE(osh, sii, sizeof(si_info_t));
  85		return (NULL);
  86	}
  87	sii->vars = vars ? *vars : NULL;
  88	sii->varsz = varsz ? *varsz : 0;
  89
  90	return (si_t *)sii;
  91}
  92
  93/* global kernel resource */
  94static si_info_t ksii;
  95
  96static uint32	wd_msticks;		/* watchdog timer ticks normalized to ms */
  97
  98/* generic kernel variant of si_attach() */
  99si_t *
 100si_kattach(osl_t *osh)
 101{
 102	static bool ksii_attached = FALSE;
 103
 104	if (!ksii_attached) {
 105		void *regs;
 106		regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
 107
 108		if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs,
 109		                SI_BUS, NULL,
 110		                osh != SI_OSH ? &ksii.vars : NULL,
 111		                osh != SI_OSH ? &ksii.varsz : NULL) == NULL) {
 112			SI_ERROR(("si_kattach: si_doattach failed\n"));
 113			REG_UNMAP(regs);
 114			return NULL;
 115		}
 116		REG_UNMAP(regs);
 117
 118		/* save ticks normalized to ms for si_watchdog_ms() */
 119		if (PMUCTL_ENAB(&ksii.pub)) {
 120			/* based on 32KHz ILP clock */
 121			wd_msticks = 32;
 122		} else {
 123			wd_msticks = ALP_CLOCK / 1000;
 124		}
 125
 126		ksii_attached = TRUE;
 127		SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n",
 128		        ksii.pub.ccrev, wd_msticks));
 129	}
 130
 131	return &ksii.pub;
 132}
 133
 134
 135static bool
 136si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh)
 137{
 138	/* need to set memseg flag for CF card first before any sb registers access */
 139	if (BUSTYPE(bustype) == PCMCIA_BUS)
 140		sii->memseg = TRUE;
 141
 142
 143	if (BUSTYPE(bustype) == SDIO_BUS) {
 144		int err;
 145		uint8 clkset;
 146
 147		/* Try forcing SDIO core to do ALPAvail request only */
 148		clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
 149		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
 150		if (!err) {
 151			uint8 clkval;
 152
 153			/* If register supported, wait for ALPAvail and then force ALP */
 154			clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, NULL);
 155			if ((clkval & ~SBSDIO_AVBITS) == clkset) {
 156				SPINWAIT(((clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
 157					SBSDIO_FUNC1_CHIPCLKCSR, NULL)), !SBSDIO_ALPAV(clkval)),
 158					PMU_MAX_TRANSITION_DLY);
 159				if (!SBSDIO_ALPAV(clkval)) {
 160					SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n",
 161						clkval));
 162					return FALSE;
 163				}
 164				clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
 165				bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
 166					clkset, &err);
 167				OSL_DELAY(65);
 168			}
 169		}
 170
 171		/* Also, disable the extra SDIO pull-ups */
 172		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
 173	}
 174
 175
 176	return TRUE;
 177}
 178
 179static bool
 180si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
 181	uint *origidx, void *regs)
 182{
 183	bool pci, pcie;
 184	uint i;
 185	uint pciidx, pcieidx, pcirev, pcierev;
 186
 187	cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
 188	ASSERT((uintptr)cc);
 189
 190	/* get chipcommon rev */
 191	sii->pub.ccrev = (int)si_corerev(&sii->pub);
 192
 193	/* get chipcommon chipstatus */
 194	if (sii->pub.ccrev >= 11)
 195		sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
 196
 197	/* get chipcommon capabilites */
 198	sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
 199	/* get chipcommon extended capabilities */
 200
 201	if (sii->pub.ccrev >= 35)
 202		sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
 203
 204	/* get pmu rev and caps */
 205	if (sii->pub.cccaps & CC_CAP_PMU) {
 206		sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
 207		sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
 208	}
 209
 210	SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
 211		sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev,
 212		sii->pub.pmucaps));
 213
 214	/* figure out bus/orignal core idx */
 215	sii->pub.buscoretype = NODEV_CORE_ID;
 216	sii->pub.buscorerev = (uint)NOREV;
 217	sii->pub.buscoreidx = BADIDX;
 218
 219	pci = pcie = FALSE;
 220	pcirev = pcierev = (uint)NOREV;
 221	pciidx = pcieidx = BADIDX;
 222
 223	for (i = 0; i < sii->numcores; i++) {
 224		uint cid, crev;
 225
 226		si_setcoreidx(&sii->pub, i);
 227		cid = si_coreid(&sii->pub);
 228		crev = si_corerev(&sii->pub);
 229
 230		/* Display cores found */
 231		SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
 232		        i, cid, crev, sii->coresba[i], sii->regs[i]));
 233
 234		if (BUSTYPE(bustype) == PCI_BUS) {
 235			if (cid == PCI_CORE_ID) {
 236				pciidx = i;
 237				pcirev = crev;
 238				pci = TRUE;
 239			} else if (cid == PCIE_CORE_ID) {
 240				pcieidx = i;
 241				pcierev = crev;
 242				pcie = TRUE;
 243			}
 244		} else if ((BUSTYPE(bustype) == PCMCIA_BUS) &&
 245		           (cid == PCMCIA_CORE_ID)) {
 246			sii->pub.buscorerev = crev;
 247			sii->pub.buscoretype = cid;
 248			sii->pub.buscoreidx = i;
 249		}
 250		else if (((BUSTYPE(bustype) == SDIO_BUS) ||
 251		          (BUSTYPE(bustype) == SPI_BUS)) &&
 252		         ((cid == PCMCIA_CORE_ID) ||
 253		          (cid == SDIOD_CORE_ID))) {
 254			sii->pub.buscorerev = crev;
 255			sii->pub.buscoretype = cid;
 256			sii->pub.buscoreidx = i;
 257		}
 258
 259		/* find the core idx before entering this func. */
 260		if ((savewin && (savewin == sii->coresba[i])) ||
 261		    (regs == sii->regs[i]))
 262			*origidx = i;
 263	}
 264
 265	if (pci) {
 266		sii->pub.buscoretype = PCI_CORE_ID;
 267		sii->pub.buscorerev = pcirev;
 268		sii->pub.buscoreidx = pciidx;
 269	} else if (pcie) {
 270		sii->pub.buscoretype = PCIE_CORE_ID;
 271		sii->pub.buscorerev = pcierev;
 272		sii->pub.buscoreidx = pcieidx;
 273	}
 274
 275	SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype,
 276	         sii->pub.buscorerev));
 277
 278	if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) &&
 279	    (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (CHIPREV(sii->pub.chiprev) <= 3))
 280		OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL);
 281
 282
 283	/* Make sure any on-chip ARM is off (in case strapping is wrong), or downloaded code was
 284	 * already running.
 285	 */
 286	if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) {
 287		if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) ||
 288		    si_setcore(&sii->pub, ARMCM3_CORE_ID, 0))
 289			si_core_disable(&sii->pub, 0);
 290	}
 291
 292	/* return to the original core */
 293	si_setcoreidx(&sii->pub, *origidx);
 294
 295	return TRUE;
 296}
 297
 298
 299
 300static si_info_t *
 301si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
 302                       uint bustype, void *sdh, char **vars, uint *varsz)
 303{
 304	struct si_pub *sih = &sii->pub;
 305	uint32 w, savewin;
 306	chipcregs_t *cc;
 307	char *pvars = NULL;
 308	uint origidx;
 309
 310	ASSERT(GOODREGS(regs));
 311
 312	bzero((uchar*)sii, sizeof(si_info_t));
 313
 314	savewin = 0;
 315
 316	sih->buscoreidx = BADIDX;
 317
 318	sii->curmap = regs;
 319	sii->sdh = sdh;
 320	sii->osh = osh;
 321
 322
 323
 324	/* find Chipcommon address */
 325	if (bustype == PCI_BUS) {
 326		savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
 327		if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
 328			savewin = SI_ENUM_BASE;
 329		OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE);
 330		cc = (chipcregs_t *)regs;
 331	} else if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) {
 332		cc = (chipcregs_t *)sii->curmap;
 333	} else {
 334		cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
 335	}
 336
 337	sih->bustype = bustype;
 338	if (bustype != BUSTYPE(bustype)) {
 339		SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n",
 340			bustype, BUSTYPE(bustype)));
 341		return NULL;
 342	}
 343
 344	/* bus/core/clk setup for register access */
 345	if (!si_buscore_prep(sii, bustype, devid, sdh)) {
 346		SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype));
 347		return NULL;
 348	}
 349
 350	/* ChipID recognition.
 351	 *   We assume we can read chipid at offset 0 from the regs arg.
 352	 *   If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
 353	 *   some way of recognizing them needs to be added here.
 354	 */
 355	w = R_REG(osh, &cc->chipid);
 356	sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
 357	/* Might as wll fill in chip id rev & pkg */
 358	sih->chip = w & CID_ID_MASK;
 359	sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
 360	sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
 361	if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK)
 362		>> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT |
 363		CST4322_SPROM_PRESENT))) {
 364		SI_ERROR(("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__));
 365		return NULL;
 366	}
 367
 368#if defined(HW_OOB)
 369	if (CHIPID(sih->chip) == BCM43362_CHIP_ID) {
 370		uint32 gpiocontrol, addr;
 371		addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, gpiocontrol);
 372		gpiocontrol = bcmsdh_reg_read(sdh, addr, 4);
 373		gpiocontrol |= 0x2;
 374		bcmsdh_reg_write(sdh, addr, 4, gpiocontrol);
 375		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10005, 0xf, NULL);
 376		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10006, 0x0, NULL);
 377		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10007, 0x2, NULL);
 378	}
 379#endif
 380
 381	if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) &&
 382		(sih->chippkg != BCM4329_289PIN_PKG_ID)) {
 383		sih->chippkg = BCM4329_182PIN_PKG_ID;
 384	}
 385
 386	sih->issim = IS_SIM(sih->chippkg);
 387
 388	/* scan for cores */
 389	if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) {
 390		SI_MSG(("Found chip type SB (0x%08x)\n", w));
 391		sb_scan(&sii->pub, regs, devid);
 392	} else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) {
 393		SI_MSG(("Found chip type AI (0x%08x)\n", w));
 394		/* pass chipc address instead of original core base */
 395		ai_scan(&sii->pub, (void *)(uintptr)cc, devid);
 396	} else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
 397		SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip));
 398		/* pass chipc address instead of original core base */
 399		ub_scan(&sii->pub, (void *)(uintptr)cc, devid);
 400	} else {
 401		SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
 402		return NULL;
 403	}
 404	/* no cores found, bail out */
 405	if (sii->numcores == 0) {
 406		SI_ERROR(("si_doattach: could not find any cores\n"));
 407		return NULL;
 408	}
 409	/* bus/core/clk setup */
 410	origidx = SI_CC_IDX;
 411	if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
 412		SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
 413		goto exit;
 414	}
 415
 416	/* assume current core is CC */
 417	if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43234_CHIP_ID ||
 418	                                  CHIPID(sih->chip) == BCM43235_CHIP_ID ||
 419	                                  CHIPID(sih->chip) == BCM43236_CHIP_ID ||
 420	                                  CHIPID(sih->chip) == BCM43238_CHIP_ID) &&
 421	                                 (CHIPREV(sii->pub.chiprev) == 0))) {
 422
 423		if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
 424			uint clkdiv;
 425			clkdiv = R_REG(osh, &cc->clkdiv);
 426			/* otp_clk_div is even number, 120/14 < 9mhz */
 427			clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
 428			W_REG(osh, &cc->clkdiv, clkdiv);
 429			SI_ERROR(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv));
 430		}
 431		OSL_DELAY(10);
 432	}
 433
 434
 435	pvars = NULL;
 436
 437
 438
 439		if (sii->pub.ccrev >= 20) {
 440			cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
 441			ASSERT(cc != NULL);
 442			W_REG(osh, &cc->gpiopullup, 0);
 443			W_REG(osh, &cc->gpiopulldown, 0);
 444			si_setcoreidx(sih, origidx);
 445		}
 446
 447
 448
 449
 450	return (sii);
 451
 452exit:
 453
 454	return NULL;
 455}
 456
 457/* may be called with core in reset */
 458void
 459si_detach(si_t *sih)
 460{
 461	si_info_t *sii;
 462	uint idx;
 463
 464
 465	sii = SI_INFO(sih);
 466
 467	if (sii == NULL)
 468		return;
 469
 470	if (BUSTYPE(sih->bustype) == SI_BUS)
 471		for (idx = 0; idx < SI_MAXCORES; idx++)
 472			if (sii->regs[idx]) {
 473				REG_UNMAP(sii->regs[idx]);
 474				sii->regs[idx] = NULL;
 475			}
 476
 477
 478
 479#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
 480	if (sii != &ksii)
 481#endif	/* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
 482		MFREE(sii->osh, sii, sizeof(si_info_t));
 483}
 484
 485void *
 486si_osh(si_t *sih)
 487{
 488	si_info_t *sii;
 489
 490	sii = SI_INFO(sih);
 491	return sii->osh;
 492}
 493
 494void
 495si_setosh(si_t *sih, osl_t *osh)
 496{
 497	si_info_t *sii;
 498
 499	sii = SI_INFO(sih);
 500	if (sii->osh != NULL) {
 501		SI_ERROR(("osh is already set....\n"));
 502		ASSERT(!sii->osh);
 503	}
 504	sii->osh = osh;
 505}
 506
 507/* register driver interrupt disabling and restoring callback functions */
 508void
 509si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
 510                          void *intrsenabled_fn, void *intr_arg)
 511{
 512	si_info_t *sii;
 513
 514	sii = SI_INFO(sih);
 515	sii->intr_arg = intr_arg;
 516	sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn;
 517	sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn;
 518	sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn;
 519	/* save current core id.  when this function called, the current core
 520	 * must be the core which provides driver functions(il, et, wl, etc.)
 521	 */
 522	sii->dev_coreid = sii->coreid[sii->curidx];
 523}
 524
 525void
 526si_deregister_intr_callback(si_t *sih)
 527{
 528	si_info_t *sii;
 529
 530	sii = SI_INFO(sih);
 531	sii->intrsoff_fn = NULL;
 532}
 533
 534uint
 535si_intflag(si_t *sih)
 536{
 537	si_info_t *sii = SI_INFO(sih);
 538
 539	if (CHIPTYPE(sih->socitype) == SOCI_SB)
 540		return sb_intflag(sih);
 541	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
 542		return R_REG(sii->osh, ((uint32 *)(uintptr)
 543			    (sii->oob_router + OOB_STATUSA)));
 544	else {
 545		ASSERT(0);
 546		return 0;
 547	}
 548}
 549
 550uint
 551si_flag(si_t *sih)
 552{
 553	if (CHIPTYPE(sih->socitype) == SOCI_SB)
 554		return sb_flag(sih);
 555	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
 556		return ai_flag(sih);
 557	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
 558		return ub_flag(sih);
 559	else {
 560		ASSERT(0);
 561		return 0;
 562	}
 563}
 564
 565void
 566si_setint(si_t *sih, int siflag)
 567{
 568	if (CHIPTYPE(sih->socitype) == SOCI_SB)
 569		sb_setint(sih, siflag);
 570	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
 571		ai_setint(sih, siflag);
 572	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
 573		ub_setint(sih, siflag);
 574	else
 575		ASSERT(0);
 576}
 577
 578uint
 579si_coreid(si_t *sih)
 580{
 581	si_info_t *sii;
 582
 583	sii = SI_INFO(sih);
 584	return sii->coreid[sii->curidx];
 585}
 586
 587uint
 588si_coreidx(si_t *sih)
 589{
 590	si_info_t *sii;
 591
 592	sii = SI_INFO(sih);
 593	return sii->curidx;
 594}
 595
 596/* return the core-type instantiation # of the current core */
 597uint
 598si_coreunit(si_t *sih)
 599{
 600	si_info_t *sii;
 601	uint idx;
 602	uint coreid;
 603	uint coreunit;
 604	uint i;
 605
 606	sii = SI_INFO(sih);
 607	coreunit = 0;
 608
 609	idx = sii->curidx;
 610
 611	ASSERT(GOODREGS(sii->curmap));
 612	coreid = si_coreid(sih);
 613
 614	/* count the cores of our type */
 615	for (i = 0; i < idx; i++)
 616		if (sii->coreid[i] == coreid)
 617			coreunit++;
 618
 619	return (coreunit);
 620}
 621
 622uint
 623si_corevendor(si_t *sih)
 624{
 625	if (CHIPTYPE(sih->socitype) == SOCI_SB)
 626		return sb_corevendor(sih);
 627	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
 628		return ai_corevendor(sih);
 629	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
 630		return ub_corevendor(sih);
 631	else {
 632		ASSERT(0);
 633		return 0;
 634	}
 635}
 636
 637bool
 638si_backplane64(si_t *sih)
 639{
 640	return ((sih->cccaps & CC_CAP_BKPLN64) != 0);
 641}
 642
 643uint
 644si_corerev(si_t *sih)
 645{
 646	if (CHIPTYPE(sih->socitype) == SOCI_SB)
 647		return sb_corerev(sih);
 648	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
 649		return ai_corerev(sih);
 650	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
 651		return ub_corerev(sih);
 652	else {
 653		ASSERT(0);
 654		return 0;
 655	}
 656}
 657
 658/* return index of coreid or BADIDX if not found */
 659uint
 660si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
 661{
 662	si_info_t *sii;
 663	uint found;
 664	uint i;
 665
 666	sii = SI_INFO(sih);
 667
 668	found = 0;
 669
 670	for (i = 0; i < sii->numcores; i++)
 671		if (sii->coreid[i] == coreid) {
 672			if (found == coreunit)
 673				return (i);
 674			found++;
 675		}
 676
 677	return (BADIDX);
 678}
 679
 680/* return list of found cores */
 681uint
 682si_corelist(si_t *sih, uint coreid[])
 683{
 684	si_info_t *sii;
 685
 686	sii = SI_INFO(sih);
 687
 688	bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint)));
 689	return (sii->numcores);
 690}
 691
 692/* return current register mapping */
 693void *
 694si_coreregs(si_t *sih)
 695{
 696	si_info_t *sii;
 697
 698	sii = SI_INFO(sih);
 699	ASSERT(GOODREGS(sii->curmap));
 700
 701	return (sii->curmap);
 702}
 703
 704/*
 705 * This function changes logical "focus" to the indicated core;
 706 * must be called with interrupts off.
 707 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
 708 */
 709void *
 710si_setcore(si_t *sih, uint coreid, uint coreunit)
 711{
 712	uint idx;
 713
 714	idx = si_findcoreidx(sih, coreid, coreunit);
 715	if (!GOODIDX(idx))
 716		return (NULL);
 717
 718	if (CHIPTYPE(sih->socitype) == SOCI_SB)
 719		return sb_setcoreidx(sih, idx);
 720	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
 721		return ai_setcoreidx(sih, idx);
 722	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
 723		return ub_setcoreidx(sih, idx);
 724	else {
 725		ASSERT(0);
 726		return NULL;
 727	}
 728}
 729
 730void *
 731si_setcoreidx(si_t *sih, uint coreidx)
 732{
 733	if (CHIPTYPE(sih->socitype) == SOCI_SB)
 734		return sb_setcoreidx(sih, coreidx);
 735	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
 736		return ai_setcoreidx(sih, coreidx);
 737	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
 738		return ub_setcoreidx(sih, coreidx);
 739	else {
 740		ASSERT(0);
 741		return NULL;
 742	}
 743}
 744
 745/* Turn off interrupt as required by sb_setcore, before switch core */
 746void *
 747si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
 748{
 749	void *cc;
 750	si_info_t *sii;
 751
 752	sii = SI_INFO(sih);
 753
 754	if (SI_FAST(sii)) {
 755		/* Overloading the origidx variable to remember the coreid,
 756		 * this works because the core ids cannot be confused with
 757		 * core indices.
 758		 */
 759		*origidx = coreid;
 760		if (coreid == CC_CORE_ID)
 761			return (void *)CCREGS_FAST(sii);
 762		else if (coreid == sih->buscoretype)
 763			return (void *)PCIEREGS(sii);
 764	}
 765	INTR_OFF(sii, *intr_val);
 766	*origidx = sii->curidx;
 767	cc = si_setcore(sih, coreid, 0);
 768	ASSERT(cc != NULL);
 769
 770	return cc;
 771}
 772
 773/* restore coreidx and restore interrupt */
 774void
 775si_restore_core(si_t *sih, uint coreid, uint intr_val)
 776{
 777	si_info_t *sii;
 778
 779	sii = SI_INFO(sih);
 780	if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
 781		return;
 782
 783	si_setcoreidx(sih, coreid);
 784	INTR_RESTORE(sii, intr_val);
 785}
 786
 787int
 788si_numaddrspaces(si_t *sih)
 789{
 790	if (CHIPTYPE(sih->socitype) == SOCI_SB)
 791		return sb_numaddrspaces(sih);
 792	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
 793		return ai_numaddrspaces(sih);
 794	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
 795		return ub_numaddrspaces(sih);
 796	else {
 797		ASSERT(0);
 798		return 0;
 799	}
 800}
 801
 802uint32
 803si_addrspace(si_t *sih, uint asidx)
 804{
 805	if (CHIPTYPE(sih->socitype) == SOCI_SB)
 806		return sb_addrspace(sih, asidx);
 807	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
 808		return ai_addrspace(sih, asidx);
 809	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
 810		return ub_addrspace(sih, asidx);
 811	else {
 812		ASSERT(0);
 813		return 0;
 814	}
 815}
 816
 817uint32
 818si_addrspacesize(si_t *sih, uint asidx)
 819{
 820	if (CHIPTYPE(sih->socitype) == SOCI_SB)
 821		return sb_addrspacesize(sih, asidx);
 822	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
 823		return ai_addrspacesize(sih, asidx);
 824	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
 825		return ub_addrspacesize(sih, asidx);
 826	else {
 827		ASSERT(0);
 828		return 0;
 829	}
 830}
 831
 832uint32
 833si_core_cflags(si_t *sih, uint32 mask, uint32 val)
 834{
 835	if (CHIPTYPE(sih->socitype) == SOCI_SB)
 836		return sb_core_cflags(sih, mask, val);
 837	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
 838		return ai_core_cflags(sih, mask, val);
 839	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
 840		return ub_core_cflags(sih, mask, val);
 841	else {
 842		ASSERT(0);
 843		return 0;
 844	}
 845}
 846
 847void
 848si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
 849{
 850	if (CHIPTYPE(sih->socitype) == SOCI_SB)
 851		sb_core_cflags_wo(sih, mask, val);
 852	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
 853		ai_core_cflags_wo(sih, mask, val);
 854	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
 855		ub_core_cflags_wo(sih, mask, val);
 856	else
 857		ASSERT(0);
 858}
 859
 860uint32
 861si_core_sflags(si_t *sih, uint32 mask, uint32 val)
 862{
 863	if (CHIPTYPE(sih->socitype) == SOCI_SB)
 864		return sb_core_sflags(sih, mask, val);
 865	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
 866		return ai_core_sflags(sih, mask, val);
 867	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
 868		return ub_core_sflags(sih, mask, val);
 869	else {
 870		ASSERT(0);
 871		return 0;
 872	}
 873}
 874
 875bool
 876si_iscoreup(si_t *sih)
 877{
 878	if (CHIPTYPE(sih->socitype) == SOCI_SB)
 879		return sb_iscoreup(sih);
 880	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
 881		return ai_iscoreup(sih);
 882	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
 883		return ub_iscoreup(sih);
 884	else {
 885		ASSERT(0);
 886		return FALSE;
 887	}
 888}
 889
 890uint
 891si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
 892{
 893	/* only for AI back plane chips */
 894	if (CHIPTYPE(sih->socitype) == SOCI_AI)
 895		return (ai_wrap_reg(sih, offset, mask, val));
 896	return 0;
 897}
 898
 899uint
 900si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
 901{
 902	if (CHIPTYPE(sih->socitype) == SOCI_SB)
 903		return sb_corereg(sih, coreidx, regoff, mask, val);
 904	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
 905		return ai_corereg(sih, coreidx, regoff, mask, val);
 906	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
 907		return ub_corereg(sih, coreidx, regoff, mask, val);
 908	else {
 909		ASSERT(0);
 910		return 0;
 911	}
 912}
 913
 914void
 915si_core_disable(si_t *sih, uint32 bits)
 916{
 917	if (CHIPTYPE(sih->socitype) == SOCI_SB)
 918		sb_core_disable(sih, bits);
 919	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
 920		ai_core_disable(sih, bits);
 921	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
 922		ub_core_disable(sih, bits);
 923}
 924
 925void
 926si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
 927{
 928	if (CHIPTYPE(sih->socitype) == SOCI_SB)
 929		sb_core_reset(sih, bits, resetbits);
 930	else if (CHIPTYPE(sih->socitype) == SOCI_AI)
 931		ai_core_reset(sih, bits, resetbits);
 932	else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
 933		ub_core_reset(sih, bits, resetbits);
 934}
 935
 936/* Run bist on current core. Caller needs to take care of core-specific bist hazards */
 937int
 938si_corebist(si_t *sih)
 939{
 940	uint32 cflags;
 941	int result = 0;
 942
 943	/* Read core control flags */
 944	cflags = si_core_cflags(sih, 0, 0);
 945
 946	/* Set bist & fgc */
 947	si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC));
 948
 949	/* Wait for bist done */
 950	SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);
 951
 952	if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
 953		result = BCME_ERROR;
 954
 955	/* Reset core control flags */
 956	si_core_cflags(sih, 0xffff, cflags);
 957
 958	return result;
 959}
 960
 961static uint32
 962factor6(uint32 x)
 963{
 964	switch (x) {
 965	case CC_F6_2:	return 2;
 966	case CC_F6_3:	return 3;
 967	case CC_F6_4:	return 4;
 968	case CC_F6_5:	return 5;
 969	case CC_F6_6:	return 6;
 970	case CC_F6_7:	return 7;
 971	default:	return 0;
 972	}
 973}
 974
 975/* calculate the speed the SI would run at given a set of clockcontrol values */
 976uint32
 977si_clock_rate(uint32 pll_type, uint32 n, uint32 m)
 978{
 979	uint32 n1, n2, clock, m1, m2, m3, mc;
 980
 981	n1 = n & CN_N1_MASK;
 982	n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
 983
 984	if (pll_type == PLL_TYPE6) {
 985		if (m & CC_T6_MMASK)
 986			return CC_T6_M1;
 987		else
 988			return CC_T6_M0;
 989	} else if ((pll_type == PLL_TYPE1) ||
 990	           (pll_type == PLL_TYPE3) ||
 991	           (pll_type == PLL_TYPE4) ||
 992	           (pll_type == PLL_TYPE7)) {
 993		n1 = factor6(n1);
 994		n2 += CC_F5_BIAS;
 995	} else if (pll_type == PLL_TYPE2) {
 996		n1 += CC_T2_BIAS;
 997		n2 += CC_T2_BIAS;
 998		ASSERT((n1 >= 2) && (n1 <= 7));
 999		ASSERT((n2 >= 5) && (n2 <= 23));
1000	} else if (pll_type == PLL_TYPE5) {
1001		return (100000000);
1002	} else
1003		ASSERT(0);
1004	/* PLL types 3 and 7 use BASE2 (25Mhz) */
1005	if ((pll_type == PLL_TYPE3) ||
1006	    (pll_type == PLL_TYPE7)) {
1007		clock = CC_CLOCK_BASE2 * n1 * n2;
1008	} else
1009		clock = CC_CLOCK_BASE1 * n1 * n2;
1010
1011	if (clock == 0)
1012		return 0;
1013
1014	m1 = m & CC_M1_MASK;
1015	m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
1016	m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
1017	mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
1018
1019	if ((pll_type == PLL_TYPE1) ||
1020	    (pll_type == PLL_TYPE3) ||
1021	    (pll_type == PLL_TYPE4) ||
1022	    (pll_type == PLL_TYPE7)) {
1023		m1 = factor6(m1);
1024		if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
1025			m2 += CC_F5_BIAS;
1026		else
1027			m2 = factor6(m2);
1028		m3 = factor6(m3);
1029
1030		switch (mc) {
1031		case CC_MC_BYPASS:	return (clock);
1032		case CC_MC_M1:		return (clock / m1);
1033		case CC_MC_M1M2:	return (clock / (m1 * m2));
1034		case CC_MC_M1M2M3:	return (clock / (m1 * m2 * m3));
1035		case CC_MC_M1M3:	return (clock / (m1 * m3));
1036		default:		return (0);
1037		}
1038	} else {
1039		ASSERT(pll_type == PLL_TYPE2);
1040
1041		m1 += CC_T2_BIAS;
1042		m2 += CC_T2M2_BIAS;
1043		m3 += CC_T2_BIAS;
1044		ASSERT((m1 >= 2) && (m1 <= 7));
1045		ASSERT((m2 >= 3) && (m2 <= 10));
1046		ASSERT((m3 >= 2) && (m3 <= 7));
1047
1048		if ((mc & CC_T2MC_M1BYP) == 0)
1049			clock /= m1;
1050		if ((mc & CC_T2MC_M2BYP) == 0)
1051			clock /= m2;
1052		if ((mc & CC_T2MC_M3BYP) == 0)
1053			clock /= m3;
1054
1055		return (clock);
1056	}
1057}
1058
1059
1060/* set chip watchdog reset timer to fire in 'ticks' */
1061void
1062si_watchdog(si_t *sih, uint ticks)
1063{
1064	uint nb, maxt;
1065
1066	if (PMUCTL_ENAB(sih)) {
1067
1068		if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) &&
1069		    (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) {
1070			si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2);
1071			si_setcore(sih, USB20D_CORE_ID, 0);
1072			si_core_disable(sih, 1);
1073			si_setcore(sih, CC_CORE_ID, 0);
1074		}
1075
1076		nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24);
1077		/* The mips compiler uses the sllv instruction,
1078		 * so we specially handle the 32-bit case.
1079		 */
1080		if (nb == 32)
1081			maxt = 0xffffffff;
1082		else
1083			maxt = ((1 << nb) - 1);
1084
1085		if (ticks == 1)
1086			ticks = 2;
1087		else if (ticks > maxt)
1088			ticks = maxt;
1089
1090		si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog), ~0, ticks);
1091	} else {
1092		maxt = (1 << 28) - 1;
1093		if (ticks > maxt)
1094			ticks = maxt;
1095
1096		si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks);
1097	}
1098}
1099
1100/* trigger watchdog reset after ms milliseconds */
1101void
1102si_watchdog_ms(si_t *sih, uint32 ms)
1103{
1104	si_watchdog(sih, wd_msticks * ms);
1105}
1106
1107
1108
1109
1110/* return the slow clock source - LPO, XTAL, or PCI */
1111static uint
1112si_slowclk_src(si_info_t *sii)
1113{
1114	chipcregs_t *cc;
1115
1116	ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1117
1118	if (sii->pub.ccrev < 6) {
1119		if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) &&
1120		    (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) &
1121		     PCI_CFG_GPIO_SCS))
1122			return (SCC_SS_PCI);
1123		else
1124			return (SCC_SS_XTAL);
1125	} else if (sii->pub.ccrev < 10) {
1126		cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx);
1127		return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
1128	} else	/* Insta-clock */
1129		return (SCC_SS_XTAL);
1130}
1131
1132/* return the ILP (slowclock) min or max frequency */
1133static uint
1134si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
1135{
1136	uint32 slowclk;
1137	uint div;
1138
1139	ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1140
1141	/* shouldn't be here unless we've established the chip has dynamic clk control */
1142	ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
1143
1144	slowclk = si_slowclk_src(sii);
1145	if (sii->pub.ccrev < 6) {
1146		if (slowclk == SCC_SS_PCI)
1147			return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64));
1148		else
1149			return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32));
1150	} else if (sii->pub.ccrev < 10) {
1151		div = 4 *
1152		        (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
1153		if (slowclk == SCC_SS_LPO)
1154			return (max_freq ? LPOMAXFREQ : LPOMINFREQ);
1155		else if (slowclk == SCC_SS_XTAL)
1156			return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div));
1157		else if (slowclk == SCC_SS_PCI)
1158			return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div));
1159		else
1160			ASSERT(0);
1161	} else {
1162		/* Chipc rev 10 is InstaClock */
1163		div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
1164		div = 4 * (div + 1);
1165		return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div));
1166	}
1167	return (0);
1168}
1169
1170static void
1171si_clkctl_setdelay(si_info_t *sii, void *chipcregs)
1172{
1173	chipcregs_t *cc = (chipcregs_t *)chipcregs;
1174	uint slowmaxfreq, pll_delay, slowclk;
1175	uint pll_on_delay, fref_sel_delay;
1176
1177	pll_delay = PLL_DELAY;
1178
1179	/* If the slow clock is not sourced by the xtal then add the xtal_on_delay
1180	 * since the xtal will also be powered down by dynamic clk control logic.
1181	 */
1182
1183	slowclk = si_slowclk_src(sii);
1184	if (slowclk != SCC_SS_XTAL)
1185		pll_delay += XTAL_ON_DELAY;
1186
1187	/* Starting with 4318 it is ILP that is used for the delays */
1188	slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc);
1189
1190	pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
1191	fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
1192
1193	W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
1194	W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
1195}
1196
1197/* initialize power control delay registers */
1198void
1199si_clkctl_init(si_t *sih)
1200{
1201	si_info_t *sii;
1202	uint origidx = 0;
1203	chipcregs_t *cc;
1204	bool fast;
1205
1206	if (!CCCTL_ENAB(sih))
1207		return;
1208
1209	sii = SI_INFO(sih);
1210	fast = SI_FAST(sii);
1211	if (!fast) {
1212		origidx = sii->curidx;
1213		if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
1214			return;
1215	} else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
1216		return;
1217	ASSERT(cc != NULL);
1218
1219	/* set all Instaclk chip ILP to 1 MHz */
1220	if (sih->ccrev >= 10)
1221		SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
1222		        (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
1223
1224	si_clkctl_setdelay(sii, (void *)(uintptr)cc);
1225
1226	if (!fast)
1227		si_setcoreidx(sih, origidx);
1228}
1229
1230/* change logical "focus" to the gpio core for optimized access */
1231void *
1232si_gpiosetcore(si_t *sih)
1233{
1234	return (si_setcoreidx(sih, SI_CC_IDX));
1235}
1236
1237/* mask&set gpiocontrol bits */
1238uint32
1239si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1240{
1241	uint regoff;
1242
1243	regoff = 0;
1244
1245	/* gpios could be shared on router platforms
1246	 * ignore reservation if it's high priority (e.g., test apps)
1247	 */
1248	if ((priority != GPIO_HI_PRIORITY) &&
1249	    (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1250		mask = priority ? (si_gpioreservation & mask) :
1251			((si_gpioreservation | mask) & ~(si_gpioreservation));
1252		val &= mask;
1253	}
1254
1255	regoff = OFFSETOF(chipcregs_t, gpiocontrol);
1256	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1257}
1258
1259/* mask&set gpio output enable bits */
1260uint32
1261si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1262{
1263	uint regoff;
1264
1265	regoff = 0;
1266
1267	/* gpios could be shared on router platforms
1268	 * ignore reservation if it's high priority (e.g., test apps)
1269	 */
1270	if ((priority != GPIO_HI_PRIORITY) &&
1271	    (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1272		mask = priority ? (si_gpioreservation & mask) :
1273			((si_gpioreservation | mask) & ~(si_gpioreservation));
1274		val &= mask;
1275	}
1276
1277	regoff = OFFSETOF(chipcregs_t, gpioouten);
1278	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1279}
1280
1281/* mask&set gpio output bits */
1282uint32
1283si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1284{
1285	uint regoff;
1286
1287	regoff = 0;
1288
1289	/* gpios could be shared on router platforms
1290	 * ignore reservation if it's high priority (e.g., test apps)
1291	 */
1292	if ((priority != GPIO_HI_PRIORITY) &&
1293	    (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1294		mask = priority ? (si_gpioreservation & mask) :
1295			((si_gpioreservation | mask) & ~(si_gpioreservation));
1296		val &= mask;
1297	}
1298
1299	regoff = OFFSETOF(chipcregs_t, gpioout);
1300	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1301}
1302
1303/* reserve one gpio */
1304uint32
1305si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority)
1306{
1307	si_info_t *sii;
1308
1309	sii = SI_INFO(sih);
1310
1311	/* only cores on SI_BUS share GPIO's and only applcation users need to
1312	 * reserve/release GPIO
1313	 */
1314	if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
1315		ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
1316		return 0xffffffff;
1317	}
1318	/* make sure only one bit is set */
1319	if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
1320		ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
1321		return 0xffffffff;
1322	}
1323
1324	/* already reserved */
1325	if (si_gpioreservation & gpio_bitmask)
1326		return 0xffffffff;
1327	/* set reservation */
1328	si_gpioreservation |= gpio_bitmask;
1329
1330	return si_gpioreservation;
1331}
1332
1333/* release one gpio */
1334/*
1335 * releasing the gpio doesn't change the current value on the GPIO last write value
1336 * persists till some one overwrites it
1337 */
1338
1339uint32
1340si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority)
1341{
1342	si_info_t *sii;
1343
1344	sii = SI_INFO(sih);
1345
1346	/* only cores on SI_BUS share GPIO's and only applcation users need to
1347	 * reserve/release GPIO
1348	 */
1349	if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
1350		ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
1351		return 0xffffffff;
1352	}
1353	/* make sure only one bit is set */
1354	if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
1355		ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
1356		return 0xffffffff;
1357	}
1358
1359	/* already released */
1360	if (!(si_gpioreservation & gpio_bitmask))
1361		return 0xffffffff;
1362
1363	/* clear reservation */
1364	si_gpioreservation &= ~gpio_bitmask;
1365
1366	return si_gpioreservation;
1367}
1368
1369/* return the current gpioin register value */
1370uint32
1371si_gpioin(si_t *sih)
1372{
1373	si_info_t *sii;
1374	uint regoff;
1375
1376	sii = SI_INFO(sih);
1377	regoff = 0;
1378
1379	regoff = OFFSETOF(chipcregs_t, gpioin);
1380	return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0));
1381}
1382
1383/* mask&set gpio interrupt polarity bits */
1384uint32
1385si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1386{
1387	si_info_t *sii;
1388	uint regoff;
1389
1390	sii = SI_INFO(sih);
1391	regoff = 0;
1392
1393	/* gpios could be shared on router platforms */
1394	if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1395		mask = priority ? (si_gpioreservation & mask) :
1396			((si_gpioreservation | mask) & ~(si_gpioreservation));
1397		val &= mask;
1398	}
1399
1400	regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
1401	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1402}
1403
1404/* mask&set gpio interrupt mask bits */
1405uint32
1406si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1407{
1408	si_info_t *sii;
1409	uint regoff;
1410
1411	sii = SI_INFO(sih);
1412	regoff = 0;
1413
1414	/* gpios could be shared on router platforms */
1415	if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1416		mask = priority ? (si_gpioreservation & mask) :
1417			((si_gpioreservation | mask) & ~(si_gpioreservation));
1418		val &= mask;
1419	}
1420
1421	regoff = OFFSETOF(chipcregs_t, gpiointmask);
1422	return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1423}
1424
1425/* assign the gpio to an led */
1426uint32
1427si_gpioled(si_t *sih, uint32 mask, uint32 val)
1428{
1429	si_info_t *sii;
1430
1431	sii = SI_INFO(sih);
1432	if (sih->ccrev < 16)
1433		return 0xffffffff;
1434
1435	/* gpio led powersave reg */
1436	return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val));
1437}
1438
1439/* mask&set gpio timer val */
1440uint32
1441si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
1442{
1443	si_info_t *sii;
1444
1445	sii = SI_INFO(sih);
1446
1447	if (sih->ccrev < 16)
1448		return 0xffffffff;
1449
1450	return (si_corereg(sih, SI_CC_IDX,
1451		OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval));
1452}
1453
1454uint32
1455si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
1456{
1457	si_info_t *sii;
1458	uint offs;
1459
1460	sii = SI_INFO(sih);
1461	if (sih->ccrev < 20)
1462		return 0xffffffff;
1463
1464	offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup));
1465	return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
1466}
1467
1468uint32
1469si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
1470{
1471	si_info_t *sii;
1472	uint offs;
1473
1474	sii = SI_INFO(sih);
1475	if (sih->ccrev < 11)
1476		return 0xffffffff;
1477
1478	if (regtype == GPIO_REGEVT)
1479		offs = OFFSETOF(chipcregs_t, gpioevent);
1480	else if (regtype == GPIO_REGEVT_INTMSK)
1481		offs = OFFSETOF(chipcregs_t, gpioeventintmask);
1482	else if (regtype == GPIO_REGEVT_INTPOL)
1483		offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
1484	else
1485		return 0xffffffff;
1486
1487	return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
1488}
1489
1490void *
1491si_gpio_handler_register(si_t *sih, uint32 event,
1492	bool level, gpio_handler_t cb, void *arg)
1493{
1494	si_info_t *sii;
1495	gpioh_item_t *gi;
1496
1497	ASSERT(event);
1498	ASSERT(cb != NULL);
1499
1500	sii = SI_INFO(sih);
1501	if (sih->ccrev < 11)
1502		return NULL;
1503
1504	if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL)
1505		return NULL;
1506
1507	bzero(gi, sizeof(gpioh_item_t));
1508	gi->event = event;
1509	gi->handler = cb;
1510	gi->arg = arg;
1511	gi->level = level;
1512
1513	gi->next = sii->gpioh_head;
1514	sii->gpioh_head = gi;
1515
1516	return (void *)(gi);
1517}
1518
1519void
1520si_gpio_handler_unregister(si_t *sih, void *gpioh)
1521{
1522	si_info_t *sii;
1523	gpioh_item_t *p, *n;
1524
1525	sii = SI_INFO(sih);
1526	if (sih->ccrev < 11)
1527		return;
1528
1529	ASSERT(sii->gpioh_head != NULL);
1530	if ((void*)sii->gpioh_head == gpioh) {
1531		sii->gpioh_head = sii->gpioh_head->next;
1532		MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
1533		return;
1534	} else {
1535		p = sii->gpioh_head;
1536		n = p->next;
1537		while (n) {
1538			if ((void*)n == gpioh) {
1539				p->next = n->next;
1540				MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
1541				return;
1542			}
1543			p = n;
1544			n = n->next;
1545		}
1546	}
1547
1548	ASSERT(0); /* Not found in list */
1549}
1550
1551void
1552si_gpio_handler_process(si_t *sih)
1553{
1554	si_info_t *sii;
1555	gpioh_item_t *h;
1556	uint32 level = si_gpioin(sih);
1557	uint32 levelp = si_gpiointpolarity(sih, 0, 0, 0);
1558	uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0);
1559	uint32 edgep = si_gpioevent(sih, GPIO_REGEVT_INTPOL, 0, 0);
1560
1561	sii = SI_INFO(sih);
1562	for (h = sii->gpioh_head; h != NULL; h = h->next) {
1563		if (h->handler) {
1564			uint32 status = (h->level ? level : edge) & h->event;
1565			uint32 polarity = (h->level ? levelp : edgep) & h->event;
1566
1567			/* polarity bitval is opposite of status bitval */
1568			if (status ^ polarity)
1569				h->handler(status, h->arg);
1570		}
1571	}
1572
1573	si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */
1574}
1575
1576uint32
1577si_gpio_int_enable(si_t *sih, bool enable)
1578{
1579	si_info_t *sii;
1580	uint offs;
1581
1582	sii = SI_INFO(sih);
1583	if (sih->ccrev < 11)
1584		return 0xffffffff;
1585
1586	offs = OFFSETOF(chipcregs_t, intmask);
1587	return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
1588}
1589
1590
1591/* Return the size of the specified SOCRAM bank */
1592static uint
1593socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 index, uint8 mem_type)
1594{
1595	uint banksize, bankinfo;
1596	uint bankidx = index | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
1597
1598	ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
1599
1600	W_REG(sii->osh, &regs->bankidx, bankidx);
1601	bankinfo = R_REG(sii->osh, &regs->bankinfo);
1602	banksize = SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
1603	return banksize;
1604}
1605
1606void
1607si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect)
1608{
1609	si_info_t *sii;
1610	uint origidx;
1611	uint intr_val = 0;
1612	sbsocramregs_t *regs;
1613	bool wasup;
1614	uint corerev;
1615
1616	sii = SI_INFO(sih);
1617
1618	/* Block ints and save current core */
1619	INTR_OFF(sii, intr_val);
1620	origidx = si_coreidx(sih);
1621
1622	if (!set)
1623		*enable = *protect = 0;
1624
1625	/* Switch to SOCRAM core */
1626	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1627		goto done;
1628
1629	/* Get info for determining size */
1630	if (!(wasup = si_iscoreup(sih)))
1631		si_core_reset(sih, 0, 0);
1632
1633	corerev = si_corerev(sih);
1634	if (corerev >= 10) {
1635		uint32 extcinfo;
1636		uint8 nb;
1637		uint8 i;
1638		uint32 bankidx, bankinfo;
1639
1640		extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
1641		nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
1642		for (i = 0; i < nb; i++) {
1643			bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
1644			W_REG(sii->osh, &regs->bankidx, bankidx);
1645			bankinfo = R_REG(sii->osh, &regs->bankinfo);
1646			if (set) {
1647				bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK;
1648				bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK;
1649				if (*enable) {
1650					bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT);
1651					if (*protect)
1652						bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT);
1653				}
1654				W_REG(sii->osh, &regs->bankinfo, bankinfo);
1655			}
1656			else if (i == 0) {
1657				if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) {
1658					*enable = 1;
1659					if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK)
1660						*protect = 1;
1661				}
1662			}
1663		}
1664	}
1665
1666	/* Return to previous state and core */
1667	if (!wasup)
1668		si_core_disable(sih, 0);
1669	si_setcoreidx(sih, origidx);
1670
1671done:
1672	INTR_RESTORE(sii, intr_val);
1673}
1674
1675bool
1676si_socdevram_pkg(si_t *sih)
1677{
1678	if (si_socdevram_size(sih) > 0)
1679		return TRUE;
1680	else
1681		return FALSE;
1682}
1683
1684uint32
1685si_socdevram_size(si_t *sih)
1686{
1687	si_info_t *sii;
1688	uint origidx;
1689	uint intr_val = 0;
1690	uint32 memsize = 0;
1691	sbsocramregs_t *regs;
1692	bool wasup;
1693	uint corerev;
1694
1695	sii = SI_INFO(sih);
1696
1697	/* Block ints and save current core */
1698	INTR_OFF(sii, intr_val);
1699	origidx = si_coreidx(sih);
1700
1701	/* Switch to SOCRAM core */
1702	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1703		goto done;
1704
1705	/* Get info for determining size */
1706	if (!(wasup = si_iscoreup(sih)))
1707		si_core_reset(sih, 0, 0);
1708
1709	corerev = si_corerev(sih);
1710	if (corerev >= 10) {
1711		uint32 extcinfo;
1712		uint8 nb;
1713		uint8 i;
1714
1715		extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
1716		nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
1717		for (i = 0; i < nb; i++)
1718			memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
1719	}
1720
1721	/* Return to previous state and core */
1722	if (!wasup)
1723		si_core_disable(sih, 0);
1724	si_setcoreidx(sih, origidx);
1725
1726done:
1727	INTR_RESTORE(sii, intr_val);
1728
1729	return memsize;
1730}
1731
1732/* Return the RAM size of the SOCRAM core */
1733uint32
1734si_socram_size(si_t *sih)
1735{
1736	si_info_t *sii;
1737	uint origidx;
1738	uint intr_val = 0;
1739
1740	sbsocramregs_t *regs;
1741	bool wasup;
1742	uint corerev;
1743	uint32 coreinfo;
1744	uint memsize = 0;
1745
1746	sii = SI_INFO(sih);
1747
1748	/* Block ints and save current core */
1749	INTR_OFF(sii, intr_val);
1750	origidx = si_coreidx(sih);
1751
1752	/* Switch to SOCRAM core */
1753	if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1754		goto done;
1755
1756	/* Get info for determining size */
1757	if (!(wasup = si_iscoreup(sih)))
1758		si_core_reset(sih, 0, 0);
1759	corerev = si_corerev(sih);
1760	coreinfo = R_REG(sii->osh, &regs->coreinfo);
1761
1762	/* Calculate size from coreinfo based on rev */
1763	if (corerev == 0)
1764		memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
1765	else if (corerev < 3) {
1766		memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
1767		memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1768	} else if ((corerev <= 7) || (corerev == 12)) {
1769		uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1770		uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
1771		uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
1772		if (lss != 0)
1773			nb --;
1774		memsize = nb * (1 << (bsz + SR_BSZ_BASE));
1775		if (lss != 0)
1776			memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
1777	} else {
1778		uint8 i;
1779		uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1780		for (i = 0; i < nb; i++)
1781			memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
1782	}
1783
1784	/* Return to previous state and core */
1785	if (!wasup)
1786		si_core_disable(sih, 0);
1787	si_setcoreidx(sih, origidx);
1788
1789done:
1790	INTR_RESTORE(sii, intr_val);
1791
1792	return memsize;
1793}
1794
1795
1796void
1797si_btcgpiowar(si_t *sih)
1798{
1799	si_info_t *sii;
1800	uint origidx;
1801	uint intr_val = 0;
1802	chipcregs_t *cc;
1803
1804	sii = SI_INFO(sih);
1805
1806	/* Make sure that there is ChipCommon core present &&
1807	 * UART_TX is strapped to 1
1808	 */
1809	if (!(sih->cccaps & CC_CAP_UARTGPIO))
1810		return;
1811
1812	/* si_corereg cannot be used as we have to guarantee 8-bit read/writes */
1813	INTR_OFF(sii, intr_val);
1814
1815	origidx = si_coreidx(sih);
1816
1817	cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
1818	ASSERT(cc != NULL);
1819
1820	W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04);
1821
1822	/* restore the original index */
1823	si_setcoreidx(sih, origidx);
1824
1825	INTR_RESTORE(sii, intr_val);
1826}
1827
1828uint
1829si_pll_reset(si_t *sih)
1830{
1831	uint err = 0;
1832
1833	return (err);
1834}
1835
1836/* check if the device is removed */
1837bool
1838si_deviceremoved(si_t *sih)
1839{
1840	uint32 w;
1841	si_info_t *sii;
1842
1843	sii = SI_INFO(sih);
1844
1845	switch (BUSTYPE(sih->bustype)) {
1846	case PCI_BUS:
1847		ASSERT(sii->osh != NULL);
1848		w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32));
1849		if ((w & 0xFFFF) != VENDOR_BROADCOM)
1850			return TRUE;
1851		break;
1852	}
1853	return FALSE;
1854}
1855
1856bool
1857si_is_sprom_available(si_t *sih)
1858{
1859	if (sih->ccrev >= 31) {
1860		si_info_t *sii;
1861		uint origidx;
1862		chipcregs_t *cc;
1863		uint32 sromctrl;
1864
1865		if ((sih->cccaps & CC_CAP_SROM) == 0)
1866			return FALSE;
1867
1868		sii = SI_INFO(sih);
1869		origidx = sii->curidx;
1870		cc = si_setcoreidx(sih, SI_CC_IDX);
1871		sromctrl = R_REG(sii->osh, &cc->sromcontrol);
1872		si_setcoreidx(sih, origidx);
1873		return (sromctrl & SRC_PRESENT);
1874	}
1875
1876	switch (CHIPID(sih->chip)) {
1877	case BCM4312_CHIP_ID:
1878		return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL);
1879	case BCM4325_CHIP_ID:
1880		return (sih->chipst & CST4325_SPROM_SEL) != 0;
1881	case BCM4322_CHIP_ID:
1882	case BCM43221_CHIP_ID:
1883	case BCM43231_CHIP_ID:
1884	case BCM43222_CHIP_ID:
1885	case BCM43111_CHIP_ID:
1886	case BCM43112_CHIP_ID:
1887	case BCM4342_CHIP_ID:
1888	{
1889		uint32 spromotp;
1890		spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
1891		        CST4322_SPROM_OTP_SEL_SHIFT;
1892		return (spromotp & CST4322_SPROM_PRESENT) != 0;
1893	}
1894	case BCM4329_CHIP_ID:
1895		return (sih->chipst & CST4329_SPROM_SEL) != 0;
1896	case BCM4315_CHIP_ID:
1897		return (sih->chipst & CST4315_SPROM_SEL) != 0;
1898	case BCM4319_CHIP_ID:
1899		return (sih->chipst & CST4319_SPROM_SEL) != 0;
1900
1901	case BCM4336_CHIP_ID:
1902	case BCM43362_CHIP_ID:
1903		return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
1904
1905	case BCM4330_CHIP_ID:
1906		return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
1907	case BCM4313_CHIP_ID:
1908		return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
1909	case BCM43239_CHIP_ID:
1910		return ((sih->chipst & CST43239_SPROM_MASK) &&
1911			!(sih->chipst & CST43239_SFLASH_MASK));
1912	default:
1913		return TRUE;
1914	}
1915}