aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbutils.c')
-rw-r--r--target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbutils.c4179
1 files changed, 0 insertions, 4179 deletions
diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbutils.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbutils.c
deleted file mode 100644
index 5c85dd7c9f..0000000000
--- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbutils.c
+++ /dev/null
@@ -1,4179 +0,0 @@
-/*
- * Misc utility routines for accessing chip-specific features
- * of the SiliconBackplane-based Broadcom chips.
- *
- * Copyright 2007, Broadcom Corporation
- * All Rights Reserved.
- *
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
- */
-
-#include <typedefs.h>
-#include <bcmdefs.h>
-#include <osl.h>
-#include <sbutils.h>
-#include <bcmdevs.h>
-#include <sbconfig.h>
-#include <sbchipc.h>
-#include <sbextif.h>
-#include <sbpci.h>
-#include <sbpcie.h>
-#include <pcicfg.h>
-#include <sbpcmcia.h>
-#include <sbsocram.h>
-#include <bcmnvram.h>
-#include <bcmsrom.h>
-#include <hndpmu.h>
-
-/* debug/trace */
-#define SB_ERROR(args)
-
-#ifdef BCMDBG
-#define SB_MSG(args) printf args
-#else
-#define SB_MSG(args)
-#endif /* BCMDBG */
-
-typedef uint32(*sb_intrsoff_t) (void *intr_arg);
-typedef void (*sb_intrsrestore_t) (void *intr_arg, uint32 arg);
-typedef bool(*sb_intrsenabled_t) (void *intr_arg);
-
-typedef struct gpioh_item {
- void *arg;
- bool level;
- gpio_handler_t handler;
- uint32 event;
- struct gpioh_item *next;
-} gpioh_item_t;
-
-/* misc sb info needed by some of the routines */
-typedef struct sb_info {
-
- struct sb_pub sb; /* back plane public state (must be first field) */
-
- void *osh; /* osl os handle */
- void *sdh; /* bcmsdh handle */
-
- void *curmap; /* current regs va */
- void *regs[SB_MAXCORES]; /* other regs va */
-
- uint curidx; /* current core index */
- uint dev_coreid; /* the core provides driver functions */
-
- bool memseg; /* flag to toggle MEM_SEG register */
-
- uint gpioidx; /* gpio control core index */
- uint gpioid; /* gpio control coretype */
-
- uint numcores; /* # discovered cores */
- uint coreid[SB_MAXCORES]; /* id of each core */
-
- void *intr_arg; /* interrupt callback function arg */
- sb_intrsoff_t intrsoff_fn; /* turns chip interrupts off */
- sb_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */
- sb_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */
-
- uint8 pciecap_lcreg_offset; /* PCIE capability LCreg offset in the config space */
- bool pr42767_war;
- uint8 pcie_polarity;
- bool pcie_war_ovr; /* Override ASPM/Clkreq settings */
-
- uint8 pmecap_offset; /* PM Capability offset in the config space */
- bool pmecap; /* Capable of generating PME */
-
- gpioh_item_t *gpioh_head; /* GPIO event handlers list */
-
- char *vars;
- uint varsz;
-} sb_info_t;
-
-/* local prototypes */
-static sb_info_t *sb_doattach(sb_info_t * si, uint devid, osl_t * osh,
- void *regs, uint bustype, void *sdh,
- char **vars, uint * varsz);
-static void sb_scan(sb_info_t * si);
-static uint _sb_coreidx(sb_info_t * si);
-static uint sb_pcidev2chip(uint pcidev);
-static uint sb_chip2numcores(uint chip);
-static bool sb_ispcie(sb_info_t * si);
-static uint8 sb_find_pci_capability(sb_info_t * si, uint8 req_cap_id,
- uchar * buf, uint32 * buflen);
-static int sb_pci_fixcfg(sb_info_t * si);
-/* routines to access mdio slave device registers */
-static int sb_pcie_mdiowrite(sb_info_t * si, uint physmedia, uint readdr,
- uint val);
-static int sb_pcie_mdioread(sb_info_t * si, uint physmedia, uint readdr,
- uint * ret_val);
-
-/* dev path concatenation util */
-static char *sb_devpathvar(sb_t * sbh, char *var, int len, const char *name);
-
-/* WARs */
-static void sb_war43448(sb_t * sbh);
-static void sb_war43448_aspm(sb_t * sbh);
-static void sb_war32414_forceHT(sb_t * sbh, bool forceHT);
-static void sb_war30841(sb_info_t * si);
-static void sb_war42767(sb_t * sbh);
-static void sb_war42767_clkreq(sb_t * sbh);
-
-/* delay needed between the mdio control/ mdiodata register data access */
-#define PR28829_DELAY() OSL_DELAY(10)
-
-/* size that can take bitfielddump */
-#define BITFIELD_DUMP_SIZE 32
-
-/* global variable to indicate reservation/release of gpio's */
-static uint32 sb_gpioreservation = 0;
-
-/* global flag to prevent shared resources from being initialized multiple times in sb_attach() */
-static bool sb_onetimeinit = FALSE;
-
-#define SB_INFO(sbh) (sb_info_t*)(uintptr)sbh
-#define SET_SBREG(si, r, mask, val) \
- W_SBREG((si), (r), ((R_SBREG((si), (r)) & ~(mask)) | (val)))
-#define GOODCOREADDR(x) (((x) >= SB_ENUM_BASE) && ((x) <= SB_ENUM_LIM) && \
- ISALIGNED((x), SB_CORE_SIZE))
-#define GOODREGS(regs) ((regs) && ISALIGNED((uintptr)(regs), SB_CORE_SIZE))
-#define REGS2SB(va) (sbconfig_t*) ((int8*)(va) + SBCONFIGOFF)
-#define BADCOREADDR 0
-#define GOODIDX(idx) (((uint)idx) < SB_MAXCORES)
-#define BADIDX (SB_MAXCORES+1)
-#define NOREV -1 /* Invalid rev */
-
-#define PCI(si) ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (si->sb.buscoretype == SB_PCI))
-#define PCIE(si) ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (si->sb.buscoretype == SB_PCIE))
-#define PCMCIA(si) ((BUSTYPE(si->sb.bustype) == PCMCIA_BUS) && (si->memseg == TRUE))
-
-/* sonicsrev */
-#define SONICS_2_2 (SBIDL_RV_2_2 >> SBIDL_RV_SHIFT)
-#define SONICS_2_3 (SBIDL_RV_2_3 >> SBIDL_RV_SHIFT)
-
-#define R_SBREG(si, sbr) sb_read_sbreg((si), (sbr))
-#define W_SBREG(si, sbr, v) sb_write_sbreg((si), (sbr), (v))
-#define AND_SBREG(si, sbr, v) W_SBREG((si), (sbr), (R_SBREG((si), (sbr)) & (v)))
-#define OR_SBREG(si, sbr, v) W_SBREG((si), (sbr), (R_SBREG((si), (sbr)) | (v)))
-
-/*
- * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/
- * after core switching to avoid invalid register accesss inside ISR.
- */
-#define INTR_OFF(si, intr_val) \
- if ((si)->intrsoff_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
- intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); }
-#define INTR_RESTORE(si, intr_val) \
- if ((si)->intrsrestore_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
- (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); }
-
-/* dynamic clock control defines */
-#define LPOMINFREQ 25000 /* low power oscillator min */
-#define LPOMAXFREQ 43000 /* low power oscillator max */
-#define XTALMINFREQ 19800000 /* 20 MHz - 1% */
-#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */
-#define PCIMINFREQ 25000000 /* 25 MHz */
-#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */
-
-#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */
-#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */
-
-/* force HT war check */
-#define FORCEHT_WAR32414(si) \
- (((PCIE(si)) && (si->sb.chip == BCM4311_CHIP_ID) && ((si->sb.chiprev <= 1))) || \
- ((PCI(si) || PCIE(si)) && (si->sb.chip == BCM4321_CHIP_ID) && (si->sb.chiprev <= 3)))
-
-#define PCIE_ASPMWARS(si) \
- ((PCIE(si)) && ((si->sb.buscorerev >= 3) && (si->sb.buscorerev <= 5)))
-
-/* GPIO Based LED powersave defines */
-#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */
-#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */
-
-#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME)
-
-static uint32 sb_read_sbreg(sb_info_t * si, volatile uint32 * sbr)
-{
- uint8 tmp;
- uint32 val, intr_val = 0;
-
- /*
- * compact flash only has 11 bits address, while we needs 12 bits address.
- * MEM_SEG will be OR'd with other 11 bits address in hardware,
- * so we program MEM_SEG with 12th bit when necessary(access sb regsiters).
- * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special
- */
- if (PCMCIA(si)) {
- INTR_OFF(si, intr_val);
- tmp = 1;
- OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1);
- sbr = (volatile uint32 *)((uintptr) sbr & ~(1 << 11)); /* mask out bit 11 */
- }
-
- val = R_REG(si->osh, sbr);
-
- if (PCMCIA(si)) {
- tmp = 0;
- OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1);
- INTR_RESTORE(si, intr_val);
- }
-
- return (val);
-}
-
-static void sb_write_sbreg(sb_info_t * si, volatile uint32 * sbr, uint32 v)
-{
- uint8 tmp;
- volatile uint32 dummy;
- uint32 intr_val = 0;
-
- /*
- * compact flash only has 11 bits address, while we needs 12 bits address.
- * MEM_SEG will be OR'd with other 11 bits address in hardware,
- * so we program MEM_SEG with 12th bit when necessary(access sb regsiters).
- * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special
- */
- if (PCMCIA(si)) {
- INTR_OFF(si, intr_val);
- tmp = 1;
- OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1);
- sbr = (volatile uint32 *)((uintptr) sbr & ~(1 << 11)); /* mask out bit 11 */
- }
-
- if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) {
-#ifdef IL_BIGENDIAN
- dummy = R_REG(si->osh, sbr);
- W_REG(si->osh, ((volatile uint16 *)sbr + 1),
- (uint16) ((v >> 16) & 0xffff));
- dummy = R_REG(si->osh, sbr);
- W_REG(si->osh, (volatile uint16 *)sbr, (uint16) (v & 0xffff));
-#else
- dummy = R_REG(si->osh, sbr);
- W_REG(si->osh, (volatile uint16 *)sbr, (uint16) (v & 0xffff));
- dummy = R_REG(si->osh, sbr);
- W_REG(si->osh, ((volatile uint16 *)sbr + 1),
- (uint16) ((v >> 16) & 0xffff));
-#endif /* IL_BIGENDIAN */
- } else
- W_REG(si->osh, sbr, v);
-
- if (PCMCIA(si)) {
- tmp = 0;
- OSL_PCMCIA_WRITE_ATTR(si->osh, MEM_SEG, &tmp, 1);
- INTR_RESTORE(si, intr_val);
- }
-}
-
-/*
- * Allocate a sb handle.
- * devid - pci device id (used to determine chip#)
- * osh - opaque OS handle
- * regs - virtual address of initial core registers
- * bustype - pci/pcmcia/sb/sdio/etc
- * vars - pointer to a pointer area for "environment" variables
- * varsz - pointer to int to return the size of the vars
- */
-sb_t *sb_attach(uint devid, osl_t * osh, void *regs,
- uint bustype, void *sdh, char **vars,
- uint * varsz) {
- sb_info_t *si;
-
- /* alloc sb_info_t */
- if ((si = MALLOC(osh, sizeof(sb_info_t))) == NULL) {
- SB_ERROR(("sb_attach: malloc failed! malloced %d bytes\n",
- MALLOCED(osh)));
- return (NULL);
- }
-
- if (sb_doattach(si, devid, osh, regs, bustype, sdh, vars, varsz) ==
- NULL) {
- MFREE(osh, si, sizeof(sb_info_t));
- return (NULL);
- }
- si->vars = vars ? *vars : NULL;
- si->varsz = varsz ? *varsz : 0;
-
- return (sb_t *) si;
-}
-
-/* Using sb_kattach depends on SB_BUS support, either implicit */
-/* no limiting BCMBUSTYPE value) or explicit (value is SB_BUS). */
-#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SB_BUS)
-
-/* global kernel resource */
-static sb_info_t ksi;
-
-/* generic kernel variant of sb_attach() */
-sb_t *BCMINITFN(sb_kattach) (osl_t * osh) {
- static bool ksi_attached = FALSE;
- uint32 *regs;
-
- if (!ksi_attached) {
- uint32 cid;
-
- regs = (uint32 *) REG_MAP(SB_ENUM_BASE, SB_CORE_SIZE);
- cid = R_REG(osh, (uint32 *) regs);
- if (((cid & CID_ID_MASK) == BCM4712_CHIP_ID) &&
- ((cid & CID_PKG_MASK) != BCM4712LARGE_PKG_ID) &&
- ((cid & CID_REV_MASK) <= (3 << CID_REV_SHIFT))) {
- uint32 *scc, val;
-
- scc =
- (uint32 *) ((uchar *) regs +
- OFFSETOF(chipcregs_t, slow_clk_ctl));
- val = R_REG(osh, scc);
- SB_ERROR((" initial scc = 0x%x\n", val));
- val |= SCC_SS_XTAL;
- W_REG(osh, scc, val);
- }
-
- if (sb_doattach(&ksi, BCM4710_DEVICE_ID, osh, (void *)regs, SB_BUS, NULL,
- osh != SB_OSH ? &ksi.vars : NULL,
- osh != SB_OSH ? &ksi.varsz : NULL) == NULL)
- return NULL;
- ksi_attached = TRUE;
- }
-
- return &ksi.sb;
-}
-#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SB_BUS) */
-
-static sb_info_t *BCMINITFN(sb_doattach) (sb_info_t * si, uint devid,
- osl_t * osh, void *regs,
- uint bustype, void *sdh,
- char **vars, uint * varsz) {
- uint origidx;
- chipcregs_t *cc;
- sbconfig_t *sb;
- uint32 w;
- char *pvars;
-
- ASSERT(GOODREGS(regs));
-
- bzero((uchar *) si, sizeof(sb_info_t));
- si->sb.buscoreidx = si->gpioidx = BADIDX;
-
- si->curmap = regs;
- si->sdh = sdh;
- si->osh = osh;
-
- /* check to see if we are a sb core mimic'ing a pci core */
- if (bustype == PCI_BUS) {
- if (OSL_PCI_READ_CONFIG
- (si->osh, PCI_SPROM_CONTROL,
- sizeof(uint32)) == 0xffffffff) {
- SB_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SB " "devid:0x%x\n", __FUNCTION__, devid));
- bustype = SB_BUS;
- }
- }
- si->sb.bustype = bustype;
- if (si->sb.bustype != BUSTYPE(si->sb.bustype)) {
- SB_ERROR(("sb_doattach: bus type %d does not match configured bus type %d\n", si->sb.bustype, BUSTYPE(si->sb.bustype)));
- return NULL;
- }
-
- /* need to set memseg flag for CF card first before any sb registers access */
- if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS)
- si->memseg = TRUE;
-
- /* kludge to enable the clock on the 4306 which lacks a slowclock */
- if (BUSTYPE(si->sb.bustype) == PCI_BUS && !sb_ispcie(si))
- sb_clkctl_xtal(&si->sb, XTAL | PLL, ON);
-
- if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
- w = OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32));
- if (!GOODCOREADDR(w))
- OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN,
- sizeof(uint32), SB_ENUM_BASE);
- }
-
- /* initialize current core index value */
- si->curidx = _sb_coreidx(si);
-
- if (si->curidx == BADIDX) {
- SB_ERROR(("sb_doattach: bad core index\n"));
- return NULL;
- }
-
- /* get sonics backplane revision */
- sb = REGS2SB(regs);
- si->sb.sonicsrev =
- (R_SBREG(si, &sb->sbidlow) & SBIDL_RV_MASK) >> SBIDL_RV_SHIFT;
- /* keep and reuse the initial register mapping */
- origidx = si->curidx;
- if (BUSTYPE(si->sb.bustype) == SB_BUS)
- si->regs[origidx] = regs;
-
- /* is core-0 a chipcommon core? */
- si->numcores = 1;
- cc = (chipcregs_t *) sb_setcoreidx(&si->sb, 0);
- if (sb_coreid(&si->sb) != SB_CC)
- cc = NULL;
-
- /* determine chip id and rev */
- if (cc) {
- /* chip common core found! */
- si->sb.chip = R_REG(si->osh, &cc->chipid) & CID_ID_MASK;
- si->sb.chiprev =
- (R_REG(si->osh, &cc->chipid) & CID_REV_MASK) >>
- CID_REV_SHIFT;
- si->sb.chippkg =
- (R_REG(si->osh, &cc->chipid) & CID_PKG_MASK) >>
- CID_PKG_SHIFT;
- } else {
- /* no chip common core -- must convert device id to chip id */
- if ((si->sb.chip = sb_pcidev2chip(devid)) == 0) {
- SB_ERROR(("sb_doattach: unrecognized device id 0x%04x\n", devid));
- sb_setcoreidx(&si->sb, origidx);
- return NULL;
- }
- }
-
- /* get chipcommon rev */
- si->sb.ccrev = cc ? (int)sb_corerev(&si->sb) : NOREV;
-
- /* get chipcommon capabilites */
- si->sb.cccaps = cc ? R_REG(si->osh, &cc->capabilities) : 0;
-
- /* determine numcores */
- if (cc && ((si->sb.ccrev == 4) || (si->sb.ccrev >= 6)))
- si->numcores =
- (R_REG(si->osh, &cc->chipid) & CID_CC_MASK) >> CID_CC_SHIFT;
- else
- si->numcores = sb_chip2numcores(si->sb.chip);
-
- /* return to original core */
- sb_setcoreidx(&si->sb, origidx);
-
- /* sanity checks */
- ASSERT(si->sb.chip);
-
- /* scan for cores */
- sb_scan(si);
-
- /* fixup necessary chip/core configurations */
- if (BUSTYPE(si->sb.bustype) == PCI_BUS && sb_pci_fixcfg(si)) {
- SB_ERROR(("sb_doattach: sb_pci_fixcfg failed\n"));
- return NULL;
- }
-
- /* Init nvram from sprom/otp if they exist */
- if (srom_var_init
- (&si->sb, BUSTYPE(si->sb.bustype), regs, si->osh, vars, varsz)) {
- SB_ERROR(("sb_doattach: srom_var_init failed: bad srom\n"));
- return (NULL);
- }
- pvars = vars ? *vars : NULL;
-
- /* PMU specific initializations */
- if ((si->sb.cccaps & CC_CAP_PMU) && !sb_onetimeinit) {
- sb_pmu_init(&si->sb, si->osh);
- /* Find out Crystal frequency and init PLL */
- sb_pmu_pll_init(&si->sb, si->osh, getintvar(pvars, "xtalfreq"));
- /* Initialize PMU resources (up/dn timers, dep masks, etc.) */
- sb_pmu_res_init(&si->sb, si->osh);
- }
- if (cc == NULL) {
- /*
- * The chip revision number is hardwired into all
- * of the pci function config rev fields and is
- * independent from the individual core revision numbers.
- * For example, the "A0" silicon of each chip is chip rev 0.
- * For PCMCIA we get it from the CIS instead.
- */
- if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) {
- ASSERT(vars);
- si->sb.chiprev = getintvar(*vars, "chiprev");
- } else if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
- w = OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_REV,
- sizeof(uint32));
- si->sb.chiprev = w & 0xff;
- } else
- si->sb.chiprev = 0;
- }
-
- if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) {
- w = getintvar(pvars, "regwindowsz");
- si->memseg = (w <= CFTABLE_REGWIN_2K) ? TRUE : FALSE;
- }
- /* gpio control core is required */
- if (!GOODIDX(si->gpioidx)) {
- SB_ERROR(("sb_doattach: gpio control core not found\n"));
- return NULL;
- }
-
- /* get boardtype and boardrev */
- switch (BUSTYPE(si->sb.bustype)) {
- case PCI_BUS:
- /* do a pci config read to get subsystem id and subvendor id */
- w = OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_SVID, sizeof(uint32));
- /* Let nvram variables override subsystem Vend/ID */
- if ((si->sb.boardvendor =
- (uint16) sb_getdevpathintvar(&si->sb, "boardvendor")) == 0)
- si->sb.boardvendor = w & 0xffff;
- else
- SB_ERROR(("Overriding boardvendor: 0x%x instead of 0x%x\n", si->sb.boardvendor, w & 0xffff));
- if ((si->sb.boardtype =
- (uint16) sb_getdevpathintvar(&si->sb, "boardtype")) == 0)
- si->sb.boardtype = (w >> 16) & 0xffff;
- else
- SB_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n", si->sb.boardtype, (w >> 16) & 0xffff));
- break;
-
- case PCMCIA_BUS:
- si->sb.boardvendor = getintvar(pvars, "manfid");
- si->sb.boardtype = getintvar(pvars, "prodid");
- break;
-
- case SB_BUS:
- case JTAG_BUS:
- si->sb.boardvendor = VENDOR_BROADCOM;
- if (pvars == NULL
- || ((si->sb.boardtype = getintvar(pvars, "prodid")) == 0))
- if ((si->sb.boardtype =
- getintvar(NULL, "boardtype")) == 0)
- si->sb.boardtype = 0xffff;
- break;
- }
-
- if (si->sb.boardtype == 0) {
- SB_ERROR(("sb_doattach: unknown board type\n"));
- ASSERT(si->sb.boardtype);
- }
-
- si->sb.boardflags = getintvar(pvars, "boardflags");
-
- /* setup the GPIO based LED powersave register */
- if (si->sb.ccrev >= 16) {
- if ((pvars == NULL) || ((w = getintvar(pvars, "leddc")) == 0))
- w = DEFAULT_GPIOTIMERVAL;
- sb_corereg(&si->sb, SB_CC_IDX,
- OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
- }
-
- /* Determine if this board needs override */
- if (PCIE(si) && (si->sb.chip == BCM4321_CHIP_ID))
- si->pcie_war_ovr = ((si->sb.boardvendor == VENDOR_APPLE) &&
- ((uint8) getintvar(pvars, "sromrev") == 4)
- && ((uint8) getintvar(pvars, "boardrev") <=
- 0x71))
- || ((uint32) getintvar(pvars, "boardflags2") &
- BFL2_PCIEWAR_OVR);
-
- if (PCIE_ASPMWARS(si)) {
- sb_war43448_aspm((void *)si);
- sb_war42767_clkreq((void *)si);
- }
-
- if (FORCEHT_WAR32414(si)) {
- si->sb.pr32414 = TRUE;
- sb_clkctl_init(&si->sb);
- sb_war32414_forceHT(&si->sb, 1);
- }
-
- if (PCIE(si) && ((si->sb.buscorerev == 6) || (si->sb.buscorerev == 7)))
- si->sb.pr42780 = TRUE;
-
- if (PCIE_ASPMWARS(si))
- sb_pcieclkreq(&si->sb, 1, 0);
-
- if (PCIE(si) &&
- (((si->sb.chip == BCM4311_CHIP_ID) && (si->sb.chiprev == 2)) ||
- ((si->sb.chip == BCM4312_CHIP_ID) && (si->sb.chiprev == 0))))
- sb_set_initiator_to(&si->sb, 0x3,
- sb_findcoreidx(&si->sb, SB_D11, 0));
-
- /* Disable gpiopullup and gpiopulldown */
- if (!sb_onetimeinit && si->sb.ccrev >= 20) {
- cc = (chipcregs_t *) sb_setcore(&si->sb, SB_CC, 0);
- W_REG(osh, &cc->gpiopullup, 0);
- W_REG(osh, &cc->gpiopulldown, 0);
- sb_setcoreidx(&si->sb, origidx);
- }
-#ifdef BCMDBG
- /* clear any previous epidiag-induced target abort */
- sb_taclear(&si->sb);
-#endif /* BCMDBG */
-
-#ifdef HNDRTE
- sb_onetimeinit = TRUE;
-#endif
-
- return (si);
-}
-
-/* Enable/Disable clkreq for PCIE (4311B0/4321B1) */
-void sb_war42780_clkreq(sb_t * sbh, bool clkreq) {
- sb_info_t *si;
-
- si = SB_INFO(sbh);
-
- /* Don't change clkreq value if serdespll war has not yet been applied */
- if (!si->pr42767_war && PCIE_ASPMWARS(si))
- return;
-
- sb_pcieclkreq(sbh, 1, (int32) clkreq);
-}
-
-static void BCMINITFN(sb_war43448) (sb_t * sbh) {
- sb_info_t *si;
-
- si = SB_INFO(sbh);
-
- /* if not pcie bus, we're done */
- if (!PCIE(si) || !PCIE_ASPMWARS(si))
- return;
-
- /* Restore the polarity */
- if (si->pcie_polarity != 0)
- sb_pcie_mdiowrite((void *)(uintptr) & si->sb, MDIODATA_DEV_RX,
- SERDES_RX_CTRL, si->pcie_polarity);
-}
-
-static void BCMINITFN(sb_war43448_aspm) (sb_t * sbh) {
- uint32 w;
- uint16 val16, *reg16;
- sbpcieregs_t *pcieregs;
- sb_info_t *si;
-
- si = SB_INFO(sbh);
-
- /* if not pcie bus, we're done */
- if (!PCIE(si) || !PCIE_ASPMWARS(si))
- return;
-
- /* no ASPM stuff on QT or VSIM */
- if (si->sb.chippkg == HDLSIM_PKG_ID || si->sb.chippkg == HWSIM_PKG_ID)
- return;
-
- pcieregs = (sbpcieregs_t *) sb_setcoreidx(sbh, si->sb.buscoreidx);
-
- /* Enable ASPM in the shadow SROM and Link control */
- reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET];
- val16 = R_REG(si->osh, reg16);
- if (!si->pcie_war_ovr)
- val16 |= SRSH_ASPM_ENB;
- else
- val16 &= ~SRSH_ASPM_ENB;
- W_REG(si->osh, reg16, val16);
-
- w = OSL_PCI_READ_CONFIG(si->osh, si->pciecap_lcreg_offset,
- sizeof(uint32));
- if (!si->pcie_war_ovr)
- w |= PCIE_ASPM_ENAB;
- else
- w &= ~PCIE_ASPM_ENAB;
- OSL_PCI_WRITE_CONFIG(si->osh, si->pciecap_lcreg_offset, sizeof(uint32),
- w);
-}
-
-static void BCMINITFN(sb_war32414_forceHT) (sb_t * sbh, bool forceHT) {
- sb_info_t *si;
- uint32 val = 0;
-
- si = SB_INFO(sbh);
-
- ASSERT(FORCEHT_WAR32414(si));
-
- if (forceHT)
- val = SYCC_HR;
- sb_corereg(sbh, SB_CC_IDX, OFFSETOF(chipcregs_t, system_clk_ctl),
- SYCC_HR, val);
-}
-
-uint sb_coreid(sb_t * sbh)
-{
- sb_info_t *si;
- sbconfig_t *sb;
-
- si = SB_INFO(sbh);
- sb = REGS2SB(si->curmap);
-
- return ((R_SBREG(si, &sb->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT);
-}
-
-uint sb_flag(sb_t * sbh)
-{
- sb_info_t *si;
- sbconfig_t *sb;
-
- si = SB_INFO(sbh);
- sb = REGS2SB(si->curmap);
-
- return R_SBREG(si, &sb->sbtpsflag) & SBTPS_NUM0_MASK;
-}
-
-uint sb_coreidx(sb_t * sbh)
-{
- sb_info_t *si;
-
- si = SB_INFO(sbh);
- return (si->curidx);
-}
-
-static uint _sb_coreidx(sb_info_t * si)
-{
-
- sbconfig_t *sb;
- uint32 sbaddr = 0;
-
- ASSERT(si);
-
- switch (BUSTYPE(si->sb.bustype)) {
- case SB_BUS:
- sb = REGS2SB(si->curmap);
- sbaddr = sb_base(R_SBREG(si, &sb->sbadmatch0));
- break;
-
- case PCI_BUS:
- sbaddr =
- OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32));
- break;
-
- case PCMCIA_BUS:{
- uint8 tmp = 0;
-
- OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR0, &tmp, 1);
- sbaddr = (uint) tmp << 12;
- OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR1, &tmp, 1);
- sbaddr |= (uint) tmp << 16;
- OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_ADDR2, &tmp, 1);
- sbaddr |= (uint) tmp << 24;
- break;
- }
-
-#ifdef BCMJTAG
- case JTAG_BUS:
- sbaddr = (uint32) si->curmap;
- break;
-#endif /* BCMJTAG */
-
- default:
- ASSERT(0);
- }
-
- if (!GOODCOREADDR(sbaddr))
- return BADIDX;
-
- return ((sbaddr - SB_ENUM_BASE) / SB_CORE_SIZE);
-}
-
-uint sb_corevendor(sb_t * sbh)
-{
- sb_info_t *si;
- sbconfig_t *sb;
-
- si = SB_INFO(sbh);
- sb = REGS2SB(si->curmap);
-
- return ((R_SBREG(si, &sb->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT);
-}
-
-uint sb_corerev(sb_t * sbh)
-{
- sb_info_t *si;
- sbconfig_t *sb;
- uint sbidh;
-
- si = SB_INFO(sbh);
- sb = REGS2SB(si->curmap);
- sbidh = R_SBREG(si, &sb->sbidhigh);
-
- return (SBCOREREV(sbidh));
-}
-
-void *sb_osh(sb_t * sbh)
-{
- sb_info_t *si;
-
- si = SB_INFO(sbh);
- return si->osh;
-}
-
-void sb_setosh(sb_t * sbh, osl_t * osh)
-{
- sb_info_t *si;
-
- si = SB_INFO(sbh);
- if (si->osh != NULL) {
- SB_ERROR(("osh is already set....\n"));
- ASSERT(!si->osh);
- }
- si->osh = osh;
-}
-
-/* set sbtmstatelow core-specific flags */
-void sb_coreflags_wo(sb_t * sbh, uint32 mask, uint32 val)
-{
- sb_info_t *si;
- sbconfig_t *sb;
- uint32 w;
-
- si = SB_INFO(sbh);
- sb = REGS2SB(si->curmap);
-
- ASSERT((val & ~mask) == 0);
-
- /* mask and set */
- w = (R_SBREG(si, &sb->sbtmstatelow) & ~mask) | val;
- W_SBREG(si, &sb->sbtmstatelow, w);
-}
-
-/* set/clear sbtmstatelow core-specific flags */
-uint32 sb_coreflags(sb_t * sbh, uint32 mask, uint32 val)
-{
- sb_info_t *si;
- sbconfig_t *sb;
- uint32 w;
-
- si = SB_INFO(sbh);
- sb = REGS2SB(si->curmap);
-
- ASSERT((val & ~mask) == 0);
-
- /* mask and set */
- if (mask || val) {
- w = (R_SBREG(si, &sb->sbtmstatelow) & ~mask) | val;
- W_SBREG(si, &sb->sbtmstatelow, w);
- }
-
- /* return the new value
- * for write operation, the following readback ensures the completion of write opration.
- */
- return (R_SBREG(si, &sb->sbtmstatelow));
-}
-
-/* set/clear sbtmstatehigh core-specific flags */
-uint32 sb_coreflagshi(sb_t * sbh, uint32 mask, uint32 val)
-{
- sb_info_t *si;
- sbconfig_t *sb;
- uint32 w;
-
- si = SB_INFO(sbh);
- sb = REGS2SB(si->curmap);
-
- ASSERT((val & ~mask) == 0);
- ASSERT((mask & ~SBTMH_FL_MASK) == 0);
-
- /* mask and set */
- if (mask || val) {
- w = (R_SBREG(si, &sb->sbtmstatehigh) & ~mask) | val;
- W_SBREG(si, &sb->sbtmstatehigh, w);
- }
-
- /* return the new value */
- return (R_SBREG(si, &sb->sbtmstatehigh));
-}
-
-/* Run bist on current core. Caller needs to take care of core-specific bist hazards */
-int sb_corebist(sb_t * sbh)
-{
- uint32 sblo;
- sb_info_t *si;
- sbconfig_t *sb;
- int result = 0;
-
- si = SB_INFO(sbh);
- sb = REGS2SB(si->curmap);
-
- sblo = R_SBREG(si, &sb->sbtmstatelow);
- W_SBREG(si, &sb->sbtmstatelow, (sblo | SBTML_FGC | SBTML_BE));
-
- SPINWAIT(((R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BISTD) == 0),
- 100000);
-
- if (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BISTF)
- result = -1;
-
- W_SBREG(si, &sb->sbtmstatelow, sblo);
-
- return result;
-}
-
-bool sb_iscoreup(sb_t * sbh)
-{
- sb_info_t *si;
- sbconfig_t *sb;
-
- si = SB_INFO(sbh);
- sb = REGS2SB(si->curmap);
-
- return ((R_SBREG(si, &sb->sbtmstatelow) &
- (SBTML_RESET | SBTML_REJ_MASK | SBTML_CLK)) == SBTML_CLK);
-}
-
-/*
- * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation,
- * switch back to the original core, and return the new value.
- *
- * When using the silicon backplane, no fidleing with interrupts or core switches are needed.
- *
- * Also, when using pci/pcie, we can optimize away the core switching for pci registers
- * and (on newer pci cores) chipcommon registers.
- */
-uint sb_corereg(sb_t * sbh, uint coreidx, uint regoff, uint mask, uint val)
-{
- uint origidx = 0;
- uint32 *r = NULL;
- uint w;
- uint intr_val = 0;
- bool fast = FALSE;
- sb_info_t *si;
-
- si = SB_INFO(sbh);
-
- ASSERT(GOODIDX(coreidx));
- ASSERT(regoff < SB_CORE_SIZE);
- ASSERT((val & ~mask) == 0);
-
-#if 0
- if (BUSTYPE(si->sb.bustype) == SB_BUS) {
- /* If internal bus, we can always get at everything */
- fast = TRUE;
- /* map if does not exist */
- if (!si->regs[coreidx]) {
- si->regs[coreidx] =
- (void *)REG_MAP(si->coresba[coreidx], SB_CORE_SIZE);
- ASSERT(GOODREGS(si->regs[coreidx]));
- }
- r = (uint32 *) ((uchar *) si->regs[coreidx] + regoff);
- } else if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
- /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */
-
- if ((si->coreid[coreidx] == SB_CC) &&
- ((si->sb.buscoretype == SB_PCIE)
- || (si->sb.buscorerev >= 13))) {
- /* Chipc registers are mapped at 12KB */
-
- fast = TRUE;
- r = (uint32 *) ((char *)si->curmap +
- PCI_16KB0_CCREGS_OFFSET + regoff);
- } else if (si->sb.buscoreidx == coreidx) {
- /* pci registers are at either in the last 2KB of an 8KB window
- * or, in pcie and pci rev 13 at 8KB
- */
- fast = TRUE;
- if ((si->sb.buscoretype == SB_PCIE)
- || (si->sb.buscorerev >= 13))
- r = (uint32 *) ((char *)si->curmap +
- PCI_16KB0_PCIREGS_OFFSET +
- regoff);
- else
- r = (uint32 *) ((char *)si->curmap +
- ((regoff >= SBCONFIGOFF) ?
- PCI_BAR0_PCISBR_OFFSET :
- PCI_BAR0_PCIREGS_OFFSET)
- + regoff);
- }
- }
-#endif
-
- if (!fast) {
- INTR_OFF(si, intr_val);
-
- /* save current core index */
- origidx = sb_coreidx(&si->sb);
-
- /* switch core */
- r = (uint32 *) ((uchar *) sb_setcoreidx(&si->sb, coreidx) +
- regoff);
- }
- ASSERT(r);
-
- /* mask and set */
- if (mask || val) {
- if (regoff >= SBCONFIGOFF) {
- w = (R_SBREG(si, r) & ~mask) | val;
- W_SBREG(si, r, w);
- } else {
- w = (R_REG(si->osh, r) & ~mask) | val;
- W_REG(si->osh, r, w);
- }
- }
-
- /* readback */
- if (regoff >= SBCONFIGOFF)
- w = R_SBREG(si, r);
- else {
- if ((si->sb.chip == BCM5354_CHIP_ID) &&
- (coreidx == SB_CC_IDX) &&
- (regoff == OFFSETOF(chipcregs_t, watchdog))) {
- w = val;
- } else
- w = R_REG(si->osh, r);
- }
-
- if (!fast) {
- /* restore core index */
- if (origidx != coreidx)
- sb_setcoreidx(&si->sb, origidx);
-
- INTR_RESTORE(si, intr_val);
- }
-
- return (w);
-}
-
-#define DWORD_ALIGN(x) (x & ~(0x03))
-#define BYTE_POS(x) (x & 0x3)
-#define WORD_POS(x) (x & 0x1)
-
-#define BYTE_SHIFT(x) (8 * BYTE_POS(x))
-#define WORD_SHIFT(x) (16 * WORD_POS(x))
-
-#define BYTE_VAL(a, x) ((a >> BYTE_SHIFT(x)) & 0xFF)
-#define WORD_VAL(a, x) ((a >> WORD_SHIFT(x)) & 0xFFFF)
-
-#define read_pci_cfg_byte(a) \
- (BYTE_VAL(OSL_PCI_READ_CONFIG(si->osh, DWORD_ALIGN(a), 4), a) & 0xff)
-
-#define read_pci_cfg_word(a) \
- (WORD_VAL(OSL_PCI_READ_CONFIG(si->osh, DWORD_ALIGN(a), 4), a) & 0xffff)
-
-/* return cap_offset if requested capability exists in the PCI config space */
-static uint8
-sb_find_pci_capability(sb_info_t * si, uint8 req_cap_id, uchar * buf,
- uint32 * buflen)
-{
- uint8 cap_id;
- uint8 cap_ptr = 0;
- uint32 bufsize;
- uint8 byte_val;
-
- if (BUSTYPE(si->sb.bustype) != PCI_BUS)
- goto end;
-
- /* check for Header type 0 */
- byte_val = read_pci_cfg_byte(PCI_CFG_HDR);
- if ((byte_val & 0x7f) != PCI_HEADER_NORMAL)
- goto end;
-
- /* check if the capability pointer field exists */
- byte_val = read_pci_cfg_byte(PCI_CFG_STAT);
- if (!(byte_val & PCI_CAPPTR_PRESENT))
- goto end;
-
- cap_ptr = read_pci_cfg_byte(PCI_CFG_CAPPTR);
- /* check if the capability pointer is 0x00 */
- if (cap_ptr == 0x00)
- goto end;
-
- /* loop thr'u the capability list and see if the pcie capabilty exists */
-
- cap_id = read_pci_cfg_byte(cap_ptr);
-
- while (cap_id != req_cap_id) {
- cap_ptr = read_pci_cfg_byte((cap_ptr + 1));
- if (cap_ptr == 0x00)
- break;
- cap_id = read_pci_cfg_byte(cap_ptr);
- }
- if (cap_id != req_cap_id) {
- goto end;
- }
- /* found the caller requested capability */
- if ((buf != NULL) && (buflen != NULL)) {
- uint8 cap_data;
-
- bufsize = *buflen;
- if (!bufsize)
- goto end;
- *buflen = 0;
- /* copy the cpability data excluding cap ID and next ptr */
- cap_data = cap_ptr + 2;
- if ((bufsize + cap_data) > SZPCR)
- bufsize = SZPCR - cap_data;
- *buflen = bufsize;
- while (bufsize--) {
- *buf = read_pci_cfg_byte(cap_data);
- cap_data++;
- buf++;
- }
- }
- end:
- return cap_ptr;
-}
-
-uint8 sb_pcieclkreq(sb_t * sbh, uint32 mask, uint32 val)
-{
- sb_info_t *si;
- uint32 reg_val;
- uint8 offset;
-
- si = SB_INFO(sbh);
-
- offset = si->pciecap_lcreg_offset;
- if (!offset)
- return 0;
-
- reg_val = OSL_PCI_READ_CONFIG(si->osh, offset, sizeof(uint32));
- /* set operation */
- if (mask) {
- if (val)
- reg_val |= PCIE_CLKREQ_ENAB;
- else
- reg_val &= ~PCIE_CLKREQ_ENAB;
- OSL_PCI_WRITE_CONFIG(si->osh, offset, sizeof(uint32), reg_val);
- reg_val = OSL_PCI_READ_CONFIG(si->osh, offset, sizeof(uint32));
- }
- if (reg_val & PCIE_CLKREQ_ENAB)
- return 1;
- else
- return 0;
-}
-
-#ifdef BCMDBG
-
-uint32 sb_pcielcreg(sb_t * sbh, uint32 mask, uint32 val)
-{
- sb_info_t *si;
- uint32 reg_val;
- uint8 offset;
-
- si = SB_INFO(sbh);
-
- if (!PCIE(si))
- return 0;
-
- offset = si->pciecap_lcreg_offset;
- if (!offset)
- return 0;
-
- /* set operation */
- if (mask)
- OSL_PCI_WRITE_CONFIG(si->osh, offset, sizeof(uint32), val);
-
- reg_val = OSL_PCI_READ_CONFIG(si->osh, offset, sizeof(uint32));
-
- return reg_val;
-}
-
-uint8 sb_pcieL1plldown(sb_t * sbh)
-{
- sb_info_t *si;
- uint intr_val = 0;
- uint origidx;
- uint32 reg_val;
-
- si = SB_INFO(sbh);
-
- if (!PCIE(si))
- return 0;
- if (!((si->sb.buscorerev == 3) || (si->sb.buscorerev == 4)))
- return 0;
-
- if (!sb_pcieclkreq((void *)(uintptr) sbh, 0, 0)) {
- SB_ERROR(("PCIEL1PLLDOWN requires Clkreq be enabled, so enable it\n"));
- sb_pcieclkreq((void *)(uintptr) sbh, 1, 1);
- }
- reg_val = sb_pcielcreg((void *)(uintptr) sbh, 0, 0);
- if (reg_val & PCIE_CAP_LCREG_ASPML0s) {
- SB_ERROR(("PCIEL1PLLDOWN requires L0s to be disabled\n"));
- reg_val &= ~PCIE_CAP_LCREG_ASPML0s;
- sb_pcielcreg((void *)(uintptr) sbh, 1, reg_val);
- } else
- SB_ERROR(("PCIEL1PLLDOWN: L0s is already disabled\n"));
-
- /* turnoff intrs, change core, set original back, turn on intrs back on */
- origidx = si->curidx;
- INTR_OFF(si, intr_val);
- sb_setcore(sbh, SB_PCIE, 0);
-
- sb_pcie_writereg((void *)(uintptr) sbh, (void *)PCIE_PCIEREGS,
- PCIE_DLLP_PCIE11, 0);
-
- sb_setcoreidx(sbh, origidx);
- INTR_RESTORE(si, intr_val);
- return 1;
-}
-#endif /* BCMDBG */
-
-/* return TRUE if PCIE capability exists in the pci config space */
-static bool sb_ispcie(sb_info_t * si)
-{
- uint8 cap_ptr;
-
- cap_ptr = sb_find_pci_capability(si, PCI_CAP_PCIECAP_ID, NULL, NULL);
- if (!cap_ptr)
- return FALSE;
-
- si->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET;
-
- return TRUE;
-}
-
-/* Wake-on-wireless-LAN (WOWL) support functions */
-/* return TRUE if PM capability exists in the pci config space */
-bool sb_pci_pmecap(sb_t * sbh)
-{
- uint8 cap_ptr;
- uint32 pmecap;
- sb_info_t *si;
-
- si = SB_INFO(sbh);
-
- if (si == NULL || !(PCI(si) || PCIE(si)))
- return FALSE;
-
- if (!si->pmecap_offset) {
- cap_ptr =
- sb_find_pci_capability(si, PCI_CAP_POWERMGMTCAP_ID, NULL,
- NULL);
- if (!cap_ptr)
- return FALSE;
-
- si->pmecap_offset = cap_ptr;
-
- pmecap =
- OSL_PCI_READ_CONFIG(si->osh, si->pmecap_offset,
- sizeof(uint32));
-
- /* At least one state can generate PME */
- si->pmecap = (pmecap & PME_CAP_PM_STATES) != 0;
- }
-
- return (si->pmecap);
-}
-
-/* Enable PME generation and disable clkreq */
-void sb_pci_pmeen(sb_t * sbh)
-{
- sb_info_t *si;
- uint32 w;
- si = SB_INFO(sbh);
-
- /* if not pmecapable return */
- if (!sb_pci_pmecap(sbh))
- return;
-
- w = OSL_PCI_READ_CONFIG(si->osh, si->pmecap_offset + PME_CSR_OFFSET,
- sizeof(uint32));
- w |= (PME_CSR_PME_EN);
- OSL_PCI_WRITE_CONFIG(si->osh, si->pmecap_offset + PME_CSR_OFFSET,
- sizeof(uint32), w);
-
- /* Disable clkreq */
- if (si->pr42767_war) {
- sb_pcieclkreq(sbh, 1, 0);
- si->pr42767_war = FALSE;
- } else if (si->sb.pr42780) {
- sb_pcieclkreq(sbh, 1, 1);
- }
-}
-
-/* Disable PME generation, clear the PME status bit if set and
- * return TRUE if PME status set
- */
-bool sb_pci_pmeclr(sb_t * sbh)
-{
- sb_info_t *si;
- uint32 w;
- bool ret = FALSE;
-
- si = SB_INFO(sbh);
-
- if (!sb_pci_pmecap(sbh))
- return ret;
-
- w = OSL_PCI_READ_CONFIG(si->osh, si->pmecap_offset + PME_CSR_OFFSET,
- sizeof(uint32));
-
- SB_ERROR(("sb_pci_pmeclr PMECSR : 0x%x\n", w));
- ret = (w & PME_CSR_PME_STAT) == PME_CSR_PME_STAT;
-
- /* PMESTAT is cleared by writing 1 to it */
- w &= ~(PME_CSR_PME_EN);
-
- OSL_PCI_WRITE_CONFIG(si->osh, si->pmecap_offset + PME_CSR_OFFSET,
- sizeof(uint32), w);
-
- return ret;
-}
-
-/* use pci dev id to determine chip id for chips not having a chipcommon core */
-static uint BCMINITFN(sb_pcidev2chip) (uint pcidev) {
- if ((pcidev >= BCM4710_DEVICE_ID) && (pcidev <= BCM47XX_USB_ID))
- return (BCM4710_CHIP_ID);
- if ((pcidev >= BCM4402_ENET_ID) && (pcidev <= BCM4402_V90_ID))
- return (BCM4402_CHIP_ID);
- if (pcidev == BCM4401_ENET_ID)
- return (BCM4402_CHIP_ID);
- if (pcidev == SDIOH_FPGA_ID)
- return (SDIOH_FPGA_ID);
-
- return (0);
-}
-
-/* Scan the enumeration space to find all cores starting from the given
- * bus 'sbba'. Append coreid and other info to the lists in 'si'. 'sba'
- * is the default core address at chip POR time and 'regs' is the virtual
- * address that the default core is mapped at. 'ncores' is the number of
- * cores expected on bus 'sbba'. It returns the total number of cores
- * starting from bus 'sbba', inclusive.
- */
-
-static void BCMINITFN(sb_scan) (sb_info_t * si) {
- sb_t *sbh;
- uint origidx;
- uint i;
- bool pci;
- bool pcie;
- uint pciidx;
- uint pcieidx;
- uint pcirev;
- uint pcierev;
-
- sbh = (sb_t *) si;
-
- /* numcores should already be set */
- ASSERT((si->numcores > 0) && (si->numcores <= SB_MAXCORES));
-
- /* save current core index */
- origidx = sb_coreidx(&si->sb);
-
- si->sb.buscorerev = NOREV;
- si->sb.buscoreidx = BADIDX;
-
- si->gpioidx = BADIDX;
-
- pci = pcie = FALSE;
- pcirev = pcierev = NOREV;
- pciidx = pcieidx = BADIDX;
-
- for (i = 0; i < si->numcores; i++) {
- sb_setcoreidx(&si->sb, i);
- si->coreid[i] = sb_coreid(&si->sb);
-
- if (si->coreid[i] == SB_PCI) {
- pciidx = i;
- pcirev = sb_corerev(&si->sb);
- pci = TRUE;
- } else if (si->coreid[i] == SB_PCIE) {
- pcieidx = i;
- pcierev = sb_corerev(&si->sb);
- pcie = TRUE;
- } else if (si->coreid[i] == SB_PCMCIA) {
- si->sb.buscorerev = sb_corerev(&si->sb);
- si->sb.buscoretype = si->coreid[i];
- si->sb.buscoreidx = i;
- }
- }
- if (pci && pcie) {
- if (sb_ispcie(si))
- pci = FALSE;
- else
- pcie = FALSE;
- }
- if (pci) {
- si->sb.buscoretype = SB_PCI;
- si->sb.buscorerev = pcirev;
- si->sb.buscoreidx = pciidx;
- } else if (pcie) {
- si->sb.buscoretype = SB_PCIE;
- si->sb.buscorerev = pcierev;
- si->sb.buscoreidx = pcieidx;
- }
-
- /*
- * Find the gpio "controlling core" type and index.
- * Precedence:
- * - if there's a chip common core - use that
- * - else if there's a pci core (rev >= 2) - use that
- * - else there had better be an extif core (4710 only)
- */
- if (GOODIDX(sb_findcoreidx(sbh, SB_CC, 0))) {
- si->gpioidx = sb_findcoreidx(sbh, SB_CC, 0);
- si->gpioid = SB_CC;
- } else if (PCI(si) && (si->sb.buscorerev >= 2)) {
- si->gpioidx = si->sb.buscoreidx;
- si->gpioid = SB_PCI;
- } else if (sb_findcoreidx(sbh, SB_EXTIF, 0)) {
- si->gpioidx = sb_findcoreidx(sbh, SB_EXTIF, 0);
- si->gpioid = SB_EXTIF;
- } else
- ASSERT(si->gpioidx != BADIDX);
-
- /* return to original core index */
- sb_setcoreidx(&si->sb, origidx);
-}
-
-/* may be called with core in reset */
-void sb_detach(sb_t * sbh)
-{
- sb_info_t *si;
- uint idx;
-
- si = SB_INFO(sbh);
-
- if (si == NULL)
- return;
-
- if (BUSTYPE(si->sb.bustype) == SB_BUS)
- for (idx = 0; idx < SB_MAXCORES; idx++)
- if (si->regs[idx]) {
- REG_UNMAP(si->regs[idx]);
- si->regs[idx] = NULL;
- }
-#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SB_BUS)
- if (si != &ksi)
-#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SB_BUS) */
- MFREE(si->osh, si, sizeof(sb_info_t));
-}
-
-
-/* convert chip number to number of i/o cores */
-static uint BCMINITFN(sb_chip2numcores) (uint chip) {
- if (chip == BCM4710_CHIP_ID)
- return (9);
- if (chip == BCM4402_CHIP_ID)
- return (3);
- if (chip == BCM4306_CHIP_ID) /* < 4306c0 */
- return (6);
- if (chip == BCM4704_CHIP_ID)
- return (9);
- if (chip == BCM5365_CHIP_ID)
- return (7);
- if (chip == SDIOH_FPGA_ID)
- return (2);
-
- SB_ERROR(("sb_chip2numcores: unsupported chip 0x%x\n", chip));
- ASSERT(0);
- return (1);
-}
-
-/* return index of coreid or BADIDX if not found */
-uint sb_findcoreidx(sb_t * sbh, uint coreid, uint coreunit)
-{
- sb_info_t *si;
- uint found;
- uint i;
-
- si = SB_INFO(sbh);
-
- found = 0;
-
- for (i = 0; i < si->numcores; i++)
- if (si->coreid[i] == coreid) {
- if (found == coreunit)
- return (i);
- found++;
- }
-
- return (BADIDX);
-}
-
-/*
- * this function changes logical "focus" to the indiciated core,
- * must be called with interrupt off.
- * Moreover, callers should keep interrupts off during switching out of and back to d11 core
- */
-void *sb_setcoreidx(sb_t * sbh, uint coreidx)
-{
- sb_info_t *si;
- uint32 sbaddr;
- uint8 tmp;
-
- si = SB_INFO(sbh);
-
- if (coreidx >= si->numcores)
- return (NULL);
-
- /*
- * If the user has provided an interrupt mask enabled function,
- * then assert interrupts are disabled before switching the core.
- */
- ASSERT((si->intrsenabled_fn == NULL)
- || !(*(si)->intrsenabled_fn) ((si)->intr_arg));
-
- sbaddr = SB_ENUM_BASE + (coreidx * SB_CORE_SIZE);
-
- switch (BUSTYPE(si->sb.bustype)) {
- case SB_BUS:
- /* map new one */
- if (!si->regs[coreidx]) {
- si->regs[coreidx] =
- (void *)REG_MAP(sbaddr, SB_CORE_SIZE);
- ASSERT(GOODREGS(si->regs[coreidx]));
- }
- si->curmap = si->regs[coreidx];
- break;
-
- case PCI_BUS:
- /* point bar0 window */
- OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, 4, sbaddr);
- break;
-
- case PCMCIA_BUS:
- tmp = (sbaddr >> 12) & 0x0f;
- OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_ADDR0, &tmp, 1);
- tmp = (sbaddr >> 16) & 0xff;
- OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_ADDR1, &tmp, 1);
- tmp = (sbaddr >> 24) & 0xff;
- OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_ADDR2, &tmp, 1);
- break;
-#ifdef BCMJTAG
- case JTAG_BUS:
- /* map new one */
- if (!si->regs[coreidx]) {
- si->regs[coreidx] = (void *)sbaddr;
- ASSERT(GOODREGS(si->regs[coreidx]));
- }
- si->curmap = si->regs[coreidx];
- break;
-#endif /* BCMJTAG */
- }
-
- si->curidx = coreidx;
-
- return (si->curmap);
-}
-
-/*
- * this function changes logical "focus" to the indiciated core,
- * must be called with interrupt off.
- * Moreover, callers should keep interrupts off during switching out of and back to d11 core
- */
-void *sb_setcore(sb_t * sbh, uint coreid, uint coreunit)
-{
- uint idx;
-
- idx = sb_findcoreidx(sbh, coreid, coreunit);
- if (!GOODIDX(idx))
- return (NULL);
-
- return (sb_setcoreidx(sbh, idx));
-}
-
-/* return chip number */
-uint BCMINITFN(sb_chip) (sb_t * sbh) {
- sb_info_t *si;
-
- si = SB_INFO(sbh);
- return (si->sb.chip);
-}
-
-/* return chip revision number */
-uint BCMINITFN(sb_chiprev) (sb_t * sbh) {
- sb_info_t *si;
-
- si = SB_INFO(sbh);
- return (si->sb.chiprev);
-}
-
-/* return chip common revision number */
-uint BCMINITFN(sb_chipcrev) (sb_t * sbh) {
- sb_info_t *si;
-
- si = SB_INFO(sbh);
- return (si->sb.ccrev);
-}
-
-/* return chip package option */
-uint BCMINITFN(sb_chippkg) (sb_t * sbh) {
- sb_info_t *si;
-
- si = SB_INFO(sbh);
- return (si->sb.chippkg);
-}
-
-/* return PCI core rev. */
-uint BCMINITFN(sb_pcirev) (sb_t * sbh) {
- sb_info_t *si;
-
- si = SB_INFO(sbh);
- return (si->sb.buscorerev);
-}
-
-bool BCMINITFN(sb_war16165) (sb_t * sbh) {
- sb_info_t *si;
-
- si = SB_INFO(sbh);
-
- return (PCI(si) && (si->sb.buscorerev <= 10));
-}
-
-static void BCMINITFN(sb_war30841) (sb_info_t * si) {
- sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128);
- sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100);
- sb_pcie_mdiowrite(si, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466);
-}
-
-/* return PCMCIA core rev. */
-uint BCMINITFN(sb_pcmciarev) (sb_t * sbh) {
- sb_info_t *si;
-
- si = SB_INFO(sbh);
- return (si->sb.buscorerev);
-}
-
-/* return board vendor id */
-uint BCMINITFN(sb_boardvendor) (sb_t * sbh) {
- sb_info_t *si;
-
- si = SB_INFO(sbh);
- return (si->sb.boardvendor);
-}
-
-/* return boardtype */
-uint BCMINITFN(sb_boardtype) (sb_t * sbh) {
- sb_info_t *si;
- char *var;
-
- si = SB_INFO(sbh);
-
- if (BUSTYPE(si->sb.bustype) == SB_BUS && si->sb.boardtype == 0xffff) {
- /* boardtype format is a hex string */
- si->sb.boardtype = getintvar(NULL, "boardtype");
-
- /* backward compatibility for older boardtype string format */
- if ((si->sb.boardtype == 0)
- && (var = getvar(NULL, "boardtype"))) {
- if (!strcmp(var, "bcm94710dev"))
- si->sb.boardtype = BCM94710D_BOARD;
- else if (!strcmp(var, "bcm94710ap"))
- si->sb.boardtype = BCM94710AP_BOARD;
- else if (!strcmp(var, "bu4710"))
- si->sb.boardtype = BU4710_BOARD;
- else if (!strcmp(var, "bcm94702mn"))
- si->sb.boardtype = BCM94702MN_BOARD;
- else if (!strcmp(var, "bcm94710r1"))
- si->sb.boardtype = BCM94710R1_BOARD;
- else if (!strcmp(var, "bcm94710r4"))
- si->sb.boardtype = BCM94710R4_BOARD;
- else if (!strcmp(var, "bcm94702cpci"))
- si->sb.boardtype = BCM94702CPCI_BOARD;
- else if (!strcmp(var, "bcm95380_rr"))
- si->sb.boardtype = BCM95380RR_BOARD;
- }
- }
-
- return (si->sb.boardtype);
-}
-
-/* return bus type of sbh device */
-uint sb_bus(sb_t * sbh)
-{
- sb_info_t *si;
-
- si = SB_INFO(sbh);
- return (si->sb.bustype);
-}
-
-/* return bus core type */
-uint sb_buscoretype(sb_t * sbh)
-{
- sb_info_t *si;
-
- si = SB_INFO(sbh);
-
- return (si->sb.buscoretype);
-}
-
-/* return bus core revision */
-uint sb_buscorerev(sb_t * sbh)
-{
- sb_info_t *si;
- si = SB_INFO(sbh);
-
- return (si->sb.buscorerev);
-}
-
-/* return list of found cores */
-uint sb_corelist(sb_t * sbh, uint coreid[])
-{
- sb_info_t *si;
-
- si = SB_INFO(sbh);
-
- bcopy((uchar *) si->coreid, (uchar *) coreid,
- (si->numcores * sizeof(uint)));
- return (si->numcores);
-}
-
-/* return current register mapping */
-void *sb_coreregs(sb_t * sbh)
-{
- sb_info_t *si;
-
- si = SB_INFO(sbh);
- ASSERT(GOODREGS(si->curmap));
-
- return (si->curmap);
-}
-
-#if defined(BCMDBG_ASSERT)
-/* traverse all cores to find and clear source of serror */
-static void sb_serr_clear(sb_info_t * si)
-{
- sbconfig_t *sb;
- uint origidx;
- uint i, intr_val = 0;
- void *corereg = NULL;
-
- INTR_OFF(si, intr_val);
- origidx = sb_coreidx(&si->sb);
-
- for (i = 0; i < si->numcores; i++) {
- corereg = sb_setcoreidx(&si->sb, i);
- if (NULL != corereg) {
- sb = REGS2SB(corereg);
- if ((R_SBREG(si, &sb->sbtmstatehigh)) & SBTMH_SERR) {
- AND_SBREG(si, &sb->sbtmstatehigh, ~SBTMH_SERR);
- SB_ERROR(("sb_serr_clear: SError at core 0x%x\n", sb_coreid(&si->sb)));
- }
- }
- }
-
- sb_setcoreidx(&si->sb, origidx);
- INTR_RESTORE(si, intr_val);
-}
-
-/*
- * Check if any inband, outband or timeout errors has happened and clear them.
- * Must be called with chip clk on !
- */
-bool sb_taclear(sb_t * sbh)
-{
- sb_info_t *si;
- sbconfig_t *sb;
- uint origidx;
- uint intr_val = 0;
- bool rc = FALSE;
- uint32 inband = 0, serror = 0, timeout = 0;
- void *corereg = NULL;
- volatile uint32 imstate, tmstate;
-
- si = SB_INFO(sbh);
-
- if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
- volatile uint32 stcmd;
-
- /* inband error is Target abort for PCI */
- stcmd =
- OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_CMD, sizeof(uint32));
- inband = stcmd & PCI_CFG_CMD_STAT_TA;
- if (inband) {
-#ifdef BCMDBG
- SB_ERROR(("inband:\n"));
- sb_viewall((void *)si);
-#endif
- OSL_PCI_WRITE_CONFIG(si->osh, PCI_CFG_CMD,
- sizeof(uint32), stcmd);
- }
-
- /* serror */
- stcmd =
- OSL_PCI_READ_CONFIG(si->osh, PCI_INT_STATUS,
- sizeof(uint32));
- serror = stcmd & PCI_SBIM_STATUS_SERR;
- if (serror) {
-#ifdef BCMDBG
- SB_ERROR(("serror:\n"));
- sb_viewall((void *)si);
-#endif
- sb_serr_clear(si);
- OSL_PCI_WRITE_CONFIG(si->osh, PCI_INT_STATUS,
- sizeof(uint32), stcmd);
- }
-
- /* timeout */
- imstate = sb_corereg(sbh, si->sb.buscoreidx,
- SBCONFIGOFF + OFFSETOF(sbconfig_t,
- sbimstate), 0, 0);
- if ((imstate != 0xffffffff) && (imstate & (SBIM_IBE | SBIM_TO))) {
- sb_corereg(sbh, si->sb.buscoreidx,
- SBCONFIGOFF + OFFSETOF(sbconfig_t,
- sbimstate), ~0,
- (imstate & ~(SBIM_IBE | SBIM_TO)));
- /* inband = imstate & SBIM_IBE; same as TA above */
- timeout = imstate & SBIM_TO;
- if (timeout) {
-#ifdef BCMDBG
- SB_ERROR(("timeout:\n"));
- sb_viewall((void *)si);
-#endif
- }
- }
-
- if (inband) {
- /* dump errlog for sonics >= 2.3 */
- if (si->sb.sonicsrev == SONICS_2_2) ;
- else {
- uint32 imerrlog, imerrloga;
- imerrlog =
- sb_corereg(sbh, si->sb.buscoreidx,
- SBIMERRLOG, 0, 0);
- if (imerrlog & SBTMEL_EC) {
- imerrloga =
- sb_corereg(sbh, si->sb.buscoreidx,
- SBIMERRLOGA, 0, 0);
- /* clear errlog */
- sb_corereg(sbh, si->sb.buscoreidx,
- SBIMERRLOG, ~0, 0);
- SB_ERROR(("sb_taclear: ImErrLog 0x%x, ImErrLogA 0x%x\n", imerrlog, imerrloga));
- }
- }
- }
-
- } else if (BUSTYPE(si->sb.bustype) == PCMCIA_BUS) {
-
- INTR_OFF(si, intr_val);
- origidx = sb_coreidx(sbh);
-
- corereg = sb_setcore(sbh, SB_PCMCIA, 0);
- if (NULL != corereg) {
- sb = REGS2SB(corereg);
-
- imstate = R_SBREG(si, &sb->sbimstate);
- /* handle surprise removal */
- if ((imstate != 0xffffffff)
- && (imstate & (SBIM_IBE | SBIM_TO))) {
- AND_SBREG(si, &sb->sbimstate,
- ~(SBIM_IBE | SBIM_TO));
- inband = imstate & SBIM_IBE;
- timeout = imstate & SBIM_TO;
- }
- tmstate = R_SBREG(si, &sb->sbtmstatehigh);
- if ((tmstate != 0xffffffff)
- && (tmstate & SBTMH_INT_STATUS)) {
- if (!inband) {
- serror = 1;
- sb_serr_clear(si);
- }
- OR_SBREG(si, &sb->sbtmstatelow, SBTML_INT_ACK);
- AND_SBREG(si, &sb->sbtmstatelow,
- ~SBTML_INT_ACK);
- }
- }
- sb_setcoreidx(sbh, origidx);
- INTR_RESTORE(si, intr_val);
-
- }
-
- if (inband | timeout | serror) {
- rc = TRUE;
- SB_ERROR(("sb_taclear: inband 0x%x, serror 0x%x, timeout 0x%x!\n", inband, serror, timeout));
- }
-
- return (rc);
-}
-#endif /* BCMDBG */
-
-/* do buffered registers update */
-void sb_commit(sb_t * sbh)
-{
- sb_info_t *si;
- uint origidx;
- uint intr_val = 0;
-
- si = SB_INFO(sbh);
-
- origidx = si->curidx;
- ASSERT(GOODIDX(origidx));
-
- INTR_OFF(si, intr_val);
-
- /* switch over to chipcommon core if there is one, else use pci */
- if (si->sb.ccrev != NOREV) {
- chipcregs_t *ccregs = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0);
-
- /* do the buffer registers update */
- W_REG(si->osh, &ccregs->broadcastaddress, SB_COMMIT);
- W_REG(si->osh, &ccregs->broadcastdata, 0x0);
- } else if (PCI(si)) {
- sbpciregs_t *pciregs =
- (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0);
-
- /* do the buffer registers update */
- W_REG(si->osh, &pciregs->bcastaddr, SB_COMMIT);
- W_REG(si->osh, &pciregs->bcastdata, 0x0);
- } else
- ASSERT(0);
-
- /* restore core index */
- sb_setcoreidx(sbh, origidx);
- INTR_RESTORE(si, intr_val);
-}
-
-/* reset and re-enable a core
- * inputs:
- * bits - core specific bits that are set during and after reset sequence
- * resetbits - core specific bits that are set only during reset sequence
- */
-void sb_core_reset(sb_t * sbh, uint32 bits, uint32 resetbits)
-{
- sb_info_t *si;
- sbconfig_t *sb;
- volatile uint32 dummy;
-
- si = SB_INFO(sbh);
- ASSERT(GOODREGS(si->curmap));
- sb = REGS2SB(si->curmap);
-
- /*
- * Must do the disable sequence first to work for arbitrary current core state.
- */
- sb_core_disable(sbh, (bits | resetbits));
-
- /*
- * Now do the initialization sequence.
- */
-
- /* set reset while enabling the clock and forcing them on throughout the core */
- W_SBREG(si, &sb->sbtmstatelow,
- (SBTML_FGC | SBTML_CLK | SBTML_RESET | bits | resetbits));
- dummy = R_SBREG(si, &sb->sbtmstatelow);
- OSL_DELAY(1);
-
- if (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_SERR) {
- W_SBREG(si, &sb->sbtmstatehigh, 0);
- }
- if ((dummy = R_SBREG(si, &sb->sbimstate)) & (SBIM_IBE | SBIM_TO)) {
- AND_SBREG(si, &sb->sbimstate, ~(SBIM_IBE | SBIM_TO));
- }
-
- /* clear reset and allow it to propagate throughout the core */
- W_SBREG(si, &sb->sbtmstatelow, (SBTML_FGC | SBTML_CLK | bits));
- dummy = R_SBREG(si, &sb->sbtmstatelow);
- OSL_DELAY(1);
-
- /* leave clock enabled */
- W_SBREG(si, &sb->sbtmstatelow, (SBTML_CLK | bits));
- dummy = R_SBREG(si, &sb->sbtmstatelow);
- OSL_DELAY(1);
-}
-
-void sb_core_tofixup(sb_t * sbh)
-{
- sb_info_t *si;
- sbconfig_t *sb;
-
- si = SB_INFO(sbh);
-
- if ((BUSTYPE(si->sb.bustype) != PCI_BUS) || PCIE(si) ||
- (PCI(si) && (si->sb.buscorerev >= 5)))
- return;
-
- ASSERT(GOODREGS(si->curmap));
- sb = REGS2SB(si->curmap);
-
- if (BUSTYPE(si->sb.bustype) == SB_BUS) {
- SET_SBREG(si, &sb->sbimconfiglow,
- SBIMCL_RTO_MASK | SBIMCL_STO_MASK,
- (0x5 << SBIMCL_RTO_SHIFT) | 0x3);
- } else {
- if (sb_coreid(sbh) == SB_PCI) {
- SET_SBREG(si, &sb->sbimconfiglow,
- SBIMCL_RTO_MASK | SBIMCL_STO_MASK,
- (0x3 << SBIMCL_RTO_SHIFT) | 0x2);
- } else {
- SET_SBREG(si, &sb->sbimconfiglow,
- (SBIMCL_RTO_MASK | SBIMCL_STO_MASK), 0);
- }
- }
-
- sb_commit(sbh);
-}
-
-/*
- * Set the initiator timeout for the "master core".
- * The master core is defined to be the core in control
- * of the chip and so it issues accesses to non-memory
- * locations (Because of dma *any* core can access memeory).
- *
- * The routine uses the bus to decide who is the master:
- * SB_BUS => mips
- * JTAG_BUS => chipc
- * PCI_BUS => pci or pcie
- * PCMCIA_BUS => pcmcia
- * SDIO_BUS => pcmcia
- *
- * This routine exists so callers can disable initiator
- * timeouts so accesses to very slow devices like otp
- * won't cause an abort. The routine allows arbitrary
- * settings of the service and request timeouts, though.
- *
- * Returns the timeout state before changing it or -1
- * on error.
- */
-
-#define TO_MASK (SBIMCL_RTO_MASK | SBIMCL_STO_MASK)
-
-uint32 sb_set_initiator_to(sb_t * sbh, uint32 to, uint idx)
-{
- sb_info_t *si;
- uint origidx;
- uint intr_val = 0;
- uint32 tmp, ret = 0xffffffff;
- sbconfig_t *sb;
-
- si = SB_INFO(sbh);
-
- if ((to & ~TO_MASK) != 0)
- return ret;
-
- /* Figure out the master core */
- if (idx == BADIDX) {
- switch (BUSTYPE(si->sb.bustype)) {
- case PCI_BUS:
- idx = si->sb.buscoreidx;
- break;
- case JTAG_BUS:
- idx = SB_CC_IDX;
- break;
- case PCMCIA_BUS:
- case SDIO_BUS:
- idx = sb_findcoreidx(sbh, SB_PCMCIA, 0);
- break;
- case SB_BUS:
- if ((idx = sb_findcoreidx(sbh, SB_MIPS33, 0)) == BADIDX)
- idx = sb_findcoreidx(sbh, SB_MIPS, 0);
- break;
- default:
- ASSERT(0);
- }
- if (idx == BADIDX)
- return ret;
- }
-
- INTR_OFF(si, intr_val);
- origidx = sb_coreidx(sbh);
-
- sb = REGS2SB(sb_setcoreidx(sbh, idx));
-
- tmp = R_SBREG(si, &sb->sbimconfiglow);
- ret = tmp & TO_MASK;
- W_SBREG(si, &sb->sbimconfiglow, (tmp & ~TO_MASK) | to);
-
- sb_commit(sbh);
- sb_setcoreidx(sbh, origidx);
- INTR_RESTORE(si, intr_val);
- return ret;
-}
-
-void sb_core_disable(sb_t * sbh, uint32 bits)
-{
- sb_info_t *si;
- volatile uint32 dummy;
- uint32 rej;
- sbconfig_t *sb;
-
- si = SB_INFO(sbh);
-
- ASSERT(GOODREGS(si->curmap));
- sb = REGS2SB(si->curmap);
-
- /* if core is already in reset, just return */
- if (R_SBREG(si, &sb->sbtmstatelow) & SBTML_RESET)
- return;
-
- /* reject value changed between sonics 2.2 and 2.3 */
- if (si->sb.sonicsrev == SONICS_2_2)
- rej = (1 << SBTML_REJ_SHIFT);
- else
- rej = (2 << SBTML_REJ_SHIFT);
-
- /* if clocks are not enabled, put into reset and return */
- if ((R_SBREG(si, &sb->sbtmstatelow) & SBTML_CLK) == 0)
- goto disable;
-
- /* set target reject and spin until busy is clear (preserve core-specific bits) */
- OR_SBREG(si, &sb->sbtmstatelow, rej);
- dummy = R_SBREG(si, &sb->sbtmstatelow);
- OSL_DELAY(1);
- SPINWAIT((R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BUSY), 100000);
- if (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_BUSY)
- SB_ERROR(("%s: target state still busy\n", __FUNCTION__));
-
- if (R_SBREG(si, &sb->sbidlow) & SBIDL_INIT) {
- OR_SBREG(si, &sb->sbimstate, SBIM_RJ);
- dummy = R_SBREG(si, &sb->sbimstate);
- OSL_DELAY(1);
- SPINWAIT((R_SBREG(si, &sb->sbimstate) & SBIM_BY), 100000);
- }
-
- /* set reset and reject while enabling the clocks */
- W_SBREG(si, &sb->sbtmstatelow,
- (bits | SBTML_FGC | SBTML_CLK | rej | SBTML_RESET));
- dummy = R_SBREG(si, &sb->sbtmstatelow);
- OSL_DELAY(10);
-
- /* don't forget to clear the initiator reject bit */
- if (R_SBREG(si, &sb->sbidlow) & SBIDL_INIT)
- AND_SBREG(si, &sb->sbimstate, ~SBIM_RJ);
-
- disable:
- /* leave reset and reject asserted */
- W_SBREG(si, &sb->sbtmstatelow, (bits | rej | SBTML_RESET));
- OSL_DELAY(1);
-}
-
-/* set chip watchdog reset timer to fire in 'ticks' backplane cycles */
-void sb_watchdog(sb_t * sbh, uint ticks)
-{
- sb_info_t *si = SB_INFO(sbh);
-
- /* make sure we come up in fast clock mode; or if clearing, clear clock */
- if (ticks)
- sb_clkctl_clk(sbh, CLK_FAST);
- else
- sb_clkctl_clk(sbh, CLK_DYNAMIC);
-
- if (sbh->chip == BCM4328_CHIP_ID && ticks != 0)
- sb_corereg(sbh, SB_CC_IDX, OFFSETOF(chipcregs_t, min_res_mask),
- PMURES_BIT(RES4328_ROM_SWITCH),
- PMURES_BIT(RES4328_ROM_SWITCH));
-
- /* instant NMI */
- switch (si->gpioid) {
- case SB_CC:
- sb_corereg(sbh, SB_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0,
- ticks);
- break;
- case SB_EXTIF:
- sb_corereg(sbh, si->gpioidx, OFFSETOF(extifregs_t, watchdog),
- ~0, ticks);
- break;
- }
-}
-
-/* initialize the pcmcia core */
-void sb_pcmcia_init(sb_t * sbh)
-{
- sb_info_t *si;
- uint8 cor = 0;
-
- si = SB_INFO(sbh);
-
- /* enable d11 mac interrupts */
- OSL_PCMCIA_READ_ATTR(si->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1);
- cor |= COR_IRQEN | COR_FUNEN;
- OSL_PCMCIA_WRITE_ATTR(si->osh, PCMCIA_FCR0 + PCMCIA_COR, &cor, 1);
-
-}
-
-void BCMINITFN(sb_pci_up) (sb_t * sbh) {
- sb_info_t *si = SB_INFO(sbh);
- if (si->gpioid == SB_EXTIF)
- return;
-
- /* if not pci bus, we're done */
- if (BUSTYPE(si->sb.bustype) != PCI_BUS)
- return;
-
- if (FORCEHT_WAR32414(si))
- sb_war32414_forceHT(sbh, 1);
-
- if (PCIE_ASPMWARS(si) || si->sb.pr42780)
- sb_pcieclkreq(sbh, 1, 0);
-
- if (PCIE(si) &&
- (((si->sb.chip == BCM4311_CHIP_ID) && (si->sb.chiprev == 2)) ||
- ((si->sb.chip == BCM4312_CHIP_ID) && (si->sb.chiprev == 0))))
- sb_set_initiator_to((void *)si, 0x3,
- sb_findcoreidx((void *)si, SB_D11, 0));
-}
-
-/* Unconfigure and/or apply various WARs when system is going to sleep mode */
-void BCMUNINITFN(sb_pci_sleep) (sb_t * sbh) {
- sb_info_t *si = SB_INFO(sbh);
- if (si->gpioid == SB_EXTIF)
- return;
- uint32 w;
-
- /* if not pci bus, we're done */
- if (!PCIE(si) || !PCIE_ASPMWARS(si))
- return;
-
- w = OSL_PCI_READ_CONFIG(si->osh, si->pciecap_lcreg_offset,
- sizeof(uint32));
- w &= ~PCIE_CAP_LCREG_ASPML1;
- OSL_PCI_WRITE_CONFIG(si->osh, si->pciecap_lcreg_offset, sizeof(uint32),
- w);
-}
-
-/* Unconfigure and/or apply various WARs when going down */
-void BCMINITFN(sb_pci_down) (sb_t * sbh) {
- sb_info_t *si = SB_INFO(sbh);
- if (si->gpioid == SB_EXTIF)
- return;
-
- /* if not pci bus, we're done */
- if (BUSTYPE(si->sb.bustype) != PCI_BUS)
- return;
-
- if (FORCEHT_WAR32414(si))
- sb_war32414_forceHT(sbh, 0);
-
- if (si->pr42767_war) {
- sb_pcieclkreq(sbh, 1, 1);
- si->pr42767_war = FALSE;
- } else if (si->sb.pr42780) {
- sb_pcieclkreq(sbh, 1, 1);
- }
-}
-
-static void BCMINITFN(sb_war42767_clkreq) (sb_t * sbh) {
- sbpcieregs_t *pcieregs;
- uint16 val16, *reg16;
- sb_info_t *si;
-
- si = SB_INFO(sbh);
-
- /* if not pcie bus, we're done */
- if (!PCIE(si) || !PCIE_ASPMWARS(si))
- return;
-
- pcieregs = (sbpcieregs_t *) sb_setcoreidx(sbh, si->sb.buscoreidx);
- reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET];
- val16 = R_REG(si->osh, reg16);
- /* if clockreq is not advertized advertize it */
- if (!si->pcie_war_ovr) {
- val16 |= SRSH_CLKREQ_ENB;
- si->pr42767_war = TRUE;
-
- si->sb.pr42780 = TRUE;
- } else
- val16 &= ~SRSH_CLKREQ_ENB;
- W_REG(si->osh, reg16, val16);
-}
-
-static void BCMINITFN(sb_war42767) (sb_t * sbh) {
- uint32 w = 0;
- sb_info_t *si;
-
- si = SB_INFO(sbh);
-
- /* if not pcie bus, we're done */
- if (!PCIE(si) || !PCIE_ASPMWARS(si))
- return;
-
- sb_pcie_mdioread(si, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w);
- if (w & PLL_CTRL_FREQDET_EN) {
- w &= ~PLL_CTRL_FREQDET_EN;
- sb_pcie_mdiowrite(si, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w);
- }
-}
-
-/*
- * Configure the pci core for pci client (NIC) action
- * coremask is the bitvec of cores by index to be enabled.
- */
-void BCMINITFN(sb_pci_setup) (sb_t * sbh, uint coremask) {
- sb_info_t *si;
- sbconfig_t *sb;
- sbpciregs_t *pciregs;
- uint32 sbflag;
- uint32 w;
- uint idx;
-
- si = SB_INFO(sbh);
-
- /* if not pci bus, we're done */
- if (BUSTYPE(si->sb.bustype) != PCI_BUS)
- return;
-
- ASSERT(PCI(si) || PCIE(si));
- ASSERT(si->sb.buscoreidx != BADIDX);
-
- /* get current core index */
- idx = si->curidx;
-
- /* we interrupt on this backplane flag number */
- ASSERT(GOODREGS(si->curmap));
- sb = REGS2SB(si->curmap);
- sbflag = R_SBREG(si, &sb->sbtpsflag) & SBTPS_NUM0_MASK;
-
- /* switch over to pci core */
- pciregs = (sbpciregs_t *) sb_setcoreidx(sbh, si->sb.buscoreidx);
- sb = REGS2SB(pciregs);
-
- /*
- * Enable sb->pci interrupts. Assume
- * PCI rev 2.3 support was added in pci core rev 6 and things changed..
- */
- if (PCIE(si) || (PCI(si) && ((si->sb.buscorerev) >= 6))) {
- /* pci config write to set this core bit in PCIIntMask */
- w = OSL_PCI_READ_CONFIG(si->osh, PCI_INT_MASK, sizeof(uint32));
- w |= (coremask << PCI_SBIM_SHIFT);
- OSL_PCI_WRITE_CONFIG(si->osh, PCI_INT_MASK, sizeof(uint32), w);
- } else {
- /* set sbintvec bit for our flag number */
- OR_SBREG(si, &sb->sbintvec, (1 << sbflag));
- }
-
- if (PCI(si)) {
- OR_REG(si->osh, &pciregs->sbtopci2,
- (SBTOPCI_PREF | SBTOPCI_BURST));
- if (si->sb.buscorerev >= 11)
- OR_REG(si->osh, &pciregs->sbtopci2,
- SBTOPCI_RC_READMULTI);
- if (si->sb.buscorerev < 5) {
- SET_SBREG(si, &sb->sbimconfiglow,
- SBIMCL_RTO_MASK | SBIMCL_STO_MASK,
- (0x3 << SBIMCL_RTO_SHIFT) | 0x2);
- sb_commit(sbh);
- }
- }
-
- /* PCIE workarounds */
- if (PCIE(si)) {
- if ((si->sb.buscorerev == 0) || (si->sb.buscorerev == 1)) {
- w = sb_pcie_readreg((void *)(uintptr) sbh,
- (void *)(uintptr) PCIE_PCIEREGS,
- PCIE_TLP_WORKAROUNDSREG);
- w |= 0x8;
- sb_pcie_writereg((void *)(uintptr) sbh,
- (void *)(uintptr) PCIE_PCIEREGS,
- PCIE_TLP_WORKAROUNDSREG, w);
- }
-
- if (si->sb.buscorerev == 1) {
- w = sb_pcie_readreg((void *)(uintptr) sbh,
- (void *)(uintptr) PCIE_PCIEREGS,
- PCIE_DLLP_LCREG);
- w |= (0x40);
- sb_pcie_writereg((void *)(uintptr) sbh,
- (void *)(uintptr) PCIE_PCIEREGS,
- PCIE_DLLP_LCREG, w);
- }
-
- if (si->sb.buscorerev == 0)
- sb_war30841(si);
-
- if ((si->sb.buscorerev >= 3) && (si->sb.buscorerev <= 5)) {
- w = sb_pcie_readreg((void *)(uintptr) sbh,
- (void *)(uintptr) PCIE_PCIEREGS,
- PCIE_DLLP_PMTHRESHREG);
- w &= ~(PCIE_L1THRESHOLDTIME_MASK);
- w |= (PCIE_L1THRESHOLD_WARVAL <<
- PCIE_L1THRESHOLDTIME_SHIFT);
- sb_pcie_writereg((void *)(uintptr) sbh,
- (void *)(uintptr) PCIE_PCIEREGS,
- PCIE_DLLP_PMTHRESHREG, w);
-
- sb_war43448(sbh);
-
- sb_war42767(sbh);
-
- sb_war43448_aspm(sbh);
- sb_war42767_clkreq(sbh);
- }
- }
-
- /* switch back to previous core */
- sb_setcoreidx(sbh, idx);
-}
-
-uint32 sb_base(uint32 admatch)
-{
- uint32 base;
- uint type;
-
- type = admatch & SBAM_TYPE_MASK;
- ASSERT(type < 3);
-
- base = 0;
-
- if (type == 0) {
- base = admatch & SBAM_BASE0_MASK;
- } else if (type == 1) {
- ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
- base = admatch & SBAM_BASE1_MASK;
- } else if (type == 2) {
- ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
- base = admatch & SBAM_BASE2_MASK;
- }
-
- return (base);
-}
-
-uint32 sb_size(uint32 admatch)
-{
- uint32 size;
- uint type;
-
- type = admatch & SBAM_TYPE_MASK;
- ASSERT(type < 3);
-
- size = 0;
-
- if (type == 0) {
- size =
- 1 << (((admatch & SBAM_ADINT0_MASK) >> SBAM_ADINT0_SHIFT) +
- 1);
- } else if (type == 1) {
- ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
- size =
- 1 << (((admatch & SBAM_ADINT1_MASK) >> SBAM_ADINT1_SHIFT) +
- 1);
- } else if (type == 2) {
- ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */
- size =
- 1 << (((admatch & SBAM_ADINT2_MASK) >> SBAM_ADINT2_SHIFT) +
- 1);
- }
-
- return (size);
-}
-
-/* return the core-type instantiation # of the current core */
-uint sb_coreunit(sb_t * sbh)
-{
- sb_info_t *si;
- uint idx;
- uint coreid;
- uint coreunit;
- uint i;
-
- si = SB_INFO(sbh);
- coreunit = 0;
-
- idx = si->curidx;
-
- ASSERT(GOODREGS(si->curmap));
- coreid = sb_coreid(sbh);
-
- /* count the cores of our type */
- for (i = 0; i < idx; i++)
- if (si->coreid[i] == coreid)
- coreunit++;
-
- return (coreunit);
-}
-
-static uint32 BCMINITFN(factor6) (uint32 x) {
- switch (x) {
- case CC_F6_2:
- return 2;
- case CC_F6_3:
- return 3;
- case CC_F6_4:
- return 4;
- case CC_F6_5:
- return 5;
- case CC_F6_6:
- return 6;
- case CC_F6_7:
- return 7;
- default:
- return 0;
- }
-}
-
-/* calculate the speed the SB would run at given a set of clockcontrol values */
-uint32 BCMINITFN(sb_clock_rate) (uint32 pll_type, uint32 n, uint32 m) {
- uint32 n1, n2, clock, m1, m2, m3, mc;
-
- n1 = n & CN_N1_MASK;
- n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
-
- if (pll_type == PLL_TYPE6) {
- if (m & CC_T6_MMASK)
- return CC_T6_M1;
- else
- return CC_T6_M0;
- } else if ((pll_type == PLL_TYPE1) ||
- (pll_type == PLL_TYPE3) ||
- (pll_type == PLL_TYPE4) || (pll_type == PLL_TYPE7)) {
- n1 = factor6(n1);
- n2 += CC_F5_BIAS;
- } else if (pll_type == PLL_TYPE2) {
- n1 += CC_T2_BIAS;
- n2 += CC_T2_BIAS;
- ASSERT((n1 >= 2) && (n1 <= 7));
- ASSERT((n2 >= 5) && (n2 <= 23));
- } else if (pll_type == PLL_TYPE5) {
- return (100000000);
- } else
- ASSERT(0);
- /* PLL types 3 and 7 use BASE2 (25Mhz) */
- if ((pll_type == PLL_TYPE3) || (pll_type == PLL_TYPE7)) {
- clock = CC_CLOCK_BASE2 * n1 * n2;
- } else
- clock = CC_CLOCK_BASE1 * n1 * n2;
-
- if (clock == 0)
- return 0;
-
- m1 = m & CC_M1_MASK;
- m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
- m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
- mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
-
- if ((pll_type == PLL_TYPE1) ||
- (pll_type == PLL_TYPE3) ||
- (pll_type == PLL_TYPE4) || (pll_type == PLL_TYPE7)) {
- m1 = factor6(m1);
- if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
- m2 += CC_F5_BIAS;
- else
- m2 = factor6(m2);
- m3 = factor6(m3);
-
- switch (mc) {
- case CC_MC_BYPASS:
- return (clock);
- case CC_MC_M1:
- return (clock / m1);
- case CC_MC_M1M2:
- return (clock / (m1 * m2));
- case CC_MC_M1M2M3:
- return (clock / (m1 * m2 * m3));
- case CC_MC_M1M3:
- return (clock / (m1 * m3));
- default:
- return (0);
- }
- } else {
- ASSERT(pll_type == PLL_TYPE2);
-
- m1 += CC_T2_BIAS;
- m2 += CC_T2M2_BIAS;
- m3 += CC_T2_BIAS;
- ASSERT((m1 >= 2) && (m1 <= 7));
- ASSERT((m2 >= 3) && (m2 <= 10));
- ASSERT((m3 >= 2) && (m3 <= 7));
-
- if ((mc & CC_T2MC_M1BYP) == 0)
- clock /= m1;
- if ((mc & CC_T2MC_M2BYP) == 0)
- clock /= m2;
- if ((mc & CC_T2MC_M3BYP) == 0)
- clock /= m3;
-
- return (clock);
- }
-}
-
-/* returns the current speed the SB is running at */
-uint32 BCMINITFN(sb_clock) (sb_t * sbh) {
- sb_info_t *si;
- extifregs_t *eir;
- chipcregs_t *cc;
- uint32 n, m;
- uint idx;
- uint32 cap, pll_type, rate;
- uint intr_val = 0;
-
- si = SB_INFO(sbh);
- idx = si->curidx;
- pll_type = PLL_TYPE1;
-
- INTR_OFF(si, intr_val);
-
- /* switch to extif or chipc core */
- if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
- n = R_REG(si->osh, &eir->clockcontrol_n);
- m = R_REG(si->osh, &eir->clockcontrol_sb);
- } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
-
- cap = R_REG(si->osh, &cc->capabilities);
-
- if (cap & CC_CAP_PMU) {
-
- if (sb_chip(sbh) == BCM5354_CHIP_ID) {
- /* 5354 has a constant sb clock of 120MHz */
- rate = 120000000;
- goto end;
- } else
- if (sb_chip(sbh) == BCM4328_CHIP_ID) {
- rate = 80000000;
- goto end;
- } else
- ASSERT(0);
- }
-
- pll_type = cap & CC_CAP_PLL_MASK;
- if (pll_type == PLL_NONE) {
- INTR_RESTORE(si, intr_val);
- return 80000000;
- }
- n = R_REG(si->osh, &cc->clockcontrol_n);
- if (pll_type == PLL_TYPE6)
- m = R_REG(si->osh, &cc->clockcontrol_m3);
- else if (pll_type == PLL_TYPE3
- && !(BCMINIT(sb_chip) (sbh) == 0x5365))
- m = R_REG(si->osh, &cc->clockcontrol_m2);
- else
- m = R_REG(si->osh, &cc->clockcontrol_sb);
- } else {
- INTR_RESTORE(si, intr_val);
- return 0;
- }
-
- /* calculate rate */
- if (BCMINIT(sb_chip) (sbh) == 0x5365)
- rate = 100000000;
- else {
- rate = sb_clock_rate(pll_type, n, m);
-
- if (pll_type == PLL_TYPE3)
- rate = rate / 2;
- }
-
- end:
- /* switch back to previous core */
- sb_setcoreidx(sbh, idx);
-
- INTR_RESTORE(si, intr_val);
-
- return rate;
-}
-
-uint32 BCMINITFN(sb_alp_clock) (sb_t * sbh) {
- uint32 clock = ALP_CLOCK;
-
- if (sbh->cccaps & CC_CAP_PMU)
- clock = sb_pmu_alp_clock(sbh, sb_osh(sbh));
-
- return clock;
-}
-
-/* change logical "focus" to the gpio core for optimized access */
-void *sb_gpiosetcore(sb_t * sbh)
-{
- sb_info_t *si;
-
- si = SB_INFO(sbh);
-
- return (sb_setcoreidx(sbh, si->gpioidx));
-}
-
-/* mask&set gpiocontrol bits */
-uint32 sb_gpiocontrol(sb_t * sbh, uint32 mask, uint32 val, uint8 priority)
-{
- sb_info_t *si;
- uint regoff;
-
- si = SB_INFO(sbh);
- regoff = 0;
-
- /* gpios could be shared on router platforms
- * ignore reservation if it's high priority (e.g., test apps)
- */
- if ((priority != GPIO_HI_PRIORITY) &&
- (BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
- mask = priority ? (sb_gpioreservation & mask) :
- ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
- val &= mask;
- }
-
- switch (si->gpioid) {
- case SB_CC:
- regoff = OFFSETOF(chipcregs_t, gpiocontrol);
- break;
-
- case SB_PCI:
- regoff = OFFSETOF(sbpciregs_t, gpiocontrol);
- break;
-
- case SB_EXTIF:
- return (0);
- }
-
- return (sb_corereg(sbh, si->gpioidx, regoff, mask, val));
-}
-
-/* mask&set gpio output enable bits */
-uint32 sb_gpioouten(sb_t * sbh, uint32 mask, uint32 val, uint8 priority)
-{
- sb_info_t *si;
- uint regoff;
-
- si = SB_INFO(sbh);
- regoff = 0;
-
- /* gpios could be shared on router platforms
- * ignore reservation if it's high priority (e.g., test apps)
- */
- if ((priority != GPIO_HI_PRIORITY) &&
- (BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
- mask = priority ? (sb_gpioreservation & mask) :
- ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
- val &= mask;
- }
-
- switch (si->gpioid) {
- case SB_CC:
- regoff = OFFSETOF(chipcregs_t, gpioouten);
- break;
-
- case SB_PCI:
- regoff = OFFSETOF(sbpciregs_t, gpioouten);
- break;
-
- case SB_EXTIF:
- regoff = OFFSETOF(extifregs_t, gpio[0].outen);
- break;
- }
-
- return (sb_corereg(sbh, si->gpioidx, regoff, mask, val));
-}
-
-/* mask&set gpio output bits */
-uint32 sb_gpioout(sb_t * sbh, uint32 mask, uint32 val, uint8 priority)
-{
- sb_info_t *si;
- uint regoff;
-
- si = SB_INFO(sbh);
- regoff = 0;
-
- /* gpios could be shared on router platforms
- * ignore reservation if it's high priority (e.g., test apps)
- */
- if ((priority != GPIO_HI_PRIORITY) &&
- (BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
- mask = priority ? (sb_gpioreservation & mask) :
- ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
- val &= mask;
- }
-
- switch (si->gpioid) {
- case SB_CC:
- regoff = OFFSETOF(chipcregs_t, gpioout);
- break;
-
- case SB_PCI:
- regoff = OFFSETOF(sbpciregs_t, gpioout);
- break;
-
- case SB_EXTIF:
- regoff = OFFSETOF(extifregs_t, gpio[0].out);
- break;
- }
-
- return (sb_corereg(sbh, si->gpioidx, regoff, mask, val));
-}
-
-/* reserve one gpio */
-uint32 sb_gpioreserve(sb_t * sbh, uint32 gpio_bitmask, uint8 priority)
-{
- sb_info_t *si;
-
- si = SB_INFO(sbh);
-
- /* only cores on SB_BUS share GPIO's and only applcation users need to
- * reserve/release GPIO
- */
- if ((BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) {
- ASSERT((BUSTYPE(si->sb.bustype) == SB_BUS) && (priority));
- return -1;
- }
- /* make sure only one bit is set */
- if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
- ASSERT((gpio_bitmask)
- && !((gpio_bitmask) & (gpio_bitmask - 1)));
- return -1;
- }
-
- /* already reserved */
- if (sb_gpioreservation & gpio_bitmask)
- return -1;
- /* set reservation */
- sb_gpioreservation |= gpio_bitmask;
-
- return sb_gpioreservation;
-}
-
-/* release one gpio */
-/*
- * releasing the gpio doesn't change the current value on the GPIO last write value
- * persists till some one overwrites it
-*/
-
-uint32 sb_gpiorelease(sb_t * sbh, uint32 gpio_bitmask, uint8 priority)
-{
- sb_info_t *si;
-
- si = SB_INFO(sbh);
-
- /* only cores on SB_BUS share GPIO's and only applcation users need to
- * reserve/release GPIO
- */
- if ((BUSTYPE(si->sb.bustype) != SB_BUS) || (!priority)) {
- ASSERT((BUSTYPE(si->sb.bustype) == SB_BUS) && (priority));
- return -1;
- }
- /* make sure only one bit is set */
- if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
- ASSERT((gpio_bitmask)
- && !((gpio_bitmask) & (gpio_bitmask - 1)));
- return -1;
- }
-
- /* already released */
- if (!(sb_gpioreservation & gpio_bitmask))
- return -1;
-
- /* clear reservation */
- sb_gpioreservation &= ~gpio_bitmask;
-
- return sb_gpioreservation;
-}
-
-/* return the current gpioin register value */
-uint32 sb_gpioin(sb_t * sbh)
-{
- sb_info_t *si;
- uint regoff;
-
- si = SB_INFO(sbh);
- regoff = 0;
-
- switch (si->gpioid) {
- case SB_CC:
- regoff = OFFSETOF(chipcregs_t, gpioin);
- break;
-
- case SB_PCI:
- regoff = OFFSETOF(sbpciregs_t, gpioin);
- break;
-
- case SB_EXTIF:
- regoff = OFFSETOF(extifregs_t, gpioin);
- break;
- }
-
- return (sb_corereg(sbh, si->gpioidx, regoff, 0, 0));
-}
-
-/* mask&set gpio interrupt polarity bits */
-uint32 sb_gpiointpolarity(sb_t * sbh, uint32 mask, uint32 val, uint8 priority)
-{
- sb_info_t *si;
- uint regoff;
-
- si = SB_INFO(sbh);
- regoff = 0;
-
- /* gpios could be shared on router platforms */
- if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
- mask = priority ? (sb_gpioreservation & mask) :
- ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
- val &= mask;
- }
-
- switch (si->gpioid) {
- case SB_CC:
- regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
- break;
-
- case SB_PCI:
- /* pci gpio implementation does not support interrupt polarity */
- ASSERT(0);
- break;
-
- case SB_EXTIF:
- regoff = OFFSETOF(extifregs_t, gpiointpolarity);
- break;
- }
-
- return (sb_corereg(sbh, si->gpioidx, regoff, mask, val));
-}
-
-/* mask&set gpio interrupt mask bits */
-uint32 sb_gpiointmask(sb_t * sbh, uint32 mask, uint32 val, uint8 priority)
-{
- sb_info_t *si;
- uint regoff;
-
- si = SB_INFO(sbh);
- regoff = 0;
-
- /* gpios could be shared on router platforms */
- if ((BUSTYPE(si->sb.bustype) == SB_BUS) && (val || mask)) {
- mask = priority ? (sb_gpioreservation & mask) :
- ((sb_gpioreservation | mask) & ~(sb_gpioreservation));
- val &= mask;
- }
-
- switch (si->gpioid) {
- case SB_CC:
- regoff = OFFSETOF(chipcregs_t, gpiointmask);
- break;
-
- case SB_PCI:
- /* pci gpio implementation does not support interrupt mask */
- ASSERT(0);
- break;
-
- case SB_EXTIF:
- regoff = OFFSETOF(extifregs_t, gpiointmask);
- break;
- }
-
- return (sb_corereg(sbh, si->gpioidx, regoff, mask, val));
-}
-
-/* assign the gpio to an led */
-uint32 sb_gpioled(sb_t * sbh, uint32 mask, uint32 val)
-{
- sb_info_t *si;
-
- si = SB_INFO(sbh);
- if (si->sb.ccrev < 16)
- return -1;
-
- /* gpio led powersave reg */
- return (sb_corereg
- (sbh, SB_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask,
- val));
-}
-
-/* mask&set gpio timer val */
-uint32 sb_gpiotimerval(sb_t * sbh, uint32 mask, uint32 gpiotimerval)
-{
- sb_info_t *si;
- si = SB_INFO(sbh);
-
- if (si->sb.ccrev < 16)
- return -1;
-
- return (sb_corereg(sbh, SB_CC_IDX,
- OFFSETOF(chipcregs_t, gpiotimerval), mask,
- gpiotimerval));
-}
-
-uint32 sb_gpiopull(sb_t * sbh, bool updown, uint32 mask, uint32 val)
-{
- sb_info_t *si;
- uint offs;
-
- si = SB_INFO(sbh);
- if (si->sb.ccrev < 20)
- return -1;
-
- offs =
- (updown ? OFFSETOF(chipcregs_t, gpiopulldown) :
- OFFSETOF(chipcregs_t, gpiopullup));
- return (sb_corereg(sbh, SB_CC_IDX, offs, mask, val));
-}
-
-uint32 sb_gpioevent(sb_t * sbh, uint regtype, uint32 mask, uint32 val)
-{
- sb_info_t *si;
- uint offs;
-
- si = SB_INFO(sbh);
- if (si->sb.ccrev < 11)
- return -1;
-
- if (regtype == GPIO_REGEVT)
- offs = OFFSETOF(chipcregs_t, gpioevent);
- else if (regtype == GPIO_REGEVT_INTMSK)
- offs = OFFSETOF(chipcregs_t, gpioeventintmask);
- else if (regtype == GPIO_REGEVT_INTPOL)
- offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
- else
- return -1;
-
- return (sb_corereg(sbh, SB_CC_IDX, offs, mask, val));
-}
-
-void *BCMINITFN(sb_gpio_handler_register) (sb_t * sbh, uint32 event,
- bool level, gpio_handler_t cb,
- void *arg) {
- sb_info_t *si;
- gpioh_item_t *gi;
-
- ASSERT(event);
- ASSERT(cb);
-
- si = SB_INFO(sbh);
- if (si->sb.ccrev < 11)
- return NULL;
-
- if ((gi = MALLOC(si->osh, sizeof(gpioh_item_t))) == NULL)
- return NULL;
-
- bzero(gi, sizeof(gpioh_item_t));
- gi->event = event;
- gi->handler = cb;
- gi->arg = arg;
- gi->level = level;
-
- gi->next = si->gpioh_head;
- si->gpioh_head = gi;
-
- return (void *)(gi);
-}
-
-void BCMINITFN(sb_gpio_handler_unregister) (sb_t * sbh, void *gpioh) {
- sb_info_t *si;
- gpioh_item_t *p, *n;
-
- si = SB_INFO(sbh);
- if (si->sb.ccrev < 11)
- return;
-
- ASSERT(si->gpioh_head);
- if ((void *)si->gpioh_head == gpioh) {
- si->gpioh_head = si->gpioh_head->next;
- MFREE(si->osh, gpioh, sizeof(gpioh_item_t));
- return;
- } else {
- p = si->gpioh_head;
- n = p->next;
- while (n) {
- if ((void *)n == gpioh) {
- p->next = n->next;
- MFREE(si->osh, gpioh, sizeof(gpioh_item_t));
- return;
- }
- p = n;
- n = n->next;
- }
- }
-
- ASSERT(0); /* Not found in list */
-}
-
-void sb_gpio_handler_process(sb_t * sbh)
-{
- sb_info_t *si;
- gpioh_item_t *h;
- uint32 status;
- uint32 level = sb_gpioin(sbh);
- uint32 edge = sb_gpioevent(sbh, GPIO_REGEVT, 0, 0);
-
- si = SB_INFO(sbh);
- for (h = si->gpioh_head; h != NULL; h = h->next) {
- if (h->handler) {
- status = (h->level ? level : edge);
-
- if (status & h->event)
- h->handler(status, h->arg);
- }
- }
-
- sb_gpioevent(sbh, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */
-}
-
-uint32 sb_gpio_int_enable(sb_t * sbh, bool enable)
-{
- sb_info_t *si;
- uint offs;
-
- si = SB_INFO(sbh);
- if (si->sb.ccrev < 11)
- return -1;
-
- offs = OFFSETOF(chipcregs_t, intmask);
- return (sb_corereg
- (sbh, SB_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
-}
-
-#ifdef BCMDBG
-void sb_dump(sb_t * sbh, struct bcmstrbuf *b)
-{
- sb_info_t *si;
- uint i;
-
- si = SB_INFO(sbh);
-
- bcm_bprintf(b,
- "si %p chip 0x%x chiprev 0x%x boardtype 0x%x boardvendor 0x%x bus %d\n",
- si, si->sb.chip, si->sb.chiprev, si->sb.boardtype,
- si->sb.boardvendor, si->sb.bustype);
- bcm_bprintf(b, "osh %p curmap %p\n", si->osh, si->curmap);
- bcm_bprintf(b,
- "sonicsrev %d ccrev %d buscoretype 0x%x buscorerev %d curidx %d\n",
- si->sb.sonicsrev, si->sb.ccrev, si->sb.buscoretype,
- si->sb.buscorerev, si->curidx);
-
- bcm_bprintf(b, "forceHT %d ASPM overflowPR42780 %d pcie_polarity %d\n",
- si->sb.pr32414, si->sb.pr42780, si->pcie_polarity);
-
- bcm_bprintf(b, "cores: ");
- for (i = 0; i < si->numcores; i++)
- bcm_bprintf(b, "0x%x ", si->coreid[i]);
- bcm_bprintf(b, "\n");
-}
-
-/* print interesting sbconfig registers */
-void sb_dumpregs(sb_t * sbh, struct bcmstrbuf *b)
-{
- sb_info_t *si;
- sbconfig_t *sb;
- uint origidx;
- uint curidx, i, intr_val = 0;
-
- si = SB_INFO(sbh);
- origidx = si->curidx;
-
- INTR_OFF(si, intr_val);
- curidx = si->curidx;
-
- for (i = 0; i < si->numcores; i++) {
- sb = REGS2SB(sb_setcoreidx(sbh, i));
-
- bcm_bprintf(b, "core 0x%x: \n", si->coreid[i]);
- bcm_bprintf(b,
- "sbtmstatelow 0x%x sbtmstatehigh 0x%x sbidhigh 0x%x "
- "sbimstate 0x%x\n sbimconfiglow 0x%x sbimconfighigh 0x%x\n",
- R_SBREG(si, &sb->sbtmstatelow), R_SBREG(si,
- &sb->
- sbtmstatehigh),
- R_SBREG(si, &sb->sbidhigh), R_SBREG(si,
- &sb->sbimstate),
- R_SBREG(si, &sb->sbimconfiglow), R_SBREG(si,
- &sb->
- sbimconfighigh));
- }
-
- sb_setcoreidx(sbh, origidx);
- INTR_RESTORE(si, intr_val);
-}
-
-void sb_view(sb_t * sbh)
-{
- sb_info_t *si;
- sbconfig_t *sb;
-
- si = SB_INFO(sbh);
- sb = REGS2SB(si->curmap);
-
- if (si->sb.sonicsrev > SONICS_2_2)
- SB_ERROR(("sbimerrlog 0x%x sbimerrloga 0x%x\n",
- sb_corereg(sbh, sb_coreidx(&si->sb), SBIMERRLOG, 0,
- 0), sb_corereg(sbh, sb_coreidx(&si->sb),
- SBIMERRLOGA, 0, 0)));
-
- 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)));
- SB_ERROR(("sbadmatch3 0x%x sbadmatch2 0x%x sbadmatch1 0x%x\n",
- R_SBREG(si, &sb->sbadmatch3), R_SBREG(si, &sb->sbadmatch2),
- R_SBREG(si, &sb->sbadmatch1)));
- 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)));
- 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)));
- 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)));
- SB_ERROR(("sbactcnfg 0x%x sbflagst 0x%x sbidlow 0x%x sbidhigh 0x%x\n",
- R_SBREG(si, &sb->sbactcnfg), R_SBREG(si, &sb->sbflagst),
- R_SBREG(si, &sb->sbidlow), R_SBREG(si, &sb->sbidhigh)));
-}
-
-void sb_viewall(sb_t * sbh)
-{
- sb_info_t *si;
- uint curidx, i;
- uint intr_val = 0;
-
- si = SB_INFO(sbh);
- curidx = si->curidx;
-
- for (i = 0; i < si->numcores; i++) {
- INTR_OFF(si, intr_val);
- sb_setcoreidx(sbh, i);
- sb_view(sbh);
- INTR_RESTORE(si, intr_val);
- }
-
- sb_setcoreidx(sbh, curidx);
-}
-#endif /* BCMDBG */
-
-/* return the slow clock source - LPO, XTAL, or PCI */
-static uint sb_slowclk_src(sb_info_t * si)
-{
- chipcregs_t *cc;
-
- ASSERT(sb_coreid(&si->sb) == SB_CC);
-
- if (si->sb.ccrev < 6) {
- if ((BUSTYPE(si->sb.bustype) == PCI_BUS) &&
- (OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, sizeof(uint32))
- & PCI_CFG_GPIO_SCS))
- return (SCC_SS_PCI);
- else
- return (SCC_SS_XTAL);
- } else if (si->sb.ccrev < 10) {
- cc = (chipcregs_t *) sb_setcoreidx(&si->sb, si->curidx);
- return (R_REG(si->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
- } else /* Insta-clock */
- return (SCC_SS_XTAL);
-}
-
-/* return the ILP (slowclock) min or max frequency */
-static uint sb_slowclk_freq(sb_info_t * si, bool max_freq)
-{
- chipcregs_t *cc;
- uint32 slowclk;
- uint div;
-
- ASSERT(sb_coreid(&si->sb) == SB_CC);
-
- cc = (chipcregs_t *) sb_setcoreidx(&si->sb, si->curidx);
-
- /* shouldn't be here unless we've established the chip has dynamic clk control */
- ASSERT(R_REG(si->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
-
- slowclk = sb_slowclk_src(si);
- if (si->sb.ccrev < 6) {
- if (slowclk == SCC_SS_PCI)
- return (max_freq ? (PCIMAXFREQ / 64)
- : (PCIMINFREQ / 64));
- else
- return (max_freq ? (XTALMAXFREQ / 32)
- : (XTALMINFREQ / 32));
- } else if (si->sb.ccrev < 10) {
- div =
- 4 *
- (((R_REG(si->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >>
- SCC_CD_SHIFT)
- + 1);
- if (slowclk == SCC_SS_LPO)
- return (max_freq ? LPOMAXFREQ : LPOMINFREQ);
- else if (slowclk == SCC_SS_XTAL)
- return (max_freq ? (XTALMAXFREQ / div)
- : (XTALMINFREQ / div));
- else if (slowclk == SCC_SS_PCI)
- return (max_freq ? (PCIMAXFREQ / div)
- : (PCIMINFREQ / div));
- else
- ASSERT(0);
- } else {
- /* Chipc rev 10 is InstaClock */
- div = R_REG(si->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
- div = 4 * (div + 1);
- return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div));
- }
- return (0);
-}
-
-static void BCMINITFN(sb_clkctl_setdelay) (sb_info_t * si, void *chipcregs) {
- chipcregs_t *cc;
- uint slowmaxfreq, pll_delay, slowclk;
- uint pll_on_delay, fref_sel_delay;
-
- pll_delay = PLL_DELAY;
-
- /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
- * since the xtal will also be powered down by dynamic clk control logic.
- */
-
- slowclk = sb_slowclk_src(si);
- if (slowclk != SCC_SS_XTAL)
- pll_delay += XTAL_ON_DELAY;
-
- /* Starting with 4318 it is ILP that is used for the delays */
- slowmaxfreq = sb_slowclk_freq(si, (si->sb.ccrev >= 10) ? FALSE : TRUE);
-
- pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
- fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
-
- cc = (chipcregs_t *) chipcregs;
- W_REG(si->osh, &cc->pll_on_delay, pll_on_delay);
- W_REG(si->osh, &cc->fref_sel_delay, fref_sel_delay);
-}
-
-/* initialize power control delay registers */
-void BCMINITFN(sb_clkctl_init) (sb_t * sbh) {
- sb_info_t *si;
- uint origidx;
- chipcregs_t *cc;
-
- si = SB_INFO(sbh);
-
- origidx = si->curidx;
-
- if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0)) == NULL)
- return;
-
- if ((si->sb.chip == BCM4321_CHIP_ID) && (si->sb.chiprev < 2))
- W_REG(si->osh, &cc->chipcontrol,
- (si->sb.chiprev ==
- 0) ? CHIPCTRL_4321A0_DEFAULT : CHIPCTRL_4321A1_DEFAULT);
-
- if (!(R_REG(si->osh, &cc->capabilities) & CC_CAP_PWR_CTL))
- goto done;
-
- /* set all Instaclk chip ILP to 1 MHz */
- if (si->sb.ccrev >= 10)
- SET_REG(si->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
- (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
-
- sb_clkctl_setdelay(si, (void *)(uintptr) cc);
-
- done:
- sb_setcoreidx(sbh, origidx);
-}
-
-/* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */
-uint16 BCMINITFN(sb_clkctl_fast_pwrup_delay) (sb_t * sbh) {
- sb_info_t *si;
- uint origidx;
- chipcregs_t *cc;
- uint slowminfreq;
- uint16 fpdelay;
- uint intr_val = 0;
-
- si = SB_INFO(sbh);
- fpdelay = 0;
- origidx = si->curidx;
-
- INTR_OFF(si, intr_val);
-
- if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0)) == NULL)
- goto done;
-
- if (sbh->cccaps & CC_CAP_PMU) {
- fpdelay = sb_pmu_fast_pwrup_delay(sbh, si->osh);
- goto done;
- }
-
- if (!(sbh->cccaps & CC_CAP_PWR_CTL))
- goto done;
-
- slowminfreq = sb_slowclk_freq(si, FALSE);
- fpdelay = (((R_REG(si->osh, &cc->pll_on_delay) + 2) * 1000000) +
- (slowminfreq - 1)) / slowminfreq;
-
- done:
- sb_setcoreidx(sbh, origidx);
- INTR_RESTORE(si, intr_val);
- return (fpdelay);
-}
-
-/* turn primary xtal and/or pll off/on */
-int sb_clkctl_xtal(sb_t * sbh, uint what, bool on)
-{
- sb_info_t *si;
- uint32 in, out, outen;
-
- si = SB_INFO(sbh);
-
- switch (BUSTYPE(si->sb.bustype)) {
-
- case PCMCIA_BUS:
- return (0);
-
- case PCI_BUS:
-
- /* pcie core doesn't have any mapping to control the xtal pu */
- if (PCIE(si))
- return -1;
-
- in = OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_IN, sizeof(uint32));
- out =
- OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT, sizeof(uint32));
- outen =
- OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUTEN,
- sizeof(uint32));
-
- /*
- * Avoid glitching the clock if GPRS is already using it.
- * We can't actually read the state of the PLLPD so we infer it
- * by the value of XTAL_PU which *is* readable via gpioin.
- */
- if (on && (in & PCI_CFG_GPIO_XTAL))
- return (0);
-
- if (what & XTAL)
- outen |= PCI_CFG_GPIO_XTAL;
- if (what & PLL)
- outen |= PCI_CFG_GPIO_PLL;
-
- if (on) {
- /* turn primary xtal on */
- if (what & XTAL) {
- out |= PCI_CFG_GPIO_XTAL;
- if (what & PLL)
- out |= PCI_CFG_GPIO_PLL;
- OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT,
- sizeof(uint32), out);
- OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUTEN,
- sizeof(uint32), outen);
- OSL_DELAY(XTAL_ON_DELAY);
- }
-
- /* turn pll on */
- if (what & PLL) {
- out &= ~PCI_CFG_GPIO_PLL;
- OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT,
- sizeof(uint32), out);
- OSL_DELAY(2000);
- }
- } else {
- if (what & XTAL)
- out &= ~PCI_CFG_GPIO_XTAL;
- if (what & PLL)
- out |= PCI_CFG_GPIO_PLL;
- OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUT,
- sizeof(uint32), out);
- OSL_PCI_WRITE_CONFIG(si->osh, PCI_GPIO_OUTEN,
- sizeof(uint32), outen);
- }
-
- default:
- return (-1);
- }
-
- return (0);
-}
-
-/* set dynamic clk control mode (forceslow, forcefast, dynamic) */
-/* returns true if we are forcing fast clock */
-bool sb_clkctl_clk(sb_t * sbh, uint mode)
-{
- sb_info_t *si;
- uint origidx;
- chipcregs_t *cc;
- uint32 scc;
- uint intr_val = 0;
-
- si = SB_INFO(sbh);
-
- /* chipcommon cores prior to rev6 don't support dynamic clock control */
- if (si->sb.ccrev < 6)
- return (FALSE);
-
- /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */
- ASSERT(si->sb.ccrev != 10);
-
- INTR_OFF(si, intr_val);
-
- origidx = si->curidx;
-
- if (sb_setcore(sbh, SB_MIPS33, 0) && (sb_corerev(&si->sb) <= 7) &&
- (BUSTYPE(si->sb.bustype) == SB_BUS) && (si->sb.ccrev >= 10))
- goto done;
-
- if (FORCEHT_WAR32414(si))
- goto done;
-
- cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0);
- ASSERT(cc != NULL);
-
- if (!(R_REG(si->osh, &cc->capabilities) & CC_CAP_PWR_CTL)
- && (si->sb.ccrev < 20))
- goto done;
-
- switch (mode) {
- case CLK_FAST: /* force fast (pll) clock */
- if (si->sb.ccrev < 10) {
- /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
- sb_clkctl_xtal(&si->sb, XTAL, ON);
-
- SET_REG(si->osh, &cc->slow_clk_ctl,
- (SCC_XC | SCC_FS | SCC_IP), SCC_IP);
- } else if (si->sb.ccrev < 20) {
- OR_REG(si->osh, &cc->system_clk_ctl, SYCC_HR);
- } else {
- OR_REG(si->osh, &cc->clk_ctl_st, CCS_FORCEHT);
- }
-
- /* wait for the PLL */
- if (R_REG(si->osh, &cc->capabilities) & CC_CAP_PMU) {
- SPINWAIT(((R_REG(si->osh, &cc->clk_ctl_st) &
- CCS_HTAVAIL) == 0), PMU_MAX_TRANSITION_DLY);
- ASSERT(R_REG(si->osh, &cc->clk_ctl_st) & CCS_HTAVAIL);
- } else {
- OSL_DELAY(PLL_DELAY);
- }
- break;
-
- case CLK_DYNAMIC: /* enable dynamic clock control */
- if (si->sb.ccrev < 10) {
- scc = R_REG(si->osh, &cc->slow_clk_ctl);
- scc &= ~(SCC_FS | SCC_IP | SCC_XC);
- if ((scc & SCC_SS_MASK) != SCC_SS_XTAL)
- scc |= SCC_XC;
- W_REG(si->osh, &cc->slow_clk_ctl, scc);
-
- /* for dynamic control, we have to release our xtal_pu "force on" */
- if (scc & SCC_XC)
- sb_clkctl_xtal(&si->sb, XTAL, OFF);
- } else if (si->sb.ccrev < 20) {
- /* Instaclock */
- AND_REG(si->osh, &cc->system_clk_ctl, ~SYCC_HR);
- } else {
- AND_REG(si->osh, &cc->clk_ctl_st, ~CCS_FORCEHT);
- }
- break;
-
- default:
- ASSERT(0);
- }
-
- done:
- sb_setcoreidx(sbh, origidx);
- INTR_RESTORE(si, intr_val);
- return (mode == CLK_FAST);
-}
-
-/* register driver interrupt disabling and restoring callback functions */
-void
-sb_register_intr_callback(sb_t * sbh, void *intrsoff_fn,
- void *intrsrestore_fn, void *intrsenabled_fn,
- void *intr_arg)
-{
- sb_info_t *si;
-
- si = SB_INFO(sbh);
- si->intr_arg = intr_arg;
- si->intrsoff_fn = (sb_intrsoff_t) intrsoff_fn;
- si->intrsrestore_fn = (sb_intrsrestore_t) intrsrestore_fn;
- si->intrsenabled_fn = (sb_intrsenabled_t) intrsenabled_fn;
- /* save current core id. when this function called, the current core
- * must be the core which provides driver functions(il, et, wl, etc.)
- */
- si->dev_coreid = si->coreid[si->curidx];
-}
-
-void sb_deregister_intr_callback(sb_t * sbh)
-{
- sb_info_t *si;
-
- si = SB_INFO(sbh);
- si->intrsoff_fn = NULL;
-}
-
-#ifdef BCMDBG
-/* dump dynamic clock control related registers */
-void sb_clkctl_dump(sb_t * sbh, struct bcmstrbuf *b)
-{
- sb_info_t *si;
- chipcregs_t *cc;
- uint origidx;
- uint intr_val = 0;
-
- si = SB_INFO(sbh);
-
- INTR_OFF(si, intr_val);
-
- origidx = si->curidx;
-
- if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0)) == NULL) {
- INTR_RESTORE(si, intr_val);
- return;
- }
-
- if (!(R_REG(si->osh, &cc->capabilities) & CC_CAP_PWR_CTL))
- goto done;
-
- bcm_bprintf(b, "pll_on_delay 0x%x fref_sel_delay 0x%x ",
- cc->pll_on_delay, cc->fref_sel_delay);
- if ((si->sb.ccrev >= 6) && (si->sb.ccrev < 10))
- bcm_bprintf(b, "slow_clk_ctl 0x%x ", cc->slow_clk_ctl);
- if (si->sb.ccrev >= 10) {
- bcm_bprintf(b, "system_clk_ctl 0x%x ", cc->system_clk_ctl);
- bcm_bprintf(b, "clkstatestretch 0x%x ", cc->clkstatestretch);
- }
- if (BUSTYPE(si->sb.bustype) == PCI_BUS)
- bcm_bprintf(b, "gpioout 0x%x gpioouten 0x%x ",
- OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUT,
- sizeof(uint32)),
- OSL_PCI_READ_CONFIG(si->osh, PCI_GPIO_OUTEN,
- sizeof(uint32)));
- bcm_bprintf(b, "\n");
-
- done:
- sb_setcoreidx(sbh, origidx);
- INTR_RESTORE(si, intr_val);
-}
-#endif /* BCMDBG */
-
-uint16 BCMINITFN(sb_d11_devid) (sb_t * sbh) {
- sb_info_t *si = SB_INFO(sbh);
- uint16 device;
-
-#if defined(BCM4328)
- /* Fix device id for dual band BCM4328 */
- if (sbh->chip == BCM4328_CHIP_ID &&
- (sbh->chippkg == BCM4328USBDUAL_PKG_ID
- || sbh->chippkg == BCM4328SDIODUAL_PKG_ID))
- device = BCM4328_D11DUAL_ID;
- else
-#endif /* BCM4328 */
- /* Let an nvram variable with devpath override devid */
- if ((device = (uint16) sb_getdevpathintvar(sbh, "devid")) != 0) ;
- /* Get devid from OTP/SPROM depending on where the SROM is read */
- else if ((device = (uint16) getintvar(si->vars, "devid")) != 0) ;
- /*
- * no longer support wl0id, but keep the code
- * here for backward compatibility.
- */
- else if ((device = (uint16) getintvar(si->vars, "wl0id")) != 0) ;
- /* Chip specific conversion */
- else if (sbh->chip == BCM4712_CHIP_ID) {
- if (sbh->chippkg == BCM4712SMALL_PKG_ID)
- device = BCM4306_D11G_ID;
- else
- device = BCM4306_D11DUAL_ID;
- }
- /* ignore it */
- else
- device = 0xffff;
-
- return device;
-}
-
-int
-BCMINITFN(sb_corepciid) (sb_t * sbh, uint func, uint16 * pcivendor,
- uint16 * pcidevice, uint8 * pciclass,
- uint8 * pcisubclass, uint8 * pciprogif,
- uint8 * pciheader) {
- uint16 vendor = 0xffff, device = 0xffff;
- uint8 class, subclass, progif = 0;
- uint8 header = PCI_HEADER_NORMAL;
- uint32 core = sb_coreid(sbh);
-
- /* Verify whether the function exists for the core */
- if (func >= (uint) (core == SB_USB20H ? 2 : 1))
- return -1;
-
- /* Known vendor translations */
- switch (sb_corevendor(sbh)) {
- case SB_VEND_BCM:
- vendor = VENDOR_BROADCOM;
- break;
- default:
- return -1;
- }
-
- /* Determine class based on known core codes */
- switch (core) {
- case SB_ILINE20:
- class = PCI_CLASS_NET;
- subclass = PCI_NET_ETHER;
- device = BCM47XX_ILINE_ID;
- break;
- case SB_ENET:
- class = PCI_CLASS_NET;
- subclass = PCI_NET_ETHER;
- device = BCM47XX_ENET_ID;
- break;
- case SB_GIGETH:
- class = PCI_CLASS_NET;
- subclass = PCI_NET_ETHER;
- device = BCM47XX_GIGETH_ID;
- break;
- case SB_SDRAM:
- case SB_MEMC:
- class = PCI_CLASS_MEMORY;
- subclass = PCI_MEMORY_RAM;
- device = (uint16) core;
- break;
- case SB_PCI:
- case SB_PCIE:
- class = PCI_CLASS_BRIDGE;
- subclass = PCI_BRIDGE_PCI;
- device = (uint16) core;
- header = PCI_HEADER_BRIDGE;
- break;
- case SB_MIPS:
- case SB_MIPS33:
- class = PCI_CLASS_CPU;
- subclass = PCI_CPU_MIPS;
- device = (uint16) core;
- break;
- case SB_CODEC:
- class = PCI_CLASS_COMM;
- subclass = PCI_COMM_MODEM;
- device = BCM47XX_V90_ID;
- break;
- case SB_USB:
- class = PCI_CLASS_SERIAL;
- subclass = PCI_SERIAL_USB;
- progif = 0x10; /* OHCI */
- device = BCM47XX_USB_ID;
- break;
- case SB_USB11H:
- class = PCI_CLASS_SERIAL;
- subclass = PCI_SERIAL_USB;
- progif = 0x10; /* OHCI */
- device = BCM47XX_USBH_ID;
- break;
- case SB_USB20H:
- class = PCI_CLASS_SERIAL;
- subclass = PCI_SERIAL_USB;
- progif = func == 0 ? 0x10 : 0x20; /* OHCI/EHCI */
- device = BCM47XX_USB20H_ID;
- header = 0x80; /* multifunction */
- break;
- case SB_IPSEC:
- class = PCI_CLASS_CRYPT;
- subclass = PCI_CRYPT_NETWORK;
- device = BCM47XX_IPSEC_ID;
- break;
- case SB_ROBO:
- class = PCI_CLASS_NET;
- subclass = PCI_NET_OTHER;
- device = BCM47XX_ROBO_ID;
- break;
- case SB_EXTIF:
- case SB_CC:
- class = PCI_CLASS_MEMORY;
- subclass = PCI_MEMORY_FLASH;
- device = (uint16) core;
- break;
- case SB_SATAXOR:
- class = PCI_CLASS_XOR;
- subclass = PCI_XOR_QDMA;
- device = BCM47XX_SATAXOR_ID;
- break;
- case SB_ATA100:
- class = PCI_CLASS_DASDI;
- subclass = PCI_DASDI_IDE;
- device = BCM47XX_ATA100_ID;
- break;
- case SB_USB11D:
- class = PCI_CLASS_SERIAL;
- subclass = PCI_SERIAL_USB;
- device = BCM47XX_USBD_ID;
- break;
- case SB_USB20D:
- class = PCI_CLASS_SERIAL;
- subclass = PCI_SERIAL_USB;
- device = BCM47XX_USB20D_ID;
- break;
- case SB_D11:
- class = PCI_CLASS_NET;
- subclass = PCI_NET_OTHER;
- device = sb_d11_devid(sbh);
- break;
-
- default:
- class = subclass = progif = 0xff;
- device = (uint16) core;
- break;
- }
-
- *pcivendor = vendor;
- *pcidevice = device;
- *pciclass = class;
- *pcisubclass = subclass;
- *pciprogif = progif;
- *pciheader = header;
-
- return 0;
-}
-
-/* use the mdio interface to read from mdio slaves */
-static int
-sb_pcie_mdioread(sb_info_t * si, uint physmedia, uint regaddr, uint * regval)
-{
- uint mdiodata;
- uint i = 0;
- sbpcieregs_t *pcieregs;
-
- pcieregs = (sbpcieregs_t *) sb_setcoreidx(&si->sb, si->sb.buscoreidx);
- ASSERT(pcieregs);
-
- /* enable mdio access to SERDES */
- W_REG(si->osh, (&pcieregs->mdiocontrol),
- MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
-
- mdiodata = MDIODATA_START | MDIODATA_READ |
- (physmedia << MDIODATA_DEVADDR_SHF) |
- (regaddr << MDIODATA_REGADDR_SHF) | MDIODATA_TA;
-
- W_REG(si->osh, &pcieregs->mdiodata, mdiodata);
-
- PR28829_DELAY();
-
- /* retry till the transaction is complete */
- while (i < 10) {
- if (R_REG(si->osh, &(pcieregs->mdiocontrol)) &
- MDIOCTL_ACCESS_DONE) {
- PR28829_DELAY();
- *regval =
- (R_REG(si->osh, &(pcieregs->mdiodata)) &
- MDIODATA_MASK);
- /* Disable mdio access to SERDES */
- W_REG(si->osh, (&pcieregs->mdiocontrol), 0);
- return 0;
- }
- OSL_DELAY(1000);
- i++;
- }
-
- SB_ERROR(("sb_pcie_mdioread: timed out\n"));
- /* Disable mdio access to SERDES */
- W_REG(si->osh, (&pcieregs->mdiocontrol), 0);
- return 1;
-}
-
-/* use the mdio interface to write to mdio slaves */
-static int
-sb_pcie_mdiowrite(sb_info_t * si, uint physmedia, uint regaddr, uint val)
-{
- uint mdiodata;
- uint i = 0;
- sbpcieregs_t *pcieregs;
-
- pcieregs = (sbpcieregs_t *) sb_setcoreidx(&si->sb, si->sb.buscoreidx);
- ASSERT(pcieregs);
-
- /* enable mdio access to SERDES */
- W_REG(si->osh, (&pcieregs->mdiocontrol),
- MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
-
- mdiodata = MDIODATA_START | MDIODATA_WRITE |
- (physmedia << MDIODATA_DEVADDR_SHF) |
- (regaddr << MDIODATA_REGADDR_SHF) | MDIODATA_TA | val;
-
- W_REG(si->osh, (&pcieregs->mdiodata), mdiodata);
-
- PR28829_DELAY();
-
- /* retry till the transaction is complete */
- while (i < 10) {
- if (R_REG(si->osh, &(pcieregs->mdiocontrol)) &
- MDIOCTL_ACCESS_DONE) {
- /* Disable mdio access to SERDES */
- W_REG(si->osh, (&pcieregs->mdiocontrol), 0);
- return 0;
- }
- OSL_DELAY(1000);
- i++;
- }
-
- SB_ERROR(("sb_pcie_mdiowrite: timed out\n"));
- /* Disable mdio access to SERDES */
- W_REG(si->osh, (&pcieregs->mdiocontrol), 0);
- return 1;
-
-}
-
-/* indirect way to read pcie config regs */
-uint sb_pcie_readreg(void *sb, void *arg1, uint offset)
-{
- sb_info_t *si;
- sb_t *sbh;
- uint retval = 0xFFFFFFFF;
- sbpcieregs_t *pcieregs;
- uint addrtype;
-
- sbh = (sb_t *) sb;
- si = SB_INFO(sbh);
- ASSERT(PCIE(si));
-
- pcieregs = (sbpcieregs_t *) sb_setcore(sbh, SB_PCIE, 0);
- ASSERT(pcieregs);
-
- addrtype = (uint) ((uintptr) arg1);
- switch (addrtype) {
- case PCIE_CONFIGREGS:
- W_REG(si->osh, (&pcieregs->configaddr), offset);
- retval = R_REG(si->osh, &(pcieregs->configdata));
- break;
- case PCIE_PCIEREGS:
- W_REG(si->osh, &(pcieregs->pcieindaddr), offset);
- retval = R_REG(si->osh, &(pcieregs->pcieinddata));
- break;
- default:
- ASSERT(0);
- break;
- }
- return retval;
-}
-
-/* indirect way to write pcie config/mdio/pciecore regs */
-uint sb_pcie_writereg(sb_t * sbh, void *arg1, uint offset, uint val)
-{
- sb_info_t *si;
- sbpcieregs_t *pcieregs;
- uint addrtype;
-
- si = SB_INFO(sbh);
- ASSERT(PCIE(si));
-
- pcieregs = (sbpcieregs_t *) sb_setcore(sbh, SB_PCIE, 0);
- ASSERT(pcieregs);
-
- addrtype = (uint) ((uintptr) arg1);
-
- switch (addrtype) {
- case PCIE_CONFIGREGS:
- W_REG(si->osh, (&pcieregs->configaddr), offset);
- W_REG(si->osh, (&pcieregs->configdata), val);
- break;
- case PCIE_PCIEREGS:
- W_REG(si->osh, (&pcieregs->pcieindaddr), offset);
- W_REG(si->osh, (&pcieregs->pcieinddata), val);
- break;
- default:
- ASSERT(0);
- break;
- }
- return 0;
-}
-
-/* Build device path. Support SB, PCI, and JTAG for now. */
-int BCMINITFN(sb_devpath) (sb_t * sbh, char *path, int size) {
- int slen;
- ASSERT(path);
- ASSERT(size >= SB_DEVPATH_BUFSZ);
-
- if (!path || size <= 0)
- return -1;
-
- switch (BUSTYPE((SB_INFO(sbh))->sb.bustype)) {
- case SB_BUS:
- case JTAG_BUS:
- slen = snprintf(path, (size_t) size, "sb/%u/", sb_coreidx(sbh));
- break;
- case PCI_BUS:
- ASSERT((SB_INFO(sbh))->osh);
- slen = snprintf(path, (size_t) size, "pci/%u/%u/",
- OSL_PCI_BUS((SB_INFO(sbh))->osh),
- OSL_PCI_SLOT((SB_INFO(sbh))->osh));
- break;
- case PCMCIA_BUS:
- SB_ERROR(("sb_devpath: OSL_PCMCIA_BUS() not implemented, bus 1 assumed\n"));
- SB_ERROR(("sb_devpath: OSL_PCMCIA_SLOT() not implemented, slot 1 assumed\n"));
- slen = snprintf(path, (size_t) size, "pc/1/1/");
- break;
- default:
- slen = -1;
- ASSERT(0);
- break;
- }
-
- if (slen < 0 || slen >= size) {
- path[0] = '\0';
- return -1;
- }
-
- return 0;
-}
-
-/* Get a variable, but only if it has a devpath prefix */
-char *BCMINITFN(sb_getdevpathvar) (sb_t * sbh, const char *name) {
- char varname[SB_DEVPATH_BUFSZ + 32];
-
- sb_devpathvar(sbh, varname, sizeof(varname), name);
-
- return (getvar(NULL, varname));
-}
-
-/* Get a variable, but only if it has a devpath prefix */
-int BCMINITFN(sb_getdevpathintvar) (sb_t * sbh, const char *name) {
- char varname[SB_DEVPATH_BUFSZ + 32];
-
- sb_devpathvar(sbh, varname, sizeof(varname), name);
-
- return (getintvar(NULL, varname));
-}
-
-/* Concatenate the dev path with a varname into the given 'var' buffer
- * and return the 'var' pointer.
- * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned.
- * On overflow, the first char will be set to '\0'.
- */
-static char *BCMINITFN(sb_devpathvar) (sb_t * sbh, char *var, int len,
- const char *name) {
- uint path_len;
-
- if (!var || len <= 0)
- return var;
-
- if (sb_devpath(sbh, var, len) == 0) {
- path_len = strlen(var);
-
- if (strlen(name) + 1 > (uint) (len - path_len))
- var[0] = '\0';
- else
- strncpy(var + path_len, name, len - path_len - 1);
- }
-
- return var;
-}
-
-/*
- * Fixup SROMless PCI device's configuration.
- * The current core may be changed upon return.
- */
-static int sb_pci_fixcfg(sb_info_t * si)
-{
- uint origidx, pciidx;
- sbpciregs_t *pciregs;
- sbpcieregs_t *pcieregs = NULL;
- uint16 val16, *reg16;
- uint32 w;
-
- ASSERT(BUSTYPE(si->sb.bustype) == PCI_BUS);
-
- /* Fixup PI in SROM shadow area to enable the correct PCI core access */
- /* save the current index */
- origidx = sb_coreidx(&si->sb);
-
- /* check 'pi' is correct and fix it if not */
- if (si->sb.buscoretype == SB_PCIE) {
- pcieregs = (sbpcieregs_t *) sb_setcore(&si->sb, SB_PCIE, 0);
- ASSERT(pcieregs);
- reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
- } else if (si->sb.buscoretype == SB_PCI) {
- pciregs = (sbpciregs_t *) sb_setcore(&si->sb, SB_PCI, 0);
- ASSERT(pciregs);
- reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
- } else {
- ASSERT(0);
- return -1;
- }
- pciidx = sb_coreidx(&si->sb);
- val16 = R_REG(si->osh, reg16);
- if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (uint16) pciidx) {
- val16 =
- (uint16) (pciidx << SRSH_PI_SHIFT) | (val16 &
- ~SRSH_PI_MASK);
- W_REG(si->osh, reg16, val16);
- }
-
- if (PCIE_ASPMWARS(si)) {
- w = sb_pcie_readreg((void *)(uintptr) & si->sb,
- (void *)PCIE_PCIEREGS, PCIE_PLP_STATUSREG);
-
- /* Detect the current polarity at attach and force that polarity and
- * disable changing the polarity
- */
- if ((w & PCIE_PLP_POLARITYINV_STAT) == 0) {
- si->pcie_polarity = (SERDES_RX_CTRL_FORCE);
- } else {
- si->pcie_polarity = (SERDES_RX_CTRL_FORCE |
- SERDES_RX_CTRL_POLARITY);
- }
-
- w = OSL_PCI_READ_CONFIG(si->osh, si->pciecap_lcreg_offset,
- sizeof(uint32));
- if (w & PCIE_CLKREQ_ENAB) {
- reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET];
- val16 = R_REG(si->osh, reg16);
- /* if clockreq is not advertized clkreq should not be enabled */
- if (!(val16 & SRSH_CLKREQ_ENB))
- SB_ERROR(("WARNING: CLK REQ enabled already 0x%x\n", w));
- }
-
- sb_war43448(&si->sb);
-
- sb_war42767(&si->sb);
-
- }
-
- /* restore the original index */
- sb_setcoreidx(&si->sb, origidx);
-
- return 0;
-}
-
-/* Return ADDR64 capability of the backplane */
-bool sb_backplane64(sb_t * sbh)
-{
- sb_info_t *si;
-
- si = SB_INFO(sbh);
- return ((si->sb.cccaps & CC_CAP_BKPLN64) != 0);
-}
-
-void sb_btcgpiowar(sb_t * sbh)
-{
- sb_info_t *si;
- uint origidx;
- uint intr_val = 0;
- chipcregs_t *cc;
- si = SB_INFO(sbh);
-
- /* Make sure that there is ChipCommon core present &&
- * UART_TX is strapped to 1
- */
- if (!(si->sb.cccaps & CC_CAP_UARTGPIO))
- return;
-
- /* sb_corereg cannot be used as we have to guarantee 8-bit read/writes */
- INTR_OFF(si, intr_val);
-
- origidx = sb_coreidx(sbh);
-
- cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0);
- ASSERT(cc);
-
- W_REG(si->osh, &cc->uart0mcr, R_REG(si->osh, &cc->uart0mcr) | 0x04);
-
- /* restore the original index */
- sb_setcoreidx(sbh, origidx);
-
- INTR_RESTORE(si, intr_val);
-}
-
-/* check if the device is removed */
-bool sb_deviceremoved(sb_t * sbh)
-{
- uint32 w;
- sb_info_t *si;
-
- si = SB_INFO(sbh);
-
- switch (BUSTYPE(si->sb.bustype)) {
- case PCI_BUS:
- ASSERT(si->osh);
- w = OSL_PCI_READ_CONFIG(si->osh, PCI_CFG_VID, sizeof(uint32));
- if ((w & 0xFFFF) != VENDOR_BROADCOM)
- return TRUE;
- else
- return FALSE;
- default:
- return FALSE;
- }
- return FALSE;
-}
-
-#if 0
-/* Return the RAM size of the SOCRAM core */
-uint32 BCMINITFN(sb_socram_size) (sb_t * sbh) {
- sb_info_t *si;
- uint origidx;
- uint intr_val = 0;
-
- sbsocramregs_t *regs;
- bool wasup;
- uint corerev;
- uint32 coreinfo;
- uint memsize = 0;
-
- si = SB_INFO(sbh);
- ASSERT(si);
-
- /* Block ints and save current core */
- INTR_OFF(si, intr_val);
- origidx = sb_coreidx(sbh);
-
- /* Switch to SOCRAM core */
- if (!(regs = sb_setcore(sbh, SB_SOCRAM, 0)))
- goto done;
-
- /* Get info for determining size */
- if (!(wasup = sb_iscoreup(sbh)))
- sb_core_reset(sbh, 0, 0);
- corerev = sb_corerev(sbh);
- coreinfo = R_REG(si->osh, &regs->coreinfo);
-
- /* Calculate size from coreinfo based on rev */
- if (corerev == 0)
- memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
- else if (corerev < 3) {
- memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
- memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
- } else {
- uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
- uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
- uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
- if (lss != 0)
- nb--;
- memsize = nb * (1 << (bsz + SR_BSZ_BASE));
- if (lss != 0)
- memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
- }
- /* Return to previous state and core */
- if (!wasup)
- sb_core_disable(sbh, 0);
- sb_setcoreidx(sbh, origidx);
-
- done:
- INTR_RESTORE(si, intr_val);
- return memsize;
-}
-
-#endif