/** * * * This function set WrLvOdt for registered DDR3 dimms. * * @param *pMCTData * @param[in] *pDCTData - Pointer to buffer with information about each DCT * @param dimm - targeted dimm * * @return WrLvOdt */ u8 WrLvOdtRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm) { u8 WrLvOdt1, i; WrLvOdt1 = 0; i = 0; while (i < 8) { if (pDCTData->DctCSPresent & (1 << i)) { WrLvOdt1 = (u8)bitTestSet(WrLvOdt1, i/2); } i += 2; } if (mctGet_NVbits(NV_MAX_DIMMS_PER_CH) == 2) { if ((pDCTData->DimmRanks[dimm] == 4) && (pDCTData->MaxDimmsInstalled != 1)) { if (dimm >= 2) { WrLvOdt1 = (u8)bitTestReset (WrLvOdt1, (dimm - 2)); } else { WrLvOdt1 = (u8)bitTestReset (WrLvOdt1, (dimm + 2)); } } else if ((pDCTData->DimmRanks[dimm] == 2) && (pDCTData->MaxDimmsInstalled == 1)) { /* the case for one DR on a 2 dimms per channel is special */ WrLvOdt1 = 0x8; } } return WrLvOdt1; }
/*------------------------------------------------- * BOOL bitTest(u32 value, u8 bitLoc) * * Description: * This routine tests the value to determine if the bitLoc is set * * Parameters: * IN Value - value to be tested * bitLoc - bit location to be tested * OUT TRUE - bit is set * FALSE - bit is clear *------------------------------------------------- */ static BOOL bitTest(u32 value, u8 bitLoc) { u32 tempD, compD; tempD = value; compD = 0; compD = bitTestSet(compD,bitLoc); tempD &= compD; if (compD == tempD) { return TRUE; } else { return FALSE; } }
/*------------------------------------------------- * void set_DCT_ADDR_Bits(DCTStruct *DCTData, u8 DCT,u8 Node,u8 func, * u16 offset,u8 low, u8 high, u32 value) * * Description: * This routine sets the Additional PCT register from Function 2 by specified * Node, DCT and PCI address * * Parameters: * IN OUT *DCTData - Pointer to buffer with information about each DCT * IN DCT - DCT number * - 1 indicates DCT 1 * - 0 indicates DCT 0 * - 2 both DCTs * Node - Node number * Func - PCI Function number * Offset - Additional PCI register number * Low - Low bit of the bit field * High - High bit of the bit field * * OUT *------------------------------------------------- */ static void set_DCT_ADDR_Bits(sDCTStruct *pDCTData, u8 dct, u8 node, u8 func, u16 offset, u8 low, u8 high, u32 value) { u32 tempD; set_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, PCI_MIN_LOW, PCI_MAX_HIGH, offset); while ((get_Bits(pDCTData,dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, DctAccessDone, DctAccessDone)) == 0); set_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_PORT_REG, low, high, value); tempD = offset; tempD = bitTestSet(tempD,DctAccessWrite); set_Bits(pDCTData, dct, node, FUN_DCT,DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, PCI_MIN_LOW, PCI_MAX_HIGH, tempD); while ((get_Bits(pDCTData,dct, pDCTData->NodeId, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, DctAccessDone, DctAccessDone)) == 0); }
/*----------------------------------------------------------------------------- * void AgesaHwWlPhase1(SPDStruct *SPDData,MCTStruct *MCTData, DCTStruct *DCTData, * u8 Dimm, u8 Pass) * * Description: * This function initialized Hardware based write levelization phase 1 * * Parameters: * IN OUT *SPDData - Pointer to buffer with information about each DIMMs * SPD information * *MCTData - Pointer to buffer with runtime parameters, * *DCTData - Pointer to buffer with information about each DCT * * IN DIMM - Logical DIMM number * Pass - First or Second Pass * OUT *----------------------------------------------------------------------------- */ void AgesaHwWlPhase1(sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, u8 pass) { u8 ByteLane; u32 Value, Addr; u16 Addl_Data_Offset, Addl_Data_Port; pDCTData->WLPass = pass; /* 1. Specify the target DIMM that is to be trained by programming * F2x[1, 0]9C_x08[TrDimmSel]. */ set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT, DRAM_ADD_DCT_PHY_CONTROL_REG, TrDimmSelStart, TrDimmSelEnd,(u32)dimm); /* 2. Prepare the DIMMs for write levelization using DDR3-defined * MR commands. */ prepareDimms(pMCTData, pDCTData,dimm, TRUE); /* 3. After the DIMMs are configured, BIOS waits 40 MEMCLKs to * satisfy DDR3-defined internal DRAM timing. */ pMCTData->AgesaDelay(40); /* 4. Configure the processor's DDR phy for write levelization training: */ procConifg(pMCTData,pDCTData, dimm, pass); /* 5. Begin write levelization training: * Program F2x[1, 0]9C_x08[WrtLevelTrEn]=1. */ 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 { /* Broadcast write to all D3Dbyte chipset register offset 0xc * Set bit 0 (wrTrain) * Program bit 4 to nibble being trained (only matters for x4dimms) * retain value of 3:2 (Trdimmsel) * reset bit 5 (FrzPR) */ if (pDCTData->DctTrain) { Addl_Data_Offset=0x198; Addl_Data_Port=0x19C; } else { Addl_Data_Offset=0x98; Addl_Data_Port=0x9C; } Addr=0x0D00000C; AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Offset), 31, 0, &Addr); while ((get_Bits(pDCTData,FUN_DCT,pDCTData->NodeId, FUN_DCT, Addl_Data_Offset, DctAccessDone, DctAccessDone)) == 0); AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Port), 31, 0, &Value); Value = bitTestSet(Value, 0); /* enable WL training */ Value = bitTestReset(Value, 4); /* for x8 only */ Value = bitTestReset(Value, 5); /* for hardware WL training */ AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Port), 31, 0, &Value); Addr=0x4D030F0C; AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Offset), 31, 0, &Addr); while ((get_Bits(pDCTData,FUN_DCT,pDCTData->NodeId, FUN_DCT, Addl_Data_Offset, DctAccessDone, DctAccessDone)) == 0); } /* Wait 200 MEMCLKs. If executing pass 2, wait 32 MEMCLKs. */ pMCTData->AgesaDelay(140); /* Program F2x[1, 0]9C_x08[WrtLevelTrEn]=0. */ set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT, DRAM_ADD_DCT_PHY_CONTROL_REG, WrtLvTrEn, WrtLvTrEn, 0); /* Read from registers F2x[1, 0]9C_x[51:50] and F2x[1, 0]9C_x52 * to get the gross and fine delay settings * for the target DIMM and save these values. */ ByteLane = 0; while (ByteLane < MAX_BYTE_LANES) { getWLByteDelay(pDCTData,ByteLane, dimm); setWLByteDelay(pDCTData,ByteLane, dimm, 1); ByteLane++; } /* 6. Configure DRAM Phy Control Register so that the phy stops driving * write levelization ODT. */ set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT, DRAM_ADD_DCT_PHY_CONTROL_REG, WrLvOdtEn, WrLvOdtEn, 0); /* Wait 10 MEMCLKs to allow for ODT signal settling. */ pMCTData->AgesaDelay(10); /* 7. Program the target DIMM back to normal operation by configuring * the following (See section 2.8.5.4.1.1 * [Phy Assisted Write Levelization] on page 97 pass 1, step #2): * Configure all ranks of the target DIMM for normal operation. * Enable the output drivers of all ranks of the target DIMM. * For a two DIMM system, program the Rtt value for the target DIMM * to the normal operating termination: */ prepareDimms(pMCTData, pDCTData,dimm,FALSE); }