Author: monofin Date: Thu Jun 10 17:24:57 2010 New Revision: 5629 URL: https://tracker.coreboot.org/trac/coreboot/changeset/5629
Log: 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 edwin_beasant@virtensys.com Acked-by: Roland G. Minnich rminnich@gmail.com
Modified: trunk/src/cpu/amd/model_lx/cpureginit.c trunk/src/cpu/amd/model_lx/msrinit.c trunk/src/include/cpu/amd/lxdef.h trunk/src/include/cpu/x86/msr.h trunk/src/mainboard/amd/db800/romstage.c trunk/src/mainboard/amd/norwich/romstage.c trunk/src/mainboard/artecgroup/dbe61/romstage.c trunk/src/mainboard/digitallogic/msm800sev/romstage.c trunk/src/mainboard/iei/pcisa-lx-800-r10/romstage.c trunk/src/mainboard/lippert/roadrunner-lx/romstage.c trunk/src/mainboard/lippert/spacerunner-lx/romstage.c trunk/src/mainboard/pcengines/alix1c/romstage.c trunk/src/mainboard/traverse/geos/romstage.c trunk/src/mainboard/winent/pl6064/romstage.c
Modified: trunk/src/cpu/amd/model_lx/cpureginit.c ============================================================================== --- trunk/src/cpu/amd/model_lx/cpureginit.c Thu Jun 10 06:06:52 2010 (r5628) +++ trunk/src/cpu/amd/model_lx/cpureginit.c Thu Jun 10 17:24:57 2010 (r5629) @@ -1,6 +1,6 @@ /* * This file is part of the coreboot project. - * + * * Copyright (C) 2006 Indrek Kruusa indrek.kruusa@artecdesign.ee * Copyright (C) 2006 Ronald G. Minnich rminnich@gmail.com * 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 @@
/* 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 @@
/* 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");
Modified: trunk/src/cpu/amd/model_lx/msrinit.c ============================================================================== --- trunk/src/cpu/amd/model_lx/msrinit.c Thu Jun 10 06:06:52 2010 (r5628) +++ trunk/src/cpu/amd/model_lx/msrinit.c Thu Jun 10 17:24:57 2010 (r5629) @@ -18,13 +18,9 @@ */
#include <stdlib.h> +#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 @@ { 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); }
Modified: trunk/src/include/cpu/amd/lxdef.h ============================================================================== --- trunk/src/include/cpu/amd/lxdef.h Thu Jun 10 06:06:52 2010 (r5628) +++ trunk/src/include/cpu/amd/lxdef.h Thu Jun 10 17:24:57 2010 (r5629) @@ -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);
Modified: trunk/src/include/cpu/x86/msr.h ============================================================================== --- trunk/src/include/cpu/x86/msr.h Thu Jun 10 06:06:52 2010 (r5628) +++ trunk/src/include/cpu/x86/msr.h Thu Jun 10 17:24:57 2010 (r5629) @@ -23,6 +23,12 @@ 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;
Modified: trunk/src/mainboard/amd/db800/romstage.c ============================================================================== --- trunk/src/mainboard/amd/db800/romstage.c Thu Jun 10 06:06:52 2010 (r5628) +++ trunk/src/mainboard/amd/db800/romstage.c Thu Jun 10 17:24:57 2010 (r5629) @@ -44,8 +44,8 @@ }
#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 @@
pll_reset(ManualConf);
- cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED);
sdram_initialize(1, memctrl);
Modified: trunk/src/mainboard/amd/norwich/romstage.c ============================================================================== --- trunk/src/mainboard/amd/norwich/romstage.c Thu Jun 10 06:06:52 2010 (r5628) +++ trunk/src/mainboard/amd/norwich/romstage.c Thu Jun 10 17:24:57 2010 (r5629) @@ -19,6 +19,7 @@ */
#include <stdint.h> +#include <stdlib.h> #include <device/pci_def.h> #include <arch/io.h> #include <device/pnp_def.h> @@ -88,7 +89,7 @@
pll_reset(ManualConf);
- cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED);
sdram_initialize(1, memctrl);
Modified: trunk/src/mainboard/artecgroup/dbe61/romstage.c ============================================================================== --- trunk/src/mainboard/artecgroup/dbe61/romstage.c Thu Jun 10 06:06:52 2010 (r5628) +++ trunk/src/mainboard/artecgroup/dbe61/romstage.c Thu Jun 10 17:24:57 2010 (r5629) @@ -109,7 +109,7 @@
pll_reset(ManualConf);
- cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED);
sdram_initialize(1, memctrl);
Modified: trunk/src/mainboard/digitallogic/msm800sev/romstage.c ============================================================================== --- trunk/src/mainboard/digitallogic/msm800sev/romstage.c Thu Jun 10 06:06:52 2010 (r5628) +++ trunk/src/mainboard/digitallogic/msm800sev/romstage.c Thu Jun 10 17:24:57 2010 (r5629) @@ -1,4 +1,5 @@ #include <stdint.h> +#include <stdlib.h> #include <device/pci_def.h> #include <arch/io.h> #include <device/pnp_def.h> @@ -69,7 +70,7 @@
pll_reset(ManualConf);
- cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED);
sdram_initialize(1, memctrl);
Modified: trunk/src/mainboard/iei/pcisa-lx-800-r10/romstage.c ============================================================================== --- trunk/src/mainboard/iei/pcisa-lx-800-r10/romstage.c Thu Jun 10 06:06:52 2010 (r5628) +++ trunk/src/mainboard/iei/pcisa-lx-800-r10/romstage.c Thu Jun 10 17:24:57 2010 (r5629) @@ -19,6 +19,7 @@ */
#include <stdint.h> +#include <stdlib.h> #include <device/pci_def.h> #include <arch/io.h> #include <device/pnp_def.h> @@ -92,7 +93,7 @@
pll_reset(ManualConf);
- cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED);
sdram_initialize(1, memctrl);
Modified: trunk/src/mainboard/lippert/roadrunner-lx/romstage.c ============================================================================== --- trunk/src/mainboard/lippert/roadrunner-lx/romstage.c Thu Jun 10 06:06:52 2010 (r5628) +++ trunk/src/mainboard/lippert/roadrunner-lx/romstage.c Thu Jun 10 17:24:57 2010 (r5629) @@ -122,7 +122,7 @@
pll_reset(ManualConf);
- cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED);
sdram_initialize(1, memctrl);
Modified: trunk/src/mainboard/lippert/spacerunner-lx/romstage.c ============================================================================== --- trunk/src/mainboard/lippert/spacerunner-lx/romstage.c Thu Jun 10 06:06:52 2010 (r5628) +++ trunk/src/mainboard/lippert/spacerunner-lx/romstage.c Thu Jun 10 17:24:57 2010 (r5629) @@ -184,7 +184,7 @@
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))) {
Modified: trunk/src/mainboard/pcengines/alix1c/romstage.c ============================================================================== --- trunk/src/mainboard/pcengines/alix1c/romstage.c Thu Jun 10 06:06:52 2010 (r5628) +++ trunk/src/mainboard/pcengines/alix1c/romstage.c Thu Jun 10 17:24:57 2010 (r5629) @@ -18,6 +18,7 @@ */
#include <stdint.h> +#include <stdlib.h> #include <spd.h> #include <device/pci_def.h> #include <arch/io.h> @@ -148,7 +149,7 @@
pll_reset(ManualConf);
- cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED);
sdram_initialize(1, memctrl);
Modified: trunk/src/mainboard/traverse/geos/romstage.c ============================================================================== --- trunk/src/mainboard/traverse/geos/romstage.c Thu Jun 10 06:06:52 2010 (r5628) +++ trunk/src/mainboard/traverse/geos/romstage.c Thu Jun 10 17:24:57 2010 (r5629) @@ -88,7 +88,7 @@
pll_reset(ManualConf);
- cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED);
sdram_initialize(1, memctrl);
Modified: trunk/src/mainboard/winent/pl6064/romstage.c ============================================================================== --- trunk/src/mainboard/winent/pl6064/romstage.c Thu Jun 10 06:06:52 2010 (r5628) +++ trunk/src/mainboard/winent/pl6064/romstage.c Thu Jun 10 17:24:57 2010 (r5629) @@ -90,7 +90,7 @@
pll_reset(ManualConf);
- cpuRegInit(); + cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED);
sdram_initialize(1, memctrl);