Root/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbutils.c

1/*
2 * Misc utility routines for accessing chip-specific features
3 * of the SiliconBackplane-based Broadcom chips.
4 *
5 * Copyright 2007, Broadcom Corporation
6 * All Rights Reserved.
7 *
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.
12 */
13
14#include <typedefs.h>
15#include <bcmdefs.h>
16#include <osl.h>
17#include <sbutils.h>
18#include <bcmdevs.h>
19#include <sbconfig.h>
20#include <sbchipc.h>
21#include <sbextif.h>
22#include <sbpci.h>
23#include <sbpcie.h>
24#include <pcicfg.h>
25#include <sbpcmcia.h>
26#include <sbsocram.h>
27#include <bcmnvram.h>
28#include <bcmsrom.h>
29#include <hndpmu.h>
30
31/* debug/trace */
32#define SB_ERROR(args)
33
34#ifdef BCMDBG
35#define SB_MSG(args) printf args
36#else
37#define SB_MSG(args)
38#endif /* BCMDBG */
39
40typedef uint32(*sb_intrsoff_t) (void *intr_arg);
41typedef void (*sb_intrsrestore_t) (void *intr_arg, uint32 arg);
42typedef bool(*sb_intrsenabled_t) (void *intr_arg);
43
44typedef struct gpioh_item {
45    void *arg;
46    bool level;
47    gpio_handler_t handler;
48    uint32 event;
49    struct gpioh_item *next;
50} gpioh_item_t;
51
52/* misc sb info needed by some of the routines */
53typedef struct sb_info {
54
55    struct sb_pub sb; /* back plane public state (must be first field) */
56
57    void *osh; /* osl os handle */
58    void *sdh; /* bcmsdh handle */
59
60    void *curmap; /* current regs va */
61    void *regs[SB_MAXCORES]; /* other regs va */
62
63    uint curidx; /* current core index */
64    uint dev_coreid; /* the core provides driver functions */
65
66    bool memseg; /* flag to toggle MEM_SEG register */
67
68    uint gpioidx; /* gpio control core index */
69    uint gpioid; /* gpio control coretype */
70
71    uint numcores; /* # discovered cores */
72    uint coreid[SB_MAXCORES]; /* id of each core */
73
74    void *intr_arg; /* interrupt callback function arg */
75    sb_intrsoff_t intrsoff_fn; /* turns chip interrupts off */
76    sb_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */
77    sb_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */
78
79    uint8 pciecap_lcreg_offset; /* PCIE capability LCreg offset in the config space */
80    bool pr42767_war;
81    uint8 pcie_polarity;
82    bool pcie_war_ovr; /* Override ASPM/Clkreq settings */
83
84    uint8 pmecap_offset; /* PM Capability offset in the config space */
85    bool pmecap; /* Capable of generating PME */
86
87    gpioh_item_t *gpioh_head; /* GPIO event handlers list */
88
89    char *vars;
90    uint varsz;
91} sb_info_t;
92
93/* local prototypes */
94static sb_info_t *sb_doattach(sb_info_t * si, uint devid, osl_t * osh,
95                  void *regs, uint bustype, void *sdh,
96                  char **vars, uint * varsz);
97static void sb_scan(sb_info_t * si);
98static uint _sb_coreidx(sb_info_t * si);
99static uint sb_pcidev2chip(uint pcidev);
100static uint sb_chip2numcores(uint chip);
101static bool sb_ispcie(sb_info_t * si);
102static uint8 sb_find_pci_capability(sb_info_t * si, uint8 req_cap_id,
103                    uchar * buf, uint32 * buflen);
104static int sb_pci_fixcfg(sb_info_t * si);
105/* routines to access mdio slave device registers */
106static int sb_pcie_mdiowrite(sb_info_t * si, uint physmedia, uint readdr,
107                 uint val);
108static int sb_pcie_mdioread(sb_info_t * si, uint physmedia, uint readdr,
109                uint * ret_val);
110
111/* dev path concatenation util */
112static char *sb_devpathvar(sb_t * sbh, char *var, int len, const char *name);
113
114/* WARs */
115static void sb_war43448(sb_t * sbh);
116static void sb_war43448_aspm(sb_t * sbh);
117static void sb_war32414_forceHT(sb_t * sbh, bool forceHT);
118static void sb_war30841(sb_info_t * si);
119static void sb_war42767(sb_t * sbh);
120static void sb_war42767_clkreq(sb_t * sbh);
121
122/* delay needed between the mdio control/ mdiodata register data access */
123#define PR28829_DELAY() OSL_DELAY(10)
124
125/* size that can take bitfielddump */
126#define BITFIELD_DUMP_SIZE 32
127
128/* global variable to indicate reservation/release of gpio's */
129static uint32 sb_gpioreservation = 0;
130
131/* global flag to prevent shared resources from being initialized multiple times in sb_attach() */
132static bool sb_onetimeinit = FALSE;
133
134#define SB_INFO(sbh) (sb_info_t*)(uintptr)sbh
135#define SET_SBREG(si, r, mask, val) \
136        W_SBREG((si), (r), ((R_SBREG((si), (r)) & ~(mask)) | (val)))
137#define GOODCOREADDR(x) (((x) >= SB_ENUM_BASE) && ((x) <= SB_ENUM_LIM) && \
138        ISALIGNED((x), SB_CORE_SIZE))
139#define GOODREGS(regs) ((regs) && ISALIGNED((uintptr)(regs), SB_CORE_SIZE))
140#define REGS2SB(va) (sbconfig_t*) ((int8*)(va) + SBCONFIGOFF)
141#define BADCOREADDR 0
142#define GOODIDX(idx) (((uint)idx) < SB_MAXCORES)
143#define BADIDX (SB_MAXCORES+1)
144#define NOREV -1 /* Invalid rev */
145
146#define PCI(si) ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (si->sb.buscoretype == SB_PCI))
147#define PCIE(si) ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (si->sb.buscoretype == SB_PCIE))
148#define PCMCIA(si) ((BUSTYPE(si->sb.bustype) == PCMCIA_BUS) && (si->memseg == TRUE))
149
150/* sonicsrev */
151#define SONICS_2_2 (SBIDL_RV_2_2 >> SBIDL_RV_SHIFT)
152#define SONICS_2_3 (SBIDL_RV_2_3 >> SBIDL_RV_SHIFT)
153
154#define R_SBREG(si, sbr) sb_read_sbreg((si), (sbr))
155#define W_SBREG(si, sbr, v) sb_write_sbreg((si), (sbr), (v))
156#define AND_SBREG(si, sbr, v) W_SBREG((si), (sbr), (R_SBREG((si), (sbr)) & (v)))
157#define OR_SBREG(si, sbr, v) W_SBREG((si), (sbr), (R_SBREG((si), (sbr)) | (v)))
158
159/*
160 * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/
161 * after core switching to avoid invalid register accesss inside ISR.
162 */
163#define INTR_OFF(si, intr_val) \
164    if ((si)->intrsoff_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
165        intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); }
166#define INTR_RESTORE(si, intr_val) \
167    if ((si)->intrsrestore_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
168        (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); }
169
170/* dynamic clock control defines */
171#define LPOMINFREQ 25000 /* low power oscillator min */
172#define LPOMAXFREQ 43000 /* low power oscillator max */
173#define XTALMINFREQ 19800000 /* 20 MHz - 1% */
174#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */
175#define PCIMINFREQ 25000000 /* 25 MHz */
176#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */
177
178#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */
179#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */
180
181/* force HT war check */
182#define FORCEHT_WAR32414(si) \
183    (((PCIE(si)) && (si->sb.chip == BCM4311_CHIP_ID) && ((si->sb.chiprev <= 1))) || \
184    ((PCI(si) || PCIE(si)) && (si->sb.chip == BCM4321_CHIP_ID) && (si->sb.chiprev <= 3)))
185
186#define PCIE_ASPMWARS(si) \
187    ((PCIE(si)) && ((si->sb.buscorerev >= 3) && (si->sb.buscorerev <= 5)))
188
189/* GPIO Based LED powersave defines */
190#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */
191#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */
192
193#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME)
194
195static uint32 sb_read_sbreg(sb_info_t * si, volatile uint32 * sbr)
196{
197    uint8 tmp;
198    uint32 val, intr_val = 0;
199
200    /*
201     * compact flash only has 11 bits address, while we needs 12 bits address.
202     * MEM_SEG will be OR'd with other 11 bits address in hardware,
203     * so we program MEM_SEG with 12th bit when necessary(access sb regsiters).
204     * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special
205     */
206    if (PCMCIA(si)) {
207        INTR_OFF(si, intr_val);
208        tmp = 1;
209        OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1);
210        sbr = (volatile uint32 *)((uintptr) sbr & ~(1 << 11)); /* mask out bit 11 */
211    }
212
213    val = R_REG(si->osh, sbr);
214
215    if (PCMCIA(si)) {
216        tmp = 0;
217        OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1);
218        INTR_RESTORE(si, intr_val);
219    }
220
221    return (val);
222}
223
224static void sb_write_sbreg(sb_info_t * si, volatile uint32 * sbr, uint32 v)
225{
226    uint8 tmp;
227    volatile uint32 dummy;
228    uint32 intr_val = 0;
229
230    /*
231     * compact flash only has 11 bits address, while we needs 12 bits address.
232     * MEM_SEG will be OR'd with other 11 bits address in hardware,
233     * so we program MEM_SEG with 12th bit when necessary(access sb regsiters).
234     * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special
235     */
236    if (PCMCIA(si)) {
237        INTR_OFF(si, intr_val);
238        tmp = 1;
239        OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1);
240        sbr = (volatile uint32 *)((uintptr) sbr & ~(1 << 11)); /* mask out bit 11 */
241    }
242
243    if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) {
244#ifdef IL_BIGENDIAN
245        dummy = R_REG(si->osh, sbr);
246        W_REG(si->osh, ((volatile uint16 *)sbr + 1),
247              (uint16) ((v >> 16) & 0xffff));
248        dummy = R_REG(si->osh, sbr);
249        W_REG(si->osh, (volatile uint16 *)sbr, (uint16) (v & 0xffff));
250#else
251        dummy = R_REG(si->osh, sbr);
252        W_REG(si->osh, (volatile uint16 *)sbr, (uint16) (v & 0xffff));
253        dummy = R_REG(si->osh, sbr);
254        W_REG(si->osh, ((volatile uint16 *)sbr + 1),
255              (uint16) ((v >> 16) & 0xffff));
256#endif /* IL_BIGENDIAN */
257    } else
258        W_REG(si->osh, sbr, v);
259
260    if (PCMCIA(si)) {
261        tmp = 0;
262        OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1);
263        INTR_RESTORE(si, intr_val);
264    }
265}
266
267/*
268 * Allocate a sb handle.
269 * devid - pci device id (used to determine chip#)
270 * osh - opaque OS handle
271 * regs - virtual address of initial core registers
272 * bustype - pci/pcmcia/sb/sdio/etc
273 * vars - pointer to a pointer area for "environment" variables
274 * varsz - pointer to int to return the size of the vars
275 */
276sb_t *sb_attach(uint devid, osl_t * osh, void *regs,
277                uint bustype, void *sdh, char **vars,
278                uint * varsz) {
279    sb_info_t *si;
280
281    /* alloc sb_info_t */
282    if ((si = MALLOC(osh, sizeof(sb_info_t))) == NULL) {
283        SB_ERROR(("sb_attach: malloc failed! malloced %d bytes\n",
284              MALLOCED(osh)));
285        return (NULL);
286    }
287
288    if (sb_doattach(si, devid, osh, regs, bustype, sdh, vars, varsz) ==
289        NULL) {
290        MFREE(osh, si, sizeof(sb_info_t));
291        return (NULL);
292    }
293    si->vars = vars ? *vars : NULL;
294    si->varsz = varsz ? *varsz : 0;
295
296    return (sb_t *) si;
297}
298
299/* Using sb_kattach depends on SB_BUS support, either implicit */
300/* no limiting BCMBUSTYPE value) or explicit (value is SB_BUS). */
301#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SB_BUS)
302
303/* global kernel resource */
304static sb_info_t ksi;
305
306/* generic kernel variant of sb_attach() */
307sb_t *BCMINITFN(sb_kattach) (osl_t * osh) {
308    static bool ksi_attached = FALSE;
309    uint32 *regs;
310
311    if (!ksi_attached) {
312        uint32 cid;
313
314        regs = (uint32 *) REG_MAP(SB_ENUM_BASE, SB_CORE_SIZE);
315        cid = R_REG(osh, (uint32 *) regs);
316        if (((cid & CID_ID_MASK) == BCM4712_CHIP_ID) &&
317            ((cid & CID_PKG_MASK) != BCM4712LARGE_PKG_ID) &&
318            ((cid & CID_REV_MASK) <= (3 << CID_REV_SHIFT))) {
319            uint32 *scc, val;
320
321            scc =
322                (uint32 *) ((uchar *) regs +
323                    OFFSETOF(chipcregs_t, slow_clk_ctl));
324            val = R_REG(osh, scc);
325            SB_ERROR((" initial scc = 0x%x\n", val));
326            val |= SCC_SS_XTAL;
327            W_REG(osh, scc, val);
328        }
329
330        if (sb_doattach(&ksi, BCM4710_DEVICE_ID, osh, (void *)regs, SB_BUS, NULL,
331                osh != SB_OSH ? &ksi.vars : NULL,
332                osh != SB_OSH ? &ksi.varsz : NULL) == NULL)
333            return NULL;
334        ksi_attached = TRUE;
335    }
336
337    return &ksi.sb;
338}
339#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SB_BUS) */
340
341static sb_info_t *BCMINITFN(sb_doattach) (sb_info_t * si, uint devid,
342                      osl_t * osh, void *regs,
343                      uint bustype, void *sdh,
344                      char **vars, uint * varsz) {
345    uint origidx;
346    chipcregs_t *cc;
347    sbconfig_t *sb;
348    uint32 w;
349    char *pvars;
350
351    ASSERT(GOODREGS(regs));
352
353    bzero((uchar *) si, sizeof(sb_info_t));
354    si->sb.buscoreidx = si->gpioidx = BADIDX;
355
356    si->curmap = regs;
357    si->sdh = sdh;
358    si->osh = osh;
359
360    /* check to see if we are a sb core mimic'ing a pci core */
361    if (bustype == PCI_BUS) {
362        if (OSL_PCI_READ_CONFIG
363            (si->osh, PCI_SPROM_CONTROL,
364             sizeof(uint32)) == 0xffffffff) {
365            SB_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SB " "devid:0x%x\n", __FUNCTION__, devid));
366            bustype = SB_BUS;
367        }
368    }
369    si->sb.bustype = bustype;
370    if (si->sb.bustype != BUSTYPE(si->sb.bustype)) {
371        SB_ERROR(("sb_doattach: bus type %d does not match configured bus type %d\n", si->sb.bustype, BUSTYPE(si->sb.bustype)));
372        return NULL;
373    }
374
375    /* need to set memseg flag for CF card first before any sb registers access */
376    if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS)
377        si->memseg = TRUE;
378
379    /* kludge to enable the clock on the 4306 which lacks a slowclock */
380    if (BUSTYPE(si->sb.bustype) == PCI_BUS && !sb_ispcie(si))
381        sb_clkctl_xtal(&si->sb, XTAL | PLL, ON);
382
383    if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
384        w = OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32));
385        if (!GOODCOREADDR(w))
386            OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN,
387                         sizeof(uint32), SB_ENUM_BASE);
388    }
389
390    /* initialize current core index value */
391    si->curidx = _sb_coreidx(si);
392
393    if (si->curidx == BADIDX) {
394        SB_ERROR(("sb_doattach: bad core index\n"));
395        return NULL;
396    }
397
398    /* get sonics backplane revision */
399    sb = REGS2SB(regs);
400    si->sb.sonicsrev =
401        (R_SBREG(si, &sb->sbidlow) & SBIDL_RV_MASK) >> SBIDL_RV_SHIFT;
402    /* keep and reuse the initial register mapping */
403    origidx = si->curidx;
404    if (BUSTYPE(si->sb.bustype) == SB_BUS)
405        si->regs[origidx] = regs;
406
407    /* is core-0 a chipcommon core? */
408    si->numcores = 1;
409    cc = (chipcregs_t *) sb_setcoreidx(&si->sb, 0);
410    if (sb_coreid(&si->sb) != SB_CC)
411        cc = NULL;
412
413    /* determine chip id and rev */
414    if (cc) {
415        /* chip common core found! */
416        si->sb.chip = R_REG(si->osh, &cc->chipid) & CID_ID_MASK;
417        si->sb.chiprev =
418            (R_REG(si->osh, &cc->chipid) & CID_REV_MASK) >>
419            CID_REV_SHIFT;
420        si->sb.chippkg =
421            (R_REG(si->osh, &cc->chipid) & CID_PKG_MASK) >>
422            CID_PKG_SHIFT;
423    } else {
424        /* no chip common core -- must convert device id to chip id */
425        if ((si->sb.chip = sb_pcidev2chip(devid)) == 0) {
426            SB_ERROR(("sb_doattach: unrecognized device id 0x%04x\n", devid));
427            sb_setcoreidx(&si->sb, origidx);
428            return NULL;
429        }
430    }
431
432    /* get chipcommon rev */
433    si->sb.ccrev = cc ? (int)sb_corerev(&si->sb) : NOREV;
434
435    /* get chipcommon capabilites */
436    si->sb.cccaps = cc ? R_REG(si->osh, &cc->capabilities) : 0;
437
438    /* determine numcores */
439    if (cc && ((si->sb.ccrev == 4) || (si->sb.ccrev >= 6)))
440        si->numcores =
441            (R_REG(si->osh, &cc->chipid) & CID_CC_MASK) >> CID_CC_SHIFT;
442    else
443        si->numcores = sb_chip2numcores(si->sb.chip);
444
445    /* return to original core */
446    sb_setcoreidx(&si->sb, origidx);
447
448    /* sanity checks */
449    ASSERT(si->sb.chip);
450
451    /* scan for cores */
452    sb_scan(si);
453
454    /* fixup necessary chip/core configurations */
455    if (BUSTYPE(si->sb.bustype) == PCI_BUS && sb_pci_fixcfg(si)) {
456        SB_ERROR(("sb_doattach: sb_pci_fixcfg failed\n"));
457        return NULL;
458    }
459
460    /* Init nvram from sprom/otp if they exist */
461    if (srom_var_init
462        (&si->sb, BUSTYPE(si->sb.bustype), regs, si->osh, vars, varsz)) {
463        SB_ERROR(("sb_doattach: srom_var_init failed: bad srom\n"));
464        return (NULL);
465    }
466    pvars = vars ? *vars : NULL;
467
468    /* PMU specific initializations */
469    if ((si->sb.cccaps & CC_CAP_PMU) && !sb_onetimeinit) {
470        sb_pmu_init(&si->sb, si->osh);
471        /* Find out Crystal frequency and init PLL */
472        sb_pmu_pll_init(&si->sb, si->osh, getintvar(pvars, "xtalfreq"));
473        /* Initialize PMU resources (up/dn timers, dep masks, etc.) */
474        sb_pmu_res_init(&si->sb, si->osh);
475    }
476    if (cc == NULL) {
477        /*
478         * The chip revision number is hardwired into all
479         * of the pci function config rev fields and is
480         * independent from the individual core revision numbers.
481         * For example, the "A0" silicon of each chip is chip rev 0.
482         * For PCMCIA we get it from the CIS instead.
483         */
484        if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) {
485            ASSERT(vars);
486            si->sb.chiprev = getintvar(*vars, "chiprev");
487        } else if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
488            w = OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_REV,
489                        sizeof(uint32));
490            si->sb.chiprev = w & 0xff;
491        } else
492            si->sb.chiprev = 0;
493    }
494
495    if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) {
496        w = getintvar(pvars, "regwindowsz");
497        si->memseg = (w <= CFTABLE_REGWIN_2K) ? TRUE : FALSE;
498    }
499    /* gpio control core is required */
500    if (!GOODIDX(si->gpioidx)) {
501        SB_ERROR(("sb_doattach: gpio control core not found\n"));
502        return NULL;
503    }
504
505    /* get boardtype and boardrev */
506    switch (BUSTYPE(si->sb.bustype)) {
507    case PCI_BUS:
508        /* do a pci config read to get subsystem id and subvendor id */
509        w = OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_SVID, sizeof(uint32));
510        /* Let nvram variables override subsystem Vend/ID */
511        if ((si->sb.boardvendor =
512             (uint16) sb_getdevpathintvar(&si->sb, "boardvendor")) == 0)
513            si->sb.boardvendor = w & 0xffff;
514        else
515            SB_ERROR(("Overriding boardvendor: 0x%x instead of 0x%x\n", si->sb.boardvendor, w & 0xffff));
516        if ((si->sb.boardtype =
517             (uint16) sb_getdevpathintvar(&si->sb, "boardtype")) == 0)
518            si->sb.boardtype = (w >> 16) & 0xffff;
519        else
520            SB_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n", si->sb.boardtype, (w >> 16) & 0xffff));
521        break;
522
523    case PCMCIA_BUS:
524        si->sb.boardvendor = getintvar(pvars, "manfid");
525        si->sb.boardtype = getintvar(pvars, "prodid");
526        break;
527
528    case SB_BUS:
529    case JTAG_BUS:
530        si->sb.boardvendor = VENDOR_BROADCOM;
531        if (pvars == NULL
532            || ((si->sb.boardtype = getintvar(pvars, "prodid")) == 0))
533            if ((si->sb.boardtype =
534                 getintvar(NULL, "boardtype")) == 0)
535                si->sb.boardtype = 0xffff;
536        break;
537    }
538
539    if (si->sb.boardtype == 0) {
540        SB_ERROR(("sb_doattach: unknown board type\n"));
541        ASSERT(si->sb.boardtype);
542    }
543
544    si->sb.boardflags = getintvar(pvars, "boardflags");
545
546    /* setup the GPIO based LED powersave register */
547    if (si->sb.ccrev >= 16) {
548        if ((pvars == NULL) || ((w = getintvar(pvars, "leddc")) == 0))
549            w = DEFAULT_GPIOTIMERVAL;
550        sb_corereg(&si->sb, SB_CC_IDX,
551               OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
552    }
553
554    /* Determine if this board needs override */
555    if (PCIE(si) && (si->sb.chip == BCM4321_CHIP_ID))
556        si->pcie_war_ovr = ((si->sb.boardvendor == VENDOR_APPLE) &&
557                    ((uint8) getintvar(pvars, "sromrev") == 4)
558                    && ((uint8) getintvar(pvars, "boardrev") <=
559                    0x71))
560            || ((uint32) getintvar(pvars, "boardflags2") &
561            BFL2_PCIEWAR_OVR);
562
563    if (PCIE_ASPMWARS(si)) {
564        sb_war43448_aspm((void *)si);
565        sb_war42767_clkreq((void *)si);
566    }
567
568    if (FORCEHT_WAR32414(si)) {
569        si->sb.pr32414 = TRUE;
570        sb_clkctl_init(&si->sb);
571        sb_war32414_forceHT(&si->sb, 1);
572    }
573
574    if (PCIE(si) && ((si->sb.buscorerev == 6) || (si->sb.buscorerev == 7)))
575        si->sb.pr42780 = TRUE;
576
577    if (PCIE_ASPMWARS(si))
578        sb_pcieclkreq(&si->sb, 1, 0);
579
580    if (PCIE(si) &&
581        (((si->sb.chip == BCM4311_CHIP_ID) && (si->sb.chiprev == 2)) ||
582         ((si->sb.chip == BCM4312_CHIP_ID) && (si->sb.chiprev == 0))))
583        sb_set_initiator_to(&si->sb, 0x3,
584                    sb_findcoreidx(&si->sb, SB_D11, 0));
585
586    /* Disable gpiopullup and gpiopulldown */
587    if (!sb_onetimeinit && si->sb.ccrev >= 20) {
588        cc = (chipcregs_t *) sb_setcore(&si->sb, SB_CC, 0);
589        W_REG(osh, &cc->gpiopullup, 0);
590        W_REG(osh, &cc->gpiopulldown, 0);
591        sb_setcoreidx(&si->sb, origidx);
592    }
593#ifdef BCMDBG
594    /* clear any previous epidiag-induced target abort */
595    sb_taclear(&si->sb);
596#endif /* BCMDBG */
597
598#ifdef HNDRTE
599    sb_onetimeinit = TRUE;
600#endif
601
602    return (si);
603}
604
605/* Enable/Disable clkreq for PCIE (4311B0/4321B1) */
606void sb_war42780_clkreq(sb_t * sbh, bool clkreq) {
607    sb_info_t *si;
608
609    si = SB_INFO(sbh);
610
611    /* Don't change clkreq value if serdespll war has not yet been applied */
612    if (!si->pr42767_war && PCIE_ASPMWARS(si))
613        return;
614
615    sb_pcieclkreq(sbh, 1, (int32) clkreq);
616}
617
618static void BCMINITFN(sb_war43448) (sb_t * sbh) {
619    sb_info_t *si;
620
621    si = SB_INFO(sbh);
622
623    /* if not pcie bus, we're done */
624    if (!PCIE(si) || !PCIE_ASPMWARS(si))
625        return;
626
627    /* Restore the polarity */
628    if (si->pcie_polarity != 0)
629        sb_pcie_mdiowrite((void *)(uintptr) & si->sb, MDIODATA_DEV_RX,
630                  SERDES_RX_CTRL, si->pcie_polarity);
631}
632
633static void BCMINITFN(sb_war43448_aspm) (sb_t * sbh) {
634    uint32 w;
635    uint16 val16, *reg16;
636    sbpcieregs_t *pcieregs;
637    sb_info_t *si;
638
639    si = SB_INFO(sbh);
640
641    /* if not pcie bus, we're done */
642    if (!PCIE(si) || !PCIE_ASPMWARS(si))
643        return;
644
645    /* no ASPM stuff on QT or VSIM */
646    if (si->sb.chippkg == HDLSIM_PKG_ID || si->sb.chippkg == HWSIM_PKG_ID)
647        return;
648
649    pcieregs = (sbpcieregs_t *) sb_setcoreidx(sbh, si->sb.buscoreidx);
650
651    /* Enable ASPM in the shadow SROM and Link control */
652    reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET];
653    val16 = R_REG(si->osh, reg16);
654    if (!si->pcie_war_ovr)
655        val16 |= SRSH_ASPM_ENB;
656    else
657        val16 &= ~SRSH_ASPM_ENB;
658    W_REG(si->osh, reg16, val16);
659
660    w = OSL_PCI_READ_CONFIG(si->osh, si->pciecap_lcreg_offset,
661                sizeof(uint32));
662    if (!si->pcie_war_ovr)
663        w |= PCIE_ASPM_ENAB;
664    else
665        w &= ~PCIE_ASPM_ENAB;
666    OSL_PCI_WRITE_CONFIG(si->osh, si->pciecap_lcreg_offset, sizeof(uint32),
667                 w);
668}
669
670static void BCMINITFN(sb_war32414_forceHT) (sb_t * sbh, bool forceHT) {
671    sb_info_t *si;
672    uint32 val = 0;
673
674    si = SB_INFO(sbh);
675
676    ASSERT(FORCEHT_WAR32414(si));
677
678    if (forceHT)
679        val = SYCC_HR;
680    sb_corereg(sbh, SB_CC_IDX, OFFSETOF(chipcregs_t, system_clk_ctl),
681           SYCC_HR, val);
682}
683
684uint sb_coreid(sb_t * sbh)
685{
686    sb_info_t *si;
687    sbconfig_t *sb;
688
689    si = SB_INFO(sbh);
690    sb = REGS2SB(si->curmap);
691
692    return ((R_SBREG(si, &sb->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT);
693}
694
695uint sb_flag(sb_t * sbh)
696{
697    sb_info_t *si;
698    sbconfig_t *sb;
699
700    si = SB_INFO(sbh);
701    sb = REGS2SB(si->curmap);
702
703    return R_SBREG(si, &sb->sbtpsflag) & SBTPS_NUM0_MASK;
704}
705
706uint sb_coreidx(sb_t * sbh)
707{
708    sb_info_t *si;
709
710    si = SB_INFO(sbh);
711    return (si->curidx);
712}
713
714static uint _sb_coreidx(sb_info_t * si)
715{
716
717    sbconfig_t *sb;
718    uint32 sbaddr = 0;
719
720    ASSERT(si);
721
722    switch (BUSTYPE(si->sb.bustype)) {
723    case SB_BUS:
724        sb = REGS2SB(si->curmap);
725        sbaddr = sb_base(R_SBREG(si, &sb->sbadmatch0));
726        break;
727
728    case PCI_BUS:
729        sbaddr =
730            OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32));
731        break;
732
733    case PCMCIA_BUS:{
734            uint8 tmp = 0;
735
736            OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR0, &tmp, 1);
737            sbaddr = (uint) tmp << 12;
738            OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR1, &tmp, 1);
739            sbaddr |= (uint) tmp << 16;
740            OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR2, &tmp, 1);
741            sbaddr |= (uint) tmp << 24;
742            break;
743        }
744
745#ifdef BCMJTAG
746    case JTAG_BUS:
747        sbaddr = (uint32) si->curmap;
748        break;
749#endif /* BCMJTAG */
750
751    default:
752        ASSERT(0);
753    }
754
755    if (!GOODCOREADDR(sbaddr))
756        return BADIDX;
757
758    return ((sbaddr - SB_ENUM_BASE) / SB_CORE_SIZE);
759}
760
761uint sb_corevendor(sb_t * sbh)
762{
763    sb_info_t *si;
764    sbconfig_t *sb;
765
766    si = SB_INFO(sbh);
767    sb = REGS2SB(si->curmap);
768
769    return ((R_SBREG(si, &sb->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT);
770}
771
772uint sb_corerev(sb_t * sbh)
773{
774    sb_info_t *si;
775    sbconfig_t *sb;
776    uint sbidh;
777
778    si = SB_INFO(sbh);
779    sb = REGS2SB(si->curmap);
780    sbidh = R_SBREG(si, &sb->sbidhigh);
781
782    return (SBCOREREV(sbidh));
783}
784
785void *sb_osh(sb_t * sbh)
786{
787    sb_info_t *si;
788
789    si = SB_INFO(sbh);
790    return si->osh;
791}
792
793void sb_setosh(sb_t * sbh, osl_t * osh)
794{
795    sb_info_t *si;
796
797    si = SB_INFO(sbh);
798    if (si->osh != NULL) {
799        SB_ERROR(("osh is already set....\n"));
800        ASSERT(!si->osh);
801    }
802    si->osh = osh;
803}
804
805/* set sbtmstatelow core-specific flags */
806void sb_coreflags_wo(sb_t * sbh, uint32 mask, uint32 val)
807{
808    sb_info_t *si;
809    sbconfig_t *sb;
810    uint32 w;
811
812    si = SB_INFO(sbh);
813    sb = REGS2SB(si->curmap);
814
815    ASSERT((val & ~mask) == 0);
816
817    /* mask and set */
818    w = (R_SBREG(si, &sb->sbtmstatelow) & ~mask) | val;
819    W_SBREG(si, &sb->sbtmstatelow, w);
820}
821
822/* set/clear sbtmstatelow core-specific flags */
823uint32 sb_coreflags(sb_t * sbh, uint32 mask, uint32 val)
824{
825    sb_info_t *si;
826    sbconfig_t *sb;
827    uint32 w;
828
829    si = SB_INFO(sbh);
830    sb = REGS2SB(si->curmap);
831
832    ASSERT((val & ~mask) == 0);
833
834    /* mask and set */
835    if (mask || val) {
836        w = (R_SBREG(si, &sb->sbtmstatelow) & ~mask) | val;
837        W_SBREG(si, &sb->sbtmstatelow, w);
838    }
839
840    /* return the new value
841     * for write operation, the following readback ensures the completion of write opration.
842     */
843    return (R_SBREG(si, &sb->sbtmstatelow));
844}
845
846/* set/clear sbtmstatehigh core-specific flags */
847uint32 sb_coreflagshi(sb_t * sbh, uint32 mask, uint32 val)
848{
849    sb_info_t *si;
850    sbconfig_t *sb;
851    uint32 w;
852
853    si = SB_INFO(sbh);
854    sb = REGS2SB(si->curmap);
855
856    ASSERT((val & ~mask) == 0);
857    ASSERT((mask & ~SBTMH_FL_MASK) == 0);
858
859    /* mask and set */
860    if (mask || val) {
861        w = (R_SBREG(si, &sb->sbtmstatehigh) & ~mask) | val;
862        W_SBREG(si, &sb->sbtmstatehigh, w);
863    }
864
865    /* return the new value */
866    return (R_SBREG(si, &sb->sbtmstatehigh));
867}
868
869/* Run bist on current core. Caller needs to take care of core-specific bist hazards */
870int sb_corebist(sb_t * sbh)
871{
872    uint32 sblo;
873    sb_info_t *si;
874    sbconfig_t *sb;
875    int result = 0;
876
877    si = SB_INFO(sbh);
878    sb = REGS2SB(si->curmap);
879
880    sblo = R_SBREG(si, &sb->sbtmstatelow);
881    W_SBREG(si, &sb->sbtmstatelow, (sblo | SBTML_FGC | SBTML_BE));
882
883    SPINWAIT(((R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BISTD) == 0),
884         100000);
885
886    if (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BISTF)
887        result = -1;
888
889    W_SBREG(si, &sb->sbtmstatelow, sblo);
890
891    return result;
892}
893
894bool sb_iscoreup(sb_t * sbh)
895{
896    sb_info_t *si;
897    sbconfig_t *sb;
898
899    si = SB_INFO(sbh);
900    sb = REGS2SB(si->curmap);
901
902    return ((R_SBREG(si, &sb->sbtmstatelow) &
903         (SBTML_RESET | SBTML_REJ_MASK | SBTML_CLK)) == SBTML_CLK);
904}
905
906/*
907 * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation,
908 * switch back to the original core, and return the new value.
909 *
910 * When using the silicon backplane, no fidleing with interrupts or core switches are needed.
911 *
912 * Also, when using pci/pcie, we can optimize away the core switching for pci registers
913 * and (on newer pci cores) chipcommon registers.
914 */
915uint sb_corereg(sb_t * sbh, uint coreidx, uint regoff, uint mask, uint val)
916{
917    uint origidx = 0;
918    uint32 *r = NULL;
919    uint w;
920    uint intr_val = 0;
921    bool fast = FALSE;
922    sb_info_t *si;
923
924    si = SB_INFO(sbh);
925
926    ASSERT(GOODIDX(coreidx));
927    ASSERT(regoff < SB_CORE_SIZE);
928    ASSERT((val & ~mask) == 0);
929
930#if 0
931    if (BUSTYPE(si->sb.bustype) == SB_BUS) {
932        /* If internal bus, we can always get at everything */
933        fast = TRUE;
934        /* map if does not exist */
935        if (!si->regs[coreidx]) {
936            si->regs[coreidx] =
937                (void *)REG_MAP(si->coresba[coreidx], SB_CORE_SIZE);
938            ASSERT(GOODREGS(si->regs[coreidx]));
939        }
940        r = (uint32 *) ((uchar *) si->regs[coreidx] + regoff);
941    } else if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
942        /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */
943
944        if ((si->coreid[coreidx] == SB_CC) &&
945            ((si->sb.buscoretype == SB_PCIE)
946             || (si->sb.buscorerev >= 13))) {
947            /* Chipc registers are mapped at 12KB */
948
949            fast = TRUE;
950            r = (uint32 *) ((char *)si->curmap +
951                    PCI_16KB0_CCREGS_OFFSET + regoff);
952        } else if (si->sb.buscoreidx == coreidx) {
953            /* pci registers are at either in the last 2KB of an 8KB window
954             * or, in pcie and pci rev 13 at 8KB
955             */
956            fast = TRUE;
957            if ((si->sb.buscoretype == SB_PCIE)
958                || (si->sb.buscorerev >= 13))
959                r = (uint32 *) ((char *)si->curmap +
960                        PCI_16KB0_PCIREGS_OFFSET +
961                        regoff);
962            else
963                r = (uint32 *) ((char *)si->curmap +
964                        ((regoff >= SBCONFIGOFF) ?
965                         PCI_BAR0_PCISBR_OFFSET :
966                         PCI_BAR0_PCIREGS_OFFSET)
967                        + regoff);
968        }
969    }
970#endif
971
972    if (!fast) {
973        INTR_OFF(si, intr_val);
974
975        /* save current core index */
976        origidx = sb_coreidx(&si->sb);
977
978        /* switch core */
979        r = (uint32 *) ((uchar *) sb_setcoreidx(&si->sb, coreidx) +
980                regoff);
981    }
982    ASSERT(r);
983
984    /* mask and set */
985    if (mask || val) {
986        if (regoff >= SBCONFIGOFF) {
987            w = (R_SBREG(si, r) & ~mask) | val;
988            W_SBREG(si, r, w);
989        } else {
990            w = (R_REG(si->osh, r) & ~mask) | val;
991            W_REG(si->osh, r, w);
992        }
993    }
994
995    /* readback */
996    if (regoff >= SBCONFIGOFF)
997        w = R_SBREG(si, r);
998    else {
999        if ((si->sb.chip == BCM5354_CHIP_ID) &&
1000            (coreidx == SB_CC_IDX) &&
1001            (regoff == OFFSETOF(chipcregs_t, watchdog))) {
1002            w = val;
1003        } else
1004            w = R_REG(si->osh, r);
1005    }
1006
1007    if (!fast) {
1008        /* restore core index */
1009        if (origidx != coreidx)
1010            sb_setcoreidx(&si->sb, origidx);
1011
1012        INTR_RESTORE(si, intr_val);
1013    }
1014
1015    return (w);
1016}
1017
1018#define DWORD_ALIGN(x) (x & ~(0x03))
1019#define BYTE_POS(x) (x & 0x3)
1020#define WORD_POS(x) (x & 0x1)
1021
1022#define BYTE_SHIFT(x) (8 * BYTE_POS(x))
1023#define WORD_SHIFT(x) (16 * WORD_POS(x))
1024
1025#define BYTE_VAL(a, x) ((a >> BYTE_SHIFT(x)) & 0xFF)
1026#define WORD_VAL(a, x) ((a >> WORD_SHIFT(x)) & 0xFFFF)
1027
1028#define read_pci_cfg_byte(a) \
1029    (BYTE_VAL(OSL_PCI_READ_CONFIG(si->osh, DWORD_ALIGN(a), 4), a) & 0xff)
1030
1031#define read_pci_cfg_word(a) \
1032    (WORD_VAL(OSL_PCI_READ_CONFIG(si->osh, DWORD_ALIGN(a), 4), a) & 0xffff)
1033
1034/* return cap_offset if requested capability exists in the PCI config space */
1035static uint8
1036sb_find_pci_capability(sb_info_t * si, uint8 req_cap_id, uchar * buf,
1037               uint32 * buflen)
1038{
1039    uint8 cap_id;
1040    uint8 cap_ptr = 0;
1041    uint32 bufsize;
1042    uint8 byte_val;
1043
1044    if (BUSTYPE(si->sb.bustype) != PCI_BUS)
1045        goto end;
1046
1047    /* check for Header type 0 */
1048    byte_val = read_pci_cfg_byte(PCI_CFG_HDR);
1049    if ((byte_val & 0x7f) != PCI_HEADER_NORMAL)
1050        goto end;
1051
1052    /* check if the capability pointer field exists */
1053    byte_val = read_pci_cfg_byte(PCI_CFG_STAT);
1054    if (!(byte_val & PCI_CAPPTR_PRESENT))
1055        goto end;
1056
1057    cap_ptr = read_pci_cfg_byte(PCI_CFG_CAPPTR);
1058    /* check if the capability pointer is 0x00 */
1059    if (cap_ptr == 0x00)
1060        goto end;
1061
1062    /* loop thr'u the capability list and see if the pcie capabilty exists */
1063
1064    cap_id = read_pci_cfg_byte(cap_ptr);
1065
1066    while (cap_id != req_cap_id) {
1067        cap_ptr = read_pci_cfg_byte((cap_ptr + 1));
1068        if (cap_ptr == 0x00)
1069            break;
1070        cap_id = read_pci_cfg_byte(cap_ptr);
1071    }
1072    if (cap_id != req_cap_id) {
1073        goto end;
1074    }
1075    /* found the caller requested capability */
1076    if ((buf != NULL) && (buflen != NULL)) {
1077        uint8 cap_data;
1078
1079        bufsize = *buflen;
1080        if (!bufsize)
1081            goto end;
1082        *buflen = 0;
1083        /* copy the cpability data excluding cap ID and next ptr */
1084        cap_data = cap_ptr + 2;
1085        if ((bufsize + cap_data) > SZPCR)
1086            bufsize = SZPCR - cap_data;
1087        *buflen = bufsize;
1088        while (bufsize--) {
1089            *buf = read_pci_cfg_byte(cap_data);
1090            cap_data++;
1091            buf++;
1092        }
1093    }
1094      end:
1095    return cap_ptr;
1096}
1097
1098uint8 sb_pcieclkreq(sb_t * sbh, uint32 mask, uint32 val)
1099{
1100    sb_info_t *si;
1101    uint32 reg_val;
1102    uint8 offset;
1103
1104    si = SB_INFO(sbh);
1105
1106    offset = si->pciecap_lcreg_offset;
1107    if (!offset)
1108        return 0;
1109
1110    reg_val = OSL_PCI_READ_CONFIG(si->osh, offset, sizeof(uint32));
1111    /* set operation */
1112    if (mask) {
1113        if (val)
1114            reg_val |= PCIE_CLKREQ_ENAB;
1115        else
1116            reg_val &= ~PCIE_CLKREQ_ENAB;
1117        OSL_PCI_WRITE_CONFIG(si->osh, offset, sizeof(uint32), reg_val);
1118        reg_val = OSL_PCI_READ_CONFIG(si->osh, offset, sizeof(uint32));
1119    }
1120    if (reg_val & PCIE_CLKREQ_ENAB)
1121        return 1;
1122    else
1123        return 0;
1124}
1125
1126#ifdef BCMDBG
1127
1128uint32 sb_pcielcreg(sb_t * sbh, uint32 mask, uint32 val)
1129{
1130    sb_info_t *si;
1131    uint32 reg_val;
1132    uint8 offset;
1133
1134    si = SB_INFO(sbh);
1135
1136    if (!PCIE(si))
1137        return 0;
1138
1139    offset = si->pciecap_lcreg_offset;
1140    if (!offset)
1141        return 0;
1142
1143    /* set operation */
1144    if (mask)
1145        OSL_PCI_WRITE_CONFIG(si->osh, offset, sizeof(uint32), val);
1146
1147    reg_val = OSL_PCI_READ_CONFIG(si->osh, offset, sizeof(uint32));
1148
1149    return reg_val;
1150}
1151
1152uint8 sb_pcieL1plldown(sb_t * sbh)
1153{
1154    sb_info_t *si;
1155    uint intr_val = 0;
1156    uint origidx;
1157    uint32 reg_val;
1158
1159    si = SB_INFO(sbh);
1160
1161    if (!PCIE(si))
1162        return 0;
1163    if (!((si->sb.buscorerev == 3) || (si->sb.buscorerev == 4)))
1164        return 0;
1165
1166    if (!sb_pcieclkreq((void *)(uintptr) sbh, 0, 0)) {
1167        SB_ERROR(("PCIEL1PLLDOWN requires Clkreq be enabled, so enable it\n"));
1168        sb_pcieclkreq((void *)(uintptr) sbh, 1, 1);
1169    }
1170    reg_val = sb_pcielcreg((void *)(uintptr) sbh, 0, 0);
1171    if (reg_val & PCIE_CAP_LCREG_ASPML0s) {
1172        SB_ERROR(("PCIEL1PLLDOWN requires L0s to be disabled\n"));
1173        reg_val &= ~PCIE_CAP_LCREG_ASPML0s;
1174        sb_pcielcreg((void *)(uintptr) sbh, 1, reg_val);
1175    } else
1176        SB_ERROR(("PCIEL1PLLDOWN: L0s is already disabled\n"));
1177
1178    /* turnoff intrs, change core, set original back, turn on intrs back on */
1179    origidx = si->curidx;
1180    INTR_OFF(si, intr_val);
1181    sb_setcore(sbh, SB_PCIE, 0);
1182
1183    sb_pcie_writereg((void *)(uintptr) sbh, (void *)PCIE_PCIEREGS,
1184             PCIE_DLLP_PCIE11, 0);
1185
1186    sb_setcoreidx(sbh, origidx);
1187    INTR_RESTORE(si, intr_val);
1188    return 1;
1189}
1190#endif /* BCMDBG */
1191
1192/* return TRUE if PCIE capability exists in the pci config space */
1193static bool sb_ispcie(sb_info_t * si)
1194{
1195    uint8 cap_ptr;
1196
1197    cap_ptr = sb_find_pci_capability(si, PCI_CAP_PCIECAP_ID, NULL, NULL);
1198    if (!cap_ptr)
1199        return FALSE;
1200
1201    si->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET;
1202
1203    return TRUE;
1204}
1205
1206/* Wake-on-wireless-LAN (WOWL) support functions */
1207/* return TRUE if PM capability exists in the pci config space */
1208bool sb_pci_pmecap(sb_t * sbh)
1209{
1210    uint8 cap_ptr;
1211    uint32 pmecap;
1212    sb_info_t *si;
1213
1214    si = SB_INFO(sbh);
1215
1216    if (si == NULL || !(PCI(si) || PCIE(si)))
1217        return FALSE;
1218
1219    if (!si->pmecap_offset) {
1220        cap_ptr =
1221            sb_find_pci_capability(si, PCI_CAP_POWERMGMTCAP_ID, NULL,
1222                       NULL);
1223        if (!cap_ptr)
1224            return FALSE;
1225
1226        si->pmecap_offset = cap_ptr;
1227
1228        pmecap =
1229            OSL_PCI_READ_CONFIG(si->osh, si->pmecap_offset,
1230                    sizeof(uint32));
1231
1232        /* At least one state can generate PME */
1233        si->pmecap = (pmecap & PME_CAP_PM_STATES) != 0;
1234    }
1235
1236    return (si->pmecap);
1237}
1238
1239/* Enable PME generation and disable clkreq */
1240void sb_pci_pmeen(sb_t * sbh)
1241{
1242    sb_info_t *si;
1243    uint32 w;
1244    si = SB_INFO(sbh);
1245
1246    /* if not pmecapable return */
1247    if (!sb_pci_pmecap(sbh))
1248        return;
1249
1250    w = OSL_PCI_READ_CONFIG(si->osh, si->pmecap_offset + PME_CSR_OFFSET,
1251                sizeof(uint32));
1252    w |= (PME_CSR_PME_EN);
1253    OSL_PCI_WRITE_CONFIG(si->osh, si->pmecap_offset + PME_CSR_OFFSET,
1254                 sizeof(uint32), w);
1255
1256    /* Disable clkreq */
1257    if (si->pr42767_war) {
1258        sb_pcieclkreq(sbh, 1, 0);
1259        si->pr42767_war = FALSE;
1260    } else if (si->sb.pr42780) {
1261        sb_pcieclkreq(sbh, 1, 1);
1262    }
1263}
1264
1265/* Disable PME generation, clear the PME status bit if set and
1266 * return TRUE if PME status set
1267 */
1268bool sb_pci_pmeclr(sb_t * sbh)
1269{
1270    sb_info_t *si;
1271    uint32 w;
1272    bool ret = FALSE;
1273
1274    si = SB_INFO(sbh);
1275
1276    if (!sb_pci_pmecap(sbh))
1277        return ret;
1278
1279    w = OSL_PCI_READ_CONFIG(si->osh, si->pmecap_offset + PME_CSR_OFFSET,
1280                sizeof(uint32));
1281
1282    SB_ERROR(("sb_pci_pmeclr PMECSR : 0x%x\n", w));
1283    ret = (w & PME_CSR_PME_STAT) == PME_CSR_PME_STAT;
1284
1285    /* PMESTAT is cleared by writing 1 to it */
1286    w &= ~(PME_CSR_PME_EN);
1287
1288    OSL_PCI_WRITE_CONFIG(si->osh, si->pmecap_offset + PME_CSR_OFFSET,
1289                 sizeof(uint32), w);
1290
1291    return ret;
1292}
1293
1294/* use pci dev id to determine chip id for chips not having a chipcommon core */
1295static uint BCMINITFN(sb_pcidev2chip) (uint pcidev) {
1296    if ((pcidev >= BCM4710_DEVICE_ID) && (pcidev <= BCM47XX_USB_ID))
1297        return (BCM4710_CHIP_ID);
1298    if ((pcidev >= BCM4402_ENET_ID) && (pcidev <= BCM4402_V90_ID))
1299        return (BCM4402_CHIP_ID);
1300    if (pcidev == BCM4401_ENET_ID)
1301        return (BCM4402_CHIP_ID);
1302    if (pcidev == SDIOH_FPGA_ID)
1303        return (SDIOH_FPGA_ID);
1304
1305    return (0);
1306}
1307
1308/* Scan the enumeration space to find all cores starting from the given
1309 * bus 'sbba'. Append coreid and other info to the lists in 'si'. 'sba'
1310 * is the default core address at chip POR time and 'regs' is the virtual
1311 * address that the default core is mapped at. 'ncores' is the number of
1312 * cores expected on bus 'sbba'. It returns the total number of cores
1313 * starting from bus 'sbba', inclusive.
1314 */
1315
1316static void BCMINITFN(sb_scan) (sb_info_t * si) {
1317    sb_t *sbh;
1318    uint origidx;
1319    uint i;
1320    bool pci;
1321    bool pcie;
1322    uint pciidx;
1323    uint pcieidx;
1324    uint pcirev;
1325    uint pcierev;
1326
1327    sbh = (sb_t *) si;
1328
1329    /* numcores should already be set */
1330    ASSERT((si->numcores > 0) && (si->numcores <= SB_MAXCORES));
1331
1332    /* save current core index */
1333    origidx = sb_coreidx(&si->sb);
1334
1335    si->sb.buscorerev = NOREV;
1336    si->sb.buscoreidx = BADIDX;
1337
1338    si->gpioidx = BADIDX;
1339
1340    pci = pcie = FALSE;
1341    pcirev = pcierev = NOREV;
1342    pciidx = pcieidx = BADIDX;
1343
1344    for (i = 0; i < si->numcores; i++) {
1345        sb_setcoreidx(&si->sb, i);
1346        si->coreid[i] = sb_coreid(&si->sb);
1347
1348        if (si->coreid[i] == SB_PCI) {
1349            pciidx = i;
1350            pcirev = sb_corerev(&si->sb);
1351            pci = TRUE;
1352        } else if (si->coreid[i] == SB_PCIE) {
1353            pcieidx = i;
1354            pcierev = sb_corerev(&si->sb);
1355            pcie = TRUE;
1356        } else if (si->coreid[i] == SB_PCMCIA) {
1357            si->sb.buscorerev = sb_corerev(&si->sb);
1358            si->sb.buscoretype = si->coreid[i];
1359            si->sb.buscoreidx = i;
1360        }
1361    }
1362    if (pci && pcie) {
1363        if (sb_ispcie(si))
1364            pci = FALSE;
1365        else
1366            pcie = FALSE;
1367    }
1368    if (pci) {
1369        si->sb.buscoretype = SB_PCI;
1370        si->sb.buscorerev = pcirev;
1371        si->sb.buscoreidx = pciidx;
1372    } else if (pcie) {
1373        si->sb.buscoretype = SB_PCIE;
1374        si->sb.buscorerev = pcierev;
1375        si->sb.buscoreidx = pcieidx;
1376    }
1377
1378    /*
1379     * Find the gpio "controlling core" type and index.
1380     * Precedence:
1381     * - if there's a chip common core - use that
1382     * - else if there's a pci core (rev >= 2) - use that
1383     * - else there had better be an extif core (4710 only)
1384     */
1385    if (GOODIDX(sb_findcoreidx(sbh, SB_CC, 0))) {
1386        si->gpioidx = sb_findcoreidx(sbh, SB_CC, 0);
1387        si->gpioid = SB_CC;
1388    } else if (PCI(si) && (si->sb.buscorerev >= 2)) {
1389        si->gpioidx = si->sb.buscoreidx;
1390        si->gpioid = SB_PCI;
1391    } else if (sb_findcoreidx(sbh, SB_EXTIF, 0)) {
1392        si->gpioidx = sb_findcoreidx(sbh, SB_EXTIF, 0);
1393        si->gpioid = SB_EXTIF;
1394    } else
1395        ASSERT(si->gpioidx != BADIDX);
1396
1397    /* return to original core index */
1398    sb_setcoreidx(&si->sb, origidx);
1399}
1400
1401/* may be called with core in reset */
1402void sb_detach(sb_t * sbh)
1403{
1404    sb_info_t *si;
1405    uint idx;
1406
1407    si = SB_INFO(sbh);
1408
1409    if (si == NULL)
1410        return;
1411
1412    if (BUSTYPE(si->sb.bustype) == SB_BUS)
1413        for (idx = 0; idx < SB_MAXCORES; idx++)
1414            if (si->regs[idx]) {
1415                REG_UNMAP(si->regs[idx]);
1416                si->regs[idx] = NULL;
1417            }
1418#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SB_BUS)
1419    if (si != &ksi)
1420#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SB_BUS) */
1421        MFREE(si->osh, si, sizeof(sb_info_t));
1422}
1423
1424
1425/* convert chip number to number of i/o cores */
1426static uint BCMINITFN(sb_chip2numcores) (uint chip) {
1427    if (chip == BCM4710_CHIP_ID)
1428        return (9);
1429    if (chip == BCM4402_CHIP_ID)
1430        return (3);
1431    if (chip == BCM4306_CHIP_ID) /* < 4306c0 */
1432        return (6);
1433    if (chip == BCM4704_CHIP_ID)
1434        return (9);
1435    if (chip == BCM5365_CHIP_ID)
1436        return (7);
1437    if (chip == SDIOH_FPGA_ID)
1438        return (2);
1439
1440    SB_ERROR(("sb_chip2numcores: unsupported chip 0x%x\n", chip));
1441    ASSERT(0);
1442    return (1);
1443}
1444
1445/* return index of coreid or BADIDX if not found */
1446uint sb_findcoreidx(sb_t * sbh, uint coreid, uint coreunit)
1447{
1448    sb_info_t *si;
1449    uint found;
1450    uint i;
1451
1452    si = SB_INFO(sbh);
1453
1454    found = 0;
1455
1456    for (i = 0; i < si->numcores; i++)
1457        if (si->coreid[i] == coreid) {
1458            if (found == coreunit)
1459                return (i);
1460            found++;
1461        }
1462
1463    return (BADIDX);
1464}
1465
1466/*
1467 * this function changes logical "focus" to the indiciated core,
1468 * must be called with interrupt off.
1469 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
1470 */
1471void *sb_setcoreidx(sb_t * sbh, uint coreidx)
1472{
1473    sb_info_t *si;
1474    uint32 sbaddr;
1475    uint8 tmp;
1476
1477    si = SB_INFO(sbh);
1478
1479    if (coreidx >= si->numcores)
1480        return (NULL);
1481
1482    /*
1483     * If the user has provided an interrupt mask enabled function,
1484     * then assert interrupts are disabled before switching the core.
1485     */
1486    ASSERT((si->intrsenabled_fn == NULL)
1487           || !(*(si)->intrsenabled_fn) ((si)->intr_arg));
1488
1489    sbaddr = SB_ENUM_BASE + (coreidx * SB_CORE_SIZE);
1490
1491    switch (BUSTYPE(si->sb.bustype)) {
1492    case SB_BUS:
1493        /* map new one */
1494        if (!si->regs[coreidx]) {
1495            si->regs[coreidx] =
1496                (void *)REG_MAP(sbaddr, SB_CORE_SIZE);
1497            ASSERT(GOODREGS(si->regs[coreidx]));
1498        }
1499        si->curmap = si->regs[coreidx];
1500        break;
1501
1502    case PCI_BUS:
1503        /* point bar0 window */
1504        OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, 4, sbaddr);
1505        break;
1506
1507    case PCMCIA_BUS:
1508        tmp = (sbaddr >> 12) & 0x0f;
1509        OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_ADDR0, &tmp, 1);
1510        tmp = (sbaddr >> 16) & 0xff;
1511        OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_ADDR1, &tmp, 1);
1512        tmp = (sbaddr >> 24) & 0xff;
1513        OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_ADDR2, &tmp, 1);
1514        break;
1515#ifdef BCMJTAG
1516    case JTAG_BUS:
1517        /* map new one */
1518        if (!si->regs[coreidx]) {
1519            si->regs[coreidx] = (void *)sbaddr;
1520            ASSERT(GOODREGS(si->regs[coreidx]));
1521        }
1522        si->curmap = si->regs[coreidx];
1523        break;
1524#endif /* BCMJTAG */
1525    }
1526
1527    si->curidx = coreidx;
1528
1529    return (si->curmap);
1530}
1531
1532/*
1533 * this function changes logical "focus" to the indiciated core,
1534 * must be called with interrupt off.
1535 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
1536 */
1537void *sb_setcore(sb_t * sbh, uint coreid, uint coreunit)
1538{
1539    uint idx;
1540
1541    idx = sb_findcoreidx(sbh, coreid, coreunit);
1542    if (!GOODIDX(idx))
1543        return (NULL);
1544
1545    return (sb_setcoreidx(sbh, idx));
1546}
1547
1548/* return chip number */
1549uint BCMINITFN(sb_chip) (sb_t * sbh) {
1550    sb_info_t *si;
1551
1552    si = SB_INFO(sbh);
1553    return (si->sb.chip);
1554}
1555
1556/* return chip revision number */
1557uint BCMINITFN(sb_chiprev) (sb_t * sbh) {
1558    sb_info_t *si;
1559
1560    si = SB_INFO(sbh);
1561    return (si->sb.chiprev);
1562}
1563
1564/* return chip common revision number */
1565uint BCMINITFN(sb_chipcrev) (sb_t * sbh) {
1566    sb_info_t *si;
1567
1568    si = SB_INFO(sbh);
1569    return (si->sb.ccrev);
1570}
1571
1572/* return chip package option */
1573uint BCMINITFN(sb_chippkg) (sb_t * sbh) {
1574    sb_info_t *si;
1575
1576    si = SB_INFO(sbh);
1577    return (si->sb.chippkg);
1578}
1579
1580/* return PCI core rev. */
1581uint BCMINITFN(sb_pcirev) (sb_t * sbh) {
1582    sb_info_t *si;
1583
1584    si = SB_INFO(sbh);
1585    return (si->sb.buscorerev);
1586}
1587
1588bool BCMINITFN(sb_war16165) (sb_t * sbh) {
1589    sb_info_t *si;
1590
1591    si = SB_INFO(sbh);
1592
1593    return (PCI(si) && (si->sb.buscorerev <= 10));
1594}
1595
1596static void BCMINITFN(sb_war30841) (sb_info_t * si) {
1597    sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128);
1598    sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100);
1599    sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466);
1600}
1601
1602/* return PCMCIA core rev. */
1603uint BCMINITFN(sb_pcmciarev) (sb_t * sbh) {
1604    sb_info_t *si;
1605
1606    si = SB_INFO(sbh);
1607    return (si->sb.buscorerev);
1608}
1609
1610/* return board vendor id */
1611uint BCMINITFN(sb_boardvendor) (sb_t * sbh) {
1612    sb_info_t *si;
1613
1614    si = SB_INFO(sbh);
1615    return (si->sb.boardvendor);
1616}
1617
1618/* return boardtype */
1619uint BCMINITFN(sb_boardtype) (sb_t * sbh) {
1620    sb_info_t *si;
1621    char *var;
1622
1623    si = SB_INFO(sbh);
1624
1625    if (BUSTYPE(si->sb.bustype) == SB_BUS && si->sb.boardtype == 0xffff) {
1626        /* boardtype format is a hex string */
1627        si->sb.boardtype = getintvar(NULL, "boardtype");
1628
1629        /* backward compatibility for older boardtype string format */
1630        if ((si->sb.boardtype == 0)
1631            && (var = getvar(NULL, "boardtype"))) {
1632            if (!strcmp(var, "bcm94710dev"))
1633                si->sb.boardtype = BCM94710D_BOARD;
1634            else if (!strcmp(var, "bcm94710ap"))
1635                si->sb.boardtype = BCM94710AP_BOARD;
1636            else if (!strcmp(var, "bu4710"))
1637                si->sb.boardtype = BU4710_BOARD;
1638            else if (!strcmp(var, "bcm94702mn"))
1639                si->sb.boardtype = BCM94702MN_BOARD;
1640            else if (!strcmp(var, "bcm94710r1"))
1641                si->sb.boardtype = BCM94710R1_BOARD;
1642            else if (!strcmp(var, "bcm94710r4"))
1643                si->sb.boardtype = BCM94710R4_BOARD;
1644            else if (!strcmp(var, "bcm94702cpci"))
1645                si->sb.boardtype = BCM94702CPCI_BOARD;
1646            else if (!strcmp(var, "bcm95380_rr"))
1647                si->sb.boardtype = BCM95380RR_BOARD;
1648        }
1649    }
1650
1651    return (si->sb.boardtype);
1652}
1653
1654/* return bus type of sbh device */
1655uint sb_bus(sb_t * sbh)
1656{
1657    sb_info_t *si;
1658
1659    si = SB_INFO(sbh);
1660    return (si->sb.bustype);
1661}
1662
1663/* return bus core type */
1664uint sb_buscoretype(sb_t * sbh)
1665{
1666    sb_info_t *si;
1667
1668    si = SB_INFO(sbh);
1669
1670    return (si->sb.buscoretype);
1671}
1672
1673/* return bus core revision */
1674uint sb_buscorerev(sb_t * sbh)
1675{
1676    sb_info_t *si;
1677    si = SB_INFO(sbh);
1678
1679    return (si->sb.buscorerev);
1680}
1681
1682/* return list of found cores */
1683uint sb_corelist(sb_t * sbh, uint coreid[])
1684{
1685    sb_info_t *si;
1686
1687    si = SB_INFO(sbh);
1688
1689    bcopy((uchar *) si->coreid, (uchar *) coreid,
1690          (si->numcores * sizeof(uint)));
1691    return (si->numcores);
1692}
1693
1694/* return current register mapping */
1695void *sb_coreregs(sb_t * sbh)
1696{
1697    sb_info_t *si;
1698
1699    si = SB_INFO(sbh);
1700    ASSERT(GOODREGS(si->curmap));
1701
1702    return (si->curmap);
1703}
1704
1705#if defined(BCMDBG_ASSERT)
1706/* traverse all cores to find and clear source of serror */
1707static void sb_serr_clear(sb_info_t * si)
1708{
1709    sbconfig_t *sb;
1710    uint origidx;
1711    uint i, intr_val = 0;
1712    void *corereg = NULL;
1713
1714    INTR_OFF(si, intr_val);
1715    origidx = sb_coreidx(&si->sb);
1716
1717    for (i = 0; i < si->numcores; i++) {
1718        corereg = sb_setcoreidx(&si->sb, i);
1719        if (NULL != corereg) {
1720            sb = REGS2SB(corereg);
1721            if ((R_SBREG(si, &sb->sbtmstatehigh)) & SBTMH_SERR) {
1722                AND_SBREG(si, &sb->sbtmstatehigh, ~SBTMH_SERR);
1723                SB_ERROR(("sb_serr_clear: SError at core 0x%x\n", sb_coreid(&si->sb)));
1724            }
1725        }
1726    }
1727
1728    sb_setcoreidx(&si->sb, origidx);
1729    INTR_RESTORE(si, intr_val);
1730}
1731
1732/*
1733 * Check if any inband, outband or timeout errors has happened and clear them.
1734 * Must be called with chip clk on !
1735 */
1736bool sb_taclear(sb_t * sbh)
1737{
1738    sb_info_t *si;
1739    sbconfig_t *sb;
1740    uint origidx;
1741    uint intr_val = 0;
1742    bool rc = FALSE;
1743    uint32 inband = 0, serror = 0, timeout = 0;
1744    void *corereg = NULL;
1745    volatile uint32 imstate, tmstate;
1746
1747    si = SB_INFO(sbh);
1748
1749    if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
1750        volatile uint32 stcmd;
1751
1752        /* inband error is Target abort for PCI */
1753        stcmd =
1754            OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_CMD, sizeof(uint32));
1755        inband = stcmd & PCI_CFG_CMD_STAT_TA;
1756        if (inband) {
1757#ifdef BCMDBG
1758            SB_ERROR(("inband:\n"));
1759            sb_viewall((void *)si);
1760#endif
1761            OSL_PCI_WRITE_CONFIG(si->osh, PCI_CFG_CMD,
1762                         sizeof(uint32), stcmd);
1763        }
1764
1765        /* serror */
1766        stcmd =
1767            OSL_PCI_READ_CONFIG(si->osh, PCI_INT_STATUS,
1768                    sizeof(uint32));
1769        serror = stcmd & PCI_SBIM_STATUS_SERR;
1770        if (serror) {
1771#ifdef BCMDBG
1772            SB_ERROR(("serror:\n"));
1773            sb_viewall((void *)si);
1774#endif
1775            sb_serr_clear(si);
1776            OSL_PCI_WRITE_CONFIG(si->osh, PCI_INT_STATUS,
1777                         sizeof(uint32), stcmd);
1778        }
1779
1780        /* timeout */
1781        imstate = sb_corereg(sbh, si->sb.buscoreidx,
1782                     SBCONFIGOFF + OFFSETOF(sbconfig_t,
1783                                sbimstate), 0, 0);
1784        if ((imstate != 0xffffffff) && (imstate & (SBIM_IBE | SBIM_TO))) {
1785            sb_corereg(sbh, si->sb.buscoreidx,
1786                   SBCONFIGOFF + OFFSETOF(sbconfig_t,
1787                              sbimstate), ~0,
1788                   (imstate & ~(SBIM_IBE | SBIM_TO)));
1789            /* inband = imstate & SBIM_IBE; same as TA above */
1790            timeout = imstate & SBIM_TO;
1791            if (timeout) {
1792#ifdef BCMDBG
1793                SB_ERROR(("timeout:\n"));
1794                sb_viewall((void *)si);
1795#endif
1796            }
1797        }
1798
1799        if (inband) {
1800            /* dump errlog for sonics >= 2.3 */
1801            if (si->sb.sonicsrev == SONICS_2_2) ;
1802            else {
1803                uint32 imerrlog, imerrloga;
1804                imerrlog =
1805                    sb_corereg(sbh, si->sb.buscoreidx,
1806                           SBIMERRLOG, 0, 0);
1807                if (imerrlog & SBTMEL_EC) {
1808                    imerrloga =
1809                        sb_corereg(sbh, si->sb.buscoreidx,
1810                               SBIMERRLOGA, 0, 0);
1811                    /* clear errlog */
1812                    sb_corereg(sbh, si->sb.buscoreidx,
1813                           SBIMERRLOG, ~0, 0);
1814                    SB_ERROR(("sb_taclear: ImErrLog 0x%x, ImErrLogA 0x%x\n", imerrlog, imerrloga));
1815                }
1816            }
1817        }
1818
1819    } else if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) {
1820
1821        INTR_OFF(si, intr_val);
1822        origidx = sb_coreidx(sbh);
1823
1824        corereg = sb_setcore(sbh, SB_PCMCIA, 0);
1825        if (NULL != corereg) {
1826            sb = REGS2SB(corereg);
1827
1828            imstate = R_SBREG(si, &sb->sbimstate);
1829            /* handle surprise removal */
1830            if ((imstate != 0xffffffff)
1831                && (imstate & (SBIM_IBE | SBIM_TO))) {
1832                AND_SBREG(si, &sb->sbimstate,
1833                      ~(SBIM_IBE | SBIM_TO));
1834                inband = imstate & SBIM_IBE;
1835                timeout = imstate & SBIM_TO;
1836            }
1837            tmstate = R_SBREG(si, &sb->sbtmstatehigh);
1838            if ((tmstate != 0xffffffff)
1839                && (tmstate & SBTMH_INT_STATUS)) {
1840                if (!inband) {
1841                    serror = 1;
1842                    sb_serr_clear(si);
1843                }
1844                OR_SBREG(si, &sb->sbtmstatelow, SBTML_INT_ACK);
1845                AND_SBREG(si, &sb->sbtmstatelow,
1846                      ~SBTML_INT_ACK);
1847            }
1848        }
1849        sb_setcoreidx(sbh, origidx);
1850        INTR_RESTORE(si, intr_val);
1851
1852    }
1853
1854    if (inband | timeout | serror) {
1855        rc = TRUE;
1856        SB_ERROR(("sb_taclear: inband 0x%x, serror 0x%x, timeout 0x%x!\n", inband, serror, timeout));
1857    }
1858
1859    return (rc);
1860}
1861#endif /* BCMDBG */
1862
1863/* do buffered registers update */
1864void sb_commit(sb_t * sbh)
1865{
1866    sb_info_t *si;
1867    uint origidx;
1868    uint intr_val = 0;
1869
1870    si = SB_INFO(sbh);
1871
1872    origidx = si->curidx;
1873    ASSERT(GOODIDX(origidx));
1874
1875    INTR_OFF(si, intr_val);
1876
1877    /* switch over to chipcommon core if there is one, else use pci */
1878    if (si->sb.ccrev != NOREV) {
1879        chipcregs_t *ccregs = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0);
1880
1881        /* do the buffer registers update */
1882        W_REG(si->osh, &ccregs->broadcastaddress, SB_COMMIT);
1883        W_REG(si->osh, &ccregs->broadcastdata, 0x0);
1884    } else if (PCI(si)) {
1885        sbpciregs_t *pciregs =
1886            (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0);
1887
1888        /* do the buffer registers update */
1889        W_REG(si->osh, &pciregs->bcastaddr, SB_COMMIT);
1890        W_REG(si->osh, &pciregs->bcastdata, 0x0);
1891    } else
1892        ASSERT(0);
1893
1894    /* restore core index */
1895    sb_setcoreidx(sbh, origidx);
1896    INTR_RESTORE(si, intr_val);
1897}
1898
1899/* reset and re-enable a core
1900 * inputs:
1901 * bits - core specific bits that are set during and after reset sequence
1902 * resetbits - core specific bits that are set only during reset sequence
1903 */
1904void sb_core_reset(sb_t * sbh, uint32 bits, uint32 resetbits)
1905{
1906    sb_info_t *si;
1907    sbconfig_t *sb;
1908    volatile uint32 dummy;
1909
1910    si = SB_INFO(sbh);
1911    ASSERT(GOODREGS(si->curmap));
1912    sb = REGS2SB(si->curmap);
1913
1914    /*
1915     * Must do the disable sequence first to work for arbitrary current core state.
1916     */
1917    sb_core_disable(sbh, (bits | resetbits));
1918
1919    /*
1920     * Now do the initialization sequence.
1921     */
1922
1923    /* set reset while enabling the clock and forcing them on throughout the core */
1924    W_SBREG(si, &sb->sbtmstatelow,
1925        (SBTML_FGC | SBTML_CLK | SBTML_RESET | bits | resetbits));
1926    dummy = R_SBREG(si, &sb->sbtmstatelow);
1927    OSL_DELAY(1);
1928
1929    if (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_SERR) {
1930        W_SBREG(si, &sb->sbtmstatehigh, 0);
1931    }
1932    if ((dummy = R_SBREG(si, &sb->sbimstate)) & (SBIM_IBE | SBIM_TO)) {
1933        AND_SBREG(si, &sb->sbimstate, ~(SBIM_IBE | SBIM_TO));
1934    }
1935
1936    /* clear reset and allow it to propagate throughout the core */
1937    W_SBREG(si, &sb->sbtmstatelow, (SBTML_FGC | SBTML_CLK | bits));
1938    dummy = R_SBREG(si, &sb->sbtmstatelow);
1939    OSL_DELAY(1);
1940
1941    /* leave clock enabled */
1942    W_SBREG(si, &sb->sbtmstatelow, (SBTML_CLK | bits));
1943    dummy = R_SBREG(si, &sb->sbtmstatelow);
1944    OSL_DELAY(1);
1945}
1946
1947void sb_core_tofixup(sb_t * sbh)
1948{
1949    sb_info_t *si;
1950    sbconfig_t *sb;
1951
1952    si = SB_INFO(sbh);
1953
1954    if ((BUSTYPE(si->sb.bustype) != PCI_BUS) || PCIE(si) ||
1955        (PCI(si) && (si->sb.buscorerev >= 5)))
1956        return;
1957
1958    ASSERT(GOODREGS(si->curmap));
1959    sb = REGS2SB(si->curmap);
1960
1961    if (BUSTYPE(si->sb.bustype) == SB_BUS) {
1962        SET_SBREG(si, &sb->sbimconfiglow,
1963              SBIMCL_RTO_MASK | SBIMCL_STO_MASK,
1964              (0x5 << SBIMCL_RTO_SHIFT) | 0x3);
1965    } else {
1966        if (sb_coreid(sbh) == SB_PCI) {
1967            SET_SBREG(si, &sb->sbimconfiglow,
1968                  SBIMCL_RTO_MASK | SBIMCL_STO_MASK,
1969                  (0x3 << SBIMCL_RTO_SHIFT) | 0x2);
1970        } else {
1971            SET_SBREG(si, &sb->sbimconfiglow,
1972                  (SBIMCL_RTO_MASK | SBIMCL_STO_MASK), 0);
1973        }
1974    }
1975
1976    sb_commit(sbh);
1977}
1978
1979/*
1980 * Set the initiator timeout for the "master core".
1981 * The master core is defined to be the core in control
1982 * of the chip and so it issues accesses to non-memory
1983 * locations (Because of dma *any* core can access memeory).
1984 *
1985 * The routine uses the bus to decide who is the master:
1986 * SB_BUS => mips
1987 * JTAG_BUS => chipc
1988 * PCI_BUS => pci or pcie
1989 * PCMCIA_BUS => pcmcia
1990 * SDIO_BUS => pcmcia
1991 *
1992 * This routine exists so callers can disable initiator
1993 * timeouts so accesses to very slow devices like otp
1994 * won't cause an abort. The routine allows arbitrary
1995 * settings of the service and request timeouts, though.
1996 *
1997 * Returns the timeout state before changing it or -1
1998 * on error.
1999 */
2000
2001#define TO_MASK (SBIMCL_RTO_MASK | SBIMCL_STO_MASK)
2002
2003uint32 sb_set_initiator_to(sb_t * sbh, uint32 to, uint idx)
2004{
2005    sb_info_t *si;
2006    uint origidx;
2007    uint intr_val = 0;
2008    uint32 tmp, ret = 0xffffffff;
2009    sbconfig_t *sb;
2010
2011    si = SB_INFO(sbh);
2012
2013    if ((to & ~TO_MASK) != 0)
2014        return ret;
2015
2016    /* Figure out the master core */
2017    if (idx == BADIDX) {
2018        switch (BUSTYPE(si->sb.bustype)) {
2019        case PCI_BUS:
2020            idx = si->sb.buscoreidx;
2021            break;
2022        case JTAG_BUS:
2023            idx = SB_CC_IDX;
2024            break;
2025        case PCMCIA_BUS:
2026        case SDIO_BUS:
2027            idx = sb_findcoreidx(sbh, SB_PCMCIA, 0);
2028            break;
2029        case SB_BUS:
2030            if ((idx = sb_findcoreidx(sbh, SB_MIPS33, 0)) == BADIDX)
2031                idx = sb_findcoreidx(sbh, SB_MIPS, 0);
2032            break;
2033        default:
2034            ASSERT(0);
2035        }
2036        if (idx == BADIDX)
2037            return ret;
2038    }
2039
2040    INTR_OFF(si, intr_val);
2041    origidx = sb_coreidx(sbh);
2042
2043    sb = REGS2SB(sb_setcoreidx(sbh, idx));
2044
2045    tmp = R_SBREG(si, &sb->sbimconfiglow);
2046    ret = tmp & TO_MASK;
2047    W_SBREG(si, &sb->sbimconfiglow, (tmp & ~TO_MASK) | to);
2048
2049    sb_commit(sbh);
2050    sb_setcoreidx(sbh, origidx);
2051    INTR_RESTORE(si, intr_val);
2052    return ret;
2053}
2054
2055void sb_core_disable(sb_t * sbh, uint32 bits)
2056{
2057    sb_info_t *si;
2058    volatile uint32 dummy;
2059    uint32 rej;
2060    sbconfig_t *sb;
2061
2062    si = SB_INFO(sbh);
2063
2064    ASSERT(GOODREGS(si->curmap));
2065    sb = REGS2SB(si->curmap);
2066
2067    /* if core is already in reset, just return */
2068    if (R_SBREG(si, &sb->sbtmstatelow) & SBTML_RESET)
2069        return;
2070
2071    /* reject value changed between sonics 2.2 and 2.3 */
2072    if (si->sb.sonicsrev == SONICS_2_2)
2073        rej = (1 << SBTML_REJ_SHIFT);
2074    else
2075        rej = (2 << SBTML_REJ_SHIFT);
2076
2077    /* if clocks are not enabled, put into reset and return */
2078    if ((R_SBREG(si, &sb->sbtmstatelow) & SBTML_CLK) == 0)
2079        goto disable;
2080
2081    /* set target reject and spin until busy is clear (preserve core-specific bits) */
2082    OR_SBREG(si, &sb->sbtmstatelow, rej);
2083    dummy = R_SBREG(si, &sb->sbtmstatelow);
2084    OSL_DELAY(1);
2085    SPINWAIT((R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BUSY), 100000);
2086    if (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BUSY)
2087        SB_ERROR(("%s: target state still busy\n", __FUNCTION__));
2088
2089    if (R_SBREG(si, &sb->sbidlow) & SBIDL_INIT) {
2090        OR_SBREG(si, &sb->sbimstate, SBIM_RJ);
2091        dummy = R_SBREG(si, &sb->sbimstate);
2092        OSL_DELAY(1);
2093        SPINWAIT((R_SBREG(si, &sb->sbimstate) & SBIM_BY), 100000);
2094    }
2095
2096    /* set reset and reject while enabling the clocks */
2097    W_SBREG(si, &sb->sbtmstatelow,
2098        (bits | SBTML_FGC | SBTML_CLK | rej | SBTML_RESET));
2099    dummy = R_SBREG(si, &sb->sbtmstatelow);
2100    OSL_DELAY(10);
2101
2102    /* don't forget to clear the initiator reject bit */
2103    if (R_SBREG(si, &sb->sbidlow) & SBIDL_INIT)
2104        AND_SBREG(si, &sb->sbimstate, ~SBIM_RJ);
2105
2106      disable:
2107    /* leave reset and reject asserted */
2108    W_SBREG(si, &sb->sbtmstatelow, (bits | rej | SBTML_RESET));
2109    OSL_DELAY(1);
2110}
2111
2112/* set chip watchdog reset timer to fire in 'ticks' backplane cycles */
2113void sb_watchdog(sb_t * sbh, uint ticks)
2114{
2115    sb_info_t *si = SB_INFO(sbh);
2116
2117    /* make sure we come up in fast clock mode; or if clearing, clear clock */
2118    if (ticks)
2119        sb_clkctl_clk(sbh, CLK_FAST);
2120    else
2121        sb_clkctl_clk(sbh, CLK_DYNAMIC);
2122
2123    if (sbh->chip == BCM4328_CHIP_ID && ticks != 0)
2124        sb_corereg(sbh, SB_CC_IDX, OFFSETOF(chipcregs_t, min_res_mask),
2125               PMURES_BIT(RES4328_ROM_SWITCH),
2126               PMURES_BIT(RES4328_ROM_SWITCH));
2127
2128    /* instant NMI */
2129    switch (si->gpioid) {
2130    case SB_CC:
2131        sb_corereg(sbh, SB_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0,
2132               ticks);
2133        break;
2134    case SB_EXTIF:
2135        sb_corereg(sbh, si->gpioidx, OFFSETOF(extifregs_t, watchdog),
2136               ~0, ticks);
2137        break;
2138    }
2139}
2140
2141/* initialize the pcmcia core */
2142void sb_pcmcia_init(sb_t * sbh)
2143{
2144    sb_info_t *si;
2145    uint8 cor = 0;
2146
2147    si = SB_INFO(sbh);
2148
2149    /* enable d11 mac interrupts */
2150    OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1);
2151    cor |= COR_IRQEN | COR_FUNEN;
2152    OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1);
2153
2154}
2155
2156void BCMINITFN(sb_pci_up) (sb_t * sbh) {
2157    sb_info_t *si = SB_INFO(sbh);
2158    if (si->gpioid == SB_EXTIF)
2159        return;
2160
2161    /* if not pci bus, we're done */
2162    if (BUSTYPE(si->sb.bustype) != PCI_BUS)
2163        return;
2164
2165    if (FORCEHT_WAR32414(si))
2166        sb_war32414_forceHT(sbh, 1);
2167
2168    if (PCIE_ASPMWARS(si) || si->sb.pr42780)
2169        sb_pcieclkreq(sbh, 1, 0);
2170
2171    if (PCIE(si) &&
2172        (((si->sb.chip == BCM4311_CHIP_ID) && (si->sb.chiprev == 2)) ||
2173         ((si->sb.chip == BCM4312_CHIP_ID) && (si->sb.chiprev == 0))))
2174        sb_set_initiator_to((void *)si, 0x3,
2175                    sb_findcoreidx((void *)si, SB_D11, 0));
2176}
2177
2178/* Unconfigure and/or apply various WARs when system is going to sleep mode */
2179void BCMUNINITFN(sb_pci_sleep) (sb_t * sbh) {
2180    sb_info_t *si = SB_INFO(sbh);
2181    if (si->gpioid == SB_EXTIF)
2182        return;
2183    uint32 w;
2184
2185    /* if not pci bus, we're done */
2186    if (!PCIE(si) || !PCIE_ASPMWARS(si))
2187        return;
2188
2189    w = OSL_PCI_READ_CONFIG(si->osh, si->pciecap_lcreg_offset,
2190                sizeof(uint32));
2191    w &= ~PCIE_CAP_LCREG_ASPML1;
2192    OSL_PCI_WRITE_CONFIG(si->osh, si->pciecap_lcreg_offset, sizeof(uint32),
2193                 w);
2194}
2195
2196/* Unconfigure and/or apply various WARs when going down */
2197void BCMINITFN(sb_pci_down) (sb_t * sbh) {
2198    sb_info_t *si = SB_INFO(sbh);
2199    if (si->gpioid == SB_EXTIF)
2200        return;
2201
2202    /* if not pci bus, we're done */
2203    if (BUSTYPE(si->sb.bustype) != PCI_BUS)
2204        return;
2205
2206    if (FORCEHT_WAR32414(si))
2207        sb_war32414_forceHT(sbh, 0);
2208
2209    if (si->pr42767_war) {
2210        sb_pcieclkreq(sbh, 1, 1);
2211        si->pr42767_war = FALSE;
2212    } else if (si->sb.pr42780) {
2213        sb_pcieclkreq(sbh, 1, 1);
2214    }
2215}
2216
2217static void BCMINITFN(sb_war42767_clkreq) (sb_t * sbh) {
2218    sbpcieregs_t *pcieregs;
2219    uint16 val16, *reg16;
2220    sb_info_t *si;
2221
2222    si = SB_INFO(sbh);
2223
2224    /* if not pcie bus, we're done */
2225    if (!PCIE(si) || !PCIE_ASPMWARS(si))
2226        return;
2227
2228    pcieregs = (sbpcieregs_t *) sb_setcoreidx(sbh, si->sb.buscoreidx);
2229    reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET];
2230    val16 = R_REG(si->osh, reg16);
2231    /* if clockreq is not advertized advertize it */
2232    if (!si->pcie_war_ovr) {
2233        val16 |= SRSH_CLKREQ_ENB;
2234        si->pr42767_war = TRUE;
2235
2236        si->sb.pr42780 = TRUE;
2237    } else
2238        val16 &= ~SRSH_CLKREQ_ENB;
2239    W_REG(si->osh, reg16, val16);
2240}
2241
2242static void BCMINITFN(sb_war42767) (sb_t * sbh) {
2243    uint32 w = 0;
2244    sb_info_t *si;
2245
2246    si = SB_INFO(sbh);
2247
2248    /* if not pcie bus, we're done */
2249    if (!PCIE(si) || !PCIE_ASPMWARS(si))
2250        return;
2251
2252    sb_pcie_mdioread(si, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w);
2253    if (w & PLL_CTRL_FREQDET_EN) {
2254        w &= ~PLL_CTRL_FREQDET_EN;
2255        sb_pcie_mdiowrite(si, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w);
2256    }
2257}
2258
2259/*
2260 * Configure the pci core for pci client (NIC) action
2261 * coremask is the bitvec of cores by index to be enabled.
2262 */
2263void BCMINITFN(sb_pci_setup) (sb_t * sbh, uint coremask) {
2264    sb_info_t *si;
2265    sbconfig_t *sb;
2266    sbpciregs_t *pciregs;
2267    uint32 sbflag;
2268    uint32 w;
2269    uint idx;
2270
2271    si = SB_INFO(sbh);
2272
2273    /* if not pci bus, we're done */
2274    if (BUSTYPE(si->sb.bustype) != PCI_BUS)
2275        return;
2276
2277    ASSERT(PCI(si) || PCIE(si));
2278    ASSERT(si->sb.buscoreidx != BADIDX);
2279
2280    /* get current core index */
2281    idx = si->curidx;
2282
2283    /* we interrupt on this backplane flag number */
2284    ASSERT(GOODREGS(si->curmap));
2285    sb = REGS2SB(si->curmap);
2286    sbflag = R_SBREG(si, &sb->sbtpsflag) & SBTPS_NUM0_MASK;
2287
2288    /* switch over to pci core */
2289    pciregs = (sbpciregs_t *) sb_setcoreidx(sbh, si->sb.buscoreidx);
2290    sb = REGS2SB(pciregs);
2291
2292    /*
2293     * Enable sb->pci interrupts. Assume
2294     * PCI rev 2.3 support was added in pci core rev 6 and things changed..
2295     */
2296    if (PCIE(si) || (PCI(si) && ((si->sb.buscorerev) >= 6))) {
2297        /* pci config write to set this core bit in PCIIntMask */
2298        w = OSL_PCI_READ_CONFIG(si->osh, PCI_INT_MASK, sizeof(uint32));
2299        w |= (coremask << PCI_SBIM_SHIFT);
2300        OSL_PCI_WRITE_CONFIG(si->osh, PCI_INT_MASK, sizeof(uint32), w);
2301    } else {
2302        /* set sbintvec bit for our flag number */
2303        OR_SBREG(si, &sb->sbintvec, (1 << sbflag));
2304    }
2305
2306    if (PCI(si)) {
2307        OR_REG(si->osh, &pciregs->sbtopci2,
2308               (SBTOPCI_PREF | SBTOPCI_BURST));
2309        if (si->sb.buscorerev >= 11)
2310            OR_REG(si->osh, &pciregs->sbtopci2,
2311                   SBTOPCI_RC_READMULTI);
2312        if (si->sb.buscorerev < 5) {
2313            SET_SBREG(si, &sb->sbimconfiglow,
2314                  SBIMCL_RTO_MASK | SBIMCL_STO_MASK,
2315                  (0x3 << SBIMCL_RTO_SHIFT) | 0x2);
2316            sb_commit(sbh);
2317        }
2318    }
2319
2320    /* PCIE workarounds */
2321    if (PCIE(si)) {
2322        if ((si->sb.buscorerev == 0) || (si->sb.buscorerev == 1)) {
2323            w = sb_pcie_readreg((void *)(uintptr) sbh,
2324                        (void *)(uintptr) PCIE_PCIEREGS,
2325                        PCIE_TLP_WORKAROUNDSREG);
2326            w |= 0x8;
2327            sb_pcie_writereg((void *)(uintptr) sbh,
2328                     (void *)(uintptr) PCIE_PCIEREGS,
2329                     PCIE_TLP_WORKAROUNDSREG, w);
2330        }
2331
2332        if (si->sb.buscorerev == 1) {
2333            w = sb_pcie_readreg((void *)(uintptr) sbh,
2334                        (void *)(uintptr) PCIE_PCIEREGS,
2335                        PCIE_DLLP_LCREG);
2336            w |= (0x40);
2337            sb_pcie_writereg((void *)(uintptr) sbh,
2338                     (void *)(uintptr) PCIE_PCIEREGS,
2339                     PCIE_DLLP_LCREG, w);
2340        }
2341
2342        if (si->sb.buscorerev == 0)
2343            sb_war30841(si);
2344
2345        if ((si->sb.buscorerev >= 3) && (si->sb.buscorerev <= 5)) {
2346            w = sb_pcie_readreg((void *)(uintptr) sbh,
2347                        (void *)(uintptr) PCIE_PCIEREGS,
2348                        PCIE_DLLP_PMTHRESHREG);
2349            w &= ~(PCIE_L1THRESHOLDTIME_MASK);
2350            w |= (PCIE_L1THRESHOLD_WARVAL <<
2351                  PCIE_L1THRESHOLDTIME_SHIFT);
2352            sb_pcie_writereg((void *)(uintptr) sbh,
2353                     (void *)(uintptr) PCIE_PCIEREGS,
2354                     PCIE_DLLP_PMTHRESHREG, w);
2355
2356            sb_war43448(sbh);
2357
2358            sb_war42767(sbh);
2359
2360            sb_war43448_aspm(sbh);
2361            sb_war42767_clkreq(sbh);
2362        }
2363    }
2364
2365    /* switch back to previous core */
2366    sb_setcoreidx(sbh, idx);
2367}
2368
2369uint32 sb_base(uint32 admatch)
2370{
2371    uint32 base;
2372    uint type;
2373
2374    type = admatch & SBAM_TYPE_MASK;
2375    ASSERT(type < 3);
2376
2377    base = 0;
2378
2379    if (type == 0) {
2380        base = admatch & SBAM_BASE0_MASK;
2381    } else if (type == 1) {
2382        ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
2383        base = admatch & SBAM_BASE1_MASK;
2384    } else if (type == 2) {
2385        ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
2386        base = admatch & SBAM_BASE2_MASK;
2387    }
2388
2389    return (base);
2390}
2391
2392uint32 sb_size(uint32 admatch)
2393{
2394    uint32 size;
2395    uint type;
2396
2397    type = admatch & SBAM_TYPE_MASK;
2398    ASSERT(type < 3);
2399
2400    size = 0;
2401
2402    if (type == 0) {
2403        size =
2404            1 << (((admatch & SBAM_ADINT0_MASK) >> SBAM_ADINT0_SHIFT) +
2405              1);
2406    } else if (type == 1) {
2407        ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
2408        size =
2409            1 << (((admatch & SBAM_ADINT1_MASK) >> SBAM_ADINT1_SHIFT) +
2410              1);
2411    } else if (type == 2) {
2412        ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
2413        size =
2414            1 << (((admatch & SBAM_ADINT2_MASK) >> SBAM_ADINT2_SHIFT) +
2415              1);
2416    }
2417
2418    return (size);
2419}
2420
2421/* return the core-type instantiation # of the current core */
2422uint sb_coreunit(sb_t * sbh)
2423{
2424    sb_info_t *si;
2425    uint idx;
2426    uint coreid;
2427    uint coreunit;
2428    uint i;
2429
2430    si = SB_INFO(sbh);
2431    coreunit = 0;
2432
2433    idx = si->curidx;
2434
2435    ASSERT(GOODREGS(si->curmap));
2436    coreid = sb_coreid(sbh);
2437
2438    /* count the cores of our type */
2439    for (i = 0; i < idx; i++)
2440        if (si->coreid[i] == coreid)
2441            coreunit++;
2442
2443    return (coreunit);
2444}
2445
2446static uint32 BCMINITFN(factor6) (uint32 x) {
2447    switch (x) {
2448    case CC_F6_2:
2449        return 2;
2450    case CC_F6_3:
2451        return 3;
2452    case CC_F6_4:
2453        return 4;
2454    case CC_F6_5:
2455        return 5;
2456    case CC_F6_6:
2457        return 6;
2458    case CC_F6_7:
2459        return 7;
2460    default:
2461        return 0;
2462    }
2463}
2464
2465/* calculate the speed the SB would run at given a set of clockcontrol values */
2466uint32 BCMINITFN(sb_clock_rate) (uint32 pll_type, uint32 n, uint32 m) {
2467    uint32 n1, n2, clock, m1, m2, m3, mc;
2468
2469    n1 = n & CN_N1_MASK;
2470    n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
2471
2472    if (pll_type == PLL_TYPE6) {
2473        if (m & CC_T6_MMASK)
2474            return CC_T6_M1;
2475        else
2476            return CC_T6_M0;
2477    } else if ((pll_type == PLL_TYPE1) ||
2478           (pll_type == PLL_TYPE3) ||
2479           (pll_type == PLL_TYPE4) || (pll_type == PLL_TYPE7)) {
2480        n1 = factor6(n1);
2481        n2 += CC_F5_BIAS;
2482    } else if (pll_type == PLL_TYPE2) {
2483        n1 += CC_T2_BIAS;
2484        n2 += CC_T2_BIAS;
2485        ASSERT((n1 >= 2) && (n1 <= 7));
2486        ASSERT((n2 >= 5) && (n2 <= 23));
2487    } else if (pll_type == PLL_TYPE5) {
2488        return (100000000);
2489    } else
2490        ASSERT(0);
2491    /* PLL types 3 and 7 use BASE2 (25Mhz) */
2492    if ((pll_type == PLL_TYPE3) || (pll_type == PLL_TYPE7)) {
2493        clock = CC_CLOCK_BASE2 * n1 * n2;
2494    } else
2495        clock = CC_CLOCK_BASE1 * n1 * n2;
2496
2497    if (clock == 0)
2498        return 0;
2499
2500    m1 = m & CC_M1_MASK;
2501    m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
2502    m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
2503    mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
2504
2505    if ((pll_type == PLL_TYPE1) ||
2506        (pll_type == PLL_TYPE3) ||
2507        (pll_type == PLL_TYPE4) || (pll_type == PLL_TYPE7)) {
2508        m1 = factor6(m1);
2509        if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
2510            m2 += CC_F5_BIAS;
2511        else
2512            m2 = factor6(m2);
2513        m3 = factor6(m3);
2514
2515        switch (mc) {
2516        case CC_MC_BYPASS:
2517            return (clock);
2518        case CC_MC_M1:
2519            return (clock / m1);
2520        case CC_MC_M1M2:
2521            return (clock / (m1 * m2));
2522        case CC_MC_M1M2M3:
2523            return (clock / (m1 * m2 * m3));
2524        case CC_MC_M1M3:
2525            return (clock / (m1 * m3));
2526        default:
2527            return (0);
2528        }
2529    } else {
2530        ASSERT(pll_type == PLL_TYPE2);
2531
2532        m1 += CC_T2_BIAS;
2533        m2 += CC_T2M2_BIAS;
2534        m3 += CC_T2_BIAS;
2535        ASSERT((m1 >= 2) && (m1 <= 7));
2536        ASSERT((m2 >= 3) && (m2 <= 10));
2537        ASSERT((m3 >= 2) && (m3 <= 7));
2538
2539        if ((mc & CC_T2MC_M1BYP) == 0)
2540            clock /= m1;
2541        if ((mc & CC_T2MC_M2BYP) == 0)
2542            clock /= m2;
2543        if ((mc & CC_T2MC_M3BYP) == 0)
2544            clock /= m3;
2545
2546        return (clock);
2547    }
2548}
2549
2550/* returns the current speed the SB is running at */
2551uint32 BCMINITFN(sb_clock) (sb_t * sbh) {
2552    sb_info_t *si;
2553    extifregs_t *eir;
2554    chipcregs_t *cc;
2555    uint32 n, m;
2556    uint idx;
2557    uint32 cap, pll_type, rate;
2558    uint intr_val = 0;
2559
2560    si = SB_INFO(sbh);
2561    idx = si->curidx;
2562    pll_type = PLL_TYPE1;
2563
2564    INTR_OFF(si, intr_val);
2565
2566    /* switch to extif or chipc core */
2567    if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
2568        n = R_REG(si->osh, &eir->clockcontrol_n);
2569        m = R_REG(si->osh, &eir->clockcontrol_sb);
2570    } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
2571
2572        cap = R_REG(si->osh, &cc->capabilities);
2573
2574        if (cap & CC_CAP_PMU) {
2575
2576            if (sb_chip(sbh) == BCM5354_CHIP_ID) {
2577                /* 5354 has a constant sb clock of 120MHz */
2578                rate = 120000000;
2579                goto end;
2580            } else
2581            if (sb_chip(sbh) == BCM4328_CHIP_ID) {
2582                rate = 80000000;
2583                goto end;
2584            } else
2585                ASSERT(0);
2586        }
2587
2588        pll_type = cap & CC_CAP_PLL_MASK;
2589        if (pll_type == PLL_NONE) {
2590            INTR_RESTORE(si, intr_val);
2591            return 80000000;
2592        }
2593        n = R_REG(si->osh, &cc->clockcontrol_n);
2594        if (pll_type == PLL_TYPE6)
2595            m = R_REG(si->osh, &cc->clockcontrol_m3);
2596        else if (pll_type == PLL_TYPE3
2597             && !(BCMINIT(sb_chip) (sbh) == 0x5365))
2598            m = R_REG(si->osh, &cc->clockcontrol_m2);
2599        else
2600            m = R_REG(si->osh, &cc->clockcontrol_sb);
2601    } else {
2602        INTR_RESTORE(si, intr_val);
2603        return 0;
2604    }
2605
2606    /* calculate rate */
2607    if (BCMINIT(sb_chip) (sbh) == 0x5365)
2608        rate = 100000000;
2609    else {
2610        rate = sb_clock_rate(pll_type, n, m);
2611
2612        if (pll_type == PLL_TYPE3)
2613            rate = rate / 2;
2614    }
2615
2616      end:
2617    /* switch back to previous core */
2618    sb_setcoreidx(sbh, idx);
2619
2620    INTR_RESTORE(si, intr_val);
2621
2622    return rate;
2623}
2624
2625uint32 BCMINITFN(sb_alp_clock) (sb_t * sbh) {
2626    uint32 clock = ALP_CLOCK;
2627
2628    if (sbh->cccaps & CC_CAP_PMU)
2629        clock = sb_pmu_alp_clock(sbh, sb_osh(sbh));
2630
2631    return clock;
2632}
2633
2634/* change logical "focus" to the gpio core for optimized access */
2635void *sb_gpiosetcore(sb_t * sbh)
2636{
2637    sb_info_t *si;
2638
2639    si = SB_INFO(sbh);
2640
2641    return (sb_setcoreidx(sbh, si->gpioidx));
2642}
2643
2644/* mask&set gpiocontrol bits */
2645uint32 sb_gpiocontrol(sb_t * sbh, uint32 mask, uint32 val, uint8 priority)
2646{
2647    sb_info_t *si;
2648    uint regoff;
2649
2650    si = SB_INFO(sbh);
2651    regoff = 0;
2652
2653    /* gpios could be shared on router platforms
2654     * ignore reservation if it's high priority (e.g., test apps)
2655     */
2656    if ((priority != GPIO_HI_PRIORITY) &&
2657        (BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
2658        mask = priority ? (sb_gpioreservation & mask) :
2659            ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
2660        val &= mask;
2661    }
2662
2663    switch (si->gpioid) {
2664    case SB_CC:
2665        regoff = OFFSETOF(chipcregs_t, gpiocontrol);
2666        break;
2667
2668    case SB_PCI:
2669        regoff = OFFSETOF(sbpciregs_t, gpiocontrol);
2670        break;
2671
2672    case SB_EXTIF:
2673        return (0);
2674    }
2675
2676    return (sb_corereg(sbh, si->gpioidx, regoff, mask, val));
2677}
2678
2679/* mask&set gpio output enable bits */
2680uint32 sb_gpioouten(sb_t * sbh, uint32 mask, uint32 val, uint8 priority)
2681{
2682    sb_info_t *si;
2683    uint regoff;
2684
2685    si = SB_INFO(sbh);
2686    regoff = 0;
2687
2688    /* gpios could be shared on router platforms
2689     * ignore reservation if it's high priority (e.g., test apps)
2690     */
2691    if ((priority != GPIO_HI_PRIORITY) &&
2692        (BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
2693        mask = priority ? (sb_gpioreservation & mask) :
2694            ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
2695        val &= mask;
2696    }
2697
2698    switch (si->gpioid) {
2699    case SB_CC:
2700        regoff = OFFSETOF(chipcregs_t, gpioouten);
2701        break;
2702
2703    case SB_PCI:
2704        regoff = OFFSETOF(sbpciregs_t, gpioouten);
2705        break;
2706
2707    case SB_EXTIF:
2708        regoff = OFFSETOF(extifregs_t, gpio[0].outen);
2709        break;
2710    }
2711
2712    return (sb_corereg(sbh, si->gpioidx, regoff, mask, val));
2713}
2714
2715/* mask&set gpio output bits */
2716uint32 sb_gpioout(sb_t * sbh, uint32 mask, uint32 val, uint8 priority)
2717{
2718    sb_info_t *si;
2719    uint regoff;
2720
2721    si = SB_INFO(sbh);
2722    regoff = 0;
2723
2724    /* gpios could be shared on router platforms
2725     * ignore reservation if it's high priority (e.g., test apps)
2726     */
2727    if ((priority != GPIO_HI_PRIORITY) &&
2728        (BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
2729        mask = priority ? (sb_gpioreservation & mask) :
2730            ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
2731        val &= mask;
2732    }
2733
2734    switch (si->gpioid) {
2735    case SB_CC:
2736        regoff = OFFSETOF(chipcregs_t, gpioout);
2737        break;
2738
2739    case SB_PCI:
2740        regoff = OFFSETOF(sbpciregs_t, gpioout);
2741        break;
2742
2743    case SB_EXTIF:
2744        regoff = OFFSETOF(extifregs_t, gpio[0].out);
2745        break;
2746    }
2747
2748    return (sb_corereg(sbh, si->gpioidx, regoff, mask, val));
2749}
2750
2751/* reserve one gpio */
2752uint32 sb_gpioreserve(sb_t * sbh, uint32 gpio_bitmask, uint8 priority)
2753{
2754    sb_info_t *si;
2755
2756    si = SB_INFO(sbh);
2757
2758    /* only cores on SB_BUS share GPIO's and only applcation users need to
2759     * reserve/release GPIO
2760     */
2761    if ((BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) {
2762        ASSERT((BUSTYPE(si->sb.bustype) == SB_BUS) && (priority));
2763        return -1;
2764    }
2765    /* make sure only one bit is set */
2766    if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
2767        ASSERT((gpio_bitmask)
2768               && !((gpio_bitmask) & (gpio_bitmask - 1)));
2769        return -1;
2770    }
2771
2772    /* already reserved */
2773    if (sb_gpioreservation & gpio_bitmask)
2774        return -1;
2775    /* set reservation */
2776    sb_gpioreservation |= gpio_bitmask;
2777
2778    return sb_gpioreservation;
2779}
2780
2781/* release one gpio */
2782/*
2783 * releasing the gpio doesn't change the current value on the GPIO last write value
2784 * persists till some one overwrites it
2785*/
2786
2787uint32 sb_gpiorelease(sb_t * sbh, uint32 gpio_bitmask, uint8 priority)
2788{
2789    sb_info_t *si;
2790
2791    si = SB_INFO(sbh);
2792
2793    /* only cores on SB_BUS share GPIO's and only applcation users need to
2794     * reserve/release GPIO
2795     */
2796    if ((BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) {
2797        ASSERT((BUSTYPE(si->sb.bustype) == SB_BUS) && (priority));
2798        return -1;
2799    }
2800    /* make sure only one bit is set */
2801    if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
2802        ASSERT((gpio_bitmask)
2803               && !((gpio_bitmask) & (gpio_bitmask - 1)));
2804        return -1;
2805    }
2806
2807    /* already released */
2808    if (!(sb_gpioreservation & gpio_bitmask))
2809        return -1;
2810
2811    /* clear reservation */
2812    sb_gpioreservation &= ~gpio_bitmask;
2813
2814    return sb_gpioreservation;
2815}
2816
2817/* return the current gpioin register value */
2818uint32 sb_gpioin(sb_t * sbh)
2819{
2820    sb_info_t *si;
2821    uint regoff;
2822
2823    si = SB_INFO(sbh);
2824    regoff = 0;
2825
2826    switch (si->gpioid) {
2827    case SB_CC:
2828        regoff = OFFSETOF(chipcregs_t, gpioin);
2829        break;
2830
2831    case SB_PCI:
2832        regoff = OFFSETOF(sbpciregs_t, gpioin);
2833        break;
2834
2835    case SB_EXTIF:
2836        regoff = OFFSETOF(extifregs_t, gpioin);
2837        break;
2838    }
2839
2840    return (sb_corereg(sbh, si->gpioidx, regoff, 0, 0));
2841}
2842
2843/* mask&set gpio interrupt polarity bits */
2844uint32 sb_gpiointpolarity(sb_t * sbh, uint32 mask, uint32 val, uint8 priority)
2845{
2846    sb_info_t *si;
2847    uint regoff;
2848
2849    si = SB_INFO(sbh);
2850    regoff = 0;
2851
2852    /* gpios could be shared on router platforms */
2853    if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
2854        mask = priority ? (sb_gpioreservation & mask) :
2855            ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
2856        val &= mask;
2857    }
2858
2859    switch (si->gpioid) {
2860    case SB_CC:
2861        regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
2862        break;
2863
2864    case SB_PCI:
2865        /* pci gpio implementation does not support interrupt polarity */
2866        ASSERT(0);
2867        break;
2868
2869    case SB_EXTIF:
2870        regoff = OFFSETOF(extifregs_t, gpiointpolarity);
2871        break;
2872    }
2873
2874    return (sb_corereg(sbh, si->gpioidx, regoff, mask, val));
2875}
2876
2877/* mask&set gpio interrupt mask bits */
2878uint32 sb_gpiointmask(sb_t * sbh, uint32 mask, uint32 val, uint8 priority)
2879{
2880    sb_info_t *si;
2881    uint regoff;
2882
2883    si = SB_INFO(sbh);
2884    regoff = 0;
2885
2886    /* gpios could be shared on router platforms */
2887    if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
2888        mask = priority ? (sb_gpioreservation & mask) :
2889            ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
2890        val &= mask;
2891    }
2892
2893    switch (si->gpioid) {
2894    case SB_CC:
2895        regoff = OFFSETOF(chipcregs_t, gpiointmask);
2896        break;
2897
2898    case SB_PCI:
2899        /* pci gpio implementation does not support interrupt mask */
2900        ASSERT(0);
2901        break;
2902
2903    case SB_EXTIF:
2904        regoff = OFFSETOF(extifregs_t, gpiointmask);
2905        break;
2906    }
2907
2908    return (sb_corereg(sbh, si->gpioidx, regoff, mask, val));
2909}
2910
2911/* assign the gpio to an led */
2912uint32 sb_gpioled(sb_t * sbh, uint32 mask, uint32 val)
2913{
2914    sb_info_t *si;
2915
2916    si = SB_INFO(sbh);
2917    if (si->sb.ccrev < 16)
2918        return -1;
2919
2920    /* gpio led powersave reg */
2921    return (sb_corereg
2922        (sbh, SB_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask,
2923         val));
2924}
2925
2926/* mask&set gpio timer val */
2927uint32 sb_gpiotimerval(sb_t * sbh, uint32 mask, uint32 gpiotimerval)
2928{
2929    sb_info_t *si;
2930    si = SB_INFO(sbh);
2931
2932    if (si->sb.ccrev < 16)
2933        return -1;
2934
2935    return (sb_corereg(sbh, SB_CC_IDX,
2936               OFFSETOF(chipcregs_t, gpiotimerval), mask,
2937               gpiotimerval));
2938}
2939
2940uint32 sb_gpiopull(sb_t * sbh, bool updown, uint32 mask, uint32 val)
2941{
2942    sb_info_t *si;
2943    uint offs;
2944
2945    si = SB_INFO(sbh);
2946    if (si->sb.ccrev < 20)
2947        return -1;
2948
2949    offs =
2950        (updown ? OFFSETOF(chipcregs_t, gpiopulldown) :
2951         OFFSETOF(chipcregs_t, gpiopullup));
2952    return (sb_corereg(sbh, SB_CC_IDX, offs, mask, val));
2953}
2954
2955uint32 sb_gpioevent(sb_t * sbh, uint regtype, uint32 mask, uint32 val)
2956{
2957    sb_info_t *si;
2958    uint offs;
2959
2960    si = SB_INFO(sbh);
2961    if (si->sb.ccrev < 11)
2962        return -1;
2963
2964    if (regtype == GPIO_REGEVT)
2965        offs = OFFSETOF(chipcregs_t, gpioevent);
2966    else if (regtype == GPIO_REGEVT_INTMSK)
2967        offs = OFFSETOF(chipcregs_t, gpioeventintmask);
2968    else if (regtype == GPIO_REGEVT_INTPOL)
2969        offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
2970    else
2971        return -1;
2972
2973    return (sb_corereg(sbh, SB_CC_IDX, offs, mask, val));
2974}
2975
2976void *BCMINITFN(sb_gpio_handler_register) (sb_t * sbh, uint32 event,
2977                       bool level, gpio_handler_t cb,
2978                       void *arg) {
2979    sb_info_t *si;
2980    gpioh_item_t *gi;
2981
2982    ASSERT(event);
2983    ASSERT(cb);
2984
2985    si = SB_INFO(sbh);
2986    if (si->sb.ccrev < 11)
2987        return NULL;
2988
2989    if ((gi = MALLOC(si->osh, sizeof(gpioh_item_t))) == NULL)
2990        return NULL;
2991
2992    bzero(gi, sizeof(gpioh_item_t));
2993    gi->event = event;
2994    gi->handler = cb;
2995    gi->arg = arg;
2996    gi->level = level;
2997
2998    gi->next = si->gpioh_head;
2999    si->gpioh_head = gi;
3000
3001    return (void *)(gi);
3002}
3003
3004void BCMINITFN(sb_gpio_handler_unregister) (sb_t * sbh, void *gpioh) {
3005    sb_info_t *si;
3006    gpioh_item_t *p, *n;
3007
3008    si = SB_INFO(sbh);
3009    if (si->sb.ccrev < 11)
3010        return;
3011
3012    ASSERT(si->gpioh_head);
3013    if ((void *)si->gpioh_head == gpioh) {
3014        si->gpioh_head = si->gpioh_head->next;
3015        MFREE(si->osh, gpioh, sizeof(gpioh_item_t));
3016        return;
3017    } else {
3018        p = si->gpioh_head;
3019        n = p->next;
3020        while (n) {
3021            if ((void *)n == gpioh) {
3022                p->next = n->next;
3023                MFREE(si->osh, gpioh, sizeof(gpioh_item_t));
3024                return;
3025            }
3026            p = n;
3027            n = n->next;
3028        }
3029    }
3030
3031    ASSERT(0); /* Not found in list */
3032}
3033
3034void sb_gpio_handler_process(sb_t * sbh)
3035{
3036    sb_info_t *si;
3037    gpioh_item_t *h;
3038    uint32 status;
3039    uint32 level = sb_gpioin(sbh);
3040    uint32 edge = sb_gpioevent(sbh, GPIO_REGEVT, 0, 0);
3041
3042    si = SB_INFO(sbh);
3043    for (h = si->gpioh_head; h != NULL; h = h->next) {
3044        if (h->handler) {
3045            status = (h->level ? level : edge);
3046
3047            if (status & h->event)
3048                h->handler(status, h->arg);
3049        }
3050    }
3051
3052    sb_gpioevent(sbh, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */
3053}
3054
3055uint32 sb_gpio_int_enable(sb_t * sbh, bool enable)
3056{
3057    sb_info_t *si;
3058    uint offs;
3059
3060    si = SB_INFO(sbh);
3061    if (si->sb.ccrev < 11)
3062        return -1;
3063
3064    offs = OFFSETOF(chipcregs_t, intmask);
3065    return (sb_corereg
3066        (sbh, SB_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
3067}
3068
3069#ifdef BCMDBG
3070void sb_dump(sb_t * sbh, struct bcmstrbuf *b)
3071{
3072    sb_info_t *si;
3073    uint i;
3074
3075    si = SB_INFO(sbh);
3076
3077    bcm_bprintf(b,
3078            "si %p chip 0x%x chiprev 0x%x boardtype 0x%x boardvendor 0x%x bus %d\n",
3079            si, si->sb.chip, si->sb.chiprev, si->sb.boardtype,
3080            si->sb.boardvendor, si->sb.bustype);
3081    bcm_bprintf(b, "osh %p curmap %p\n", si->osh, si->curmap);
3082    bcm_bprintf(b,
3083            "sonicsrev %d ccrev %d buscoretype 0x%x buscorerev %d curidx %d\n",
3084            si->sb.sonicsrev, si->sb.ccrev, si->sb.buscoretype,
3085            si->sb.buscorerev, si->curidx);
3086
3087    bcm_bprintf(b, "forceHT %d ASPM overflowPR42780 %d pcie_polarity %d\n",
3088            si->sb.pr32414, si->sb.pr42780, si->pcie_polarity);
3089
3090    bcm_bprintf(b, "cores: ");
3091    for (i = 0; i < si->numcores; i++)
3092        bcm_bprintf(b, "0x%x ", si->coreid[i]);
3093    bcm_bprintf(b, "\n");
3094}
3095
3096/* print interesting sbconfig registers */
3097void sb_dumpregs(sb_t * sbh, struct bcmstrbuf *b)
3098{
3099    sb_info_t *si;
3100    sbconfig_t *sb;
3101    uint origidx;
3102    uint curidx, i, intr_val = 0;
3103
3104    si = SB_INFO(sbh);
3105    origidx = si->curidx;
3106
3107    INTR_OFF(si, intr_val);
3108    curidx = si->curidx;
3109
3110    for (i = 0; i < si->numcores; i++) {
3111        sb = REGS2SB(sb_setcoreidx(sbh, i));
3112
3113        bcm_bprintf(b, "core 0x%x: \n", si->coreid[i]);
3114        bcm_bprintf(b,
3115                "sbtmstatelow 0x%x sbtmstatehigh 0x%x sbidhigh 0x%x "
3116                "sbimstate 0x%x\n sbimconfiglow 0x%x sbimconfighigh 0x%x\n",
3117                R_SBREG(si, &sb->sbtmstatelow), R_SBREG(si,
3118                                    &sb->
3119                                    sbtmstatehigh),
3120                R_SBREG(si, &sb->sbidhigh), R_SBREG(si,
3121                                &sb->sbimstate),
3122                R_SBREG(si, &sb->sbimconfiglow), R_SBREG(si,
3123                                     &sb->
3124                                     sbimconfighigh));
3125    }
3126
3127    sb_setcoreidx(sbh, origidx);
3128    INTR_RESTORE(si, intr_val);
3129}
3130
3131void sb_view(sb_t * sbh)
3132{
3133    sb_info_t *si;
3134    sbconfig_t *sb;
3135
3136    si = SB_INFO(sbh);
3137    sb = REGS2SB(si->curmap);
3138
3139    if (si->sb.sonicsrev > SONICS_2_2)
3140        SB_ERROR(("sbimerrlog 0x%x sbimerrloga 0x%x\n",
3141              sb_corereg(sbh, sb_coreidx(&si->sb), SBIMERRLOG, 0,
3142                     0), sb_corereg(sbh, sb_coreidx(&si->sb),
3143                            SBIMERRLOGA, 0, 0)));
3144
3145    SB_ERROR(("sbipsflag 0x%x sbtpsflag 0x%x sbtmerrloga 0x%x sbtmerrlog 0x%x\n", R_SBREG(si, &sb->sbipsflag), R_SBREG(si, &sb->sbtpsflag), R_SBREG(si, &sb->sbtmerrloga), R_SBREG(si, &sb->sbtmerrlog)));
3146    SB_ERROR(("sbadmatch3 0x%x sbadmatch2 0x%x sbadmatch1 0x%x\n",
3147          R_SBREG(si, &sb->sbadmatch3), R_SBREG(si, &sb->sbadmatch2),
3148          R_SBREG(si, &sb->sbadmatch1)));
3149    SB_ERROR(("sbimstate 0x%x sbintvec 0x%x sbtmstatelow 0x%x sbtmstatehigh 0x%x\n", R_SBREG(si, &sb->sbimstate), R_SBREG(si, &sb->sbintvec), R_SBREG(si, &sb->sbtmstatelow), R_SBREG(si, &sb->sbtmstatehigh)));
3150    SB_ERROR(("sbbwa0 0x%x sbimconfiglow 0x%x sbimconfighigh 0x%x sbadmatch0 0x%x\n", R_SBREG(si, &sb->sbbwa0), R_SBREG(si, &sb->sbimconfiglow), R_SBREG(si, &sb->sbimconfighigh), R_SBREG(si, &sb->sbadmatch0)));
3151    SB_ERROR(("sbtmconfiglow 0x%x sbtmconfighigh 0x%x sbbconfig 0x%x sbbstate 0x%x\n", R_SBREG(si, &sb->sbtmconfiglow), R_SBREG(si, &sb->sbtmconfighigh), R_SBREG(si, &sb->sbbconfig), R_SBREG(si, &sb->sbbstate)));
3152    SB_ERROR(("sbactcnfg 0x%x sbflagst 0x%x sbidlow 0x%x sbidhigh 0x%x\n",
3153          R_SBREG(si, &sb->sbactcnfg), R_SBREG(si, &sb->sbflagst),
3154          R_SBREG(si, &sb->sbidlow), R_SBREG(si, &sb->sbidhigh)));
3155}
3156
3157void sb_viewall(sb_t * sbh)
3158{
3159    sb_info_t *si;
3160    uint curidx, i;
3161    uint intr_val = 0;
3162
3163    si = SB_INFO(sbh);
3164    curidx = si->curidx;
3165
3166    for (i = 0; i < si->numcores; i++) {
3167        INTR_OFF(si, intr_val);
3168        sb_setcoreidx(sbh, i);
3169        sb_view(sbh);
3170        INTR_RESTORE(si, intr_val);
3171    }
3172
3173    sb_setcoreidx(sbh, curidx);
3174}
3175#endif /* BCMDBG */
3176
3177/* return the slow clock source - LPO, XTAL, or PCI */
3178static uint sb_slowclk_src(sb_info_t * si)
3179{
3180    chipcregs_t *cc;
3181
3182    ASSERT(sb_coreid(&si->sb) == SB_CC);
3183
3184    if (si->sb.ccrev < 6) {
3185        if ((BUSTYPE(si->sb.bustype) == PCI_BUS) &&
3186            (OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, sizeof(uint32))
3187             & PCI_CFG_GPIO_SCS))
3188            return (SCC_SS_PCI);
3189        else
3190            return (SCC_SS_XTAL);
3191    } else if (si->sb.ccrev < 10) {
3192        cc = (chipcregs_t *) sb_setcoreidx(&si->sb, si->curidx);
3193        return (R_REG(si->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
3194    } else /* Insta-clock */
3195        return (SCC_SS_XTAL);
3196}
3197
3198/* return the ILP (slowclock) min or max frequency */
3199static uint sb_slowclk_freq(sb_info_t * si, bool max_freq)
3200{
3201    chipcregs_t *cc;
3202    uint32 slowclk;
3203    uint div;
3204
3205    ASSERT(sb_coreid(&si->sb) == SB_CC);
3206
3207    cc = (chipcregs_t *) sb_setcoreidx(&si->sb, si->curidx);
3208
3209    /* shouldn't be here unless we've established the chip has dynamic clk control */
3210    ASSERT(R_REG(si->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
3211
3212    slowclk = sb_slowclk_src(si);
3213    if (si->sb.ccrev < 6) {
3214        if (slowclk == SCC_SS_PCI)
3215            return (max_freq ? (PCIMAXFREQ / 64)
3216                : (PCIMINFREQ / 64));
3217        else
3218            return (max_freq ? (XTALMAXFREQ / 32)
3219                : (XTALMINFREQ / 32));
3220    } else if (si->sb.ccrev < 10) {
3221        div =
3222            4 *
3223            (((R_REG(si->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >>
3224              SCC_CD_SHIFT)
3225             + 1);
3226        if (slowclk == SCC_SS_LPO)
3227            return (max_freq ? LPOMAXFREQ : LPOMINFREQ);
3228        else if (slowclk == SCC_SS_XTAL)
3229            return (max_freq ? (XTALMAXFREQ / div)
3230                : (XTALMINFREQ / div));
3231        else if (slowclk == SCC_SS_PCI)
3232            return (max_freq ? (PCIMAXFREQ / div)
3233                : (PCIMINFREQ / div));
3234        else
3235            ASSERT(0);
3236    } else {
3237        /* Chipc rev 10 is InstaClock */
3238        div = R_REG(si->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
3239        div = 4 * (div + 1);
3240        return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div));
3241    }
3242    return (0);
3243}
3244
3245static void BCMINITFN(sb_clkctl_setdelay) (sb_info_t * si, void *chipcregs) {
3246    chipcregs_t *cc;
3247    uint slowmaxfreq, pll_delay, slowclk;
3248    uint pll_on_delay, fref_sel_delay;
3249
3250    pll_delay = PLL_DELAY;
3251
3252    /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
3253     * since the xtal will also be powered down by dynamic clk control logic.
3254     */
3255
3256    slowclk = sb_slowclk_src(si);
3257    if (slowclk != SCC_SS_XTAL)
3258        pll_delay += XTAL_ON_DELAY;
3259
3260    /* Starting with 4318 it is ILP that is used for the delays */
3261    slowmaxfreq = sb_slowclk_freq(si, (si->sb.ccrev >= 10) ? FALSE : TRUE);
3262
3263    pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
3264    fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
3265
3266    cc = (chipcregs_t *) chipcregs;
3267    W_REG(si->osh, &cc->pll_on_delay, pll_on_delay);
3268    W_REG(si->osh, &cc->fref_sel_delay, fref_sel_delay);
3269}
3270
3271/* initialize power control delay registers */
3272void BCMINITFN(sb_clkctl_init) (sb_t * sbh) {
3273    sb_info_t *si;
3274    uint origidx;
3275    chipcregs_t *cc;
3276
3277    si = SB_INFO(sbh);
3278
3279    origidx = si->curidx;
3280
3281    if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0)) == NULL)
3282        return;
3283
3284    if ((si->sb.chip == BCM4321_CHIP_ID) && (si->sb.chiprev < 2))
3285        W_REG(si->osh, &cc->chipcontrol,
3286              (si->sb.chiprev ==
3287               0) ? CHIPCTRL_4321A0_DEFAULT : CHIPCTRL_4321A1_DEFAULT);
3288
3289    if (!(R_REG(si->osh, &cc->capabilities) & CC_CAP_PWR_CTL))
3290        goto done;
3291
3292    /* set all Instaclk chip ILP to 1 MHz */
3293    if (si->sb.ccrev >= 10)
3294        SET_REG(si->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
3295            (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
3296
3297    sb_clkctl_setdelay(si, (void *)(uintptr) cc);
3298
3299      done:
3300    sb_setcoreidx(sbh, origidx);
3301}
3302
3303/* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */
3304uint16 BCMINITFN(sb_clkctl_fast_pwrup_delay) (sb_t * sbh) {
3305    sb_info_t *si;
3306    uint origidx;
3307    chipcregs_t *cc;
3308    uint slowminfreq;
3309    uint16 fpdelay;
3310    uint intr_val = 0;
3311
3312    si = SB_INFO(sbh);
3313    fpdelay = 0;
3314    origidx = si->curidx;
3315
3316    INTR_OFF(si, intr_val);
3317
3318    if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0)) == NULL)
3319        goto done;
3320
3321    if (sbh->cccaps & CC_CAP_PMU) {
3322        fpdelay = sb_pmu_fast_pwrup_delay(sbh, si->osh);
3323        goto done;
3324    }
3325
3326    if (!(sbh->cccaps & CC_CAP_PWR_CTL))
3327        goto done;
3328
3329    slowminfreq = sb_slowclk_freq(si, FALSE);
3330    fpdelay = (((R_REG(si->osh, &cc->pll_on_delay) + 2) * 1000000) +
3331           (slowminfreq - 1)) / slowminfreq;
3332
3333      done:
3334    sb_setcoreidx(sbh, origidx);
3335    INTR_RESTORE(si, intr_val);
3336    return (fpdelay);
3337}
3338
3339/* turn primary xtal and/or pll off/on */
3340int sb_clkctl_xtal(sb_t * sbh, uint what, bool on)
3341{
3342    sb_info_t *si;
3343    uint32 in, out, outen;
3344
3345    si = SB_INFO(sbh);
3346
3347    switch (BUSTYPE(si->sb.bustype)) {
3348
3349    case PCMCIA_BUS:
3350        return (0);
3351
3352    case PCI_BUS:
3353
3354        /* pcie core doesn't have any mapping to control the xtal pu */
3355        if (PCIE(si))
3356            return -1;
3357
3358        in = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_IN, sizeof(uint32));
3359        out =
3360            OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, sizeof(uint32));
3361        outen =
3362            OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUTEN,
3363                    sizeof(uint32));
3364
3365        /*
3366         * Avoid glitching the clock if GPRS is already using it.
3367         * We can't actually read the state of the PLLPD so we infer it
3368         * by the value of XTAL_PU which *is* readable via gpioin.
3369         */
3370        if (on && (in & PCI_CFG_GPIO_XTAL))
3371            return (0);
3372
3373        if (what & XTAL)
3374            outen |= PCI_CFG_GPIO_XTAL;
3375        if (what & PLL)
3376            outen |= PCI_CFG_GPIO_PLL;
3377
3378        if (on) {
3379            /* turn primary xtal on */
3380            if (what & XTAL) {
3381                out |= PCI_CFG_GPIO_XTAL;
3382                if (what & PLL)
3383                    out |= PCI_CFG_GPIO_PLL;
3384                OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT,
3385                             sizeof(uint32), out);
3386                OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUTEN,
3387                             sizeof(uint32), outen);
3388                OSL_DELAY(XTAL_ON_DELAY);
3389            }
3390
3391            /* turn pll on */
3392            if (what & PLL) {
3393                out &= ~PCI_CFG_GPIO_PLL;
3394                OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT,
3395                             sizeof(uint32), out);
3396                OSL_DELAY(2000);
3397            }
3398        } else {
3399            if (what & XTAL)
3400                out &= ~PCI_CFG_GPIO_XTAL;
3401            if (what & PLL)
3402                out |= PCI_CFG_GPIO_PLL;
3403            OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT,
3404                         sizeof(uint32), out);
3405            OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUTEN,
3406                         sizeof(uint32), outen);
3407        }
3408
3409    default:
3410        return (-1);
3411    }
3412
3413    return (0);
3414}
3415
3416/* set dynamic clk control mode (forceslow, forcefast, dynamic) */
3417/* returns true if we are forcing fast clock */
3418bool sb_clkctl_clk(sb_t * sbh, uint mode)
3419{
3420    sb_info_t *si;
3421    uint origidx;
3422    chipcregs_t *cc;
3423    uint32 scc;
3424    uint intr_val = 0;
3425
3426    si = SB_INFO(sbh);
3427
3428    /* chipcommon cores prior to rev6 don't support dynamic clock control */
3429    if (si->sb.ccrev < 6)
3430        return (FALSE);
3431
3432    /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */
3433    ASSERT(si->sb.ccrev != 10);
3434
3435    INTR_OFF(si, intr_val);
3436
3437    origidx = si->curidx;
3438
3439    if (sb_setcore(sbh, SB_MIPS33, 0) && (sb_corerev(&si->sb) <= 7) &&
3440        (BUSTYPE(si->sb.bustype) == SB_BUS) && (si->sb.ccrev >= 10))
3441        goto done;
3442
3443    if (FORCEHT_WAR32414(si))
3444        goto done;
3445
3446    cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0);
3447    ASSERT(cc != NULL);
3448
3449    if (!(R_REG(si->osh, &cc->capabilities) & CC_CAP_PWR_CTL)
3450        && (si->sb.ccrev < 20))
3451        goto done;
3452
3453    switch (mode) {
3454    case CLK_FAST: /* force fast (pll) clock */
3455        if (si->sb.ccrev < 10) {
3456            /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
3457            sb_clkctl_xtal(&si->sb, XTAL, ON);
3458
3459            SET_REG(si->osh, &cc->slow_clk_ctl,
3460                (SCC_XC | SCC_FS | SCC_IP), SCC_IP);
3461        } else if (si->sb.ccrev < 20) {
3462            OR_REG(si->osh, &cc->system_clk_ctl, SYCC_HR);
3463        } else {
3464            OR_REG(si->osh, &cc->clk_ctl_st, CCS_FORCEHT);
3465        }
3466
3467        /* wait for the PLL */
3468        if (R_REG(si->osh, &cc->capabilities) & CC_CAP_PMU) {
3469            SPINWAIT(((R_REG(si->osh, &cc->clk_ctl_st) &
3470                   CCS_HTAVAIL) == 0), PMU_MAX_TRANSITION_DLY);
3471            ASSERT(R_REG(si->osh, &cc->clk_ctl_st) & CCS_HTAVAIL);
3472        } else {
3473            OSL_DELAY(PLL_DELAY);
3474        }
3475        break;
3476
3477    case CLK_DYNAMIC: /* enable dynamic clock control */
3478        if (si->sb.ccrev < 10) {
3479            scc = R_REG(si->osh, &cc->slow_clk_ctl);
3480            scc &= ~(SCC_FS | SCC_IP | SCC_XC);
3481            if ((scc & SCC_SS_MASK) != SCC_SS_XTAL)
3482                scc |= SCC_XC;
3483            W_REG(si->osh, &cc->slow_clk_ctl, scc);
3484
3485            /* for dynamic control, we have to release our xtal_pu "force on" */
3486            if (scc & SCC_XC)
3487                sb_clkctl_xtal(&si->sb, XTAL, OFF);
3488        } else if (si->sb.ccrev < 20) {
3489            /* Instaclock */
3490            AND_REG(si->osh, &cc->system_clk_ctl, ~SYCC_HR);
3491        } else {
3492            AND_REG(si->osh, &cc->clk_ctl_st, ~CCS_FORCEHT);
3493        }
3494        break;
3495
3496    default:
3497        ASSERT(0);
3498    }
3499
3500      done:
3501    sb_setcoreidx(sbh, origidx);
3502    INTR_RESTORE(si, intr_val);
3503    return (mode == CLK_FAST);
3504}
3505
3506/* register driver interrupt disabling and restoring callback functions */
3507void
3508sb_register_intr_callback(sb_t * sbh, void *intrsoff_fn,
3509              void *intrsrestore_fn, void *intrsenabled_fn,
3510              void *intr_arg)
3511{
3512    sb_info_t *si;
3513
3514    si = SB_INFO(sbh);
3515    si->intr_arg = intr_arg;
3516    si->intrsoff_fn = (sb_intrsoff_t) intrsoff_fn;
3517    si->intrsrestore_fn = (sb_intrsrestore_t) intrsrestore_fn;
3518    si->intrsenabled_fn = (sb_intrsenabled_t) intrsenabled_fn;
3519    /* save current core id. when this function called, the current core
3520     * must be the core which provides driver functions(il, et, wl, etc.)
3521     */
3522    si->dev_coreid = si->coreid[si->curidx];
3523}
3524
3525void sb_deregister_intr_callback(sb_t * sbh)
3526{
3527    sb_info_t *si;
3528
3529    si = SB_INFO(sbh);
3530    si->intrsoff_fn = NULL;
3531}
3532
3533#ifdef BCMDBG
3534/* dump dynamic clock control related registers */
3535void sb_clkctl_dump(sb_t * sbh, struct bcmstrbuf *b)
3536{
3537    sb_info_t *si;
3538    chipcregs_t *cc;
3539    uint origidx;
3540    uint intr_val = 0;
3541
3542    si = SB_INFO(sbh);
3543
3544    INTR_OFF(si, intr_val);
3545
3546    origidx = si->curidx;
3547
3548    if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0)) == NULL) {
3549        INTR_RESTORE(si, intr_val);
3550        return;
3551    }
3552
3553    if (!(R_REG(si->osh, &cc->capabilities) & CC_CAP_PWR_CTL))
3554        goto done;
3555
3556    bcm_bprintf(b, "pll_on_delay 0x%x fref_sel_delay 0x%x ",
3557            cc->pll_on_delay, cc->fref_sel_delay);
3558    if ((si->sb.ccrev >= 6) && (si->sb.ccrev < 10))
3559        bcm_bprintf(b, "slow_clk_ctl 0x%x ", cc->slow_clk_ctl);
3560    if (si->sb.ccrev >= 10) {
3561        bcm_bprintf(b, "system_clk_ctl 0x%x ", cc->system_clk_ctl);
3562        bcm_bprintf(b, "clkstatestretch 0x%x ", cc->clkstatestretch);
3563    }
3564    if (BUSTYPE(si->sb.bustype) == PCI_BUS)
3565        bcm_bprintf(b, "gpioout 0x%x gpioouten 0x%x ",
3566                OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT,
3567                        sizeof(uint32)),
3568                OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUTEN,
3569                        sizeof(uint32)));
3570    bcm_bprintf(b, "\n");
3571
3572      done:
3573    sb_setcoreidx(sbh, origidx);
3574    INTR_RESTORE(si, intr_val);
3575}
3576#endif /* BCMDBG */
3577
3578uint16 BCMINITFN(sb_d11_devid) (sb_t * sbh) {
3579    sb_info_t *si = SB_INFO(sbh);
3580    uint16 device;
3581
3582#if defined(BCM4328)
3583    /* Fix device id for dual band BCM4328 */
3584    if (sbh->chip == BCM4328_CHIP_ID &&
3585        (sbh->chippkg == BCM4328USBDUAL_PKG_ID
3586         || sbh->chippkg == BCM4328SDIODUAL_PKG_ID))
3587        device = BCM4328_D11DUAL_ID;
3588    else
3589#endif /* BCM4328 */
3590        /* Let an nvram variable with devpath override devid */
3591    if ((device = (uint16) sb_getdevpathintvar(sbh, "devid")) != 0) ;
3592    /* Get devid from OTP/SPROM depending on where the SROM is read */
3593    else if ((device = (uint16) getintvar(si->vars, "devid")) != 0) ;
3594    /*
3595     * no longer support wl0id, but keep the code
3596     * here for backward compatibility.
3597     */
3598    else if ((device = (uint16) getintvar(si->vars, "wl0id")) != 0) ;
3599    /* Chip specific conversion */
3600    else if (sbh->chip == BCM4712_CHIP_ID) {
3601        if (sbh->chippkg == BCM4712SMALL_PKG_ID)
3602            device = BCM4306_D11G_ID;
3603        else
3604            device = BCM4306_D11DUAL_ID;
3605    }
3606    /* ignore it */
3607    else
3608        device = 0xffff;
3609
3610    return device;
3611}
3612
3613int
3614BCMINITFN(sb_corepciid) (sb_t * sbh, uint func, uint16 * pcivendor,
3615             uint16 * pcidevice, uint8 * pciclass,
3616             uint8 * pcisubclass, uint8 * pciprogif,
3617             uint8 * pciheader) {
3618    uint16 vendor = 0xffff, device = 0xffff;
3619    uint8 class, subclass, progif = 0;
3620    uint8 header = PCI_HEADER_NORMAL;
3621    uint32 core = sb_coreid(sbh);
3622
3623    /* Verify whether the function exists for the core */
3624    if (func >= (uint) (core == SB_USB20H ? 2 : 1))
3625        return -1;
3626
3627    /* Known vendor translations */
3628    switch (sb_corevendor(sbh)) {
3629    case SB_VEND_BCM:
3630        vendor = VENDOR_BROADCOM;
3631        break;
3632    default:
3633        return -1;
3634    }
3635
3636    /* Determine class based on known core codes */
3637    switch (core) {
3638    case SB_ILINE20:
3639        class = PCI_CLASS_NET;
3640        subclass = PCI_NET_ETHER;
3641        device = BCM47XX_ILINE_ID;
3642        break;
3643    case SB_ENET:
3644        class = PCI_CLASS_NET;
3645        subclass = PCI_NET_ETHER;
3646        device = BCM47XX_ENET_ID;
3647        break;
3648    case SB_GIGETH:
3649        class = PCI_CLASS_NET;
3650        subclass = PCI_NET_ETHER;
3651        device = BCM47XX_GIGETH_ID;
3652        break;
3653    case SB_SDRAM:
3654    case SB_MEMC:
3655        class = PCI_CLASS_MEMORY;
3656        subclass = PCI_MEMORY_RAM;
3657        device = (uint16) core;
3658        break;
3659    case SB_PCI:
3660    case SB_PCIE:
3661        class = PCI_CLASS_BRIDGE;
3662        subclass = PCI_BRIDGE_PCI;
3663        device = (uint16) core;
3664        header = PCI_HEADER_BRIDGE;
3665        break;
3666    case SB_MIPS:
3667    case SB_MIPS33:
3668        class = PCI_CLASS_CPU;
3669        subclass = PCI_CPU_MIPS;
3670        device = (uint16) core;
3671        break;
3672    case SB_CODEC:
3673        class = PCI_CLASS_COMM;
3674        subclass = PCI_COMM_MODEM;
3675        device = BCM47XX_V90_ID;
3676        break;
3677    case SB_USB:
3678        class = PCI_CLASS_SERIAL;
3679        subclass = PCI_SERIAL_USB;
3680        progif = 0x10; /* OHCI */
3681        device = BCM47XX_USB_ID;
3682        break;
3683    case SB_USB11H:
3684        class = PCI_CLASS_SERIAL;
3685        subclass = PCI_SERIAL_USB;
3686        progif = 0x10; /* OHCI */
3687        device = BCM47XX_USBH_ID;
3688        break;
3689    case SB_USB20H:
3690        class = PCI_CLASS_SERIAL;
3691        subclass = PCI_SERIAL_USB;
3692        progif = func == 0 ? 0x10 : 0x20; /* OHCI/EHCI */
3693        device = BCM47XX_USB20H_ID;
3694        header = 0x80; /* multifunction */
3695        break;
3696    case SB_IPSEC:
3697        class = PCI_CLASS_CRYPT;
3698        subclass = PCI_CRYPT_NETWORK;
3699        device = BCM47XX_IPSEC_ID;
3700        break;
3701    case SB_ROBO:
3702        class = PCI_CLASS_NET;
3703        subclass = PCI_NET_OTHER;
3704        device = BCM47XX_ROBO_ID;
3705        break;
3706    case SB_EXTIF:
3707    case SB_CC:
3708        class = PCI_CLASS_MEMORY;
3709        subclass = PCI_MEMORY_FLASH;
3710        device = (uint16) core;
3711        break;
3712    case SB_SATAXOR:
3713        class = PCI_CLASS_XOR;
3714        subclass = PCI_XOR_QDMA;
3715        device = BCM47XX_SATAXOR_ID;
3716        break;
3717    case SB_ATA100:
3718        class = PCI_CLASS_DASDI;
3719        subclass = PCI_DASDI_IDE;
3720        device = BCM47XX_ATA100_ID;
3721        break;
3722    case SB_USB11D:
3723        class = PCI_CLASS_SERIAL;
3724        subclass = PCI_SERIAL_USB;
3725        device = BCM47XX_USBD_ID;
3726        break;
3727    case SB_USB20D:
3728        class = PCI_CLASS_SERIAL;
3729        subclass = PCI_SERIAL_USB;
3730        device = BCM47XX_USB20D_ID;
3731        break;
3732    case SB_D11:
3733        class = PCI_CLASS_NET;
3734        subclass = PCI_NET_OTHER;
3735        device = sb_d11_devid(sbh);
3736        break;
3737
3738    default:
3739        class = subclass = progif = 0xff;
3740        device = (uint16) core;
3741        break;
3742    }
3743
3744    *pcivendor = vendor;
3745    *pcidevice = device;
3746    *pciclass = class;
3747    *pcisubclass = subclass;
3748    *pciprogif = progif;
3749    *pciheader = header;
3750
3751    return 0;
3752}
3753
3754/* use the mdio interface to read from mdio slaves */
3755static int
3756sb_pcie_mdioread(sb_info_t * si, uint physmedia, uint regaddr, uint * regval)
3757{
3758    uint mdiodata;
3759    uint i = 0;
3760    sbpcieregs_t *pcieregs;
3761
3762    pcieregs = (sbpcieregs_t *) sb_setcoreidx(&si->sb, si->sb.buscoreidx);
3763    ASSERT(pcieregs);
3764
3765    /* enable mdio access to SERDES */
3766    W_REG(si->osh, (&pcieregs->mdiocontrol),
3767          MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
3768
3769    mdiodata = MDIODATA_START | MDIODATA_READ |
3770        (physmedia << MDIODATA_DEVADDR_SHF) |
3771        (regaddr << MDIODATA_REGADDR_SHF) | MDIODATA_TA;
3772
3773    W_REG(si->osh, &pcieregs->mdiodata, mdiodata);
3774
3775    PR28829_DELAY();
3776
3777    /* retry till the transaction is complete */
3778    while (i < 10) {
3779        if (R_REG(si->osh, &(pcieregs->mdiocontrol)) &
3780            MDIOCTL_ACCESS_DONE) {
3781            PR28829_DELAY();
3782            *regval =
3783                (R_REG(si->osh, &(pcieregs->mdiodata)) &
3784                 MDIODATA_MASK);
3785            /* Disable mdio access to SERDES */
3786            W_REG(si->osh, (&pcieregs->mdiocontrol), 0);
3787            return 0;
3788        }
3789        OSL_DELAY(1000);
3790        i++;
3791    }
3792
3793    SB_ERROR(("sb_pcie_mdioread: timed out\n"));
3794    /* Disable mdio access to SERDES */
3795    W_REG(si->osh, (&pcieregs->mdiocontrol), 0);
3796    return 1;
3797}
3798
3799/* use the mdio interface to write to mdio slaves */
3800static int
3801sb_pcie_mdiowrite(sb_info_t * si, uint physmedia, uint regaddr, uint val)
3802{
3803    uint mdiodata;
3804    uint i = 0;
3805    sbpcieregs_t *pcieregs;
3806
3807    pcieregs = (sbpcieregs_t *) sb_setcoreidx(&si->sb, si->sb.buscoreidx);
3808    ASSERT(pcieregs);
3809
3810    /* enable mdio access to SERDES */
3811    W_REG(si->osh, (&pcieregs->mdiocontrol),
3812          MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
3813
3814    mdiodata = MDIODATA_START | MDIODATA_WRITE |
3815        (physmedia << MDIODATA_DEVADDR_SHF) |
3816        (regaddr << MDIODATA_REGADDR_SHF) | MDIODATA_TA | val;
3817
3818    W_REG(si->osh, (&pcieregs->mdiodata), mdiodata);
3819
3820    PR28829_DELAY();
3821
3822    /* retry till the transaction is complete */
3823    while (i < 10) {
3824        if (R_REG(si->osh, &(pcieregs->mdiocontrol)) &
3825            MDIOCTL_ACCESS_DONE) {
3826            /* Disable mdio access to SERDES */
3827            W_REG(si->osh, (&pcieregs->mdiocontrol), 0);
3828            return 0;
3829        }
3830        OSL_DELAY(1000);
3831        i++;
3832    }
3833
3834    SB_ERROR(("sb_pcie_mdiowrite: timed out\n"));
3835    /* Disable mdio access to SERDES */
3836    W_REG(si->osh, (&pcieregs->mdiocontrol), 0);
3837    return 1;
3838
3839}
3840
3841/* indirect way to read pcie config regs */
3842uint sb_pcie_readreg(void *sb, void *arg1, uint offset)
3843{
3844    sb_info_t *si;
3845    sb_t *sbh;
3846    uint retval = 0xFFFFFFFF;
3847    sbpcieregs_t *pcieregs;
3848    uint addrtype;
3849
3850    sbh = (sb_t *) sb;
3851    si = SB_INFO(sbh);
3852    ASSERT(PCIE(si));
3853
3854    pcieregs = (sbpcieregs_t *) sb_setcore(sbh, SB_PCIE, 0);
3855    ASSERT(pcieregs);
3856
3857    addrtype = (uint) ((uintptr) arg1);
3858    switch (addrtype) {
3859    case PCIE_CONFIGREGS:
3860        W_REG(si->osh, (&pcieregs->configaddr), offset);
3861        retval = R_REG(si->osh, &(pcieregs->configdata));
3862        break;
3863    case PCIE_PCIEREGS:
3864        W_REG(si->osh, &(pcieregs->pcieindaddr), offset);
3865        retval = R_REG(si->osh, &(pcieregs->pcieinddata));
3866        break;
3867    default:
3868        ASSERT(0);
3869        break;
3870    }
3871    return retval;
3872}
3873
3874/* indirect way to write pcie config/mdio/pciecore regs */
3875uint sb_pcie_writereg(sb_t * sbh, void *arg1, uint offset, uint val)
3876{
3877    sb_info_t *si;
3878    sbpcieregs_t *pcieregs;
3879    uint addrtype;
3880
3881    si = SB_INFO(sbh);
3882    ASSERT(PCIE(si));
3883
3884    pcieregs = (sbpcieregs_t *) sb_setcore(sbh, SB_PCIE, 0);
3885    ASSERT(pcieregs);
3886
3887    addrtype = (uint) ((uintptr) arg1);
3888
3889    switch (addrtype) {
3890    case PCIE_CONFIGREGS:
3891        W_REG(si->osh, (&pcieregs->configaddr), offset);
3892        W_REG(si->osh, (&pcieregs->configdata), val);
3893        break;
3894    case PCIE_PCIEREGS:
3895        W_REG(si->osh, (&pcieregs->pcieindaddr), offset);
3896        W_REG(si->osh, (&pcieregs->pcieinddata), val);
3897        break;
3898    default:
3899        ASSERT(0);
3900        break;
3901    }
3902    return 0;
3903}
3904
3905/* Build device path. Support SB, PCI, and JTAG for now. */
3906int BCMINITFN(sb_devpath) (sb_t * sbh, char *path, int size) {
3907    int slen;
3908    ASSERT(path);
3909    ASSERT(size >= SB_DEVPATH_BUFSZ);
3910
3911    if (!path || size <= 0)
3912        return -1;
3913
3914    switch (BUSTYPE((SB_INFO(sbh))->sb.bustype)) {
3915    case SB_BUS:
3916    case JTAG_BUS:
3917        slen = snprintf(path, (size_t) size, "sb/%u/", sb_coreidx(sbh));
3918        break;
3919    case PCI_BUS:
3920        ASSERT((SB_INFO(sbh))->osh);
3921        slen = snprintf(path, (size_t) size, "pci/%u/%u/",
3922                OSL_PCI_BUS((SB_INFO(sbh))->osh),
3923                OSL_PCI_SLOT((SB_INFO(sbh))->osh));
3924        break;
3925    case PCMCIA_BUS:
3926        SB_ERROR(("sb_devpath: OSL_PCMCIA_BUS() not implemented, bus 1 assumed\n"));
3927        SB_ERROR(("sb_devpath: OSL_PCMCIA_SLOT() not implemented, slot 1 assumed\n"));
3928        slen = snprintf(path, (size_t) size, "pc/1/1/");
3929        break;
3930    default:
3931        slen = -1;
3932        ASSERT(0);
3933        break;
3934    }
3935
3936    if (slen < 0 || slen >= size) {
3937        path[0] = '\0';
3938        return -1;
3939    }
3940
3941    return 0;
3942}
3943
3944/* Get a variable, but only if it has a devpath prefix */
3945char *BCMINITFN(sb_getdevpathvar) (sb_t * sbh, const char *name) {
3946    char varname[SB_DEVPATH_BUFSZ + 32];
3947
3948    sb_devpathvar(sbh, varname, sizeof(varname), name);
3949
3950    return (getvar(NULL, varname));
3951}
3952
3953/* Get a variable, but only if it has a devpath prefix */
3954int BCMINITFN(sb_getdevpathintvar) (sb_t * sbh, const char *name) {
3955    char varname[SB_DEVPATH_BUFSZ + 32];
3956
3957    sb_devpathvar(sbh, varname, sizeof(varname), name);
3958
3959    return (getintvar(NULL, varname));
3960}
3961
3962/* Concatenate the dev path with a varname into the given 'var' buffer
3963 * and return the 'var' pointer.
3964 * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned.
3965 * On overflow, the first char will be set to '\0'.
3966 */
3967static char *BCMINITFN(sb_devpathvar) (sb_t * sbh, char *var, int len,
3968                       const char *name) {
3969    uint path_len;
3970
3971    if (!var || len <= 0)
3972        return var;
3973
3974    if (sb_devpath(sbh, var, len) == 0) {
3975        path_len = strlen(var);
3976
3977        if (strlen(name) + 1 > (uint) (len - path_len))
3978            var[0] = '\0';
3979        else
3980            strncpy(var + path_len, name, len - path_len - 1);
3981    }
3982
3983    return var;
3984}
3985
3986/*
3987 * Fixup SROMless PCI device's configuration.
3988 * The current core may be changed upon return.
3989 */
3990static int sb_pci_fixcfg(sb_info_t * si)
3991{
3992    uint origidx, pciidx;
3993    sbpciregs_t *pciregs;
3994    sbpcieregs_t *pcieregs = NULL;
3995    uint16 val16, *reg16;
3996    uint32 w;
3997
3998    ASSERT(BUSTYPE(si->sb.bustype) == PCI_BUS);
3999
4000    /* Fixup PI in SROM shadow area to enable the correct PCI core access */
4001    /* save the current index */
4002    origidx = sb_coreidx(&si->sb);
4003
4004    /* check 'pi' is correct and fix it if not */
4005    if (si->sb.buscoretype == SB_PCIE) {
4006        pcieregs = (sbpcieregs_t *) sb_setcore(&si->sb, SB_PCIE, 0);
4007        ASSERT(pcieregs);
4008        reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
4009    } else if (si->sb.buscoretype == SB_PCI) {
4010        pciregs = (sbpciregs_t *) sb_setcore(&si->sb, SB_PCI, 0);
4011        ASSERT(pciregs);
4012        reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
4013    } else {
4014        ASSERT(0);
4015        return -1;
4016    }
4017    pciidx = sb_coreidx(&si->sb);
4018    val16 = R_REG(si->osh, reg16);
4019    if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (uint16) pciidx) {
4020        val16 =
4021            (uint16) (pciidx << SRSH_PI_SHIFT) | (val16 &
4022                              ~SRSH_PI_MASK);
4023        W_REG(si->osh, reg16, val16);
4024    }
4025
4026    if (PCIE_ASPMWARS(si)) {
4027        w = sb_pcie_readreg((void *)(uintptr) & si->sb,
4028                    (void *)PCIE_PCIEREGS, PCIE_PLP_STATUSREG);
4029
4030        /* Detect the current polarity at attach and force that polarity and
4031         * disable changing the polarity
4032         */
4033        if ((w & PCIE_PLP_POLARITYINV_STAT) == 0) {
4034            si->pcie_polarity = (SERDES_RX_CTRL_FORCE);
4035        } else {
4036            si->pcie_polarity = (SERDES_RX_CTRL_FORCE |
4037                         SERDES_RX_CTRL_POLARITY);
4038        }
4039
4040        w = OSL_PCI_READ_CONFIG(si->osh, si->pciecap_lcreg_offset,
4041                    sizeof(uint32));
4042        if (w & PCIE_CLKREQ_ENAB) {
4043            reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET];
4044            val16 = R_REG(si->osh, reg16);
4045            /* if clockreq is not advertized clkreq should not be enabled */
4046            if (!(val16 & SRSH_CLKREQ_ENB))
4047                SB_ERROR(("WARNING: CLK REQ enabled already 0x%x\n", w));
4048        }
4049
4050        sb_war43448(&si->sb);
4051
4052        sb_war42767(&si->sb);
4053
4054    }
4055
4056    /* restore the original index */
4057    sb_setcoreidx(&si->sb, origidx);
4058
4059    return 0;
4060}
4061
4062/* Return ADDR64 capability of the backplane */
4063bool sb_backplane64(sb_t * sbh)
4064{
4065    sb_info_t *si;
4066
4067    si = SB_INFO(sbh);
4068    return ((si->sb.cccaps & CC_CAP_BKPLN64) != 0);
4069}
4070
4071void sb_btcgpiowar(sb_t * sbh)
4072{
4073    sb_info_t *si;
4074    uint origidx;
4075    uint intr_val = 0;
4076    chipcregs_t *cc;
4077    si = SB_INFO(sbh);
4078
4079    /* Make sure that there is ChipCommon core present &&
4080     * UART_TX is strapped to 1
4081     */
4082    if (!(si->sb.cccaps & CC_CAP_UARTGPIO))
4083        return;
4084
4085    /* sb_corereg cannot be used as we have to guarantee 8-bit read/writes */
4086    INTR_OFF(si, intr_val);
4087
4088    origidx = sb_coreidx(sbh);
4089
4090    cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0);
4091    ASSERT(cc);
4092
4093    W_REG(si->osh, &cc->uart0mcr, R_REG(si->osh, &cc->uart0mcr) | 0x04);
4094
4095    /* restore the original index */
4096    sb_setcoreidx(sbh, origidx);
4097
4098    INTR_RESTORE(si, intr_val);
4099}
4100
4101/* check if the device is removed */
4102bool sb_deviceremoved(sb_t * sbh)
4103{
4104    uint32 w;
4105    sb_info_t *si;
4106
4107    si = SB_INFO(sbh);
4108
4109    switch (BUSTYPE(si->sb.bustype)) {
4110    case PCI_BUS:
4111        ASSERT(si->osh);
4112        w = OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_VID, sizeof(uint32));
4113        if ((w & 0xFFFF) != VENDOR_BROADCOM)
4114            return TRUE;
4115        else
4116            return FALSE;
4117    default:
4118        return FALSE;
4119    }
4120    return FALSE;
4121}
4122
4123#if 0
4124/* Return the RAM size of the SOCRAM core */
4125uint32 BCMINITFN(sb_socram_size) (sb_t * sbh) {
4126    sb_info_t *si;
4127    uint origidx;
4128    uint intr_val = 0;
4129
4130    sbsocramregs_t *regs;
4131    bool wasup;
4132    uint corerev;
4133    uint32 coreinfo;
4134    uint memsize = 0;
4135
4136    si = SB_INFO(sbh);
4137    ASSERT(si);
4138
4139    /* Block ints and save current core */
4140    INTR_OFF(si, intr_val);
4141    origidx = sb_coreidx(sbh);
4142
4143    /* Switch to SOCRAM core */
4144    if (!(regs = sb_setcore(sbh, SB_SOCRAM, 0)))
4145        goto done;
4146
4147    /* Get info for determining size */
4148    if (!(wasup = sb_iscoreup(sbh)))
4149        sb_core_reset(sbh, 0, 0);
4150    corerev = sb_corerev(sbh);
4151    coreinfo = R_REG(si->osh, &regs->coreinfo);
4152
4153    /* Calculate size from coreinfo based on rev */
4154    if (corerev == 0)
4155        memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
4156    else if (corerev < 3) {
4157        memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
4158        memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
4159    } else {
4160        uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
4161        uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
4162        uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
4163        if (lss != 0)
4164            nb--;
4165        memsize = nb * (1 << (bsz + SR_BSZ_BASE));
4166        if (lss != 0)
4167            memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
4168    }
4169    /* Return to previous state and core */
4170    if (!wasup)
4171        sb_core_disable(sbh, 0);
4172    sb_setcoreidx(sbh, origidx);
4173
4174      done:
4175    INTR_RESTORE(si, intr_val);
4176    return memsize;
4177}
4178
4179#endif
4180

Archive Download this file



interactive