2 * Misc utility routines for accessing chip-specific features
3 * of the SiliconBackplane-based Broadcom chips.
5 * Copyright 2004, Broadcom Corporation
8 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
9 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
10 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
11 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
29 #define SB_ERROR(args)
31 typedef uint32 (*sb_intrsoff_t
)(void *intr_arg
);
32 typedef void (*sb_intrsrestore_t
)(void *intr_arg
, uint32 arg
);
33 typedef bool (*sb_intrsenabled_t
)(void *intr_arg
);
35 /* misc sb info needed by some of the routines */
36 typedef struct sb_info
{
37 uint chip
; /* chip number */
38 uint chiprev
; /* chip revision */
39 uint chippkg
; /* chip package option */
40 uint boardtype
; /* board type */
41 uint boardvendor
; /* board vendor id */
42 uint bus
; /* what bus type we are going through */
44 void *osh
; /* osl os handle */
45 void *sdh
; /* bcmsdh handle */
47 void *curmap
; /* current regs va */
48 void *regs
[SB_MAXCORES
]; /* other regs va */
50 uint curidx
; /* current core index */
51 uint dev_coreid
; /* the core provides driver functions */
52 uint pciidx
; /* pci core index */
53 uint pcirev
; /* pci core rev */
55 uint pcmciaidx
; /* pcmcia core index */
56 uint pcmciarev
; /* pcmcia core rev */
57 bool memseg
; /* flag to toggle MEM_SEG register */
59 uint ccrev
; /* chipc core rev */
61 uint gpioidx
; /* gpio control core index */
62 uint gpioid
; /* gpio control coretype */
64 uint numcores
; /* # discovered cores */
65 uint coreid
[SB_MAXCORES
]; /* id of each core */
67 void *intr_arg
; /* interrupt callback function arg */
68 sb_intrsoff_t intrsoff_fn
; /* function turns chip interrupts off */
69 sb_intrsrestore_t intrsrestore_fn
; /* function restore chip interrupts */
70 sb_intrsenabled_t intrsenabled_fn
; /* function to check if chip interrupts are enabled */
73 /* local prototypes */
74 static void* sb_doattach(sb_info_t
*si
, uint devid
, void *osh
, void *regs
, uint bustype
, void *sdh
, char **vars
, int *varsz
);
75 static void sb_scan(sb_info_t
*si
);
76 static uint
sb_corereg(void *sbh
, uint coreidx
, uint regoff
, uint mask
, uint val
);
77 static uint
_sb_coreidx(void *sbh
);
78 static uint
sb_findcoreidx(void *sbh
, uint coreid
, uint coreunit
);
79 static uint
sb_pcidev2chip(uint pcidev
);
80 static uint
sb_chip2numcores(uint chip
);
82 #define SB_INFO(sbh) (sb_info_t*)sbh
83 #define SET_SBREG(sbh, r, mask, val) W_SBREG((sbh), (r), ((R_SBREG((sbh), (r)) & ~(mask)) | (val)))
84 #define GOODCOREADDR(x) (((x) >= SB_ENUM_BASE) && ((x) <= SB_ENUM_LIM) && ISALIGNED((x), SB_CORE_SIZE))
85 #define GOODREGS(regs) (regs && ISALIGNED(regs, SB_CORE_SIZE))
86 #define REGS2SB(va) (sbconfig_t*) ((uint)(va) + SBCONFIGOFF)
87 #define GOODIDX(idx) (((uint)idx) < SB_MAXCORES)
88 #define BADIDX (SB_MAXCORES+1)
90 #define R_SBREG(sbh, sbr) sb_read_sbreg((sbh), (sbr))
91 #define W_SBREG(sbh, sbr, v) sb_write_sbreg((sbh), (sbr), (v))
92 #define AND_SBREG(sbh, sbr, v) W_SBREG((sbh), (sbr), (R_SBREG((sbh), (sbr)) & (v)))
93 #define OR_SBREG(sbh, sbr, v) W_SBREG((sbh), (sbr), (R_SBREG((sbh), (sbr)) | (v)))
96 * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/
97 * after core switching to avoid invalid register accesss inside ISR.
99 #define INTR_OFF(si, intr_val) \
100 if ((si)->intrsoff_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
101 intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); }
102 #define INTR_RESTORE(si, intr_val) \
103 if ((si)->intrsrestore_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
104 (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); }
106 /* power control defines */
107 #define LPOMINFREQ 25000 /* low power oscillator min */
108 #define LPOMAXFREQ 43000 /* low power oscillator max */
109 #define XTALMINFREQ 19800000 /* 20mhz - 1% */
110 #define XTALMAXFREQ 20200000 /* 20mhz + 1% */
111 #define PCIMINFREQ 25000000 /* 25mhz */
112 #define PCIMAXFREQ 34000000 /* 33mhz + fudge */
113 #define SCC_DEF_DIV 0 /* default slow clock divider */
115 #define XTAL_ON_DELAY 1000 /* Xtal power on delay in us */
117 #define SCC_LOW2FAST_LIMIT 5000 /* turn on fast clock time, in unit of ms */
121 sb_read_sbreg(void *sbh
, volatile uint32
*sbr
)
125 uint32 val
, intr_val
= 0;
130 * compact flash only has 11 bits address, while we needs 12 bits address.
131 * MEM_SEG will be OR'd with other 11 bits address in hardware,
132 * so we program MEM_SEG with 12th bit when necessary(access sb regsiters).
133 * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special
136 INTR_OFF(si
, intr_val
);
138 OSL_PCMCIA_WRITE_ATTR(si
->osh
, MEM_SEG
, &tmp
, 1);
139 (uint32
)sbr
&= ~(1 << 11); /* mask out bit 11*/
146 OSL_PCMCIA_WRITE_ATTR(si
->osh
, MEM_SEG
, &tmp
, 1);
147 INTR_RESTORE(si
, intr_val
);
154 sb_write_sbreg(void *sbh
, volatile uint32
*sbr
, uint32 v
)
158 volatile uint32 dummy
;
164 * compact flash only has 11 bits address, while we needs 12 bits address.
165 * MEM_SEG will be OR'd with other 11 bits address in hardware,
166 * so we program MEM_SEG with 12th bit when necessary(access sb regsiters).
167 * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special
170 INTR_OFF(si
, intr_val
);
172 OSL_PCMCIA_WRITE_ATTR(si
->osh
, MEM_SEG
, &tmp
, 1);
173 (uint32
)sbr
&= ~(1 << 11); /* mask out bit 11 */
176 if (si
->bus
== PCMCIA_BUS
) {
179 W_REG((volatile uint16
*)((uint32
)sbr
+ 2), (uint16
)((v
>> 16) & 0xffff));
181 W_REG((volatile uint16
*)sbr
, (uint16
)(v
& 0xffff));
184 W_REG((volatile uint16
*)sbr
, (uint16
)(v
& 0xffff));
186 W_REG((volatile uint16
*)((uint32
)sbr
+ 2), (uint16
)((v
>> 16) & 0xffff));
193 OSL_PCMCIA_WRITE_ATTR(si
->osh
, MEM_SEG
, &tmp
, 1);
194 INTR_RESTORE(si
, intr_val
);
199 * Allocate a sb handle.
200 * devid - pci device id (used to determine chip#)
201 * osh - opaque OS handle
202 * regs - virtual address of initial core registers
203 * bustype - pci/pcmcia/sb/sdio/etc
204 * vars - pointer to a pointer area for "environment" variables
205 * varsz - pointer to int to return the size of the vars
208 sb_attach(uint devid
, void *osh
, void *regs
, uint bustype
, void *sdh
, char **vars
, int *varsz
)
212 /* alloc sb_info_t */
213 if ((si
= MALLOC(sizeof (sb_info_t
))) == NULL
) {
214 SB_ERROR(("sb_attach: malloc failed!\n"));
218 return (sb_doattach(si
, devid
, osh
, regs
, bustype
, sdh
, vars
, varsz
));
221 /* global kernel resource */
222 static sb_info_t ksi
;
224 /* generic kernel variant of sb_attach() */
232 if (ksi
.curmap
== NULL
) {
235 regs
= (uint32
*)REG_MAP(SB_ENUM_BASE
, SB_CORE_SIZE
);
236 cid
= R_REG((uint32
*)regs
);
237 if (((cid
& CID_ID_MASK
) == 0x4712) &&
238 ((cid
& CID_REV_MASK
) <= 0x00020000)) {
241 scc
= (uint32
*)((uint32
)regs
+ OFFSETOF(chipcregs_t
, slow_clk_ctl
));
243 SB_ERROR((" initial scc = 0x%x\n", val
));
248 sb_doattach(&ksi
, BCM4710_DEVICE_ID
, NULL
, (void*)regs
,
249 SB_BUS
, NULL
, &unused
, &varsz
);
256 sb_doattach(sb_info_t
*si
, uint devid
, void *osh
, void *regs
, uint bustype
, void *sdh
, char **vars
, int *varsz
)
262 ASSERT(GOODREGS(regs
));
264 bzero((uchar
*)si
, sizeof (sb_info_t
));
266 si
->pciidx
= si
->gpioidx
= BADIDX
;
272 /* check to see if we are a sb core mimic'ing a pci core */
273 if (bustype
== PCI_BUS
) {
274 if (OSL_PCI_READ_CONFIG(osh
, PCI_SPROM_CONTROL
, sizeof (uint32
)) == 0xffffffff)
282 if (si
->bus
== PCMCIA_BUS
)
283 /* need to set memseg flag for CF card first before any sb registers access,
284 * such as the access inside sb_scan. the card type is detected and memseg
285 * flag is reassigned later after srom_var_init. there should be no effect
286 * for PCMCIA cards even though the memseg flag is set
290 /* kludge to enable the clock on the 4306 which lacks a slowclock */
291 if (si
->bus
== PCI_BUS
)
292 sb_pwrctl_xtal((void*)si
, XTAL
|PLL
, ON
);
294 /* initialize current core index value */
295 si
->curidx
= _sb_coreidx((void*)si
);
296 if (si
->curidx
== BADIDX
)
299 /* keep and reuse the initial register mapping */
300 origidx
= si
->curidx
;
301 if (si
->bus
== SB_BUS
)
302 si
->regs
[origidx
] = regs
;
304 /* is core-0 a chipcommon core? */
306 cc
= (chipcregs_t
*) sb_setcoreidx((void*)si
, 0);
307 if (sb_coreid((void*)si
) != SB_CC
)
310 /* determine chip id and rev */
312 /* chip common core found! */
313 si
->chip
= R_REG(&cc
->chipid
) & CID_ID_MASK
;
314 si
->chiprev
= (R_REG(&cc
->chipid
) & CID_REV_MASK
) >> CID_REV_SHIFT
;
315 si
->chippkg
= (R_REG(&cc
->chipid
) & CID_PKG_MASK
) >> CID_PKG_SHIFT
;
317 /* The only pcmcia chip without a chipcommon core is a 4301 */
318 if (si
->bus
== PCMCIA_BUS
)
319 devid
= BCM4301_DEVICE_ID
;
321 /* no chip common core -- must convert device id to chip id */
322 if ((si
->chip
= sb_pcidev2chip(devid
)) == 0) {
323 SB_ERROR(("sb_attach: unrecognized device id 0x%04x\n", devid
));
328 /* get chipcommon rev */
329 si
->ccrev
= cc
? sb_corerev((void*)si
) : 0;
331 /* determine numcores */
332 if ((si
->ccrev
== 4) || (si
->ccrev
>= 6))
333 si
->numcores
= (R_REG(&cc
->chipid
) & CID_CC_MASK
) >> CID_CC_SHIFT
;
335 si
->numcores
= sb_chip2numcores(si
->chip
);
337 /* return to original core */
338 sb_setcoreidx((void*)si
, origidx
);
346 /* initialize the vars after sb_scan so that the core rev. information
347 * collected by sb_scan is available for the srom_var_init.
349 if (srom_var_init(si
, si
->bus
, si
->curmap
, osh
, vars
, varsz
)) {
350 SB_ERROR(("sb_attach: srom_var_init failed\n"));
356 * The chip revision number is hardwired into all
357 * of the pci function config rev fields and is
358 * independent from the individual core revision numbers.
359 * For example, the "A0" silicon of each chip is chip rev 0.
360 * For PCMCIA we get it from the CIS instead.
362 if (si
->bus
== PCMCIA_BUS
) {
364 si
->chiprev
= getintvar(*vars
, "chiprev");
365 } else if (si
->bus
== PCI_BUS
) {
366 w
= OSL_PCI_READ_CONFIG(osh
, PCI_CFG_REV
, sizeof (uint32
));
367 si
->chiprev
= w
& 0xff;
372 if (si
->bus
== PCMCIA_BUS
) {
373 w
= getintvar(*vars
, "regwindowsz");
374 si
->memseg
= (w
<= CFTABLE_REGWIN_2K
) ? TRUE
: FALSE
;
377 /* pci core is required */
378 if (!GOODIDX(si
->pciidx
)) {
379 SB_ERROR(("sb_attach: pci core not found\n"));
383 /* gpio control core is required */
384 if (!GOODIDX(si
->gpioidx
)) {
385 SB_ERROR(("sb_attach: gpio control core not found\n"));
389 /* get boardtype and boardrev */
392 /* do a pci config read to get subsystem id and subvendor id */
393 w
= OSL_PCI_READ_CONFIG(osh
, PCI_CFG_SVID
, sizeof (uint32
));
394 si
->boardvendor
= w
& 0xffff;
395 si
->boardtype
= (w
>> 16) & 0xffff;
400 si
->boardvendor
= getintvar(*vars
, "manfid");
401 si
->boardtype
= getintvar(*vars
, "prodid");
405 si
->boardvendor
= VENDOR_BROADCOM
;
406 si
->boardtype
= 0xffff;
410 if (si
->boardtype
== 0) {
411 SB_ERROR(("sb_attach: unknown board type\n"));
412 ASSERT(si
->boardtype
);
415 /* clear any previous epidiag-induced target abort */
416 sb_taclear((void*)si
);
421 MFREE(si
, sizeof (sb_info_t
));
432 sb
= REGS2SB(si
->curmap
);
434 return ((R_SBREG(sbh
, &(sb
)->sbidhigh
) & SBIDH_CC_MASK
) >> SBIDH_CC_SHIFT
);
438 sb_coreidx(void *sbh
)
446 /* return current index of core */
448 _sb_coreidx(void *sbh
)
459 sb
= REGS2SB(si
->curmap
);
460 sbaddr
= sb_base(R_SBREG(sbh
, &sb
->sbadmatch0
));
464 sbaddr
= OSL_PCI_READ_CONFIG(si
->osh
, PCI_BAR0_WIN
, sizeof (uint32
));
470 OSL_PCMCIA_READ_ATTR(si
->osh
, PCMCIA_ADDR0
, &tmp
, 1);
471 sbaddr
= (uint
)tmp
<< 12;
472 OSL_PCMCIA_READ_ATTR(si
->osh
, PCMCIA_ADDR1
, &tmp
, 1);
473 sbaddr
|= (uint
)tmp
<< 16;
474 OSL_PCMCIA_READ_ATTR(si
->osh
, PCMCIA_ADDR2
, &tmp
, 1);
475 sbaddr
|= (uint
)tmp
<< 24;
482 if (!GOODCOREADDR(sbaddr
))
485 return ((sbaddr
- SB_ENUM_BASE
) / SB_CORE_SIZE
);
489 sb_corevendor(void *sbh
)
495 sb
= REGS2SB(si
->curmap
);
497 return ((R_SBREG(sbh
, &(sb
)->sbidhigh
) & SBIDH_VC_MASK
) >> SBIDH_VC_SHIFT
);
501 sb_corerev(void *sbh
)
507 sb
= REGS2SB(si
->curmap
);
509 return (R_SBREG(sbh
, &(sb
)->sbidhigh
) & SBIDH_RC_MASK
);
512 #define SBTML_ALLOW (SBTML_PE | SBTML_FGC | SBTML_FL_MASK)
514 /* set/clear sbtmstatelow core-specific flags */
516 sb_coreflags(void *sbh
, uint32 mask
, uint32 val
)
523 sb
= REGS2SB(si
->curmap
);
525 ASSERT((val
& ~mask
) == 0);
526 ASSERT((mask
& ~SBTML_ALLOW
) == 0);
530 w
= (R_SBREG(sbh
, &sb
->sbtmstatelow
) & ~mask
) | val
;
531 W_SBREG(sbh
, &sb
->sbtmstatelow
, w
);
534 /* return the new value */
535 return (R_SBREG(sbh
, &sb
->sbtmstatelow
) & SBTML_ALLOW
);
538 /* set/clear sbtmstatehigh core-specific flags */
540 sb_coreflagshi(void *sbh
, uint32 mask
, uint32 val
)
547 sb
= REGS2SB(si
->curmap
);
549 ASSERT((val
& ~mask
) == 0);
550 ASSERT((mask
& ~SBTMH_FL_MASK
) == 0);
554 w
= (R_SBREG(sbh
, &sb
->sbtmstatehigh
) & ~mask
) | val
;
555 W_SBREG(sbh
, &sb
->sbtmstatehigh
, w
);
558 /* return the new value */
559 return (R_SBREG(sbh
, &sb
->sbtmstatehigh
) & SBTMH_FL_MASK
);
563 sb_iscoreup(void *sbh
)
569 sb
= REGS2SB(si
->curmap
);
571 return ((R_SBREG(sbh
, &(sb
)->sbtmstatelow
) & (SBTML_RESET
| SBTML_REJ
| SBTML_CLK
)) == SBTML_CLK
);
575 * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation,
576 * switch back to the original core, and return the new value.
579 sb_corereg(void *sbh
, uint coreidx
, uint regoff
, uint mask
, uint val
)
587 ASSERT(GOODIDX(coreidx
));
588 ASSERT(regoff
< SB_CORE_SIZE
);
589 ASSERT((val
& ~mask
) == 0);
593 INTR_OFF(si
, intr_val
);
595 /* save current core index */
596 origidx
= sb_coreidx(sbh
);
599 r
= (uint32
*) ((uint
) sb_setcoreidx(sbh
, coreidx
) + regoff
);
603 if (regoff
>= SBCONFIGOFF
) {
604 w
= (R_SBREG(sbh
, r
) & ~mask
) | val
;
607 w
= (R_REG(r
) & ~mask
) | val
;
613 if (regoff
>= SBCONFIGOFF
)
618 /* restore core index */
619 if (origidx
!= coreidx
)
620 sb_setcoreidx(sbh
, origidx
);
622 INTR_RESTORE(si
, intr_val
);
626 /* scan the sb enumerated space to identify all cores */
628 sb_scan(sb_info_t
*si
)
636 /* numcores should already be set */
637 ASSERT((si
->numcores
> 0) && (si
->numcores
<= SB_MAXCORES
));
639 /* save current core index */
640 origidx
= sb_coreidx(sbh
);
642 si
->pciidx
= si
->gpioidx
= BADIDX
;
644 for (i
= 0; i
< si
->numcores
; i
++) {
645 sb_setcoreidx(sbh
, i
);
646 si
->coreid
[i
] = sb_coreid(sbh
);
648 if (si
->coreid
[i
] == SB_PCI
) {
650 si
->pcirev
= sb_corerev(sbh
);
652 } else if (si
->coreid
[i
] == SB_PCMCIA
) {
654 si
->pcmciarev
= sb_corerev(sbh
);
659 * Find the gpio "controlling core" type and index.
661 * - if there's a chip common core - use that
662 * - else if there's a pci core (rev >= 2) - use that
663 * - else there had better be an extif core (4710 only)
665 if (GOODIDX(sb_findcoreidx(sbh
, SB_CC
, 0))) {
666 si
->gpioidx
= sb_findcoreidx(sbh
, SB_CC
, 0);
668 } else if (GOODIDX(si
->pciidx
) && (si
->pcirev
>= 2)) {
669 si
->gpioidx
= si
->pciidx
;
671 } else if (sb_findcoreidx(sbh
, SB_EXTIF
, 0)) {
672 si
->gpioidx
= sb_findcoreidx(sbh
, SB_EXTIF
, 0);
673 si
->gpioid
= SB_EXTIF
;
676 /* return to original core index */
677 sb_setcoreidx(sbh
, origidx
);
680 /* may be called with core in reset */
692 if (si
->bus
== SB_BUS
)
693 for (idx
= 0; idx
< SB_MAXCORES
; idx
++)
695 REG_UNMAP(si
->regs
[idx
]);
696 si
->regs
[idx
] = NULL
;
699 MFREE(si
, sizeof (sb_info_t
));
702 /* use pci dev id to determine chip id for chips not having a chipcommon core */
704 sb_pcidev2chip(uint pcidev
)
706 if ((pcidev
>= BCM4710_DEVICE_ID
) && (pcidev
<= BCM47XX_USB_ID
))
707 return (BCM4710_DEVICE_ID
);
708 if ((pcidev
>= BCM4610_DEVICE_ID
) && (pcidev
<= BCM4610_USB_ID
))
709 return (BCM4610_DEVICE_ID
);
710 if ((pcidev
>= BCM4402_DEVICE_ID
) && (pcidev
<= BCM4402_V90_ID
))
711 return (BCM4402_DEVICE_ID
);
712 if ((pcidev
>= BCM4307_V90_ID
) && (pcidev
<= BCM4307_D11B_ID
))
713 return (BCM4307_DEVICE_ID
);
714 if (pcidev
== BCM4301_DEVICE_ID
)
715 return (BCM4301_DEVICE_ID
);
720 /* convert chip number to number of i/o cores */
722 sb_chip2numcores(uint chip
)
730 if ((chip
== 0x4307) || (chip
== 0x4301))
734 if (chip
== 0x4306) /* < 4306c0 */
741 SB_ERROR(("sb_chip2numcores: unsupported chip 0x%x\n", chip
));
746 /* return index of coreid or BADIDX if not found */
748 sb_findcoreidx(void *sbh
, uint coreid
, uint coreunit
)
757 for (i
= 0; i
< si
->numcores
; i
++)
758 if (si
->coreid
[i
] == coreid
) {
759 if (found
== coreunit
)
768 * this function changes logical "focus" to the indiciated core,
769 * must be called with interrupt off.
770 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
773 sb_setcoreidx(void *sbh
, uint coreidx
)
781 if (coreidx
>= si
->numcores
)
785 * If the user has provided an interrupt mask enabled function,
786 * then assert interrupts are disabled before switching the core.
788 ASSERT((si
->intrsenabled_fn
== NULL
) || !(*(si
)->intrsenabled_fn
)((si
)->intr_arg
));
790 sbaddr
= SB_ENUM_BASE
+ (coreidx
* SB_CORE_SIZE
);
795 if (!si
->regs
[coreidx
]) {
796 si
->regs
[coreidx
] = (void*)REG_MAP(sbaddr
, SB_CORE_SIZE
);
797 ASSERT(GOODREGS(si
->regs
[coreidx
]));
799 si
->curmap
= si
->regs
[coreidx
];
803 /* point bar0 window */
804 OSL_PCI_WRITE_CONFIG(si
->osh
, PCI_BAR0_WIN
, 4, sbaddr
);
808 tmp
= (sbaddr
>> 12) & 0x0f;
809 OSL_PCMCIA_WRITE_ATTR(si
->osh
, PCMCIA_ADDR0
, &tmp
, 1);
810 tmp
= (sbaddr
>> 16) & 0xff;
811 OSL_PCMCIA_WRITE_ATTR(si
->osh
, PCMCIA_ADDR1
, &tmp
, 1);
812 tmp
= (sbaddr
>> 24) & 0xff;
813 OSL_PCMCIA_WRITE_ATTR(si
->osh
, PCMCIA_ADDR2
, &tmp
, 1);
817 si
->curidx
= coreidx
;
823 * this function changes logical "focus" to the indiciated core,
824 * must be called with interrupt off.
825 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
828 sb_setcore(void *sbh
, uint coreid
, uint coreunit
)
835 idx
= sb_findcoreidx(sbh
, coreid
, coreunit
);
839 return (sb_setcoreidx(sbh
, idx
));
842 /* return chip number */
852 /* return chip revision number */
854 sb_chiprev(void *sbh
)
859 return (si
->chiprev
);
862 /* return chip common revision number */
864 sb_chipcrev(void *sbh
)
872 /* return chip package option */
874 sb_chippkg(void *sbh
)
879 return (si
->chippkg
);
882 /* return PCI core rev. */
892 /* return PCMCIA core rev. */
894 sb_pcmciarev(void *sbh
)
899 return (si
->pcmciarev
);
902 /* return board vendor id */
904 sb_boardvendor(void *sbh
)
909 return (si
->boardvendor
);
912 /* return boardtype */
914 sb_boardtype(void *sbh
)
921 if (si
->bus
== SB_BUS
&& si
->boardtype
== 0xffff) {
922 /* boardtype format is a hex string */
923 si
->boardtype
= getintvar(NULL
, "boardtype");
925 /* backward compatibility for older boardtype string format */
926 if ((si
->boardtype
== 0) && (var
= getvar(NULL
, "boardtype"))) {
927 if (!strcmp(var
, "bcm94710dev"))
928 si
->boardtype
= BCM94710D_BOARD
;
929 else if (!strcmp(var
, "bcm94710ap"))
930 si
->boardtype
= BCM94710AP_BOARD
;
931 else if (!strcmp(var
, "bcm94310u"))
932 si
->boardtype
= BCM94310U_BOARD
;
933 else if (!strcmp(var
, "bu4711"))
934 si
->boardtype
= BU4711_BOARD
;
935 else if (!strcmp(var
, "bu4710"))
936 si
->boardtype
= BU4710_BOARD
;
937 else if (!strcmp(var
, "bcm94702mn"))
938 si
->boardtype
= BCM94702MN_BOARD
;
939 else if (!strcmp(var
, "bcm94710r1"))
940 si
->boardtype
= BCM94710R1_BOARD
;
941 else if (!strcmp(var
, "bcm94710r4"))
942 si
->boardtype
= BCM94710R4_BOARD
;
943 else if (!strcmp(var
, "bcm94702cpci"))
944 si
->boardtype
= BCM94702CPCI_BOARD
;
945 else if (!strcmp(var
, "bcm95380_rr"))
946 si
->boardtype
= BCM95380RR_BOARD
;
950 return (si
->boardtype
);
953 /* return board bus style */
955 sb_boardstyle(void *sbh
)
962 if (si
->bus
== PCMCIA_BUS
)
963 return (BOARDSTYLE_PCMCIA
);
965 if (si
->bus
== SB_BUS
)
966 return (BOARDSTYLE_SOC
);
970 if (OSL_PCI_READ_CONFIG(si
->osh
, PCI_CFG_CIS
, sizeof (uint32
)) != 0)
971 return (BOARDSTYLE_CARDBUS
);
973 if ((srom_read(si
->bus
, si
->curmap
, si
->osh
, (SPROM_SIZE
- 1) * 2, 2, &w
) == 0) &&
975 return (BOARDSTYLE_CARDBUS
);
977 return (BOARDSTYLE_PCI
);
980 /* return boolean if sbh device is in pci hostmode or client mode */
990 /* return list of found cores */
992 sb_corelist(void *sbh
, uint coreid
[])
998 bcopy((uchar
*)si
->coreid
, (uchar
*)coreid
, (si
->numcores
* sizeof (uint
)));
999 return (si
->numcores
);
1002 /* return current register mapping */
1004 sb_coreregs(void *sbh
)
1009 ASSERT(GOODREGS(si
->curmap
));
1011 return (si
->curmap
);
1014 /* traverse all cores to find and clear source of serror */
1016 sb_serr_clear(void *sbh
)
1021 uint i
, intr_val
= 0;
1022 void * corereg
= NULL
;
1026 INTR_OFF(si
, intr_val
);
1027 origidx
= sb_coreidx(sbh
);
1029 for (i
= 0; i
< si
->numcores
; i
++) {
1030 corereg
= sb_setcoreidx(sbh
, i
);
1031 if (NULL
!= corereg
) {
1032 sb
= REGS2SB(corereg
);
1033 if ((si
->chip
== BCM4317_DEVICE_ID
) && (si
->chiprev
== 0)) {
1034 W_SBREG(sbh
, &sb
->sbtmstatehigh
, 0);
1036 if ((R_SBREG(sbh
, &sb
->sbtmstatehigh
)) & SBTMH_SERR
) {
1037 AND_SBREG(sbh
, &sb
->sbtmstatehigh
, ~SBTMH_SERR
);
1038 SB_ERROR(("sb_serr_clear: SError at core 0x%x\n", sb_coreid(sbh
)));
1044 sb_setcoreidx(sbh
, origidx
);
1045 INTR_RESTORE(si
, intr_val
);
1048 /* check if any inband, outband or timeout errors has happened and clear them */
1049 /* !! must be called with chip clk on */
1051 sb_taclear(void *sbh
)
1058 uint32 inband
= 0, serror
= 0, timeout
= 0;
1059 void *corereg
= NULL
;
1060 volatile uint32 imstate
, tmstate
;
1064 if (si
->bus
== PCI_BUS
) {
1065 volatile uint32 stcmd
;
1067 /* inband error is Target abort for PCI */
1068 stcmd
= OSL_PCI_READ_CONFIG(si
->osh
, PCI_CFG_CMD
, sizeof(uint32
));
1069 inband
= stcmd
& PCI_CFG_CMD_STAT_TA
;
1071 OSL_PCI_WRITE_CONFIG(si
->osh
, PCI_CFG_CMD
, sizeof(uint32
), stcmd
);
1074 stcmd
= OSL_PCI_READ_CONFIG(si
->osh
, PCI_INT_STATUS
, sizeof(uint32
));
1075 serror
= stcmd
& PCI_SBIM_STATUS_SERR
;
1078 OSL_PCI_WRITE_CONFIG(si
->osh
, PCI_INT_STATUS
, sizeof(uint32
), stcmd
);
1082 imstate
= sb_corereg(sbh
, si
->pciidx
, SBCONFIGOFF
+ OFFSETOF(sbconfig_t
, sbimstate
), 0, 0);
1083 if ((imstate
!= 0xffffffff) && (imstate
& (SBIM_IBE
| SBIM_TO
))) {
1084 sb_corereg(sbh
, si
->pciidx
, SBCONFIGOFF
+ OFFSETOF(sbconfig_t
, sbimstate
), ~0,
1085 (imstate
& ~(SBIM_IBE
| SBIM_TO
)));
1086 /* inband = imstate & SBIM_IBE; same as TA above */
1087 timeout
= imstate
& SBIM_TO
;
1090 } else if (si
->bus
== PCMCIA_BUS
) {
1092 INTR_OFF(si
, intr_val
);
1093 origidx
= sb_coreidx(sbh
);
1095 corereg
= sb_setcore(sbh
, SB_PCMCIA
, 0);
1096 if (NULL
!= corereg
) {
1097 sb
= REGS2SB(corereg
);
1099 imstate
= R_SBREG(sbh
, &sb
->sbimstate
);
1100 /* handle surprise removal */
1101 if ((imstate
!= 0xffffffff) && (imstate
& (SBIM_IBE
| SBIM_TO
))) {
1102 AND_SBREG(sbh
, &sb
->sbimstate
, ~(SBIM_IBE
| SBIM_TO
));
1103 inband
= imstate
& SBIM_IBE
;
1104 timeout
= imstate
& SBIM_TO
;
1106 tmstate
= R_SBREG(sbh
, &sb
->sbtmstatehigh
);
1107 if ((tmstate
!= 0xffffffff) && (tmstate
& SBTMH_INT_STATUS
)) {
1112 OR_SBREG(sbh
, &sb
->sbtmstatelow
, SBTML_INT_ACK
);
1113 AND_SBREG(sbh
, &sb
->sbtmstatelow
, ~SBTML_INT_ACK
);
1116 sb_setcoreidx(sbh
, origidx
);
1117 INTR_RESTORE(si
, intr_val
);
1119 } else if (si
->bus
== SDIO_BUS
) {
1121 INTR_OFF(si
, intr_val
);
1122 origidx
= sb_coreidx(sbh
);
1124 corereg
= sb_setcore(sbh
, SB_PCMCIA
, 0);
1125 if (NULL
!= corereg
) {
1126 sb
= REGS2SB(corereg
);
1128 imstate
= R_SBREG(sbh
, &sb
->sbimstate
);
1129 if ((imstate
!= 0xffffffff) && (imstate
& (SBIM_IBE
| SBIM_TO
))) {
1130 AND_SBREG(sbh
, &sb
->sbimstate
, ~(SBIM_IBE
| SBIM_TO
));
1131 /* inband = imstate & SBIM_IBE; cmd error */
1132 timeout
= imstate
& SBIM_TO
;
1134 tmstate
= R_SBREG(sbh
, &sb
->sbtmstatehigh
);
1135 if ((tmstate
!= 0xffffffff) && (tmstate
& SBTMH_INT_STATUS
)) {
1138 OR_SBREG(sbh
, &sb
->sbtmstatelow
, SBTML_INT_ACK
);
1139 AND_SBREG(sbh
, &sb
->sbtmstatelow
, ~SBTML_INT_ACK
);
1143 sb_setcoreidx(sbh
, origidx
);
1144 INTR_RESTORE(si
, intr_val
);
1147 if ((inband
| timeout
| serror
) != 0) {
1149 SB_ERROR(("sb_taclear: inband 0x%x, serror 0x%x, timeout 0x%x!\n", inband
, serror
, timeout
));
1155 /* do buffered registers update */
1157 sb_commit(void *sbh
)
1160 sbpciregs_t
*pciregs
;
1166 origidx
= si
->curidx
;
1167 ASSERT(GOODIDX(origidx
));
1169 INTR_OFF(si
, intr_val
);
1170 /* switch over to pci core */
1171 pciregs
= (sbpciregs_t
*) sb_setcore(sbh
, SB_PCI
, 0);
1173 /* do the buffer registers update */
1174 W_REG(&pciregs
->bcastaddr
, SB_COMMIT
);
1175 W_REG(&pciregs
->bcastdata
, 0x0);
1177 /* restore core index */
1178 sb_setcoreidx(sbh
, origidx
);
1179 INTR_RESTORE(si
, intr_val
);
1182 /* reset and re-enable a core */
1184 sb_core_reset(void *sbh
, uint32 bits
)
1188 volatile uint32 dummy
;
1191 ASSERT(GOODREGS(si
->curmap
));
1192 sb
= REGS2SB(si
->curmap
);
1195 * Must do the disable sequence first to work for arbitrary current core state.
1197 sb_core_disable(sbh
, bits
);
1200 * Now do the initialization sequence.
1203 /* set reset while enabling the clock and forcing them on throughout the core */
1204 W_SBREG(sbh
, &sb
->sbtmstatelow
, (SBTML_FGC
| SBTML_CLK
| SBTML_RESET
| bits
));
1205 dummy
= R_SBREG(sbh
, &sb
->sbtmstatelow
);
1207 if (sb_coreid(sbh
) == SB_ILINE100
) {
1213 if (R_SBREG(sbh
, &sb
->sbtmstatehigh
) & SBTMH_SERR
) {
1214 W_SBREG(sbh
, &sb
->sbtmstatehigh
, 0);
1216 if ((dummy
= R_SBREG(sbh
, &sb
->sbimstate
)) & (SBIM_IBE
| SBIM_TO
)) {
1217 AND_SBREG(sbh
, &sb
->sbimstate
, ~(SBIM_IBE
| SBIM_TO
));
1220 /* clear reset and allow it to propagate throughout the core */
1221 W_SBREG(sbh
, &sb
->sbtmstatelow
, (SBTML_FGC
| SBTML_CLK
| bits
));
1222 dummy
= R_SBREG(sbh
, &sb
->sbtmstatelow
);
1225 /* leave clock enabled */
1226 W_SBREG(sbh
, &sb
->sbtmstatelow
, (SBTML_CLK
| bits
));
1227 dummy
= R_SBREG(sbh
, &sb
->sbtmstatelow
);
1232 sb_core_tofixup(void *sbh
)
1239 if (si
->pcirev
>= 5)
1242 ASSERT(GOODREGS(si
->curmap
));
1243 sb
= REGS2SB(si
->curmap
);
1245 if (si
->bus
== SB_BUS
) {
1246 SET_SBREG(sbh
, &sb
->sbimconfiglow
,
1247 SBIMCL_RTO_MASK
| SBIMCL_STO_MASK
,
1248 (0x5 << SBIMCL_RTO_SHIFT
) | 0x3);
1250 if (sb_coreid(sbh
) == SB_PCI
) {
1251 SET_SBREG(sbh
, &sb
->sbimconfiglow
,
1252 SBIMCL_RTO_MASK
| SBIMCL_STO_MASK
,
1253 (0x3 << SBIMCL_RTO_SHIFT
) | 0x2);
1255 SET_SBREG(sbh
, &sb
->sbimconfiglow
, (SBIMCL_RTO_MASK
| SBIMCL_STO_MASK
), 0);
1263 sb_core_disable(void *sbh
, uint32 bits
)
1266 volatile uint32 dummy
;
1271 ASSERT(GOODREGS(si
->curmap
));
1272 sb
= REGS2SB(si
->curmap
);
1274 /* must return if core is already in reset */
1275 if (R_SBREG(sbh
, &sb
->sbtmstatelow
) & SBTML_RESET
)
1278 /* put into reset and return if clocks are not enabled */
1279 if ((R_SBREG(sbh
, &sb
->sbtmstatelow
) & SBTML_CLK
) == 0)
1282 /* set the reject bit */
1283 W_SBREG(sbh
, &sb
->sbtmstatelow
, (SBTML_CLK
| SBTML_REJ
));
1285 /* spin until reject is set */
1286 while ((R_SBREG(sbh
, &sb
->sbtmstatelow
) & SBTML_REJ
) == 0)
1289 /* spin until sbtmstatehigh.busy is clear */
1290 while (R_SBREG(sbh
, &sb
->sbtmstatehigh
) & SBTMH_BUSY
)
1293 /* set reset and reject while enabling the clocks */
1294 W_SBREG(sbh
, &sb
->sbtmstatelow
, (bits
| SBTML_FGC
| SBTML_CLK
| SBTML_REJ
| SBTML_RESET
));
1295 dummy
= R_SBREG(sbh
, &sb
->sbtmstatelow
);
1299 /* leave reset and reject asserted */
1300 W_SBREG(sbh
, &sb
->sbtmstatelow
, (bits
| SBTML_REJ
| SBTML_RESET
));
1305 sb_watchdog(void *sbh
, uint ticks
)
1307 sb_info_t
*si
= SB_INFO(sbh
);
1310 switch (si
->gpioid
) {
1312 sb_corereg(sbh
, si
->gpioidx
, OFFSETOF(chipcregs_t
, watchdog
), ~0, ticks
);
1315 sb_corereg(sbh
, si
->gpioidx
, OFFSETOF(extifregs_t
, watchdog
), ~0, ticks
);
1320 /* initialize the pcmcia core */
1322 sb_pcmcia_init(void *sbh
)
1329 /* enable d11 mac interrupts */
1330 if (si
->chip
== BCM4301_DEVICE_ID
) {
1331 /* Have to use FCR2 in 4301 */
1332 OSL_PCMCIA_READ_ATTR(si
->osh
, PCMCIA_FCR2
+ PCMCIA_COR
, &cor
, 1);
1333 cor
|= COR_IRQEN
| COR_FUNEN
;
1334 OSL_PCMCIA_WRITE_ATTR(si
->osh
, PCMCIA_FCR2
+ PCMCIA_COR
, &cor
, 1);
1336 OSL_PCMCIA_READ_ATTR(si
->osh
, PCMCIA_FCR0
+ PCMCIA_COR
, &cor
, 1);
1337 cor
|= COR_IRQEN
| COR_FUNEN
;
1338 OSL_PCMCIA_WRITE_ATTR(si
->osh
, PCMCIA_FCR0
+ PCMCIA_COR
, &cor
, 1);
1345 * Configure the pci core for pci client (NIC) action
1346 * and get appropriate dma offset value.
1347 * coremask is the bitvec of cores by index to be enabled.
1350 sb_pci_setup(void *sbh
, uint32
*dmaoffset
, uint coremask
)
1354 sbpciregs_t
*pciregs
;
1364 /* if not pci bus, we're done */
1365 if (si
->bus
!= PCI_BUS
)
1370 /* get current core index */
1373 /* we interrupt on this backplane flag number */
1374 ASSERT(GOODREGS(si
->curmap
));
1375 sb
= REGS2SB(si
->curmap
);
1376 sbflag
= R_SBREG(sbh
, &sb
->sbtpsflag
) & SBTPS_NUM0_MASK
;
1378 /* switch over to pci core */
1379 pciregs
= (sbpciregs_t
*) sb_setcoreidx(sbh
, si
->pciidx
);
1380 sb
= REGS2SB(pciregs
);
1383 * Enable sb->pci interrupts. Assume
1384 * PCI rev 2.3 support was added in pci core rev 6 and things changed..
1386 if (si
->pcirev
< 6) {
1387 /* set sbintvec bit for our flag number */
1388 OR_SBREG(sbh
, &sb
->sbintvec
, (1 << sbflag
));
1390 /* pci config write to set this core bit in PCIIntMask */
1391 w
= OSL_PCI_READ_CONFIG(si
->osh
, PCI_INT_MASK
, sizeof(uint32
));
1392 w
|= (coremask
<< PCI_SBIM_SHIFT
);
1393 OSL_PCI_WRITE_CONFIG(si
->osh
, PCI_INT_MASK
, sizeof(uint32
), w
);
1396 /* enable prefetch and bursts for sonics-to-pci translation 2 */
1397 OR_REG(&pciregs
->sbtopci2
, (SBTOPCI_PREF
|SBTOPCI_BURST
));
1399 if (si
->pcirev
< 5) {
1400 SET_SBREG(sbh
, &sb
->sbimconfiglow
, SBIMCL_RTO_MASK
| SBIMCL_STO_MASK
,
1401 (0x3 << SBIMCL_RTO_SHIFT
) | 0x2);
1405 /* switch back to previous core */
1406 sb_setcoreidx(sbh
, idx
);
1408 /* use large sb pci dma window */
1410 *dmaoffset
= SB_PCI_DMA
;
1414 sb_base(uint32 admatch
)
1419 type
= admatch
& SBAM_TYPE_MASK
;
1425 base
= admatch
& SBAM_BASE0_MASK
;
1426 } else if (type
== 1) {
1427 ASSERT(!(admatch
& SBAM_ADNEG
)); /* neg not supported */
1428 base
= admatch
& SBAM_BASE1_MASK
;
1429 } else if (type
== 2) {
1430 ASSERT(!(admatch
& SBAM_ADNEG
)); /* neg not supported */
1431 base
= admatch
& SBAM_BASE2_MASK
;
1438 sb_size(uint32 admatch
)
1443 type
= admatch
& SBAM_TYPE_MASK
;
1449 size
= 1 << (((admatch
& SBAM_ADINT0_MASK
) >> SBAM_ADINT0_SHIFT
) + 1);
1450 } else if (type
== 1) {
1451 ASSERT(!(admatch
& SBAM_ADNEG
)); /* neg not supported */
1452 size
= 1 << (((admatch
& SBAM_ADINT1_MASK
) >> SBAM_ADINT1_SHIFT
) + 1);
1453 } else if (type
== 2) {
1454 ASSERT(!(admatch
& SBAM_ADNEG
)); /* neg not supported */
1455 size
= 1 << (((admatch
& SBAM_ADINT2_MASK
) >> SBAM_ADINT2_SHIFT
) + 1);
1461 /* return the core-type instantiation # of the current core */
1463 sb_coreunit(void *sbh
)
1476 ASSERT(GOODREGS(si
->curmap
));
1477 coreid
= sb_coreid(sbh
);
1479 /* count the cores of our type */
1480 for (i
= 0; i
< idx
; i
++)
1481 if (si
->coreid
[i
] == coreid
)
1487 static INLINE uint32
1491 case CC_F6_2
: return 2;
1492 case CC_F6_3
: return 3;
1493 case CC_F6_4
: return 4;
1494 case CC_F6_5
: return 5;
1495 case CC_F6_6
: return 6;
1496 case CC_F6_7
: return 7;
1501 /* calculate the speed the SB would run at given a set of clockcontrol values */
1503 sb_clock_rate(uint32 pll_type
, uint32 n
, uint32 m
)
1505 uint32 n1
, n2
, clock
, m1
, m2
, m3
, mc
;
1507 n1
= n
& CN_N1_MASK
;
1508 n2
= (n
& CN_N2_MASK
) >> CN_N2_SHIFT
;
1510 if ((pll_type
== PLL_TYPE1
) || (pll_type
== PLL_TYPE4
)) {
1513 } else if (pll_type
== PLL_TYPE2
) {
1516 ASSERT((n1
>= 2) && (n1
<= 7));
1517 ASSERT((n2
>= 5) && (n2
<= 23));
1518 } else if (pll_type
== PLL_TYPE3
) {
1521 ASSERT((pll_type
>= PLL_TYPE1
) && (pll_type
<= PLL_TYPE4
));
1523 clock
= CC_CLOCK_BASE
* n1
* n2
;
1528 m1
= m
& CC_M1_MASK
;
1529 m2
= (m
& CC_M2_MASK
) >> CC_M2_SHIFT
;
1530 m3
= (m
& CC_M3_MASK
) >> CC_M3_SHIFT
;
1531 mc
= (m
& CC_MC_MASK
) >> CC_MC_SHIFT
;
1533 if ((pll_type
== PLL_TYPE1
) || (pll_type
== PLL_TYPE4
)) {
1535 if (pll_type
== PLL_TYPE1
)
1542 case CC_MC_BYPASS
: return (clock
);
1543 case CC_MC_M1
: return (clock
/ m1
);
1544 case CC_MC_M1M2
: return (clock
/ (m1
* m2
));
1545 case CC_MC_M1M2M3
: return (clock
/ (m1
* m2
* m3
));
1546 case CC_MC_M1M3
: return (clock
/ (m1
* m3
));
1547 default: return (0);
1550 ASSERT(pll_type
== PLL_TYPE2
);
1555 ASSERT((m1
>= 2) && (m1
<= 7));
1556 ASSERT((m2
>= 3) && (m2
<= 10));
1557 ASSERT((m3
>= 2) && (m3
<= 7));
1559 if ((mc
& CC_T2MC_M1BYP
) == 0)
1561 if ((mc
& CC_T2MC_M2BYP
) == 0)
1563 if ((mc
& CC_T2MC_M3BYP
) == 0)
1570 /* returns the current speed the SB is running at */
1579 uint32 pll_type
, rate
;
1584 pll_type
= PLL_TYPE1
;
1586 INTR_OFF(si
, intr_val
);
1588 /* switch to extif or chipc core */
1589 if ((eir
= (extifregs_t
*) sb_setcore(sbh
, SB_EXTIF
, 0))) {
1590 n
= R_REG(&eir
->clockcontrol_n
);
1591 m
= R_REG(&eir
->clockcontrol_sb
);
1592 } else if ((cc
= (chipcregs_t
*) sb_setcore(sbh
, SB_CC
, 0))) {
1593 pll_type
= R_REG(&cc
->capabilities
) & CAP_PLL_MASK
;
1594 n
= R_REG(&cc
->clockcontrol_n
);
1595 m
= R_REG(&cc
->clockcontrol_sb
);
1597 INTR_RESTORE(si
, intr_val
);
1601 /* calculate rate */
1602 rate
= sb_clock_rate(pll_type
, n
, m
);
1604 /* switch back to previous core */
1605 sb_setcoreidx(sbh
, idx
);
1607 INTR_RESTORE(si
, intr_val
);
1612 /* change logical "focus" to the gpio core for optimized access */
1614 sb_gpiosetcore(void *sbh
)
1620 return (sb_setcoreidx(sbh
, si
->gpioidx
));
1623 /* mask&set gpiocontrol bits */
1625 sb_gpiocontrol(void *sbh
, uint32 mask
, uint32 val
)
1633 switch (si
->gpioid
) {
1635 regoff
= OFFSETOF(chipcregs_t
, gpiocontrol
);
1639 regoff
= OFFSETOF(sbpciregs_t
, gpiocontrol
);
1646 return (sb_corereg(sbh
, si
->gpioidx
, regoff
, mask
, val
));
1649 /* mask&set gpio output enable bits */
1651 sb_gpioouten(void *sbh
, uint32 mask
, uint32 val
)
1659 switch (si
->gpioid
) {
1661 regoff
= OFFSETOF(chipcregs_t
, gpioouten
);
1665 regoff
= OFFSETOF(sbpciregs_t
, gpioouten
);
1669 regoff
= OFFSETOF(extifregs_t
, gpio
[0].outen
);
1673 return (sb_corereg(sbh
, si
->gpioidx
, regoff
, mask
, val
));
1676 /* mask&set gpio output bits */
1678 sb_gpioout(void *sbh
, uint32 mask
, uint32 val
)
1686 switch (si
->gpioid
) {
1688 regoff
= OFFSETOF(chipcregs_t
, gpioout
);
1692 regoff
= OFFSETOF(sbpciregs_t
, gpioout
);
1696 regoff
= OFFSETOF(extifregs_t
, gpio
[0].out
);
1700 return (sb_corereg(sbh
, si
->gpioidx
, regoff
, mask
, val
));
1703 /* return the current gpioin register value */
1705 sb_gpioin(void *sbh
)
1713 switch (si
->gpioid
) {
1715 regoff
= OFFSETOF(chipcregs_t
, gpioin
);
1719 regoff
= OFFSETOF(sbpciregs_t
, gpioin
);
1723 regoff
= OFFSETOF(extifregs_t
, gpioin
);
1727 return (sb_corereg(sbh
, si
->gpioidx
, regoff
, 0, 0));
1730 /* mask&set gpio interrupt polarity bits */
1732 sb_gpiointpolarity(void *sbh
, uint32 mask
, uint32 val
)
1740 switch (si
->gpioid
) {
1742 regoff
= OFFSETOF(chipcregs_t
, gpiointpolarity
);
1746 /* pci gpio implementation does not support interrupt polarity */
1751 regoff
= OFFSETOF(extifregs_t
, gpiointpolarity
);
1755 return (sb_corereg(sbh
, si
->gpioidx
, regoff
, mask
, val
));
1758 /* mask&set gpio interrupt mask bits */
1760 sb_gpiointmask(void *sbh
, uint32 mask
, uint32 val
)
1768 switch (si
->gpioid
) {
1770 regoff
= OFFSETOF(chipcregs_t
, gpiointmask
);
1774 /* pci gpio implementation does not support interrupt mask */
1779 regoff
= OFFSETOF(extifregs_t
, gpiointmask
);
1783 return (sb_corereg(sbh
, si
->gpioidx
, regoff
, mask
, val
));
1788 * Return the slow clock source.
1789 * Three sources of SLOW CLOCK: LPO, Xtal, PCI
1792 sb_slowclk_src(void *sbh
)
1800 ASSERT(sb_coreid(sbh
) == SB_CC
);
1802 if (si
->ccrev
< 6) {
1804 case PCMCIA_BUS
: return (SCC_SS_XTAL
);
1806 v
= OSL_PCI_READ_CONFIG(si
->osh
, PCI_GPIO_OUT
, sizeof (uint32
));
1807 if (v
& PCI_CFG_GPIO_SCS
)
1808 return (SCC_SS_PCI
);
1810 return (SCC_SS_XTAL
);
1811 default: return (SCC_SS_XTAL
);
1813 } else if (si
->ccrev
< 10) {
1814 cc
= (chipcregs_t
*) sb_setcoreidx(sbh
, si
->curidx
);
1815 v
= R_REG(&cc
->slow_clk_ctl
) & SCC_SS_MASK
;
1818 return (SCC_SS_XTAL
);
1823 * Return the slowclock min or max frequency.
1824 * Three sources of SLOW CLOCK:
1825 * 1. On Chip LPO - 32khz or 160khz
1826 * 2. On Chip Xtal OSC - 20mhz/4*(divider+1)
1827 * 3. External PCI clock - 66mhz/4*(divider+1)
1830 sb_slowclk_freq(void *sbh
, bool max
)
1839 ASSERT(sb_coreid(sbh
) == SB_CC
);
1841 cc
= (chipcregs_t
*) sb_setcoreidx(sbh
, si
->curidx
);
1843 /* shouldn't be here unless we've established the chip has dynamic power control */
1844 ASSERT(R_REG(&cc
->capabilities
) & CAP_PWR_CTL
);
1846 slowclk
= sb_slowclk_src(sbh
);
1847 if (si
->ccrev
< 6) {
1848 if (slowclk
== SCC_SS_PCI
)
1849 return (max
? (PCIMAXFREQ
/64) : (PCIMINFREQ
/64));
1851 return (max
? (XTALMAXFREQ
/32) : (XTALMINFREQ
/32));
1852 } else if (si
->ccrev
< 10) {
1853 div
= 4 * (((R_REG(&cc
->slow_clk_ctl
) & SCC_CD_MASK
) >> SCC_CD_SHF
) + 1);
1854 if (slowclk
== SCC_SS_LPO
)
1855 return (max
? LPOMAXFREQ
: LPOMINFREQ
);
1856 else if (slowclk
== SCC_SS_XTAL
)
1857 return (max
? (XTALMAXFREQ
/div
) : (XTALMINFREQ
/div
));
1858 else if (slowclk
== SCC_SS_PCI
)
1859 return (max
? (PCIMAXFREQ
/div
) : (PCIMINFREQ
/div
));
1863 /* Chipc rev 10 is InstaClock */
1864 div
= R_REG(&cc
->system_clk_ctl
) >> SYCC_CD_SHF
;
1865 div
= 4 * (div
+ 1);
1866 return (max
? XTALMAXFREQ
: (XTALMINFREQ
/div
));
1872 sb_pwrctl_setdelay(void *sbh
, void *chipcregs
)
1875 uint slowmaxfreq
, pll_delay
, slowclk
;
1876 uint pll_on_delay
, fref_sel_delay
;
1878 pll_delay
= PLL_DELAY
;
1880 /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
1881 * since the xtal will also be powered down by dynamic power control logic.
1883 slowclk
= sb_slowclk_src(sbh
);
1884 if (slowclk
!= SCC_SS_XTAL
)
1885 pll_delay
+= XTAL_ON_DELAY
;
1887 slowmaxfreq
= sb_slowclk_freq(sbh
, TRUE
);
1889 pll_on_delay
= ((slowmaxfreq
* pll_delay
) + 999999) / 1000000;
1890 fref_sel_delay
= ((slowmaxfreq
* FREF_DELAY
) + 999999) / 1000000;
1892 cc
= (chipcregs_t
*)chipcregs
;
1893 W_REG(&cc
->pll_on_delay
, pll_on_delay
);
1894 W_REG(&cc
->fref_sel_delay
, fref_sel_delay
);
1897 /* set or get slow clock divider */
1899 sb_pwrctl_slowclk(void *sbh
, bool set
, uint
*div
)
1909 /* chipcommon cores prior to rev6 don't support slowclkcontrol */
1913 /* chipcommon cores rev10 are a whole new ball game */
1914 if (si
->ccrev
>= 10)
1917 if (set
&& ((*div
% 4) || (*div
< 4)))
1920 INTR_OFF(si
, intr_val
);
1921 origidx
= si
->curidx
;
1922 cc
= (chipcregs_t
*) sb_setcore(sbh
, SB_CC
, 0);
1925 if (!(R_REG(&cc
->capabilities
) & CAP_PWR_CTL
)) {
1931 SET_REG(&cc
->slow_clk_ctl
, SCC_CD_MASK
, ((*div
/ 4 - 1) << SCC_CD_SHF
));
1932 sb_pwrctl_setdelay(sbh
, (void *)cc
);
1934 *div
= 4 * (((R_REG(&cc
->slow_clk_ctl
) & SCC_CD_MASK
) >> SCC_CD_SHF
) + 1);
1937 sb_setcoreidx(sbh
, origidx
);
1938 INTR_RESTORE(si
, intr_val
);
1942 /* initialize power control delay registers */
1944 sb_pwrctl_init(void *sbh
)
1952 if (si
->bus
== SB_BUS
)
1955 origidx
= si
->curidx
;
1957 if ((cc
= (chipcregs_t
*) sb_setcore(sbh
, SB_CC
, 0)) == NULL
)
1960 if (!(R_REG(&cc
->capabilities
) & CAP_PWR_CTL
))
1963 /* 4317pc does not work with SlowClock less than 5Mhz */
1964 if (si
->bus
== PCMCIA_BUS
) {
1965 if ((si
->ccrev
>= 6) && (si
->ccrev
< 10))
1966 SET_REG(&cc
->slow_clk_ctl
, SCC_CD_MASK
, (SCC_DEF_DIV
<< SCC_CD_SHF
));
1969 sb_pwrctl_setdelay(sbh
, (void *)cc
);
1972 sb_setcoreidx(sbh
, origidx
);
1975 /* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */
1977 sb_pwrctl_fast_pwrup_delay(void *sbh
)
1988 origidx
= si
->curidx
;
1990 if (si
->bus
== SB_BUS
)
1993 INTR_OFF(si
, intr_val
);
1995 if ((cc
= (chipcregs_t
*) sb_setcore(sbh
, SB_CC
, 0)) == NULL
)
1998 if (!(R_REG(&cc
->capabilities
) & CAP_PWR_CTL
))
2001 slowminfreq
= sb_slowclk_freq(sbh
, FALSE
);
2002 fpdelay
= (((R_REG(&cc
->pll_on_delay
) + 2) * 1000000) + (slowminfreq
- 1)) / slowminfreq
;
2005 sb_setcoreidx(sbh
, origidx
);
2006 INTR_RESTORE(si
, intr_val
);
2010 /* turn primary xtal and/or pll off/on */
2012 sb_pwrctl_xtal(void *sbh
, uint what
, bool on
)
2015 uint32 in
, out
, outen
;
2028 in
= OSL_PCI_READ_CONFIG(si
->osh
, PCI_GPIO_IN
, sizeof (uint32
));
2029 out
= OSL_PCI_READ_CONFIG(si
->osh
, PCI_GPIO_OUT
, sizeof (uint32
));
2030 outen
= OSL_PCI_READ_CONFIG(si
->osh
, PCI_GPIO_OUTEN
, sizeof (uint32
));
2033 * We can't actually read the state of the PLLPD so we infer it
2034 * by the value of XTAL_PU which *is* readable via gpioin.
2036 if (on
&& (in
& PCI_CFG_GPIO_XTAL
))
2040 outen
|= PCI_CFG_GPIO_XTAL
;
2042 outen
|= PCI_CFG_GPIO_PLL
;
2045 /* turn primary xtal on */
2047 out
|= PCI_CFG_GPIO_XTAL
;
2049 out
|= PCI_CFG_GPIO_PLL
;
2050 OSL_PCI_WRITE_CONFIG(si
->osh
, PCI_GPIO_OUT
, sizeof (uint32
), out
);
2051 OSL_PCI_WRITE_CONFIG(si
->osh
, PCI_GPIO_OUTEN
, sizeof (uint32
), outen
);
2052 OSL_DELAY(XTAL_ON_DELAY
);
2057 out
&= ~PCI_CFG_GPIO_PLL
;
2058 OSL_PCI_WRITE_CONFIG(si
->osh
, PCI_GPIO_OUT
, sizeof (uint32
), out
);
2063 out
&= ~PCI_CFG_GPIO_XTAL
;
2065 out
|= PCI_CFG_GPIO_PLL
;
2066 OSL_PCI_WRITE_CONFIG(si
->osh
, PCI_GPIO_OUT
, sizeof (uint32
), out
);
2067 OSL_PCI_WRITE_CONFIG(si
->osh
, PCI_GPIO_OUTEN
, sizeof (uint32
), outen
);
2077 /* set dynamic power control mode (forceslow, forcefast, dynamic) */
2078 /* returns true if ignore pll off is set and false if it is not */
2080 sb_pwrctl_clk(void *sbh
, uint mode
)
2086 bool forcefastclk
=FALSE
;
2091 /* chipcommon cores prior to rev6 don't support slowclkcontrol */
2095 /* chipcommon cores rev10 are a whole new ball game */
2096 if (si
->ccrev
>= 10)
2099 INTR_OFF(si
, intr_val
);
2101 origidx
= si
->curidx
;
2103 cc
= (chipcregs_t
*) sb_setcore(sbh
, SB_CC
, 0);
2106 if (!(R_REG(&cc
->capabilities
) & CAP_PWR_CTL
))
2110 case CLK_FAST
: /* force fast (pll) clock */
2111 /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
2112 sb_pwrctl_xtal(sbh
, XTAL
, ON
);
2114 SET_REG(&cc
->slow_clk_ctl
, (SCC_XC
| SCC_FS
| SCC_IP
), SCC_IP
);
2117 case CLK_SLOW
: /* force slow clock */
2118 if ((si
->bus
== SDIO_BUS
) || (si
->bus
== PCMCIA_BUS
))
2122 OR_REG(&cc
->slow_clk_ctl
, SCC_FS
);
2125 case CLK_DYNAMIC
: /* enable dynamic power control */
2126 scc
= R_REG(&cc
->slow_clk_ctl
);
2127 scc
&= ~(SCC_FS
| SCC_IP
| SCC_XC
);
2128 if ((scc
& SCC_SS_MASK
) != SCC_SS_XTAL
)
2130 W_REG(&cc
->slow_clk_ctl
, scc
);
2132 /* for dynamic control, we have to release our xtal_pu "force on" */
2134 sb_pwrctl_xtal(sbh
, XTAL
, OFF
);
2138 /* Is the h/w forcing the use of the fast clk */
2139 forcefastclk
= (bool)((R_REG(&cc
->slow_clk_ctl
) & SCC_IP
) == SCC_IP
);
2142 sb_setcoreidx(sbh
, origidx
);
2143 INTR_RESTORE(si
, intr_val
);
2144 return (forcefastclk
);
2147 /* register driver interrupt disabling and restoring callback functions */
2149 sb_register_intr_callback(void *sbh
, void *intrsoff_fn
, void *intrsrestore_fn
, void *intrsenabled_fn
, void *intr_arg
)
2154 si
->intr_arg
= intr_arg
;
2155 si
->intrsoff_fn
= (sb_intrsoff_t
)intrsoff_fn
;
2156 si
->intrsrestore_fn
= (sb_intrsrestore_t
)intrsrestore_fn
;
2157 si
->intrsenabled_fn
= (sb_intrsenabled_t
)intrsenabled_fn
;
2158 /* save current core id. when this function called, the current core
2159 * must be the core which provides driver functions(il, et, wl, etc.)
2161 si
->dev_coreid
= si
->coreid
[si
->curidx
];