📄 skxmac2.c
字号:
/* configure the Serial Mode Register */#ifndef SK_SLIM SWord = (SK_U16)(DATA_BLIND_VAL(pPrt->PMacDataBlind) | GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData)); if (pPrt->PMacLimit4) { /* reset of collision counter after 4 consecutive collisions */ SWord |= GM_SMOD_LIMIT_4; }#else SWord = (SK_U16)(DATA_BLIND_VAL(DATA_BLIND_DEF) | GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF));#endif if (pPrt->PPortUsage == SK_JUMBO_LINK) { /* enable jumbo mode (Max. Frame Length = 9018) */ SWord |= GM_SMOD_JUMBO_ENA; } if (HW_FEATURE(pAC, HWF_NEW_FLOW_CONTROL)) { /* enable new Flow-Control */ SWord |= GM_NEW_FLOW_CTRL; } GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord); /* * configure the GMACs Station Addresses * in PROM you can find our addresses at: * B2_MAC_1 = xx xx xx xx xx x0 virtual address * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort */ for (i = 0; i < 3; i++) { /* * The following 2 statements are together endianess * independent. Remember this when changing. */ /* physical address: will be used for pause frames */ SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);#ifdef WA_DEV_16 /* WA for deviation #16 */ if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) { /* swap the address bytes */ SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8); /* write to register in reversed order */ GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord); } else { GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord); }#else GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);#endif /* WA_DEV_16 */ /* virtual address: will be used for data */ SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord); GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord); /* reset Multicast filtering Hash registers 1-3 */ GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + i * 4, 0); } /* reset Multicast filtering Hash register 4 */ GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0); /* enable interrupt mask for counter overflows */ GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0); GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0); GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0); pPrt->PState = SK_PRT_STOP;} /* SkGmInitMac */#ifdef SK_PHY_LP_MODE/****************************************************************************** * * SkGmEnterLowPowerMode() * * Description: * This function sets the Marvell Alaska PHY to the low power mode * given by parameter mode. * The following low power modes are available: * * - COMA Mode (Deep Sleep): * The PHY cannot wake up on its own. * * - IEEE 22.2.4.1.5 compatible power down mode * The PHY cannot wake up on its own. * * - energy detect mode * The PHY can wake up on its own by detecting activity * on the CAT 5 cable. * * - energy detect plus mode * The PHY can wake up on its own by detecting activity * on the CAT 5 cable. * Connected devices can be woken up by sending normal link * pulses every second. * * Note: * * Returns: * 0: ok * 1: error */int SkGmEnterLowPowerMode(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* I/O Context */int Port, /* Port Index (e.g. MAC_1) */SK_U8 Mode) /* low power mode */{ SK_U8 LastMode; SK_U8 Byte; SK_U16 Word; SK_U16 PhySpec; SK_U16 ClkDiv; SK_U32 DWord; SK_U32 PowerDownBit; SK_U32 ClkMask; int ChipId; int Ret = 0; if (!(CHIP_ID_YUKON_2(pAC) || (pAC->GIni.GIYukonLite && pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3))) { return(1); } /* save current power mode */ LastMode = pAC->GIni.GP[Port].PPhyPowerState; pAC->GIni.GP[Port].PPhyPowerState = Mode; ChipId = pAC->GIni.GIChipId; SK_DBG_MSG(pAC, SK_DBGMOD_POWM, SK_DBGCAT_CTRL, ("SkGmEnterLowPowerMode: %u\n", Mode)); /* release GPHY Control reset */ SK_OUT8(IoC, MR_ADDR(Port, GPHY_CTRL), (SK_U8)GPC_RST_CLR); /* release GMAC reset */ SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_RST_CLR); if (ChipId == CHIP_ID_YUKON_EC_U || ChipId == CHIP_ID_YUKON_EX || ChipId >= CHIP_ID_YUKON_SUPR) { /* select page 2 to access MAC control register */ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 2); SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); /* allow GMII Power Down */ Word &= ~PHY_M_MAC_GMIF_PUP; SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); /* set page register back to 0 */ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0); } switch (Mode) { /* COMA mode (deep sleep) */ case PHY_PM_DEEP_SLEEP: /* setup General Purpose Control Register */ GM_OUT16(IoC, Port, GM_GP_CTRL, GM_GPCR_FL_PASS | GM_GPCR_SPEED_100 | GM_GPCR_AU_ALL_DIS); if (CHIP_ID_YUKON_2(pAC)) { /* set power down bit */ PowerDownBit = (Port == MAC_1) ? PCI_Y2_PHY1_POWD : PCI_Y2_PHY2_POWD; if (ChipId != CHIP_ID_YUKON_EC) { if (ChipId == CHIP_ID_YUKON_EC_U) { SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &PhySpec); /* enable Power Down */ PhySpec |= PHY_M_PC_POW_D_ENA; SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PhySpec); } /* set IEEE compatible Power Down Mode (dev. #4.99) */ Ret = SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PHY_CT_PDOWN); } } else { /* apply COMA mode workaround for Yukon-Plus */ (void)SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_ADDR, 31); Ret = SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xfff3); PowerDownBit = PCI_PHY_COMA; } SK_TST_MODE_ON(IoC); SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_1), &DWord); /* set PHY to PowerDown/COMA Mode */ SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_1), DWord | PowerDownBit); /* check if this routine was called from a for() loop */ if (CHIP_ID_YUKON_2(pAC) && (pAC->GIni.GIMacsFound == 1 || Port == MAC_2)) { if (ChipId == CHIP_ID_YUKON_EC_U || ChipId == CHIP_ID_YUKON_EX || ChipId >= CHIP_ID_YUKON_FE_P) { /* set GPHY Control reset */ SK_OUT8(IoC, MR_ADDR(Port, GPHY_CTRL), (SK_U8)GPC_RST_SET); /* additional power saving measurements */ SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_4), &DWord); if (pAC->GIni.GIGotoD3Cold) { /* set gating core clock for LTSSM in DETECT state */ DWord |= (P_PEX_LTSSM_STAT(P_PEX_LTSSM_DET_STAT) | /* enable Gate Root Core Clock */ P_CLK_GATE_ROOT_COR_ENA); /* set Mask Register for Release/Gate Clock */ SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_5), P_REL_MAIN_PWR_AVAIL | P_GAT_MAIN_PWR_N_AVAIL); } else { /* set gating core clock for LTSSM in L1 state */ DWord |= (P_PEX_LTSSM_STAT(P_PEX_LTSSM_L1_STAT) | /* auto clock gated scheme controlled by CLKREQ */ P_ASPM_A1_MODE_SELECT | /* enable Gate Root Core Clock */ P_CLK_GATE_ROOT_COR_ENA); if (HW_FEATURE(pAC, HWF_WA_DEV_4200)) { /* enable Clock Power Management (CLKREQ) */ SK_IN16(IoC, PCI_C(pAC, PEX_CAP_REGS(PEX_LNK_CTRL)), &Word); Word |= PEX_LC_CLK_PM_ENA; SK_OUT16(IoC, PCI_C(pAC, PEX_CAP_REGS(PEX_LNK_CTRL)), Word); } else { /* force CLKREQ Enable in Our4 (A1b only) */ DWord |= P_ASPM_FORCE_CLKREQ_ENA; } if (ChipId == CHIP_ID_YUKON_FE_P) { /* set delay-timer value to 2 ms */ DWord |= P_TIMER_VALUE_MSK; } /* set Mask Register for Release/Gate Clock */ SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_5), P_REL_PCIE_EXIT_L1_ST | P_GAT_PCIE_ENTER_L1_ST | P_REL_PCIE_RX_EX_IDLE | P_GAT_PCIE_RX_EL_IDLE | P_REL_GPHY_LINK_UP | P_GAT_GPHY_LINK_DOWN); } SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_4), DWord); if (!pAC->GIni.GIAsfRunning) { /* stop the watchdog */ SK_OUT32(IoC, CPU_WDOG, 0); /* put CPU into reset state */ SK_OUT8(IoC, B28_Y2_ASF_STAT_CMD, (SK_U8)HCU_CCSR_ASF_RESET); if (!HW_FEATURE(pAC, HWF_WA_DEV_542)) { /* put CPU into halt state */ SK_OUT8(IoC, B28_Y2_ASF_STAT_CMD, (SK_U8)HCU_CCSR_ASF_HALTED); } /* stop the watchdog */ SK_OUT32(IoC, CPU_WDOG, 0); } } else { /* ASF system clock stopped */ SK_OUT8(IoC, B28_Y2_ASF_STAT_CMD, (SK_U8)Y2_ASF_CLK_HALT); } if (HW_FEATURE(pAC, HWF_RED_CORE_CLK_SUP)) { /* divide clock by 4 only for Yukon-EC */ ClkDiv = (ChipId == CHIP_ID_YUKON_EC) ? 1 : 0; /* on Yukon-2 clock select value is 31 */ DWord = (ChipId == CHIP_ID_YUKON_XL) ? (Y2_CLK_DIV_VAL_2(0) | Y2_CLK_SEL_VAL_2(31)) : Y2_CLK_DIV_VAL(ClkDiv); /* check for Yukon-2 dual port PCI-Express adapter */ if (!(pAC->GIni.GIMacsFound == 2 && pAC->GIni.GIPciBus == SK_PEX_BUS)) { /* enable Core Clock Division */ DWord |= Y2_CLK_DIV_ENA; } SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Set Core Clock: 0x%08X\n", DWord)); /* reduce Core Clock Frequency */ SK_OUT32(IoC, B2_Y2_CLK_CTRL, DWord); } if (HW_FEATURE(pAC, HWF_CLK_GATING_ENABLE)) { /* check for Yukon-2 Rev. A2 */ if (ChipId == CHIP_ID_YUKON_XL && pAC->GIni.GIChipRev > CHIP_REV_YU_XL_A1) { /* enable bits are inverted */ Byte = 0; } else { Byte = (SK_U8)(Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); } SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Set Clock Gating: 0x%02X\n", Byte)); /* disable MAC/PHY, PCI and Core Clock for both Links */ SK_OUT8(IoC, B2_Y2_CLK_GATE, Byte); } if (pAC->GIni.GILevel != SK_INIT_IO && pAC->GIni.GIMacsFound == 1 && pAC->GIni.GIPciBus == SK_PEX_BUS) { if (ChipId == CHIP_ID_YUKON_EC_U || ChipId == CHIP_ID_YUKON_EX || ChipId >= CHIP_ID_YUKON_FE_P) {#ifdef PCI_E_L1_STATE SK_IN16(IoC, PCI_C(pAC, PCI_OUR_REG_1), &Word); /* force to PCIe L1 */ Word |= (SK_U16)PCI_FORCE_PEX_L1; SK_OUT16(IoC, PCI_C(pAC, PCI_OUR_REG_1), Word);#else /* !PCI_E_L1_STATE */#ifdef DEEP_SLEEP_D1 SK_IN16(IoC, PCI_C(pAC, PEX_CAP_REGS(PEX_LNK_CTRL)), &Word); /* check if ASPM L1 enabled */ if ((Word & PEX_LC_ASPM_LC_L1) != 0) { break; }#else break;#endif /* !DEEP_SLEEP_D1 */#endif /* !PCI_E_L1_STATE */ } SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Switch to D1 state\n", DWord)); /* switch to D1 state */ SK_OUT8(IoC, PCI_C(pAC, PCI_PM_CTL_STS), PCI_PM_STATE_D1); } } break; /* IEEE 22.2.4.1.5 compatible power down mode */ case PHY_PM_IEEE_POWER_DOWN: if (!CHIP_ID_YUKON_2(pAC) && !pAC->GIni.GIYukonLite) { Ret = SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &PhySpec); /* disable MAC 125 MHz clock */ PhySpec |= PHY_M_PC_DIS_125CLK; PhySpec &= ~PHY_M_PC_MAC_POW_UP; SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PhySpec); /* these register changes must be followed by a software reset */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word); SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word | PHY_CT_RESET); } /* switch IEEE compatible power down mode on */ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PHY_CT_PDOWN);#ifdef DEBUG SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);#endif /* DEBUG */ break; /* energy detect and energy detect plus mode */ case PHY_PM_ENERGY_DETECT: case PHY_PM_ENERGY_DETECT_PLUS: Ret = SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &PhySpec);#ifdef XXX /* disable Polarity Reversal */ PhySpec |= PHY_M_PC_POL_R_DIS;#endif /* XXX */ if (!CHIP_ID_YUKON_2(pAC)) { /* disable MAC 125 MHz clock */ PhySpec |= PHY_M_PC_DIS_125CLK; } if (ChipId == CHIP_ID_YUKON_FE || ChipId == CHIP_ID_YUKON_FE_P) { /* enable Energy Detect (sense & pulse) */ PhySpec |= PHY_M_PC_ENA_ENE_DT; } else { /* clear energy detect mode bits */ PhySpec &= ~PHY_M_PC_EN_DET_MSK; PhySpec |= (Mode == PHY_PM_ENERGY_DETECT) ? PHY_M_PC_EN_DET : PHY_M_PC_EN_DET_PLUS; } SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PhySpec); /* these register changes must be followed by a software reset */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word); Word |= PHY_CT_RESET; SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word); if (ChipId == CHIP_ID_YUKON_FE_P) { /* Re-enable Link Partner Next Page */ PhySpec |= PHY_M_PC_ENA_LIP_NP; SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PhySpec); } if (ChipId == CHIP_ID_YUKON_EC_U || ChipId == CHIP_ID_YUKON_EX || ChipId >= CHIP_ID_YUKON_FE_P) { /* additional power saving measurements */ SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_4), &DWord); if (pAC->GIni.GIGotoD3Cold) { /* set gating core clock for LTSSM in DETECT state */ DWord |= (P_PEX_LTSSM_STAT(P_PEX_LTSSM_DET_STAT) | /* enable Gate Root Core Clock */ P_CLK_GATE_ROOT_COR_ENA); /* set Mask Register for Release/Gate Clock */ SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_5), P_REL_MAIN_PWR_AVAIL | P_GAT_MAIN_PWR_N_AVAIL); } else { /* set gating core clock for LTSSM in L1 state */ DWord |= (P_PEX_LTSSM_STAT(P_PEX_LTSSM_L1_STAT) | /* auto clock gated scheme controlled by CLKREQ */ P_ASPM_A1_MODE_SELECT | /* enable Gate Root Core Clock */ P_CLK_GATE_ROOT_COR_ENA); if (HW_FEATURE(pAC, HWF_WA_DEV_4200)) { /* enable Clock Power Management (CLKREQ) */ SK_IN16(IoC, PCI_C(pAC, PEX_CAP_REGS(PEX_LNK_CTRL)), &Word); Word |= PEX_LC_CLK_PM_ENA; SK_OUT16(IoC, PCI_C(pAC, PEX_CAP_REGS(PEX_LNK_CTRL)), Word); } else { /* force CLKREQ Enable in Our4 (A1b only) */ DWord |= P_ASPM_FORCE_CLKREQ_ENA; } if (ChipId == CHIP_ID_YUKON_FE_P) { /* set delay-timer value to 2 ms */ DWord |= P_TIMER_VALUE_MSK; } ClkMask = P_REL_PCIE_EXIT_L1_ST | P_GAT_PCIE_ENTER_L1_ST | P_REL_PCIE_RX_EX_IDLE | P_GAT_PCIE_RX_EL_IDLE | P_REL_GPHY_LINK_UP | P_GAT_GPHY_LINK_DOWN; if (pAC->GIni.GIAsfEnabled) { ClkMask |= P_REL_CPU_TO_SLEEP | P_GAT_CPU_TO_SLEEP; } /* set Mask Register for Release/Gate Clock */ SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_5), ClkMask); } SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_4), DWord);#ifdef PCI_E_L1_STATE SK_IN16(IoC, PCI_C(pAC, PCI_OUR_REG_1), &Word); /* enable PCIe L1 on GPHY link down */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -