This commit updates the Geode LX GLCP delay control setup from the v2 way to the...
authorEdwin Beasant <edwin_beasant@virtensys.com>
Thu, 10 Jun 2010 15:24:57 +0000 (15:24 +0000)
committerEdwin Beasant <edwin_beasant@virtensys.com>
Thu, 10 Jun 2010 15:24:57 +0000 (15:24 +0000)
This resolves problems with terminated DRAM modules.
Signed-off-by: Edwin Beasant <edwin_beasant@virtensys.com>
Acked-by: Roland G. Minnich <rminnich@gmail.com>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5629 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1

14 files changed:
src/cpu/amd/model_lx/cpureginit.c
src/cpu/amd/model_lx/msrinit.c
src/include/cpu/amd/lxdef.h
src/include/cpu/x86/msr.h
src/mainboard/amd/db800/romstage.c
src/mainboard/amd/norwich/romstage.c
src/mainboard/artecgroup/dbe61/romstage.c
src/mainboard/digitallogic/msm800sev/romstage.c
src/mainboard/iei/pcisa-lx-800-r10/romstage.c
src/mainboard/lippert/roadrunner-lx/romstage.c
src/mainboard/lippert/spacerunner-lx/romstage.c
src/mainboard/pcengines/alix1c/romstage.c
src/mainboard/traverse/geos/romstage.c
src/mainboard/winent/pl6064/romstage.c

index 62fa973a8c021f37a4ddaeb988de29c139333b58..6e7de84c6abec3bf848ab5954253b563c6b83972 100644 (file)
@@ -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.
 ;*     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");
index 53c0a851dcba300224d371333c42803c8b1af030..35c9ae4f250938867ecece2e31586925ceaa0ee4 100644 (file)
  */
 
 #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 @@ 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);
 }
 
 
index d312c0e6da462994a5cbc9028182b690438142b1..16a22ba10f863ab0ef0298d984a81efe06d68718 100644 (file)
 #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);
index daa7e184224fca2e03e51d74615fc154c2328945..a201ef42f2ab7033618680fb6c9a3262c5dd57e2 100644 (file)
@@ -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;
index 893e73dd4a4038da270d3956764bbc4c7251343b..48b3ede433b55addd3e56079dc96d5c13473ac07 100644 (file)
@@ -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);
 
index 1cc020fd416a1f26e4fcd5f2422f5900b623f976..ff6621964f2894e45bdb307373d09d00fcadc5d8 100644 (file)
@@ -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 @@ void main(unsigned long bist)
 
        pll_reset(ManualConf);
 
-       cpuRegInit();
+       cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED);
 
        sdram_initialize(1, memctrl);
 
index 48be6820c7ef1970f68b54e1f903c5548077fae9..4e9c9788f731242b0121323520374dcceb05fe06 100644 (file)
@@ -109,7 +109,7 @@ void main(unsigned long bist)
 
        pll_reset(ManualConf);
 
-       cpuRegInit();
+       cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED);
 
        sdram_initialize(1, memctrl);
 
index 0a9b6dfe98b5a2daf69334bc17a141c424fc06b1..07c4c4d43875f0463d051c8b192aaf2b9514e976 100644 (file)
@@ -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 @@ void main(unsigned long bist)
 
        pll_reset(ManualConf);
 
-       cpuRegInit();
+       cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED);
 
        sdram_initialize(1, memctrl);
 
index b41b82ba7cdc0f8d822820d70fdcf45884ecabc3..35d16eaac2558fab583570397de63ddc9f8f2a67 100644 (file)
@@ -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 @@ void main(unsigned long bist)
 
        pll_reset(ManualConf);
 
-       cpuRegInit();
+       cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED);
 
        sdram_initialize(1, memctrl);
 
index 91230524521a1ec9e7eef25863ce4c5ec70c5dc4..767b42f2d38e59d6ba2a213cf9e2f2f0ad6988b2 100644 (file)
@@ -122,7 +122,7 @@ void main(unsigned long bist)
 
        pll_reset(ManualConf);
 
-       cpuRegInit();
+       cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED);
 
        sdram_initialize(1, memctrl);
 
index b9b0e4f048119faf3e979093df50cded41066664..a62ad91c0eada81c2f127c2adab1ed6398604855 100644 (file)
@@ -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))) {
index ee101b944f4200b51d483332c465538f0ec4de9f..6ec9557aac16d184e53c6e9ef6ac0396ef3fc9e4 100644 (file)
@@ -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 @@ void main(unsigned long bist)
 
        pll_reset(ManualConf);
 
-       cpuRegInit();
+       cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED);
 
        sdram_initialize(1, memctrl);
 
index 40501a95e04938da8f69eaf5b381f8cd258922d9..cfdbde9b1fedac0ee4041f77bdab10468e668a1d 100644 (file)
@@ -88,7 +88,7 @@ void main(unsigned long bist)
 
        pll_reset(ManualConf);
 
-       cpuRegInit();
+       cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED);
 
        sdram_initialize(1, memctrl);
 
index f6d969681f85ea9580030d9155a1adf0f96e2d51..12945e3fddffe698cbab5cd61b38c2fa9af7e96a 100644 (file)
@@ -90,7 +90,7 @@ void main(unsigned long bist)
 
        pll_reset(ManualConf);
 
-       cpuRegInit();
+       cpuRegInit(0, DIMM0, DIMM1, DRAM_TERMINATED);
 
        sdram_initialize(1, memctrl);