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