remove trailing whitespace
[coreboot.git] / src / cpu / amd / model_lx / cpureginit.c
index 58576c2fcd2627742f2b0415da4cbb1a791cc155..bad98b51bfa44834be8f59c02c4bf48ceb02d1b9 100644 (file)
-
-
-/* ***************************************************************************/
-/* **/
-/* *   BIST */
-/* **/
-/* *   GX2 BISTs need to be run before BTB or caches are enabled.*/
-/* *   BIST result left in registers on failure to be checked with FS2.*/
-/* **/
-/* ***************************************************************************/
-static void
-BIST(void){
-       int msrnum;
+/*
+ * 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.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+/**************************************************************************
+;*
+;*     SetDelayControl
+;*
+;*************************************************************************/
+#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)
+{
+       u32 glspeed;
+       u8 spdbyte0, spdbyte1, dimms, i;
        msr_t msr;
 
-       /* DM*/
-       msrnum = CPU_DM_CONFIG0;
-       msr = rdmsr(msrnum);
-       msr.lo |=  DM_CONFIG0_LOWER_DCDIS_SET;
-       wrmsr(msrnum, msr);
-       
-       msr.lo =  0x00000003F;
-       msr.hi =  0x000000000;
-       msrnum = CPU_DM_BIST;
-       wrmsr(msrnum, msr);
+       glspeed = GeodeLinkSpeed();
 
-       outb(POST_CPU_DM_BIST_FAILURE, 0x80);                           /* 0x29*/
-       msr = rdmsr(msrnum);                                            /* read back for pass fail*/
-       msr.lo &= 0x0F3FF0000;
-       if (msr.lo != 0xfeff0000)
-               goto BISTFail;
-       msrnum = CPU_DM_CONFIG0;
-       msr = rdmsr(msrnum);
-       msr.lo &=  ~ DM_CONFIG0_LOWER_DCDIS_SET;
-       wrmsr(msrnum, msr);
-
-       /* FPU*/
-       msr.lo =  0x000000131;
-       msr.hi = 0;
-       msrnum = CPU_FP_UROM_BIST;
-       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);
 
-       outb(POST_CPU_FPU_BIST_FAILURE, 0x80);                          /* 0x89*/
-       inb(0x80);                                                                      /*  IO delay*/
-       msr = rdmsr(msrnum);                                                    /* read back for pass fail*/
-       while ((msr.lo&0x884) != 0x884)
-               msr = rdmsr(msrnum);                                    /*  Endless loop if BIST is broken*/
-       if ((msr.lo&0x642) != 0x642)
-               goto BISTFail;
+       msr = rdmsr(GLCP_FIFOCTL);
+       msr.hi = 0x00000005;
+       wrmsr(GLCP_FIFOCTL, msr);
 
-       msr.lo = msr.hi = 0;                            /*  clear FPU BIST bits*/
-       msrnum = CPU_FP_UROM_BIST;
-       wrmsr(msrnum, msr);
-
-
-       /* BTB*/
-       msr.lo =  0x000000303;
-       msr.hi =  0x000000000;
-       msrnum = CPU_PF_BTBRMA_BIST;
-       wrmsr(msrnum, msr);
-
-       outb(POST_CPU_BTB_BIST_FAILURE  , 0x80);                                /* 0x8A*/
-       msr = rdmsr(msrnum);                                                    /* read back for pass fail*/
-       if ((msr.lo & 0x3030) != 0x3030)
-               goto BISTFail;
+       /* Enable setting. */
+       msr.hi = 0;
+       msr.lo = 0x00000001;
+       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.
+        */
+       msr = rdmsr(GLCP_DELAY_CONTROLS);
+       if (msr.lo & ~(DELAY_LOWER_STATUS_MASK))
+               return;
+
+       /* 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.
+        */
+       dimms = 0;
+       spdbyte0 = spd_read_byte(dimm0, SPD_PRIMARY_SDRAM_WIDTH);
+       if (spdbyte0 != 0xFF) {
+               dimms++;
+               spdbyte0 = (u8)64 / spdbyte0 *
+                          (u8)(spd_read_byte(dimm0, SPD_NUM_DIMM_BANKS));
+       } else {
+               spdbyte0 = 0;
+       }
 
-       return;
+       spdbyte1 = spd_read_byte(dimm1, SPD_PRIMARY_SDRAM_WIDTH);
+       if (spdbyte1 != 0xFF) {
+               dimms++;
+               spdbyte1 = (u8)64 / spdbyte1 *
+                          (u8)(spd_read_byte(dimm1, SPD_NUM_DIMM_BANKS));
+       } else {
+               spdbyte1 = 0;
+       }
 
-BISTFail:
-       print_err("BIST failed!\n");
-       while(1);
+       /* Zero GLCP_DELAY_CONTROLS MSR */
+       msr.hi = msr.lo = 0;
+
+       /* 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 |= delay_control_table[i].slow_hi;
+                               msr.lo |= delay_control_table[i].slow_low;
+                       } else {
+                               msr.hi |= delay_control_table[i].fast_hi;
+                               msr.lo |= delay_control_table[i].fast_low;
+                       }
+                       break;
+               }
+       }
+       wrmsr(GLCP_DELAY_CONTROLS, msr);
 }
+
 /* ***************************************************************************/
 /* *   cpuRegInit*/
 /* ***************************************************************************/
-void
-cpuRegInit (void){
+void cpuRegInit(int debug_clock_disable, u8 dimm0, u8 dimm1, int terminated)
+{
        int msrnum;
        msr_t msr;
-       
-       //GX3 suspend: what is desired?
 
-       /*  Enable Suspend on Halt*/
-       /*msrnum = CPU_XC_CONFIG;
+       /* Castle 2.0 BTM periodic sync period. */
+       /*      [40:37] 1 sync record per 256 bytes */
+       print_debug("Castle 2.0 BTM periodic sync period.\n");
+       msrnum = CPU_PF_CONF;
        msr = rdmsr(msrnum);
-       msr.lo |=  XC_CONFIG_SUSP_ON_HLT;
-       wrmsr(msrnum, msr);*/
+       msr.hi |= (0x8 << 5);
+       wrmsr(msrnum, msr);
 
-       /*  ENable SUSP and allow TSC to run in Suspend */
-       /*  to keep speed detection happy*/
-       /*msrnum = CPU_BC_CONF_0;
-       msr = rdmsr(msrnum);
-       msr.lo |=  TSC_SUSP_SET | SUSP_EN_SET;
-       wrmsr(msrnum, msr);*/
-
-       /*  Setup throttling to proper mode if it is ever enabled.*/
-       msrnum = 0x04C00001E;
-       msr.hi =  0x000000000;
-       msr.lo =  0x00000603C;
-       wrmsr(msrnum, msr);             // GX3 OK +/-
-
-
-/*  Only do this if we are building for 5535*/
-/* */
-/*  FooGlue Setup*/
-/* */
-#if 0
-       /*  Enable CIS mode B in FooGlue*/
-       msrnum = MSR_FG + 0x10;
+       /*
+        * LX performance setting.
+        * Enable Quack for fewer re-RAS on the MC
+        */
+       print_debug("Enable Quack for fewer re-RAS on the MC\n");
+       msrnum = GLIU0_ARB;
        msr = rdmsr(msrnum);
-       msr.lo &= ~3;
-       msr.lo |= 2;                    /*  ModeB*/
+       msr.hi &= ~ARB_UPPER_DACK_EN_SET;
+       msr.hi |= ARB_UPPER_QUACK_EN_SET;
        wrmsr(msrnum, msr);
-#endif
 
-/* */
-/*  Disable DOT PLL. Graphics init will enable it if needed.*/
-/* */
-
-// GX3: Disable DOT PLL? No. Lets tick.
-
-/*     msrnum = GLCP_DOTPLL;
+       msrnum = GLIU1_ARB;
        msr = rdmsr(msrnum);
-       msr.lo |= DOTPPL_LOWER_PD_SET;
-       wrmsr(msrnum, msr); */
+       msr.hi &= ~ARB_UPPER_DACK_EN_SET;
+       msr.hi |= ARB_UPPER_QUACK_EN_SET;
+       wrmsr(msrnum, msr);
 
-/* */
-/*  Enable RSDC*/
-/* */
-       msrnum = 0x1301 ;
+       /* GLIU port active enable, limit south pole masters
+        * (AES and PCI) to one outstanding transaction.
+        */
+       print_debug(" GLIU port active enable\n");
+       msrnum = GLIU1_PORT_ACTIVE;
        msr = rdmsr(msrnum);
-       msr.lo |=  0x08;
-       wrmsr(msrnum, msr);             //GX3 OK
-
-
-/* */
-/*  BIST*/
-/* */
-       /*if (getnvram( TOKEN_BIST_ENABLE) & == TVALUE_DISABLE) {*/
-       {
-//             BIST();
-       }
-
-
-/* */
-/*  Enable BTB*/
-/* */
-       /*  I hate to put this check here but it doesn't really work in cpubug.asm*/
+       msr.lo &= ~0x880;
+       wrmsr(msrnum, msr);
 
-//GX3: BTB is enabled by default
+       /* Set the Delay Control in GLCP */
+       print_debug("Set the Delay Control in GLCP\n");
+       SetDelayControl(dimm0, dimm1, terminated);
 
-/*     msrnum = MSR_GLCP+0x17;
+       /*  Enable RSDC */
+       print_debug("Enable RSDC\n");
+       msrnum = CPU_AC_SMM_CTL;
        msr = rdmsr(msrnum);
-       if (msr.lo >= CPU_REV_2_1){
-               msrnum = CPU_PF_BTB_CONF;
-               msr = rdmsr(msrnum);
-               msr.lo |= BTB_ENABLE_SET | RETURN_STACK_ENABLE_SET;
-               wrmsr(msrnum, msr);
-       }
-
-       */
-
-/* */
-/*  FPU impercise exceptions bit*/
-/* */
-       /*if (getnvram( TOKEN_FPU_IE_ENABLE) != TVALUE_DISABLE) {*/
-
-
-
-// GX3: FPU impercise exceptions bit - what's that?
-/*     {
-               msrnum = CPU_FPU_MSR_MODE;
-               msr = rdmsr(msrnum);
-               msr.lo |= FPU_IE_SET;
-               wrmsr(msrnum, msr);
-       }
-
-       */
-
-#if 0
-       /* */
-       /*  Cache Overides*/
-       /* */
-       /* This code disables the data cache.  Don't execute this
-        * unless you're testing something.
-        */ 
-       /*  Allow NVRam to override DM Setup*/
-       /*if (getnvram( TOKEN_CACHE_DM_MODE) != 1) {*/
-       {
-
-               msrnum = CPU_DM_CONFIG0;
-               msr = rdmsr(msrnum);
-               msr.lo |=  DM_CONFIG0_LOWER_DCDIS_SET;
-               wrmsr(msrnum, msr);
-       }
-       /* This code disables the instruction cache.  Don't execute
-        * this unless you're testing something.
-       */ 
-       /*  Allow NVRam to override IM Setup*/
-       /*if (getnvram( TOKEN_CACHE_IM_MODE) ==1) {*/
-       {
-               msrnum = CPU_IM_CONFIG;
-               msr = rdmsr(msrnum);
-               msr.lo |=  IM_CONFIG_LOWER_ICD_SET;
-               wrmsr(msrnum, msr);
-       }
-#endif
-}
-
-
-
-
-/* ***************************************************************************/
-/* **/
-/* *   MTestPinCheckBX*/
-/* **/
-/* *   Set MTEST pins to expected values from OPTIONS.INC/NVRAM*/
-/* *  This version is called when there isn't a stack available*/
-/* **/
-/* ***************************************************************************/
-static void
-MTestPinCheckBX (void){
-       int msrnum;
-       msr_t msr;
+       msr.lo |= SMM_INST_EN_SET;
+       wrmsr(msrnum, msr);
 
-       /*if (getnvram( TOKEN_MTEST_ENABLE) ==TVALUE_DISABLE ) {*/
-                       /* return ; */
-       /* } */
+       /* FPU imprecise exceptions bit */
+       print_debug("FPU imprecise exceptions bit\n");
+       msrnum = CPU_FPU_MSR_MODE;
+       msr = rdmsr(msrnum);
+       msr.lo |= FPU_IE_SET;
+       wrmsr(msrnum, msr);
 
-       /*  Turn on MTEST*/
-       msrnum = MC_CFCLK_DBUG;
+       /* Power Savers (Do after BIST) */
+       /* Enable Suspend on HLT & PAUSE instructions */
+       print_debug("Enable Suspend on HLT & PAUSE instructions\n");
+       msrnum = CPU_XC_CONFIG;
        msr = rdmsr(msrnum);
-       msr.hi |=  CFCLK_UPPER_MTST_B2B_DIS_SET | CFCLK_UPPER_MTEST_EN_SET;
+       msr.lo |= XC_CONFIG_SUSP_ON_HLT | XC_CONFIG_SUSP_ON_PAUSE;
        wrmsr(msrnum, msr);
 
-       msrnum = GLCP_SYS_RSTPLL                        /*  Get SDR/DDR mode from GLCP*/;
+       /* Enable SUSP and allow TSC to run in Suspend (keep speed detection happy) */
+       print_debug("Enable SUSP and allow TSC to run in Suspend\n");
+       msrnum = CPU_BC_CONF_0;
        msr = rdmsr(msrnum);
-       msr.lo >>=  RSTPPL_LOWER_SDRMODE_SHIFT;
-       if (msr.lo & 1) {
-               msrnum = MC_CFCLK_DBUG;                 /*  Turn on SDR MTEST stuff*/
-               msr = rdmsr(msrnum);
-               msr.lo |=  CFCLK_LOWER_SDCLK_SET;
-               msr.hi |=  CFCLK_UPPER_MTST_DQS_EN_SET;
+       msr.lo |= TSC_SUSP_SET | SUSP_EN_SET;
+       msr.lo &= 0x0F0FFFFFF;
+       msr.lo |= 0x002000000;  /* PBZ213: Set PAUSEDLY = 2 */
+       wrmsr(msrnum, msr);
+
+       /* Disable the debug clock to save power. */
+       /* NOTE: leave it enabled for fs2 debug */
+       if (debug_clock_disable && 0) {
+               msrnum = GLCP_DBGCLKCTL;
+               msr.hi = 0;
+               msr.lo = 0;
                wrmsr(msrnum, msr);
        }
 
-       /*  Lock the cache down here.*/
-       __asm__("wbinvd\n");
-
+       /* Setup throttling delays to proper mode if it is ever enabled. */
+       print_debug("Setup throttling delays to proper mode\n");
+       msrnum = GLCP_TH_OD;
+       msr.hi = 0;
+       msr.lo = 0x00000603C;
+       wrmsr(msrnum, msr);
+       print_debug("Done cpuRegInit\n");
 }