northbridge/amd/amdht: Add support for HT3 2.8GHz and up link frequencies

Change-Id: Ifa1592d26ba7deb034046fd3f2a15149117d9a76
Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com>
Reviewed-on: http://review.coreboot.org/12027
Tested-by: build bot (Jenkins)
Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
This commit is contained in:
Timothy Pearson 2015-08-02 21:36:24 -05:00 committed by Martin Roth
parent 5173bb7d9d
commit 7c55f374d1
7 changed files with 155 additions and 85 deletions

View File

@ -273,7 +273,13 @@ static const struct {
/* Link Global Retry Control Register */
{ 0, 0x150, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL,
0x00073900, 0x00073F00 },
0x00073900, 0x00073f70 }, /* TotalRetryAttempts = 0x7,
HtRetryCrcDatInsDynEn = 0x1,
HtRetryCrcCmdPackDynEn = 0x1,
HtRetryCrcDatIns = 0x4,
HtRetryCrcCmdPack = 0x1,
ForceErrType = 0x0,
MultRetryErr = 0x0 */
/* Errata 351
* System software should program the Link Extended Control Registers[LS2En]

View File

@ -120,21 +120,21 @@ enumerations
10 21 42ms
10 22 84ms
11 0 Auto
11 1 2.6GHz
11 2 2.4GHz
11 3 2.2GHz
11 4 2.0GHz
11 5 1.8GHz
11 6 1.6GHz
11 7 1.4GHz
11 8 1.2GHz
11 9 1.0GHz
11 10 800MHz
11 11 600MHz
11 12 500MHz
11 13 400MHz
11 14 300MHz
11 15 200MHz
11 1 3.2GHz
11 2 3.0GHz
11 3 2.8GHz
11 4 2.6GHz
11 5 2.4GHz
11 6 2.2GHz
11 7 2.0GHz
11 8 1.8GHz
11 9 1.6GHz
11 10 1.4GHz
11 11 1.2GHz
11 12 1.0GHz
11 13 800MHz
11 14 600MHz
11 15 500MHz
12 0 1.5V
12 1 1.35V
12 2 1.25V

View File

@ -2,6 +2,7 @@
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -58,6 +59,7 @@
#define HTHOST_LINK_CAPABILITY_REG 0x00
#define HTHOST_LINK_CONTROL_REG 0x04
#define HTHOST_FREQ_REV_REG 0x08
#define HTHOST_FREQ_REV_REG_2 0x1c
#define HT_HOST_REV_REV3 0x60
#define HTHOST_FEATURE_CAP_REG 0x0C
#define HTHOST_BUFFER_COUNT_REG 0x10
@ -123,10 +125,10 @@ typedef struct
/* This section is for keeping track of capabilities and possible configurations */
BOOL RegangCap;
u16 PrvFrequencyCap;
uint32_t PrvFrequencyCap;
u8 PrvWidthInCap;
u8 PrvWidthOutCap;
u16 CompositeFrequencyCap;
uint32_t CompositeFrequencyCap;
} sPortDescriptor;

View File

@ -48,28 +48,32 @@
#define APIC_Base_BSP 8
#define APIC_Base 0x1b
#define NVRAM_LIMIT_HT_SPEED_200 0xf
#define NVRAM_LIMIT_HT_SPEED_300 0xe
#define NVRAM_LIMIT_HT_SPEED_400 0xd
#define NVRAM_LIMIT_HT_SPEED_500 0xc
#define NVRAM_LIMIT_HT_SPEED_600 0xb
#define NVRAM_LIMIT_HT_SPEED_800 0xa
#define NVRAM_LIMIT_HT_SPEED_1000 0x9
#define NVRAM_LIMIT_HT_SPEED_1200 0x8
#define NVRAM_LIMIT_HT_SPEED_1400 0x7
#define NVRAM_LIMIT_HT_SPEED_1600 0x6
#define NVRAM_LIMIT_HT_SPEED_1800 0x5
#define NVRAM_LIMIT_HT_SPEED_2000 0x4
#define NVRAM_LIMIT_HT_SPEED_2200 0x3
#define NVRAM_LIMIT_HT_SPEED_2400 0x2
#define NVRAM_LIMIT_HT_SPEED_2600 0x1
#define NVRAM_LIMIT_HT_SPEED_200 0x12
#define NVRAM_LIMIT_HT_SPEED_300 0x11
#define NVRAM_LIMIT_HT_SPEED_400 0x10
#define NVRAM_LIMIT_HT_SPEED_500 0xf
#define NVRAM_LIMIT_HT_SPEED_600 0xe
#define NVRAM_LIMIT_HT_SPEED_800 0xd
#define NVRAM_LIMIT_HT_SPEED_1000 0xc
#define NVRAM_LIMIT_HT_SPEED_1200 0xb
#define NVRAM_LIMIT_HT_SPEED_1400 0xa
#define NVRAM_LIMIT_HT_SPEED_1600 0x9
#define NVRAM_LIMIT_HT_SPEED_1800 0x8
#define NVRAM_LIMIT_HT_SPEED_2000 0x7
#define NVRAM_LIMIT_HT_SPEED_2200 0x6
#define NVRAM_LIMIT_HT_SPEED_2400 0x5
#define NVRAM_LIMIT_HT_SPEED_2600 0x4
#define NVRAM_LIMIT_HT_SPEED_2800 0x3
#define NVRAM_LIMIT_HT_SPEED_3000 0x2
#define NVRAM_LIMIT_HT_SPEED_3200 0x1
#define NVRAM_LIMIT_HT_SPEED_AUTO 0x0
static const uint16_t ht_speed_limit[16] =
{0xFFFF, 0x7FFF, 0x3FFF, 0x1FFF,
0x0FFF, 0x07FF, 0x03FF, 0x01FF,
0x00FF, 0x007F, 0x003F, 0x001F,
0x000F, 0x0007, 0x0003, 0x0001};
static const uint32_t ht_speed_limit[20] =
{0xFFFFF, 0xFFFFF, 0x7FFFF, 0x3FFFF,
0x0FFFF, 0x07FFF, 0x03FFF, 0x01FFF,
0x00FFF, 0x007FF, 0x003FF, 0x001FF,
0x000FF, 0x0007F, 0x0003F, 0x0001F,
0x0000F, 0x00007, 0x00003, 0x00001};
static const struct ht_speed_limit_map_t {
uint16_t mhz;
@ -91,9 +95,12 @@ static const struct ht_speed_limit_map_t {
{2200, NVRAM_LIMIT_HT_SPEED_2200},
{2400, NVRAM_LIMIT_HT_SPEED_2400},
{2600, NVRAM_LIMIT_HT_SPEED_2600},
{2800, NVRAM_LIMIT_HT_SPEED_2800},
{3000, NVRAM_LIMIT_HT_SPEED_3000},
{3200, NVRAM_LIMIT_HT_SPEED_3200},
};
static const uint16_t ht_speed_mhz_to_hw(uint16_t mhz)
static const uint32_t ht_speed_mhz_to_hw(uint16_t mhz)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(ht_speed_limit_map); i++)
@ -452,7 +459,7 @@ static void htDiscoveryFloodFill(sMainData *pDat)
/* Set currentNode's NodeID field to currentNode */
pDat->nb->writeNodeID(currentNode, currentNode, pDat->nb);
/* Enable routing tables on currentNode*/
/* Enable routing tables on currentNode */
pDat->nb->enableRoutingTables(currentNode, pDat->nb);
for (currentLinkID = 0; currentLinkID < pDat->nb->maxLinks; currentLinkID++)
@ -1427,19 +1434,30 @@ static void regangLinks(sMainData *pDat)
static void selectOptimalWidthAndFrequency(sMainData *pDat)
{
u8 i, j;
u32 temp;
u16 cbPCBFreqLimit;
u16 cbPCBFreqLimit_NVRAM;
uint32_t temp;
uint32_t cbPCBFreqLimit;
uint32_t cbPCBFreqLimit_NVRAM;
u8 cbPCBABDownstreamWidth;
u8 cbPCBBAUpstreamWidth;
cbPCBFreqLimit_NVRAM = 0xFFFF;
cbPCBFreqLimit_NVRAM = 0xfffff;
if (get_option(&temp, "hypertransport_speed_limit") == CB_SUCCESS)
cbPCBFreqLimit_NVRAM = ht_speed_limit[temp & 0xf];
if (!is_fam15h()) {
/* FIXME
* By default limit frequency to 2.6 GHz as there are residual
* problems with HT v3.1 implementation on at least some Socket G34
* mainboards / Fam10h CPUs.
* Debug the issues and reenable this...
*/
if (cbPCBFreqLimit_NVRAM > 0xffff)
cbPCBFreqLimit_NVRAM = 0xffff;
}
for (i = 0; i < pDat->TotalLinks*2; i += 2)
{
cbPCBFreqLimit = 0xFFFF; // Maximum allowed by autoconfiguration
cbPCBFreqLimit = 0xfffff; // Maximum allowed by autoconfiguration
if (pDat->HtBlock->ht_link_configuration)
cbPCBFreqLimit = ht_speed_mhz_to_hw(pDat->HtBlock->ht_link_configuration->ht_speed_limit);
cbPCBFreqLimit = min(cbPCBFreqLimit, cbPCBFreqLimit_NVRAM);
@ -1484,17 +1502,18 @@ static void selectOptimalWidthAndFrequency(sMainData *pDat)
}
}
temp = pDat->PortList[i].PrvFrequencyCap;
temp &= pDat->PortList[i+1].PrvFrequencyCap;
temp &= cbPCBFreqLimit;
pDat->PortList[i].CompositeFrequencyCap = (u16)temp;
pDat->PortList[i+1].CompositeFrequencyCap = (u16)temp;
pDat->PortList[i].CompositeFrequencyCap = temp;
pDat->PortList[i+1].CompositeFrequencyCap = temp;
ASSERT (temp != 0);
for (j = 15; ; j--)
for (j = 19; ; j--)
{
if (temp & ((u32)1 << j))
if ((j == 16) || (j == 15))
continue;
if (temp & ((uint32_t)1 << j))
break;
}
@ -1638,12 +1657,14 @@ static void hammerSublinkFixup(sMainData *pDat)
/* Remove hiFreq from the list of valid frequencies */
temp = temp & ~((uint32)1 << hiFreq);
ASSERT (temp != 0);
pDat->PortList[hiIndex].CompositeFrequencyCap = (uint16)temp;
pDat->PortList[hiIndex+1].CompositeFrequencyCap = (uint16)temp;
pDat->PortList[hiIndex].CompositeFrequencyCap = temp;
pDat->PortList[hiIndex+1].CompositeFrequencyCap = temp;
for (k = 15; ; k--)
for (k = 19; ; k--)
{
if (temp & ((u32)1 << k))
if ((j == 16) || (j == 15))
continue;
if (temp & ((uint32_t)1 << k))
break;
}

View File

@ -49,6 +49,9 @@
#define HT_FREQUENCY_2200M 12
#define HT_FREQUENCY_2400M 13
#define HT_FREQUENCY_2600M 14
#define HT_FREQUENCY_2800M 17
#define HT_FREQUENCY_3000M 18
#define HT_FREQUENCY_3200M 19
/* Frequency Limit equates for call backs which take a frequency supported mask. */
#define HT_FREQUENCY_LIMIT_200M 1
@ -65,6 +68,9 @@
#define HT_FREQUENCY_LIMIT_2200M 0x1FFF
#define HT_FREQUENCY_LIMIT_2400M 0x3FFF
#define HT_FREQUENCY_LIMIT_2600M 0x7FFF
#define HT_FREQUENCY_LIMIT_2800M 0x3FFFF
#define HT_FREQUENCY_LIMIT_3000M 0x7FFFF
#define HT_FREQUENCY_LIMIT_3200M 0xFFFFF
/*
* Event Notify definitions
@ -220,7 +226,7 @@ typedef struct {
* @param[in] u8 Link = The Device's link number (0 or 1)
* @param[in,out] u8* LinkWidthIn = modify to change the Link Witdh In
* @param[in,out] u8* LinkWidthOut = modify to change the Link Witdh Out
* @param[in,out] u16* FreqCap = modify to change the link's frequency capability
* @param[in,out] u32* FreqCap = modify to change the link's frequency capability
*
* ---------------------------------------------------------------------------------------
*/
@ -235,7 +241,7 @@ typedef struct {
u8 Link,
u8 *LinkWidthIn,
u8 *LinkWidthOut,
u16 *FreqCap
u32 *FreqCap
);
/**----------------------------------------------------------------------------------------
@ -258,7 +264,7 @@ typedef struct {
* @param[in] u8 linkB = The link on that node
* @param[in,out] u8* ABLinkWidthLimit = modify to change the Link Witdh In
* @param[in,out] u8* BALinkWidthLimit = modify to change the Link Witdh Out
* @param[in,out] u16* PCBFreqCap = modify to change the link's frequency capability
* @param[in,out] u32* PCBFreqCap = modify to change the link's frequency capability
*
* ---------------------------------------------------------------------------------------
*/
@ -269,7 +275,7 @@ typedef struct {
u8 LinkB,
u8 *ABLinkWidthLimit,
u8 *BALinkWidthLimit,
u16 *PCBFreqCap
u32 *PCBFreqCap
);
/**----------------------------------------------------------------------------------------
@ -291,7 +297,7 @@ typedef struct {
* @param[in] u8 Depth = The depth in the I/O chain from the Host
* @param[in,out] u8* DownstreamLinkWidthLimit = modify to change the Link Witdh In
* @param[in,out] u8* UpstreamLinkWidthLimit = modify to change the Link Witdh Out
* @param[in,out] u16* PCBFreqCap = modify to change the link's frequency capability
* @param[in,out] u32* PCBFreqCap = modify to change the link's frequency capability
*
* ---------------------------------------------------------------------------------------
*/
@ -301,7 +307,7 @@ typedef struct {
u8 Depth,
u8 *DownstreamLinkWidthLimit,
u8 *UpstreamLinkWidthLimit,
u16 *PCBFreqCap
u32 *PCBFreqCap
);
/**----------------------------------------------------------------------------------------

View File

@ -1310,7 +1310,7 @@ static u8 convertWidthToBits(u8 value, cNorthBridge *nb)
* @return Frequency mask
*
******************************************************************************/
static u16 ht1NorthBridgeFreqMask(u8 node, cNorthBridge *nb)
static uint32_t ht1NorthBridgeFreqMask(u8 node, cNorthBridge *nb)
{
/* only up to HT1 speeds */
return (HT_FREQUENCY_LIMIT_HT1_ONLY);
@ -1331,26 +1331,43 @@ static u16 ht1NorthBridgeFreqMask(u8 node, cNorthBridge *nb)
* @return = Frequency mask
*
******************************************************************************/
static u16 fam10NorthBridgeFreqMask(u8 node, cNorthBridge *nb)
static uint32_t fam10NorthBridgeFreqMask(u8 node, cNorthBridge *nb)
{
u8 nbCOF;
u16 supported;
uint32_t supported;
nbCOF = getMinNbCOF();
/*
* nbCOF is minimum northbridge speed in hundreds of MHz.
* HT can not go faster than the minimum speed of the northbridge.
*/
if ((nbCOF >= 6) && (nbCOF <= 26))
if ((nbCOF >= 6) && (nbCOF < 10))
{
/* Generation 1 HT link frequency */
/* Convert frequency to bit and all less significant bits,
* by setting next power of 2 and subtracting 1.
*/
supported = ((u16)1 << ((nbCOF >> 1) + 2)) - 1;
supported = ((uint32_t)1 << ((nbCOF >> 1) + 2)) - 1;
}
else if (nbCOF > 26)
else if ((nbCOF >= 10) && (nbCOF <= 32))
{
supported = HT_FREQUENCY_LIMIT_2600M;
/* Generation 3 HT link frequency
* Assume error retry is enabled on all Gen 3 links
*/
if (is_gt_rev_d()) {
nbCOF *= 2;
if (nbCOF > 32)
nbCOF = 32;
}
/* Convert frequency to bit and all less significant bits,
* by setting next power of 2 and subtracting 1.
*/
supported = ((uint32_t)1 << ((nbCOF >> 1) + 2)) - 1;
}
else if (nbCOF > 32)
{
supported = HT_FREQUENCY_LIMIT_3200M;
}
/* unlikely cases, but include as a defensive measure, also avoid trick above */
else if (nbCOF == 4)
@ -1405,8 +1422,13 @@ static void gatherLinkData(sMainData *pDat, cNorthBridge *nb)
pDat->PortList[i].PrvWidthInCap = convertBitsToWidth((u8)temp, pDat->nb);
AmdPCIReadBits(linkBase + HTHOST_FREQ_REV_REG, 31, 16, &temp);
pDat->PortList[i].PrvFrequencyCap = (u16)temp & 0x7FFF
& nb->northBridgeFreqMask(pDat->PortList[i].NodeID, pDat->nb); /* Mask off bit 15, reserved value */
pDat->PortList[i].PrvFrequencyCap = temp & 0x7FFF /* Mask off bit 15, reserved value */
& nb->northBridgeFreqMask(pDat->PortList[i].NodeID, pDat->nb);
if (is_gt_rev_d()) {
AmdPCIReadBits(linkBase + HTHOST_FREQ_REV_REG_2, 15, 1, &temp);
temp &= 0x7; /* Mask off reserved values */
pDat->PortList[i].PrvFrequencyCap |= (temp << 17);
}
}
else
{
@ -1463,7 +1485,7 @@ static void setLinkData(sMainData *pDat, cNorthBridge *nb)
{
u8 i;
SBDFO linkBase;
u32 temp, widthin, widthout, bits;
u32 temp, temp2, frequency_index, widthin, widthout, bits;
for (i = 0; i < pDat->TotalLinks*2; i++)
{
@ -1524,10 +1546,19 @@ static void setLinkData(sMainData *pDat, cNorthBridge *nb)
temp = pDat->PortList[i].SelFrequency;
if (pDat->PortList[i].Type == PORTLIST_TYPE_CPU)
{
ASSERT((temp >= HT_FREQUENCY_600M && temp <= HT_FREQUENCY_2600M)
ASSERT((temp >= HT_FREQUENCY_600M && temp <= HT_FREQUENCY_3200M)
|| (temp == HT_FREQUENCY_200M) || (temp == HT_FREQUENCY_400M));
frequency_index = temp;
if (temp > 0xf) {
temp2 = (temp >> 4) & 0x1;
temp &= 0xf;
} else {
temp2 = 0x0;
}
if (is_gt_rev_d())
AmdPCIWriteBits(linkBase + HTHOST_FREQ_REV_REG_2, 0, 0, &temp2);
AmdPCIWriteBits(linkBase + HTHOST_FREQ_REV_REG, 11, 8, &temp);
if (temp > HT_FREQUENCY_1000M) /* Gen1 = 200MHz -> 1000MHz, Gen3 = 1200MHz -> 2600MHz */
if (frequency_index > HT_FREQUENCY_1000M) /* Gen1 = 200MHz -> 1000MHz, Gen3 = 1200MHz -> 3200MHz */
{
/* Enable for Gen3 frequencies */
temp = 1;
@ -1557,7 +1588,7 @@ static void setLinkData(sMainData *pDat, cNorthBridge *nb)
SBDFO currentPtr;
BOOL isFound;
ASSERT(temp <= HT_FREQUENCY_2600M);
ASSERT(temp <= HT_FREQUENCY_3200M);
/* Write the frequency setting */
AmdPCIWriteBits(linkBase + HTSLAVE_FREQ_REV_0_REG, 11, 8, &temp);
@ -1718,6 +1749,9 @@ static void fam0fWriteHTLinkCmdBufferAlloc(u8 node, u8 link, u8 req, u8 preq, u8
/* Probe Command Buffers */
temp = prb;
AmdPCIWriteBits(currentPtr, 15, 12, &temp);
/* LockBc */
temp = 1;
AmdPCIWriteBits(currentPtr, 31, 31, &temp);
}
#endif /* HT_BUILD_NC_ONLY */

View File

@ -2,6 +2,7 @@
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Advanced Micro Devices, Inc.
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -103,7 +104,7 @@ struct cNorthBridge
/* Public Interfaces for northbridge clients, Optimization */
u8 (*convertBitsToWidth)(u8 value, cNorthBridge *nb);
u8 (*convertWidthToBits)(u8 value, cNorthBridge *nb);
u16 (*northBridgeFreqMask)(u8 node, cNorthBridge *nb);
uint32_t (*northBridgeFreqMask)(u8 node, cNorthBridge *nb);
void (*gatherLinkData)(sMainData *pDat, cNorthBridge *nb);
void (*setLinkData)(sMainData *pDat, cNorthBridge *nb);