blob: a805e615639e96c85053137776a0113b76ac5971 [file] [log] [blame]
/*******************************************************************************
Copyright (C) Marvell International Ltd. and its affiliates
This software file (the "File") is owned and distributed by Marvell
International Ltd. and/or its affiliates ("Marvell") under the following
alternative licensing terms. Once you have made an election to distribute the
File under one of the following license alternatives, please (i) delete this
introductory statement regarding license alternatives, (ii) delete the two
license alternatives that you have not elected to use and (iii) preserve the
Marvell copyright notice above.
********************************************************************************
Marvell Commercial License Option
If you received this File from Marvell and you have entered into a commercial
license agreement (a "Commercial License") with Marvell, the File is licensed
to you under the terms of the applicable Commercial License.
********************************************************************************
Marvell GPL License Option
If you received this File from Marvell, you may opt to use, redistribute and/or
modify this File in accordance with the terms and conditions of the General
Public License Version 2, June 1991 (the "GPL License"), a copy of which is
available along with the File in the license.txt file or by writing to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
DISCLAIMED. The GPL License provides additional details about this warranty
disclaimer.
********************************************************************************
Marvell BSD License Option
If you received this File from Marvell, you may opt to use, redistribute and/or
modify this File under the following licensing terms.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Marvell nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
#include "config_marvell.h" /* Required to identify SOC and Board */
#include "mvHighSpeedEnvSpec.h"
#include "mvHighSpeedTopologySpec.h"
#include "mvSysEnvLib.h"
#include "mvCtrlPex.h"
#include "printf.h"
#if defined (MV88F68XX)
#elif defined (MV88F69XX)
#else
#error "No device is defined"
#endif
#define SLOWDOWN mvOsUDelay(50);
#ifdef REGISTER_TRACE_DEBUG
static MV_U32 _MV_REG_READ(MV_U32 regAddr)
{
putstring("\n >>> MV_REG_READ. regAddr=0x");
putdata(INTER_REGS_BASE | (regAddr), 8);
putstring(" regData=0x");
MV_U32 regData = MV_MEMIO_LE32_READ((INTER_REGS_BASE | (regAddr)));
putdata(regData, 8);
return regData;
}
static MV_VOID _MV_REG_WRITE(MV_U32 regAddr, MV_U32 regData)
{
putstring("\n >>> MV_REG_WRITE. regAddr=0x");
putdata(INTER_REGS_BASE | (regAddr), 8);
putstring(" regData=0x");
putdata(regData, 8);
MV_MEMIO_LE32_WRITE((INTER_REGS_BASE | (regAddr)), (regData));
}
#undef MV_REG_WRITE
#undef MV_REG_READ
#define MV_REG_WRITE _MV_REG_WRITE
#define MV_REG_READ _MV_REG_READ
#endif /*REGISTER_TRACE_DEBUG*/
#define SERDES_VERION "2.0"
#define ENDED_OK "High speed PHY - Ended Successfully\n"
#define LINK_WAIT_CNTR 100
#define LINK_WAIT_SLEEP 100
#define MAX_UNIT_NUMB 4
#define TOPOLOGY_TEST_OK 0
#define WRONG_NUMBER_OF_UNITS 1
#define SERDES_ALREADY_IN_USE 2
#define UNIT_NUMBER_VIOLATION 3
/* SerdesLaneInUseCount contains the exact amount of serdes lanes needed per type */
MV_U8 SerdesLaneInUseCount[MAX_UNITS_ID][MAX_UNIT_NUMB] =
{
/* if PEX0 is defines as PEXx4 it can use 4 lanes; in PEXx1 only 1
the value for PEX 0 is updated in mvHwsSerdesTopologyVerify function */
/* 0 1 2 3 */
{ 4, 1, 1, 1 }, /* PEX */
{ 1, 1, 1, 1 }, /* ETH_SGMII */
{ 1, 1, 0, 0 }, /* USB3H */
{ 1, 1, 1, 0 }, /* USB3D */
{ 1, 1, 1, 1 }, /* SATA */
{ 1, 0, 0, 0 }, /* QSGMII */
{ 4, 0, 0, 0 }, /* XAUI */
{ 2, 0, 0, 0 } /* RXAUI */
};
/* serdesUnitCount count unit number. (i.e a single XAUI is counted as 1 unit) */
MV_U8 serdesUnitCount[MAX_UNITS_ID] = {0};
/* Selector mapping for A380-A0 and A390-Z1 */
MV_U8 commonPhysSelectorsSerdesRev2Map[LAST_SERDES_TYPE][MAX_SERDES_LANES] =
{
/* 0 1 2 3 4 5 6 */
{ 0x1, 0x1, NA, NA, NA, NA, NA }, /* PEX0 */
{ NA, NA, 0x1, NA, 0x1, NA, 0x1 }, /* PEX1 */
{ NA, NA, NA, NA, 0x7, 0x1, NA }, /* PEX2 */
{ NA, NA, NA, 0x1, NA, NA, NA }, /* PEX3 */
{ 0x2, 0x3, NA, NA, NA, NA, NA }, /* SATA0 */
{ NA, NA, 0x3, NA, NA, NA, NA }, /* SATA1 */
{ NA, NA, NA, NA, 0x6, 0x2, NA }, /* SATA2 */
{ NA, NA, NA, 0x3, NA, NA, NA }, /* SATA3 */
{ 0x3, 0x4, NA, NA, NA, NA, NA }, /* SGMII0 */
{ NA, 0x5, 0x4, NA, 0x3, NA, NA }, /* SGMII1 */
{ NA, NA, NA, 0x4, NA, 0x3, NA }, /* SGMII2 */
{ NA, 0x7, NA, NA, NA, NA, NA }, /* QSGMII */
{ NA, 0x6, NA, NA, 0x4, NA, NA }, /* USB3_HOST0 */
{ NA, NA, NA, 0x5, NA, 0x4, NA }, /* USB3_HOST1 */
{ NA, NA, NA, 0x6, 0x5, 0x5, NA }, /* USB3_DEVICE */
#ifdef MV88F69XX
{ 0x4, 0x8, NA, NA, NA, NA, NA }, /* SGMIIv3-0 */
{ NA, 0x9, 0x5, NA, NA, NA, NA }, /* SGMIIv3-1 */
{ NA, NA, NA, 0x7, NA, 0x6, NA }, /* SGMIIv3-2 */
{ NA, NA, NA, NA, 0x8, NA, 0x2 }, /* SGMIIv3-3 */
{ NA, NA, NA, 0x8, 0x9, 0x8, 0x4 }, /* XAUI */
{ NA, NA, NA, NA, NA, 0x8, 0x4 }, /* RXAUI */
#endif
{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, NA } /* DEFAULT_SERDES */
};
/* Selector mapping for PEX by 4 confiuration */
MV_U8 commonPhysSelectorsPexBy4Lanes[] = { 0x1, 0x2, 0x2, 0x2 };
static const char *serdesTypeToString[] = {
"PCIe0 ",
"PCIe1 ",
"PCIe2 ",
"PCIe3 ",
"SATA0 ",
"SATA1 ",
"SATA2 ",
"SATA3 ",
"SGMII0 ",
"SGMII1 ",
"SGMII2 ",
"QSGMII ",
"USB3 HOST0 ",
"USB3 HOST1 ",
"USB3 DEVICE",
"SGMIIv3-0 ",
"SGMIIv3-1 ",
"SGMIIv3-2 ",
"SGMIIv3-3 ",
"XAUI ",
"RXAUI ",
"DEFAULT SERDES",
"LAST_SERDES_TYPE"
};
typedef struct serdesUnitData {
MV_U8 serdesUnitId;
MV_U8 serdesUnitNum;
} MV_SERDES_UNIT_P;
static MV_SERDES_UNIT_P serdesTypeToUnitInfo[] = {
{ PEX_UNIT_ID , 0, },
{ PEX_UNIT_ID , 1, },
{ PEX_UNIT_ID , 2, },
{ PEX_UNIT_ID , 3, },
{ SATA_UNIT_ID, 0, },
{ SATA_UNIT_ID, 1, },
{ SATA_UNIT_ID, 2, },
{ SATA_UNIT_ID, 3, },
{ SGMII_UNIT_ID,0, },
{ SGMII_UNIT_ID,1, },
{ SGMII_UNIT_ID,2, },
{ QSGMII_UNIT_ID, 0, },
{ USB3H_UNIT_ID, 0, },
{ USB3H_UNIT_ID, 1, },
{ USB3D_UNIT_ID, 0, },
{ SGMII_UNIT_ID,0, },
{ SGMII_UNIT_ID,1, },
{ SGMII_UNIT_ID,2, },
{ SGMII_UNIT_ID,3, },
{ XAUI_UNIT_ID, 0, },
{ RXAUI_UNIT_ID, 0, },
};
/******************************** Sequences DB ********************************/
/******************/
/* SATA and SGMII */
/******************/
MV_OP_PARAMS sataPort0PowerUpParams[] =
{
/* unitunitBaseReg unitOffset mask SATA data waitTime numOfLoops */
{ SATA_VENDOR_PORT_0_REG_ADDR, 0x38000, 0xFFFFFFFF, { 0x48, }, 0, 0 }, /* Access to reg 0x48(OOB param 1) */
{ SATA_VENDOR_PORT_0_REG_DATA, 0x38000, 0xF03F, { 0x6018, }, 0, 0 }, /* OOB ComWake and ComReset spacing upper limit data */
{ SATA_VENDOR_PORT_0_REG_ADDR, 0x38000, 0xFFFFFFFF, { 0xA, }, 0, 0 }, /* Access to reg 0xA(PHY Control) */
{ SATA_VENDOR_PORT_0_REG_DATA, 0x38000, 0x3000, { 0x0, }, 0, 0 }, /* Rx clk and Tx clk select non-inverted mode */
{ SATA_CTRL_REG_IND_ADDR, 0x38000, 0xFFFFFFFF, { 0x0, }, 0, 0 }, /* Power Down Sata addr */
{ SATA_CTRL_REG_IND_DATA, 0x38000, 0xFFFF00FF, { 0xC40040,}, 0, 0 }, /* Power Down Sata Port 0 */
};
MV_OP_PARAMS sataPort1PowerUpParams[] =
{
/* unitunitBaseReg unitOffset mask SATA data waitTime numOfLoops */
{ SATA_VENDOR_PORT_1_REG_ADDR, 0x38000, 0xFFFFFFFF, { 0x48, }, 0, 0 }, /* Access to reg 0x48(OOB param 1) */
{ SATA_VENDOR_PORT_1_REG_DATA, 0x38000, 0xF03F, { 0x6018, }, 0, 0 }, /* OOB ComWake and ComReset spacing upper limit data */
{ SATA_VENDOR_PORT_1_REG_ADDR, 0x38000, 0xFFFFFFFF, { 0xA, }, 0, 0 }, /* Access to reg 0xA(PHY Control) */
{ SATA_VENDOR_PORT_1_REG_DATA, 0x38000, 0x3000, { 0x0, }, 0, 0 }, /* Rx clk and Tx clk select non-inverted mode */
{ SATA_CTRL_REG_IND_ADDR, 0x38000, 0xFFFFFFFF, { 0x0, }, 0, 0 }, /* Power Down Sata addr */
{ SATA_CTRL_REG_IND_DATA, 0x38000, 0xFFFFFF00, { 0xC44000, }, 0, 0 }, /* Power Down Sata Port 1 */
};
/* SATA and SGMII - power up seq */
MV_OP_PARAMS sataAndSgmiiPowerUpParams[] =
{
/* unitBaseReg unitOffset mask SATA data SGMII data waitTime numOfLoops */
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x90006, { 0x80002, 0x80002 }, 0, 0 }, /* Power Up */
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x7800, { 0x6000, 0x6000 }, 0, 0 }, /* Unreset */
{ POWER_AND_PLL_CTRL_REG, 0x800, 0x0E0, { 0x0, 0x80 }, 0, 0 }, /* Phy Selector */
{ MISC_REG, 0x800, 0x440, { 0x440, 0x400 }, 0, 0 } /* Ref clock source select */
};
/* SATA and SGMII - speed config seq */
MV_OP_PARAMS sataAndSgmiiSpeedConfigParams[] =
{
/* unitBaseReg unitOffset mask SATA data SGMII (1.25G) SGMII (3.125G) waitTime numOfLoops */
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x3FC00000, { 0x8800000, 0x19800000, 0x22000000 }, 0, 0 }, /* Baud Rate */
{ INTERFACE_REG, 0x800, 0xC00, { 0x800, NO_DATA, NO_DATA }, 0, 0 }, /* Select Baud Rate for SATA only*/
{ ISOLATE_REG, 0x800, 0xFF, { NO_DATA, 0x66, 0x66 }, 0, 0 }, /* Phy Gen RX and TX */
{ LOOPBACK_REG, 0x800, 0xE, { 0x4, 0x2, 0x2 }, 0, 0 } /* Bus Width */
};
/* SATA and SGMII - TX config seq */
MV_OP_PARAMS sataAndSgmiiTxConfigParams1[] =
{
/* unitunitBaseReg unitOffset mask SATA data SGMII data waitTime numOfLoops */
{ GLUE_REG, 0x800, 0x1800, { NO_DATA, 0x800 }, 0, 0 },
{ RESET_DFE_REG, 0x800, 0x401, { 0x401, 0x401 }, 0, 0 }, /* Sft Reset pulse */
{ RESET_DFE_REG, 0x800, 0x401, { 0x0, 0x0 }, 0, 0 }, /* Sft Reset pulse */
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, 0xF0000, { 0x70000, 0x70000 }, 0, 0 } /* Power up PLL, RX and TX */
};
MV_OP_PARAMS sataPort0TxConfigParams[] =
{
/* unitunitBaseReg unitOffset mask SATA data waitTime numOfLoops */
{ SATA_CTRL_REG_IND_ADDR, 0x38000, 0xFFFFFFFF, { 0x0 }, 0, 0 }, /* Power Down Sata addr*/
{ SATA_CTRL_REG_IND_DATA, 0x38000, 0xFFFF00FF, { 0xC40000 }, 0, 0 }, /* Power Down Sata Port 0 */
{ SATA_CTRL_REG_IND_ADDR, 0x38000, 0xFFFFFFFF, { 0x4 }, 0, 0 }, /* Regret bit addr*/
{ SATA_CTRL_REG_IND_DATA, 0x38000, 0xFFFFFFFF, { 0x80 }, 0, 0 } /* Regret bit data */
};
MV_OP_PARAMS sataPort1TxConfigParams[] =
{
/* unitunitBaseReg unitOffset mask SATA data waitTime numOfLoops */
{ SATA_CTRL_REG_IND_ADDR, 0x38000, 0xFFFFFFFF, { 0x0 }, 0, 0 }, /* Power Down Sata addr*/
{ SATA_CTRL_REG_IND_DATA, 0x38000, 0xFFFFFF00, { 0xC40000 }, 0, 0 }, /* Power Down Sata Port 1 */
{ SATA_CTRL_REG_IND_ADDR, 0x38000, 0xFFFFFFFF, { 0x4 }, 0, 0 }, /* Regret bit addr*/
{ SATA_CTRL_REG_IND_DATA, 0x38000, 0xFFFFFFFF, { 0x80 }, 0, 0 } /* Regret bit data */
};
MV_OP_PARAMS sataAndSgmiiTxConfigSerdesRev1Params2[] =
{
/* unitunitBaseReg unitOffset mask SATA data SGMII data waitTime numOfLoops */
{ COMMON_PHY_STATUS1_REG, 0x28, 0xC, { 0xC, 0xC }, 10, 1000 }, /* Wait for PHY power up sequence to finish */
{ COMMON_PHY_STATUS1_REG, 0x28, 0x1, { 0x1, 0x1 }, 1, 1000 } /* Wait for PHY power up sequence to finish */
};
MV_OP_PARAMS sataAndSgmiiTxConfigSerdesRev2Params2[] =
{
/* unitunitBaseReg unitOffset mask SATA data SGMII data waitTime numOfLoops */
{ COMMON_PHY_STATUS1_REG, 0x28, 0xC, { 0xC, 0xC }, 10, 1000 }, /* Wait for PHY power up sequence to finish */
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x40000000, { NA, 0x40000000 }, 0, 0 }, /* Assert Rx Init for SGMII */
{ ISOLATE_REG, 0x800, 0x400, { 0x400, NA }, 0, 0 }, /* Assert Rx Init for SATA */
{ COMMON_PHY_STATUS1_REG, 0x28, 0x1, { 0x1, 0x1 }, 1, 1000 }, /* Wait for PHY power up sequence to finish */
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x40000000, { NA, 0x0 }, 0, 0 }, /* De-assert Rx Init for SGMII */
{ ISOLATE_REG, 0x800, 0x400, { 0x0, NA }, 0, 0 }, /* De-assert Rx Init for SATA */
{ RX_REG3, 0x800, 0xFF, { 0xDE, NO_DATA }, 0, 0 }, /* os_ph_offset_force (align 90) */
{ RX_REG3, 0x800, 0x100, { 0x100, NO_DATA }, 0, 0 }, /* Set os_ph_valid */
{ RX_REG3, 0x800, 0x100, { 0x0, NO_DATA }, 0, 0 }, /* Unset os_ph_valid */
};
MV_OP_PARAMS sataElectricalConfigSerdesRev1Params[] =
{
/* unitunitBaseReg unitOffset mask SATA data waitTime numOfLoops */
{ COMMON_PHY_CONFIGURATION4_REG, 0x28, 0x400008, { 0x400000, }, 0, 0 }, /* enable SSC and DFE update enable */
{ VTHIMPCAL_CTRL_REG, 0x800, 0xFF00, { 0x4000, }, 0, 0 }, /* tximpcal_th and rximpcal_th */
{ SQUELCH_FFE_SETTING_REG, 0x800, 0xFFF, { 0x6CF, }, 0, 0 }, /* SQ_THRESH and FFE Setting */
{ G1_SETTINGS_0_REG, 0x800, 0xFFFF, { 0x8A32, }, 0, 0 }, /* G1_TX SLEW, EMPH1 and AMP */
{ G1_SETTINGS_1_REG, 0x800, 0x3FF, { 0x3C9, }, 0, 0 }, /* G1_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */
{ G2_SETTINGS_0_REG, 0x800, 0xFFFF, { 0x8B5C, }, 0, 0 }, /* G2_TX SLEW, EMPH1 and AMP */
{ G2_SETTINGS_1_REG, 0x800, 0x3FF, { 0x3D2, }, 0, 0 }, /* G2_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */
{ G3_SETTINGS_0_REG, 0x800, 0xFFFF, { 0xE6E, }, 0, 0 }, /* G3_TX SLEW, EMPH1 and AMP */
{ G3_SETTINGS_1_REG, 0x800, 0x3FF, { 0x3D2, }, 0, 0 }, /* G3_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */
{ CAL_REG6, 0x800, 0xFF00, { 0xDD00, }, 0, 0 }, /* Cal rxclkalign90 ext enable and Cal os ph ext */
{ RX_REG2, 0x800, 0xF0, { 0x70, }, 0, 0 }, /* Dtl Clamping disable and Dtl clamping Sel(6000ppm) */
};
MV_OP_PARAMS sataElectricalConfigSerdesRev2Params[] =
{
/* unitunitBaseReg unitOffset mask SATA data waitTime numOfLoops */
{ SQUELCH_FFE_SETTING_REG, 0x800, 0xF00, { 0x600 }, 0, 0 }, /* SQ_THRESH and FFE Setting */
{ COMMON_PHY_CONFIGURATION4_REG, 0x28, 0x400008, { 0x400000 }, 0, 0 }, /* enable SSC and DFE update enable */
{ G1_SETTINGS_0_REG, 0x800, 0xFFFF, { 0x8A32 }, 0, 0 }, /* G1_TX SLEW, EMPH1 and AMP */
{ G1_SETTINGS_1_REG, 0x800, 0x3FF, { 0x3C9 }, 0, 0 }, /* G1_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */
{ G2_SETTINGS_0_REG, 0x800, 0xFFFF, { 0x8B5C }, 0, 0 }, /* G2_TX SLEW, EMPH1 and AMP */
{ G2_SETTINGS_1_REG, 0x800, 0x3FF, { 0x3D2 }, 0, 0 }, /* G2_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */
{ G3_SETTINGS_0_REG, 0x800, 0xFFFF, { 0xE6E }, 0, 0 }, /* G3_TX SLEW, EMPH1 and AMP */
{ G3_SETTINGS_1_REG, 0x800, 0x47FF, { 0x7D2 }, 0, 0 }, /* G3_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI & DFE_En Gen3, DC wander calibration dis */
{ PCIE_REG0, 0x800, 0x1000, { 0x0 }, 0, 0 }, /* Bit[12]=0x0 idle_sync_en */
{ RX_REG2, 0x800, 0xF0, { 0x70, }, 0, 0 }, /* Dtl Clamping disable and Dtl clamping Sel(6000ppm) */
{ VTHIMPCAL_CTRL_REG, 0x800, 0xFF00, { 0x3000 }, 0, 0 }, /* tximpcal_th and rximpcal_th */
{ DFE_REG0, 0x800, 0xA00F, { 0x800A }, 0, 0 }, /* DFE_STEP_FINE_FX[3:0] =0xA */
{ DFE_REG3, 0x800, 0xC000, { 0x0 }, 0, 0 }, /* DFE_EN and Dis Update control from pin disable */
{ G1_SETTINGS_3_REG, 0x800, 0xFF, { 0xCF }, 0, 0 }, /* FFE Force FFE_REs and cap settings for Gen1 */
{ G2_SETTINGS_3_REG, 0x800, 0xFF, { 0xBF }, 0, 0 }, /* FFE Force FFE_REs and cap settings for Gen2 */
{ G3_SETTINGS_3_REG, 0x800, 0xFF, { 0xCF }, 0, 0 }, /* FE Force FFE_REs=4 and cap settings for Gen3n */
{ G3_SETTINGS_4_REG, 0x800, 0x300, { 0x300 }, 0, 0 }, /* Set DFE Gen 3 Resolution to 3 */
};
MV_OP_PARAMS sgmiiElectricalConfigSerdesRev1Params[] =
{
/* unitunitBaseReg unitOffset mask SGMII (1.25G) SGMII (3.125G) waitTime numOfLoops */
{ G1_SETTINGS_1_REG, 0x800, 0x3FF, { 0x3C9, 0x3C9 }, 0, 0 }, /* G1_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */
{ SQUELCH_FFE_SETTING_REG, 0x800, 0xFFF, { 0x8F, 0xBF }, 0, 0 }, /* SQ_THRESH and FFE Setting */
{ VTHIMPCAL_CTRL_REG, 0x800, 0xFF00, { 0x4000, 0x4000 }, 0, 0 }, /* tximpcal_th and rximpcal_th */
};
MV_OP_PARAMS sgmiiElectricalConfigSerdesRev2Params[] =
{
/* unitunitBaseReg unitOffset mask SGMII (1.25G) SGMII (3.125G) waitTime numOfLoops */
{ G1_SETTINGS_0_REG, 0x800, 0xFFFF, { 0x8FA, 0x8FA }, 0, 0 }, /* Set SlewRate, Emph and Amp */
{ G1_SETTINGS_1_REG, 0x800, 0x3FF, { 0x3C9, 0x3C9 }, 0, 0 }, /* G1_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */
{ RX_REG2, 0x800, 0x4, { 0x0, 0x0 }, 0, 0 }, /* DTL_FLOOP_EN */
{ G1_SETTINGS_3_REG, 0x800, 0xFF, { 0x8F, 0xBF }, 0, 0 }, /* G1 FFE Setting Force, RES and CAP */
{ VTHIMPCAL_CTRL_REG, 0x800, 0xFF00, { 0x3000, 0x3000 }, 0, 0 }, /* tximpcal_th and rximpcal_th */
};
/****************/
/* PEX and USB3 */
/****************/
/* PEX and USB3 - power up seq for Serdes Rev 1.2 */
MV_OP_PARAMS pexAndUsb3PowerUpSerdesRev1Params[] =
{
/* unitunitBaseReg unitOffset mask PEX data USB3 data waitTime numOfLoops */
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x3FC7F806, { 0x4471804, 0x4479804 }, 0, 0 },
{ COMMON_PHY_CONFIGURATION2_REG, 0x28, 0x5C, { 0x58, 0x58 }, 0, 0 },
{ COMMON_PHY_CONFIGURATION4_REG, 0x28, 0x3, { 0x1, 0x1 }, 0, 0 },
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x7800, { 0x6000, 0xE000 }, 0, 0 },
{ GLOBAL_CLK_CTRL, 0x800, 0xD, { 0x5, 0x1 }, 0, 0 },
{ MISC_REG, 0x800, 0x4C0, { 0x80, 0x4C0 }, 0, 0 } /* Ref clock source select */
};
/* PEX and USB3 - power up seq for Serdes Rev 2.1 */
MV_OP_PARAMS pexAndUsb3PowerUpSerdesRev2Params[] =
{
/* unitunitBaseReg unitOffset mask PEX data USB3 data waitTime numOfLoops */
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x3FC7F806, { 0x4471804, 0x4479804 }, 0, 0 },
{ COMMON_PHY_CONFIGURATION2_REG, 0x28, 0x5C, { 0x58, 0x58 }, 0, 0 },
{ COMMON_PHY_CONFIGURATION4_REG, 0x28, 0x3, { 0x1, 0x1 }, 0, 0 },
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x7800, { 0x6000, 0xE000 }, 0, 0 },
{ GLOBAL_CLK_CTRL, 0x800, 0x3D, { 0x35, 0x21 }, 0, 0 },
{ GLOBAL_MISC_CTRL, 0x800, 0xC0, { 0x0, NO_DATA }, 0, 0 },
{ MISC_REG, 0x800, 0x4C0, { 0x80, 0x4C0 }, 0, 0 } /* Ref clock source select */
};
/* PEX and USB3 - speed config seq */
MV_OP_PARAMS pexAndUsb3SpeedConfigParams[] =
{
/* unitunitBaseReg unitOffset mask PEX data USB3 data waitTime numOfLoops
2.5 5 HOST DEVICE */
{ INTERFACE_REG, 0x800, 0xC00, { 0x400, 0x400, 0x400, 0x400, 0x400 }, 0, 0 }, /* Maximal PHY Generation Setting */
};
MV_OP_PARAMS usb3ElectricalConfigSerdesRev1Params[] =
{
{ LANE_CFG4_REG, 0x800, 0x80, { 0x80 }, 0, 0 }, /* Spread Spectrum Clock Enable */
{ G2_SETTINGS_2_REG, 0x800, 0xFE40, { 0x4440 }, 0, 0 }, /* G2_TX_SSC_AMP[6:0]=4.5kPPM and TX emphasis mode=mV */
{ VTHIMPCAL_CTRL_REG, 0x800, 0xFF00, { 0x4000 }, 0, 0 }, /* tximpcal_th and rximpcal_th */
{ G2_SETTINGS_1_REG, 0x800, 0x3FF, { 0x3D2 }, 0, 0 }, /* G2_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */
{ SQUELCH_FFE_SETTING_REG, 0x800, 0xFF, { 0xEF }, 0, 0 }, /* FFE Setting Force, RES and CAP */
{ RX_REG2, 0x800, 0xF0, { 0x70 }, 0, 0 }, /* Dtl Clamping disable and Dtl-clamping-Sel(6000ppm) */
{ CAL_REG6, 0x800, 0xFF00, { 0xD500 }, 0, 0 }, /* cal_rxclkalign90_ext_en and cal_os_ph_ext */
{ REF_REG0, 0x800, 0x38, { 0x20 }, 0, 0 }, /* vco_cal_vth_sel */
};
MV_OP_PARAMS usb3ElectricalConfigSerdesRev2Params[] =
{
{ LANE_CFG4_REG, 0x800, 0xC2, { 0xC0 }, 0, 0 }, /* Bit[7]=0x1 - Spread Spectrum Clock Enable,Bit[6]-0x1- CFG_DFE_OVERRIDE,Bit[1]-0x0-PIN_DFE_PAT_DIS, */
{ LANE_CFG5_REG, 0x800, 0x3, { 0x3 }, 0, 0 }, /* Bit[1]=0x1 - CFG_SQ_DET_SEL,Bit[0]=0x1-CFG_RX_INIT_SEL, */
{ G2_SETTINGS_2_REG, 0x800, 0xFE40, { 0x4440 }, 0, 0 }, /* Bits[15:9]= 0x22 -G2_TX_SSC_AMP[6:0]=4.5kPPM,Bits[6] = 0x1 - TX emphasis mode=mV */
{ G2_SETTINGS_3_REG, 0x800, 0xFF, { 0xEF }, 0, 0 }, /* Bit[7] =0x1 FFE Setting Force;Bits[6:4]=0x6 FFE_RES;Bits[3:0] = 0xF FFE_CAP; */
{ G2_SETTINGS_4_REG, 0x800, 0x300, { 0x300 }, 0, 0 }, /* Bits[9:8]=0x0 - G2_DFE_RES[1:0]*/
{ PLLINTP_REG1, 0x800, 0x300, { 0x300 }, 0, 0 }, /* Bits[9:8]=0x3 HPF_Bw[1:0] */
{ VTHIMPCAL_CTRL_REG, 0x800, 0xFF00, { 0x3000 }, 0, 0 }, /* Bits[15:12]= 0x3 - tximpcal_th;Bits[11:8] = 0x0 - RXIMPCAL_TH */
{ LANE_CFG5_REG, 0x800, 0x3, { 0x3 }, 0, 0 }, /* Bit[1]=0x1 - CFG_SQ_DET_SEL,Bit[0]=0x1-CFG_RX_INIT_SEL, */
{ MISC_REG, 0x800, 0x42F, { 0x42A }, 0, 0 }, /* Bit[10]=0x1 - REFCLK_SEL(=25Mhz);Bit[5]=0x1 ICP_FORCE_En;Bits[3:0]=0xA ICP=0xA(210uA); */
{ POWER_AND_PLL_CTRL_REG, 0x800, 0x1F, { 0x02 }, 0, 0 }, /* Bits[4:0] =0x2 - REF_FREF_SEL(=25Mhz) */
{ G2_SETTINGS_1_REG, 0x800, 0x3FF, { 0x3D2 }, 0, 0 }, /* Bits[9:8]=0x3- G2_RX_SELMUFF;Bits[7:6]=0x3- G2_RX_SELMUFI;Bits[5:3]=0x2 G2_RX_SELMUPF;Bits[2:0]=0x2 - G2_RX_SELMUPI*/
{ RX_REG2, 0x800, 0xF0, { 0x70 }, 0, 0 }, /* Dtl Clamping disable and Dtl-clamping-Sel(6000ppm) */
{ PCIE_REG1, 0x800, 0xF80, { 0xD00 }, 0, 0 }, /* Bits[11:7]=0x1a - tx_amp_pipe_v0[4:0] */
{ REF_REG0, 0x800, 0x38, { 0x20 }, 0, 0 }, /* vco_cal_vth_sel */
{ LANE_CFG0_REG, 0x800, 0x1, { 0x1 }, 0, 0 }, /* Bit[0]=0x1- PRD_TXDEEMPH0 */
{ GLOBAL_TEST_CTRL, 0x800, 0x4, { 0x4 }, 0, 0 }, /* Bit[4]=0x1-MODE_MARGIN_OVERRIDE */
};
/* PEX and USB3 - TX config seq */
/* For PEXx1: the pexAndUsb3TxConfigParams1/2/3 configurations should run
one by one on the lane.
For PEXx4: the pexAndUsb3TxConfigParams1/2/3 configurations should run
by setting each sequence for all 4 lanes. */
MV_OP_PARAMS pexAndUsb3TxConfigParams1[] =
{
/* unitBaseReg unitOffset mask PEX data USB3 data waitTime numOfLoops */
{ GLOBAL_CLK_CTRL, 0x800, 0x1, { 0x0, 0x0 }, 0, 0 },
{ 0x0, 0x0, 0x0, { 0x0, 0x0 }, 10, 0 }, /* 10ms delay */
};
MV_OP_PARAMS pexAndUsb3TxConfigParams2[] =
{
/* unitBaseReg unitOffset mask PEX data USB3 data waitTime numOfLoops */
{ RESET_DFE_REG, 0x800, 0x401, { 0x401, 0x401 }, 0, 0 }, /* Sft Reset pulse */
};
MV_OP_PARAMS pexAndUsb3TxConfigParams3[] =
{
/* unitBaseReg unitOffset mask PEX data USB3 data waitTime numOfLoops */
{ RESET_DFE_REG, 0x800, 0x401, { 0x0, 0x0 }, 0, 0 }, /* Sft Reset pulse */
{ 0x0, 0x0, 0x0, { 0x0, 0x0 }, 10, 0 }, /* 10ms delay */
{ RX_REG3, 0x800, 0xFF, { 0xDC, 0xD8 }, 0, 0 }, /* os_ph_offset_force (align 90) */
{ RX_REG3, 0x800, 0x100, { 0x100, 0x100 }, 0, 0 }, /* Set os_ph_valid */
{ RX_REG3, 0x800, 0x100, { 0x0, 0x0 }, 0, 0 }, /* Unset os_ph_valid */
};
/* PEX by 4 config seq */
MV_OP_PARAMS pexBy4ConfigParams[] =
{
/* unitunitBaseReg unitOffset mask data waitTime numOfLoops */
{ GLOBAL_CLK_SRC_HI, 0x800, 0x7, { 0x5, 0x0, 0x0, 0x2 }, 0, 0 },
{ LANE_ALIGN_REG0, 0x800, 0x1000, { 0x0, 0x0, 0x0, 0x0 }, 0, 0 }, /* Lane Alignement enable */
{ CALIBRATION_CTRL_REG, 0x800, 0x1000, { 0x1000, 0x1000, 0x1000, 0x1000 }, 0, 0 }, /* Max PLL phy config */
{ LANE_CFG1_REG, 0x800, 0x600, { 0x600, 0x600, 0x600, 0x600 }, 0, 0 }, /* Max PLL pipe config */
};
/* USB3 device donfig seq */
MV_OP_PARAMS usb3DeviceConfigParams[] =
{
/* unitunitBaseReg unitOffset mask data waitTime numOfLoops */
{ LANE_CFG4_REG, 0x800, 0x200, { 0x200 }, 0, 0 }
};
/* PEX - electrical configuration seq Rev 1.2 */
MV_OP_PARAMS pexElectricalConfigSerdesRev1Params[] =
{
/* unitunitBaseReg unitOffset mask PEX data waitTime numOfLoops */
{ G1_SETTINGS_0_REG, 0x800, 0xF000, { 0xB000 }, 0, 0 }, /* G1_TX_SLEW_CTRL_EN and G1_TX_SLEW_RATE */
{ G1_SETTINGS_1_REG, 0x800, 0x3FF, { 0x3C9 }, 0, 0 }, /* G1_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */
{ G2_SETTINGS_1_REG, 0x800, 0x3FF, { 0x3C9 }, 0, 0 }, /* G2_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */
{ LANE_CFG4_REG, 0x800, 0x8, { 0x8 }, 0, 0 }, /* CFG_DFE_EN_SEL */
{ SQUELCH_FFE_SETTING_REG, 0x800, 0xFF, { 0xAF }, 0, 0 }, /* FFE Setting Force, RES and CAP */
{ VTHIMPCAL_CTRL_REG, 0x800, 0xFF00, { 0x3000 }, 0, 0 }, /* tximpcal_th and rximpcal_th */
{ CAL_REG6, 0x800, 0xFF00, { 0xDC00 }, 0, 0 }, /* cal_rxclkalign90_ext_en and cal_os_ph_ext */
};
/* PEX - electrical configuration seq Rev 2.1 */
MV_OP_PARAMS pexElectricalConfigSerdesRev2Params[] =
{
/* unitunitBaseReg unitOffset mask PEX data waitTime numOfLoops */
{ G1_SETTINGS_0_REG, 0x800, 0xF000, { 0xB000 }, 0, 0 }, /* G1_TX_SLEW_CTRL_EN and G1_TX_SLEW_RATE */
{ G1_SETTINGS_1_REG, 0x800, 0x3FF, { 0x3C9 }, 0, 0 }, /* G1_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */
{ G1_SETTINGS_3_REG, 0x800, 0xFF, { 0xCF }, 0, 0 }, /* G1 FFE Setting Force, RES and CAP */
{ G2_SETTINGS_1_REG, 0x800, 0x3FF, { 0x3C9 }, 0, 0 }, /* G2_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */
{ G2_SETTINGS_3_REG, 0x800, 0xFF, { 0xAF }, 0, 0 }, /* G2 FFE Setting Force, RES and CAP */
{ G2_SETTINGS_4_REG, 0x800, 0x300, { 0x300 }, 0, 0 }, /* G2 DFE resolution value */
{ DFE_REG0, 0x800, 0x8000, { 0x8000 }, 0, 0 }, /* DFE resolution force */
{ PCIE_REG1, 0x800, 0xF80, { 0xD00 }, 0, 0 }, /* Tx amplitude for Tx Margin 0 */
{ PCIE_REG3, 0x800, 0xFF00, { 0xAF00 }, 0, 0 }, /* Tx_Emph value for -3.5dB and -6dB */
{ LANE_CFG4_REG, 0x800, 0x8, { 0x8 }, 0, 0 }, /* CFG_DFE_EN_SEL */
{ VTHIMPCAL_CTRL_REG, 0x800, 0xFF00, { 0x3000 }, 0, 0 }, /* tximpcal_th and rximpcal_th */
};
/* PEX - configuration seq for REF_CLOCK_25MHz */
MV_OP_PARAMS pexConfigRefClock25MHz[] =
{
/* unitunitBaseReg unitOffset mask PEX data waitTime numOfLoops */
{ POWER_AND_PLL_CTRL_REG, 0x800, 0x1F, { 0x2 }, 0, 0 }, /* Bits[4:0]=0x2 - REF_FREF_SEL */
{ MISC_REG, 0x800, 0x400, { 0x400 }, 0, 0 }, /* Bit[10]=0x1 - REFCLK_SEL */
{ GLOBAL_PM_CTRL, 0x800, 0xFF, { 0x7 }, 0, 0 }, /* Bits[7:0]=0x7 - CFG_PM_RXDLOZ_WAIT */
};
/* PEX - configuration seq for REF_CLOCK_40MHz */
MV_OP_PARAMS pexConfigRefClock40MHz[] =
{
/* unitunitBaseReg unitOffset mask PEX data waitTime numOfLoops */
{ POWER_AND_PLL_CTRL_REG, 0x800, 0x1F, { 0x3 }, 0, 0 }, /* Bits[4:0]=0x3 - REF_FREF_SEL */
{ MISC_REG, 0x800, 0x400, { 0x400 }, 0, 0 }, /* Bits[10]=0x1 - REFCLK_SEL */
{ GLOBAL_PM_CTRL, 0x800, 0xFF, { 0xC }, 0, 0 }, /* Bits[7:0]=0xC - CFG_PM_RXDLOZ_WAIT */
};
/* PEX - configuration seq for REF_CLOCK_100MHz */
MV_OP_PARAMS pexConfigRefClock100MHz[] =
{
/* unitunitBaseReg unitOffset mask PEX data waitTime numOfLoops */
{ POWER_AND_PLL_CTRL_REG, 0x800, 0x1F, { 0x0 }, 0, 0 }, /* Bits[4:0]=0x0 - REF_FREF_SEL */
{ MISC_REG, 0x800, 0x400, { 0x0 }, 0, 0 }, /* Bit[10]=0x0 - REFCLK_SEL */
{ GLOBAL_PM_CTRL, 0x800, 0xFF, { 0x1E }, 0, 0 }, /* Bits[7:0]=0x1E - CFG_PM_RXDLOZ_WAIT */
};
/*****************/
/* USB2 */
/*****************/
MV_OP_PARAMS usb2PowerUpParams[] =
{
/* unitunitBaseReg unitOffset mask USB2 data waitTime numOfLoops */
{ 0x18440 , 0x0 /*NA*/, 0xffffffff, {0x62}, 0, 0}, /* Init phy 0 */
{ 0x18444 , 0x0 /*NA*/, 0xffffffff, {0x62}, 0, 0}, /* Init phy 1 */
{ 0x18448 , 0x0 /*NA*/, 0xffffffff, {0x62}, 0, 0}, /* Init phy 2 */
{ 0xC0000 , 0x0 /*NA*/, 0xffffffff, {0x40605205}, 0, 0}, /* Phy offset 0x0 - PLL_CONTROL0 */
{ 0xC001C , 0x0 /*NA*/, 0xffffffff, {0x39F16CE}, 0, 0},
{ 0xC201C , 0x0 /*NA*/, 0xffffffff, {0x39F16CE}, 0, 0},
{ 0xC401C , 0x0 /*NA*/, 0xffffffff, {0x39F16CE}, 0, 0},
{ 0xC0004 , 0x0 /*NA*/, 0x1, {0x1}, 0, 0}, /* Phy offset 0x1 - PLL_CONTROL1 */
{ 0xC000C , 0x0 /*NA*/, 0x1000000, {0x1000000}, 0, 0}, /* Phy0 register 3 - TX Channel control 0 */
{ 0xC200C , 0x0 /*NA*/, 0x1000000, {0x1000000}, 0, 0}, /* Phy0 register 3 - TX Channel control 0 */
{ 0xC400C , 0x0 /*NA*/, 0x1000000, {0x1000000}, 0, 0}, /* Phy0 register 3 - TX Channel control 0 */
{ 0xC000C , 0x0 /*NA*/, 0xf000, {0x1000}, 0, 0}, /* Decrease the amplitude of the low speed eye to meet the spec */
{ 0xC200C , 0x0 /*NA*/, 0xf000, {0x1000}, 0, 0}, /* Decrease the amplitude of the low speed eye to meet the spec */
{ 0xC400C , 0x0 /*NA*/, 0xf000, {0x1000}, 0, 0}, /* Decrease the amplitude of the low speed eye to meet the spec */
{ 0xC0008 , 0x0 /*NA*/, 0x700, {0x600}, 0, 0}, /* Change the High speed impedance threshold */
{ 0xC2008 , 0x0 /*NA*/, 0x700, {0x600}, 0, 0}, /* Change the High speed impedance threshold */
{ 0xC4008 , 0x0 /*NA*/, 0x700, {0x600}, 0, 0}, /* Change the High speed impedance threshold */
{ 0xC0014 , 0x0 /*NA*/, 0xf, {0x8}, 0, 0}, /* Change the squelch level of the receiver to meet the receiver electrical measurements(squelch and receiver sensitivity tests) */
{ 0xC2014 , 0x0 /*NA*/, 0xf, {0x8}, 0, 0}, /* Change the squelch level of the receiver to meet the receiver electrical measurements(squelch and receiver sensitivity tests) */
{ 0xC4014 , 0x0 /*NA*/, 0xf, {0x8}, 0, 0}, /* Change the squelch level of the receiver to meet the receiver electrical measurements(squelch and receiver sensitivity tests) */
{ 0xC0008 , 0x0 /*NA*/, 0x80800000, {0x80800000}, 1, 1000}, /* Check PLLCAL_DONE is set and IMPCAL_DONE is set*/
{ 0xC0018 , 0x0 /*NA*/, 0x80000000, {0x80000000}, 1, 1000}, /* Check REG_SQCAL_DONE is set*/
{ 0xC0000 , 0x0 /*NA*/, 0x80000000, {0x80000000}, 1, 1000}, /* Check PLL_READY is set*/
{ 0xC0008 , 0x0 /*NA*/, 0x2000, {0x2000}, 0, 0}, /* Start calibrate of high seed impedance */
{ 0x0 , 0x0 /*NA*/, 0x0, {0x0}, 10, 0},
{ 0xC0008 , 0x0 /*NA*/, 0x2000, {0x0}, 0, 0}, /* De-assert the calibration signal */
};
/*****************/
/* QSGMII */
/*****************/
/* QSGMII - power up seq */
MV_OP_PARAMS qsgmiiPortPowerUpParams[] =
{
/* unitBaseReg unitOffset mask QSGMII data waitTime numOfLoops */
{ QSGMII_CONTROL_REG1, 0x0, 0x44000000, { 0x44000000 }, 0, 0 }, /* Connect QSGMII to Gigabit Ethernet units;
Set sampling edge of Tx QSGMII to be positive
to achive port the stability - JIRA-1282 */
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, 0xF0006, { 0x80002 }, 0, 0 }, /* Power Up */
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x7800, { 0x6000 }, 0, 0 }, /* Unreset */
{ POWER_AND_PLL_CTRL_REG, 0x800, 0xFF, { 0xFC81 }, 0, 0 }, /* Phy Selector */
{ MISC_REG, 0x800, 0x4C0, { 0x480 }, 0, 0 } /* Ref clock source select */
};
/* QSGMII - speed config seq */
MV_OP_PARAMS qsgmiiPortSpeedConfigParams[] =
{
/* unitBaseReg unitOffset mask QSGMII waitTime numOfLoops */
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x3FC00000, { 0xCC00000 }, 0, 0 }, /* Baud Rate */
{ ISOLATE_REG, 0x800, 0xFF, { 0x33 }, 0, 0 }, /* Phy Gen RX and TX */
{ LOOPBACK_REG, 0x800, 0xE, { 0x2 }, 0, 0 } /* Bus Width */
};
/* QSGMII - Select electrical param seq */
MV_OP_PARAMS qsgmiiPortElectricalConfigParams[] =
{
/* unitunitBaseReg unitOffset mask QSGMII data waitTime numOfLoops */
{ G1_SETTINGS_0_REG, 0x800, 0x8000, { 0x0 }, 0, 0 } /* Slew rate and emphasis */
};
/* QSGMII - TX config seq */
MV_OP_PARAMS qsgmiiPortTxConfigParams1[] =
{
/* unitunitBaseReg unitOffset mask QSGMII data waitTime numOfLoops */
{ GLUE_REG, 0x800, 0x1800, { 0x800 }, 0, 0 },
{ RESET_DFE_REG, 0x800, 0x401, { 0x401 }, 0, 0 }, /* Sft Reset pulse */
{ RESET_DFE_REG, 0x800, 0x401, { 0x0 }, 0, 0 }, /* Sft Reset pulse */
{ LANE_ALIGN_REG0, 0x800, 0x1000, { 0x1000 }, 0, 0 }, /* Lane align */
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x70000, { 0x70000 }, 0, 0 }, /* Power up PLL, RX and TX */
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x80000, { 0x80000 }, 0, 0 } /* Tx driver output idle */
};
MV_OP_PARAMS qsgmiiPortTxConfigParams2[] =
{
/* unitunitBaseReg unitOffset mask QSGMII data waitTime numOfLoops */
{ COMMON_PHY_STATUS1_REG, 0x28, 0xC, { 0xC }, 10, 1000 }, /* Wait for PHY power up sequence to finish */
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x40080000, { 0x40000000 }, 0, 0 }, /* Assert Rx Init and Tx driver output valid */
{ COMMON_PHY_STATUS1_REG, 0x28, 0x1, { 0x1 }, 1, 1000 }, /* Wait for PHY power up sequence to finish */
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, 0x40000000, { 0x0 }, 0, 0 } /* De-assert Rx Init */
};
/* SERDES_POWER_DOWN */
MV_OP_PARAMS serdesPowerDownParams[] =
{
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, (0xF << 11), { (0x3 << 11) }, 0, 0 },
{ COMMON_PHY_CONFIGURATION1_REG, 0x28, (0x7 << 16), { 0 }, 0, 0 }
};
/************************* Local functions declarations ***********************/
/*******************************************************************************
* mvCtrlSerdesRevGet
*
* DESCRIPTION: Get the Serdes revision number
*
* INPUT: configField - Field description enum
*
* OUTPUT: None
*
* RETURN:
* 8bit Serdes revision number
*
*******************************************************************************/
MV_U8 mvHwsCtrlSerdesRevGet(MV_VOID)
{
#ifdef MV88F68XX
/* for A38x-Z1 */
if (mvSysEnvDeviceRevGet() == MV_88F68XX_Z1_ID) {
return MV_SERDES_REV_1_2;
}
#endif
/* for A39x-Z1, A38x-A0 */
return MV_SERDES_REV_2_1;
}
MV_U32 mvHwsSerdesTopologyVerify(SERDES_TYPE serdesType, MV_U32 serdesId, SERDES_MODE serdesMode)
{
MV_U32 testResult = TOPOLOGY_TEST_OK;
MV_U8 serdMaxNumb,unitNumb;
MV_UNIT_ID unitId;
if (serdesType > RXAUI){
mvPrintf("%s: Warning: Wrong serdes type %s serdes#%d \n", __func__, serdesTypeToString[serdesType], serdesId);
return MV_FAIL;
}
unitId = serdesTypeToUnitInfo[serdesType].serdesUnitId;
unitNumb =serdesTypeToUnitInfo[serdesType].serdesUnitNum;
serdMaxNumb = mvSysEnvUnitMaxNumGet(unitId);
if (SerdesLaneInUseCount[unitId][unitNumb] == 0) {
testResult = SERDES_ALREADY_IN_USE;
} else {
/* if didn't exceed amount of required Serdes lanes for current type */
if (serdesType == PEX0){
if(serdesMode != PEX_END_POINT_x4){
if(serdesMode != PEX_ROOT_COMPLEX_x4){
/* SerdesLaneInUseCount for PEX0 = 4 , but if it is PCIex1 only 1 lane may be used */
SerdesLaneInUseCount[unitId][unitNumb] = 1;
}
}
}
SerdesLaneInUseCount[unitId][unitNumb]--; /* update amount of required Serdes lanes for current type */
if (SerdesLaneInUseCount[unitId][unitNumb] == 0){ /* if reached the exact amount of required Serdes lanes for current type */
if (((serdesType <= PEX3)) && ((serdesMode == PEX_END_POINT_x4) || (serdesMode == PEX_ROOT_COMPLEX_x4)))
serdesUnitCount[PEX_UNIT_ID] +=2; /* PCiex4 uses 2 SerDes */
else
serdesUnitCount[unitId]++;
if (serdesUnitCount[unitId] > serdMaxNumb) /* test SoC unit count limitation */
testResult = WRONG_NUMBER_OF_UNITS;
else if (unitNumb >= serdMaxNumb) /* test SoC unit number limitation */
testResult = UNIT_NUMBER_VIOLATION;
}
}
if (testResult == SERDES_ALREADY_IN_USE) {
mvPrintf("%s: Error: serdes lane %d is configured ", __func__, serdesId);
mvPrintf("to type %s: type already in use\n", serdesTypeToString[serdesType]);
return MV_FAIL;
} else if (testResult == WRONG_NUMBER_OF_UNITS) {
mvPrintf("%s: Warning: serdes lane %d is ", __func__, serdesId);
mvPrintf("set to type %s.\n", serdesTypeToString[serdesType]);
mvPrintf("%s: Maximum supported lanes are ", __func__);
mvPrintf("already set to this type (limit = %d)\n", serdMaxNumb);
return MV_FAIL;
}
else if (testResult == UNIT_NUMBER_VIOLATION) {
mvPrintf("%s: Warning: serdes lane %d type is %s: ",
__func__, serdesId, serdesTypeToString[serdesType]);
mvPrintf("current device support only %d units of this type.\n", serdMaxNumb);
return MV_FAIL;
}
return MV_OK;
}
MV_VOID mvHwsSerdesXAUITopologyVerify(MV_VOID)
{
if ((SerdesLaneInUseCount[XAUI_UNIT_ID][0] != 0) && (SerdesLaneInUseCount[XAUI_UNIT_ID][0] != 4)){ /* if XAUI is in use - SerdesLaneInUseCount has to be = 0;
if it is not in use hast be = 4 */
mvPrintf("%s: Warning: wrong number of lanes is set to XAUI - %d\n", __func__, SerdesLaneInUseCount[XAUI_UNIT_ID][0]);
mvPrintf("%s: XAUI has to be defined on 4 lanes\n", __func__);
}
if ((SerdesLaneInUseCount[RXAUI_UNIT_ID][0] != 0) && (SerdesLaneInUseCount[RXAUI_UNIT_ID][0] != 2)){/* if RXAUI is in use - SerdesLaneInUseCount has to be = 0;
if it is not in use hast be = 2 */
mvPrintf("%s: Warning: wrong number of lanes is set to RXAUI - %d\n", __func__, SerdesLaneInUseCount[RXAUI_UNIT_ID][0]);
mvPrintf("%s: RXAUI has to be defined on 2 lanes\n", __func__);
}
}
MV_VOID mvHwsSerdesPCIX4TopologyVerify(MV_VOID )
{
if (SerdesLaneInUseCount[PEX_UNIT_ID][0] != 0) {
mvPrintf("%s: Warning: wrong number of lanes is set to PEX0 - %d\n", __func__, SerdesLaneInUseCount[PEX_UNIT_ID][0]);
mvPrintf("%s: PCIex4 has to be defined on 4 lanes\n", __func__);
}
}
MV_STATUS mvHwsSerdesSeqDbInit(MV_VOID)
{
DEBUG_INIT_FULL_S("\n### serdesSeq38xInit ###\n");
MV_U8 serdesRev = mvHwsCtrlSerdesRevGet();
if(serdesRev == MV_SERDES_REV_NA) {
mvPrintf("mvHwsSerdesSeqDbInit: serdes revision number is not supported\n");
return MV_NOT_SUPPORTED;
}
/* SATA_PORT_0_ONLY_POWER_UP_SEQ sequence init */
serdesSeqDb[SATA_PORT_0_ONLY_POWER_UP_SEQ].opParamsPtr = sataPort0PowerUpParams;
serdesSeqDb[SATA_PORT_0_ONLY_POWER_UP_SEQ].cfgSeqSize = sizeof(sataPort0PowerUpParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[SATA_PORT_0_ONLY_POWER_UP_SEQ].dataArrIdx = SATA;
/* SATA_PORT_1_ONLY_POWER_UP_SEQ sequence init */
serdesSeqDb[SATA_PORT_1_ONLY_POWER_UP_SEQ].opParamsPtr = sataPort1PowerUpParams;
serdesSeqDb[SATA_PORT_1_ONLY_POWER_UP_SEQ].cfgSeqSize = sizeof(sataPort1PowerUpParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[SATA_PORT_1_ONLY_POWER_UP_SEQ].dataArrIdx = SATA;
/* SATA_POWER_UP_SEQ sequence init */
serdesSeqDb[SATA_POWER_UP_SEQ].opParamsPtr = sataAndSgmiiPowerUpParams;
serdesSeqDb[SATA_POWER_UP_SEQ].cfgSeqSize = sizeof(sataAndSgmiiPowerUpParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[SATA_POWER_UP_SEQ].dataArrIdx = SATA;
/* SATA__1_5_SPEED_CONFIG_SEQ sequence init */
serdesSeqDb[SATA__1_5_SPEED_CONFIG_SEQ].opParamsPtr = sataAndSgmiiSpeedConfigParams;
serdesSeqDb[SATA__1_5_SPEED_CONFIG_SEQ].cfgSeqSize = sizeof(sataAndSgmiiSpeedConfigParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[SATA__1_5_SPEED_CONFIG_SEQ].dataArrIdx = SATA;
/* SATA__3_SPEED_CONFIG_SEQ sequence init */
serdesSeqDb[SATA__3_SPEED_CONFIG_SEQ].opParamsPtr = sataAndSgmiiSpeedConfigParams;
serdesSeqDb[SATA__3_SPEED_CONFIG_SEQ].cfgSeqSize = sizeof(sataAndSgmiiSpeedConfigParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[SATA__3_SPEED_CONFIG_SEQ].dataArrIdx = SATA;
/* SATA__6_SPEED_CONFIG_SEQ sequence init */
serdesSeqDb[SATA__6_SPEED_CONFIG_SEQ].opParamsPtr = sataAndSgmiiSpeedConfigParams;
serdesSeqDb[SATA__6_SPEED_CONFIG_SEQ].cfgSeqSize = sizeof(sataAndSgmiiSpeedConfigParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[SATA__6_SPEED_CONFIG_SEQ].dataArrIdx = SATA;
/* SATA_ELECTRICAL_CONFIG_SEQ seq sequence init */
if(serdesRev == MV_SERDES_REV_1_2) {
serdesSeqDb[SATA_ELECTRICAL_CONFIG_SEQ].opParamsPtr = sataElectricalConfigSerdesRev1Params;
serdesSeqDb[SATA_ELECTRICAL_CONFIG_SEQ].cfgSeqSize = sizeof(sataElectricalConfigSerdesRev1Params) / sizeof(MV_OP_PARAMS);
} else {
serdesSeqDb[SATA_ELECTRICAL_CONFIG_SEQ].opParamsPtr = sataElectricalConfigSerdesRev2Params;
serdesSeqDb[SATA_ELECTRICAL_CONFIG_SEQ].cfgSeqSize = sizeof(sataElectricalConfigSerdesRev2Params) / sizeof(MV_OP_PARAMS);
}
serdesSeqDb[SATA_ELECTRICAL_CONFIG_SEQ].dataArrIdx = SATA;
/* SATA_TX_CONFIG_SEQ sequence init */
serdesSeqDb[SATA_TX_CONFIG_SEQ1].opParamsPtr = sataAndSgmiiTxConfigParams1;
serdesSeqDb[SATA_TX_CONFIG_SEQ1].cfgSeqSize = sizeof(sataAndSgmiiTxConfigParams1) / sizeof(MV_OP_PARAMS);
serdesSeqDb[SATA_TX_CONFIG_SEQ1].dataArrIdx = SATA;
/* SATA_PORT_0_ONLY_TX_CONFIG_SEQ sequence init */
serdesSeqDb[SATA_PORT_0_ONLY_TX_CONFIG_SEQ].opParamsPtr = sataPort0TxConfigParams;
serdesSeqDb[SATA_PORT_0_ONLY_TX_CONFIG_SEQ].cfgSeqSize = sizeof(sataPort0TxConfigParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[SATA_PORT_0_ONLY_TX_CONFIG_SEQ].dataArrIdx = SATA;
/* SATA_PORT_1_ONLY_TX_CONFIG_SEQ sequence init */
serdesSeqDb[SATA_PORT_1_ONLY_TX_CONFIG_SEQ].opParamsPtr = sataPort1TxConfigParams;
serdesSeqDb[SATA_PORT_1_ONLY_TX_CONFIG_SEQ].cfgSeqSize = sizeof(sataPort1TxConfigParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[SATA_PORT_1_ONLY_TX_CONFIG_SEQ].dataArrIdx = SATA;
/* SATA_TX_CONFIG_SEQ2 sequence init */
if(serdesRev == MV_SERDES_REV_1_2) {
serdesSeqDb[SATA_TX_CONFIG_SEQ2].opParamsPtr = sataAndSgmiiTxConfigSerdesRev1Params2;
serdesSeqDb[SATA_TX_CONFIG_SEQ2].cfgSeqSize = sizeof(sataAndSgmiiTxConfigSerdesRev1Params2) / sizeof(MV_OP_PARAMS);
} else {
serdesSeqDb[SATA_TX_CONFIG_SEQ2].opParamsPtr = sataAndSgmiiTxConfigSerdesRev2Params2;
serdesSeqDb[SATA_TX_CONFIG_SEQ2].cfgSeqSize = sizeof(sataAndSgmiiTxConfigSerdesRev2Params2) / sizeof(MV_OP_PARAMS);
}
serdesSeqDb[SATA_TX_CONFIG_SEQ2].dataArrIdx = SATA;
/* SGMII_POWER_UP_SEQ sequence init */
serdesSeqDb[SGMII_POWER_UP_SEQ].opParamsPtr = sataAndSgmiiPowerUpParams;
serdesSeqDb[SGMII_POWER_UP_SEQ].cfgSeqSize = sizeof(sataAndSgmiiPowerUpParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[SGMII_POWER_UP_SEQ].dataArrIdx = SGMII;
/* SGMII__1_25_SPEED_CONFIG_SEQ sequence init */
serdesSeqDb[SGMII__1_25_SPEED_CONFIG_SEQ].opParamsPtr = sataAndSgmiiSpeedConfigParams;
serdesSeqDb[SGMII__1_25_SPEED_CONFIG_SEQ].cfgSeqSize = sizeof(sataAndSgmiiSpeedConfigParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[SGMII__1_25_SPEED_CONFIG_SEQ].dataArrIdx = SGMII;
/* SGMII__3_125_SPEED_CONFIG_SEQ sequence init */
serdesSeqDb[SGMII__3_125_SPEED_CONFIG_SEQ].opParamsPtr = sataAndSgmiiSpeedConfigParams;
serdesSeqDb[SGMII__3_125_SPEED_CONFIG_SEQ].cfgSeqSize = sizeof(sataAndSgmiiSpeedConfigParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[SGMII__3_125_SPEED_CONFIG_SEQ].dataArrIdx = SGMII_3_125;
/* SGMII_ELECTRICAL_CONFIG_SEQ seq sequence init */
if(serdesRev == MV_SERDES_REV_1_2) {
serdesSeqDb[SGMII_ELECTRICAL_CONFIG_SEQ].opParamsPtr = sgmiiElectricalConfigSerdesRev1Params;
serdesSeqDb[SGMII_ELECTRICAL_CONFIG_SEQ].cfgSeqSize = sizeof(sgmiiElectricalConfigSerdesRev1Params) / sizeof(MV_OP_PARAMS);
} else {
serdesSeqDb[SGMII_ELECTRICAL_CONFIG_SEQ].opParamsPtr = sgmiiElectricalConfigSerdesRev2Params;
serdesSeqDb[SGMII_ELECTRICAL_CONFIG_SEQ].cfgSeqSize = sizeof(sgmiiElectricalConfigSerdesRev2Params) / sizeof(MV_OP_PARAMS);
}
serdesSeqDb[SGMII_ELECTRICAL_CONFIG_SEQ].dataArrIdx = SGMII;
/* SGMII_TX_CONFIG_SEQ sequence init */
serdesSeqDb[SGMII_TX_CONFIG_SEQ1].opParamsPtr = sataAndSgmiiTxConfigParams1;
serdesSeqDb[SGMII_TX_CONFIG_SEQ1].cfgSeqSize = sizeof(sataAndSgmiiTxConfigParams1) / sizeof(MV_OP_PARAMS);
serdesSeqDb[SGMII_TX_CONFIG_SEQ1].dataArrIdx = SGMII;
/* SGMII_TX_CONFIG_SEQ sequence init */
if(serdesRev == MV_SERDES_REV_1_2) {
serdesSeqDb[SGMII_TX_CONFIG_SEQ2].opParamsPtr = sataAndSgmiiTxConfigSerdesRev1Params2;
serdesSeqDb[SGMII_TX_CONFIG_SEQ2].cfgSeqSize = sizeof(sataAndSgmiiTxConfigSerdesRev1Params2) / sizeof(MV_OP_PARAMS);
} else {
serdesSeqDb[SGMII_TX_CONFIG_SEQ2].opParamsPtr = sataAndSgmiiTxConfigSerdesRev2Params2;
serdesSeqDb[SGMII_TX_CONFIG_SEQ2].cfgSeqSize = sizeof(sataAndSgmiiTxConfigSerdesRev2Params2) / sizeof(MV_OP_PARAMS);
}
serdesSeqDb[SGMII_TX_CONFIG_SEQ2].dataArrIdx = SGMII;
/* PEX_POWER_UP_SEQ sequence init */
if(serdesRev == MV_SERDES_REV_1_2) {
serdesSeqDb[PEX_POWER_UP_SEQ].opParamsPtr = pexAndUsb3PowerUpSerdesRev1Params;
serdesSeqDb[PEX_POWER_UP_SEQ].cfgSeqSize = sizeof(pexAndUsb3PowerUpSerdesRev1Params) / sizeof(MV_OP_PARAMS);
} else {
serdesSeqDb[PEX_POWER_UP_SEQ].opParamsPtr = pexAndUsb3PowerUpSerdesRev2Params;
serdesSeqDb[PEX_POWER_UP_SEQ].cfgSeqSize = sizeof(pexAndUsb3PowerUpSerdesRev2Params) / sizeof(MV_OP_PARAMS);
}
serdesSeqDb[PEX_POWER_UP_SEQ].dataArrIdx = PEX;
/* PEX__2_5_SPEED_CONFIG_SEQ sequence init */
serdesSeqDb[PEX__2_5_SPEED_CONFIG_SEQ].opParamsPtr = pexAndUsb3SpeedConfigParams;
serdesSeqDb[PEX__2_5_SPEED_CONFIG_SEQ].cfgSeqSize = sizeof(pexAndUsb3SpeedConfigParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[PEX__2_5_SPEED_CONFIG_SEQ].dataArrIdx = PEX__2_5Gbps;
/* PEX__5_SPEED_CONFIG_SEQ sequence init */
serdesSeqDb[PEX__5_SPEED_CONFIG_SEQ].opParamsPtr = pexAndUsb3SpeedConfigParams;
serdesSeqDb[PEX__5_SPEED_CONFIG_SEQ].cfgSeqSize = sizeof(pexAndUsb3SpeedConfigParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[PEX__5_SPEED_CONFIG_SEQ].dataArrIdx = PEX__5Gbps;
/* PEX_ELECTRICAL_CONFIG_SEQ seq sequence init */
if(serdesRev == MV_SERDES_REV_1_2) {
serdesSeqDb[PEX_ELECTRICAL_CONFIG_SEQ].opParamsPtr = pexElectricalConfigSerdesRev1Params;
serdesSeqDb[PEX_ELECTRICAL_CONFIG_SEQ].cfgSeqSize = sizeof(pexElectricalConfigSerdesRev1Params) / sizeof(MV_OP_PARAMS);
} else {
serdesSeqDb[PEX_ELECTRICAL_CONFIG_SEQ].opParamsPtr = pexElectricalConfigSerdesRev2Params;
serdesSeqDb[PEX_ELECTRICAL_CONFIG_SEQ].cfgSeqSize = sizeof(pexElectricalConfigSerdesRev2Params) / sizeof(MV_OP_PARAMS);
}
serdesSeqDb[PEX_ELECTRICAL_CONFIG_SEQ].dataArrIdx = PEX;
/* PEX_TX_CONFIG_SEQ1 sequence init */
serdesSeqDb[PEX_TX_CONFIG_SEQ1].opParamsPtr = pexAndUsb3TxConfigParams1;
serdesSeqDb[PEX_TX_CONFIG_SEQ1].cfgSeqSize = sizeof(pexAndUsb3TxConfigParams1) / sizeof(MV_OP_PARAMS);
serdesSeqDb[PEX_TX_CONFIG_SEQ1].dataArrIdx = PEX;
/* PEX_TX_CONFIG_SEQ2 sequence init */
serdesSeqDb[PEX_TX_CONFIG_SEQ2].opParamsPtr = pexAndUsb3TxConfigParams2;
serdesSeqDb[PEX_TX_CONFIG_SEQ2].cfgSeqSize = sizeof(pexAndUsb3TxConfigParams2) / sizeof(MV_OP_PARAMS);
serdesSeqDb[PEX_TX_CONFIG_SEQ2].dataArrIdx = PEX;
/* PEX_TX_CONFIG_SEQ3 sequence init */
serdesSeqDb[PEX_TX_CONFIG_SEQ3].opParamsPtr = pexAndUsb3TxConfigParams3;
serdesSeqDb[PEX_TX_CONFIG_SEQ3].cfgSeqSize = sizeof(pexAndUsb3TxConfigParams3) / sizeof(MV_OP_PARAMS);
serdesSeqDb[PEX_TX_CONFIG_SEQ3].dataArrIdx = PEX;
/* PEX_BY_4_CONFIG_SEQ sequence init */
serdesSeqDb[PEX_BY_4_CONFIG_SEQ].opParamsPtr = pexBy4ConfigParams;
serdesSeqDb[PEX_BY_4_CONFIG_SEQ].cfgSeqSize = sizeof(pexBy4ConfigParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[PEX_BY_4_CONFIG_SEQ].dataArrIdx = PEX;
/* PEX_CONFIG_REF_CLOCK_25MHz_SEQ sequence init */
serdesSeqDb[PEX_CONFIG_REF_CLOCK_25MHz_SEQ].opParamsPtr = pexConfigRefClock25MHz;
serdesSeqDb[PEX_CONFIG_REF_CLOCK_25MHz_SEQ].cfgSeqSize = sizeof(pexConfigRefClock25MHz) / sizeof(MV_OP_PARAMS);
serdesSeqDb[PEX_CONFIG_REF_CLOCK_25MHz_SEQ].dataArrIdx = PEX;
/* PEX_ELECTRICAL_CONFIG_REF_CLOCK_40MHz_SEQ sequence init */
serdesSeqDb[PEX_CONFIG_REF_CLOCK_40MHz_SEQ].opParamsPtr = pexConfigRefClock40MHz;
serdesSeqDb[PEX_CONFIG_REF_CLOCK_40MHz_SEQ].cfgSeqSize = sizeof(pexConfigRefClock40MHz) / sizeof(MV_OP_PARAMS);
serdesSeqDb[PEX_CONFIG_REF_CLOCK_40MHz_SEQ].dataArrIdx = PEX;
/* PEX_CONFIG_REF_CLOCK_100MHz_SEQ sequence init */
serdesSeqDb[PEX_CONFIG_REF_CLOCK_100MHz_SEQ].opParamsPtr = pexConfigRefClock100MHz;
serdesSeqDb[PEX_CONFIG_REF_CLOCK_100MHz_SEQ].cfgSeqSize = sizeof(pexConfigRefClock100MHz) / sizeof(MV_OP_PARAMS);
serdesSeqDb[PEX_CONFIG_REF_CLOCK_100MHz_SEQ].dataArrIdx = PEX;
/* USB3_POWER_UP_SEQ sequence init */
if(serdesRev == MV_SERDES_REV_1_2) {
serdesSeqDb[USB3_POWER_UP_SEQ].opParamsPtr = pexAndUsb3PowerUpSerdesRev1Params;
serdesSeqDb[USB3_POWER_UP_SEQ].cfgSeqSize = sizeof(pexAndUsb3PowerUpSerdesRev1Params) / sizeof(MV_OP_PARAMS);
} else {
serdesSeqDb[USB3_POWER_UP_SEQ].opParamsPtr = pexAndUsb3PowerUpSerdesRev2Params;
serdesSeqDb[USB3_POWER_UP_SEQ].cfgSeqSize = sizeof(pexAndUsb3PowerUpSerdesRev2Params) / sizeof(MV_OP_PARAMS);
}
serdesSeqDb[USB3_POWER_UP_SEQ].dataArrIdx = USB3;
/* USB3__HOST_SPEED_CONFIG_SEQ sequence init */
serdesSeqDb[USB3__HOST_SPEED_CONFIG_SEQ].opParamsPtr = pexAndUsb3SpeedConfigParams;
serdesSeqDb[USB3__HOST_SPEED_CONFIG_SEQ].cfgSeqSize = sizeof(pexAndUsb3SpeedConfigParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[USB3__HOST_SPEED_CONFIG_SEQ].dataArrIdx = USB3__5Gbps_HOST;
/* USB3__DEVICE_SPEED_CONFIG_SEQ sequence init */
serdesSeqDb[USB3__DEVICE_SPEED_CONFIG_SEQ].opParamsPtr = pexAndUsb3SpeedConfigParams;
serdesSeqDb[USB3__DEVICE_SPEED_CONFIG_SEQ].cfgSeqSize = sizeof(pexAndUsb3SpeedConfigParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[USB3__DEVICE_SPEED_CONFIG_SEQ].dataArrIdx = USB3__5Gbps_DEVICE;
/* USB3_ELECTRICAL_CONFIG_SEQ seq sequence init */
if(serdesRev == MV_SERDES_REV_1_2) {
serdesSeqDb[USB3_ELECTRICAL_CONFIG_SEQ].opParamsPtr = usb3ElectricalConfigSerdesRev1Params;
serdesSeqDb[USB3_ELECTRICAL_CONFIG_SEQ].cfgSeqSize = sizeof(usb3ElectricalConfigSerdesRev1Params) / sizeof(MV_OP_PARAMS);
} else {
serdesSeqDb[USB3_ELECTRICAL_CONFIG_SEQ].opParamsPtr = usb3ElectricalConfigSerdesRev2Params;
serdesSeqDb[USB3_ELECTRICAL_CONFIG_SEQ].cfgSeqSize = sizeof(usb3ElectricalConfigSerdesRev2Params) / sizeof(MV_OP_PARAMS);
}
serdesSeqDb[USB3_ELECTRICAL_CONFIG_SEQ].dataArrIdx = FIRST_CELL;
/* USB3_TX_CONFIG_SEQ sequence init */
serdesSeqDb[USB3_TX_CONFIG_SEQ1].opParamsPtr = pexAndUsb3TxConfigParams1;
serdesSeqDb[USB3_TX_CONFIG_SEQ1].cfgSeqSize = sizeof(pexAndUsb3TxConfigParams1) / sizeof(MV_OP_PARAMS);
serdesSeqDb[USB3_TX_CONFIG_SEQ1].dataArrIdx = USB3;
/* USB3_TX_CONFIG_SEQ sequence init */
serdesSeqDb[USB3_TX_CONFIG_SEQ2].opParamsPtr = pexAndUsb3TxConfigParams2;
serdesSeqDb[USB3_TX_CONFIG_SEQ2].cfgSeqSize = sizeof(pexAndUsb3TxConfigParams2) / sizeof(MV_OP_PARAMS);
serdesSeqDb[USB3_TX_CONFIG_SEQ2].dataArrIdx = USB3;
/* USB3_TX_CONFIG_SEQ sequence init */
serdesSeqDb[USB3_TX_CONFIG_SEQ3].opParamsPtr = pexAndUsb3TxConfigParams3;
serdesSeqDb[USB3_TX_CONFIG_SEQ3].cfgSeqSize = sizeof(pexAndUsb3TxConfigParams3) / sizeof(MV_OP_PARAMS);
serdesSeqDb[USB3_TX_CONFIG_SEQ3].dataArrIdx = USB3;
/* USB2_POWER_UP_SEQ sequence init */
serdesSeqDb[USB2_POWER_UP_SEQ].opParamsPtr = usb2PowerUpParams;
serdesSeqDb[USB2_POWER_UP_SEQ].cfgSeqSize = sizeof(usb2PowerUpParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[USB2_POWER_UP_SEQ].dataArrIdx = 0;
/* USB3_DEVICE_CONFIG_SEQ sequence init */
serdesSeqDb[USB3_DEVICE_CONFIG_SEQ].opParamsPtr = usb3DeviceConfigParams;
serdesSeqDb[USB3_DEVICE_CONFIG_SEQ].cfgSeqSize = sizeof(usb3DeviceConfigParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[USB3_DEVICE_CONFIG_SEQ].dataArrIdx = 0; /* Not relevant */
/* SERDES_POWER_DOWN_SEQ sequence init */
serdesSeqDb[SERDES_POWER_DOWN_SEQ].opParamsPtr = serdesPowerDownParams;
serdesSeqDb[SERDES_POWER_DOWN_SEQ].cfgSeqSize = sizeof(serdesPowerDownParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[SERDES_POWER_DOWN_SEQ].dataArrIdx = FIRST_CELL;
if(serdesRev == MV_SERDES_REV_2_1) {
/* QSGMII_POWER_UP_SEQ sequence init */
serdesSeqDb[QSGMII_POWER_UP_SEQ].opParamsPtr = qsgmiiPortPowerUpParams;
serdesSeqDb[QSGMII_POWER_UP_SEQ].cfgSeqSize = sizeof(qsgmiiPortPowerUpParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[QSGMII_POWER_UP_SEQ].dataArrIdx = QSGMII_SEQ_IDX;
/* QSGMII__5_SPEED_CONFIG_SEQ sequence init */
serdesSeqDb[QSGMII__5_SPEED_CONFIG_SEQ].opParamsPtr = qsgmiiPortSpeedConfigParams;
serdesSeqDb[QSGMII__5_SPEED_CONFIG_SEQ].cfgSeqSize = sizeof(qsgmiiPortSpeedConfigParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[QSGMII__5_SPEED_CONFIG_SEQ].dataArrIdx = QSGMII_SEQ_IDX;
/* QSGMII_ELECTRICAL_CONFIG_SEQ seq sequence init */
serdesSeqDb[QSGMII_ELECTRICAL_CONFIG_SEQ].opParamsPtr = qsgmiiPortElectricalConfigParams;
serdesSeqDb[QSGMII_ELECTRICAL_CONFIG_SEQ].cfgSeqSize = sizeof(qsgmiiPortElectricalConfigParams) / sizeof(MV_OP_PARAMS);
serdesSeqDb[QSGMII_ELECTRICAL_CONFIG_SEQ].dataArrIdx = QSGMII_SEQ_IDX;
/* QSGMII_TX_CONFIG_SEQ sequence init */
serdesSeqDb[QSGMII_TX_CONFIG_SEQ1].opParamsPtr = qsgmiiPortTxConfigParams1;
serdesSeqDb[QSGMII_TX_CONFIG_SEQ1].cfgSeqSize = sizeof(qsgmiiPortTxConfigParams1) / sizeof(MV_OP_PARAMS);
serdesSeqDb[QSGMII_TX_CONFIG_SEQ1].dataArrIdx = QSGMII_SEQ_IDX;
/* QSGMII_TX_CONFIG_SEQ sequence init */
serdesSeqDb[QSGMII_TX_CONFIG_SEQ2].opParamsPtr = qsgmiiPortTxConfigParams2;
serdesSeqDb[QSGMII_TX_CONFIG_SEQ2].cfgSeqSize = sizeof(qsgmiiPortTxConfigParams2) / sizeof(MV_OP_PARAMS);
serdesSeqDb[QSGMII_TX_CONFIG_SEQ2].dataArrIdx = QSGMII_SEQ_IDX;
}
return MV_OK;
}
/***************************************************************************/
SERDES_SEQ serdesTypeAndSpeedToSpeedSeq
(
SERDES_TYPE serdesType,
SERDES_SPEED baudRate
)
{
SERDES_SEQ seqId = SERDES_LAST_SEQ;
DEBUG_INIT_FULL_S("\n### serdesTypeAndSpeedToSpeedSeq ###\n");
switch (serdesType) {
case PEX0:
case PEX1:
case PEX2:
case PEX3:
if (baudRate == __2_5Gbps)
seqId = PEX__2_5_SPEED_CONFIG_SEQ;
else if (baudRate == __5Gbps)
seqId = PEX__5_SPEED_CONFIG_SEQ;
break;
case USB3_HOST0:
case USB3_HOST1:
if (baudRate == __5Gbps)
seqId = USB3__HOST_SPEED_CONFIG_SEQ;
break;
case USB3_DEVICE:
if (baudRate == __5Gbps)
seqId = USB3__DEVICE_SPEED_CONFIG_SEQ;
break;
case SATA0:
case SATA1:
case SATA2:
case SATA3:
if (baudRate == __1_5Gbps)
seqId = SATA__1_5_SPEED_CONFIG_SEQ;
else if (baudRate == __3Gbps)
seqId = SATA__3_SPEED_CONFIG_SEQ;
else if (baudRate == __6Gbps)
seqId = SATA__6_SPEED_CONFIG_SEQ;
break;
case SGMII0:
case SGMII1:
case SGMII2:
#ifdef MV88F69XX
case SGMIIv3_0:
case SGMIIv3_1:
case SGMIIv3_2:
case SGMIIv3_3:
#endif
if (baudRate == __1_25Gbps)
seqId = SGMII__1_25_SPEED_CONFIG_SEQ;
else if (baudRate == __3_125Gbps)
seqId = SGMII__3_125_SPEED_CONFIG_SEQ;
break;
case QSGMII:
seqId = QSGMII__5_SPEED_CONFIG_SEQ;
break;
#ifdef MV88F69XX
case XAUI:
seqId = XAUI__3_125_SPEED_CONFIG_SEQ;
break;
case RXAUI:
seqId = RXAUI__6_25_SPEED_CONFIG_SEQ;
break;
#endif
default:
return SERDES_LAST_SEQ;
}
return seqId;
}
/***************************************************************************/
MV_STATUS mvHwsBoardTopologyLoad(SERDES_MAP *serdesMapArray)
{
MV_U32 boardId = mvBoardIdGet();
MV_U32 boardIdIndex = mvBoardIdIndexGet(boardId);
DEBUG_INIT_FULL_S("\n### mvHwsBoardTopologyLoad ###\n");
/* getting board topology according to the board id */
DEBUG_INIT_FULL_S("Getting board topology according to the board id\n");
CHECK_STATUS(loadTopologyFuncArr[boardIdIndex](serdesMapArray));
return MV_OK;
}
/***************************************************************************/
MV_VOID printTopologyDetails(SERDES_MAP *serdesMapArray)
{
MV_U32 laneNum, pexBy4Lane=0;
mvPrintf("board SerDes lanes topology details:\n");
mvPrintf(" | Lane # | Speed| Type |\n");
mvPrintf(" ------------------------------|\n");
for (laneNum = 0; laneNum < mvHwsSerdesGetMaxLane(); laneNum++) {
if (serdesMapArray[laneNum].serdesType == DEFAULT_SERDES)
{
continue;
}
mvPrintf (" | %d | %d | ",mvHwsGetPhysicalSerdesNum(laneNum),serdesMapArray[laneNum].serdesSpeed);
if ((serdesMapArray[laneNum].serdesMode == PEX_END_POINT_x4) || (serdesMapArray[laneNum].serdesMode == PEX_ROOT_COMPLEX_x4)){
mvPrintf ("PCIe0x4-%01d ",pexBy4Lane++ );
}
else{
mvPrintf ("%s",serdesTypeToString[serdesMapArray[laneNum].serdesType]);
}
mvPrintf("|\n");
}
mvPrintf(" -------------------------------\n");
}
/***************************************************************************/
MV_STATUS mvHwsPreSerdesInitConfig(MV_VOID)
{
MV_U32 data, refClkSatR;
/* configure Core PLL */
/*
set PLL parameters
bits[2:0] =0x3 (Core-PLL Kdiv)
bits[20:12]=0x9F (Core-PLL Ndiv)
bits[24:21]=0x7(Core-PLL VCO Band)
bits[28:25]=0x1(Core-PLL Rlf)
bits[31:29]=0x2(Core-PLL charge-pump adjust)
(the configuration valid only for refclk 25Mhz, for 40Mhz better default configuration at this time)
*/
refClkSatR = MV_REG_READ(DEVICE_SAMPLE_AT_RESET2_REG);
if(((refClkSatR >> DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_OFFSET) & 0x1) == DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_25MHZ){
/*Skip the configuration in REFLK 40Mhz mode*/
MV_REG_WRITE(CORE_PLL_PARAMETERS_REG, 0x42E9F003);
}
/* Enable PLL Configuration */
data = MV_REG_READ(CORE_PLL_CONFIG_REG);
data = SET_BIT(data, 9);
MV_REG_WRITE(CORE_PLL_CONFIG_REG, data);
return MV_OK;
}
/***************************************************************************/
MV_STATUS mvHwsCtrlHighSpeedSerdesPhyConfig(MV_VOID)
{
DEBUG_INIT_FULL_S("\n### mvCtrlHighSpeedSerdesPhyConfig ###\n");
DEBUG_INIT_S("High speed PHY - Version: ");
DEBUG_INIT_S(SERDES_VERION);
DEBUG_INIT_S("\n");
/* Init serdes sequences DB */
if (mvHwsSerdesSeqInit() != MV_OK){
mvPrintf("mvHwsCtrlHighSpeedSerdesPhyConfig: Error: Serdes initialization fail\n");
return MV_FAIL;
}
/* TWSI init */
DEBUG_INIT_FULL_S("mvHwsTwsiInitWrapper: Init TWSI interface.\n");
CHECK_STATUS(mvHwsTwsiInitWrapper());
/* Board topology load */
DEBUG_INIT_FULL_S("mvCtrlHighSpeedSerdesPhyConfig: Loading board topology..\n");
CHECK_STATUS(mvHwsBoardTopologyLoad(serdesConfigurationMap));
/* print topology */
printTopologyDetails(serdesConfigurationMap);
CHECK_STATUS(mvHwsPreSerdesInitConfig());
/* Power-Up sequence */
DEBUG_INIT_FULL_S("mvCtrlHighSpeedSerdesPhyConfig: Starting serdes power up sequence\n");
CHECK_STATUS(mvHwsPowerUpSerdesLanes(serdesConfigurationMap));
DEBUG_INIT_FULL_S("\n### mvCtrlHighSpeedSerdesPhyConfig ended successfully ###\n");
DEBUG_INIT_S(ENDED_OK);
return MV_OK;
}
/***************************************************************************/
MV_STATUS mvSerdesPolarityConfig(MV_U32 serdesNum, MV_BOOL isRx)
{
MV_U32 data;
MV_U32 regAddr;
MV_U8 bitOff = (isRx) ? 11 : 10;
regAddr = SERDES_REGS_LANE_BASE_OFFSET(serdesNum) + SYNC_PATTERN_REG;
data = MV_REG_READ(regAddr);
data = SET_BIT(data, bitOff);
MV_REG_WRITE(regAddr, data);
return MV_OK;
}
/***************************************************************************/
MV_STATUS mvHwsPowerUpSerdesLanes(SERDES_MAP *serdesConfigMap)
{
MV_U32 serdesId, serdesLaneNum;
REF_CLOCK refClock;
SERDES_TYPE serdesType;
SERDES_SPEED serdesSpeed;
SERDES_MODE serdesMode;
MV_BOOL serdesRxPolaritySwap;
MV_BOOL serdesTxPolaritySwap;
MV_BOOL isPexEnabled = MV_FALSE; /* flag which indicates that one of the
Serdes is of PEX. in this case, PEX
unit will be initialized after Serdes power-up */
DEBUG_INIT_FULL_S("\n### mvHwsPowerUpSerdesLanes ###\n");
/* COMMON PHYS SELECTORS register configuration */
DEBUG_INIT_FULL_S("mvHwsPowerUpSerdesLanes: Updating COMMON PHYS SELECTORS reg\n");
CHECK_STATUS(mvHwsUpdateSerdesPhySelectors(serdesConfigurationMap));
/* per Serdes Power Up */
for (serdesId = 0; serdesId < mvHwsSerdesGetMaxLane(); serdesId++) {
DEBUG_INIT_FULL_S("calling serdesPowerUpCtrl: serdes lane number ");
DEBUG_INIT_FULL_D_10(serdesLaneNum, 1);
DEBUG_INIT_FULL_S("\n");
serdesLaneNum = mvHwsGetPhysicalSerdesNum(serdesId);
serdesType = serdesConfigMap[serdesId].serdesType;
serdesSpeed = serdesConfigMap[serdesId].serdesSpeed;
serdesMode = serdesConfigMap[serdesId].serdesMode;
serdesRxPolaritySwap = serdesConfigMap[serdesId].swapRx;
serdesTxPolaritySwap = serdesConfigMap[serdesId].swapTx;
/* serdes lane is not in use */
if (serdesType == DEFAULT_SERDES)
continue;
else if(serdesType <= PEX3) /* PEX type */
isPexEnabled = MV_TRUE;
refClock = mvHwsSerdesGetRefClockVal(serdesType);
if (refClock == REF_CLOCK_UNSUPPORTED) {
DEBUG_INIT_S("mvHwsPowerUpSerdesLanes: unsupported ref clock\n");
return MV_NOT_SUPPORTED;
}
CHECK_STATUS(mvSerdesPowerUpCtrl(serdesLaneNum,
MV_TRUE,
serdesType,
serdesSpeed,
serdesMode,
refClock));
/* RX Polarity config */
if(serdesRxPolaritySwap)
CHECK_STATUS(mvSerdesPolarityConfig(serdesLaneNum, MV_TRUE));
/* TX Polarity config */
if(serdesTxPolaritySwap)
CHECK_STATUS(mvSerdesPolarityConfig(serdesLaneNum, MV_FALSE));
}
if(isPexEnabled)
{
/* Set PEX_TX_CONFIG_SEQ sequence for PEXx4 mode.
After finish the PowerUp sequence for all lanes,
the lanes should be released from reset state. */
CHECK_STATUS(mvHwsPexTxConfigSeq(serdesConfigMap));
/* PEX configuration*/
CHECK_STATUS(mvHwsPexConfig(serdesConfigMap));
}
/* USB2 configuration */
DEBUG_INIT_FULL_S("mvHwsPowerUpSerdesLanes: init USB2 Phys\n");
CHECK_STATUS(mvSeqExec(0 /* not relevant */, USB2_POWER_UP_SEQ));
DEBUG_INIT_FULL_S("### mvHwsPowerUpSerdesLanes ended successfully ###\n");
return MV_OK;
}
/***************************************************************************/
MV_STATUS mvCtrlHighSpeedSerdesPhyConfig(MV_VOID)
{
return mvHwsCtrlHighSpeedSerdesPhyConfig(); // stub
}
/**************************************************************************
* updateUsb3DeviceConfig
* DESCRIPTION: Update USB3 configuration register if USB3 device is enabled
* INPUT:
* topologyConfigPtr - pointer to the Serdes mapping
*
***************************************************************************/
void updateUsb3DeviceConfig(SERDES_MAP *serdesMapArray)
{
MV_U32 laneNum;
for (laneNum = 0; laneNum < mvHwsSerdesGetMaxLane(); laneNum++) {
if (serdesMapArray[laneNum].serdesType == USB3_DEVICE) {
/* write 0x1 to USB3_CONFIG_REG[0:1]
* BIT0 (USB3 Device UTMI En) 0 : USB3 Device disabled.
* (USB2 on UTMI0, and USB3 Host1 on UTMI2)
* -> 1 : USB3 Device enabled
*
* BIT1 (USB3 Device UTMI Mux) -> 0 : UTMI2: USB3 Device is on UTMI2
* 1 : UTMI0: USB3 Device is on UTMI0 */
MV_REG_BIT_RESET(USB3_CONFIG_REG, BIT1);
MV_REG_BIT_SET(USB3_CONFIG_REG, BIT0);
return;
}
}
}
/***************************************************************************/
static MV_STATUS mvSerdesPexUsb3PipeDelayWA(MV_U32 serdesNum, MV_U8 serdesType)
{
MV_U32 regData;
/* WA for A380 Z1 relevant for lanes 3,4,5 only*/
if (serdesNum >= 3)
{
regData = MV_REG_READ(GENERAL_PURPOSE_RESERVED0_REG);
/* set delay on pipe -
* When lane 3 is connected to a MAC of Pex -> set bit 7 to 1.
* When lane 3 is connected to a MAC of USB3 -> set bit 7 to 0.
* When lane 4 is connected to a MAC of Pex -> set bit 8 to 1.
* When lane 4 is connected to a MAC of USB3 -> set bit 8 to 0.
* When lane 5 is connected to a MAC of Pex -> set bit 8 to 1.
* When lane 5 is connected to a MAC of USB3 -> set bit 8 to 0.
*/
if (serdesType == PEX)
{
regData |= 1 << (7 + (serdesNum - 3));
}
if (serdesType == USB3)
{
/* USB3 */
regData &= ~(1 << (7 + (serdesNum - 3)));
}
MV_REG_WRITE(GENERAL_PURPOSE_RESERVED0_REG, regData);
}
return MV_OK;
}
/**************************************************************************
* mvHwsSerdesPexRefClockSatRGet -
*
* DESCRIPTION: Get the reference clock value from DEVICE_SAMPLE_AT_RESET1_REG and check:
* bit[2] for PEX#0, bit[3] for PEX#1, bit[30] for PEX#2, bit[31] for PEX#3.
* If bit=0 --> REF_CLOCK_100MHz
* If bit=1 && DEVICE_SAMPLE_AT_RESET2_REG bit[0]=0 --> REF_CLOCK_25MHz
* If bit=1 && DEVICE_SAMPLE_AT_RESET2_REG bit[0]=1 --> REF_CLOCK_40MHz
*
* INPUT: serdesType - Type of Serdes
*
* OUTPUT: pexSatR - Return the REF_CLOCK value:
* REF_CLOCK_25MHz, REF_CLOCK_40MHz or REF_CLOCK_100MHz
*
* RETURNS: MV_OK - for success
* MV_BAD_PARAM - for fail
***************************************************************************/
MV_STATUS mvHwsSerdesPexRefClockSatRGet(SERDES_TYPE serdesType, MV_U32 *pexSatR)
{
MV_U32 data, regSatR1;
regSatR1 = MV_REG_READ(DEVICE_SAMPLE_AT_RESET1_REG);
switch (serdesType) {
case PEX0:
data = REF_CLK_SELECTOR_VAL_PEX0(regSatR1);
break;
case PEX1:
data = REF_CLK_SELECTOR_VAL_PEX1(regSatR1);
break;
case PEX2:
data = REF_CLK_SELECTOR_VAL_PEX2(regSatR1);
break;
case PEX3:
data = REF_CLK_SELECTOR_VAL_PEX3(regSatR1);
break;
default:
mvPrintf("%s: Error: SerDes type %d is not supported\n", __func__, serdesType);
return MV_BAD_PARAM;
}
*pexSatR = data;
return MV_OK;
}
/***************************************************************************/
MV_U32 mvHwsSerdesGetRefClockVal(SERDES_TYPE serdesType)
{
MV_U32 pexSatR;
REF_CLOCK refClock;
DEBUG_INIT_FULL_S("\n### mvHwsSerdesGetRefClockVal ###\n");
if (serdesType >= LAST_SERDES_TYPE) {
return REF_CLOCK_UNSUPPORTED;
}
/* read ref clock from S@R */
refClock = mvHwsSerdesSiliconRefClockGet();
if(serdesType > PEX3) {
/* for all Serdes types but PCIe */
return refClock;
}
/* for PCIe, need also to check PCIe S@R */
CHECK_STATUS(mvHwsSerdesPexRefClockSatRGet(serdesType, &pexSatR));
if (pexSatR == 0) {
return REF_CLOCK__100MHz;
}
else if(pexSatR == 1) {
/* value of 1 means we can use ref clock from SoC (as other Serdes types) */
return refClock;
}
else {
mvPrintf("%s: Error: REF_CLK_SELECTOR_VAL for SerDes type %d is wrong\n", __func__, serdesType);
return REF_CLOCK_UNSUPPORTED;
}
}
/***************************************************************************/
MV_STATUS mvSerdesPowerUpCtrl
(
MV_U32 serdesNum,
MV_BOOL serdesPowerUp,
SERDES_TYPE serdesType,
SERDES_SPEED baudRate,
SERDES_MODE serdesMode,
REF_CLOCK refClock
)
{
#ifdef DB_LINK_CHECK
int i;
#endif
MV_U32 sataIdx, pexIdx,sataPort;
SERDES_SEQ speedSeqId;
MV_U32 regData;
MV_BOOL isPexBy1;
MV_U32 boardId = mvBoardIdGet();
DEBUG_INIT_FULL_S("\n### mvSerdesPowerUpCtrl ###\n");
if (serdesPowerUp == MV_TRUE) { /* Serdes power up */
DEBUG_INIT_FULL_S("mvSerdesPowerUpCtrl: executing power up.. ");
DEBUG_INIT_FULL_C("serdes num = ", serdesNum, 2);
DEBUG_INIT_FULL_C("serdes type = ", serdesType, 2);
DEBUG_INIT_FULL_S("Going access 1");
/* Getting the Speed Select sequence id */
speedSeqId = serdesTypeAndSpeedToSpeedSeq(serdesType, baudRate);
if (speedSeqId == SERDES_LAST_SEQ) {
mvPrintf("mvSerdesPowerUpCtrl: serdes type %d and speed %d are not supported together\n",
serdesType, baudRate);
return MV_BAD_PARAM;
}
/* Executing power up, ref clock set, speed config and TX config */
switch (serdesType) {
case PEX0:
case PEX1:
case PEX2:
case PEX3:
if (mvHwsCtrlSerdesRevGet() == MV_SERDES_REV_1_2) {
CHECK_STATUS(mvSerdesPexUsb3PipeDelayWA(serdesNum, PEX));
}
isPexBy1 = (serdesMode == PEX_ROOT_COMPLEX_x1) || (serdesMode == PEX_END_POINT_x1);
pexIdx = serdesType - PEX0;
if ((isPexBy1 == MV_TRUE) || ((serdesType == PEX0) && (serdesNum == 0)))
{
/* the following should be done for PEXx1 and for PEX by 4-for the first lane only */
regData = MV_REG_READ(SOC_CONTROL_REG1);
if (isPexBy1 == MV_TRUE)
regData |= 0x4000;
else
regData &= ~0x4000;
MV_REG_WRITE(SOC_CONTROL_REG1, regData);
/* Setup link width bit[9:4] */
regData = MV_REG_READ(PEX_LINK_CAPABILITIES_REG(pexIdx));
regData &= ~0x3F0;
if (isPexBy1 == MV_TRUE)
regData |= 0x10;
else
regData |= 0x40;
MV_REG_WRITE(PEX_LINK_CAPABILITIES_REG(pexIdx), regData);
/* Setup maximum link speed bit[3:0] */
regData = MV_REG_READ(PEX_LINK_CAPABILITIES_REG(pexIdx));
regData &= ~0xF;
if ((boardId == DB_AMC_6820_ID) && (pexIdx == 0) &&
mvBoardForcePcieGen1Get()) {
/* The WA is required for BC2 A0, so SatR is coded accordingly */
mvPrintf("Forcing Link to GEN1 on PCIe-%d\n", pexIdx);
regData |= 0x1; /* GEN1, 2.5G */
} else
regData |= 0x2; /* GEN2, 5G */
MV_REG_WRITE(PEX_LINK_CAPABILITIES_REG(pexIdx), regData);
/* Setup common clock configuration bit[6] */
regData = MV_REG_READ(PEX_LINK_CTRL_STATUS_REG(pexIdx));
regData &= ~0x40;
regData |= 0x40;
MV_REG_WRITE(PEX_LINK_CTRL_STATUS_REG(pexIdx), regData);
}
CHECK_STATUS(mvSeqExec(serdesNum, PEX_POWER_UP_SEQ));
if (isPexBy1 == MV_FALSE) {
/* for PEX by 4 - use the serdesNum as the seq array index */
serdesSeqDb[PEX_BY_4_CONFIG_SEQ].dataArrIdx = serdesNum;
CHECK_STATUS(mvSeqExec(serdesNum, PEX_BY_4_CONFIG_SEQ));
}
CHECK_STATUS(mvHwsRefClockSet(serdesNum, serdesType, refClock));
CHECK_STATUS(mvSeqExec(serdesNum, speedSeqId));
CHECK_STATUS(mvSeqExec(serdesNum, PEX_ELECTRICAL_CONFIG_SEQ));
if (isPexBy1 == MV_TRUE) {
CHECK_STATUS(mvSeqExec(serdesNum, PEX_TX_CONFIG_SEQ2));
CHECK_STATUS(mvSeqExec(serdesNum, PEX_TX_CONFIG_SEQ3));
CHECK_STATUS(mvSeqExec(serdesNum, PEX_TX_CONFIG_SEQ1));
}
mvOsUDelay(20);
#ifdef DB_LINK_CHECK
if (serdesNum == 1) {
MV_REG_WRITE(SOC_CONTROL_REG1, 0x0707C0F1);
for (i = 0; i < LINK_WAIT_CNTR; i++) {
if ((MV_REG_READ(0x81a64) & 0xFF) == 0x7E) {
DEBUG_INIT_S("PCIe0 LINK UP ;-)\n");
break;
}
mvOsUDelay(LINK_WAIT_SLEEP);
}
if (i == LINK_WAIT_CNTR)
DEBUG_INIT_S("PCIe0 NO LINK ;-|\n");
}else{
MV_REG_WRITE(SOC_CONTROL_REG1, 0x0707C0F3);
for (i = 0; i < LINK_WAIT_CNTR; i++) {
if ((MV_REG_READ(0x41a64) & 0xFF) == 0x7E) {
DEBUG_INIT_S("PCIe1 LINK UP ;-)\n");
break;
}
mvOsUDelay(LINK_WAIT_SLEEP);
}
if (i == LINK_WAIT_CNTR)
DEBUG_INIT_S("PCIe1 NO LINK ;-|\n");
}
#endif /* DB_LINK_CHECK */
break;
case USB3_HOST0:
case USB3_HOST1:
case USB3_DEVICE:
if (mvHwsCtrlSerdesRevGet() == MV_SERDES_REV_1_2) {
CHECK_STATUS(mvSerdesPexUsb3PipeDelayWA(serdesNum, USB3));
}
CHECK_STATUS(mvSeqExec(serdesNum, USB3_POWER_UP_SEQ));
CHECK_STATUS(mvHwsRefClockSet(serdesNum, serdesType, refClock));
CHECK_STATUS(mvSeqExec(serdesNum, speedSeqId));
if (serdesType == USB3_DEVICE) {
CHECK_STATUS(mvSeqExec(serdesNum, USB3_DEVICE_CONFIG_SEQ));
}
CHECK_STATUS(mvSeqExec(serdesNum, USB3_ELECTRICAL_CONFIG_SEQ));
CHECK_STATUS(mvSeqExec(serdesNum, USB3_TX_CONFIG_SEQ1));
CHECK_STATUS(mvSeqExec(serdesNum, USB3_TX_CONFIG_SEQ2));
CHECK_STATUS(mvSeqExec(serdesNum, USB3_TX_CONFIG_SEQ3));
mvOsUDelay(10000);
#ifdef DB_LINK_CHECK
if ( serdesNum == 4) {
if ( 0 != (MV_REG_READ(0xA2004) & 0x100))
DEBUG_INIT_S("USB PLL0 LOCKED ;-|\n");
else
DEBUG_INIT_S("USB PLL0 UNLOCK ;-)\n");
if ( 0xD == (MV_REG_READ(0x183B8) & 0xD))
DEBUG_INIT_S("USB PLL0 READY ;-)\n");
else
DEBUG_INIT_S("USB PLL0 NOT READY ;-|\n");
}else{
if ( 0 != (MV_REG_READ(0xA2804) & 0x100))
DEBUG_INIT_S("USB PLL1 LOCKED ;-|\n");
else
DEBUG_INIT_S("USB PLL1 UNLOCK ;-)\n");
if ( 0xD == (MV_REG_READ(0x183E0) & 0xD))
DEBUG_INIT_S("USB PLL1 READY ;-)\n");
else
DEBUG_INIT_S("USB PLL1 NOT READY ;-|\n");
}
#endif /* DB_LINK_CHECK */
break;
case SATA0:
case SATA1:
case SATA2:
case SATA3:
sataIdx = ((serdesType == SATA0) || (serdesType == SATA1)) ? 0 : 1;
sataPort = ((serdesType == SATA0) || (serdesType == SATA2)) ? 0 : 1;
CHECK_STATUS(mvSeqExec(sataIdx, (sataPort == 0) ? SATA_PORT_0_ONLY_POWER_UP_SEQ :
SATA_PORT_1_ONLY_POWER_UP_SEQ));
CHECK_STATUS(mvSeqExec(serdesNum, SATA_POWER_UP_SEQ));
CHECK_STATUS(mvHwsRefClockSet(serdesNum, serdesType, refClock));
CHECK_STATUS(mvSeqExec(serdesNum, speedSeqId));
CHECK_STATUS(mvSeqExec(serdesNum, SATA_ELECTRICAL_CONFIG_SEQ));
CHECK_STATUS(mvSeqExec(serdesNum, SATA_TX_CONFIG_SEQ1));
CHECK_STATUS(mvSeqExec(sataIdx, (sataPort == 0) ? SATA_PORT_0_ONLY_TX_CONFIG_SEQ :
SATA_PORT_1_ONLY_TX_CONFIG_SEQ));
CHECK_STATUS(mvSeqExec(serdesNum, SATA_TX_CONFIG_SEQ2));
mvOsUDelay(10000);
#ifdef DB_LINK_CHECK
if ( serdesNum == 0) {
for (i = 0; i < LINK_WAIT_CNTR; i++) {
if ((MV_REG_READ(0x18318) & 0xD) == 0xD) {
DEBUG_INIT_S("SATA0 PLL READY ;-)\n");
break;
}
mvOsUDelay(LINK_WAIT_SLEEP);
}
if (i == LINK_WAIT_CNTR)
DEBUG_INIT_S("SATA0 PLL NOT READY\n");
}else{
for (i = 0; i < LINK_WAIT_CNTR; i++) {
if ((MV_REG_READ(0x18390) & 0xD) == 0xD) {
DEBUG_INIT_S("SATA1 PLL READY ;-)\n");
break;
}
mvOsUDelay(LINK_WAIT_SLEEP);
}
if (i == LINK_WAIT_CNTR)
DEBUG_INIT_S("SATA1 PLL NOT READY\n");
}
#endif /* DB_LINK_CHECK */
break;
case SGMII0:
case SGMII1:
case SGMII2:
CHECK_STATUS(mvSeqExec(serdesNum, SGMII_POWER_UP_SEQ));
CHECK_STATUS(mvHwsRefClockSet(serdesNum, serdesType, refClock));
CHECK_STATUS(mvSeqExec(serdesNum, speedSeqId));
CHECK_STATUS(mvSeqExec(serdesNum, SGMII_ELECTRICAL_CONFIG_SEQ));
CHECK_STATUS(mvSeqExec(serdesNum, SGMII_TX_CONFIG_SEQ1));
CHECK_STATUS(mvSeqExec(serdesNum, SGMII_TX_CONFIG_SEQ2));
/* GBE configuration */
regData = MV_REG_READ(GBE_CONFIGURATION_REG);
regData |= 0x1 << (serdesType - SGMII0); /* write the SGMII index */
MV_REG_WRITE(GBE_CONFIGURATION_REG, regData);
break;
case QSGMII:
if (mvHwsCtrlSerdesRevGet() < MV_SERDES_REV_2_1) {
return MV_NOT_SUPPORTED;
}
CHECK_STATUS(mvSeqExec(serdesNum, QSGMII_POWER_UP_SEQ));
CHECK_STATUS(mvHwsRefClockSet(serdesNum, serdesType, refClock));
CHECK_STATUS(mvSeqExec(serdesNum, speedSeqId));
CHECK_STATUS(mvSeqExec(serdesNum, QSGMII_ELECTRICAL_CONFIG_SEQ));
CHECK_STATUS(mvSeqExec(serdesNum, QSGMII_TX_CONFIG_SEQ1));
CHECK_STATUS(mvSeqExec(serdesNum, QSGMII_TX_CONFIG_SEQ2));
break;
case SGMIIv3_0:
case SGMIIv3_1:
case SGMIIv3_2:
case SGMIIv3_3:
case XAUI:
case RXAUI:
CHECK_STATUS(mvSerdesPowerUpCtrlExt(serdesNum, serdesPowerUp, serdesType, baudRate, serdesMode, refClock));
break;
default:
DEBUG_INIT_S("mvSerdesPowerUpCtrl: bad serdesType parameter\n");
return MV_BAD_PARAM;
}
}else { /* Serdes power down */
DEBUG_INIT_FULL_S("mvSerdesPowerUp: executing power down.. ");
DEBUG_INIT_FULL_C("serdes num = ", serdesNum, 1);
CHECK_STATUS(mvSeqExec(serdesNum, SERDES_POWER_DOWN_SEQ));
}
DEBUG_INIT_FULL_C("mvSerdesPowerUpCtrl ended successfully for serdes ", serdesNum, 2);
return MV_OK;
}
/***************************************************************************/
MV_STATUS mvHwsUpdateSerdesPhySelectors(SERDES_MAP* serdesConfigMap)
{
MV_U32 laneData, serdesIdx,serdesLaneHwNum, regData = 0;
SERDES_TYPE serdesType;
SERDES_MODE serdesMode;
MV_U8 selectBitOff;
MV_BOOL isPEXx4 = MV_FALSE;
MV_BOOL updatedTopologyPrint = MV_FALSE;
DEBUG_INIT_FULL_S("\n### mvHwsUpdateSerdesPhySelectors ###\n");
DEBUG_INIT_FULL_S("Updating the COMMON PHYS SELECTORS register with the serdes types\n");
if(mvHwsCtrlSerdesRevGet() == MV_SERDES_REV_1_2) {
selectBitOff = 3;
} else {
selectBitOff = 4;
}
/* Updating bits 0-17 in the COMMON PHYS SELECTORS register according to the serdes types */
for (serdesIdx = 0; serdesIdx < mvHwsSerdesGetMaxLane(); serdesIdx++) {
serdesType = serdesConfigMap[serdesIdx].serdesType;
serdesMode = serdesConfigMap[serdesIdx].serdesMode;
serdesLaneHwNum = mvHwsGetPhysicalSerdesNum(serdesIdx);
laneData = mvHwsSerdesGetPhySelectorVal(serdesLaneHwNum, serdesType);
if(serdesType == DEFAULT_SERDES) {
continue;
}
if (mvHwsSerdesTopologyVerify(serdesType,serdesIdx,serdesMode) != MV_OK){
serdesConfigMap[serdesIdx].serdesType = DEFAULT_SERDES;
mvPrintf("%s: SerDes lane #%d is disabled\n",__func__, serdesLaneHwNum);
updatedTopologyPrint = MV_TRUE;
continue;
}
/* Checking if the board topology configuration includes PEXx4 - for the next step */
if ((serdesMode == PEX_END_POINT_x4) || (serdesMode == PEX_ROOT_COMPLEX_x4)) {
/* update lane data to the 3 next SERDES lanes */
laneData = commonPhysSelectorsPexBy4Lanes[serdesLaneHwNum];
if (serdesType == PEX0) {
isPEXx4 = MV_TRUE;
}
}
if (laneData == NA) {
mvPrintf("%s: Warning: SerDes lane #%d and type %d are not supported together\n",
__func__, serdesLaneHwNum, serdesMode);
serdesConfigMap[serdesIdx].serdesType = DEFAULT_SERDES;
mvPrintf("%s: SerDes lane #%d is disabled\n",__func__, serdesLaneHwNum);
continue;
}
/* Updating the data that will be written to COMMON_PHYS_SELECTORS_REG */
regData |= (laneData << (selectBitOff * serdesLaneHwNum));
}
/* check that number of used lanes for PEXx4 if used is right */
if (isPEXx4)
mvHwsSerdesPCIX4TopologyVerify();
/* check that number of used lanes for XAUI and RXAUI (if used) is right */
mvHwsSerdesXAUITopologyVerify();
/* print topology */
if (updatedTopologyPrint)
printTopologyDetails(serdesConfigMap);
/* Updating the PEXx4 Enable bit in the COMMON PHYS SELECTORS register for PEXx4 mode */
regData |= (isPEXx4 == MV_TRUE) ? (0x1 << PEXx4_ENABLE_OFFS) : 0;
/* Updating the COMMON PHYS SELECTORS register */
MV_REG_WRITE(COMMON_PHYS_SELECTORS_REG, regData);
return MV_OK;
}
/***************************************************************************/
MV_STATUS mvHwsRefClockSet
(
MV_U32 serdesNum,
SERDES_TYPE serdesType,
REF_CLOCK refClock
)
{
MV_U32 data1=0, data2=0, data3=0, regData;
DEBUG_INIT_FULL_S("\n### mvHwsRefClockSet ###\n");
if (mvHwsIsSerdesActive(serdesNum) != MV_TRUE) {
mvPrintf("%s: SerDes lane #%d is not Active\n", __func__, serdesNum);
return MV_BAD_PARAM;
}
switch (serdesType) {
case PEX0:
case PEX1:
case PEX2:
case PEX3:
switch (refClock) {
case REF_CLOCK__25MHz:
CHECK_STATUS(mvSeqExec(serdesNum, PEX_CONFIG_REF_CLOCK_25MHz_SEQ));
return MV_OK;
case REF_CLOCK__100MHz:
CHECK_STATUS(mvSeqExec(serdesNum, PEX_CONFIG_REF_CLOCK_100MHz_SEQ));
return MV_OK;
#ifdef MV88F69XX
case REF_CLOCK__40MHz:
CHECK_STATUS(mvSeqExec(serdesNum, PEX_CONFIG_REF_CLOCK_40MHz_SEQ));
return MV_OK;
#endif
default:
mvPrintf("%s: Error: refClock %d for SerDes lane #%d, type %d is not supported\n",
__func__, refClock, serdesNum, serdesType);
return MV_BAD_PARAM;
}
case USB3_HOST0:
case USB3_HOST1:
case USB3_DEVICE:
if (refClock == REF_CLOCK__25MHz) {
data1 = POWER_AND_PLL_CTRL_REG_25MHZ_VAL_2;
data2 = GLOBAL_PM_CTRL_REG_25MHZ_VAL;
data3 = LANE_CFG4_REG_25MHZ_VAL;
}
else if (refClock == REF_CLOCK__40MHz) {
data1 = POWER_AND_PLL_CTRL_REG_40MHZ_VAL;
data2 = GLOBAL_PM_CTRL_REG_40MHZ_VAL;
data3 = LANE_CFG4_REG_40MHZ_VAL;
}
else{
mvPrintf("mvHwsRefClockSet: ref clock is not valid for serdes type %d\n", serdesType);
return MV_BAD_PARAM;
}
break;
case SATA0:
case SATA1:
case SATA2:
case SATA3:
case SGMII0:
case SGMII1:
case SGMII2:
case QSGMII:
if (refClock == REF_CLOCK__25MHz) {
data1 = POWER_AND_PLL_CTRL_REG_25MHZ_VAL_1;
}
else if (refClock == REF_CLOCK__40MHz) {
data1 = POWER_AND_PLL_CTRL_REG_40MHZ_VAL;
}
else{
mvPrintf("mvHwsRefClockSet: ref clock is not valid for serdes type %d\n", serdesType);
return MV_BAD_PARAM;
}
break;
#ifdef MV88F69XX
case SGMIIv3_0:
case SGMIIv3_1:
case SGMIIv3_2:
case SGMIIv3_3:
case XAUI:
case RXAUI:
if (refClock == REF_CLOCK__25MHz) {
data1 = POWER_AND_PLL_CTRL_REG_25MHZ_VAL_1;
}
else if (refClock == REF_CLOCK__40MHz) {
data1 = POWER_AND_PLL_CTRL_REG_40MHZ_VAL;
}
else{
mvPrintf("mvHwsRefClockSet: ref clock is not valid for serdes type %d\n", serdesType);
return MV_BAD_PARAM;
}
break;
#endif
default:
DEBUG_INIT_S("mvHwsRefClockSet: not supported serdes type\n");
return MV_BAD_PARAM;
}
/* Write the refClock to relevant SELECT_REF_CLOCK_REG bits and offset */
regData = MV_REG_READ(POWER_AND_PLL_CTRL_REG + SERDES_REGS_LANE_BASE_OFFSET(serdesNum));
regData &= POWER_AND_PLL_CTRL_REG_MASK;
regData |= data1;
MV_REG_WRITE(POWER_AND_PLL_CTRL_REG + SERDES_REGS_LANE_BASE_OFFSET(serdesNum), regData);
if ((serdesType == USB3_HOST0) || (serdesType == USB3_HOST1) || (serdesType == USB3_DEVICE)) {
regData = MV_REG_READ(GLOBAL_PM_CTRL + SERDES_REGS_LANE_BASE_OFFSET(serdesNum));
regData &= GLOBAL_PM_CTRL_REG_MASK;
regData |= data2;
MV_REG_WRITE(GLOBAL_PM_CTRL + SERDES_REGS_LANE_BASE_OFFSET(serdesNum), regData);
regData = MV_REG_READ(LANE_CFG4_REG + SERDES_REGS_LANE_BASE_OFFSET(serdesNum));
regData &= LANE_CFG4_REG_MASK;
regData |= data3;
MV_REG_WRITE(LANE_CFG4_REG + SERDES_REGS_LANE_BASE_OFFSET(serdesNum), regData);
}
return MV_OK;
}
/**************************************************************************
* mvHwsPexTxConfigSeq -
*
* DESCRIPTION: Set PEX_TX_CONFIG_SEQ sequence init for PEXx4 mode
* INPUT: serdesMap - The board topology map
* OUTPUT: None
* RETURNS: MV_OK - for success
* MV_BAD_PARAM - for fail
***************************************************************************/
MV_STATUS mvHwsPexTxConfigSeq(SERDES_MAP *serdesMap)
{
SERDES_MODE serdesMode;
MV_U32 serdesLaneId, serdesLaneHwNum;
DEBUG_INIT_FULL_S("\n### mvHwsPexTxConfigSeq ###\n");
/* For PEXx4: the pexAndUsb3TxConfigParams1/2/3 configurations should run
by setting each sequence for all 4 lanes. */
/* relese pipe soft reset for all lanes */
for (serdesLaneId = 0; serdesLaneId < mvHwsSerdesGetMaxLane(); serdesLaneId++) {
serdesMode = serdesMap[serdesLaneId].serdesMode;
serdesLaneHwNum = mvHwsGetPhysicalSerdesNum(serdesLaneId);
if ((serdesMode == PEX_ROOT_COMPLEX_x4) || (serdesMode == PEX_END_POINT_x4)) {
CHECK_STATUS(mvSeqExec(serdesLaneHwNum, PEX_TX_CONFIG_SEQ1));
}
}
/* set phy soft reset for all lanes */
for (serdesLaneId = 0; serdesLaneId < mvHwsSerdesGetMaxLane(); serdesLaneId++) {
serdesMode = serdesMap[serdesLaneId].serdesMode;
serdesLaneHwNum = mvHwsGetPhysicalSerdesNum(serdesLaneId);
if ((serdesMode == PEX_ROOT_COMPLEX_x4) || (serdesMode == PEX_END_POINT_x4)) {
CHECK_STATUS(mvSeqExec(serdesLaneHwNum, PEX_TX_CONFIG_SEQ2));
}
}
/* set phy soft reset for all lanes */
for (serdesLaneId = 0; serdesLaneId < mvHwsSerdesGetMaxLane(); serdesLaneId++) {
serdesMode = serdesMap[serdesLaneId].serdesMode;
serdesLaneHwNum = mvHwsGetPhysicalSerdesNum(serdesLaneId);
if ((serdesMode == PEX_ROOT_COMPLEX_x4) || (serdesMode == PEX_END_POINT_x4)) {
CHECK_STATUS(mvSeqExec(serdesLaneHwNum, PEX_TX_CONFIG_SEQ3));
}
}
return MV_OK;
}