Since some people disapprove of white space cleanups mixed in regular commits
[coreboot.git] / src / northbridge / amd / gx2 / pll_reset.c
index 0e3a3caf95f7ab7f50595f7ccdcae8e066f5b6cd..c1b22a28a0428f074dcbd4c36a9c3bea37362962 100644 (file)
@@ -86,34 +86,167 @@ static const unsigned char fbdiv2plldiv[] = {
        49, 40, 19, 59, 32, 54, 35,  0, 41, 60, 55,  0, 61,  0,  0,  0
 };
 
-#if 1
-static void get_memory_speed(void)
+static const unsigned char pci33_ddr_crt [] = {
+       /* FbDIV, VDIV, MDIV               CPU/GeodeLink */
+            12,    2,    3,            // 200/133
+            16,    2,    3,            // 266/177
+             18,    2,    3,           // 300/200
+             20,    2,    3,           // 333/222
+             22,    2,    3,           // 366/244
+             24,    2,    3,           // 400/266
+             26,    2,    3             // 433/289
+};
+
+#if 0
+static unsigned int get_memory_speed(void)
 {
-       unsigned char val;
-
-       val = do_smbus_read_byte(0x6000, 0xA0, 0);
-       print_debug("SPD byte ");
-       print_debug_hex8(0);
-       print_debug(" = ");
-       print_debug_hex8(val);
-       print_debug("\r\n");
-
-       val = do_smbus_read_byte(0x6000, 0xA0, 1);
-       print_debug("SPD byte ");
-       print_debug_hex8(1);
-       print_debug(" = ");
-       print_debug_hex8(val);
-       print_debug("\r\n");
-
-       val = do_smbus_read_byte(0x6000, 0xA0, 2);
-       print_debug("SPD byte ");
-       print_debug_hex8(2);
-       print_debug(" = ");
-       print_debug_hex8(val);
-       print_debug("\r\n");
+       unsigned char val, hi, lo;
+
+       val = spd_read_byte(0xA0, 9);
+       hi = (val >> 4) & 0x0f;
+       lo = val & 0x0f;
+
+       return 20000/(hi*10 + lo);
 }
 #endif
 
+#define USE_GOODRICH_VERSION 1
+
+#if USE_GOODRICH_VERSION
+///////////////////////////////////////////////////////////////////////////////
+// Goodrich Version of pll_reset
+
+// PLLCHECK_COMPLETED is the "we've already done this" flag
+#define PLLCHECK_COMPLETED (1 << RSTPLL_LOWER_SWFLAGS_SHIFT)
+
+#ifndef RSTPPL_LOWER_BYPASS_SET
+#define RSTPPL_LOWER_BYPASS_SET (1 << GLCP_SYS_RSTPLL_BYPASS)
+#endif // RSTPPL_LOWER_BYPASS_SET
+
+#define DEFAULT_MDIV   3
+#define DEFAULT_VDIV   2
+#define DEFAULT_FBDIV  22      // 366/244 ; 24 400/266 018 ;300/200
+
+static void pll_reset(void)
+{
+       msr_t msrGlcpSysRstpll;
+       unsigned MDIV_VDIV_FBDIV;
+       unsigned SyncBits;                      // store the sync bits in up ebx
+
+       // clear the Bypass bit
+
+       // If the straps say we are in bypass and the syspll is not AND there are no software
+       // bits set then FS2 or something set up the PLL and we should not change it.
+
+       msrGlcpSysRstpll = rdmsr(GLCP_SYS_RSTPLL);
+       msrGlcpSysRstpll.lo &= ~RSTPPL_LOWER_BYPASS_SET;
+       wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
+
+       // If the "we've already been here" flag is set, don't reconfigure the pll
+       if ( !(msrGlcpSysRstpll.lo & PLLCHECK_COMPLETED ) )
+       { // we haven't configured the PLL; do it now
+
+               // Store PCI33(0)/66(1), SDR(0)/DDR(1), and CRT(0)/TFT(1) in upper esi to get to the
+               // correct Strap Table.
+               post_code(POST_PLL_INIT);
+
+               // configure for DDR
+               msrGlcpSysRstpll.lo &= ~(1 << RSTPPL_LOWER_SDRMODE_SHIFT);
+               wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
+
+               // Use Manual settings
+               //      UseManual:
+               post_code(POST_PLL_MANUAL);
+
+               // DIV settings manually entered.
+               // ax = VDIV, upper eax = MDIV, upper ecx = FbDIV
+               // use gs and fs since we don't need them.
+
+               //      ProgramClocks:
+               // ax = VDIV, upper eax = MDIV, upper ecx = FbDIV
+               // move everything into ebx
+               // VDIV
+               MDIV_VDIV_FBDIV = ((DEFAULT_VDIV - 2) << RSTPLL_UPPER_VDIV_SHIFT);
+
+               // MDIV
+               MDIV_VDIV_FBDIV |= ((DEFAULT_MDIV - 2) << RSTPLL_UPPER_MDIV_SHIFT);
+
+               // FbDIV
+               MDIV_VDIV_FBDIV |= (plldiv2fbdiv[DEFAULT_FBDIV] << RSTPLL_UPPER_FBDIV_SHIFT);
+
+               // write GLCP_SYS_RSTPPL (GLCP reg 0x14) with clock values
+               msrGlcpSysRstpll.lo &= ~(1 << RSTPPL_LOWER_SDRMODE_SHIFT);
+               wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
+
+               msrGlcpSysRstpll.hi = MDIV_VDIV_FBDIV;
+               wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
+
+               // Set Reset, LockWait, and SW flag
+               //      DoReset:
+
+               // CheckSemiSync proc
+               // Check for Semi-Sync in GeodeLink and CPU.
+               // We need to do this here since the strap settings don't account for these bits.
+               SyncBits = 0;                   // store the sync bits in up ebx
+
+               // Check for Bypass mode.
+               if (msrGlcpSysRstpll.lo & RSTPPL_LOWER_BYPASS_SET)
+               {
+                       // If we are in BYPASS PCI may or may not be sync'd but CPU and GeodeLink will.
+                       SyncBits |= RSTPPL_LOWER_CPU_SEMI_SYNC_SET;
+               }
+               else
+               {
+                       //      CheckPCIsync:
+                       // If FBdiv/Mdiv is evenly divisible then set the PCI semi-sync. FB is always greater
+                       // look up the real divider... if we get a 0 we have serious problems
+                       if ( !(fbdiv2plldiv[((msrGlcpSysRstpll.hi >> RSTPLL_UPPER_FBDIV_SHIFT) & 0x3f)] %
+                               (((msrGlcpSysRstpll.hi >> RSTPLL_UPPER_MDIV_SHIFT) & 0x0F) + 2)) )
+                       {
+                               SyncBits |= RSTPPL_LOWER_PCI_SEMI_SYNC_SET;
+                       }
+
+                       //      CheckCPUSync:
+                       // If Vdiv/Mdiv is evenly divisible then set the CPU semi-sync.
+                       // CPU is always greater or equal.
+                       if (!((((msrGlcpSysRstpll.hi >> RSTPLL_UPPER_MDIV_SHIFT) & 0x07) + 2) %
+                               (((msrGlcpSysRstpll.hi >> RSTPLL_UPPER_VDIV_SHIFT) & 0x0F) + 2)))
+                       {
+                               SyncBits |= RSTPPL_LOWER_CPU_SEMI_SYNC_SET;
+                       }
+               }
+
+
+               //      SetSync:
+               msrGlcpSysRstpll.lo &= ~(RSTPPL_LOWER_PCI_SEMI_SYNC_SET | RSTPPL_LOWER_CPU_SEMI_SYNC_SET);
+               msrGlcpSysRstpll.lo |= SyncBits;
+               wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
+               // CheckSemiSync endp
+
+               // now we do the reset
+               // Set hold count to 99 (063h)
+               msrGlcpSysRstpll.lo &= ~(0x0FF << RSTPPL_LOWER_HOLD_COUNT_SHIFT);
+               msrGlcpSysRstpll.lo |=  (0x0DE << RSTPPL_LOWER_HOLD_COUNT_SHIFT);
+               msrGlcpSysRstpll.lo |=  PLLCHECK_COMPLETED;             // Say we are done
+               wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
+
+               // Don't want to use LOCKWAIT
+               msrGlcpSysRstpll.lo |= (RSTPPL_LOWER_PLL_RESET_SET + RSTPPL_LOWER_PD_SET);
+               msrGlcpSysRstpll.lo |= RSTPPL_LOWER_CHIP_RESET_SET;
+               wrmsr(GLCP_SYS_RSTPLL, msrGlcpSysRstpll);
+
+               // You should never get here..... The chip has reset.
+               post_code(POST_PLL_RESET_FAIL);
+               while (1);
+
+       } // we haven't configured the PLL; do it now
+
+}
+// End of Goodrich version of pll_reset
+///////////////////////////////////////////////////////////////////////////////
+
+#else // #if USE_GOODRICH_VERSION
+
 static void pll_reset(void)
 {
        msr_t msr;
@@ -125,52 +258,50 @@ static void pll_reset(void)
        print_debug("Cpu core is ");
        print_debug_hex32(cpu_core);
        print_debug("\n");
-       //get_memory_speed();
-       //msr = rdmsr(GLCP_SYS_RSTPLL);
-       msr = rdmsr(0x4c000014);
-       print_debug("4c000014 is ");
-       print_debug_hex32(msr.hi); print_debug(":"); print_debug_hex32(msr.lo); print_debug("\n");
-       if (msr.lo & (1 << GLCP_SYS_RSTPLL_BYPASS)) {
-               print_debug("disable PLL bypass\n\r");
 
-               msr.hi = 0x00001490;
-               msr.lo = 0x02000030;
+       msr = rdmsr(GLCP_SYS_RSTPLL);
+       if (msr.lo & (1 << GLCP_SYS_RSTPLL_BYPASS)) {
+#if 0
+               print_debug("MSR ");
+               print_debug_hex32(GLCP_SYS_RSTPLL);
+               print_debug("is ");
+               print_debug_hex32(msr.hi);
+               print_debug(":");
+               print_debug_hex32(msr.lo);
+
+               msr.hi = PLLMSRhi;
+               msr.lo = PLLMSRlo;
                wrmsr(GLCP_SYS_RSTPLL, msr);
-               msr.lo |= ((0xde << 16) | (1 << 26) | (1 << 24));
+               msr.lo |= PLLMSRlo1;
                wrmsr(GLCP_SYS_RSTPLL, msr);
 
-               print_debug("Reset PLL\n\r");
+               print_debug("Reset PLL\n");
 
-               msr.lo |= ((1<<14) |(1<<13) | (1<<0));
+               msr.lo |= PLLMSRlo2;
                wrmsr(GLCP_SYS_RSTPLL,msr);
-               print_debug("should not be here\n\r");
+               print_debug("should not be here\n");
+#endif
+               print_err("shit");
+               while (1)
+                       ;
        }
 
        if (msr.lo & GLCP_SYS_RSTPLL_SWFLAGS_MASK) {
                /* PLL is already set and we are reboot from PLL reset */
-               print_debug("reboot from BIOS reset\n\r");
+               print_debug("reboot from BIOS reset\n");
                return;
        }
 
-       print_debug("prgramming PLL\n\r");
-
+       /* get the sysref clock rate */
        vdiv  = (msr.hi >> GLCP_SYS_RSTPLL_VDIV_SHIFT) & 0x07;
        vdiv += 2;
        fbdiv = (msr.hi >> GLCP_SYS_RSTPLL_FBDIV_SHIFT) & 0x3f;
        fbdiv = fbdiv2plldiv[fbdiv];
-
        spll_raw = cpu_core * vdiv;
        sysref   = spll_raw / fbdiv;
 
-       print_debug("SYSREF/PCI Clock ");
-       print_debug_hex32(sysref);
-       print_debug("\n\r");
-
+       /* get target memory rate by SPD */
        //gliu = get_memory_speed();
-       //get_memory_speed();
-       //print_debug("Target Memory Clock ");
-       //print_debug_hex32(gliu);
-       //print_debug("\n\r");
 
        msr.hi = 0x00000019;
        msr.lo = 0x06de0378;
@@ -178,10 +309,11 @@ static void pll_reset(void)
        msr.lo |= ((0xde << 16) | (1 << 26) | (1 << 24));
        wrmsr(0x4c000014, msr);
 
-       print_debug("Reset PLL\n\r");
+       print_debug("Reset PLL\n");
 
        msr.lo |= ((1<<14) |(1<<13) | (1<<0));
        wrmsr(0x4c000014,msr);
 
-       print_debug("should not be here\n\r");
+       print_debug("should not be here\n");
 }
+#endif // #if USE_GOODRICH_VERSION