northbridge/amd/amdfam10: Fold back memory frequency based on MCT load

K10 processors cannot operate at full memory speeds when more than a
certain number of DIMMs are installed on a specific channel.  The
allowed DIMM numbers and speeds are listed in the BKDG; this patch
implements the appropriate frequency reduction to ensure stability.

Change-Id: I8ac5b508915e423d262ad36c49de1fe696df2ecd
Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com>
Reviewed-on: http://review.coreboot.org/8435
Tested-by: build bot (Jenkins)
Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
This commit is contained in:
Timothy Pearson 2015-02-14 03:32:21 -06:00 committed by Alexandru Gagniuc
parent a70093611f
commit 3c206781f2
2 changed files with 57 additions and 1 deletions

View File

@ -1,6 +1,7 @@
/* /*
* This file is part of the coreboot project. * This file is part of the coreboot project.
* *
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
* Copyright (C) 2007 Advanced Micro Devices, Inc. * Copyright (C) 2007 Advanced Micro Devices, Inc.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -34,6 +35,42 @@ static void print_t(const char *strval)
#endif #endif
} }
static void print_tf(const char *func, const char *strval)
{
#if CONFIG_DEBUG_RAM_SETUP
printk(BIOS_DEBUG, "%s: %s", func, strval);
#endif
}
static uint16_t mct_MaxLoadFreq(uint8_t count, uint16_t freq)
{
/* Return limited maximum RAM frequency */
if (IS_ENABLED(CONFIG_DIMM_DDR2)) {
if (IS_ENABLED(CONFIG_DIMM_REGISTERED)) {
/* K10 BKDG Rev. 3.62 Table 53 */
if (count > 2) {
/* Limit to DDR2-533 */
if (freq > 266) {
freq = 266;
print_tf(__func__, ": More than 2 DIMMs on channel; limiting to DDR2-533\n");
}
}
}
else {
/* K10 BKDG Rev. 3.62 Table 52 */
if (count > 1) {
/* Limit to DDR2-800 */
if (freq > 400) {
freq = 400;
print_tf(__func__, ": More than 1 DIMM on channel; limiting to DDR2-800\n");
}
}
}
}
return freq;
}
#if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */ #if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */
#include "amdfam10.h" #include "amdfam10.h"
#include "../amdmct/wrappers/mcti.h" #include "../amdmct/wrappers/mcti.h"

View File

@ -1,6 +1,7 @@
/* /*
* This file is part of the coreboot project. * This file is part of the coreboot project.
* *
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
* Copyright (C) 2007-2008 Advanced Micro Devices, Inc. * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -281,7 +282,25 @@ static void mctHookAfterDIMMpre(void)
static void mctGet_MaxLoadFreq(struct DCTStatStruc *pDCTstat) static void mctGet_MaxLoadFreq(struct DCTStatStruc *pDCTstat)
{ {
pDCTstat->PresetmaxFreq = MEM_MAX_LOAD_FREQ; pDCTstat->PresetmaxFreq = mctGet_NVbits(NV_MAX_MEMCLK);
/* Determine the number of installed DIMMs */
int ch1_count = 0;
int ch2_count = 0;
int i;
for (i = 0; i < 15; i = i + 2) {
if (pDCTstat->DIMMValid & (1 << i))
ch1_count++;
if (pDCTstat->DIMMValid & (1 << (i + 1)))
ch2_count++;
}
if (IS_ENABLED(CONFIG_DEBUG_RAM_SETUP)) {
printk(BIOS_DEBUG, "mctGet_MaxLoadFreq: Channel 1: %d DIMM(s) detected\n", ch1_count);
printk(BIOS_DEBUG, "mctGet_MaxLoadFreq: Channel 2: %d DIMM(s) detected\n", ch2_count);
}
/* Set limits if needed */
pDCTstat->PresetmaxFreq = mct_MaxLoadFreq(max(ch1_count, ch2_count), pDCTstat->PresetmaxFreq);
} }
#ifdef UNUSED_CODE #ifdef UNUSED_CODE