int si_bist_cc(si_t *sih, uint32 *biststatus) { si_info_t *sii; uint origidx; uint intr_val = 0; int error = 0; void *regs; int status; bool wasup; sii = SI_INFO(sih); SI_ERROR(("doing the bist on ChipC\n")); /* Block ints and save current core */ INTR_OFF(sii, intr_val); origidx = si_coreidx(sih); /* Switch to CC core */ if (!(regs = si_setcore(sih, CC_CORE_ID, 0))) goto done; /* Get info for determining size */ if (!(wasup = si_iscoreup(sih))) si_core_reset(sih, 0, 0); status = si_corebist(sih); if (status == BCME_ERROR) { *biststatus = si_corereg(sih, si_coreidx(&sii->pub), 12, 0, 0); /* XXX: OTP gives the BIST error */ *biststatus &= ~(0x1); if (*biststatus) error = 1; } /* Return to previous state and core */ if (!wasup) si_core_disable(sih, 0); /* Return to previous state and core */ si_setcoreidx(sih, origidx); *biststatus = 0; done: INTR_RESTORE(sii, intr_val); return error; }
/* Return the RAM size of the SOCRAM core */ uint32 si_socram_size(si_t *sih) { si_info_t *sii; uint origidx; uint intr_val = 0; sbsocramregs_t *regs; bool wasup; uint corerev; uint32 coreinfo; uint memsize = 0; sii = SI_INFO(sih); /* Block ints and save current core */ INTR_OFF(sii, intr_val); origidx = si_coreidx(sih); /* Switch to SOCRAM core */ if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) goto done; /* Get info for determining size */ if (!(wasup = si_iscoreup(sih))) si_core_reset(sih, 0, 0); corerev = si_corerev(sih); coreinfo = R_REG(sii->osh, ®s->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 {
int si_bist_d11(si_t *sih, uint32 *biststatus1, uint32 *biststatus2) { si_info_t *sii; uint origidx; uint intr_val = 0; void *regs; int error = 0; bool wasup; uint32 offset = SBCONFIGOFF + SBTMSTATELOW; uint32 max_res_mask; uint32 pmu_ctrl; *biststatus1 = 0; *biststatus2 = 0; SI_ERROR(("doing the bist on D11\n")); sii = SI_INFO(sih); if (CHIPTYPE(sih->socitype) != SOCI_SB) { return 0; } /* Block ints and save current core */ INTR_OFF(sii, intr_val); origidx = si_coreidx(sih); /* Switch to D11 core */ if (!(regs = si_setcore(sih, D11_CORE_ID, 0))) goto done; /* Get info for determining size */ /* coming out of reset device shoudl have clk enabled, bw set, etc */ if (!(wasup = si_iscoreup(sih))) si_core_reset(sih, 0x4F, 0x4F); max_res_mask = si_corereg(sih, 0, OFFSETOF(chipcregs_t, max_res_mask), 0, 0); si_corereg(sih, 0, OFFSETOF(chipcregs_t, max_res_mask), ~0, 0x3fffff); if (si_corerev(&sii->pub) == 20) { uint32 phy_reset_val; uint32 bist_test_val, bist_status; /* XXX: enable the phy PLL */ pmu_ctrl = si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, 0, 0); pmu_ctrl |= 0x000010000; si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, ~0, pmu_ctrl); SPINWAIT(((si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, 0, 0) & 0x01000000) == 0), 1000000); pmu_ctrl = si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, 0, 0); /* take the phy out of reset */ phy_reset_val = si_corereg(sih, si_coreidx(&sii->pub), offset, 0, 0); phy_reset_val &= ~(0x0008 << SBTML_SICF_SHIFT); si_corereg(sih, si_coreidx(&sii->pub), offset, ~0, phy_reset_val); phy_reset_val = si_corereg(sih, si_coreidx(&sii->pub), offset, 0, 0); /* enable bist first */ bist_test_val = si_corereg(sih, si_coreidx(&sii->pub), offset, 0, 0); bist_test_val |= (SICF_BIST_EN << 16); si_corereg(sih, si_coreidx(&sii->pub), offset, ~0, bist_test_val); SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 1000000); bist_status = si_core_sflags(sih, 0, 0); SI_ERROR(("status are 0x%08x\n", bist_status)); if (bist_status & SISF_BIST_DONE) { if (bist_status & SISF_BIST_ERROR) { error = 1; *biststatus1 = si_corereg(sih, si_coreidx(&sii->pub), 12, 0, 0); *biststatus2 = si_corereg(sih, si_coreidx(&sii->pub), 16, 0, 0); } } /* stop the phy pll */ pmu_ctrl = si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, 0, 0); pmu_ctrl &= ~0x10000; si_corereg(sih, si_coreidx(&sii->pub), 0x1e8, ~0, pmu_ctrl); } /* remove the resource mask */ si_corereg(sih, 0, OFFSETOF(chipcregs_t, max_res_mask), ~0, max_res_mask); /* Return to previous state and core */ if (!wasup) si_core_disable(sih, 0); /* Return to previous state and core */ si_setcoreidx(sih, origidx); done: INTR_RESTORE(sii, intr_val); return error; }
/* * Setup the gige core. * Resetting the core will lose all settings. */ void hndgige_init(si_t *sih, uint32 unit, bool *rgmii) { volatile pci_config_regs *pci; sbgige_pcishim_t *ocp; sbconfig_t *sb; osl_t *osh; uint32 statelow; uint32 statehigh; uint32 base; uint32 idx; void *regs; /* Sanity checks */ ASSERT(sih); ASSERT(rgmii); idx = si_coreidx(sih); /* point to the gige core registers */ regs = si_setcore(sih, GIGETH_CORE_ID, unit); ASSERT(regs); osh = si_osh(sih); pci = &((sbgige_t *)regs)->pcicfg; ocp = &((sbgige_t *)regs)->pcishim; sb = &((sbgige_t *)regs)->sbconfig; /* Enable the core clock and memory access */ if (!si_iscoreup(sih)) si_core_reset(sih, 0, 0); /* * Setup the 64K memory-mapped region base address through BAR0. * Leave the other BAR values alone. */ base = si_addrspace(sih, 1); W_REG(osh, &pci->base[0], base); W_REG(osh, &pci->base[1], 0); /* * Enable the PCI memory access anyway. Any PCI config commands * issued before the core is enabled will go to the emulation * only and will not go to the real PCI config registers. */ OR_REG(osh, &pci->command, 2); /* * Enable the posted write flush scheme as follows: * * - Enable flush on any core register read * - Enable timeout on the flush * - Disable the interrupt mask when flushing * * This differs from the default setting only in that interrupts are * not masked. Since posted writes are not flushed on interrupt, the * driver must explicitly request a flush in its interrupt handling * by reading a core register. */ W_REG(osh, &ocp->FlushStatusControl, 0x68); /* * Determine whether the GbE is in GMII or RGMII mode. This is * indicated in bit 16 of the SBTMStateHigh register, which is * part of the core-specific flags field. * * For GMII, bypass the Rx/Tx DLLs, i.e. add no delay to RXC/GTXC * within the core. For RGMII, do not bypass the DLLs, resulting * in added delay for RXC/GTXC. The SBTMStateLow register contains * the controls for doing this in the core-specific flags field: * * bit 24 - Enable DLL controls * bit 20 - Bypass Rx DLL * bit 19 - Bypass Tx DLL */ statelow = R_REG(osh, &sb->sbtmstatelow); /* DLL controls */ statehigh = R_REG(osh, &sb->sbtmstatehigh); /* GMII/RGMII mode */ if ((statehigh & (1 << 16)) != 0) /* RGMII */ { statelow &= ~(1 << 20); /* no Rx bypass (delay) */ statelow &= ~(1 << 19); /* no Tx bypass (delay) */ *rgmii = TRUE; } else /* GMII */ { statelow |= (1 << 20); /* Rx bypass (no delay) */ statelow |= (1 << 19); /* Tx bypass (no delay) */ *rgmii = FALSE; } statelow |= (1 << 24); /* enable DLL controls */ W_REG(osh, &sb->sbtmstatelow, statelow); si_setcoreidx(sih, idx); }
static void chipreset(struct bcm4xxx *ch) { bcmenetregs_t *regs; uint32 clk, mdc; ET_TRACE(("et%d: chipreset\n", ch->etc->unit)); regs = ch->regs; if (!si_iscoreup(ch->sih)) { if (!ch->etc->nicmode) si_pci_setup(ch->sih, (1 << si_coreidx(ch->sih))); /* power on reset: reset the enet core */ si_core_reset(ch->sih, 0, 0); goto chipinreset; } /* read counters before resetting the chip */ if (ch->mibgood) chipstatsupd(ch); /* reset the tx dma engine */ if (ch->di) dma_txreset(ch->di); /* set emac into loopback mode to ensure no rx traffic */ W_REG(ch->osh, ®s->rxconfig, ERC_LE); OSL_DELAY(1); /* reset the rx dma engine */ if (ch->di) dma_rxreset(ch->di); /* reset core */ si_core_reset(ch->sih, 0, 0); chipinreset: /* must clear mib registers by hand */ W_REG(ch->osh, ®s->mibcontrol, EMC_RZ); (void) R_REG(ch->osh, ®s->mib.tx_broadcast_pkts); (void) R_REG(ch->osh, ®s->mib.tx_multicast_pkts); (void) R_REG(ch->osh, ®s->mib.tx_len_64); (void) R_REG(ch->osh, ®s->mib.tx_len_65_to_127); (void) R_REG(ch->osh, ®s->mib.tx_len_128_to_255); (void) R_REG(ch->osh, ®s->mib.tx_len_256_to_511); (void) R_REG(ch->osh, ®s->mib.tx_len_512_to_1023); (void) R_REG(ch->osh, ®s->mib.tx_len_1024_to_max); (void) R_REG(ch->osh, ®s->mib.tx_jabber_pkts); (void) R_REG(ch->osh, ®s->mib.tx_oversize_pkts); (void) R_REG(ch->osh, ®s->mib.tx_fragment_pkts); (void) R_REG(ch->osh, ®s->mib.tx_underruns); (void) R_REG(ch->osh, ®s->mib.tx_total_cols); (void) R_REG(ch->osh, ®s->mib.tx_single_cols); (void) R_REG(ch->osh, ®s->mib.tx_multiple_cols); (void) R_REG(ch->osh, ®s->mib.tx_excessive_cols); (void) R_REG(ch->osh, ®s->mib.tx_late_cols); (void) R_REG(ch->osh, ®s->mib.tx_defered); (void) R_REG(ch->osh, ®s->mib.tx_carrier_lost); (void) R_REG(ch->osh, ®s->mib.tx_pause_pkts); (void) R_REG(ch->osh, ®s->mib.rx_broadcast_pkts); (void) R_REG(ch->osh, ®s->mib.rx_multicast_pkts); (void) R_REG(ch->osh, ®s->mib.rx_len_64); (void) R_REG(ch->osh, ®s->mib.rx_len_65_to_127); (void) R_REG(ch->osh, ®s->mib.rx_len_128_to_255); (void) R_REG(ch->osh, ®s->mib.rx_len_256_to_511); (void) R_REG(ch->osh, ®s->mib.rx_len_512_to_1023); (void) R_REG(ch->osh, ®s->mib.rx_len_1024_to_max); (void) R_REG(ch->osh, ®s->mib.rx_jabber_pkts); (void) R_REG(ch->osh, ®s->mib.rx_oversize_pkts); (void) R_REG(ch->osh, ®s->mib.rx_fragment_pkts); (void) R_REG(ch->osh, ®s->mib.rx_missed_pkts); (void) R_REG(ch->osh, ®s->mib.rx_crc_align_errs); (void) R_REG(ch->osh, ®s->mib.rx_undersize); (void) R_REG(ch->osh, ®s->mib.rx_crc_errs); (void) R_REG(ch->osh, ®s->mib.rx_align_errs); (void) R_REG(ch->osh, ®s->mib.rx_symbol_errs); (void) R_REG(ch->osh, ®s->mib.rx_pause_pkts); (void) R_REG(ch->osh, ®s->mib.rx_nonpause_pkts); ch->mibgood = TRUE; /* * We want the phy registers to be accessible even when * the driver is "downed" so initialize MDC preamble, frequency, * and whether internal or external phy here. */ /* default: 100Mhz SI clock and external phy */ W_REG(ch->osh, ®s->mdiocontrol, 0x94); if (ch->etc->deviceid == BCM47XX_ENET_ID) { /* 47xx chips: find out the clock */ if ((clk = si_clock(ch->sih)) != 0) { mdc = 0x80 | ((clk + (MDC_RATIO / 2)) / MDC_RATIO); W_REG(ch->osh, ®s->mdiocontrol, mdc); } else { ET_ERROR(("et%d: chipreset: Could not figure out backplane clock, " "using 100Mhz\n", ch->etc->unit)); } } /* some chips have internal phy, some don't */ if (!(R_REG(ch->osh, ®s->devcontrol) & DC_IP)) { W_REG(ch->osh, ®s->enetcontrol, EC_EP); } else if (R_REG(ch->osh, ®s->devcontrol) & DC_ER) { AND_REG(ch->osh, ®s->devcontrol, ~DC_ER); OSL_DELAY(100); chipphyinit(ch, ch->etc->phyaddr); } /* clear persistent sw intstatus */ ch->intstatus = 0; }