The code is tested on my board with register DIMMs. More tests need to be
authorZheng Bao <zheng.bao@amd.com>
Mon, 17 Jan 2011 02:20:33 +0000 (02:20 +0000)
committerZheng Bao <Zheng.Bao@amd.com>
Mon, 17 Jan 2011 02:20:33 +0000 (02:20 +0000)
done. Please send the testing report.

Note: The pDCTstat->PresetmaxFreq in mctGet_MaxLoadFreq() should be set
to a higher limit, otherwise the frequnce will be set as 400MHz.

Signed-off-by: Zheng Bao <zheng.bao@amd.com>
Acked-by: Scott Duplichan <scott@notabs.org>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6258 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1

src/northbridge/amd/amdmct/mct_ddr3/mctwl.c
src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c

index 57d56814c1acbc702f56ac2de61070bab35ce9ca..2e749f8cd4ea5cc5ef841abbe437b0298e0b5239 100644 (file)
@@ -342,7 +342,21 @@ void SetTargetFreq(struct MCTStatStruc *pMCTstat,
        mct_Wait(250);
 
        if (pDCTstat->Status & (1 << SB_Registered)) {
-               /* TODO: Assuming the dct==0. The agesa here is confusing. */
+               u8 DCT0Present, DCT1Present;
+
+               DCT0Present = pDCTstat->DIMMValidDCT[0];
+               if (pDCTstat->GangedMode)
+                       DCT1Present = 0;
+               else
+                       DCT1Present = pDCTstat->DIMMValidDCT[1];
+
+               if (!DCT1Present)
+                       pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0];
+               else if (pDCTstat->GangedMode) {
+                       pDCTstat->CSPresent = 0;
+               } else
+                       pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[1];
+
                FreqChgCtrlWrd(pMCTstat, pDCTstat);
        }
 }
index d46a4c619982c2ff87959b219cd203948c79c7f3..af69064ddf458cb4e17a1c41c63f310c20199ca7 100644 (file)
@@ -86,7 +86,7 @@ void AgesaHwWlPhase1(sMCTStruct *pMCTData, sDCTStruct *pDCTData,
        procConifg(pMCTData,pDCTData, dimm, pass);
        /* 5. Begin write levelization training:
         *  Program F2x[1, 0]9C_x08[WrtLevelTrEn]=1. */
-       if (pDCTData->LogicalCPUID & AMD_DR_Cx)
+       if (pDCTData->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Dx))
                set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT,
                                DRAM_ADD_DCT_PHY_CONTROL_REG, WrtLvTrEn, WrtLvTrEn, 1);
        else
@@ -656,9 +656,9 @@ void procConifg(sMCTStruct *pMCTData,sDCTStruct *pDCTData, u8 dimm, u8 pass)
        programODT(pMCTData, pDCTData, dimm);
 
        /* Program F2x[1,0]9C_x08[WrLvOdtEn]=1 */
-       if (pDCTData->LogicalCPUID & AMD_DR_Cx)
+       if (pDCTData->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Dx))
                set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT,
-                               DRAM_ADD_DCT_PHY_CONTROL_REG, WrLvOdtEn, WrLvOdtEn,(u32) 1);
+                               DRAM_ADD_DCT_PHY_CONTROL_REG, WrLvOdtEn, WrLvOdtEn, (u32)1);
        else
        {
                /* Program WrLvOdtEn=1 through set bit 12 of D3CSODT reg offset 0 for Rev.B*/
@@ -722,7 +722,36 @@ void procConifg(sMCTStruct *pMCTData,sDCTStruct *pDCTData, u8 dimm, u8 pass)
                        pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Fine;
                        ByteLane++;
                }
+       } else if (pDCTData->Status[DCT_STATUS_REGISTERED]) {           /* For Pass 2 */
+               /* From BKDG, Write Leveling Seed Value. */
+               /* TODO: The unbuffered DIMMs are unstable on the code below. So temporarily it is
+                * only for registered DIMMs. */
+               u32 RegisterDelay, SeedTotal;
+               u8 MemClkFreq;
+               u16 freq_tab[] = {400, 533, 667, 800};
+               while(ByteLane < MAX_BYTE_LANES)
+               {
+                       MemClkFreq = get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
+                                             FUN_DCT, DRAM_CONFIG_HIGH, 0, 2);
+                       if (pDCTData->Status[DCT_STATUS_REGISTERED])
+                               RegisterDelay = 0x20; /* TODO: ((RCW2 & BIT0) == 0) ? 0x20 : 0x30; */
+                       else
+                               RegisterDelay = 0;
+                       SeedTotal = (pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] & 0x1F) |
+                               pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] << 5;
+                       /* SeedTotalPreScaling = (the total delay value in F2x[1, 0]9C_x[4A:30] from pass 1 of write levelization
+                          training) - RegisterDelay. */
+                       /* MemClkFreq: 3: 400Mhz; 4: 533Mhz; 5: 667Mhz; 6: 800Mhz */
+                       SeedTotal = (u16) (RegisterDelay + ((((u32) SeedTotal - RegisterDelay) *
+                                                            freq_tab[MemClkFreq-3]) / 400));
+                       Seed_Gross = (SeedTotal & 0x20) != 0 ? 1 : 2;
+                       Seed_Fine = SeedTotal & 0x1F;
+                       pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Gross;
+                       pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Fine;
+                       ByteLane ++;
+               }
        }
+
        setWLByteDelay(pDCTData, ByteLane, dimm, 0);
 }