blob: 88fe281a6c7c187100cf32d2bcb85eb97d5802b5 [file] [log] [blame]
/*******************************************************************************
* Copyright 2001, Marvell International Ltd.
* This code contains confidential information of Marvell semiconductor, inc.
* no rights are granted herein under any patent, mask work right or copyright
* of Marvell or any third party.
* Marvell reserves the right at its sole discretion to request that this code
* be immediately returned to Marvell. This code is provided "as is".
* Marvell makes no warranties, express, implied or otherwise, regarding its
* accuracy, completeness or performance.
********************************************************************************
* mvHwsDdr3TrainingStatic.c
*
* DESCRIPTION: DDR3 static leveling
*
*
* DEPENDENCIES:
*
* FILE REVISION NUMBER:
* $Revision: 58 $
******************************************************************************/
#include "mvDdr3TrainingIpStatic.h"
#include "mvDdr3TrainingIp.h"
#include "mvDdr3TrainingIpFlow.h"
#include "mvDdr3TrainingIpPbs.h"
#include "mvDdr3TrainingIpDef.h"
#include "mvDdrTrainingIpDb.h"
#include "mvDdr3TrainingIpPrvIf.h"
#include "mvDdr3LoggingDef.h"
extern MV_HWS_TOPOLOGY_MAP *topologyMap;
extern GT_U32 clampTbl[MAX_INTERFACE_NUM];
#ifdef STATIC_ALGO_SUPPORT
/************************** definitions ******************************/
extern GT_U8 debugTrainingStatic;
extern GT_U32 firstActiveIf;
#define PARAM_NOT_CARE (0)
#define MAX_STATIC_SEQ (48)
/************************** globals ***************************************/
GT_U32 siliconDelay[HWS_MAX_DEVICE_NUM];
MV_HWS_TIP_STATIC_CONFIG_INFO staticConfig[HWS_MAX_DEVICE_NUM];
static RegData* staticInitControllerConfig[HWS_MAX_DEVICE_NUM];
/* silicon delay (used in static leveling) */
/* M silicon delay (used in static leveling) */
GT_32 s_uiMSiliconDelay = 1450;
/* EZ silicon delay (used in static leveling) */
GT_32 s_uiEZSiliconDelay = 950;
/* debug delay in write leveling */
GT_32 wlDebugDelay = 0;
/* pup register #3 for functional board */
GT_32 functionRegValue = 8;
/* pup register #3 for M/Customer board */
GT_32 s_uiMRegValue = 12;
GT_U32 silicon;
GT_U32 readReadyDelayPhaseOffset[] = { 4, 4, 4, 4, 6, 6, 6, 6 };
extern ClValuePerFreq casLatencyTable[];
extern GT_U32 targetFreq;
extern MV_HWS_TIP_CONFIG_FUNC_DB configFuncInfo[HWS_MAX_DEVICE_NUM];
extern GT_U32 isPllBeforeInit, isAdllCalibBeforeInit;
extern GT_U32 clampTbl[];
extern GT_U32 initFreq;
extern MV_HWS_TOPOLOGY_MAP *topologyMap;
/* list of allowed frequency listed in order of MV_HWS_DDR_FREQ */
extern GT_U32 freqVal[];
/**************************** internal function header ************************/
GT_STATUS ddr3TipStaticRoundTripArrBuild
(
GT_U32 devNum,
TripDelayElement *tablePtr,
GT_BOOL isWl,
GT_U32 *roundTripDelayArr
);
/*****************************************************************************
Register static init controller DB
******************************************************************************/
GT_STATUS ddr3TipInitSpecificRegConfig
(
GT_U32 devNum,
RegData *regConfigArr
)
{
staticInitControllerConfig[devNum] = regConfigArr;
return GT_OK;
}
/*****************************************************************************
Register static info DB
******************************************************************************/
GT_STATUS ddr3TipInitStaticConfigDb
(
GT_U32 devNum,
MV_HWS_TIP_STATIC_CONFIG_INFO* staticConfigInfo
)
{
staticConfig[devNum].boardTraceArr = staticConfigInfo->boardTraceArr;
staticConfig[devNum].packageTraceArr = staticConfigInfo->packageTraceArr;
siliconDelay[devNum] = staticConfigInfo->siliconDelay;
return GT_OK;
}
/************************** global data ******************************/
static CsElement chipSelectMap[] =
{
/* CS Value
(single only) Num_CS */
{ 0, 0},
{ 0, 1},
{ 1, 1},
{ 0, 2},
{ 2, 1},
{ 0, 2},
{ 0, 2},
{ 0, 3},
{ 3, 1},
{ 0, 2},
{ 0, 2},
{ 0, 3},
{ 0, 2},
{ 0, 3},
{ 0, 3},
{ 0, 4}
};
/*****************************************************************************
Static round trip flow - Calculates the total round trip delay.
******************************************************************************/
GT_STATUS ddr3TipStaticRoundTripArrBuild
(
GT_U32 devNum,
TripDelayElement* tablePtr,
GT_BOOL isWl,
GT_U32 *roundTripDelayArr
)
{
GT_U32 busIndex, globalBus;
GT_U32 interfaceId;
GT_U32 busPerInterface;
GT_32 sign;
GT_U32 temp;
GT_U32 boardTrace;
TripDelayElement* pkgDelayPtr;
GT_U8 octetsPerInterfaceNum = ddr3TipDevAttrGet(devNum, MV_ATTR_OCTET_PER_INTERFACE);
sign = (isWl) ? -1 : 1; /* in WL we calc the diff between Clock to DQs in RL we sum the round trip of Clock and DQs */
busPerInterface = octetsPerInterfaceNum;
for(interfaceId = 0; interfaceId <= MAX_INTERFACE_NUM-1; interfaceId++)
{
VALIDATE_IF_ACTIVE(topologyMap->interfaceActiveMask, interfaceId)
for(busIndex = 0; busIndex < busPerInterface; busIndex++)
{
VALIDATE_BUS_ACTIVE(topologyMap->activeBusMask, busIndex)
globalBus = (interfaceId * busPerInterface) + busIndex;
/* calculate total trip delay (package and board) */
boardTrace = (tablePtr[globalBus].dqsDelay * sign) + tablePtr[globalBus].ckDelay;
/* fix: multiply and than divide instead of using floating point ;*/
temp = (boardTrace*163)/1000;
/* Convert the length to delay in psec units */
pkgDelayPtr = staticConfig[devNum].packageTraceArr;
roundTripDelayArr[globalBus] = temp + (GT_32) (pkgDelayPtr[globalBus].dqsDelay * sign) + (GT_32) pkgDelayPtr[globalBus].ckDelay + (GT_32) ((isWl == GT_TRUE) ? wlDebugDelay : (GT_32) siliconDelay[devNum]);
DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, ("Round Trip Build roundTripDelayArr[0x%x]: 0x%x temp 0x%x \n", globalBus, roundTripDelayArr[globalBus], temp));
}
}
return GT_OK;
}
/*****************************************************************************
Write leveling for static flow - calculating the round trip delay of the DQS signal.
******************************************************************************/
GT_STATUS ddr3TipWriteLevelingStaticConfig
(
GT_U32 devNum,
GT_U32 interfaceId,
MV_HWS_DDR_FREQ frequency,
GT_U32 *roundTripDelayArr
)
{
GT_U32 busIndex; /* index to the bus loop */
GT_U32 busStartIndex;
GT_U32 busPerInterface;
GT_U32 phase = 0;
GT_U32 adll = 0, adll_cen, adll_inv, adll_final;
GT_U32 adllPeriod = MEGA / freqVal[frequency] / 64;
GT_U8 octetsPerInterfaceNum = ddr3TipDevAttrGet(devNum, MV_ATTR_OCTET_PER_INTERFACE);
DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, ("ddr3TipWriteLevelingStaticConfig\n"));
DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, ("devNum 0x%x IF 0x%x freq %d (adllPeriod 0x%x)\n", devNum, interfaceId, frequency, adllPeriod));
busPerInterface = octetsPerInterfaceNum;
busStartIndex = interfaceId * busPerInterface;
for(busIndex = busStartIndex; busIndex < (busStartIndex + busPerInterface); busIndex++)
{
VALIDATE_BUS_ACTIVE(topologyMap->activeBusMask, busIndex)
phase = roundTripDelayArr[busIndex] / (32 * adllPeriod);
adll = (roundTripDelayArr[busIndex] - (phase * 32 * adllPeriod)) / adllPeriod;
adll = (adll > 31) ? 31 : adll;
adll_cen = 16 + adll;
adll_inv = adll_cen/32;
adll_final = adll_cen - (adll_inv * 32);
adll_final = (adll_final > 31) ? 31 : adll_final;
/*
cs = chipSelectMap[topologyMap->interfaceParams[interfaceId].asBusParams[busIndex % 4].csBitmask].csNum;
*/
/*cs = 0;*/ /* TBD - For NP5 Only */
DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, ("\t%d - phase 0x%x adll 0x%x\n", busIndex, phase, adll));
/* Writing to all 4 phy of Interface number, bit 0 \96 4 \96 ADLL, bit 6-8 phase*/
CHECK_STATUS(ddr3TipBusReadModifyWrite(devNum, ACCESS_TYPE_UNICAST, interfaceId, (busIndex % 4), DDR_PHY_DATA, PHY_WRITE_DELAY(cs), ((phase << 6) + (adll & 0x1F)),0x1DF));
CHECK_STATUS(mvHwsDdr3TipBUSWrite( devNum, ACCESS_TYPE_UNICAST, interfaceId, ACCESS_TYPE_UNICAST,(busIndex % 4),DDR_PHY_DATA, WRITE_CENTRALIZATION_PHY_REG, ((adll_inv & 0x1) << 5) + adll_final));
}
return GT_OK;
}
/*****************************************************************************
Read leveling for static flow
******************************************************************************/
GT_STATUS ddr3TipReadLevelingStaticConfig(GT_U32 devNum,
GT_U32 interfaceId,
MV_HWS_DDR_FREQ frequency,
GT_U32 *totalRoundTripDelayArr)
{
GT_U32 cs, data0, data1, data3 = 0;
GT_U32 busIndex; /* index to the bus loop */
GT_U32 busStartIndex;
GT_U32 phase0, phase1, maxPhase;
GT_U32 adll0, adll1;
GT_U32 clValue;
GT_U32 minDelay;
GT_U32 sdrPeriod = MEGA / freqVal[frequency];
GT_U32 ddrPeriod = MEGA / freqVal[frequency] / 2;
GT_U32 adllPeriod = MEGA / freqVal[frequency] / 64;
MV_HWS_SPEED_BIN speedBinIndex;
GT_U32 rdSampleDly[MAX_CS_NUM] = { 0 };
GT_U32 rdReadyDel[MAX_CS_NUM] = { 0 };
GT_U8 octetsPerInterfaceNum = ddr3TipDevAttrGet(devNum, MV_ATTR_OCTET_PER_INTERFACE);
DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, ("ddr3TipReadLevelingStaticConfig\n"));
DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, ("devNum 0x%x ifc 0x%x freq %d\n", devNum,interfaceId, frequency));
DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, ("SdrPeriod 0x%x DdrPeriod 0x%x adllPeriod 0x%x\n", sdrPeriod, ddrPeriod, adllPeriod));
if(topologyMap->interfaceParams[firstActiveIf].memoryFreq == frequency)
{
clValue = topologyMap->interfaceParams[firstActiveIf].casL;
DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, ("clValue 0x%x\n", clValue));
}
else
{
speedBinIndex = topologyMap->interfaceParams[interfaceId].speedBinIndex;
clValue = casLatencyTable[speedBinIndex].clVal[frequency];
DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, ("clValue 0x%x speedBinIndex %d\n", clValue, speedBinIndex));
}
busStartIndex = interfaceId * octetsPerInterfaceNum;
for(busIndex=busStartIndex; busIndex < (busStartIndex + octetsPerInterfaceNum); busIndex+=2)
{
VALIDATE_BUS_ACTIVE(topologyMap->activeBusMask, busIndex)
cs = chipSelectMap[topologyMap->interfaceParams[interfaceId].asBusParams[(busIndex % 4)].csBitmask].csNum;
/* read sample delay calculation */
minDelay = (totalRoundTripDelayArr[busIndex] < totalRoundTripDelayArr[busIndex + 1]) ? totalRoundTripDelayArr[busIndex] : totalRoundTripDelayArr[busIndex + 1];
rdSampleDly[cs] = 2 * (minDelay / (sdrPeriod*2)); /* round down */
DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, ("\t%d - minDelay 0x%x cs 0x%x rdSampleDly[cs] 0x%x\n", busIndex, minDelay, cs, rdSampleDly[cs]));
/* phase calculation */
phase0 = (totalRoundTripDelayArr[busIndex] - (sdrPeriod * rdSampleDly[cs])) / (ddrPeriod);
phase1 = (totalRoundTripDelayArr[busIndex + 1] - (sdrPeriod * rdSampleDly[cs])) / (ddrPeriod);
maxPhase = (phase0 > phase1) ? phase0 : phase1;
DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, ("\tphase0 0x%x phase1 0x%x maxPhase 0x%x\n", phase0, phase1, maxPhase));
/* ADLL calculation */
adll0 = (GT_U32)((totalRoundTripDelayArr[busIndex] - (sdrPeriod * rdSampleDly[cs]) -
(ddrPeriod * phase0)) / adllPeriod);
adll0 = (adll0 > 31) ? 31 : adll0;
adll1 = (GT_U32)((totalRoundTripDelayArr[busIndex + 1] - (sdrPeriod * rdSampleDly[cs]) -
(ddrPeriod * phase1)) / adllPeriod);
adll1 = (adll1 > 31) ? 31 : adll1;
/* The Read delay close the Read FIFO*/
rdReadyDel[cs] = rdSampleDly[cs] + readReadyDelayPhaseOffset[maxPhase];
DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, ("\tadll0 0x%x adll1 0x%x rdReadyDel[cs] 0x%x\n", adll0, adll1, rdReadyDel[cs]));
/* Write to the phy of Interface (bit 0 \96 4 \96 ADLL, bit 6-8 phase) */
data0 = ((phase0 << 6) + (adll0 & 0x1F));
data1 = ((phase1 << 6) + (adll1 & 0x1F));
CHECK_STATUS(ddr3TipBusReadModifyWrite(devNum, ACCESS_TYPE_UNICAST, interfaceId, (busIndex % 4), DDR_PHY_DATA, PHY_READ_DELAY(cs), data0,0x1DF));
CHECK_STATUS(ddr3TipBusReadModifyWrite(devNum, ACCESS_TYPE_UNICAST, interfaceId, ((busIndex + 1) % 4), DDR_PHY_DATA, PHY_READ_DELAY(cs), data1, 0x1DF));
}
for (busIndex = 0; busIndex < octetsPerInterfaceNum; busIndex++)
{
VALIDATE_BUS_ACTIVE(topologyMap->activeBusMask, busIndex)
CHECK_STATUS(ddr3TipBusReadModifyWrite( devNum, ACCESS_TYPE_UNICAST, interfaceId, busIndex, DDR_PHY_DATA, 0x3, data3, 0x1F));
}
CHECK_STATUS(mvHwsDdr3TipIFWrite(devNum, ACCESS_TYPE_UNICAST, interfaceId, READ_DATA_SAMPLE_DELAY,
(rdSampleDly[0] + clValue) + (rdSampleDly[1] << 8), MASK_ALL_BITS));
/*ReadReadyDel0 bit 0-4 , CS bits 8-12 */
CHECK_STATUS(mvHwsDdr3TipIFWrite(devNum, ACCESS_TYPE_UNICAST, interfaceId, READ_DATA_READY_DELAY,
rdReadyDel[0] + (rdReadyDel[1] << 8) + clValue , MASK_ALL_BITS));
return GT_OK;
}
/*****************************************************************************
DDR3 Static flow
******************************************************************************/
GT_STATUS ddr3TipRunStaticAlg
(
GT_U32 devNum,
MV_HWS_DDR_FREQ freq
)
{
GT_U32 interfaceId = 0;
TripDelayElement* tablePtr;
GT_U32 auiWlTotalRoundTripDelayArr[MAX_TOTAL_BUS_NUM];
GT_U32 auiRlTotalRoundTripDelayArr[MAX_TOTAL_BUS_NUM];
InitCntrParam initCntrPrm;
GT_STATUS retVal;
DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, ("ddr3TipRunStaticAlg"));
initCntrPrm.doMrsPhy = GT_TRUE;
initCntrPrm.isCtrl64Bit = GT_FALSE;
initCntrPrm.initPhy = GT_TRUE;
retVal = mvHwsDdr3TipInitController(devNum, &initCntrPrm);
if (retVal != GT_OK)
{
DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_ERROR, ("mvHwsDdr3TipInitController failure \n"));
}
/* calculate the round trip delay for Write Leveling */
tablePtr = staticConfig[devNum].boardTraceArr;
CHECK_STATUS(ddr3TipStaticRoundTripArrBuild(devNum, tablePtr, GT_TRUE, auiWlTotalRoundTripDelayArr));
/* calculate the round trip delay for Read Leveling */
CHECK_STATUS(ddr3TipStaticRoundTripArrBuild(devNum, tablePtr, GT_FALSE, auiRlTotalRoundTripDelayArr));
for(interfaceId = 0; interfaceId <= MAX_INTERFACE_NUM-1; interfaceId++)
{
/* check if the interface is enabled */
VALIDATE_IF_ACTIVE(topologyMap->interfaceActiveMask, interfaceId)
/* static frequency is defined according to init-frequency (not target) */
DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, ("Static IF %d freq %d \n", interfaceId, freq));
CHECK_STATUS(ddr3TipWriteLevelingStaticConfig(devNum, interfaceId, freq,auiWlTotalRoundTripDelayArr));
CHECK_STATUS(ddr3TipReadLevelingStaticConfig(devNum, interfaceId, freq,auiRlTotalRoundTripDelayArr));
}
return GT_OK;
}
/*****************************************************************************
Init controller for static flow
******************************************************************************/
GT_STATUS ddr3TipStaticInitController
(
GT_U32 devNum
)
{
GT_U32 indexCnt = 0;
DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, ("ddr3TipStaticInitController\n"));
while(staticInitControllerConfig[devNum][indexCnt].regAddr != 0)
{
CHECK_STATUS(mvHwsDdr3TipIFWrite(devNum,ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
staticInitControllerConfig[devNum][indexCnt].regAddr,
staticInitControllerConfig[devNum][indexCnt].regData,
staticInitControllerConfig[devNum][indexCnt].regMask));
DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, ("InitController indexCnt %d\n", indexCnt));
indexCnt++;
}
return GT_OK;
}
/*****************************************************/
GT_STATUS ddr3TipStaticPhyInitController
(
GT_U32 devNum
)
{
CHECK_STATUS(mvHwsDdr3TipBUSWrite( devNum, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, 0xA4, 0x3dfe));
CHECK_STATUS(mvHwsDdr3TipBUSWrite( devNum, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, 0xA6, 0xCB2));
CHECK_STATUS(mvHwsDdr3TipBUSWrite( devNum, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, 0xA9, 0));
CHECK_STATUS(mvHwsDdr3TipBUSWrite( devNum, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, 0xD0, 0x1F));
CHECK_STATUS(mvHwsDdr3TipBUSWrite( devNum, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, 0xA8, 0x434));
return GT_OK;
}
#endif