blob: 58a854598179fb70beafe046b7770f76b88b3796 [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 "mv_os.h"
#include "config_marvell.h" /* Required to identify SOC and Board */
#include "mvHighSpeedEnvSpec.h"
#include "mvHighSpeedTopologySpec.h"
#include "mv_seq_exec_ext.h"
#include "mvSysEnvLib.h"
#include "mvCtrlPex.h"
#if defined(MV_MSYS_BC2)
#include "ddr3_msys_bc2.h"
#include "ddr3_msys_bc2_config.h"
#elif defined(MV_MSYS_AC3)
#include "ddr3_msys_ac3.h"
#include "ddr3_msys_ac3_config.h"
#endif
#include "bin_hdr_twsi.h"
#include "mvUart.h"
#include "util.h"
/************************************ definitions ***********************************/
#define MV_SERDES_BASE 0x13000000
#define MV_SERDES_PHY_BASE 0x13000800
#define MV_SERDES_OFFSET 0x1000
#define MV_INTERNAL_OFFSET 0x1000
/************************************ globals ***********************************/
/* serdesSeqDb - holds all SERDES sequences, their size and the relevant index in the data array
initialized in mvSerdesSeqInit */
MV_CFG_EXT_SEQ serdesSeqDb[SERDES_LAST_SEQ];
/* SERDES type to ref clock map */
REF_CLOCK serdesTypeToRefClockMap[LAST_SERDES_TYPE] =
{
REF_CLOCK__100MHz, /* PEX0 */
REF_CLOCK__25MHz, /* SGMII0 */
REF_CLOCK__25MHz, /* SGMII1 */
REF_CLOCK_UNSUPPORTED /* DEFAULT_SERDES */
};
/*****************/
/* USB2 */
/*****************/
MV_OP_EXT_PARAMS usb2PowerUpParams[] =
{
/* unitunitBaseReg unitOffset mask USB2 data waitTime numOfLoops */
{ USB_REG_UNIT, 0x50804, 0x3, { 0x2 }, 0, 0 }, /* Phy offset 0x1 - PLL_CONTROL1 */
{ USB_REG_UNIT, 0x5080C, 0x3000000, { 0x2000000 }, 0, 0 }, /* Phy offset 0x3 - TX Channel control 0 */
{ USB_REG_UNIT, 0x50800, 0x1FF007F, { 0x600005 }, 0, 0 }, /* Phy offset 0x0 - PLL_CONTROL0 */
{ USB_REG_UNIT, 0x5080C, 0x000F000, { 0x0001000 }, 0, 0 }, /* DRV_EN_LS 0x1 - TX Channel control 0 */
{ USB_REG_UNIT, 0x50814, 0x000000F, { 0x000000D }, 0, 0 }, /* SQ_THRESH 0xD - TX Channel control 0 */
{ USB_REG_UNIT, 0x5080C, 0x3000000, { 0x3000000 }, 0, 0 }, /* Phy offset 0x3 - TX Channel control 0 */
{ USB_REG_UNIT, 0x50804, 0x3, { 0x3 }, 0, 0 }, /* Phy offset 0x1 - PLL_CONTROL1 */
{ USB_REG_UNIT, 0x50808, 0x80800000, { 0x80800000 }, 1, 1000 }, /* check PLLCAL_DONE is set and IMPCAL_DONE is set*/
{ USB_REG_UNIT, 0x50818, 0x80000000, { 0x80000000 }, 1, 1000 }, /* check REG_SQCAL_DONE is set*/
{ USB_REG_UNIT, 0x50800, 0x80000000, { 0x80000000 }, 1, 1000 } /* check PLL_READY is set*/
};
/******************/
/* SGMII */
/******************/
MV_OP_EXT_PARAMS sgmiiSpeedExtConfigParams[] =
{
/* unit offset mask data wait numOf */
/* ID 1.25G Time Loops */
{ SERDES_UNIT, 0x0, 0x7F8, { 0x330 }, 0, 0 }, /* Setting PIN_GEN_TX, PIN_GEN_RX */
{ SERDES_UNIT, 0x28, 0x1F, { 0xC }, 0, 0 } /* PIN_FREF_SEL=C (156.25MHz) */
};
MV_OP_EXT_PARAMS sgmiiSpeedIntConfigParams[] =
{
/* unit offset mask data wait numOf */
/* ID 1.25G Time Loops */
{ SERDES_PHY_UNIT, 0x4, 0xFFFF, { 0xFD8C }, 0, 0 }, /* FFE_R=0x0, FFE_C=0xF, SQ_THRESH=0x2*/
{ SERDES_PHY_UNIT, 0x18, 0xFFFF, { 0x4F00 }, 0, 0 }, /* DFE_RES = 3.3mv*/
{ SERDES_PHY_UNIT, 0x1C, 0xFFFF, { 0xF047 }, 0, 0 }, /* DFE UPDAE all coefficient*/
{ SERDES_PHY_UNIT, 0x34, 0xFFFF, { 0x406C }, 0, 0 }, /* TX_AMP=31, AMP_ADJ=1*/
{ SERDES_PHY_UNIT, 0x38, 0xFFFF, { 0x1E40 }, 0, 0 }, /* MUPI/F=2, rx_digclkdiv=2*/
{ SERDES_PHY_UNIT, 0x94, 0xFFFF, { 0x1FFF }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x98, 0xFFFF, { 0x66 }, 0, 0 }, /* set password */
{ SERDES_PHY_UNIT, 0x104, 0xFFFF, { 0x2208 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x108, 0xFFFF, { 0x243F }, 0, 0 }, /* Set Gen_RX/TX */
{ SERDES_PHY_UNIT, 0x114, 0xFFFF, { 0x47EF }, 0, 0 }, /* EMPH0 enable, EMPH_mode=2 */
{ SERDES_PHY_UNIT, 0x134, 0xFFFF, { 0x004A }, 0, 0 }, /* RX_IMP_VTH=2, TX_IMP_VTH=2 */
{ SERDES_PHY_UNIT, 0x13C, 0xFBFF, { 0xE028 }, 0, 0 }, /* clock set */
{ SERDES_PHY_UNIT, 0x140, 0xFFFF, { 0x800 }, 0, 0 }, /* clk 8T enable for 10G and up */
{ SERDES_PHY_UNIT, 0x154, 0xFFFF, { 0x87 }, 0, 0 }, /* rxdigclk_dv_force=1 */
{ SERDES_PHY_UNIT, 0x168, 0xFFFF, { 0xE014 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x16C, 0xFFFF, { 0x14 }, 0, 0 }, /* DTL_FLOOP_EN=0 */
{ SERDES_PHY_UNIT, 0x184, 0xFFFF, { 0x1013 }, 0, 0 }, /* Force ICP=7 */
{ SERDES_PHY_UNIT, 0x1A8, 0xFFFF, { 0x4000 }, 0, 0 }, /* rxdigclk_dv_force=1*/
{ SERDES_PHY_UNIT, 0x1AC, 0xFFFF, { 0x8498 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x1DC, 0xFFFF, { 0x780 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x1E0, 0xFFFF, { 0x03FE }, 0, 0 }, /* PHY_MODE=0x4,FREF_SEL=0xC */
{ SERDES_PHY_UNIT, 0x214, 0xFFFF, { 0x4418 }, 0, 0 }, /* PHY_MODE=0x4,FREF_SEL=0xC */
{ SERDES_PHY_UNIT, 0x220, 0xFFFF, { 0x400 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x228, 0xFFFF, { 0x2FC0 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x268, 0xFFFF, { 0x8C02 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x278, 0xFFFF, { 0x21F3 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x280, 0xFFFF, { 0xC9F8 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x29C, 0xFFFF, { 0x05BC }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x2DC, 0xFFFF, { 0x2233 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x31C, 0xFFFF, { 0x318 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x330, 0xFFFF, { 0x010F }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x334, 0xFFFF, { 0x0C03 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x338, 0xFFFF, { 0x3C00 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x33C, 0xFFFF, { 0x3C00 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x368, 0xFFFF, { 0x1000 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x36C, 0xFFFF, { 0x0AFA }, 0, 0 },
{ SERDES_PHY_UNIT, 0x378, 0xFFFF, { 0x1800 }, 0, 0 },
{ SERDES_PHY_UNIT, 0x418, 0xFFFF, { 0xE737 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x420, 0xFFFF, { 0x9B60 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x440, 0xFFFF, { 0x003E }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x444, 0xFFFF, { 0x2681 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x468, 0xFFFF, { 0x1 }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x46C, 0xFFFF, { 0xFC7C }, 0, 0 }, /* */
{ SERDES_PHY_UNIT, 0x4A0, 0xFFFF, { 0x007C }, 0, 0 },
{ SERDES_PHY_UNIT, 0x4A4, 0xFFFF, { 0xFC7C }, 0, 0 },
{ SERDES_PHY_UNIT, 0x4A8, 0xFFFF, { 0xFC7C }, 0, 0 },
{ SERDES_PHY_UNIT, 0x4AC, 0xFFFF, { 0xFC7C }, 0, 0 },
{ SERDES_PHY_UNIT, 0x10C, 0xFFFF, { 0x838 }, 0, 0 }
};
MV_OP_EXT_PARAMS sgmiiSdResetParams[] =
{
/* unit offset mask data wait numOf */
/* ID 1.25G Time Loops */
{ SERDES_UNIT, 0x4, 0x8, { 0x0 }, 0, 0 } /* SERDES_SD_RESET_SEQ Sequence init */
};
MV_OP_EXT_PARAMS sgmiiSdUnresetParams[] =
{
/* unit offset mask data wait numOf */
/* ID 1.25G Time Loops */
{ SERDES_UNIT, 0x4, 0x8, { 0x8 }, 0, 0 } /* SERDES_SD_UNRESET_SEQ Sequence init */
};
MV_OP_EXT_PARAMS sgmiiRfResetParams[] =
{
/* unit offset mask data wait numOf */
/* ID 1.25G Time Loops */
{ SERDES_UNIT, 0x4, 0x40, { 0x0 }, 0, 0 } /* SERDES_RF_RESET Sequence init */
};
MV_OP_EXT_PARAMS sgmiiRfUnresetParams[] =
{
/* unit offset mask data wait numOf */
/* ID 1.25G Time Loops */
{ SERDES_UNIT, 0x4, 0x40, { 0x40 }, 0, 0 }, /* SERDES_RF_UNRESET Sequence init */
};
MV_OP_EXT_PARAMS sgmiiCoreResetParams[] =
{
/* unit offset mask data wait numOf */
/* ID 1.25G Time Loops */
{ SERDES_UNIT, 0x4, 0x20, { 0x0 }, 0, 0 } /* SERDES_CORE_RESET_SEQ Sequence init */
};
MV_OP_EXT_PARAMS sgmiiCoreUnresetParams[] =
{
/* unit offset mask data wait numOf */
/* ID 1.25G Time Loops */
{ SERDES_UNIT, 0x4, 0x20, { 0x20 }, 0, 0 } /* SERDES_CORE_UNRESET_SEQ Sequence init */
};
MV_OP_EXT_PARAMS sgmiiSynceResetParams[] =
{
/* unit offset mask data wait numOf */
/* ID 1.25G Time Loops */
{ SERDES_UNIT, 0x8, 0x8, { 0x0 }, 0, 0 } /* SERDES_SYNCE_RESET_SEQ Sequence init */
};
MV_OP_EXT_PARAMS sgmiiSynceUnresetParams[] =
{
/* unit offset mask data wait numOf */
/* ID 1.25G Time Loops */
{ SERDES_UNIT, 0x4, 0xFF00, { 0xDD00 }, 0, 0 }, /* SERDES_SYNCE_UNRESET_SEQ Sequence init */
{ SERDES_UNIT, 0x8, 0xB, { 0xB }, 0, 0 } /* SERDES_SYNCE_UNRESET_SEQ Sequence init */
};
MV_OP_EXT_PARAMS sgmiiPowerUpCtrlParams[] =
{
/* unit offset mask data wait numOf */
/* ID 1.25G Time Loops */
{ SERDES_UNIT, 0x0, 0x1802, { 0x1802 }, 0, 0 },
{ SERDES_UNIT, 0x8, 0x10, { 0x10 }, 0, 0 },
{ SERDES_PHY_UNIT, 0x8, 0x8000, { 0x8000 }, 0, 0 },
{ SERDES_PHY_UNIT, 0x8, 0x4000, { 0x4000 }, 10, 10},
{ SERDES_PHY_UNIT, 0x8, 0x8000, { 0x0 }, 0, 0 },
{ 0, 0, 0, { 0 }, 6, 0 }
};
MV_OP_EXT_PARAMS sgmiiPowerDownCtrlParams[] =
{
/* unit offset mask data wait numOf */
/* ID 1.25G Time Loops */
{ SERDES_UNIT, 0x0, 0x1802, { 0x0 }, 0, 0 },
{ SERDES_UNIT, 0x4, 0x4000, { 0x0 }, 0, 0 }
};
/**************************************************************************************/
/*********************************** Enums ************************************/
/************************* Local functions declarations ***********************/
MV_STATUS boardTopologyLoad(SERDES_MAP *serdesMapArray);
/*************************** Functions implementation *************************/
/*********************************************************************************************
mvHwsIndirectRegRead
*
* DESCRIPTION: Indirect readfrom COMPHY_M_PIPE_R2P3_28HPM_REG_MIDAS_INTERNAL_PCIE001
* registers via PEX_PHY_INDIRECT_ACC_REG
* INPUT: devNum - device number
* regAddr - register address
* dataValue - pointer to read data
*
* OUTPUT: None.
* RETURNS: MV_OK - for success
* MV_FAIL - for failure
***************************************************************************/
MV_U32 mvHwsIndirectRegRead
(
MV_U32 devNum,
MV_U32 regAddr,
MV_U32 *dataValue
)
{
MV_U32 data;
data = (1 << PHY_ACCESS_MODE_OFFSET) + (regAddr << PHY_ADDRESS_OFFSET) ;
MV_REG_WRITE(PEX_PHY_INDIRECT_ACC_REG,data);
*dataValue = MV_REG_READ (PEX_PHY_INDIRECT_ACC_REG);
return MV_OK;
}
/*********************************************************************************************
mvHwsIndirectRegWrite
*
* DESCRIPTION: Indirect write to COMPHY_M_PIPE_R2P3_28HPM_REG_MIDAS_INTERNAL_PCIE001
* registers via PEX_PHY_INDIRECT_ACC_REG
* INPUT: devNum - device number
* regAddr - register address
* dataValue - data to write
* mask - mask
* OUTPUT: None.
* RETURNS: MV_OK - for success
* MV_FAIL - for failure
***************************************************************************/
MV_U32 mvHwsIndirectRegWrite
(
MV_U32 devNum,
MV_U32 regAddr,
MV_U32 dataValue,
MV_U32 mask
)
{
MV_U32 readData,data;
mvHwsIndirectRegRead (devNum,regAddr,&readData);
dataValue = ((readData & (~mask)) | (dataValue & mask)) & 0xFFFF;
data = (0 << PHY_ACCESS_MODE_OFFSET) + (regAddr << PHY_ADDRESS_OFFSET) + dataValue;
MV_REG_WRITE(PEX_PHY_INDIRECT_ACC_REG,data);
return MV_OK;
}
/**************************************************************************
* mvHwsSerdesLastLaneGet -
*
* DESCRIPTION: return last lane number.
* INPUT: NONE.
* OUTPUT: None.
* RETURNS: number of lanes
***************************************************************************/
MV_U32 mvHwsSerdesLastLaneGet(MV_VOID)
{
return LAST_LANE_NUM;
}
/**************************************************************************
* boardTopologyLoad -
*
* DESCRIPTION: Loads the board topology for the DB_A38X_BP board
* INPUT: serdesMapArray - The struct that will contain
* the board topology map
* OUTPUT: The board topology map.
* RETURNS: MV_OK - for success
* MV_FAIL - for failure (a wrong
* topology mode was read
* from the board)
***************************************************************************/
MV_STATUS boardTopologyLoad(SERDES_MAP *serdesMapArray)
{
MV_U32 laneNum;
MV_U32 boardIdIndex;
SERDES_MAP *topologyConfigPtr;
DEBUG_INIT_FULL_S("\n### loadTopologyDB ###\n");
boardIdIndex = mvBoardIdIndexGet(mvBoardIdGet());
topologyConfigPtr = mvHwsSerdesTopologyGet(boardIdIndex);
if (topologyConfigPtr == NULL)
{
return MV_NOT_SUPPORTED;
}
/* Updating the topology map */
for (laneNum = 0; laneNum < MAX_SERDES_LANES; laneNum++) {
serdesMapArray[laneNum].serdesMode = topologyConfigPtr[laneNum].serdesMode;
serdesMapArray[laneNum].serdesNum = topologyConfigPtr[laneNum].serdesNum;
serdesMapArray[laneNum].serdesSpeed = topologyConfigPtr[laneNum].serdesSpeed;
serdesMapArray[laneNum].serdesType = topologyConfigPtr[laneNum].serdesType;
serdesMapArray[laneNum].swapRx = topologyConfigPtr[laneNum].swapRx;
serdesMapArray[laneNum].swapTx = topologyConfigPtr[laneNum].swapTx;
}
return MV_OK;
}
#if defined MV_MSYS_AC3
/*AC3: check S@R for PCIe mode (EP/RC) ****************************************/
MV_BOOL mvCtrlIsPexEndPointMode(MV_VOID)
{
MV_U32 uiReg = 0;
/*Read AC3 SatR configuration SAR0[14]*/
CHECK_STATUS(mvGenUnitRegisterGet(SERVER_REG_UNIT, 0, REG_DEVICE_SAR0_ADDR, &uiReg, BIT14));
return (uiReg == 0);
}
/* AC3: Get the Serdes revision number **************************************/
MV_U8 mvHwsSerdesRevGet(MV_VOID)
{
return MV_SERDES_28NM_REV_3;
}
/* AC3: init silicon related configurations *********************************/
MV_STATUS mvSiliconInit(MV_VOID)
{
MV_TWSI_ADDR slave;
MV_U32 tClock;
/* Prepare data to be used by access functions for various SOC regions */
mvUnitInfoSet(INTERNAL_REG_UNIT, INTER_REGS_BASE, MV_INTERNAL_OFFSET);
mvUnitInfoSet(MG_UNIT, 0, MV_INTERNAL_OFFSET);
mvUnitInfoSet(SERDES_UNIT, MV_SERDES_BASE, MV_SERDES_OFFSET);
mvUnitInfoSet(SERDES_PHY_UNIT, MV_SERDES_PHY_BASE, MV_SERDES_OFFSET);
mvUnitInfoSet(USB_REG_UNIT, MV_REG_READ(AHB_TO_MBUS_WIN_BASE_REG(USB_WIN_ID)) & 0xFFFF0000, 0);
mvUnitInfoSet(SERVER_REG_UNIT, MV_REG_READ(AHB_TO_MBUS_WIN_BASE_REG(SERVER_WIN_ID)) & 0xFFFF0000, 0);
/* Set legacy mode address completion */
mvGenUnitRegisterSet(MG_UNIT, 0, 0x140, (1 << 16), (1 << 16));
/* TWSI init */
DEBUG_INIT_FULL_S("mvSiliconInit: Init TWSI interface.\n");
slave.type = ADDR7_BIT;
slave.address = 0;
tClock = mvBoardTclkGet();
if (tClock == MV_BOARD_TCLK_ERROR) {
DEBUG_INIT_FULL_S("mvSiliconInit: TClk read from the board is not supported\n");
return MV_NOT_SUPPORTED;
}
mvTwsiInit(0, TWSI_SPEED, tClock, &slave, 0);
return MV_OK;
}
/****************************************************************************/
/* AC3: set PCIe Comphy register optimizations after ETP */
MV_VOID mvCtrlPexImpedanceCalibration(MV_VOID)
{
MV_U32 uiReg = 0;
/* MAC soft reset */
/* Reg 0x41a60, Deassert soft_reset[20] to 0x0*/
uiReg = MV_REG_READ(PEX_DBG_CTRL_REG(0));
uiReg &= ~(0x1 << 20);
MV_REG_WRITE(PEX_DBG_CTRL_REG(0), uiReg);
/*Pipe reset */
mvHwsIndirectRegWrite (0,GLOB_CLK_CTRL,0x1,0x1);
/*Pex Tx and RX impedance adjust and recalibrate */
mvHwsIndirectRegWrite (0,VTHIMPCAL_CTRL_REG,(TX_AND_RX_IMPEDANCE_THRESHIOLD << IMPEDANCE_THRESHIOLD_OFFSET),(0xFF <<IMPEDANCE_THRESHIOLD_OFFSET)); /* set threshold */
mvHwsIndirectRegWrite (0,CAL_REG3,(0x1 << RX_CALIBRATION_OFFSET),(0x1 <<RX_CALIBRATION_OFFSET)); /* calibrate Rx */
mvHwsIndirectRegWrite (0,CAL_REG3,(0x0 << RX_CALIBRATION_OFFSET),(0x1 <<RX_CALIBRATION_OFFSET));
mvOsDelay(5);
mvHwsIndirectRegWrite (0,CAL_REG3,(0x1 << TX_CALIBRATION_OFFSET),(0x1 <<TX_CALIBRATION_OFFSET));/* calibrate Tx */
mvHwsIndirectRegWrite (0,CAL_REG3,(0x0 << TX_CALIBRATION_OFFSET),(0x1 <<TX_CALIBRATION_OFFSET));
/*Pex slew rate control disable */
mvHwsIndirectRegWrite (0,G2_SETTING_0,(0x0 << TX_SLEW_CNTRL_ENABLE_OFFSET),(0x1 << TX_SLEW_CNTRL_ENABLE_OFFSET));
}
/****************************************************************************/
/* AC3: set PCIe mode as End Point */
MV_STATUS mvCtrlPexEndPointConfig(MV_VOID)
{
MV_U32 uiReg = 0;
/* Reg 0x41a00, Set ConfRoot_Complex to 0x0 to define end point mode*/
uiReg = MV_REG_READ(PEX_CTRL_REG(0));
uiReg &= ~(0x1 << CONF_ROOT_COMPLEX_OFFSET);
MV_REG_WRITE(PEX_CTRL_REG(0), uiReg);
mvCtrlPexImpedanceCalibration();
/* unreset - set bit 0 to 0 in GLOB_CLK_CTR */
mvHwsIndirectRegWrite (0,GLOB_CLK_CTRL,0x0,0x1);
return MV_OK;
}
/****************************************************************************/
/* AC3: set PCIe mode as Root Complex */
MV_STATUS mvCtrlPexRootComplexConfig(MV_VOID)
{
MV_U32 uiReg = 0;
/* Reg 0x18204, Set PCIe0nEn[0] to 0x0*/
uiReg = MV_REG_READ(SOC_CTRL_REG);
uiReg &= ~(0x1 << 0);
uiReg |= (0x0 << 0);
MV_REG_WRITE(SOC_CTRL_REG, uiReg);
/* Reg 0x41a00, Set ConfRoot_Complex to 0x1 to define Root Complex mode*/
uiReg = MV_REG_READ(PEX_CTRL_REG(0));
uiReg &= ~(0x1 << CONF_ROOT_COMPLEX_OFFSET);
uiReg |= (0x1 << CONF_ROOT_COMPLEX_OFFSET);
MV_REG_WRITE(PEX_CTRL_REG(0), uiReg);
mvCtrlPexImpedanceCalibration();
/* Reg 0x40060, Set DevType[23:20] to 0x4(Root Complex)*/
uiReg = MV_REG_READ(PEX_CAPABILITIES_REG(0));
uiReg &= ~(0xF << 20);
uiReg |= (0x4 << 20);
MV_REG_WRITE(PEX_CAPABILITIES_REG(0), uiReg);
/* unreset - set bit 0 to 0 in GLOB_CLK_CTR */
mvHwsIndirectRegWrite (0,GLOB_CLK_CTRL,0x0,0x1);
/* Reg 0x41a60, Assert soft_reset[20] to 0x1,
Set DisLinkRestartRegRst[19] to 0x1,
Set ConfMskLnkRestart[16] to 0x1*/
uiReg = MV_REG_READ(PEX_DBG_CTRL_REG(0));
uiReg &= 0xFFE6FFFF;
uiReg |= 190000;
MV_REG_WRITE(PEX_DBG_CTRL_REG(0), uiReg);
/* Reg 0x41a00, Set ConfRoot_Complex to 0x1*/
uiReg = MV_REG_READ(PEX_CTRL_REG(0));
uiReg &= ~(0x1 << CONF_ROOT_COMPLEX_OFFSET);
uiReg |= (0x1 << CONF_ROOT_COMPLEX_OFFSET);
MV_REG_WRITE(PEX_CTRL_REG(0), uiReg);
/* Reg 0x41a60, Deassert soft_reset[20] to 0x0*/
uiReg = MV_REG_READ(PEX_DBG_CTRL_REG(0));
uiReg &= ~(0x1 << 20);
MV_REG_WRITE(PEX_DBG_CTRL_REG(0), uiReg);
/* Reg 0x18204, Set PCIe0nEn[0] to 0x1*/
uiReg = MV_REG_READ(SOC_CTRL_REG);
uiReg &= ~(0x1 << 0);
uiReg |= (0x1 << 0);
MV_REG_WRITE(SOC_CTRL_REG, uiReg);
return mvHwsPexConfig();
}
/*AC3: initialize USB2.0 UTMI PHY**********************************************/
MV_STATUS mvCtrlUsb2Config(MV_VOID)
{
/* USB2 configuration */
DEBUG_INIT_FULL_S("init USB2 PHYs\n");
CHECK_STATUS(mvSeqExecExt(0 /* not relevant */, USB2_POWER_UP_SEQ));
return MV_OK;
}
MV_STATUS mvHwsComH28nmSerdesTxIfSelect(MV_U32 serdesNum)
{
MV_U8 serdesTxIfNum = (serdesNum == 10) ? 3 : 1; /* OOB port MSYS0/MSYS1 */
/* Configure TX SERDES interface number */
CHECK_STATUS(mvGenUnitRegisterSet(SERDES_UNIT, serdesNum, 0xC, serdesTxIfNum, 0x7));
return MV_OK;
}
/*AC3: Set Ref Clock**********************************************/
MV_STATUS mvHwsRefClockGet (MV_U32 serdesNum ,MV_U8 *refClockSource)
{
*refClockSource = PRIMARY; /* in AC3 all serdes has to use the same reference clock = PRIMARY */
return MV_OK;
}
/* Reference clock source */
#elif defined MV_MSYS_BC2
/* BC2: init silicon related configurations *********************************/
MV_STATUS mvSiliconInit(MV_VOID)
{
MV_TWSI_ADDR slave;
MV_U32 tClock;
/* Prepare data to be used by access functions for various SOC regions */
mvUnitInfoSet(INTERNAL_REG_UNIT, INTER_REGS_BASE, MV_INTERNAL_OFFSET);
mvUnitInfoSet(MG_UNIT, 0, MV_INTERNAL_OFFSET);
mvUnitInfoSet(SERDES_UNIT, MV_SERDES_BASE, MV_SERDES_OFFSET);
mvUnitInfoSet(SERDES_PHY_UNIT, MV_SERDES_PHY_BASE, MV_SERDES_OFFSET);
mvUnitInfoSet(SERVER_REG_UNIT, MV_REG_READ(AHB_TO_MBUS_WIN_BASE_REG(SERVER_WIN_ID)) & 0xFFFF0000, 0);
/* Set legacy mode address completion */
mvGenUnitRegisterSet(MG_UNIT, 0, 0x140, (1 << 16), (1 << 16));
/*(errata : 4410555):
BC2 specific register Device Control 0 (0x000F8250) Bit 4 should be 0
before serdes power up */
mvGenUnitRegisterSet(SERVER_REG_UNIT,0,REG_DEVICE_SERVER_CONTROL_0,(0 << 4),(1 << 4));
/* initialize TWSI interface */
DEBUG_INIT_FULL_S("mvSiliconInit: Init TWSI interface.\n");
slave.type = ADDR7_BIT;
slave.address = 0;
tClock = mvBoardTclkGet();
if (tClock == MV_BOARD_TCLK_ERROR) {
DEBUG_INIT_FULL_S("mvSiliconInit: TClk read from the board is not supported\n");
return MV_NOT_SUPPORTED;
}
mvTwsiInit(0, TWSI_SPEED, tClock, &slave, 0);
return MV_OK;
}
/****************************************************************************/
/* BC2: set PCIe mode as End Point */
MV_STATUS mvCtrlPexEndPointConfig(MV_VOID)
{
MV_U32 uiReg = 0;
/*Do End Point pex config*/
uiReg = MV_REG_READ(PEX_CAPABILITIES_REG(0));
uiReg &= ~(0xF << 20);
uiReg |= (0x1 << 20);
MV_REG_WRITE(PEX_CAPABILITIES_REG(0), uiReg);
MV_REG_WRITE(0x41a60, 0xF63F0C0);
mvPrintf("EP detected.\n");
return MV_OK;
}
/****************************************************************************/
/* BC2: set PCIe mode as Root Complex */
MV_STATUS mvCtrlPexRootComplexConfig(MV_VOID)
{
MV_U32 uiReg = 0;
/*Do Root Complex pex config*/
uiReg = MV_REG_READ(PEX_CAPABILITIES_REG(0));
uiReg &= ~(0xF << 20);
uiReg |= (0x4 << 20);
MV_REG_WRITE(PEX_CAPABILITIES_REG(0), uiReg);
mvPrintf("RC detected.\n");
return mvHwsPexConfig();
}
/*BC2: check S@R for PCIe mode (EP/RC) ****************************************/
MV_BOOL mvCtrlIsPexEndPointMode(MV_VOID)
{
MV_U32 uiReg = 0;
/*Read BC2 SatR configuration SAR0[16]*/
CHECK_STATUS(mvGenUnitRegisterGet(SERVER_REG_UNIT, 0, REG_DEVICE_SAR1_ADDR, &uiReg, BIT16));
/* check BIT16 for PCIe mode status: 0 = EP , 1 = RC */
return (uiReg == 0);
}
/* BC2: Get the Serdes revision number **************************************/
MV_U8 mvHwsSerdesRevGet(MV_VOID)
{
return (mvSysEnvDeviceRevGet() == MV_MSYS_BC2_A0_ID) ? MV_SERDES_28NM_REV_1 : MV_SERDES_28NM_REV_3;
}
/*BC2: initialize USB2.0 UTMI PHY**********************************************/
MV_STATUS mvCtrlUsb2Config(MV_VOID)
{
/* no USB2 in BC2 */
return MV_OK;
}
MV_STATUS mvHwsComH28nmSerdesTxIfSelect(MV_U32 serdesNum)
{
MV_U32 msys2sdShift = ((serdesNum == 20) || (serdesNum == 0)) ? 14 : 13; /* serdes 0 and 20 are connected by bit 14
and serdes 1 and 21 by bit 13 of REG_DEVICE_SERVER_CONTROL_14 */
/* set RF_QSGMII_PORT_TO_CPU_EN bit in DFX */
CHECK_STATUS(mvGenUnitRegisterSet(SERVER_REG_UNIT, 0, REG_DEVICE_SERVER_CONTROL_14, 1 << msys2sdShift , 1 << msys2sdShift));
/* Configure TX SERDES interface number - for BC2 - always 1*/
CHECK_STATUS(mvGenUnitRegisterSet(SERDES_UNIT, serdesNum, 0xC, 1, 0x7));
return MV_OK;
}
MV_STATUS mvHwsRefClockGet (MV_U32 serdesNum ,MV_U8 *refClockSource)
{
*refClockSource = (serdesNum >= 20) ? SECONDARY : PRIMARY;
/* in BC2 2 reference clocks: SECONDARY and PRIMARY
serdeses 20 and 21 has to use SECONDARY others -primary */
return MV_OK;
}
#endif
/* Init serdes sequences DB ********************************************/
MV_VOID mvSerdesSeqInit(MV_VOID)
{
DEBUG_INIT_FULL_S("\n### serdesSeqInit ###\n");
/* SATA_ONLY_POWER_UP_SEQ sequence init */
serdesSeqDb[USB2_POWER_UP_SEQ].opParamsPtr = usb2PowerUpParams;
serdesSeqDb[USB2_POWER_UP_SEQ].cfgSeqSize = sizeof(usb2PowerUpParams) / sizeof(MV_OP_EXT_PARAMS);
serdesSeqDb[USB2_POWER_UP_SEQ].dataArrIdx = 0; /* Only USB2 uses these configurations */
/* SGMII_INT_SPEED_CONFIG_SEQ sequence init */
serdesSeqDb[SGMII_INT_SPEED_CONFIG_SEQ].opParamsPtr = sgmiiSpeedIntConfigParams;
serdesSeqDb[SGMII_INT_SPEED_CONFIG_SEQ].cfgSeqSize = sizeof(sgmiiSpeedIntConfigParams) / sizeof(MV_OP_EXT_PARAMS);
serdesSeqDb[SGMII_INT_SPEED_CONFIG_SEQ].dataArrIdx = 0 /* speed */;
/* SGMII_EXT_SPEED_CONFIG_SEQ sequence init */
serdesSeqDb[SGMII_EXT_SPEED_CONFIG_SEQ].opParamsPtr = sgmiiSpeedExtConfigParams;
serdesSeqDb[SGMII_EXT_SPEED_CONFIG_SEQ].cfgSeqSize = sizeof(sgmiiSpeedExtConfigParams) / sizeof(MV_OP_EXT_PARAMS);
serdesSeqDb[SGMII_EXT_SPEED_CONFIG_SEQ].dataArrIdx = 0 /* speed */;
/* SGMII_SD_RESET_SEQ sequence init */
serdesSeqDb[SGMII_SD_RESET_SEQ].opParamsPtr = sgmiiSdResetParams;
serdesSeqDb[SGMII_SD_RESET_SEQ].cfgSeqSize = sizeof(sgmiiSdResetParams) / sizeof(MV_OP_EXT_PARAMS);
serdesSeqDb[SGMII_SD_RESET_SEQ].dataArrIdx = 0;
/* SGMII_SD_UNRESET_SEQ sequence init */
serdesSeqDb[SGMII_SD_UNRESET_SEQ].opParamsPtr = sgmiiSdUnresetParams;
serdesSeqDb[SGMII_SD_UNRESET_SEQ].cfgSeqSize = sizeof(sgmiiSdUnresetParams) / sizeof(MV_OP_EXT_PARAMS);
serdesSeqDb[SGMII_SD_UNRESET_SEQ].dataArrIdx = 0;
/* SGMII_RF_RESET_SEQ sequence init */
serdesSeqDb[SGMII_RF_RESET_SEQ].opParamsPtr = sgmiiRfResetParams;
serdesSeqDb[SGMII_RF_RESET_SEQ].cfgSeqSize = sizeof(sgmiiRfResetParams) / sizeof(MV_OP_EXT_PARAMS);
serdesSeqDb[SGMII_RF_RESET_SEQ].dataArrIdx = 0;
/* SGMII_RF_UNRESET_SEQ sequence init */
serdesSeqDb[SGMII_RF_UNRESET_SEQ].opParamsPtr = sgmiiRfUnresetParams;
serdesSeqDb[SGMII_RF_UNRESET_SEQ].cfgSeqSize = sizeof(sgmiiRfUnresetParams) / sizeof(MV_OP_EXT_PARAMS);
serdesSeqDb[SGMII_RF_UNRESET_SEQ].dataArrIdx = 0;
/* SGMII_CORE_RESET_SEQ sequence init */
serdesSeqDb[SGMII_CORE_RESET_SEQ].opParamsPtr = sgmiiCoreResetParams;
serdesSeqDb[SGMII_CORE_RESET_SEQ].cfgSeqSize = sizeof(sgmiiCoreResetParams) / sizeof(MV_OP_EXT_PARAMS);
serdesSeqDb[SGMII_CORE_RESET_SEQ].dataArrIdx = 0;
/* SGMII_CORE_UNRESET_SEQ sequence init */
serdesSeqDb[SGMII_CORE_UNRESET_SEQ].opParamsPtr = sgmiiCoreUnresetParams;
serdesSeqDb[SGMII_CORE_UNRESET_SEQ].cfgSeqSize = sizeof(sgmiiCoreUnresetParams) / sizeof(MV_OP_EXT_PARAMS);
serdesSeqDb[SGMII_CORE_UNRESET_SEQ].dataArrIdx = 0;
/* SGMII_SYNCE_RESET_SEQ sequence init */
serdesSeqDb[SGMII_SYNCE_RESET_SEQ].opParamsPtr = sgmiiSynceResetParams;
serdesSeqDb[SGMII_SYNCE_RESET_SEQ].cfgSeqSize = sizeof(sgmiiSynceResetParams) / sizeof(MV_OP_EXT_PARAMS);
serdesSeqDb[SGMII_SYNCE_RESET_SEQ].dataArrIdx = 0;
/* SGMII_SYNCE_UNRESET_SEQ sequence init */
serdesSeqDb[SGMII_SYNCE_UNRESET_SEQ].opParamsPtr = sgmiiSynceUnresetParams;
serdesSeqDb[SGMII_SYNCE_UNRESET_SEQ].cfgSeqSize = sizeof(sgmiiSynceUnresetParams) / sizeof(MV_OP_EXT_PARAMS);
serdesSeqDb[SGMII_SYNCE_UNRESET_SEQ].dataArrIdx = 0;
/* SGMII_POWER_UP_SEQ sequence init */
serdesSeqDb[SGMII_POWER_UP_SEQ].opParamsPtr = sgmiiPowerUpCtrlParams;
serdesSeqDb[SGMII_POWER_UP_SEQ].cfgSeqSize = sizeof(sgmiiPowerUpCtrlParams) / sizeof(MV_OP_EXT_PARAMS);
serdesSeqDb[SGMII_POWER_UP_SEQ].dataArrIdx = 0;
/* SGMII_POWER_DOWN_SEQ sequence init */
serdesSeqDb[SGMII_POWER_DOWN_SEQ].opParamsPtr = sgmiiPowerDownCtrlParams;
serdesSeqDb[SGMII_POWER_DOWN_SEQ].cfgSeqSize = sizeof(sgmiiPowerDownCtrlParams) / sizeof(MV_OP_EXT_PARAMS);
serdesSeqDb[SGMII_POWER_DOWN_SEQ].dataArrIdx = 0;
}
/****************************************************************************/
MV_STATUS mvSerdesReset(
MV_U32 serdesNum,
MV_BOOL analogReset,
MV_BOOL digitalReset,
MV_BOOL syncEReset)
{
MV_U8 seqId;
seqId = (analogReset == MV_TRUE) ? SGMII_SD_RESET_SEQ : SGMII_SD_UNRESET_SEQ;
CHECK_STATUS(mvSeqExecExt(serdesNum, seqId));
seqId = (digitalReset == MV_TRUE) ? SGMII_RF_RESET_SEQ : SGMII_RF_UNRESET_SEQ;
CHECK_STATUS(mvSeqExecExt(serdesNum, seqId));
seqId = (syncEReset == MV_TRUE) ? SGMII_SYNCE_RESET_SEQ : SGMII_SYNCE_UNRESET_SEQ;
CHECK_STATUS(mvSeqExecExt(serdesNum, seqId));
return MV_OK;
}
/****************************************************************************/
MV_STATUS mvSerdesCoreReset(MV_U32 serdesNum, MV_BOOL coreReset)
{
MV_U8 seqId;
/* Init serdes sequences DB */
seqId = (coreReset == MV_TRUE) ? SGMII_CORE_RESET_SEQ : SGMII_CORE_UNRESET_SEQ;
CHECK_STATUS(mvSeqExecExt(serdesNum, seqId));
return MV_OK;
}
/****************************************************************************/
MV_STATUS mvHwsComH28nmSerdesPolaritySwap(MV_U32 serdesNum, MV_BOOL isRx, MV_BOOL doSwap)
{
/* bit[10] swaps TX polarity, bit[11] - RX polarity */
MV_U16 polarityBit = (isRx == MV_TRUE) ? (1 << 11) : (1 << 10);
MV_U16 data = (doSwap == MV_TRUE) ? polarityBit : 0;
CHECK_STATUS(mvGenUnitRegisterSet(SERDES_PHY_UNIT, serdesNum, 0x90, data, polarityBit));
return MV_OK;
}
/****************************************************************************/
MV_STATUS mvHwsComH28nmSerdesPowerCtrl
(
MV_U32 serdesNum,
MV_BOOL powerUp
)
{
MV_U32 regData;
MV_U8 refClockSource;
if (mvHwsSerdesRevGet() == MV_SERDES_28NM_REV_1) {
/* in BC2-A0 there is no MSYS Serdes support */
return MV_OK;
}
if (powerUp == MV_TRUE) {
DEBUG_INIT_FULL_S("mvSerdesPowerUpCtrl: executing power up.. ");
/* config media */
regData = 0; /* (media == RXAUI_MEDIA) ? (1 << 15) : 0; */
/* config 10BIT mode */
regData += (1 << 14); /* (mode == _10BIT_ON) ? (1 << 14) : 0; */
CHECK_STATUS(mvGenUnitRegisterSet(SERDES_UNIT, serdesNum, 0, regData, (3 << 14)));
/* Serdes Analog Un Reset*/
CHECK_STATUS(mvSerdesReset(serdesNum, MV_FALSE, MV_TRUE, MV_TRUE));
CHECK_STATUS(mvSerdesCoreReset(serdesNum, MV_FALSE));
/* Reference clock source */
CHECK_STATUS(mvHwsRefClockGet (serdesNum,&refClockSource));
CHECK_STATUS(mvGenUnitRegisterSet(SERDES_PHY_UNIT, serdesNum, 0x13C, (refClockSource << 10), (1 << 10)));
/* Serdes speed */
CHECK_STATUS(mvSeqExecExt(serdesNum, SGMII_EXT_SPEED_CONFIG_SEQ));
CHECK_STATUS(mvSeqExecExt(serdesNum, SGMII_INT_SPEED_CONFIG_SEQ));
/* Serdes Power up Ctrl */
CHECK_STATUS(mvSeqExecExt(serdesNum, SGMII_POWER_UP_SEQ));
/* VDD calibration start (pulse) */
regData = (1 << 2);
CHECK_STATUS(mvGenUnitRegisterSet(SERDES_PHY_UNIT, serdesNum, 0x15C, regData, (1 << 2)));
mvOsDelay(1);
/* VDD calibration end (pulse) */
regData = 0;
CHECK_STATUS(mvGenUnitRegisterSet(SERDES_PHY_UNIT, serdesNum, 0x15C, regData, (1 << 2)));
/* wait 1 msec */
mvOsDelay(1);
CHECK_STATUS(mvGenUnitRegisterGet(SERDES_UNIT, serdesNum, 0x18, &regData, 0x1C));
/* Serdes Digital Un Reset */
CHECK_STATUS(mvSerdesReset(serdesNum, MV_FALSE, MV_FALSE, MV_FALSE));
CHECK_STATUS(mvSerdesCoreReset(serdesNum, MV_FALSE));
if (regData != 0x1C)
return MV_ERROR;
} else {
/*PCI-E Root Complex configuration*/
DEBUG_INIT_FULL_S("mvSerdesPowerUpCtrl: executing power down.. ");
CHECK_STATUS(mvSerdesReset(serdesNum, MV_TRUE, MV_FALSE, MV_FALSE));
CHECK_STATUS(mvSerdesCoreReset(serdesNum, MV_TRUE));
CHECK_STATUS(mvSeqExecExt(serdesNum, SGMII_POWER_DOWN_SEQ));
CHECK_STATUS(mvSerdesReset(serdesNum, MV_TRUE, MV_TRUE, MV_TRUE));
CHECK_STATUS(mvSerdesCoreReset(serdesNum, MV_TRUE));
}
return MV_OK;
}
/***************************************************************************/
MV_STATUS mvCtrlPexPolaritySet(MV_PCIE_POLARITY polarity)
{
MV_TWSI_SLAVE twsiSlave;
/* Polarity is relevant only for DB board:
* PCIe Polarity inversion is relevant only for PCIe slots.
* only AC3 DB board use PCIe with slot,
* other boards use PCIe to connect dual MSYS cpus*/
#if defined CONFIG_ALLEYCAT3
if (mvBoardIdGet() != DB_AC3_ID)
return MV_OK;
#endif
/* Initializing twsiSlave in order to read from the TWSI address */
twsiSlave.slaveAddr.address = 0x18; /* Address of AC3 CPLD */
twsiSlave.slaveAddr.type = ADDR7_BIT;
twsiSlave.validOffset = MV_TRUE;
twsiSlave.offset = 0x1A; /* Address of PEX polarity register */
twsiSlave.moreThen256 = MV_FALSE;
DEBUG_INIT_FULL_S("mvCtrlPexPolaritySet: Setting PEX polarity in CPLD\n");
if (mvTwsiWrite(0, &twsiSlave, &polarity, 1) != MV_OK)
DEBUG_INIT_S("mvCtrlPexPolaritySet: TWSI Write failed, leaving PEX polarity in EP mode\n");
return MV_OK;
}
/***************************************************************************/
MV_STATUS mvSerdesPowerUpCtrl(
MV_U32 serdesNum,
MV_BOOL serdesPowerUp,
SERDES_TYPE serdesType,
SERDES_SPEED baudRate,
SERDES_MODE serdesMode,
REF_CLOCK refClock,
MV_BOOL swapRx,
MV_BOOL swapTx
)
{
DEBUG_INIT_FULL_S("\n### mvSerdesPowerUpCtrl ###\n");
DEBUG_INIT_FULL_C("serdes num = ", serdesNum, 2);
DEBUG_INIT_FULL_C("serdes type = ", serdesType, 2);
/* Executing power up, ref clock set, speed config and TX config */
switch (serdesType) {
case SGMII0:
case SGMII1:
if (mvHwsSerdesRevGet() == MV_SERDES_28NM_REV_1) {
/* in BC2-A0 there is no MSYS Serdes support so it is skipped */
return MV_OK;
}
DEBUG_INIT_FULL_C("== Init SGMII\n", (serdesType == SGMII0 ? 0 :1), 1);
CHECK_STATUS(mvHwsComH28nmSerdesPowerCtrl(serdesNum, serdesPowerUp));
CHECK_STATUS(mvHwsComH28nmSerdesPolaritySwap(serdesNum, MV_TRUE, swapRx));
CHECK_STATUS(mvHwsComH28nmSerdesPolaritySwap(serdesNum, MV_FALSE, swapTx));
return mvHwsComH28nmSerdesTxIfSelect(serdesNum);
case PEX0:
DEBUG_INIT_FULL_S("== Init PEX0\n");
if(mvCtrlIsPexEndPointMode() == MV_TRUE) {
CHECK_STATUS(mvCtrlPexPolaritySet(MV_PCIE_POLARITY_EP));
return mvCtrlPexEndPointConfig(); /*PCI-E End Point configuration*/
} else {
CHECK_STATUS(mvCtrlPexPolaritySet(MV_PCIE_POLARITY_RC));
return mvCtrlPexRootComplexConfig(); /*PCI-E Root Complex configuration*/
}
default:
DEBUG_INIT_S("mvSerdesPowerUpCtrl: bad serdesType parameter\n");
return MV_BAD_PARAM;
}
DEBUG_INIT_FULL_C("mvSerdesPowerUpCtrl ended successfully for serdes ", serdesNum, 2);
return MV_OK;
}
/***************************************************************************/
MV_STATUS powerUpSerdesLanes(SERDES_MAP *serdesConfigMap)
{
MV_U32 serdesId;
MV_U32 serdesNum;
REF_CLOCK refClock;
SERDES_TYPE serdesType;
SERDES_SPEED serdesSpeed;
SERDES_MODE serdesMode;
MV_BOOL swapRx;
MV_BOOL swapTx;
DEBUG_INIT_FULL_S("\n### powerUpSerdesLanes ###\n");
/* per Serdes Power Up */
for (serdesId = 0; serdesId < MAX_SERDES_LANES; serdesId++) {
DEBUG_INIT_FULL_S("calling serdesPowerUpCtrl: serdes lane number ");
DEBUG_INIT_FULL_D_10(serdesId, 1);
DEBUG_INIT_FULL_S("\n");
serdesType = serdesConfigMap[serdesId].serdesType;
serdesNum = serdesConfigMap[serdesId].serdesNum;
serdesSpeed = serdesConfigMap[serdesId].serdesSpeed;
serdesMode = serdesConfigMap[serdesId].serdesMode;
swapRx = serdesConfigMap[serdesId].swapRx;
swapTx = serdesConfigMap[serdesId].swapTx;
/* serdes lane is not in use */
if (serdesType == DEFAULT_SERDES)
continue;
/* TBD - do we need to configure ref clock*/
refClock = serdesTypeToRefClockMap[serdesType];
if (refClock == REF_CLOCK_UNSUPPORTED) {
DEBUG_INIT_S("powerUpSerdesLanes: unsupported ref clock\n");
return MV_NOT_SUPPORTED;
}
CHECK_STATUS(mvSerdesPowerUpCtrl(serdesNum,
MV_TRUE,
serdesType,
serdesSpeed,
serdesMode,
refClock,
swapRx,
swapTx));
}
return MV_OK;
}
/****************************************************************************/
MV_STATUS mvCtrlHighSpeedSerdesPhyConfig(MV_VOID)
{
SERDES_MAP serdesConfigurationMap[MAX_SERDES_LANES];
mvPrintf("Serdes initialization - Version: 1.0.2\n");
/* init silicon related configurations */
mvSiliconInit();
/* Init serdes sequences DB */
mvSerdesSeqInit();
CHECK_STATUS(boardTopologyLoad(serdesConfigurationMap));
CHECK_STATUS(powerUpSerdesLanes(serdesConfigurationMap));
/* USB2 configuration */
mvCtrlUsb2Config();
DEBUG_INIT_FULL_S("### powerUpSerdesLanes ended successfully ###\n");
return MV_OK;
}