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