/******************************************************************************* * mvPexIfEnable * * DESCRIPTION: * This function Enables PCI Express interface. * * INPUT: * pexIf - PEX interface number. * pexType - MV_PEX_ROOT_COMPLEX - root complex device * MV_PEX_END_POINT - end point device * OUTPUT: * None. * * RETURN: * None. * *******************************************************************************/ MV_VOID mvPexIfEnable(MV_U32 pexIf, MV_PEX_TYPE pexType) { MV_U32 regVal; /* NOTE: this was asked by CV, bit is reserved in the spec, but causing problems, disabling for now. */ /* MV_REG_BIT_SET(PEX_CTRL_REG(pexIf), PXCR_AUTO_SPEED_CTRL_MASK); */ /* Set pex mode incase S@R not exist */ if (pexType == MV_PEX_END_POINT) { MV_REG_BIT_RESET(PEX_CTRL_REG(pexIf), PXCR_DEV_TYPE_CTRL_MASK); /* Change pex mode in capability reg */ MV_REG_BIT_RESET(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_CAPABILITY_REG), BIT22); MV_REG_BIT_SET(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_CAPABILITY_REG), BIT20); regVal = MV_REG_READ(PEX_CAPABILITIES_REG(pexIf)); regVal |= 0x00F00000; regVal &= ~(BIT23 | BIT22 | BIT21); MV_REG_WRITE(PEX_CAPABILITIES_REG(pexIf), regVal); } else { regVal = MV_REG_READ(PEX_CAPABILITIES_REG(pexIf)); regVal |= 0x00F00000; regVal &= ~(BIT23 | BIT21 | BIT20); MV_REG_WRITE(PEX_CAPABILITIES_REG(pexIf), regVal); MV_REG_BIT_SET(PEX_CTRL_REG(pexIf), PXCR_DEV_TYPE_CTRL_MASK); } return; }
/******************************************************************************* * mvPexForceX1 * * DESCRIPTION: * shut down lanes 1-3 if recognize that attached to an x1 end-point * INPUT: * pexIf - PEX interface number. * * OUTPUT: * None * * RETURN: * MV_OK on success , MV_ERROR otherwise * *******************************************************************************/ MV_U32 mvPexForceX1(MV_U32 pexIf) { MV_U32 regData = 0; if (pexIf >= pexHalData[pexIf].maxPexIf) { mvOsPrintf("mvPexForceX1: ERR. Invalid PEX interface %d\n", pexIf); return MV_BAD_PARAM; } regData = MV_REG_READ(PEX_CTRL_REG(pexIf)) & ~(PXCR_CONF_LINK_MASK); regData |= PXCR_CONF_LINK_X1; MV_REG_WRITE(PEX_CTRL_REG(pexIf), regData); return MV_OK; }
MV_VOID mvCpuIfEnablePex(MV_U32 pexIf, MV_PEX_TYPE pexType) { /* Set pex mode incase S@R not exist */ if( pexType == MV_PEX_END_POINT) { MV_REG_BIT_RESET(PEX_CTRL_REG(pexIf),PXCR_DEV_TYPE_CTRL_MASK); /* Change pex mode in capability reg */ MV_REG_BIT_RESET(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_CAPABILITY_REG), BIT22); MV_REG_BIT_SET(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_CAPABILITY_REG), BIT20); } else { MV_REG_BIT_SET(PEX_CTRL_REG(pexIf),PXCR_DEV_TYPE_CTRL_MASK); } /* CPU config register Pex enable */ MV_REG_BIT_SET(CPU_CTRL_STAT_REG,(CCSR_PCI_ACCESS_MASK(pexIf))); }
/******************************************************************************* * mvPexModeGet - Get Pex Mode * * DESCRIPTION: * * INPUT: * pexIf - PEX interface number. * * OUTPUT: * pexMode - Pex mode structure * * RETURN: * MV_OK on success , MV_ERROR otherwise * *******************************************************************************/ MV_U32 mvPexModeGet(MV_U32 pexIf,MV_PEX_MODE *pexMode) { MV_U32 pexData; /* Parameter checking */ if (PEX_DEFAULT_IF != pexIf) { if (pexIf >= mvCtrlPexMaxIfGet()) { mvOsPrintf("mvPexModeGet: ERR. Invalid PEX interface %d\n",pexIf); return MV_ERROR; } } pexData = MV_REG_READ(PEX_CTRL_REG(pexIf)); switch (pexData & PXCR_DEV_TYPE_CTRL_MASK) { case PXCR_DEV_TYPE_CTRL_CMPLX: pexMode->pexType = MV_PEX_ROOT_COMPLEX; break; case PXCR_DEV_TYPE_CTRL_POINT: pexMode->pexType = MV_PEX_END_POINT; break; } /* Check if we have link */ if (MV_REG_READ(PEX_STATUS_REG(pexIf)) & PXSR_DL_DOWN) { pexMode->pexLinkUp = MV_FALSE; /* If there is no link, the auto negotiation data is worthless */ pexMode->pexWidth = MV_PEX_WITDH_INVALID; } else { pexMode->pexLinkUp = MV_TRUE; /* We have link. The link width is now valid */ pexData = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_LINK_CTRL_STAT_REG)); pexMode->pexWidth = ((pexData & PXLCSR_NEG_LNK_WDTH_MASK) >> PXLCSR_NEG_LNK_WDTH_OFFS); } return MV_OK; }
/******************************************************************************* * mvPexModeGet - Get Pex Mode * * DESCRIPTION: * * INPUT: * pexIf - PEX interface number. * * OUTPUT: * pexMode - Pex mode structure * * RETURN: * MV_OK on success , MV_ERROR otherwise * *******************************************************************************/ MV_U32 mvPexModeGet(MV_U32 pexIf, MV_PEX_MODE *pexMode) { MV_U32 pexData; if (pexIf >= MV_PEX_MAX_IF) return MV_BAD_PARAM; #if 0 /* maen - disabled because there is a conflict with SysPexInit sysPexInit need pexMode, however pexHalData[pexIf].maxPexIf is needed in mvPexModeGe */ */ /* Parameter checking */ if (PEX_DEFAULT_IF != pexIf) { if (pexIf >= pexHalData[pexIf].maxPexIf) { mvOsPrintf("mvPexModeGet: ERR. Invalid PEX interface %d\n", pexIf); return MV_ERROR; } } #endif pexData = MV_REG_READ(PEX_CTRL_REG(pexIf)); switch (pexData & PXCR_DEV_TYPE_CTRL_MASK) { case PXCR_DEV_TYPE_CTRL_CMPLX: pexMode->pexType = MV_PEX_ROOT_COMPLEX; break; case PXCR_DEV_TYPE_CTRL_POINT: pexMode->pexType = MV_PEX_END_POINT; break; } /* Check if we have link */ if (MV_REG_READ(PEX_STATUS_REG(pexIf)) & PXSR_DL_DOWN) { pexMode->pexLinkUp = MV_FALSE; /* If there is no link, the auto negotiation data is worthless */ pexMode->pexWidth = MV_PEX_WITDH_INVALID; } else { pexMode->pexLinkUp = MV_TRUE; /* We have link. The link width is now valid */ pexData = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_LINK_CTRL_STAT_REG)); pexMode->pexWidth = ((pexData & PXLCSR_NEG_LNK_WDTH_MASK) >> PXLCSR_NEG_LNK_WDTH_OFFS); } return MV_OK; }
/******************************************************************************* * mvPexModeGet - Get Pex Mode * * DESCRIPTION: * * INPUT: * pexIf - PEX interface number. * * OUTPUT: * pexMode - Pex mode structure * * RETURN: * MV_OK on success , MV_ERROR otherwise * *******************************************************************************/ MV_U32 mvPexModeGet(MV_U32 pexIf, MV_PEX_MODE *pexMode) { MV_U32 pexData; if (pexIf >= MV_PEX_MAX_IF) return MV_BAD_PARAM; pexData = MV_REG_READ(PEX_CTRL_REG(pexIf)); switch (pexData & PXCR_DEV_TYPE_CTRL_MASK) { case PXCR_DEV_TYPE_CTRL_CMPLX: pexMode->pexType = MV_PEX_ROOT_COMPLEX; break; case PXCR_DEV_TYPE_CTRL_POINT: pexMode->pexType = MV_PEX_END_POINT; break; } /* Check if we have link */ /* if (MV_REG_READ(PEX_STATUS_REG(pexIf)) & PXSR_DL_DOWN) { */ if ((MV_REG_READ(PEX_DBG_STATUS_REG(pexIf)) & 0x7f) != 0x7E) { pexMode->pexLinkUp = MV_FALSE; /* If there is no link, the auto negotiation data is worthless */ pexMode->pexWidth = MV_PEX_WITDH_INVALID; } else { /* We have Link negotiation started */ pexMode->pexLinkUp = MV_TRUE; /* We have link. The link width is now valid */ pexData = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_LINK_CTRL_STAT_REG)); pexMode->pexWidth = ((pexData & PXLCSR_NEG_LNK_WDTH_MASK) >> PXLCSR_NEG_LNK_WDTH_OFFS); pexMode->pexGen = ((pexData & PXLCSR_NEG_LNK_GEN_MASK) >> PXLCSR_NEG_LNK_GEN_OFFS); } return MV_OK; }
/******************************************************************************* * mvCtrlHighSpeedSerdesPhyConfig * * DESCRIPTION: This is the main function which configure the * PU sequence of the ser-des * * INPUT: * None. * * OUTPUT: * None. * * RETURN: * MV_OK - success * MV_ERROR - failure *******************************************************************************/ MV_STATUS mvCtrlHighSpeedSerdesPhyConfig(MV_VOID) { MV_U32 serdesLaneNum, pexUnit; MV_U32 uiReg; MV_BIN_SERDES_UNIT_INDX serdesLaneCfg; MV_U32 regAddr[16][11], regVal[16][11]; /* addr/value for each line @ every setup step */ MV_U8 maxSerdesLanes; MV_U32 tmp; MV_U32 tempReg, tempPexReg; MV_U32 pexIf=0; MV_U32 first_busno, next_busno; MV_U32 addr; MV_TWSI_ADDR slave; MV_U32 boardId = mvBoardIdIndexGet(mvBoardIdGet()); maxSerdesLanes = mvCtrlSerdesMaxLanesGet(); if (maxSerdesLanes == 0) return MV_OK; /*Set MPP1 for twsi access */ uiReg = (MV_REG_READ(MPP_CONTROL_REG(1)) & 0x00FFFFFF) | 0x22000000; MV_REG_WRITE(MPP_CONTROL_REG(1), uiReg); /* TWSI init */ slave.type = ADDR7_BIT; slave.address = 0; mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0); mvUartInit(); /* update board configuration (serdes lane topology and speed), if needed */ mvBoardUpdateBoardTopologyConfig(boardId); /* Initialize board configuration database */ boardLaneConfig[0] = SERDES_UNIT_PEX; /* SerDes 0 is alwyas PCIe0*/ boardLaneConfig[1] = boardTopologyConfig[boardId].serdesTopology.lane1; boardLaneConfig[2] = boardTopologyConfig[boardId].serdesTopology.lane2; boardLaneConfig[3] = boardTopologyConfig[boardId].serdesTopology.lane3; memset(regAddr, 0, sizeof(regAddr)); memset(regVal, 0, sizeof(regVal)); /* Check if DRAM is already initialized */ if (MV_REG_READ(REG_BOOTROM_ROUTINE_ADDR) & (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)) { DEBUG_INIT_S("High speed PHY - Version: "); DEBUG_INIT_S(SERDES_VERION); DEBUG_INIT_S(" - 2nd boot - Skip \n"); return MV_OK; } DEBUG_INIT_S("High speed PHY - Version: "); DEBUG_INIT_S(SERDES_VERION); DEBUG_INIT_S(" (COM-PHY-V20) \n"); DEBUG_INIT_FULL_C("SERDES 0=",boardLaneConfig[0],2); DEBUG_INIT_FULL_C("SERDES 1=",boardLaneConfig[1],2); DEBUG_INIT_FULL_C("SERDES 2=",boardLaneConfig[2],2); DEBUG_INIT_FULL_C("SERDES 3=",boardLaneConfig[3],2); /*------------------------------------------*/ /* STEP - 1.5 Power Down PLL, RX, TX all phys */ /*------------------------------------------*/ for (serdesLaneNum = 0; serdesLaneNum < maxSerdesLanes; serdesLaneNum++) { uiReg=MV_REG_READ(COMMON_PHY_CONFIGURATION1_REG(serdesLaneNum)); uiReg &= ~PIN_TX_IDLE_MASK; uiReg &= ~(PHY_POWER_UP_PLL_MASK | PHY_POWER_UP_RX_MASK | PHY_POWER_UP_TX_MASK); MV_REG_WRITE(COMMON_PHY_CONFIGURATION1_REG(serdesLaneNum),uiReg); } mvOsUDelay(10000); /*--------------------------------------------------------*/ /* STEP - 2 Reset PHY and PIPE (Zx: Un-reset, Ax: Reset)*/ /*--------------------------------------------------------*/ for (serdesLaneNum = 0; serdesLaneNum < maxSerdesLanes; serdesLaneNum++) { #ifndef CONFIG_ALP_A375_ZX_REV resetPhyAndPipe(serdesLaneNum, MV_TRUE); #else resetPhyAndPipe(serdesLaneNum, MV_FALSE); #endif } /*--------------------------------*/ /* STEP - 2 Common PHYs Selectors */ /*--------------------------------*/ MV_REG_WRITE(COMMON_PHY_SELECTOR_REG, GetLaneSelectorConfig()); /*--------------------------------*/ /* STEP - 3 Configuration 1 */ /*--------------------------------*/ for (serdesLaneNum = 0; serdesLaneNum < maxSerdesLanes; serdesLaneNum++) { serdesLaneCfg = mvGetSerdesLaneCfg(serdesLaneNum); if(serdesLaneCfg >= SERDES_LAST_UNIT){ return MV_ERROR; } uiReg = MV_REG_READ(COMMON_PHY_CONFIGURATION1_REG(serdesLaneNum)); switch(serdesLaneCfg){ case SERDES_UNIT_USB3: #ifndef CONFIG_ALP_A375_ZX_REV A375_A0_COMMON_PHY_CONFIG(uiReg); #endif uiReg |= PHY_MODE_MASK; /* PHY Mode = USB */ uiReg |= PIPE_SELECT_MASK ; /* Select USB3_PEX */ break; case SERDES_UNIT_PEX: uiReg |= PIPE_SELECT_MASK ; /* Select USB3_PEX */ #ifndef CONFIG_ALP_A375_ZX_REV uiReg &= ~(PHY_MODE_MASK); /* PHY Mode = PEX */ A375_A0_COMMON_PHY_CONFIG(uiReg); #endif break; case SERDES_UNIT_SGMII: case SERDES_UNIT_SATA: #ifndef CONFIG_ALP_A375_ZX_REV A375_A0_COMMON_PHY_CONFIG(uiReg); #endif uiReg &= ~(PIPE_SELECT_MASK); /* Select SATA_SGMII */ uiReg |= POWER_UP_IVREF_MASK; /* Power UP IVREF = Power Up */ break; case SERDES_UNIT_UNCONNECTED: default: break; } /* Serdes speed config */ tmp = getSerdesSpeedConfig(boardId, serdesLaneCfg); uiReg &= ~(GEN_RX_MASK); /* SERDES RX Speed config */ uiReg |= tmp<<GEN_RX_OFFS; uiReg &= ~(GEN_TX_MASK); /* SERDES TX Speed config */ uiReg |= tmp<<GEN_TX_OFFS; MV_REG_WRITE(COMMON_PHY_CONFIGURATION1_REG(serdesLaneNum),uiReg); } #ifndef CONFIG_ALP_A375_ZX_REV /*------------------------------------------*/ /* STEP - 3.5 Unreset PHY and PIPE(only Ax)*/ /*------------------------------------------*/ for (serdesLaneNum = 0; serdesLaneNum < maxSerdesLanes; serdesLaneNum++) { resetPhyAndPipe(serdesLaneNum, MV_FALSE); } #endif /*----------------------------------------*/ /* STEP - 4 COMPHY register configuration */ /*----------------------------------------*/ for (serdesLaneNum = 0; serdesLaneNum < maxSerdesLanes; serdesLaneNum++) { serdesLaneCfg = mvGetSerdesLaneCfg(serdesLaneNum); if(serdesLaneCfg >= SERDES_LAST_UNIT){ return MV_ERROR; } switch(serdesLaneCfg){ case SERDES_UNIT_PEX: MV_REG_WRITE(RESET_AND_CLOCK_CONTROL_REG(serdesLaneNum),0x25); /* Enable soft_reset*/ MV_REG_WRITE(POWER_AND_PLL_CONTROL_REG(serdesLaneNum),0xFC60); /* PHY Mode = PEX */ #ifndef CONFIG_ALP_A375_ZX_REV MV_REG_WRITE(MISCELLANEOUS_CONTROL0_REG(serdesLaneNum),0x6017); /* REFCLK SEL =0x0 (100Mhz) */ MV_REG_WRITE(INTERFACE_REG1_REG(serdesLaneNum),0x1400); /* PHY_Gen_Max = 5G */ MV_REG_WRITE(DIGITAL_LOOPBACK_ENABLE_REG(serdesLaneNum),0x400); /* SEL_Bits = 20-Bit */ A375_A0_RESET_DFE_SEQUENCE(serdesLaneNum); #else MV_REG_WRITE(KVCO_CALOBRATION_CONTROL_REG(serdesLaneNum),0x40); /* use_max_pll_rate=0x0, ext_force_cal_done=0x0 */ #endif MV_REG_WRITE(RESET_AND_CLOCK_CONTROL_REG(serdesLaneNum),0x24); /* Release soft_reset */ break; case SERDES_UNIT_USB3: MV_REG_WRITE(RESET_AND_CLOCK_CONTROL_REG(serdesLaneNum),0x21); /* Enable soft_reset*/ MV_REG_WRITE(POWER_AND_PLL_CONTROL_REG(serdesLaneNum),0xFCA0); /* PHY Mode = USB3 */ #ifndef CONFIG_ALP_A375_ZX_REV MV_REG_WRITE(LANE_CONFIGURATION_4_REG(serdesLaneNum),0x13); /* Ref_Clk =100Mhz */ MV_REG_WRITE(MISCELLANEOUS_CONTROL0_REG(serdesLaneNum),0x6017); /* REFCLK SEL =0x0 (100Mhz) */ MV_REG_WRITE(INTERFACE_REG1_REG(serdesLaneNum),0x1400); /* PHY_Gen_Max = 5G */ MV_REG_WRITE(DIGITAL_LOOPBACK_ENABLE_REG(serdesLaneNum),0x400); /* SEL_Bits = 20-Bit */ A375_A0_RESET_DFE_SEQUENCE(serdesLaneNum); #else MV_REG_WRITE(KVCO_CALOBRATION_CONTROL_REG(serdesLaneNum),0x40); /* use_max_pll_rate=0x0, ext_force_cal_done=0x0 */ MV_REG_WRITE(GENERETION_2_SETTINGS_1_REG(serdesLaneNum),0x149); /* Mulitiple frequency setup */ #endif MV_REG_WRITE(RESET_AND_CLOCK_CONTROL_REG(serdesLaneNum),0x20); /* Release soft_reset */ break; case SERDES_UNIT_SATA: MV_REG_WRITE(POWER_AND_PLL_CONTROL_REG(serdesLaneNum),0xFC01); /* PHY Mode = SATA */ MV_REG_WRITE(MISCELLANEOUS_CONTROL0_REG(serdesLaneNum),0x6417); /* REFCLK SEL =0x1 (25Mhz) */ #ifndef CONFIG_ALP_A375_ZX_REV MV_REG_WRITE(INTERFACE_REG1_REG(serdesLaneNum),0x1400); /* PHY_Gen_Max = 5G */ MV_REG_WRITE(DIGITAL_LOOPBACK_ENABLE_REG(serdesLaneNum),0x400); /* SEL_Bits = 20-Bit */ MV_REG_WRITE(DIGITAL_RESERVED0_REG(serdesLaneNum),0xE); /* Reg_sq_de_glitch_en */ A375_A0_RESET_DFE_SEQUENCE(serdesLaneNum); #else MV_REG_WRITE(RESERVED_46_REG(serdesLaneNum),0xFF00); #endif break; case SERDES_UNIT_SGMII: MV_REG_WRITE(POWER_AND_PLL_CONTROL_REG(serdesLaneNum),0xFC81); /* PHY Mode = SGMII */ /*moti need to change offset*/ MV_REG_WRITE(DIGITAL_LOOPBACK_ENABLE_REG(serdesLaneNum),0x0); /* SEL_BITS = 0x0 (10-bits mode) */ MV_REG_WRITE(MISCELLANEOUS_CONTROL0_REG(serdesLaneNum),0x6417); /* REFCLK SEL =0x1 (25Mhz) */ #ifndef CONFIG_ALP_A375_ZX_REV MV_REG_WRITE(DIGITAL_RESERVED0_REG(serdesLaneNum),0xE); /* Reg_sq_de_glitch_en */ A375_A0_RESET_DFE_SEQUENCE(serdesLaneNum); #else MV_REG_WRITE(RESERVED_46_REG(serdesLaneNum),0xFF00); /* Enable soft_reset*/ #endif MV_REG_WRITE(PHY_ISOLATION_MODE_CONTROL_REG(serdesLaneNum),0x166); /* Set PHY_GEN_TX/RX to 1.25Gbps */ break; case SERDES_UNIT_UNCONNECTED: default: break; } } /*------------------------------------------*/ /* STEP - 4.5 Power up PLL, RX, TX all phys */ /*------------------------------------------*/ for (serdesLaneNum = 0; serdesLaneNum < maxSerdesLanes; serdesLaneNum++) { uiReg=MV_REG_READ(COMMON_PHY_CONFIGURATION1_REG(serdesLaneNum)); uiReg |= (PHY_POWER_UP_PLL_MASK | PHY_POWER_UP_RX_MASK | PHY_POWER_UP_TX_MASK); MV_REG_WRITE(COMMON_PHY_CONFIGURATION1_REG(serdesLaneNum),uiReg); } #ifndef CONFIG_ALP_A375_ZX_REV mvOsUDelay(5000); /*--------------------------------------------------------------------*/ /* STEP - 4.6 (Only SGMII/SATA): WAIT for PHY Power up sequence to finish */ /*--------------------------------------------------------------------*/ for (serdesLaneNum = 0; serdesLaneNum < maxSerdesLanes; serdesLaneNum++) { serdesLaneCfg = mvGetSerdesLaneCfg(serdesLaneNum); if(serdesLaneCfg >= SERDES_LAST_UNIT){ return MV_ERROR; } switch(serdesLaneCfg){ case SERDES_UNIT_SATA: case SERDES_UNIT_SGMII: uiReg = MV_REG_READ(COMMON_PHY_STATUS1_REG(serdesLaneNum)); if ((uiReg & 0x6) != 0x6) { DEBUG_INIT_S("Phy Power up did't finished\n"); return MV_ERROR; } case SERDES_UNIT_UNCONNECTED: default: break; } } #endif /*----------------------------------------*/ /* STEP - 5 PEX Only */ /*----------------------------------------*/ for (pexUnit = 0; pexUnit < 4; pexUnit++) { if (boardLaneConfig[pexUnit] != SERDES_UNIT_PEX) continue; tmp = MV_REG_READ(PEX_CAPABILITIES_REG(pexUnit)); DEBUG_RD_REG(PEX_CAPABILITIES_REG(pexUnit), tmp ); tmp &= ~(0xf<<20); tmp |= (0x4<<20); MV_REG_WRITE(PEX_CAPABILITIES_REG(pexUnit),tmp); DEBUG_WR_REG(PEX_CAPABILITIES_REG(pexUnit),tmp); } tmp = MV_REG_READ(SOC_CTRL_REG); DEBUG_RD_REG(SOC_CTRL_REG, tmp); tmp &= ~(0x03); tmp |= 0x1<<PCIE0_ENABLE_OFFS; if (boardLaneConfig[1] == SERDES_UNIT_PEX) tmp |= 0x1<<PCIE1_ENABLE_OFFS; MV_REG_WRITE(SOC_CTRL_REG, tmp); DEBUG_WR_REG(SOC_CTRL_REG, tmp); /*----------------------------------------*/ /* STEP - 6 PEX Only - support gen1/gen2 */ /*----------------------------------------*/ next_busno = 0; mvOsDelay(150); for (pexIf = 0; pexIf < 2; pexIf++) // only pexIf 0 on { if (boardLaneConfig[pexIf] != SERDES_UNIT_PEX) continue; tmp = MV_REG_READ(PEX_DBG_STATUS_REG(pexIf)); DEBUG_RD_REG(PEX_DBG_STATUS_REG(pexIf), tmp); first_busno = next_busno; if ((tmp & 0x7f) == 0x7E) { next_busno++; tempPexReg = MV_REG_READ((PEX_CFG_DIRECT_ACCESS(pexIf, PEX_LINK_CAPABILITY_REG))); DEBUG_RD_REG((PEX_CFG_DIRECT_ACCESS(pexIf, PEX_LINK_CAPABILITY_REG)),tempPexReg ); tempPexReg &= (0xF); if (tempPexReg == 0x2) { tempReg = (MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_LINK_CTRL_STAT_REG)) & 0xF0000) >> 16; DEBUG_RD_REG(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_LINK_CTRL_STAT_REG),tempReg ); /* check if the link established is GEN1 */ if (tempReg == 0x1) { mvPexLocalBusNumSet(pexIf, first_busno); mvPexLocalDevNumSet(pexIf, 1); DEBUG_INIT_FULL_S("PEX: pexIf "); DEBUG_INIT_FULL_D(pexIf, 1); DEBUG_INIT_FULL_S(", link is Gen1, checking the EP capability \n"); /* link is Gen1, check the EP capability */ addr = mvPexConfigRead(pexIf, first_busno, 0, 0, 0x34) & 0xFF; DEBUG_INIT_FULL_C("mvPexConfigRead: return addr=0x%x", addr,4); if (addr == 0xff) { DEBUG_INIT_FULL_C("mvPexConfigRead: return 0xff -->PEX (%d): Detected No Link.", pexIf,1); continue; } while ((mvPexConfigRead(pexIf, first_busno, 0, 0, addr) & 0xFF) != 0x10) { addr = (mvPexConfigRead(pexIf, first_busno, 0, 0, addr) & 0xFF00) >> 8; } if ((mvPexConfigRead(pexIf, first_busno, 0, 0, addr + 0xC) & 0xF) >= 0x2) { tmp = MV_REG_READ(PEX_LINK_CTRL_STATUS2_REG(pexIf)); DEBUG_RD_REG(PEX_LINK_CTRL_STATUS2_REG(pexIf),tmp ); tmp &=~(BIT0 | BIT1); tmp |= BIT1; MV_REG_WRITE(PEX_LINK_CTRL_STATUS2_REG(pexIf),tmp); DEBUG_WR_REG(PEX_LINK_CTRL_STATUS2_REG(pexIf),tmp); tmp = MV_REG_READ(PEX_CTRL_REG(pexIf)); DEBUG_RD_REG(PEX_CTRL_REG(pexIf), tmp ); tmp |= BIT10; MV_REG_WRITE(PEX_CTRL_REG(pexIf),tmp); DEBUG_WR_REG(PEX_CTRL_REG(pexIf),tmp); mvOsUDelay(10000);/* We need to wait 10ms before reading the PEX_DBG_STATUS_REG in order not to read the status of the former state*/ DEBUG_INIT_FULL_S("PEX: pexIf "); DEBUG_INIT_FULL_D(pexIf, 1); DEBUG_INIT_FULL_S(", Link upgraded to Gen2 based on client cpabilities \n"); } else { DEBUG_INIT_FULL_S("PEX: pexIf "); DEBUG_INIT_FULL_D(pexIf, 1); DEBUG_INIT_FULL_S(", remains Gen1\n"); } } }
MV_STATUS mvPexInit(MV_U32 pexIf, MV_PEX_TYPE pexType, MV_PEX_HAL_DATA *halData) { MV_PEX_MODE pexMode; MV_U32 regVal; MV_U32 status; MV_U16 ctrlModel, phyRegVal; mvOsMemcpy(&pexHalData[pexIf], halData, sizeof(MV_PEX_HAL_DATA)); /* First implement Guideline (GL# PCI Express-2) Wrong Default Value */ /* to Transmitter Output Current (TXAMP) Relevant for: 88F5181-A1/B0/B1 */ /* and 88F5281-B0 and above, 88F5182, 88F5082, 88F5181L, 88F6082/L */ ctrlModel = pexHalData[pexIf].ctrlModel; if ((ctrlModel != MV_1281_DEV_ID) && (ctrlModel != MV_6281_DEV_ID) && (ctrlModel != MV_6282_DEV_ID) && (ctrlModel != MV_6280_DEV_ID) && (ctrlModel != MV_6192_DEV_ID) && (ctrlModel != MV_6190_DEV_ID) && (ctrlModel != MV_6180_DEV_ID) && (ctrlModel != MV_6183_DEV_ID) && (ctrlModel != MV_6183L_DEV_ID) && (ctrlModel != MV_78100_DEV_ID) && (ctrlModel != MV_78200_DEV_ID) && (ctrlModel != MV_76100_DEV_ID) && (ctrlModel != MV_6323_DEV_ID) && (ctrlModel != MV_6322_DEV_ID) && (ctrlModel != MV_6321_DEV_ID) && (ctrlModel != MV_78XX0_DEV_ID) && (ctrlModel != MV_6510_DEV_ID) && (ctrlModel != MV_6530_DEV_ID) && (ctrlModel != MV_6550_DEV_ID) && (ctrlModel != MV_6560_DEV_ID) && (ctrlModel != MV_6710_DEV_ID) && (ctrlModel != MV_78130_DEV_ID) && (ctrlModel != MV_78160_DEV_ID) && (ctrlModel != MV_78230_DEV_ID) && (ctrlModel != MV_78260_DEV_ID) && (ctrlModel != MV_78460_DEV_ID) && (ctrlModel != MV_78000_DEV_ID)) { /* Read current value of TXAMP */ MV_REG_WRITE(PEX_PHY_ACCESS_REG(pexIf), 0x80820000); /* Write the read command */ regVal = MV_REG_READ(PEX_PHY_ACCESS_REG(pexIf)); /* Extract the data */ /* Prepare new data for write */ regVal &= ~0x7; /* Clear bits [2:0] */ regVal |= 0x4; /* Set the new value */ regVal &= ~0x80000000; /* Set "write" command */ MV_REG_WRITE(PEX_PHY_ACCESS_REG(pexIf), regVal); /* Write the write command */ } else { /* Implement 1.0V termination GL for 88F1281 device only */ /* BIT0 - Common mode feedback */ /* BIT3 - TxBuf, extra drive for 1.0V termination */ if (ctrlModel == MV_1281_DEV_ID) { MV_REG_WRITE(PEX_PHY_ACCESS_REG(pexIf), 0x80860000); /* Write the read command */ regVal = MV_REG_READ(0x41b00); /* Extract the data */ regVal |= (BIT0 | BIT3); regVal &= ~0x80000000; /* Set "write" command */ MV_REG_WRITE(PEX_PHY_ACCESS_REG(pexIf), regVal); /* Write the write command */ MV_REG_WRITE(0x31b00, 0x80860000); /* Write the read command */ regVal = MV_REG_READ(0x31b00); /* Extract the data */ regVal |= (BIT0 | BIT3); regVal &= ~0x80000000; /* Set "write" command */ MV_REG_WRITE(0x31b00, regVal); /* Write the write command */ } } if ((ctrlModel == MV_6281_DEV_ID) || (ctrlModel == MV_6282_DEV_ID) || (ctrlModel == MV_6280_DEV_ID) || (ctrlModel == MV_6192_DEV_ID) || (ctrlModel == MV_6190_DEV_ID) || (ctrlModel == MV_6180_DEV_ID)) { regVal = MV_REG_READ(0x100e4); /* This register currently doesn't appear in the FS */ regVal |= 0x3 << 25; MV_REG_WRITE(0x100e4, regVal); } if (ctrlModel == MV_6282_DEV_ID) { mvPexPhyRegRead(pexIf, 0x92, &phyRegVal); phyRegVal &= ~(0x80F0); phyRegVal |= 0x8080; mvPexPhyRegWrite(pexIf, 0x92, phyRegVal); } else if ((ctrlModel == MV_6510_DEV_ID) || (ctrlModel == MV_6530_DEV_ID) || (ctrlModel == MV_6550_DEV_ID) || (ctrlModel == MV_6560_DEV_ID)) { regVal = MV_REG_READ(0x100e4); /* This register currently doesn't appear in the FS */ regVal |= 0x3 << 25; MV_REG_WRITE(0x100e4, regVal); mvPexPhyRegRead(pexIf, 0x92, &phyRegVal); phyRegVal &= ~(0x80F0); phyRegVal |= 0x8080; mvPexPhyRegWrite(pexIf, 0x92, phyRegVal); } if (mvPexModeGet(pexIf, &pexMode) != MV_OK) { mvOsPrintf("PEX init ERR. mvPexModeGet failed (pexType=%d)\n", pexMode.pexType); return MV_ERROR; } /* Check that required PEX type is the one set in reset time */ if (pexType != pexMode.pexType) { /* No Link. Shut down the Phy */ mvPexPhyPowerDown(pexIf); mvOsPrintf("PEX init ERR. PEX type sampled mismatch (%d,%d)\n", pexType, pexMode.pexType); return MV_ERROR; } if (MV_PEX_ROOT_COMPLEX == pexType) { mvPexLocalBusNumSet(pexIf, PEX_HOST_BUS_NUM(pexIf)); mvPexLocalDevNumSet(pexIf, PEX_HOST_DEV_NUM(pexIf)); /* Local device master Enable */ mvPexMasterEnable(pexIf, MV_TRUE); /* Local device slave Enable */ mvPexSlaveEnable(pexIf, mvPexLocalBusNumGet(pexIf), mvPexLocalDevNumGet(pexIf), MV_TRUE); /* Interrupt disable */ status = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_STATUS_AND_COMMAND)); status |= PXSAC_INT_DIS; MV_REG_WRITE(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_STATUS_AND_COMMAND), status); if (ctrlModel == MV_6710_DEV_ID) { /* PEX capability */ regVal = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_LINK_CAPABILITY_REG)) & 0xF; if (regVal == 0x2) { /* KW40 set to Gen 2.0 - conf_auto_speed_change */ /* when bit is set, link will issue link speed change to the max link speed possible */ regVal = MV_REG_READ(PEX_CTRL_REG(pexIf)) | (1<<10); MV_REG_WRITE(PEX_CTRL_REG(pexIf), regVal); } } } else { /* TODO: 14/12/10 - requested by CV to support EP Compliance */ MV_REG_WRITE(PEX_DBG_CTRL_REG(pexIf), 0x0F62F0C0); MV_REG_WRITE(PEX_PHY_ACCESS_REG(pexIf), (0x80C2 << 16)); regVal = MV_REG_READ(PEX_PHY_ACCESS_REG(pexIf)) & 0xFFFF; MV_REG_WRITE(PEX_PHY_ACCESS_REG(pexIf), (0xC2 << 16) | regVal | (1 << 2)); MV_REG_WRITE(PEX_PHY_ACCESS_REG(pexIf), (0x8080 << 16)); regVal = MV_REG_READ(PEX_PHY_ACCESS_REG(pexIf)) & 0xFFFF; MV_REG_WRITE(PEX_PHY_ACCESS_REG(pexIf), (0x80 << 16) | regVal | (0x2 << 1)); } mvSysPexCpuIfEnable(pexIf); /* now wait 1ms to be sure the link is valid */ mvOsDelay(100); /* Check if we have link */ if (MV_REG_READ(PEX_STATUS_REG(pexIf)) & PXSR_DL_DOWN) { /*mvOsPrintf("PEX%d interface detected no Link.\n", pexIf);*/ return MV_NO_SUCH; } #if 0 if (MV_PEX_WITDH_X1 == pexMode.pexWidth) mvOsPrintf("PEX%d interface detected Link X1\n", pexIf); else mvOsPrintf("PEX%d interface detected Link X4\n", pexIf); #endif #ifdef PCIE_VIRTUAL_BRIDGE_SUPPORT mvPexVrtBrgInit(pexIf); #endif return MV_OK; }
/******************************************************************************* * mvBoardIdGet - Get Board model * * DESCRIPTION: * This function returns board ID. * Board ID is 32bit word constructed of board model (16bit) and * board revision (16bit) in the following way: 0xMMMMRRRR. * * INPUT: * None. * * OUTPUT: * None. * * RETURN: * 32bit board ID number, '-1' if board is undefined. * *******************************************************************************/ MV_U32 mvBoardIdGet(MV_VOID) { MV_U32 tmpBoardId = -1; BOARD_DATA boardData; if(gBoardId != -1) return gBoardId; #if defined(MV_88F1181) if(boardEepromGet(&boardData) == MV_OK) { tmpBoardId = (MV_U32)boardData.boardId; } else { /* until we have relevant data in twsi then we will detect the board type from sdram config reg */ if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) { tmpBoardId = DB_88F1181_DDR2; } else { tmpBoardId = DB_88F1181_DDR1; } } #elif defined(MV_88F5181) if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) { } else /* DDR1 */ { #if defined(RD_88F5182) tmpBoardId = RD_88F5182_2XSATA; #elif defined(RD_88F5182_3) tmpBoardId = RD_88F5182_2XSATA3; #elif defined(RD_88W8660) tmpBoardId = RD_88W8660_DDR1; #elif defined(RD_88F5181L_FE) tmpBoardId = RD_88F5181L_VOIP_FE; #elif defined(RD_88F5181L_GE) tmpBoardId = RD_88F5181L_VOIP_GE; #elif defined(MV_POS_NAS) tmpBoardId = RD_88F5181_POS_NAS; #elif defined(MV_VOIP) tmpBoardId = RD_88F5181_VOIP; #elif defined(DB_PRPMC) tmpBoardId = DB_88F5181_DDR1_PRPMC; #elif defined(DB_PEX_PCI) tmpBoardId = DB_88F5181_DDR1_PEXPCI; #else tmpBoardId = RD_88F5181_POS_NAS; #endif } if(tmpBoardId != -1) { gBoardId = tmpBoardId; return tmpBoardId; } //jack20060626 // if(boardEepromGet(&boardData) == MV_OK) // { // tmpBoardId = (MV_U32)boardData.boardId; // } // else { /* until we have relevant data in twsi then we will detect the board type from sdram config reg */ if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) { if((mvCtrlModelGet() == MV_5281_DEV_ID)&&(mvCtrlRevGet() >= 0x1)) { tmpBoardId = DB_88F5X81_DDR2; } else if(mvCtrlModelGet() == MV_8660_DEV_ID) { tmpBoardId = DB_88W8660_DDR2; } else if(mvCtrlModelGet() == MV_5182_DEV_ID) { tmpBoardId = DB_88F5182_DDR2; } else { tmpBoardId = DB_88F5181_5281_DDR2; } } else /* DDR1 */ { if (MV_REG_READ(PCI_ARBITER_CTRL_REG(0)) & PACR_ARB_ENABLE) /* arbiter enabled*/ { if((mvCtrlModelGet() == MV_5281_DEV_ID)&&(mvCtrlRevGet() >= 0x1)) { tmpBoardId = DB_88F5X81_DDR1; } else { tmpBoardId = DB_88F5181_5281_DDR1; } } else /* arbiter disabled */ { if ((MV_REG_READ(PEX_CTRL_REG(0)) & PXCR_DEV_TYPE_CTRL_MASK) == PXCR_DEV_TYPE_CTRL_CMPLX) /*root complex*/ { tmpBoardId = DB_88F5181_DDR1_PRPMC; } else if ((MV_REG_READ(PEX_CTRL_REG(0)) & PXCR_DEV_TYPE_CTRL_MASK) == PXCR_DEV_TYPE_CTRL_POINT) /*end point*/ { tmpBoardId = DB_88F5181_DDR1_PEXPCI; } } } } gBoardId = tmpBoardId; return tmpBoardId; #else # error "CHIP not selected" #endif }