Home | History | Annotate | Download | only in shared
      1 /*
      2  * Misc utility routines for accessing chip-specific features
      3  * of the SiliconBackplane-based Broadcom chips.
      4  *
      5  * Copyright (C) 1999-2010, 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: sbutils.c,v 1.662.4.10.2.7.4.2 2010/04/19 05:48:48 Exp $
     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 
     39 #include "siutils_priv.h"
     40 
     41 /* local prototypes */
     42 static uint _sb_coreidx(si_info_t *sii, uint32 sba);
     43 static uint _sb_scan(si_info_t *sii, uint32 sba, void *regs, uint bus, uint32 sbba,
     44                      uint ncores);
     45 static uint32 _sb_coresba(si_info_t *sii);
     46 static void *_sb_setcoreidx(si_info_t *sii, uint coreidx);
     47 
     48 #define	SET_SBREG(sii, r, mask, val)	\
     49 		W_SBREG((sii), (r), ((R_SBREG((sii), (r)) & ~(mask)) | (val)))
     50 #define	REGS2SB(va)	(sbconfig_t*) ((int8*)(va) + SBCONFIGOFF)
     51 
     52 /* sonicsrev */
     53 #define	SONICS_2_2	(SBIDL_RV_2_2 >> SBIDL_RV_SHIFT)
     54 #define	SONICS_2_3	(SBIDL_RV_2_3 >> SBIDL_RV_SHIFT)
     55 
     56 #define	R_SBREG(sii, sbr)	sb_read_sbreg((sii), (sbr))
     57 #define	W_SBREG(sii, sbr, v)	sb_write_sbreg((sii), (sbr), (v))
     58 #define	AND_SBREG(sii, sbr, v)	W_SBREG((sii), (sbr), (R_SBREG((sii), (sbr)) & (v)))
     59 #define	OR_SBREG(sii, sbr, v)	W_SBREG((sii), (sbr), (R_SBREG((sii), (sbr)) | (v)))
     60 
     61 static uint32
     62 sb_read_sbreg(si_info_t *sii, volatile uint32 *sbr)
     63 {
     64 	uint8 tmp;
     65 	uint32 val, intr_val = 0;
     66 
     67 
     68 	/*
     69 	 * compact flash only has 11 bits address, while we needs 12 bits address.
     70 	 * MEM_SEG will be OR'd with other 11 bits address in hardware,
     71 	 * so we program MEM_SEG with 12th bit when necessary(access sb regsiters).
     72 	 * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special
     73 	 */
     74 	if (PCMCIA(sii)) {
     75 		INTR_OFF(sii, intr_val);
     76 		tmp = 1;
     77 		OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
     78 		sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */
     79 	}
     80 
     81 	val = R_REG(sii->osh, sbr);
     82 
     83 	if (PCMCIA(sii)) {
     84 		tmp = 0;
     85 		OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
     86 		INTR_RESTORE(sii, intr_val);
     87 	}
     88 
     89 	return (val);
     90 }
     91 
     92 static void
     93 sb_write_sbreg(si_info_t *sii, volatile uint32 *sbr, uint32 v)
     94 {
     95 	uint8 tmp;
     96 	volatile uint32 dummy;
     97 	uint32 intr_val = 0;
     98 
     99 
    100 	/*
    101 	 * compact flash only has 11 bits address, while we needs 12 bits address.
    102 	 * MEM_SEG will be OR'd with other 11 bits address in hardware,
    103 	 * so we program MEM_SEG with 12th bit when necessary(access sb regsiters).
    104 	 * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special
    105 	 */
    106 	if (PCMCIA(sii)) {
    107 		INTR_OFF(sii, intr_val);
    108 		tmp = 1;
    109 		OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
    110 		sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */
    111 	}
    112 
    113 	if (BUSTYPE(sii->pub.bustype) == PCMCIA_BUS) {
    114 #ifdef IL_BIGENDIAN
    115 		dummy = R_REG(sii->osh, sbr);
    116 		W_REG(sii->osh, ((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff));
    117 		dummy = R_REG(sii->osh, sbr);
    118 		W_REG(sii->osh, (volatile uint16 *)sbr, (uint16)(v & 0xffff));
    119 #else
    120 		dummy = R_REG(sii->osh, sbr);
    121 		W_REG(sii->osh, (volatile uint16 *)sbr, (uint16)(v & 0xffff));
    122 		dummy = R_REG(sii->osh, sbr);
    123 		W_REG(sii->osh, ((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff));
    124 #endif	/* IL_BIGENDIAN */
    125 	} else
    126 		W_REG(sii->osh, sbr, v);
    127 
    128 	if (PCMCIA(sii)) {
    129 		tmp = 0;
    130 		OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
    131 		INTR_RESTORE(sii, intr_val);
    132 	}
    133 }
    134 
    135 uint
    136 sb_coreid(si_t *sih)
    137 {
    138 	si_info_t *sii;
    139 	sbconfig_t *sb;
    140 
    141 	sii = SI_INFO(sih);
    142 	sb = REGS2SB(sii->curmap);
    143 
    144 	return ((R_SBREG(sii, &sb->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT);
    145 }
    146 
    147 uint
    148 sb_flag(si_t *sih)
    149 {
    150 	si_info_t *sii;
    151 	sbconfig_t *sb;
    152 
    153 	sii = SI_INFO(sih);
    154 	sb = REGS2SB(sii->curmap);
    155 
    156 	return R_SBREG(sii, &sb->sbtpsflag) & SBTPS_NUM0_MASK;
    157 }
    158 
    159 void
    160 sb_setint(si_t *sih, int siflag)
    161 {
    162 	si_info_t *sii;
    163 	sbconfig_t *sb;
    164 	uint32 vec;
    165 
    166 	sii = SI_INFO(sih);
    167 	sb = REGS2SB(sii->curmap);
    168 
    169 	if (siflag == -1)
    170 		vec = 0;
    171 	else
    172 		vec = 1 << siflag;
    173 	W_SBREG(sii, &sb->sbintvec, vec);
    174 }
    175 
    176 /* return core index of the core with address 'sba' */
    177 static uint
    178 _sb_coreidx(si_info_t *sii, uint32 sba)
    179 {
    180 	uint i;
    181 
    182 	for (i = 0; i < sii->numcores; i ++)
    183 		if (sba == sii->common_info->coresba[i])
    184 			return i;
    185 	return BADIDX;
    186 }
    187 
    188 /* return core address of the current core */
    189 static uint32
    190 _sb_coresba(si_info_t *sii)
    191 {
    192 	uint32 sbaddr;
    193 
    194 
    195 	switch (BUSTYPE(sii->pub.bustype)) {
    196 	case SI_BUS: {
    197 		sbconfig_t *sb = REGS2SB(sii->curmap);
    198 		sbaddr = sb_base(R_SBREG(sii, &sb->sbadmatch0));
    199 		break;
    200 	}
    201 
    202 	case PCI_BUS:
    203 		sbaddr = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
    204 		break;
    205 
    206 	case PCMCIA_BUS: {
    207 		uint8 tmp = 0;
    208 		OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR0, &tmp, 1);
    209 		sbaddr  = (uint32)tmp << 12;
    210 		OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR1, &tmp, 1);
    211 		sbaddr |= (uint32)tmp << 16;
    212 		OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR2, &tmp, 1);
    213 		sbaddr |= (uint32)tmp << 24;
    214 		break;
    215 	}
    216 
    217 	case SPI_BUS:
    218 	case SDIO_BUS:
    219 		sbaddr = (uint32)(uintptr)sii->curmap;
    220 		break;
    221 
    222 
    223 	default:
    224 		sbaddr = BADCOREADDR;
    225 		break;
    226 	}
    227 
    228 	return sbaddr;
    229 }
    230 
    231 uint
    232 sb_corevendor(si_t *sih)
    233 {
    234 	si_info_t *sii;
    235 	sbconfig_t *sb;
    236 
    237 	sii = SI_INFO(sih);
    238 	sb = REGS2SB(sii->curmap);
    239 
    240 	return ((R_SBREG(sii, &sb->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT);
    241 }
    242 
    243 uint
    244 sb_corerev(si_t *sih)
    245 {
    246 	si_info_t *sii;
    247 	sbconfig_t *sb;
    248 	uint sbidh;
    249 
    250 	sii = SI_INFO(sih);
    251 	sb = REGS2SB(sii->curmap);
    252 	sbidh = R_SBREG(sii, &sb->sbidhigh);
    253 
    254 	return (SBCOREREV(sbidh));
    255 }
    256 
    257 /* set core-specific control flags */
    258 void
    259 sb_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
    260 {
    261 	si_info_t *sii;
    262 	sbconfig_t *sb;
    263 	uint32 w;
    264 
    265 	sii = SI_INFO(sih);
    266 	sb = REGS2SB(sii->curmap);
    267 
    268 	ASSERT((val & ~mask) == 0);
    269 
    270 	/* mask and set */
    271 	w = (R_SBREG(sii, &sb->sbtmstatelow) & ~(mask << SBTML_SICF_SHIFT)) |
    272 	        (val << SBTML_SICF_SHIFT);
    273 	W_SBREG(sii, &sb->sbtmstatelow, w);
    274 }
    275 
    276 /* set/clear core-specific control flags */
    277 uint32
    278 sb_core_cflags(si_t *sih, uint32 mask, uint32 val)
    279 {
    280 	si_info_t *sii;
    281 	sbconfig_t *sb;
    282 	uint32 w;
    283 
    284 	sii = SI_INFO(sih);
    285 	sb = REGS2SB(sii->curmap);
    286 
    287 	ASSERT((val & ~mask) == 0);
    288 
    289 	/* mask and set */
    290 	if (mask || val) {
    291 		w = (R_SBREG(sii, &sb->sbtmstatelow) & ~(mask << SBTML_SICF_SHIFT)) |
    292 		        (val << SBTML_SICF_SHIFT);
    293 		W_SBREG(sii, &sb->sbtmstatelow, w);
    294 	}
    295 
    296 	/* return the new value
    297 	 * for write operation, the following readback ensures the completion of write opration.
    298 	 */
    299 	return (R_SBREG(sii, &sb->sbtmstatelow) >> SBTML_SICF_SHIFT);
    300 }
    301 
    302 /* set/clear core-specific status flags */
    303 uint32
    304 sb_core_sflags(si_t *sih, uint32 mask, uint32 val)
    305 {
    306 	si_info_t *sii;
    307 	sbconfig_t *sb;
    308 	uint32 w;
    309 
    310 	sii = SI_INFO(sih);
    311 	sb = REGS2SB(sii->curmap);
    312 
    313 	ASSERT((val & ~mask) == 0);
    314 	ASSERT((mask & ~SISF_CORE_BITS) == 0);
    315 
    316 	/* mask and set */
    317 	if (mask || val) {
    318 		w = (R_SBREG(sii, &sb->sbtmstatehigh) & ~(mask << SBTMH_SISF_SHIFT)) |
    319 		        (val << SBTMH_SISF_SHIFT);
    320 		W_SBREG(sii, &sb->sbtmstatehigh, w);
    321 	}
    322 
    323 	/* return the new value */
    324 	return (R_SBREG(sii, &sb->sbtmstatehigh) >> SBTMH_SISF_SHIFT);
    325 }
    326 
    327 bool
    328 sb_iscoreup(si_t *sih)
    329 {
    330 	si_info_t *sii;
    331 	sbconfig_t *sb;
    332 
    333 	sii = SI_INFO(sih);
    334 	sb = REGS2SB(sii->curmap);
    335 
    336 	return ((R_SBREG(sii, &sb->sbtmstatelow) &
    337 	         (SBTML_RESET | SBTML_REJ_MASK | (SICF_CLOCK_EN << SBTML_SICF_SHIFT))) ==
    338 	        (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
    339 }
    340 
    341 /*
    342  * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation,
    343  * switch back to the original core, and return the new value.
    344  *
    345  * When using the silicon backplane, no fidleing with interrupts or core switches are needed.
    346  *
    347  * Also, when using pci/pcie, we can optimize away the core switching for pci registers
    348  * and (on newer pci cores) chipcommon registers.
    349  */
    350 uint
    351 sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
    352 {
    353 	uint origidx = 0;
    354 	uint32 *r = NULL;
    355 	uint w;
    356 	uint intr_val = 0;
    357 	bool fast = FALSE;
    358 	si_info_t *sii;
    359 
    360 	sii = SI_INFO(sih);
    361 
    362 	ASSERT(GOODIDX(coreidx));
    363 	ASSERT(regoff < SI_CORE_SIZE);
    364 	ASSERT((val & ~mask) == 0);
    365 
    366 	if (coreidx >= SI_MAXCORES)
    367 		return 0;
    368 
    369 	if (BUSTYPE(sii->pub.bustype) == SI_BUS) {
    370 		/* If internal bus, we can always get at everything */
    371 		fast = TRUE;
    372 		/* map if does not exist */
    373 		if (!sii->common_info->regs[coreidx]) {
    374 			sii->common_info->regs[coreidx] =
    375 			    REG_MAP(sii->common_info->coresba[coreidx], SI_CORE_SIZE);
    376 			ASSERT(GOODREGS(sii->common_info->regs[coreidx]));
    377 		}
    378 		r = (uint32 *)((uchar *)sii->common_info->regs[coreidx] + regoff);
    379 	} else if (BUSTYPE(sii->pub.bustype) == PCI_BUS) {
    380 		/* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */
    381 
    382 		if ((sii->common_info->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
    383 			/* Chipc registers are mapped at 12KB */
    384 
    385 			fast = TRUE;
    386 			r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff);
    387 		} else if (sii->pub.buscoreidx == coreidx) {
    388 			/* pci registers are at either in the last 2KB of an 8KB window
    389 			 * or, in pcie and pci rev 13 at 8KB
    390 			 */
    391 			fast = TRUE;
    392 			if (SI_FAST(sii))
    393 				r = (uint32 *)((char *)sii->curmap +
    394 				               PCI_16KB0_PCIREGS_OFFSET + regoff);
    395 			else
    396 				r = (uint32 *)((char *)sii->curmap +
    397 				               ((regoff >= SBCONFIGOFF) ?
    398 				                PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) +
    399 				               regoff);
    400 		}
    401 	}
    402 
    403 	if (!fast) {
    404 		INTR_OFF(sii, intr_val);
    405 
    406 		/* save current core index */
    407 		origidx = si_coreidx(&sii->pub);
    408 
    409 		/* switch core */
    410 		r = (uint32*) ((uchar*)sb_setcoreidx(&sii->pub, coreidx) + regoff);
    411 	}
    412 	ASSERT(r != NULL);
    413 
    414 	/* mask and set */
    415 	if (mask || val) {
    416 		if (regoff >= SBCONFIGOFF) {
    417 			w = (R_SBREG(sii, r) & ~mask) | val;
    418 			W_SBREG(sii, r, w);
    419 		} else {
    420 			w = (R_REG(sii->osh, r) & ~mask) | val;
    421 			W_REG(sii->osh, r, w);
    422 		}
    423 	}
    424 
    425 	/* readback */
    426 	if (regoff >= SBCONFIGOFF)
    427 		w = R_SBREG(sii, r);
    428 	else {
    429 		if ((CHIPID(sii->pub.chip) == BCM5354_CHIP_ID) &&
    430 		    (coreidx == SI_CC_IDX) &&
    431 		    (regoff == OFFSETOF(chipcregs_t, watchdog))) {
    432 			w = val;
    433 		} else
    434 			w = R_REG(sii->osh, r);
    435 	}
    436 
    437 	if (!fast) {
    438 		/* restore core index */
    439 		if (origidx != coreidx)
    440 			sb_setcoreidx(&sii->pub, origidx);
    441 
    442 		INTR_RESTORE(sii, intr_val);
    443 	}
    444 
    445 	return (w);
    446 }
    447 
    448 /* Scan the enumeration space to find all cores starting from the given
    449  * bus 'sbba'. Append coreid and other info to the lists in 'si'. 'sba'
    450  * is the default core address at chip POR time and 'regs' is the virtual
    451  * address that the default core is mapped at. 'ncores' is the number of
    452  * cores expected on bus 'sbba'. It returns the total number of cores
    453  * starting from bus 'sbba', inclusive.
    454  */
    455 #define SB_MAXBUSES	2
    456 static uint
    457 _sb_scan(si_info_t *sii, uint32 sba, void *regs, uint bus, uint32 sbba, uint numcores)
    458 {
    459 	uint next;
    460 	uint ncc = 0;
    461 	uint i;
    462 
    463 	if (bus >= SB_MAXBUSES) {
    464 		SI_ERROR(("_sb_scan: bus 0x%08x at level %d is too deep to scan\n", sbba, bus));
    465 		return 0;
    466 	}
    467 	SI_MSG(("_sb_scan: scan bus 0x%08x assume %u cores\n", sbba, numcores));
    468 
    469 	/* Scan all cores on the bus starting from core 0.
    470 	 * Core addresses must be contiguous on each bus.
    471 	 */
    472 	for (i = 0, next = sii->numcores; i < numcores && next < SB_BUS_MAXCORES; i++, next++) {
    473 		sii->common_info->coresba[next] = sbba + (i * SI_CORE_SIZE);
    474 
    475 		/* keep and reuse the initial register mapping */
    476 		if ((BUSTYPE(sii->pub.bustype) == SI_BUS) &&
    477 			(sii->common_info->coresba[next] == sba)) {
    478 			SI_MSG(("_sb_scan: reuse mapped regs %p for core %u\n", regs, next));
    479 			sii->common_info->regs[next] = regs;
    480 		}
    481 
    482 		/* change core to 'next' and read its coreid */
    483 		sii->curmap = _sb_setcoreidx(sii, next);
    484 		sii->curidx = next;
    485 
    486 		sii->common_info->coreid[next] = sb_coreid(&sii->pub);
    487 
    488 		/* core specific processing... */
    489 		/* chipc provides # cores */
    490 		if (sii->common_info->coreid[next] == CC_CORE_ID) {
    491 			chipcregs_t *cc = (chipcregs_t *)sii->curmap;
    492 			uint32 ccrev = sb_corerev(&sii->pub);
    493 
    494 			/* determine numcores - this is the total # cores in the chip */
    495 			if (((ccrev == 4) || (ccrev >= 6)))
    496 				numcores = (R_REG(sii->osh, &cc->chipid) & CID_CC_MASK) >>
    497 				        CID_CC_SHIFT;
    498 			else {
    499 				/* Older chips */
    500 				uint chip = sii->pub.chip;
    501 
    502 				if (chip == BCM4306_CHIP_ID)	/* < 4306c0 */
    503 					numcores = 6;
    504 				else if (chip == BCM4704_CHIP_ID)
    505 					numcores = 9;
    506 				else if (chip == BCM5365_CHIP_ID)
    507 					numcores = 7;
    508 				else {
    509 					SI_ERROR(("sb_chip2numcores: unsupported chip 0x%x\n",
    510 					          chip));
    511 					ASSERT(0);
    512 					numcores = 1;
    513 				}
    514 			}
    515 			SI_MSG(("_sb_scan: there are %u cores in the chip %s\n", numcores,
    516 				sii->pub.issim ? "QT" : ""));
    517 		}
    518 		/* scan bridged SB(s) and add results to the end of the list */
    519 		else if (sii->common_info->coreid[next] == OCP_CORE_ID) {
    520 			sbconfig_t *sb = REGS2SB(sii->curmap);
    521 			uint32 nsbba = R_SBREG(sii, &sb->sbadmatch1);
    522 			uint nsbcc;
    523 
    524 			sii->numcores = next + 1;
    525 
    526 			if ((nsbba & 0xfff00000) != SI_ENUM_BASE)
    527 				continue;
    528 			nsbba &= 0xfffff000;
    529 			if (_sb_coreidx(sii, nsbba) != BADIDX)
    530 				continue;
    531 
    532 			nsbcc = (R_SBREG(sii, &sb->sbtmstatehigh) & 0x000f0000) >> 16;
    533 			nsbcc = _sb_scan(sii, sba, regs, bus + 1, nsbba, nsbcc);
    534 			if (sbba == SI_ENUM_BASE)
    535 				numcores -= nsbcc;
    536 			ncc += nsbcc;
    537 		}
    538 	}
    539 
    540 	SI_MSG(("_sb_scan: found %u cores on bus 0x%08x\n", i, sbba));
    541 
    542 	sii->numcores = i + ncc;
    543 	return sii->numcores;
    544 }
    545 
    546 /* scan the sb enumerated space to identify all cores */
    547 void
    548 sb_scan(si_t *sih, void *regs, uint devid)
    549 {
    550 	si_info_t *sii;
    551 	uint32 origsba;
    552 
    553 	sii = SI_INFO(sih);
    554 
    555 	/* Save the current core info and validate it later till we know
    556 	 * for sure what is good and what is bad.
    557 	 */
    558 	origsba = _sb_coresba(sii);
    559 
    560 	/* scan all SB(s) starting from SI_ENUM_BASE */
    561 	sii->numcores = _sb_scan(sii, origsba, regs, 0, SI_ENUM_BASE, 1);
    562 }
    563 
    564 /*
    565  * This function changes logical "focus" to the indicated core;
    566  * must be called with interrupts off.
    567  * Moreover, callers should keep interrupts off during switching out of and back to d11 core
    568  */
    569 void *
    570 sb_setcoreidx(si_t *sih, uint coreidx)
    571 {
    572 	si_info_t *sii;
    573 
    574 	sii = SI_INFO(sih);
    575 
    576 	if (coreidx >= sii->numcores)
    577 		return (NULL);
    578 
    579 	/*
    580 	 * If the user has provided an interrupt mask enabled function,
    581 	 * then assert interrupts are disabled before switching the core.
    582 	 */
    583 	ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg));
    584 
    585 	sii->curmap = _sb_setcoreidx(sii, coreidx);
    586 	sii->curidx = coreidx;
    587 
    588 	return (sii->curmap);
    589 }
    590 
    591 /* This function changes the logical "focus" to the indicated core.
    592  * Return the current core's virtual address.
    593  */
    594 static void *
    595 _sb_setcoreidx(si_info_t *sii, uint coreidx)
    596 {
    597 	uint32 sbaddr = sii->common_info->coresba[coreidx];
    598 	void *regs;
    599 
    600 	switch (BUSTYPE(sii->pub.bustype)) {
    601 	case SI_BUS:
    602 		/* map new one */
    603 		if (!sii->common_info->regs[coreidx]) {
    604 			sii->common_info->regs[coreidx] = REG_MAP(sbaddr, SI_CORE_SIZE);
    605 			ASSERT(GOODREGS(sii->common_info->regs[coreidx]));
    606 		}
    607 		regs = sii->common_info->regs[coreidx];
    608 		break;
    609 
    610 	case PCI_BUS:
    611 		/* point bar0 window */
    612 		OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, sbaddr);
    613 		regs = sii->curmap;
    614 		break;
    615 
    616 	case PCMCIA_BUS: {
    617 		uint8 tmp = (sbaddr >> 12) & 0x0f;
    618 		OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR0, &tmp, 1);
    619 		tmp = (sbaddr >> 16) & 0xff;
    620 		OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR1, &tmp, 1);
    621 		tmp = (sbaddr >> 24) & 0xff;
    622 		OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR2, &tmp, 1);
    623 		regs = sii->curmap;
    624 		break;
    625 	}
    626 	case SPI_BUS:
    627 	case SDIO_BUS:
    628 		/* map new one */
    629 		if (!sii->common_info->regs[coreidx]) {
    630 			sii->common_info->regs[coreidx] = (void *)(uintptr)sbaddr;
    631 			ASSERT(GOODREGS(sii->common_info->regs[coreidx]));
    632 		}
    633 		regs = sii->common_info->regs[coreidx];
    634 		break;
    635 
    636 
    637 	default:
    638 		ASSERT(0);
    639 		regs = NULL;
    640 		break;
    641 	}
    642 
    643 	return regs;
    644 }
    645 
    646 /* Return the address of sbadmatch0/1/2/3 register */
    647 static volatile uint32 *
    648 sb_admatch(si_info_t *sii, uint asidx)
    649 {
    650 	sbconfig_t *sb;
    651 	volatile uint32 *addrm;
    652 
    653 	sb = REGS2SB(sii->curmap);
    654 
    655 	switch (asidx) {
    656 	case 0:
    657 		addrm =  &sb->sbadmatch0;
    658 		break;
    659 
    660 	case 1:
    661 		addrm =  &sb->sbadmatch1;
    662 		break;
    663 
    664 	case 2:
    665 		addrm =  &sb->sbadmatch2;
    666 		break;
    667 
    668 	case 3:
    669 		addrm =  &sb->sbadmatch3;
    670 		break;
    671 
    672 	default:
    673 		SI_ERROR(("%s: Address space index (%d) out of range\n", __FUNCTION__, asidx));
    674 		return 0;
    675 	}
    676 
    677 	return (addrm);
    678 }
    679 
    680 /* Return the number of address spaces in current core */
    681 int
    682 sb_numaddrspaces(si_t *sih)
    683 {
    684 	si_info_t *sii;
    685 	sbconfig_t *sb;
    686 
    687 	sii = SI_INFO(sih);
    688 	sb = REGS2SB(sii->curmap);
    689 
    690 	/* + 1 because of enumeration space */
    691 	return ((R_SBREG(sii, &sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT) + 1;
    692 }
    693 
    694 /* Return the address of the nth address space in the current core */
    695 uint32
    696 sb_addrspace(si_t *sih, uint asidx)
    697 {
    698 	si_info_t *sii;
    699 
    700 	sii = SI_INFO(sih);
    701 
    702 	return (sb_base(R_SBREG(sii, sb_admatch(sii, asidx))));
    703 }
    704 
    705 /* Return the size of the nth address space in the current core */
    706 uint32
    707 sb_addrspacesize(si_t *sih, uint asidx)
    708 {
    709 	si_info_t *sii;
    710 
    711 	sii = SI_INFO(sih);
    712 
    713 	return (sb_size(R_SBREG(sii, sb_admatch(sii, asidx))));
    714 }
    715 
    716 
    717 /* do buffered registers update */
    718 void
    719 sb_commit(si_t *sih)
    720 {
    721 	si_info_t *sii;
    722 	uint origidx;
    723 	uint intr_val = 0;
    724 
    725 	sii = SI_INFO(sih);
    726 
    727 	origidx = sii->curidx;
    728 	ASSERT(GOODIDX(origidx));
    729 
    730 	INTR_OFF(sii, intr_val);
    731 
    732 	/* switch over to chipcommon core if there is one, else use pci */
    733 	if (sii->pub.ccrev != NOREV) {
    734 		chipcregs_t *ccregs = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
    735 
    736 		/* do the buffer registers update */
    737 		W_REG(sii->osh, &ccregs->broadcastaddress, SB_COMMIT);
    738 		W_REG(sii->osh, &ccregs->broadcastdata, 0x0);
    739 	} else
    740 		ASSERT(0);
    741 
    742 	/* restore core index */
    743 	sb_setcoreidx(sih, origidx);
    744 	INTR_RESTORE(sii, intr_val);
    745 }
    746 
    747 void
    748 sb_core_disable(si_t *sih, uint32 bits)
    749 {
    750 	si_info_t *sii;
    751 	volatile uint32 dummy;
    752 	sbconfig_t *sb;
    753 
    754 	sii = SI_INFO(sih);
    755 
    756 	ASSERT(GOODREGS(sii->curmap));
    757 	sb = REGS2SB(sii->curmap);
    758 
    759 	/* if core is already in reset, just return */
    760 	if (R_SBREG(sii, &sb->sbtmstatelow) & SBTML_RESET)
    761 		return;
    762 
    763 	/* if clocks are not enabled, put into reset and return */
    764 	if ((R_SBREG(sii, &sb->sbtmstatelow) & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) == 0)
    765 		goto disable;
    766 
    767 	/* set target reject and spin until busy is clear (preserve core-specific bits) */
    768 	OR_SBREG(sii, &sb->sbtmstatelow, SBTML_REJ);
    769 	dummy = R_SBREG(sii, &sb->sbtmstatelow);
    770 	OSL_DELAY(1);
    771 	SPINWAIT((R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_BUSY), 100000);
    772 	if (R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_BUSY)
    773 		SI_ERROR(("%s: target state still busy\n", __FUNCTION__));
    774 
    775 	if (R_SBREG(sii, &sb->sbidlow) & SBIDL_INIT) {
    776 		OR_SBREG(sii, &sb->sbimstate, SBIM_RJ);
    777 		dummy = R_SBREG(sii, &sb->sbimstate);
    778 		OSL_DELAY(1);
    779 		SPINWAIT((R_SBREG(sii, &sb->sbimstate) & SBIM_BY), 100000);
    780 	}
    781 
    782 	/* set reset and reject while enabling the clocks */
    783 	W_SBREG(sii, &sb->sbtmstatelow,
    784 	        (((bits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
    785 	         SBTML_REJ | SBTML_RESET));
    786 	dummy = R_SBREG(sii, &sb->sbtmstatelow);
    787 	OSL_DELAY(10);
    788 
    789 	/* don't forget to clear the initiator reject bit */
    790 	if (R_SBREG(sii, &sb->sbidlow) & SBIDL_INIT)
    791 		AND_SBREG(sii, &sb->sbimstate, ~SBIM_RJ);
    792 
    793 disable:
    794 	/* leave reset and reject asserted */
    795 	W_SBREG(sii, &sb->sbtmstatelow, ((bits << SBTML_SICF_SHIFT) | SBTML_REJ | SBTML_RESET));
    796 	OSL_DELAY(1);
    797 }
    798 
    799 /* reset and re-enable a core
    800  * inputs:
    801  * bits - core specific bits that are set during and after reset sequence
    802  * resetbits - core specific bits that are set only during reset sequence
    803  */
    804 void
    805 sb_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
    806 {
    807 	si_info_t *sii;
    808 	sbconfig_t *sb;
    809 	volatile uint32 dummy;
    810 
    811 	sii = SI_INFO(sih);
    812 	ASSERT(GOODREGS(sii->curmap));
    813 	sb = REGS2SB(sii->curmap);
    814 
    815 	/*
    816 	 * Must do the disable sequence first to work for arbitrary current core state.
    817 	 */
    818 	sb_core_disable(sih, (bits | resetbits));
    819 
    820 	/*
    821 	 * Now do the initialization sequence.
    822 	 */
    823 
    824 	/* set reset while enabling the clock and forcing them on throughout the core */
    825 	W_SBREG(sii, &sb->sbtmstatelow,
    826 	        (((bits | resetbits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
    827 	         SBTML_RESET));
    828 	dummy = R_SBREG(sii, &sb->sbtmstatelow);
    829 	OSL_DELAY(1);
    830 
    831 	if (R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_SERR) {
    832 		W_SBREG(sii, &sb->sbtmstatehigh, 0);
    833 	}
    834 	if ((dummy = R_SBREG(sii, &sb->sbimstate)) & (SBIM_IBE | SBIM_TO)) {
    835 		AND_SBREG(sii, &sb->sbimstate, ~(SBIM_IBE | SBIM_TO));
    836 	}
    837 
    838 	/* clear reset and allow it to propagate throughout the core */
    839 	W_SBREG(sii, &sb->sbtmstatelow,
    840 	        ((bits | resetbits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT));
    841 	dummy = R_SBREG(sii, &sb->sbtmstatelow);
    842 	OSL_DELAY(1);
    843 
    844 	/* leave clock enabled */
    845 	W_SBREG(sii, &sb->sbtmstatelow, ((bits | SICF_CLOCK_EN) << SBTML_SICF_SHIFT));
    846 	dummy = R_SBREG(sii, &sb->sbtmstatelow);
    847 	OSL_DELAY(1);
    848 }
    849 
    850 void
    851 sb_core_tofixup(si_t *sih)
    852 {
    853 	si_info_t *sii;
    854 	sbconfig_t *sb;
    855 
    856 	sii = SI_INFO(sih);
    857 
    858 	if ((BUSTYPE(sii->pub.bustype) != PCI_BUS) || PCIE(sii) ||
    859 	    (PCI(sii) && (sii->pub.buscorerev >= 5)))
    860 		return;
    861 
    862 	ASSERT(GOODREGS(sii->curmap));
    863 	sb = REGS2SB(sii->curmap);
    864 
    865 	if (BUSTYPE(sii->pub.bustype) == SI_BUS) {
    866 		SET_SBREG(sii, &sb->sbimconfiglow,
    867 		          SBIMCL_RTO_MASK | SBIMCL_STO_MASK,
    868 		          (0x5 << SBIMCL_RTO_SHIFT) | 0x3);
    869 	} else {
    870 		if (sb_coreid(sih) == PCI_CORE_ID) {
    871 			SET_SBREG(sii, &sb->sbimconfiglow,
    872 			          SBIMCL_RTO_MASK | SBIMCL_STO_MASK,
    873 			          (0x3 << SBIMCL_RTO_SHIFT) | 0x2);
    874 		} else {
    875 			SET_SBREG(sii, &sb->sbimconfiglow, (SBIMCL_RTO_MASK | SBIMCL_STO_MASK), 0);
    876 		}
    877 	}
    878 
    879 	sb_commit(sih);
    880 }
    881 
    882 /*
    883  * Set the initiator timeout for the "master core".
    884  * The master core is defined to be the core in control
    885  * of the chip and so it issues accesses to non-memory
    886  * locations (Because of dma *any* core can access memeory).
    887  *
    888  * The routine uses the bus to decide who is the master:
    889  *	SI_BUS => mips
    890  *	JTAG_BUS => chipc
    891  *	PCI_BUS => pci or pcie
    892  *	PCMCIA_BUS => pcmcia
    893  *	SDIO_BUS => pcmcia
    894  *
    895  * This routine exists so callers can disable initiator
    896  * timeouts so accesses to very slow devices like otp
    897  * won't cause an abort. The routine allows arbitrary
    898  * settings of the service and request timeouts, though.
    899  *
    900  * Returns the timeout state before changing it or -1
    901  * on error.
    902  */
    903 
    904 #define	TO_MASK	(SBIMCL_RTO_MASK | SBIMCL_STO_MASK)
    905 
    906 uint32
    907 sb_set_initiator_to(si_t *sih, uint32 to, uint idx)
    908 {
    909 	si_info_t *sii;
    910 	uint origidx;
    911 	uint intr_val = 0;
    912 	uint32 tmp, ret = 0xffffffff;
    913 	sbconfig_t *sb;
    914 
    915 	sii = SI_INFO(sih);
    916 
    917 	if ((to & ~TO_MASK) != 0)
    918 		return ret;
    919 
    920 	/* Figure out the master core */
    921 	if (idx == BADIDX) {
    922 		switch (BUSTYPE(sii->pub.bustype)) {
    923 		case PCI_BUS:
    924 			idx = sii->pub.buscoreidx;
    925 			break;
    926 		case JTAG_BUS:
    927 			idx = SI_CC_IDX;
    928 			break;
    929 		case PCMCIA_BUS:
    930 		case SDIO_BUS:
    931 			idx = si_findcoreidx(sih, PCMCIA_CORE_ID, 0);
    932 			break;
    933 		case SI_BUS:
    934 			idx = si_findcoreidx(sih, MIPS33_CORE_ID, 0);
    935 			break;
    936 		default:
    937 			ASSERT(0);
    938 		}
    939 		if (idx == BADIDX)
    940 			return ret;
    941 	}
    942 
    943 	INTR_OFF(sii, intr_val);
    944 	origidx = si_coreidx(sih);
    945 
    946 	sb = REGS2SB(sb_setcoreidx(sih, idx));
    947 
    948 	tmp = R_SBREG(sii, &sb->sbimconfiglow);
    949 	ret = tmp & TO_MASK;
    950 	W_SBREG(sii, &sb->sbimconfiglow, (tmp & ~TO_MASK) | to);
    951 
    952 	sb_commit(sih);
    953 	sb_setcoreidx(sih, origidx);
    954 	INTR_RESTORE(sii, intr_val);
    955 	return ret;
    956 }
    957 
    958 uint32
    959 sb_base(uint32 admatch)
    960 {
    961 	uint32 base;
    962 	uint type;
    963 
    964 	type = admatch & SBAM_TYPE_MASK;
    965 	ASSERT(type < 3);
    966 
    967 	base = 0;
    968 
    969 	if (type == 0) {
    970 		base = admatch & SBAM_BASE0_MASK;
    971 	} else if (type == 1) {
    972 		ASSERT(!(admatch & SBAM_ADNEG));	/* neg not supported */
    973 		base = admatch & SBAM_BASE1_MASK;
    974 	} else if (type == 2) {
    975 		ASSERT(!(admatch & SBAM_ADNEG));	/* neg not supported */
    976 		base = admatch & SBAM_BASE2_MASK;
    977 	}
    978 
    979 	return (base);
    980 }
    981 
    982 uint32
    983 sb_size(uint32 admatch)
    984 {
    985 	uint32 size;
    986 	uint type;
    987 
    988 	type = admatch & SBAM_TYPE_MASK;
    989 	ASSERT(type < 3);
    990 
    991 	size = 0;
    992 
    993 	if (type == 0) {
    994 		size = 1 << (((admatch & SBAM_ADINT0_MASK) >> SBAM_ADINT0_SHIFT) + 1);
    995 	} else if (type == 1) {
    996 		ASSERT(!(admatch & SBAM_ADNEG));	/* neg not supported */
    997 		size = 1 << (((admatch & SBAM_ADINT1_MASK) >> SBAM_ADINT1_SHIFT) + 1);
    998 	} else if (type == 2) {
    999 		ASSERT(!(admatch & SBAM_ADNEG));	/* neg not supported */
   1000 		size = 1 << (((admatch & SBAM_ADINT2_MASK) >> SBAM_ADINT2_SHIFT) + 1);
   1001 	}
   1002 
   1003 	return (size);
   1004 }
   1005