summaryrefslogtreecommitdiff
path: root/src/northbridge
diff options
context:
space:
mode:
authorTimothy Pearson <tpearson@raptorengineeringinc.com>2015-02-14 03:32:21 -0600
committerAlexandru Gagniuc <mr.nuke.me@gmail.com>2015-02-16 09:08:12 +0100
commit3c206781f2671e727c59f2884301338c56990889 (patch)
tree919e572745dfd13c381e1c0b066b8701bd4e6895 /src/northbridge
parenta70093611f7c5c0dda273833e975dd56cfe260b0 (diff)
downloadcoreboot-3c206781f2671e727c59f2884301338c56990889.tar.xz
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>
Diffstat (limited to 'src/northbridge')
-rw-r--r--src/northbridge/amd/amdfam10/raminit_amdmct.c37
-rw-r--r--src/northbridge/amd/amdmct/wrappers/mcti_d.c21
2 files changed, 57 insertions, 1 deletions
diff --git a/src/northbridge/amd/amdfam10/raminit_amdmct.c b/src/northbridge/amd/amdfam10/raminit_amdmct.c
index 6b022094d3..6398506049 100644
--- a/src/northbridge/amd/amdfam10/raminit_amdmct.c
+++ b/src/northbridge/amd/amdfam10/raminit_amdmct.c
@@ -1,6 +1,7 @@
/*
* 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.
*
* This program is free software; you can redistribute it and/or modify
@@ -34,6 +35,42 @@ static void print_t(const char *strval)
#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 */
#include "amdfam10.h"
#include "../amdmct/wrappers/mcti.h"
diff --git a/src/northbridge/amd/amdmct/wrappers/mcti_d.c b/src/northbridge/amd/amdmct/wrappers/mcti_d.c
index 4df2a16549..4b229bcb39 100644
--- a/src/northbridge/amd/amdmct/wrappers/mcti_d.c
+++ b/src/northbridge/amd/amdmct/wrappers/mcti_d.c
@@ -1,6 +1,7 @@
/*
* 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.
*
* 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)
{
- 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