From f333ba09580c00a6f27e3ee0796431f5df936ecf Mon Sep 17 00:00:00 2001 From: Edwin Beasant Date: Thu, 10 Jun 2010 15:24:57 +0000 Subject: This commit updates the Geode LX GLCP delay control setup from the v2 way to the v3 way. This resolves problems with terminated DRAM modules. Signed-off-by: Edwin Beasant Acked-by: Roland G. Minnich git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5629 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/cpu/amd/model_lx/cpureginit.c | 286 ++++++++++-------------- src/cpu/amd/model_lx/msrinit.c | 10 +- src/include/cpu/amd/lxdef.h | 9 +- src/include/cpu/x86/msr.h | 6 + src/mainboard/amd/db800/romstage.c | 6 +- src/mainboard/amd/norwich/romstage.c | 3 +- src/mainboard/artecgroup/dbe61/romstage.c | 2 +- src/mainboard/digitallogic/msm800sev/romstage.c | 3 +- src/mainboard/iei/pcisa-lx-800-r10/romstage.c | 3 +- src/mainboard/lippert/roadrunner-lx/romstage.c | 2 +- src/mainboard/lippert/spacerunner-lx/romstage.c | 2 +- src/mainboard/pcengines/alix1c/romstage.c | 3 +- src/mainboard/traverse/geos/romstage.c | 2 +- src/mainboard/winent/pl6064/romstage.c | 2 +- 14 files changed, 154 insertions(+), 185 deletions(-) (limited to 'src') diff --git a/src/cpu/amd/model_lx/cpureginit.c b/src/cpu/amd/model_lx/cpureginit.c index 62fa973a8c..6e7de84c6a 100644 --- a/src/cpu/amd/model_lx/cpureginit.c +++ b/src/cpu/amd/model_lx/cpureginit.c @@ -1,6 +1,6 @@ /* * This file is part of the coreboot project. - * + * * Copyright (C) 2006 Indrek Kruusa * Copyright (C) 2006 Ronald G. Minnich * Copyright (C) 2007 Advanced Micro Devices, Inc. @@ -25,200 +25,156 @@ ;* SetDelayControl ;* ;*************************************************************************/ -static void SetDelayControl(void) +#include "cpu/x86/msr.h" + + + + +/** + * Delay Control Settings table from AMD (MCP 0x4C00000F). + */ +static const msrinit_t delay_msr_table[] = { + {CPU_BC_MSS_ARRAY_CTL0, {.hi = 0x00000000, .lo = 0x2814D352}}, + {CPU_BC_MSS_ARRAY_CTL1, {.hi = 0x00000000, .lo = 0x1068334D}}, + {CPU_BC_MSS_ARRAY_CTL2, {.hi = 0x00000106, .lo = 0x83104104}}, +}; + + + +static const struct delay_controls { + u8 dimms; + u8 devices; + u32 slow_hi; + u32 slow_low; + u32 fast_hi; + u32 fast_low; +} delay_control_table[] = { + /* DIMMs Devs Slow (<=333MHz) Fast (>334MHz) */ + { 1, 4, 0x0837100FF, 0x056960004, 0x0827100FF, 0x056960004 }, + { 1, 8, 0x0837100AA, 0x056960004, 0x0827100AA, 0x056960004 }, + { 1, 16, 0x0837100AA, 0x056960004, 0x082710055, 0x056960004 }, + { 2, 8, 0x0837100A5, 0x056960004, 0x082710000, 0x056960004 }, + { 2, 16, 0x0937100A5, 0x056960004, 0x0C27100A5, 0x056960004 }, + { 2, 20, 0x0B37100A5, 0x056960004, 0x0B27100A5, 0x056960004 }, + { 2, 24, 0x0B37100A5, 0x056960004, 0x0B27100A5, 0x056960004 }, + { 2, 32, 0x0B37100A5, 0x056960004, 0x0B2710000, 0x056960004 }, +}; + +/* + * Bit 55 (disable SDCLK 1,3,5) should be set if there is a single DIMM + * in slot 0, but it should be clear for all 2 DIMM settings and if a + * single DIMM is in slot 1. Bits 54:52 should always be set to '111'. + * + * Settings for single DIMM and no VTT termination (like DB800 platform) + * 0xF2F100FF 0x56960004 + * ------------------------------------- + * ADDR/CTL have 22 ohm series R + * DQ/DQM/DQS have 33 ohm series R + */ + +/** + * This is Black Magic DRAM timing juju[1]. + * + * DRAM delay depends on CPU clock, memory bus clock, memory bus loading, + * memory bus termination, your middle initial (ha! caught you!), GeodeLink + * clock rate, and DRAM timing specifications. + * + * From this the code computes a number which is "known to work". No, + * hardware is not an exact science. And, finally, if an FS2 (JTAG debugger) + * is hooked up, then just don't do anything. This code was written by a master + * of the Dark Arts at AMD and should not be modified in any way. + * + * [1] (http://www.thefreedictionary.com/juju) + * + * @param dimm0 The SMBus address of DIMM 0 (mainboard dependent). + * @param dimm1 The SMBus address of DIMM 1 (mainboard dependent). + * @param terminated The bus is terminated. (mainboard dependent). + */ +static void SetDelayControl(u8 dimm0, u8 dimm1, int terminated) { - unsigned int msrnum, glspeed; - unsigned char spdbyte0, spdbyte1; + u32 glspeed; + u8 spdbyte0, spdbyte1, dimms, i; msr_t msr; glspeed = GeodeLinkSpeed(); - /* fix delay controls for DM and IM arrays */ - msrnum = CPU_BC_MSS_ARRAY_CTL0; - msr.hi = 0; - msr.lo = 0x2814D352; - wrmsr(msrnum, msr); - - msrnum = CPU_BC_MSS_ARRAY_CTL1; - msr.hi = 0; - msr.lo = 0x1068334D; - wrmsr(msrnum, msr); - - msrnum = CPU_BC_MSS_ARRAY_CTL2; - msr.hi = 0x00000106; - msr.lo = 0x83104104; - wrmsr(msrnum, msr); + /* Fix delay controls for DM and IM arrays. */ + for (i = 0; i < ARRAY_SIZE(delay_msr_table); i++) + wrmsr(delay_msr_table[i].index, delay_msr_table[i].msr); - msrnum = GLCP_FIFOCTL; - msr = rdmsr(msrnum); + msr = rdmsr(GLCP_FIFOCTL); msr.hi = 0x00000005; - wrmsr(msrnum, msr); + wrmsr(GLCP_FIFOCTL, msr); - /* Enable setting */ - msrnum = CPU_BC_MSS_ARRAY_CTL_ENA; + /* Enable setting. */ msr.hi = 0; msr.lo = 0x00000001; - wrmsr(msrnum, msr); + wrmsr(CPU_BC_MSS_ARRAY_CTL_ENA, msr); - /* Debug Delay Control Setup Check - Leave it alone if it has been setup. FS2 or something is here. */ - msrnum = GLCP_DELAY_CONTROLS; - msr = rdmsr(msrnum); - if (msr.lo & ~(0x7C0)) { + /* Debug Delay Control setup check. + * Leave it alone if it has been setup. FS2 or something is here. + */ + msr = rdmsr(GLCP_DELAY_CONTROLS); + if (msr.lo & ~(DELAY_LOWER_STATUS_MASK)) return; - } - /* - * Delay Controls based on DIMM loading. UGH! - * # of Devices = Module Width (SPD6) / Device Width(SPD13) * Physical Banks(SPD5) - * Note - We only support module width of 64. + /* Delay Controls based on DIMM loading. UGH! + * Number of devices = module width (SPD 6) / device width (SPD 13) + * * physical banks (SPD 5) + * + * Note: We only support a module width of 64. */ - spdbyte0 = spd_read_byte(DIMM0, SPD_PRIMARY_SDRAM_WIDTH); + dimms = 0; + spdbyte0 = spd_read_byte(dimm0, SPD_PRIMARY_SDRAM_WIDTH); if (spdbyte0 != 0xFF) { - spdbyte0 = (unsigned char)64 / spdbyte0 * - (unsigned char)(spd_read_byte(DIMM0, SPD_NUM_DIMM_BANKS)); + dimms++; + spdbyte0 = (u8)64 / spdbyte0 * + (u8)(spd_read_byte(dimm0, SPD_NUM_DIMM_BANKS)); } else { spdbyte0 = 0; } - spdbyte1 = spd_read_byte(DIMM1, SPD_PRIMARY_SDRAM_WIDTH); + spdbyte1 = spd_read_byte(dimm1, SPD_PRIMARY_SDRAM_WIDTH); if (spdbyte1 != 0xFF) { - spdbyte1 = (unsigned char)64 / spdbyte1 * - (unsigned char)(spd_read_byte(DIMM1, SPD_NUM_DIMM_BANKS)); + dimms++; + spdbyte1 = (u8)64 / spdbyte1 * + (u8)(spd_read_byte(dimm1, SPD_NUM_DIMM_BANKS)); } else { spdbyte1 = 0; } -/* The current thinking. Subject to change... - -; "FUTURE ROBUSTNESS" PROPOSAL -; ---------------------------- -; DIMM Max MBUS MC 0x2000001A bits 26:24 -;DIMMs devices Frequency MCP 0x4C00000F Setting vvv -;----- ------- --------- ---------------------- ---------- -;1 4 400MHz 0x82*100FF 0x56960004 4 -;1 8 400MHz 0x82*100AA 0x56960004 4 -;1 16 400MHz 0x82*10055 0x56960004 4 -; -;2 4,4 400MHz 0x82710000 0x56960004 4 -; -;1 4 <=333MHz 0x83*100FF 0x56960004 3 -;1 8 <=333MHz 0x83*100AA 0x56960004 3 -;1 16 <=333MHz 0x83*100AA 0x56960004 3 -; -;2 4,4 <=333MHz 0x837100A5 0x56960004 3 -;2 8,8 <=333MHz 0x937100A5 0x56960004 3 -; -;========================================================================= -;* - Bit 55 (disable SDCLK 1,3,5) should be set if there is a single DIMM in slot 0, -; but it should be clear for all 2 DIMM settings and if a single DIMM is in slot 1. -; Bits 54:52 should always be set to '111'. - -;No VTT termination -;------------------------------------- -;ADDR/CTL have 22 ohm series R -;DQ/DQM/DQS have 33 ohm series R -; -; DIMM Max MBUS -;DIMMs devices Frequency MCP 0x4C00000F Setting -;----- ------- --------- ---------------------- -;1 4 400MHz 0xF2F100FF 0x56960004 4 The No VTT changes improve timing. -;1 8 400MHz 0xF2F100FF 0x56960004 4 -;1 4 <=333MHz 0xF2F100FF 0x56960004 3 -;1 8 <=333MHz 0xF2F100FF 0x56960004 3 -;1 16 <=333MHz 0xF2F100FF 0x56960004 3 -*/ + /* Zero GLCP_DELAY_CONTROLS MSR */ msr.hi = msr.lo = 0; - if (spdbyte0 == 0 || spdbyte1 == 0) { - /* one dimm solution */ - if (spdbyte1 == 0) { - msr.hi |= 0x000800000; - } - spdbyte0 += spdbyte1; - if (spdbyte0 > 8) { - /* large dimm */ - if (glspeed < 334) { - msr.hi |= 0x0837100AA; - msr.lo |= 0x056960004; - } else { - msr.hi |= 0x082710055; - msr.lo |= 0x056960004; - } - } else if (spdbyte0 > 4) { - /* medium dimm */ - if (glspeed < 334) { - msr.hi |= 0x0837100AA; - msr.lo |= 0x056960004; - } else { - msr.hi |= 0x0827100AA; - msr.lo |= 0x056960004; - } - } else { - /* small dimm */ - if (glspeed < 334) { - msr.hi |= 0x0837100FF; - msr.lo |= 0x056960004; - } else { - msr.hi |= 0x0827100FF; - msr.lo |= 0x056960004; - } - } - } else { - /* two dimm solution */ - spdbyte0 += spdbyte1; - if (spdbyte0 > 24) { - /* huge dimms */ - if (glspeed < 334) { - msr.hi |= 0x0B37100A5; - msr.lo |= 0x056960004; - } else { - msr.hi |= 0x0B2710000; - msr.lo |= 0x056960004; - } - } else if (spdbyte0 > 16) { - /* large dimms */ - if (glspeed < 334) { - msr.hi |= 0x0B37100A5; - msr.lo |= 0x056960004; - } else { - msr.hi |= 0x0B27100A5; - msr.lo |= 0x056960004; - } - } else if (spdbyte0 >= 8) { - /* medium dimms */ - if (glspeed < 334) { - msr.hi |= 0x0937100A5; - msr.lo |= 0x056960004; - } else { - msr.hi |= 0x0C27100A5; - msr.lo |= 0x056960004; - } - } else { - /* small dimms */ + /* Save some power, disable clock to second DIMM if it is empty. */ + if (spdbyte1 == 0) + msr.hi |= DELAY_UPPER_DISABLE_CLK135; + + spdbyte0 += spdbyte1; + + if ((dimms == 1) && (terminated == DRAM_TERMINATED)) { + msr.hi = 0xF2F100FF; + msr.lo = 0x56960004; + } else for (i = 0; i < ARRAY_SIZE(delay_control_table); i++) { + if ((dimms == delay_control_table[i].dimms) && + (spdbyte0 <= delay_control_table[i].devices)) { if (glspeed < 334) { - msr.hi |= 0x0837100A5; - msr.lo |= 0x056960004; + msr.hi |= delay_control_table[i].slow_hi; + msr.lo |= delay_control_table[i].slow_low; } else { - msr.hi |= 0x082710000; - msr.lo |= 0x056960004; + msr.hi |= delay_control_table[i].fast_hi; + msr.lo |= delay_control_table[i].fast_low; } + break; } } - print_debug("Try to write GLCP_DELAY_CONTROLS: hi "); - print_debug_hex32(msr.hi); - print_debug(" and lo "); - print_debug_hex32(msr.lo); - print_debug("\n"); wrmsr(GLCP_DELAY_CONTROLS, msr); - print_debug("SetDelayControl done\n"); - return; } /* ***************************************************************************/ /* * cpuRegInit*/ /* ***************************************************************************/ -void cpuRegInit(void) +void cpuRegInit(int debug_clock_disable, u8 dimm0, u8 dimm1, int terminated) { int msrnum; msr_t msr; @@ -259,7 +215,7 @@ void cpuRegInit(void) /* Set the Delay Control in GLCP */ print_debug("Set the Delay Control in GLCP\n"); - SetDelayControl(); + SetDelayControl(dimm0, dimm1, terminated); /* Enable RSDC */ print_debug("Enable RSDC\n"); @@ -294,12 +250,12 @@ void cpuRegInit(void) /* Disable the debug clock to save power. */ /* NOTE: leave it enabled for fs2 debug */ -#if 0 - msrnum = GLCP_DBGCLKCTL; - msr.hi = 0; - msr.lo = 0; - wrmsr(msrnum, msr); -#endif + if (debug_clock_disable && 0) { + msrnum = GLCP_DBGCLKCTL; + msr.hi = 0; + msr.lo = 0; + wrmsr(msrnum, msr); + } /* Setup throttling delays to proper mode if it is ever enabled. */ print_debug("Setup throttling delays to proper mode\n"); diff --git a/src/cpu/amd/model_lx/msrinit.c b/src/cpu/amd/model_lx/msrinit.c index 53c0a851dc..35c9ae4f25 100644 --- a/src/cpu/amd/model_lx/msrinit.c +++ b/src/cpu/amd/model_lx/msrinit.c @@ -18,13 +18,9 @@ */ #include +#include "cpu/x86/msr.h" -struct msrinit { - u32 msrnum; - msr_t msr; -}; - -static const struct msrinit msr_table[] = +static const msrinit_t msr_table[] = { {CPU_RCONF_DEFAULT, {.hi = 0x24fffc02,.lo = 0x1000A000}}, /* Setup access to cache under 1MB. * Rom Properties: Write Serialize, WriteProtect. @@ -49,7 +45,7 @@ static void msr_init(void) { int i; for (i = 0; i < ARRAY_SIZE(msr_table); i++) - wrmsr(msr_table[i].msrnum, msr_table[i].msr); + wrmsr(msr_table[i].index, msr_table[i].msr); } diff --git a/src/include/cpu/amd/lxdef.h b/src/include/cpu/amd/lxdef.h index d312c0e6da..16a22ba10f 100644 --- a/src/include/cpu/amd/lxdef.h +++ b/src/include/cpu/amd/lxdef.h @@ -623,9 +623,16 @@ #define SMM_OFFSET 0x80400000 /* above 2GB */ #define SMM_SIZE 128 /* changed SMM_SIZE from 256 KB to 128 KB */ +/* DRAM_TERMINATED affects how the DELAY register is set. */ +#define DRAM_TERMINATED 'T' +#define DRAM_UNTERMINATED 't' +/* Bitfield definitions for the DELAY register */ +#define DELAY_UPPER_DISABLE_CLK135 (1 << 23) +#define DELAY_LOWER_STATUS_MASK 0x7C0 + #if !defined(__ROMCC__) && !defined(ASSEMBLY) #if defined(__PRE_RAM__) -void cpuRegInit(void); +void cpuRegInit(int debug_clock_disable, u8 dimm0, u8 dimm1, int terminated); void SystemPreInit(void); #endif void cpubug(void); diff --git a/src/include/cpu/x86/msr.h b/src/include/cpu/x86/msr.h index daa7e18422..a201ef42f2 100644 --- a/src/include/cpu/x86/msr.h +++ b/src/include/cpu/x86/msr.h @@ -23,6 +23,12 @@ typedef struct msr_struct unsigned hi; } msr_t; +typedef struct msrinit_struct +{ + unsigned index; + msr_t msr; +} msrinit_t; + static inline msr_t rdmsr(unsigned index) { msr_t result; diff --git a/src/mainboard/amd/db800/romstage.c b/src/mainboard/amd/db800/romstage.c index 893e73dd4a..48b3ede433 100644 --- a/src/mainboard/amd/db800/romstage.c +++ b/src/mainboard/amd/db800/romstage.c @@ -44,8 +44,8 @@ static inline int spd_read_byte(unsigned int device, unsigned int address) } #define ManualConf 0 /* Do automatic strapped PLL config */ -#define PLLMSRhi 0x00001490 /* Manual settings for the PLL */ -#define PLLMSRlo 0x02000030 +#define PLLMSRhi 0x000005DD /* Manual settings for the PLL */ +#define PLLMSRlo 0x00DE60EE #define DIMM0 0xA0 #define DIMM1 0xA2 @@ -88,7 +88,7 @@ void main(unsigned long bist) pll_reset(ManualConf); - cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED); sdram_initialize(1, memctrl); diff --git a/src/mainboard/amd/norwich/romstage.c b/src/mainboard/amd/norwich/romstage.c index 1cc020fd41..ff6621964f 100644 --- a/src/mainboard/amd/norwich/romstage.c +++ b/src/mainboard/amd/norwich/romstage.c @@ -19,6 +19,7 @@ */ #include +#include #include #include #include @@ -88,7 +89,7 @@ void main(unsigned long bist) pll_reset(ManualConf); - cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED); sdram_initialize(1, memctrl); diff --git a/src/mainboard/artecgroup/dbe61/romstage.c b/src/mainboard/artecgroup/dbe61/romstage.c index 48be6820c7..4e9c9788f7 100644 --- a/src/mainboard/artecgroup/dbe61/romstage.c +++ b/src/mainboard/artecgroup/dbe61/romstage.c @@ -109,7 +109,7 @@ void main(unsigned long bist) pll_reset(ManualConf); - cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED); sdram_initialize(1, memctrl); diff --git a/src/mainboard/digitallogic/msm800sev/romstage.c b/src/mainboard/digitallogic/msm800sev/romstage.c index 0a9b6dfe98..07c4c4d438 100644 --- a/src/mainboard/digitallogic/msm800sev/romstage.c +++ b/src/mainboard/digitallogic/msm800sev/romstage.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -69,7 +70,7 @@ void main(unsigned long bist) pll_reset(ManualConf); - cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED); sdram_initialize(1, memctrl); diff --git a/src/mainboard/iei/pcisa-lx-800-r10/romstage.c b/src/mainboard/iei/pcisa-lx-800-r10/romstage.c index b41b82ba7c..35d16eaac2 100644 --- a/src/mainboard/iei/pcisa-lx-800-r10/romstage.c +++ b/src/mainboard/iei/pcisa-lx-800-r10/romstage.c @@ -19,6 +19,7 @@ */ #include +#include #include #include #include @@ -92,7 +93,7 @@ void main(unsigned long bist) pll_reset(ManualConf); - cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED); sdram_initialize(1, memctrl); diff --git a/src/mainboard/lippert/roadrunner-lx/romstage.c b/src/mainboard/lippert/roadrunner-lx/romstage.c index 9123052452..767b42f2d3 100644 --- a/src/mainboard/lippert/roadrunner-lx/romstage.c +++ b/src/mainboard/lippert/roadrunner-lx/romstage.c @@ -122,7 +122,7 @@ void main(unsigned long bist) pll_reset(ManualConf); - cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED); sdram_initialize(1, memctrl); diff --git a/src/mainboard/lippert/spacerunner-lx/romstage.c b/src/mainboard/lippert/spacerunner-lx/romstage.c index b9b0e4f048..a62ad91c0e 100644 --- a/src/mainboard/lippert/spacerunner-lx/romstage.c +++ b/src/mainboard/lippert/spacerunner-lx/romstage.c @@ -184,7 +184,7 @@ void main(unsigned long bist) pll_reset(ManualConf); - cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED); /* bit1 = on-board IDE is slave, bit0 = Spread Spectrum */ if ((err = smc_send_config(SMC_CONFIG))) { diff --git a/src/mainboard/pcengines/alix1c/romstage.c b/src/mainboard/pcengines/alix1c/romstage.c index ee101b944f..6ec9557aac 100644 --- a/src/mainboard/pcengines/alix1c/romstage.c +++ b/src/mainboard/pcengines/alix1c/romstage.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -148,7 +149,7 @@ void main(unsigned long bist) pll_reset(ManualConf); - cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED); sdram_initialize(1, memctrl); diff --git a/src/mainboard/traverse/geos/romstage.c b/src/mainboard/traverse/geos/romstage.c index 40501a95e0..cfdbde9b1f 100644 --- a/src/mainboard/traverse/geos/romstage.c +++ b/src/mainboard/traverse/geos/romstage.c @@ -88,7 +88,7 @@ void main(unsigned long bist) pll_reset(ManualConf); - cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED); sdram_initialize(1, memctrl); diff --git a/src/mainboard/winent/pl6064/romstage.c b/src/mainboard/winent/pl6064/romstage.c index f6d969681f..12945e3fdd 100644 --- a/src/mainboard/winent/pl6064/romstage.c +++ b/src/mainboard/winent/pl6064/romstage.c @@ -90,7 +90,7 @@ void main(unsigned long bist) pll_reset(ManualConf); - cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED); sdram_initialize(1, memctrl); -- cgit v1.2.3