From 3c206781f2671e727c59f2884301338c56990889 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sat, 14 Feb 2015 03:32:21 -0600 Subject: [PATCH] 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 Reviewed-on: http://review.coreboot.org/8435 Tested-by: build bot (Jenkins) Reviewed-by: Alexandru Gagniuc --- src/northbridge/amd/amdfam10/raminit_amdmct.c | 37 +++++++++++++++++++ src/northbridge/amd/amdmct/wrappers/mcti_d.c | 21 ++++++++++- 2 files changed, 57 insertions(+), 1 deletion(-) 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 , 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 , 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