blob: e556ecef2cde8ce4918dcaa3675bb4ddf5c0f109 [file] [log] [blame]
/* $NoKeywords:$ */
/**
* @file
*
* PCIe early post initialization.
*
*
*
* @xrefitem bom "File Content Label" "Release Content"
* @e project: AGESA
* @e sub-project: GNB
* @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
*
*/
/*
*****************************************************************************
*
* Copyright (c) 2008 - 2012, Advanced Micro Devices, Inc.
* All rights reserved.
*
* 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 Advanced Micro Devices, Inc. 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 ADVANCED MICRO DEVICES, INC. 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.
* ***************************************************************************
*
*/
/*----------------------------------------------------------------------------------------
* M O D U L E S U S E D
*----------------------------------------------------------------------------------------
*/
#include "AGESA.h"
#include "Ids.h"
#include "amdlib.h"
#include "Gnb.h"
#include "GnbBapmCoeffCalcTN.h"
#include "GnbRegisterAccTN.h"
#include "GnbRegistersTN.h"
#include "GnbInitTN.h"
#include "Filecode.h"
#define FILECODE PROC_GNB_MODULES_GNBINITTN_GNBBAPMCOEFFCALC_FILECODE
/*----------------------------------------------------------------------------------------
* D E F I N I T I O N S A N D M A C R O S
*----------------------------------------------------------------------------------------
*/
#define GnbFpLibGetExp(V) ((INT32) ((*((UINT64*) &Value) >> 52) & 0x7FF) - (1023 + 52))
#define GnbFpLibGetMnts(V) (INT64) ((*((UINT64*) &Value) & ((1ull << 52) - 1)) | (1ull << 52))
/*----------------------------------------------------------------------------------------
* T Y P E D E F S A N D S T R U C T U R E S
*----------------------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------------------
* P R O T O T Y P E S O F L O C A L F U N C T I O N S
*----------------------------------------------------------------------------------------
*/
INT32 _fltused = 0;
/*----------------------------------------------------------------------------------------*/
/**
* Calculate power of
*
*
* @param[in] Value value
* @param[in] Pow power
* @retval Value^Pow
*/
STATIC DOUBLE
GnbBapmPowerOf (
IN DOUBLE Value,
IN UINTN Pow
)
{
DOUBLE Result;
Result = Value;
while ( --Pow > 0) {
Result *= Value;
}
return Result;
}
/*----------------------------------------------------------------------------------------*/
/**
* Decode R from fuse
*
*
* @param[in] FuseR R fused value
* @retval R
*/
STATIC DOUBLE
GnbBapmDecodeR (
IN UINT32 FuseR
)
{
DOUBLE Value;
Value = ((DOUBLE) (FuseR & 0x1ff)) / (2 << (8 - 1));
Value = GnbBapmPowerOf (Value, 4);
return ((FuseR & 0x200) != 0) ? (-1) * Value : Value;
}
/*----------------------------------------------------------------------------------------*/
/**
* Decode Tau from fuse
*
*
* @param[in] FuseTau Tau fused value
* @retval Tau
*/
STATIC DOUBLE
GnbBapmDecodeTau (
IN UINT32 FuseTau
)
{
DOUBLE Value;
Value = FuseTau;
Value = GnbBapmPowerOf (Value / (2 << (9 - 1)), 16);
return Value;
}
/*----------------------------------------------------------------------------------------*/
/**
* Calaculate X
*
*
* @param[in] Ts Samplig rate
* @param[in] Tau Tau value
* @param[in] R R value
* @retval X
*/
STATIC DOUBLE
GnbBapmCalculateX (
IN DOUBLE Ts,
IN DOUBLE Tau,
IN DOUBLE R
)
{
//X=(R*Ts)/(2*Tau+Ts);
DOUBLE Result;
Result = (R * Ts) / (2 * Tau + Ts);
return (Result * GnbBapmPowerOf (2, 36)) + 0.5;
}
/*----------------------------------------------------------------------------------------*/
/**
* Calaculate Y
*
*
* @param[in] Ts Samplig rate
* @param[in] Tau Tau value
* @retval Y
*/
STATIC DOUBLE
GnbBapmCalculateY (
IN DOUBLE Ts,
IN DOUBLE Tau
)
{
//Y=(2*Tau-Ts)/(2*Tau+Ts);
DOUBLE Result;
Result = (2 * Tau - Ts) / (2 * Tau + Ts);
return (Result * GnbBapmPowerOf (2, 32)) + 0.5;
}
/*----------------------------------------------------------------------------------------*/
/**
* Set X & Y value
*
*
* @param[in] X X value
* @param[in] Y Y value
* @param[in] AddrOffset Offset of address
* @param[in] StdHeader Standard configuration header
*/
STATIC VOID
GnbBapmSetYAndX (
IN INT32 X,
IN INT32 Y,
IN UINT32 AddrOffset,
IN AMD_CONFIG_PARAMS *StdHeader
)
{
GnbRegisterWriteTN (
D0F0xBC_x1F480_TYPE,
D0F0xBC_x1F480_ADDRESS + AddrOffset,
&X,
0,
StdHeader
);
IDS_HDT_CONSOLE (GNB_TRACE, "X: 0x%08x\n", X);
GnbRegisterWriteTN (
D0F0xBC_x1F480_TYPE,
D0F0xBC_x1F480_ADDRESS + AddrOffset + 4,
&Y,
0,
StdHeader
);
IDS_HDT_CONSOLE (GNB_TRACE, "Y: 0x%08x\n", Y);
}
/*----------------------------------------------------------------------------------------*/
/**
* Extract INt32 from DOUBLE
*
*
*
* @param[in] Value Double value
* @retval int32
*/
INT32
GnbFpLibDoubleToInt32 (
IN DOUBLE Value
)
{
INT64 Mantissa;
INT32 Exponent;
Mantissa = GnbFpLibGetMnts (Value);
Exponent = GnbFpLibGetExp (Value);
if (Exponent < -64) {
Mantissa = 0;
} else if (Exponent < 0) {
Mantissa >>= - Exponent;
} else {
Mantissa <<= Exponent;
}
return (INT32) ((Value < 0) ? - Mantissa : Mantissa);
}
/*----------------------------------------------------------------------------------------*/
/**
* Calcuate BAPM coefficient
*
*
*
* @param[in] StdHeader Standard configuration header
* @retval AGESA_STATUS
*/
VOID
GnbBapmCalculateCoeffsTN (
IN AMD_CONFIG_PARAMS *StdHeader
)
{
UINT32 RFuse1;
UINT32 TauFuse1;
UINT32 Index;
DOUBLE R;
DOUBLE Tau;
DOUBLE Ts;
INT32 X;
INT32 Y;
IDS_HDT_CONSOLE (GNB_TRACE, "GnbBapmCalculateCoeffsTN Enter\n");
LibAmdFinit ();
Ts = ((DOUBLE) (D0F0xBC_x1F468_TimerPeriod_Value * D0F0xBC_x1F46C_BapmPeriod_Value) / 100) / 1000000;
for (Index = 0; Index < 15; Index++) {
GnbRegisterReadTN (
TYPE_D0F0xBC ,
0xe01040c4 + Index * 4,
&RFuse1,
0,
StdHeader
);
GnbRegisterReadTN (
TYPE_D0F0xBC ,
0xe01040c4 + (Index + 15) * 4,
&TauFuse1,
0,
StdHeader
);
R = GnbBapmDecodeR (RFuse1 & 0x3FF);
Tau = GnbBapmDecodeTau (TauFuse1 & 0x3FF);
X = GnbFpLibDoubleToInt32 (GnbBapmCalculateX (Ts, Tau, R));
Y = GnbFpLibDoubleToInt32 (GnbBapmCalculateY (Ts, Tau));
GnbBapmSetYAndX (X, Y, Index * 2 * 4, StdHeader);
R = GnbBapmDecodeR ((RFuse1 >> 10) & 0x3FF);
Tau = GnbBapmDecodeTau ((TauFuse1 >> 10) & 0x3FF);
X = GnbFpLibDoubleToInt32 (GnbBapmCalculateX (Ts, Tau, R));
Y = GnbFpLibDoubleToInt32 (GnbBapmCalculateY (Ts, Tau));
GnbBapmSetYAndX (X, Y, (Index * 2 + 30) * 4 , StdHeader);
R = GnbBapmDecodeR ((RFuse1 >> 20) & 0x3FF);
Tau = GnbBapmDecodeTau ((TauFuse1 >> 20) & 0x3FF);
X = GnbFpLibDoubleToInt32 (GnbBapmCalculateX (Ts, Tau, R));
Y = GnbFpLibDoubleToInt32 (GnbBapmCalculateY (Ts, Tau));
GnbBapmSetYAndX (X, Y, (Index * 2 + 60) * 4 , StdHeader);
}
IDS_HDT_CONSOLE (GNB_TRACE, "GnbBapmCalculateCoeffsTN Exit\n");
}