wifi: renew patch drivers/net/wireless
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rkwifi / bcmdhd / aiutils.c
1 /*
2  * Misc utility routines for accessing chip-specific features
3  * of the SiliconBackplane-based Broadcom chips.
4  *
5  * $Copyright Open Broadcom Corporation$
6  *
7  * $Id: aiutils.c 385510 2013-02-15 21:02:07Z $
8  */
9 #include <bcm_cfg.h>
10 #include <typedefs.h>
11 #include <bcmdefs.h>
12 #include <osl.h>
13 #include <bcmutils.h>
14 #include <siutils.h>
15 #include <hndsoc.h>
16 #include <sbchipc.h>
17 #include <pcicfg.h>
18
19 #include "siutils_priv.h"
20
21 #define BCM47162_DMP() (0)
22 #define BCM5357_DMP() (0)
23 #define BCM4707_DMP() (0)
24 #define remap_coreid(sih, coreid)       (coreid)
25 #define remap_corerev(sih, corerev)     (corerev)
26
27
28
29 static uint32
30 get_erom_ent(si_t *sih, uint32 **eromptr, uint32 mask, uint32 match)
31 {
32         uint32 ent;
33         uint inv = 0, nom = 0;
34
35         while (TRUE) {
36                 ent = R_REG(si_osh(sih), *eromptr);
37                 (*eromptr)++;
38
39                 if (mask == 0)
40                         break;
41
42                 if ((ent & ER_VALID) == 0) {
43                         inv++;
44                         continue;
45                 }
46
47                 if (ent == (ER_END | ER_VALID))
48                         break;
49
50                 if ((ent & mask) == match)
51                         break;
52
53                 nom++;
54         }
55
56         SI_VMSG(("%s: Returning ent 0x%08x\n", __FUNCTION__, ent));
57         if (inv + nom) {
58                 SI_VMSG(("  after %d invalid and %d non-matching entries\n", inv, nom));
59         }
60         return ent;
61 }
62
63 static uint32
64 get_asd(si_t *sih, uint32 **eromptr, uint sp, uint ad, uint st, uint32 *addrl, uint32 *addrh,
65         uint32 *sizel, uint32 *sizeh)
66 {
67         uint32 asd, sz, szd;
68
69         asd = get_erom_ent(sih, eromptr, ER_VALID, ER_VALID);
70         if (((asd & ER_TAG1) != ER_ADD) ||
71             (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) ||
72             ((asd & AD_ST_MASK) != st)) {
73                 
74                 (*eromptr)--;
75                 return 0;
76         }
77         *addrl = asd & AD_ADDR_MASK;
78         if (asd & AD_AG32)
79                 *addrh = get_erom_ent(sih, eromptr, 0, 0);
80         else
81                 *addrh = 0;
82         *sizeh = 0;
83         sz = asd & AD_SZ_MASK;
84         if (sz == AD_SZ_SZD) {
85                 szd = get_erom_ent(sih, eromptr, 0, 0);
86                 *sizel = szd & SD_SZ_MASK;
87                 if (szd & SD_SG32)
88                         *sizeh = get_erom_ent(sih, eromptr, 0, 0);
89         } else
90                 *sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT);
91
92         SI_VMSG(("  SP %d, ad %d: st = %d, 0x%08x_0x%08x @ 0x%08x_0x%08x\n",
93                 sp, ad, st, *sizeh, *sizel, *addrh, *addrl));
94
95         return asd;
96 }
97
98 static void
99 ai_hwfixup(si_info_t *sii)
100 {
101 }
102
103
104
105 void
106 ai_scan(si_t *sih, void *regs, uint devid)
107 {
108         si_info_t *sii = SI_INFO(sih);
109         chipcregs_t *cc = (chipcregs_t *)regs;
110         uint32 erombase, *eromptr, *eromlim;
111
112         erombase = R_REG(sii->osh, &cc->eromptr);
113
114         switch (BUSTYPE(sih->bustype)) {
115         case SI_BUS:
116                 eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE);
117                 break;
118
119         case PCI_BUS:
120                 
121                 sii->curwrap = (void *)((uintptr)regs + SI_CORE_SIZE);
122
123                 
124                 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, erombase);
125                 eromptr = regs;
126                 break;
127
128         case SPI_BUS:
129         case SDIO_BUS:
130                 eromptr = (uint32 *)(uintptr)erombase;
131                 break;
132
133         case PCMCIA_BUS:
134         default:
135                 SI_ERROR(("Don't know how to do AXI enumertion on bus %d\n", sih->bustype));
136                 ASSERT(0);
137                 return;
138         }
139         eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32));
140
141         SI_VMSG(("ai_scan: regs = 0x%p, erombase = 0x%08x, eromptr = 0x%p, eromlim = 0x%p\n",
142                  regs, erombase, eromptr, eromlim));
143         while (eromptr < eromlim) {
144                 uint32 cia, cib, cid, mfg, crev, nmw, nsw, nmp, nsp;
145                 uint32 mpd, asd, addrl, addrh, sizel, sizeh;
146                 uint i, j, idx;
147                 bool br;
148
149                 br = FALSE;
150
151                 
152                 cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI);
153                 if (cia == (ER_END | ER_VALID)) {
154                         SI_VMSG(("Found END of erom after %d cores\n", sii->numcores));
155                         ai_hwfixup(sii);
156                         return;
157                 }
158
159                 cib = get_erom_ent(sih, &eromptr, 0, 0);
160
161                 if ((cib & ER_TAG) != ER_CI) {
162                         SI_ERROR(("CIA not followed by CIB\n"));
163                         goto error;
164                 }
165
166                 cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT;
167                 mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT;
168                 crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
169                 nmw = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT;
170                 nsw = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT;
171                 nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT;
172                 nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT;
173
174 #ifdef BCMDBG_SI
175                 SI_VMSG(("Found component 0x%04x/0x%04x rev %d at erom addr 0x%p, with nmw = %d, "
176                          "nsw = %d, nmp = %d & nsp = %d\n",
177                          mfg, cid, crev, eromptr - 1, nmw, nsw, nmp, nsp));
178 #else
179                 BCM_REFERENCE(crev);
180 #endif
181
182                 if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0))
183                         continue;
184                 if ((nmw + nsw == 0)) {
185                         
186                         if (cid == OOB_ROUTER_CORE_ID) {
187                                 asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE,
188                                         &addrl, &addrh, &sizel, &sizeh);
189                                 if (asd != 0) {
190                                         sii->oob_router = addrl;
191                                 }
192                         }
193                         if (cid != GMAC_COMMON_4706_CORE_ID && cid != NS_CCB_CORE_ID)
194                                 continue;
195                 }
196
197                 idx = sii->numcores;
198
199                 sii->cia[idx] = cia;
200                 sii->cib[idx] = cib;
201                 sii->coreid[idx] = remap_coreid(sih, cid);
202
203                 for (i = 0; i < nmp; i++) {
204                         mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID);
205                         if ((mpd & ER_TAG) != ER_MP) {
206                                 SI_ERROR(("Not enough MP entries for component 0x%x\n", cid));
207                                 goto error;
208                         }
209                         SI_VMSG(("  Master port %d, mp: %d id: %d\n", i,
210                                  (mpd & MPD_MP_MASK) >> MPD_MP_SHIFT,
211                                  (mpd & MPD_MUI_MASK) >> MPD_MUI_SHIFT));
212                 }
213
214                 
215                 asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh);
216                 if (asd == 0) {
217                         do {
218                         
219                         asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh,
220                                       &sizel, &sizeh);
221                         if (asd != 0)
222                                 br = TRUE;
223                         else {
224                                         if (br == TRUE) {
225                                                 break;
226                                         }
227                                         else if ((addrh != 0) || (sizeh != 0) ||
228                                                 (sizel != SI_CORE_SIZE)) {
229                                                 SI_ERROR(("addrh = 0x%x\t sizeh = 0x%x\t size1 ="
230                                                         "0x%x\n", addrh, sizeh, sizel));
231                                                 SI_ERROR(("First Slave ASD for"
232                                                         "core 0x%04x malformed "
233                                                         "(0x%08x)\n", cid, asd));
234                                                 goto error;
235                                         }
236                                 }
237                         } while (1);
238                 }
239                 sii->coresba[idx] = addrl;
240                 sii->coresba_size[idx] = sizel;
241                 
242                 j = 1;
243                 do {
244                         asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh,
245                                       &sizel, &sizeh);
246                         if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE)) {
247                                 sii->coresba2[idx] = addrl;
248                                 sii->coresba2_size[idx] = sizel;
249                         }
250                         j++;
251                 } while (asd != 0);
252
253                 
254                 for (i = 1; i < nsp; i++) {
255                         j = 0;
256                         do {
257                                 asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh,
258                                               &sizel, &sizeh);
259
260                                 if (asd == 0)
261                                         break;
262                                 j++;
263                         } while (1);
264                         if (j == 0) {
265                                 SI_ERROR((" SP %d has no address descriptors\n", i));
266                                 goto error;
267                         }
268                 }
269
270                 
271                 for (i = 0; i < nmw; i++) {
272                         asd = get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl, &addrh,
273                                       &sizel, &sizeh);
274                         if (asd == 0) {
275                                 SI_ERROR(("Missing descriptor for MW %d\n", i));
276                                 goto error;
277                         }
278                         if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
279                                 SI_ERROR(("Master wrapper %d is not 4KB\n", i));
280                                 goto error;
281                         }
282                         if (i == 0)
283                                 sii->wrapba[idx] = addrl;
284                 }
285
286                 
287                 for (i = 0; i < nsw; i++) {
288                         uint fwp = (nsp == 1) ? 0 : 1;
289                         asd = get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP, &addrl, &addrh,
290                                       &sizel, &sizeh);
291                         if (asd == 0) {
292                                 SI_ERROR(("Missing descriptor for SW %d\n", i));
293                                 goto error;
294                         }
295                         if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
296                                 SI_ERROR(("Slave wrapper %d is not 4KB\n", i));
297                                 goto error;
298                         }
299                         if ((nmw == 0) && (i == 0))
300                                 sii->wrapba[idx] = addrl;
301                 }
302
303
304                 
305                 if (br)
306                         continue;
307
308                 
309                 sii->numcores++;
310         }
311
312         SI_ERROR(("Reached end of erom without finding END"));
313
314 error:
315         sii->numcores = 0;
316         return;
317 }
318
319
320 void *
321 ai_setcoreidx(si_t *sih, uint coreidx)
322 {
323         si_info_t *sii = SI_INFO(sih);
324         uint32 addr, wrap;
325         void *regs;
326
327         if (coreidx >= MIN(sii->numcores, SI_MAXCORES))
328                 return (NULL);
329
330         addr = sii->coresba[coreidx];
331         wrap = sii->wrapba[coreidx];
332
333         
334         ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg));
335
336         switch (BUSTYPE(sih->bustype)) {
337         case SI_BUS:
338                 
339                 if (!sii->regs[coreidx]) {
340                         sii->regs[coreidx] = REG_MAP(addr, SI_CORE_SIZE);
341                         ASSERT(GOODREGS(sii->regs[coreidx]));
342                 }
343                 sii->curmap = regs = sii->regs[coreidx];
344                 if (!sii->wrappers[coreidx] && (wrap != 0)) {
345                         sii->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE);
346                         ASSERT(GOODREGS(sii->wrappers[coreidx]));
347                 }
348                 sii->curwrap = sii->wrappers[coreidx];
349                 break;
350
351
352         case SPI_BUS:
353         case SDIO_BUS:
354                 sii->curmap = regs = (void *)((uintptr)addr);
355                 sii->curwrap = (void *)((uintptr)wrap);
356                 break;
357
358         case PCMCIA_BUS:
359         default:
360                 ASSERT(0);
361                 regs = NULL;
362                 break;
363         }
364
365         sii->curmap = regs;
366         sii->curidx = coreidx;
367
368         return regs;
369 }
370
371 void
372 ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
373 {
374         si_info_t *sii = SI_INFO(sih);
375         chipcregs_t *cc = NULL;
376         uint32 erombase, *eromptr, *eromlim;
377         uint i, j, cidx;
378         uint32 cia, cib, nmp, nsp;
379         uint32 asd, addrl, addrh, sizel, sizeh;
380
381         for (i = 0; i < sii->numcores; i++) {
382                 if (sii->coreid[i] == CC_CORE_ID) {
383                         cc = (chipcregs_t *)sii->regs[i];
384                         break;
385                 }
386         }
387         if (cc == NULL)
388                 goto error;
389
390         erombase = R_REG(sii->osh, &cc->eromptr);
391         eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE);
392         eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32));
393
394         cidx = sii->curidx;
395         cia = sii->cia[cidx];
396         cib = sii->cib[cidx];
397
398         nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT;
399         nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT;
400
401         
402         while (eromptr < eromlim) {
403                 if ((get_erom_ent(sih, &eromptr, ER_TAG, ER_CI) == cia) &&
404                         (get_erom_ent(sih, &eromptr, 0, 0) == cib)) {
405                         break;
406                 }
407         }
408
409         
410         for (i = 0; i < nmp; i++)
411                 get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID);
412
413         
414         asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh);
415         if (asd == 0) {
416                 
417                 asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh,
418                               &sizel, &sizeh);
419         }
420
421         j = 1;
422         do {
423                 asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh,
424                               &sizel, &sizeh);
425                 j++;
426         } while (asd != 0);
427
428         
429         for (i = 1; i < nsp; i++) {
430                 j = 0;
431                 do {
432                         asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh,
433                                 &sizel, &sizeh);
434                         if (asd == 0)
435                                 break;
436
437                         if (!asidx--) {
438                                 *addr = addrl;
439                                 *size = sizel;
440                                 return;
441                         }
442                         j++;
443                 } while (1);
444
445                 if (j == 0) {
446                         SI_ERROR((" SP %d has no address descriptors\n", i));
447                         break;
448                 }
449         }
450
451 error:
452         *size = 0;
453         return;
454 }
455
456
457 int
458 ai_numaddrspaces(si_t *sih)
459 {
460         return 2;
461 }
462
463
464 uint32
465 ai_addrspace(si_t *sih, uint asidx)
466 {
467         si_info_t *sii;
468         uint cidx;
469
470         sii = SI_INFO(sih);
471         cidx = sii->curidx;
472
473         if (asidx == 0)
474                 return sii->coresba[cidx];
475         else if (asidx == 1)
476                 return sii->coresba2[cidx];
477         else {
478                 SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n",
479                           __FUNCTION__, asidx));
480                 return 0;
481         }
482 }
483
484
485 uint32
486 ai_addrspacesize(si_t *sih, uint asidx)
487 {
488         si_info_t *sii;
489         uint cidx;
490
491         sii = SI_INFO(sih);
492         cidx = sii->curidx;
493
494         if (asidx == 0)
495                 return sii->coresba_size[cidx];
496         else if (asidx == 1)
497                 return sii->coresba2_size[cidx];
498         else {
499                 SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n",
500                           __FUNCTION__, asidx));
501                 return 0;
502         }
503 }
504
505 uint
506 ai_flag(si_t *sih)
507 {
508         si_info_t *sii;
509         aidmp_t *ai;
510
511         sii = SI_INFO(sih);
512         if (BCM47162_DMP()) {
513                 SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__));
514                 return sii->curidx;
515         }
516         if (BCM5357_DMP()) {
517                 SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__));
518                 return sii->curidx;
519         }
520         if (BCM4707_DMP()) {
521                 SI_ERROR(("%s: Attempting to read CHIPCOMMONB DMP registers on 4707\n",
522                         __FUNCTION__));
523                 return sii->curidx;
524         }
525         ai = sii->curwrap;
526
527         return (R_REG(sii->osh, &ai->oobselouta30) & 0x1f);
528 }
529
530 uint
531 ai_flag_alt(si_t *sih)
532 {
533         si_info_t *sii;
534         aidmp_t *ai;
535
536         sii = SI_INFO(sih);
537         if (BCM47162_DMP()) {
538                 SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__));
539                 return sii->curidx;
540         }
541         if (BCM5357_DMP()) {
542                 SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__));
543                 return sii->curidx;
544         }
545         if (BCM4707_DMP()) {
546                 SI_ERROR(("%s: Attempting to read CHIPCOMMONB DMP registers on 4707\n",
547                         __FUNCTION__));
548                 return sii->curidx;
549         }
550         ai = sii->curwrap;
551
552         return ((R_REG(sii->osh, &ai->oobselouta30) >> AI_OOBSEL_1_SHIFT) & AI_OOBSEL_MASK);
553 }
554
555 void
556 ai_setint(si_t *sih, int siflag)
557 {
558 }
559
560 uint
561 ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
562 {
563         si_info_t *sii = SI_INFO(sih);
564         uint32 *map = (uint32 *) sii->curwrap;
565
566         if (mask || val) {
567                 uint32 w = R_REG(sii->osh, map+(offset/4));
568                 w &= ~mask;
569                 w |= val;
570                 W_REG(sii->osh, map+(offset/4), val);
571         }
572
573         return (R_REG(sii->osh, map+(offset/4)));
574 }
575
576 uint
577 ai_corevendor(si_t *sih)
578 {
579         si_info_t *sii;
580         uint32 cia;
581
582         sii = SI_INFO(sih);
583         cia = sii->cia[sii->curidx];
584         return ((cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT);
585 }
586
587 uint
588 ai_corerev(si_t *sih)
589 {
590         si_info_t *sii;
591         uint32 cib;
592
593         sii = SI_INFO(sih);
594         cib = sii->cib[sii->curidx];
595         return remap_corerev(sih, (cib & CIB_REV_MASK) >> CIB_REV_SHIFT);
596 }
597
598 bool
599 ai_iscoreup(si_t *sih)
600 {
601         si_info_t *sii;
602         aidmp_t *ai;
603
604         sii = SI_INFO(sih);
605         ai = sii->curwrap;
606
607         return (((R_REG(sii->osh, &ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) == SICF_CLOCK_EN) &&
608                 ((R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) == 0));
609 }
610
611
612 uint
613 ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
614 {
615         uint origidx = 0;
616         uint32 *r = NULL;
617         uint w;
618         uint intr_val = 0;
619         bool fast = FALSE;
620         si_info_t *sii;
621
622         sii = SI_INFO(sih);
623
624         ASSERT(GOODIDX(coreidx));
625         ASSERT(regoff < SI_CORE_SIZE);
626         ASSERT((val & ~mask) == 0);
627
628         if (coreidx >= SI_MAXCORES)
629                 return 0;
630
631         if (BUSTYPE(sih->bustype) == SI_BUS) {
632                 
633                 fast = TRUE;
634                 
635                 if (!sii->regs[coreidx]) {
636                         sii->regs[coreidx] = REG_MAP(sii->coresba[coreidx],
637                                                     SI_CORE_SIZE);
638                         ASSERT(GOODREGS(sii->regs[coreidx]));
639                 }
640                 r = (uint32 *)((uchar *)sii->regs[coreidx] + regoff);
641         } else if (BUSTYPE(sih->bustype) == PCI_BUS) {
642                 
643
644                 if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
645                         
646
647                         fast = TRUE;
648                         r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff);
649                 } else if (sii->pub.buscoreidx == coreidx) {
650                         
651                         fast = TRUE;
652                         if (SI_FAST(sii))
653                                 r = (uint32 *)((char *)sii->curmap +
654                                                PCI_16KB0_PCIREGS_OFFSET + regoff);
655                         else
656                                 r = (uint32 *)((char *)sii->curmap +
657                                                ((regoff >= SBCONFIGOFF) ?
658                                                 PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) +
659                                                regoff);
660                 }
661         }
662
663         if (!fast) {
664                 INTR_OFF(sii, intr_val);
665
666                 
667                 origidx = si_coreidx(&sii->pub);
668
669                 
670                 r = (uint32*) ((uchar*) ai_setcoreidx(&sii->pub, coreidx) + regoff);
671         }
672         ASSERT(r != NULL);
673
674         
675         if (mask || val) {
676                 w = (R_REG(sii->osh, r) & ~mask) | val;
677                 W_REG(sii->osh, r, w);
678         }
679
680         
681         w = R_REG(sii->osh, r);
682
683         if (!fast) {
684                 
685                 if (origidx != coreidx)
686                         ai_setcoreidx(&sii->pub, origidx);
687
688                 INTR_RESTORE(sii, intr_val);
689         }
690
691         return (w);
692 }
693
694 void
695 ai_core_disable(si_t *sih, uint32 bits)
696 {
697         si_info_t *sii;
698         volatile uint32 dummy;
699         uint32 status;
700         aidmp_t *ai;
701
702         sii = SI_INFO(sih);
703
704         ASSERT(GOODREGS(sii->curwrap));
705         ai = sii->curwrap;
706
707         
708         if (R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET)
709                 return;
710
711         
712         SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 300);
713
714         
715         if (status != 0) {
716                 
717                 
718                 SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 10000);
719                 
720                 
721         }
722
723         W_REG(sii->osh, &ai->resetctrl, AIRC_RESET);
724         dummy = R_REG(sii->osh, &ai->resetctrl);
725         BCM_REFERENCE(dummy);
726         OSL_DELAY(1);
727
728         W_REG(sii->osh, &ai->ioctrl, bits);
729         dummy = R_REG(sii->osh, &ai->ioctrl);
730         BCM_REFERENCE(dummy);
731         OSL_DELAY(10);
732 }
733
734
735 void
736 ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
737 {
738         si_info_t *sii;
739         aidmp_t *ai;
740         volatile uint32 dummy;
741
742         sii = SI_INFO(sih);
743         ASSERT(GOODREGS(sii->curwrap));
744         ai = sii->curwrap;
745
746         
747         ai_core_disable(sih, (bits | resetbits));
748
749         
750         W_REG(sii->osh, &ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN));
751         dummy = R_REG(sii->osh, &ai->ioctrl);
752         BCM_REFERENCE(dummy);
753
754         W_REG(sii->osh, &ai->resetctrl, 0);
755         dummy = R_REG(sii->osh, &ai->resetctrl);
756         BCM_REFERENCE(dummy);
757         OSL_DELAY(1);
758
759         W_REG(sii->osh, &ai->ioctrl, (bits | SICF_CLOCK_EN));
760         dummy = R_REG(sii->osh, &ai->ioctrl);
761         BCM_REFERENCE(dummy);
762         OSL_DELAY(1);
763 }
764
765 void
766 ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
767 {
768         si_info_t *sii;
769         aidmp_t *ai;
770         uint32 w;
771
772         sii = SI_INFO(sih);
773
774         if (BCM47162_DMP()) {
775                 SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
776                           __FUNCTION__));
777                 return;
778         }
779         if (BCM5357_DMP()) {
780                 SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n",
781                           __FUNCTION__));
782                 return;
783         }
784         if (BCM4707_DMP()) {
785                 SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n",
786                         __FUNCTION__));
787                 return;
788         }
789
790         ASSERT(GOODREGS(sii->curwrap));
791         ai = sii->curwrap;
792
793         ASSERT((val & ~mask) == 0);
794
795         if (mask || val) {
796                 w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val);
797                 W_REG(sii->osh, &ai->ioctrl, w);
798         }
799 }
800
801 uint32
802 ai_core_cflags(si_t *sih, uint32 mask, uint32 val)
803 {
804         si_info_t *sii;
805         aidmp_t *ai;
806         uint32 w;
807
808         sii = SI_INFO(sih);
809         if (BCM47162_DMP()) {
810                 SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0",
811                           __FUNCTION__));
812                 return 0;
813         }
814         if (BCM5357_DMP()) {
815                 SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n",
816                           __FUNCTION__));
817                 return 0;
818         }
819         if (BCM4707_DMP()) {
820                 SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n",
821                         __FUNCTION__));
822                 return 0;
823         }
824
825         ASSERT(GOODREGS(sii->curwrap));
826         ai = sii->curwrap;
827
828         ASSERT((val & ~mask) == 0);
829
830         if (mask || val) {
831                 w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val);
832                 W_REG(sii->osh, &ai->ioctrl, w);
833         }
834
835         return R_REG(sii->osh, &ai->ioctrl);
836 }
837
838 uint32
839 ai_core_sflags(si_t *sih, uint32 mask, uint32 val)
840 {
841         si_info_t *sii;
842         aidmp_t *ai;
843         uint32 w;
844
845         sii = SI_INFO(sih);
846         if (BCM47162_DMP()) {
847                 SI_ERROR(("%s: Accessing MIPS DMP register (iostatus) on 47162a0",
848                           __FUNCTION__));
849                 return 0;
850         }
851         if (BCM5357_DMP()) {
852                 SI_ERROR(("%s: Accessing USB20H DMP register (iostatus) on 5357\n",
853                           __FUNCTION__));
854                 return 0;
855         }
856         if (BCM4707_DMP()) {
857                 SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n",
858                         __FUNCTION__));
859                 return 0;
860         }
861
862         ASSERT(GOODREGS(sii->curwrap));
863         ai = sii->curwrap;
864
865         ASSERT((val & ~mask) == 0);
866         ASSERT((mask & ~SISF_CORE_BITS) == 0);
867
868         if (mask || val) {
869                 w = ((R_REG(sii->osh, &ai->iostatus) & ~mask) | val);
870                 W_REG(sii->osh, &ai->iostatus, w);
871         }
872
873         return R_REG(sii->osh, &ai->iostatus);
874 }