• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Misc utility routines for accessing chip-specific features
3  * of the SiliconBackplane-based Broadcom chips.
4  *
5  * Copyright (C) 1999-2009, 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: aiutils.c,v 1.6.4.7.4.5 2009/09/25 00:32:01 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 <hndsoc.h>
34 #include <sbchipc.h>
35 #include <pcicfg.h>
36 
37 #include "siutils_priv.h"
38 
39 STATIC uint32
40 get_asd(si_t *sih, uint32 *eromptr, uint sp, uint ad, uint st,
41 	uint32 *addrl, uint32 *addrh, uint32 *sizel, uint32 *sizeh);
42 
43 
44 /* EROM parsing */
45 
46 static uint32
get_erom_ent(si_t * sih,uint32 * eromptr,uint32 mask,uint32 match)47 get_erom_ent(si_t *sih, uint32 *eromptr, uint32 mask, uint32 match)
48 {
49 	uint32 ent;
50 	uint inv = 0, nom = 0;
51 
52 	while (TRUE) {
53 		ent = R_REG(si_osh(sih), (uint32 *)(uintptr)(*eromptr));
54 		*eromptr += sizeof(uint32);
55 
56 		if (mask == 0)
57 			break;
58 
59 		if ((ent & ER_VALID) == 0) {
60 			inv++;
61 			continue;
62 		}
63 
64 		if (ent == (ER_END | ER_VALID))
65 			break;
66 
67 		if ((ent & mask) == match)
68 			break;
69 
70 		nom++;
71 	}
72 
73 	SI_MSG(("%s: Returning ent 0x%08x\n", __FUNCTION__, ent));
74 	if (inv + nom)
75 		SI_MSG(("  after %d invalid and %d non-matching entries\n", inv, nom));
76 	return ent;
77 }
78 
79 STATIC uint32
get_asd(si_t * sih,uint32 * eromptr,uint sp,uint ad,uint st,uint32 * addrl,uint32 * addrh,uint32 * sizel,uint32 * sizeh)80 get_asd(si_t *sih, uint32 *eromptr, uint sp, uint ad, uint st,
81 	uint32 *addrl, uint32 *addrh, uint32 *sizel, uint32 *sizeh)
82 {
83 	uint32 asd, sz, szd;
84 
85 	asd = get_erom_ent(sih, eromptr, ER_VALID, ER_VALID);
86 	if (((asd & ER_TAG1) != ER_ADD) ||
87 	    (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) ||
88 	    ((asd & AD_ST_MASK) != st)) {
89 		/* This is not what we want, "push" it back */
90 		*eromptr -= sizeof(uint32);
91 		return 0;
92 	}
93 	*addrl = asd & AD_ADDR_MASK;
94 	if (asd & AD_AG32)
95 		*addrh = get_erom_ent(sih, eromptr, 0, 0);
96 	else
97 		*addrh = 0;
98 	*sizeh = 0;
99 	sz = asd & AD_SZ_MASK;
100 	if (sz == AD_SZ_SZD) {
101 		szd = get_erom_ent(sih, eromptr, 0, 0);
102 		*sizel = szd & SD_SZ_MASK;
103 		if (szd & SD_SG32)
104 			*sizeh = get_erom_ent(sih, eromptr, 0, 0);
105 	} else
106 		*sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT);
107 
108 	SI_MSG(("  SP %d, ad %d: st = %d, 0x%08x_0x%08x @ 0x%08x_0x%08x\n",
109 	        sp, ad, st, *sizeh, *sizel, *addrh, *addrl));
110 
111 	return asd;
112 }
113 
114 /* parse the enumeration rom to identify all cores */
115 void
ai_scan(si_t * sih,void * regs,uint devid)116 ai_scan(si_t *sih, void *regs, uint devid)
117 {
118 	si_info_t *sii = SI_INFO(sih);
119 	chipcregs_t *cc = (chipcregs_t *)regs;
120 	uint32 erombase, eromptr, eromlim;
121 
122 	erombase = R_REG(sii->osh, &cc->eromptr);
123 
124 	switch (BUSTYPE(sih->bustype)) {
125 	case SI_BUS:
126 		eromptr = (uintptr)REG_MAP(erombase, SI_CORE_SIZE);
127 		break;
128 
129 	case PCI_BUS:
130 		/* Set wrappers address */
131 		sii->curwrap = (void *)((uintptr)regs + SI_CORE_SIZE);
132 
133 		/* Now point the window at the erom */
134 		OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, erombase);
135 		eromptr = (uint32)(uintptr)regs;
136 		break;
137 
138 	case SPI_BUS:
139 	case SDIO_BUS:
140 		eromptr = erombase;
141 		break;
142 
143 	case PCMCIA_BUS:
144 	default:
145 		SI_ERROR(("Don't know how to do AXI enumertion on bus %d\n", sih->bustype));
146 		ASSERT(0);
147 		return;
148 	}
149 	eromlim = eromptr + ER_REMAPCONTROL;
150 
151 	SI_MSG(("ai_scan: regs = 0x%p, erombase = 0x%08x, eromptr = 0x%08x, eromlim = 0x%08x\n",
152 	        regs, erombase, eromptr, eromlim));
153 	while (eromptr < eromlim) {
154 		uint32 cia, cib, base, cid, mfg, crev, nmw, nsw, nmp, nsp;
155 		uint32 mpd, asd, addrl, addrh, sizel, sizeh;
156 		uint i, j, idx;
157 		bool br;
158 
159 		br = FALSE;
160 
161 		/* Grok a component */
162 		cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI);
163 		if (cia == (ER_END | ER_VALID)) {
164 			SI_MSG(("Found END of erom after %d cores\n", sii->numcores));
165 			return;
166 		}
167 		base = eromptr - sizeof(uint32);
168 		cib = get_erom_ent(sih, &eromptr, 0, 0);
169 
170 		if ((cib & ER_TAG) != ER_CI) {
171 			SI_ERROR(("CIA not followed by CIB\n"));
172 			goto error;
173 		}
174 
175 		cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT;
176 		mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT;
177 		crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
178 		nmw = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT;
179 		nsw = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT;
180 		nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT;
181 		nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT;
182 
183 		SI_MSG(("Found component 0x%04x/0x%4x rev %d at erom addr 0x%08x, with nmw = %d, "
184 		        "nsw = %d, nmp = %d & nsp = %d\n",
185 		        mfg, cid, crev, base, nmw, nsw, nmp, nsp));
186 
187 		if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0))
188 			continue;
189 		if ((nmw + nsw == 0)) {
190 			/* A component which is not a core */
191 			if (cid == OOB_ROUTER_CORE_ID) {
192 				asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE,
193 					&addrl, &addrh, &sizel, &sizeh);
194 				if (asd != 0) {
195 					sii->common_info->oob_router = addrl;
196 				}
197 			}
198 			continue;
199 		}
200 
201 		idx = sii->numcores;
202 /*		sii->eromptr[idx] = base; */
203 		sii->common_info->cia[idx] = cia;
204 		sii->common_info->cib[idx] = cib;
205 		sii->common_info->coreid[idx] = cid;
206 
207 		for (i = 0; i < nmp; i++) {
208 			mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID);
209 			if ((mpd & ER_TAG) != ER_MP) {
210 				SI_ERROR(("Not enough MP entries for component 0x%x\n", cid));
211 				goto error;
212 			}
213 			SI_MSG(("  Master port %d, mp: %d id: %d\n", i,
214 			        (mpd & MPD_MP_MASK) >> MPD_MP_SHIFT,
215 			        (mpd & MPD_MUI_MASK) >> MPD_MUI_SHIFT));
216 		}
217 
218 		/* First Slave Address Descriptor should be port 0:
219 		 * the main register space for the core
220 		 */
221 		asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh);
222 		if (asd == 0) {
223 			/* Try again to see if it is a bridge */
224 			asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh,
225 			              &sizel, &sizeh);
226 			if (asd != 0)
227 				br = TRUE;
228 			else
229 				if ((addrh != 0) || (sizeh != 0) || (sizel != SI_CORE_SIZE)) {
230 					SI_ERROR(("First Slave ASD for core 0x%04x malformed "
231 					          "(0x%08x)\n", cid, asd));
232 					goto error;
233 				}
234 		}
235 		sii->common_info->coresba[idx] = addrl;
236 		sii->common_info->coresba_size[idx] = sizel;
237 		/* Get any more ASDs in port 0 */
238 		j = 1;
239 		do {
240 			asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh,
241 			              &sizel, &sizeh);
242 			if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE))
243 				sii->common_info->coresba2[idx] = addrl;
244 				sii->common_info->coresba2_size[idx] = sizel;
245 			j++;
246 		} while (asd != 0);
247 
248 		/* Go through the ASDs for other slave ports */
249 		for (i = 1; i < nsp; i++) {
250 			j = 0;
251 			do {
252 				asd = get_asd(sih, &eromptr, i, j++, AD_ST_SLAVE, &addrl, &addrh,
253 				              &sizel, &sizeh);
254 			} while (asd != 0);
255 			if (j == 0) {
256 				SI_ERROR((" SP %d has no address descriptors\n", i));
257 				goto error;
258 			}
259 		}
260 
261 		/* Now get master wrappers */
262 		for (i = 0; i < nmw; i++) {
263 			asd = get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl, &addrh,
264 			              &sizel, &sizeh);
265 			if (asd == 0) {
266 				SI_ERROR(("Missing descriptor for MW %d\n", i));
267 				goto error;
268 			}
269 			if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
270 				SI_ERROR(("Master wrapper %d is not 4KB\n", i));
271 				goto error;
272 			}
273 			if (i == 0)
274 				sii->common_info->wrapba[idx] = addrl;
275 		}
276 
277 		/* And finally slave wrappers */
278 		for (i = 0; i < nsw; i++) {
279 			uint fwp = (nsp == 1) ? 0 : 1;
280 			asd = get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP, &addrl, &addrh,
281 			              &sizel, &sizeh);
282 			if (asd == 0) {
283 				SI_ERROR(("Missing descriptor for SW %d\n", i));
284 				goto error;
285 			}
286 			if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
287 				SI_ERROR(("Slave wrapper %d is not 4KB\n", i));
288 				goto error;
289 			}
290 			if ((nmw == 0) && (i == 0))
291 				sii->common_info->wrapba[idx] = addrl;
292 		}
293 
294 		/* Don't record bridges */
295 		if (br)
296 			continue;
297 
298 		/* Done with core */
299 		sii->numcores++;
300 	}
301 
302 	SI_ERROR(("Reached end of erom without finding END"));
303 
304 error:
305 	sii->numcores = 0;
306 	return;
307 }
308 
309 /* This function changes the logical "focus" to the indicated core.
310  * Return the current core's virtual address.
311  */
312 void *
ai_setcoreidx(si_t * sih,uint coreidx)313 ai_setcoreidx(si_t *sih, uint coreidx)
314 {
315 	si_info_t *sii = SI_INFO(sih);
316 	uint32 addr = sii->common_info->coresba[coreidx];
317 	uint32 wrap = sii->common_info->wrapba[coreidx];
318 	void *regs;
319 
320 	if (coreidx >= sii->numcores)
321 		return (NULL);
322 
323 	/*
324 	 * If the user has provided an interrupt mask enabled function,
325 	 * then assert interrupts are disabled before switching the core.
326 	 */
327 	ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg));
328 
329 	switch (BUSTYPE(sih->bustype)) {
330 	case SI_BUS:
331 		/* map new one */
332 		if (!sii->common_info->regs[coreidx]) {
333 			sii->common_info->regs[coreidx] = REG_MAP(addr, SI_CORE_SIZE);
334 			ASSERT(GOODREGS(sii->common_info->regs[coreidx]));
335 		}
336 		sii->curmap = regs = sii->common_info->regs[coreidx];
337 		if (!sii->common_info->wrappers[coreidx]) {
338 			sii->common_info->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE);
339 			ASSERT(GOODREGS(sii->common_info->wrappers[coreidx]));
340 		}
341 		sii->curwrap = sii->common_info->wrappers[coreidx];
342 		break;
343 
344 
345 	case SPI_BUS:
346 	case SDIO_BUS:
347 		sii->curmap = regs = (void *)((uintptr)addr);
348 		sii->curwrap = (void *)((uintptr)wrap);
349 		break;
350 
351 	case PCMCIA_BUS:
352 	default:
353 		ASSERT(0);
354 		regs = NULL;
355 		break;
356 	}
357 
358 	sii->curmap = regs;
359 	sii->curidx = coreidx;
360 
361 	return regs;
362 }
363 
364 /* Return the number of address spaces in current core */
365 int
ai_numaddrspaces(si_t * sih)366 ai_numaddrspaces(si_t *sih)
367 {
368 	return 2;
369 }
370 
371 /* Return the address of the nth address space in the current core */
372 uint32
ai_addrspace(si_t * sih,uint asidx)373 ai_addrspace(si_t *sih, uint asidx)
374 {
375 	si_info_t *sii;
376 	uint cidx;
377 
378 	sii = SI_INFO(sih);
379 	cidx = sii->curidx;
380 
381 	if (asidx == 0)
382 		return sii->common_info->coresba[cidx];
383 	else if (asidx == 1)
384 		return sii->common_info->coresba2[cidx];
385 	else {
386 		SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n",
387 		          __FUNCTION__, asidx));
388 		return 0;
389 	}
390 }
391 
392 /* Return the size of the nth address space in the current core */
393 uint32
ai_addrspacesize(si_t * sih,uint asidx)394 ai_addrspacesize(si_t *sih, uint asidx)
395 {
396 	si_info_t *sii;
397 	uint cidx;
398 
399 	sii = SI_INFO(sih);
400 	cidx = sii->curidx;
401 
402 	if (asidx == 0)
403 		return sii->common_info->coresba_size[cidx];
404 	else if (asidx == 1)
405 		return sii->common_info->coresba2_size[cidx];
406 	else {
407 		SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n",
408 		          __FUNCTION__, asidx));
409 		return 0;
410 	}
411 }
412 
413 uint
ai_flag(si_t * sih)414 ai_flag(si_t *sih)
415 {
416 	si_info_t *sii;
417 	aidmp_t *ai;
418 
419 	sii = SI_INFO(sih);
420 	ai = sii->curwrap;
421 
422 	return (R_REG(sii->osh, &ai->oobselouta30) & 0x1f);
423 }
424 
425 void
ai_setint(si_t * sih,int siflag)426 ai_setint(si_t *sih, int siflag)
427 {
428 }
429 
430 void
ai_write_wrap_reg(si_t * sih,uint32 offset,uint32 val)431 ai_write_wrap_reg(si_t *sih, uint32 offset, uint32 val)
432 {
433 	si_info_t *sii = SI_INFO(sih);
434 	aidmp_t *ai = sii->curwrap;
435 	W_REG(sii->osh, (uint32 *)((uint8 *)ai+offset), val);
436 	return;
437 }
438 
439 uint
ai_corevendor(si_t * sih)440 ai_corevendor(si_t *sih)
441 {
442 	si_info_t *sii;
443 	uint32 cia;
444 
445 	sii = SI_INFO(sih);
446 	cia = sii->common_info->cia[sii->curidx];
447 	return ((cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT);
448 }
449 
450 uint
ai_corerev(si_t * sih)451 ai_corerev(si_t *sih)
452 {
453 	si_info_t *sii;
454 	uint32 cib;
455 
456 	sii = SI_INFO(sih);
457 	cib = sii->common_info->cib[sii->curidx];
458 	return ((cib & CIB_REV_MASK) >> CIB_REV_SHIFT);
459 }
460 
461 bool
ai_iscoreup(si_t * sih)462 ai_iscoreup(si_t *sih)
463 {
464 	si_info_t *sii;
465 	aidmp_t *ai;
466 
467 	sii = SI_INFO(sih);
468 	ai = sii->curwrap;
469 
470 	return (((R_REG(sii->osh, &ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) == SICF_CLOCK_EN) &&
471 	        ((R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) == 0));
472 }
473 
474 /*
475  * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation,
476  * switch back to the original core, and return the new value.
477  *
478  * When using the silicon backplane, no fidleing with interrupts or core switches are needed.
479  *
480  * Also, when using pci/pcie, we can optimize away the core switching for pci registers
481  * and (on newer pci cores) chipcommon registers.
482  */
483 uint
ai_corereg(si_t * sih,uint coreidx,uint regoff,uint mask,uint val)484 ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
485 {
486 	uint origidx = 0;
487 	uint32 *r = NULL;
488 	uint w;
489 	uint intr_val = 0;
490 	bool fast = FALSE;
491 	si_info_t *sii;
492 
493 	sii = SI_INFO(sih);
494 
495 	ASSERT(GOODIDX(coreidx));
496 	ASSERT(regoff < SI_CORE_SIZE);
497 	ASSERT((val & ~mask) == 0);
498 
499 	if (coreidx >= SI_MAXCORES)
500 		return 0;
501 
502 	if (BUSTYPE(sih->bustype) == SI_BUS) {
503 		/* If internal bus, we can always get at everything */
504 		fast = TRUE;
505 		/* map if does not exist */
506 		if (!sii->common_info->wrappers[coreidx]) {
507 			sii->common_info->regs[coreidx] =
508 			    REG_MAP(sii->common_info->coresba[coreidx], SI_CORE_SIZE);
509 			ASSERT(GOODREGS(sii->common_info->regs[coreidx]));
510 		}
511 		r = (uint32 *)((uchar *)sii->common_info->regs[coreidx] + regoff);
512 	} else if (BUSTYPE(sih->bustype) == PCI_BUS) {
513 		/* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */
514 
515 		if ((sii->common_info->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
516 			/* Chipc registers are mapped at 12KB */
517 
518 			fast = TRUE;
519 			r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff);
520 		} else if (sii->pub.buscoreidx == coreidx) {
521 			/* pci registers are at either in the last 2KB of an 8KB window
522 			 * or, in pcie and pci rev 13 at 8KB
523 			 */
524 			fast = TRUE;
525 			if (SI_FAST(sii))
526 				r = (uint32 *)((char *)sii->curmap +
527 				               PCI_16KB0_PCIREGS_OFFSET + regoff);
528 			else
529 				r = (uint32 *)((char *)sii->curmap +
530 				               ((regoff >= SBCONFIGOFF) ?
531 				                PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) +
532 				               regoff);
533 		}
534 	}
535 
536 	if (!fast) {
537 		INTR_OFF(sii, intr_val);
538 
539 		/* save current core index */
540 		origidx = si_coreidx(&sii->pub);
541 
542 		/* switch core */
543 		r = (uint32*) ((uchar*) ai_setcoreidx(&sii->pub, coreidx) + regoff);
544 	}
545 	ASSERT(r != NULL);
546 
547 	/* mask and set */
548 	if (mask || val) {
549 		w = (R_REG(sii->osh, r) & ~mask) | val;
550 		W_REG(sii->osh, r, w);
551 	}
552 
553 	/* readback */
554 	w = R_REG(sii->osh, r);
555 
556 	if (!fast) {
557 		/* restore core index */
558 		if (origidx != coreidx)
559 			ai_setcoreidx(&sii->pub, origidx);
560 
561 		INTR_RESTORE(sii, intr_val);
562 	}
563 
564 	return (w);
565 }
566 
567 void
ai_core_disable(si_t * sih,uint32 bits)568 ai_core_disable(si_t *sih, uint32 bits)
569 {
570 	si_info_t *sii;
571 	volatile uint32 dummy;
572 	aidmp_t *ai;
573 
574 	sii = SI_INFO(sih);
575 
576 	ASSERT(GOODREGS(sii->curwrap));
577 	ai = sii->curwrap;
578 
579 	/* if core is already in reset, just return */
580 	if (R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET)
581 		return;
582 
583 	W_REG(sii->osh, &ai->ioctrl, bits);
584 	dummy = R_REG(sii->osh, &ai->ioctrl);
585 	OSL_DELAY(10);
586 
587 	W_REG(sii->osh, &ai->resetctrl, AIRC_RESET);
588 	OSL_DELAY(1);
589 }
590 
591 /* reset and re-enable a core
592  * inputs:
593  * bits - core specific bits that are set during and after reset sequence
594  * resetbits - core specific bits that are set only during reset sequence
595  */
596 void
ai_core_reset(si_t * sih,uint32 bits,uint32 resetbits)597 ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
598 {
599 	si_info_t *sii;
600 	aidmp_t *ai;
601 	volatile uint32 dummy;
602 
603 	sii = SI_INFO(sih);
604 	ASSERT(GOODREGS(sii->curwrap));
605 	ai = sii->curwrap;
606 
607 	/*
608 	 * Must do the disable sequence first to work for arbitrary current core state.
609 	 */
610 	ai_core_disable(sih, (bits | resetbits));
611 
612 	/*
613 	 * Now do the initialization sequence.
614 	 */
615 	W_REG(sii->osh, &ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN));
616 	dummy = R_REG(sii->osh, &ai->ioctrl);
617 	W_REG(sii->osh, &ai->resetctrl, 0);
618 	OSL_DELAY(1);
619 
620 	W_REG(sii->osh, &ai->ioctrl, (bits | SICF_CLOCK_EN));
621 	dummy = R_REG(sii->osh, &ai->ioctrl);
622 	OSL_DELAY(1);
623 }
624 
625 
626 void
ai_core_cflags_wo(si_t * sih,uint32 mask,uint32 val)627 ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
628 {
629 	si_info_t *sii;
630 	aidmp_t *ai;
631 	uint32 w;
632 
633 	sii = SI_INFO(sih);
634 	ASSERT(GOODREGS(sii->curwrap));
635 	ai = sii->curwrap;
636 
637 	ASSERT((val & ~mask) == 0);
638 
639 	if (mask || val) {
640 		w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val);
641 		W_REG(sii->osh, &ai->ioctrl, w);
642 	}
643 }
644 
645 uint32
ai_core_cflags(si_t * sih,uint32 mask,uint32 val)646 ai_core_cflags(si_t *sih, uint32 mask, uint32 val)
647 {
648 	si_info_t *sii;
649 	aidmp_t *ai;
650 	uint32 w;
651 
652 	sii = SI_INFO(sih);
653 	ASSERT(GOODREGS(sii->curwrap));
654 	ai = sii->curwrap;
655 
656 	ASSERT((val & ~mask) == 0);
657 
658 	if (mask || val) {
659 		w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val);
660 		W_REG(sii->osh, &ai->ioctrl, w);
661 	}
662 
663 	return R_REG(sii->osh, &ai->ioctrl);
664 }
665 
666 uint32
ai_core_sflags(si_t * sih,uint32 mask,uint32 val)667 ai_core_sflags(si_t *sih, uint32 mask, uint32 val)
668 {
669 	si_info_t *sii;
670 	aidmp_t *ai;
671 	uint32 w;
672 
673 	sii = SI_INFO(sih);
674 	ASSERT(GOODREGS(sii->curwrap));
675 	ai = sii->curwrap;
676 
677 	ASSERT((val & ~mask) == 0);
678 	ASSERT((mask & ~SISF_CORE_BITS) == 0);
679 
680 	if (mask || val) {
681 		w = ((R_REG(sii->osh, &ai->iostatus) & ~mask) | val);
682 		W_REG(sii->osh, &ai->iostatus, w);
683 	}
684 
685 	return R_REG(sii->osh, &ai->iostatus);
686 }
687