/** * * * 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; }
void InterleaveChannels_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA) { u8 Node; u32 DramBase, DctSelBase; u8 DctSelIntLvAddr, DctSelHi; u8 HoleValid = 0; u32 HoleSize, HoleBase = 0; u32 val, tmp; u32 dct0_size, dct1_size; struct DCTStatStruc *pDCTstat; /* HoleValid - indicates whether the current Node contains hole. * HoleSize - indicates whether there is IO hole in the whole system * memory. */ /* call back to wrapper not needed ManualChannelInterleave_D(); */ /* call back - DctSelIntLvAddr = mctGet_NVbits(NV_ChannelIntlv);*/ /* override interleave */ /* Manually set: typ = 5, otherwise typ = 7. */ DctSelIntLvAddr = mctGet_NVbits(NV_ChannelIntlv); /* typ = 5: Hash*: exclusive OR of address bits[20:16, 6]. */ if (DctSelIntLvAddr & 1) { DctSelIntLvAddr >>= 1; HoleSize = 0; if ((pMCTstat->GStatus & (1 << GSB_SoftHole)) || (pMCTstat->GStatus & (1 << GSB_HWHole))) { if (pMCTstat->HoleBase) { HoleBase = pMCTstat->HoleBase >> 8; HoleSize = HoleBase & 0xFFFF0000; HoleSize |= ((~HoleBase) + 1) & 0xFFFF; } }
void PrepareC_MCT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat) { pDCTstat->C_MCTPtr->AgesaDelay = AgesaDelay; pDCTstat->C_MCTPtr->PlatMaxTotalDimms = mctGet_NVbits(NV_MAX_DIMMS); pDCTstat->C_MCTPtr->PlatMaxDimmsDct = pDCTstat->C_MCTPtr->PlatMaxTotalDimms >> 1; }
/** * * * This function set Rtt_Nom for registered DDR3 dimms on non-targeted dimm. * * @param *pMCTData * @param[in] *pDCTData - Pointer to buffer with information about each DCT * @param dimm - non-targeted dimm * @param wl - current mode, either write levelization mode or normal mode * @param MemClkFreq - current frequency * @param rank * * @return tempW1 - Rtt_Nom */ u32 RttNomNonTargetRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl, u8 MemClkFreq, u8 rank) { if ((wl) && (mctGet_NVbits(NV_MAX_DIMMS_PER_CH) == 2) && (pDCTData->DimmRanks[dimm] == 2) && (rank == 1)) { return 0x00; /* for non-target dimm during WL, the second rank of a DR dimm need to have Rtt_Nom = OFF */ } else { return RttNomTargetRegDimm (pMCTData, pDCTData, dimm, FALSE, MemClkFreq, rank); /* otherwise, the same as target dimm in normal mode. */ } }
static void amdmct_cbmem_store_info(struct sys_info *sysinfo) { if (!sysinfo) return; /* Save memory info structures for use in ramstage */ size_t i; struct DCTStatStruc *pDCTstatA = NULL; if (!acpi_is_wakeup_s3()) { /* Allocate memory */ struct amdmct_memory_info *mem_info; mem_info = cbmem_add(CBMEM_ID_AMDMCT_MEMINFO, sizeof(struct amdmct_memory_info)); if (!mem_info) return; printk(BIOS_DEBUG, "%s: Storing AMDMCT configuration in CBMEM\n", __func__); /* Initialize memory */ memset(mem_info, 0, sizeof(struct amdmct_memory_info)); /* Copy data */ memcpy(&mem_info->mct_stat, &sysinfo->MCTstat, sizeof(struct MCTStatStruc)); for (i = 0; i < MAX_NODES_SUPPORTED; i++) { pDCTstatA = sysinfo->DCTstatA + i; memcpy(&mem_info->dct_stat[i], pDCTstatA, sizeof(struct DCTStatStruc)); } mem_info->ecc_enabled = mctGet_NVbits(NV_ECC_CAP); mem_info->ecc_scrub_rate = mctGet_NVbits(NV_DramBKScrub); /* Zero out invalid/unused pointers */ #if IS_ENABLED(CONFIG_DIMM_DDR3) for (i = 0; i < MAX_NODES_SUPPORTED; i++) { mem_info->dct_stat[i].C_MCTPtr = NULL; mem_info->dct_stat[i].C_DCTPtr[0] = NULL; mem_info->dct_stat[i].C_DCTPtr[1] = NULL; } #endif } }
static u32 mct_MR1(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel) { u32 dev = pDCTstat->dev_dct; u32 dword, ret; /* The formula for chip select number is: CS = dimm*2+rank */ uint8_t dimm = MrsChipSel / 2; uint8_t rank = MrsChipSel % 2; if (is_fam15h()) { uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE); /* Set defaults */ uint8_t qoff = 0; /* Enable output buffers */ uint8_t wrlvl = 0; /* Disable write levelling */ uint8_t tqds = 0; uint8_t rttnom = 0; uint8_t dic = 0; uint8_t additive_latency = 0; uint8_t dll_enable = 0; ret = 0x40000; ret |= (MrsChipSel << 21); /* Determine if TQDS should be set */ if ((pDCTstat->Dimmx8Present & (1 << dimm)) && (((dimm & 0x1)?(pDCTstat->Dimmx4Present&0x55):(pDCTstat->Dimmx4Present&0xaa)) != 0x0) && (pDCTstat->Status & (1 << SB_LoadReduced))) tqds = 1; /* Obtain RttNom */ rttnom = fam15_rttnom(pDCTstat, dct, dimm, rank, package_type); /* Obtain DIC */ dic = fam15_dimm_dic(pDCTstat, dct, dimm, rank, package_type); /* Load data into MRS word */ ret |= (qoff & 0x1) << 12; ret |= (tqds & 0x1) << 11; ret |= ((rttnom & 0x4) >> 2) << 9; ret |= ((rttnom & 0x2) >> 1) << 6; ret |= ((rttnom & 0x1) >> 0) << 2; ret |= (wrlvl & 0x1) << 7; ret |= ((dic & 0x2) >> 1) << 5; ret |= ((dic & 0x1) >> 0) << 1; ret |= (additive_latency & 0x3) << 3; ret |= (dll_enable & 0x1); } else {
u32 RttWrRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl, u8 MemClkFreq, u8 rank) { u32 tempW1; tempW1 = 0; if (wl) { tempW1 = 0x00; /* Rtt_WR = OFF */ } else { switch (mctGet_NVbits(NV_MAX_DIMMS_PER_CH)) { case 2: if (pDCTData->MaxDimmsInstalled == 1) { if (pDCTData->DimmRanks[dimm] != 4) { tempW1 = 0x00; } else { if (MemClkFreq == 6) { tempW1 = 0x200; /* Rtt_WR = 60 ohms */ } else { tempW1 = 0x400; /* Rtt_WR = 120 ohms */ } } } else { if ((pDCTData->DimmRanks[dimm] == 4) || (pDCTData->DctCSPresent & 0xF0)) { if (MemClkFreq == 3) { tempW1 = 0x400; /* Rtt_WR = 120 ohms */ } else { tempW1 = 0x200; /* Rtt_WR = 60 ohms */ } } else { if (MemClkFreq == 6) { tempW1 = 0x200; /* Rtt_WR = 60 ohms */ } else { tempW1 = 0x400; /* Rtt_Nom = 120 ohms */ } } } break; case 3: if (pDCTData->MaxDimmsInstalled == 1) { tempW1 = 0x00; /* Rtt_WR = OFF */ } else { tempW1 = 0x400; /* Rtt_Nom = 120 ohms */ } break; default: die("modtrdim.c: WTF?"); } } return tempW1; }
void mctGet_PS_Cfg_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u32 dct) { u16 val, valx; print_tx("dct: ", dct); print_tx("Speed: ", pDCTstat->Speed); Get_ChannelPS_Cfg0_D(pDCTstat->MAdimms[dct], pDCTstat->Speed, pDCTstat->MAload[dct], pDCTstat->DATAload[dct], &(pDCTstat->CH_ADDR_TMG[dct]), &(pDCTstat->CH_ODC_CTL[dct])); if (pDCTstat->MAdimms[dct] == 1) pDCTstat->CH_ODC_CTL[dct] |= 0x20000000; /* 75ohms */ else pDCTstat->CH_ODC_CTL[dct] |= 0x10000000; /* 150ohms */ pDCTstat->_2Tmode = 1; /* use byte lane 4 delay for ECC lane */ pDCTstat->CH_EccDQSLike[0] = 0x0504; pDCTstat->CH_EccDQSScale[0] = 0; /* 100% byte lane 4 */ pDCTstat->CH_EccDQSLike[1] = 0x0504; pDCTstat->CH_EccDQSScale[1] = 0; /* 100% byte lane 4 */ /* Overrides and/or exceptions */ /* 1) QRx4 needs to adjust CS/ODT setup time */ // FIXME: Add Ax support? if (mctGet_NVbits(NV_MAX_DIMMS) == 4) { if (pDCTstat->DimmQRPresent != 0) { pDCTstat->CH_ADDR_TMG[dct] &= 0xFF00FFFF; pDCTstat->CH_ADDR_TMG[dct] |= 0x00000000; if (pDCTstat->MAdimms[dct] == 4) { pDCTstat->CH_ADDR_TMG[dct] &= 0xFF00FFFF; pDCTstat->CH_ADDR_TMG[dct] |= 0x002F0000; if (pDCTstat->Speed == 3 || pDCTstat->Speed == 4) { pDCTstat->CH_ADDR_TMG[dct] &= 0xFF00FFFF; pDCTstat->CH_ADDR_TMG[dct] |= 0x00002F00; if (pDCTstat->MAdimms[dct] == 4) pDCTstat->CH_ODC_CTL[dct] = 0x00331222; } } } } /* 2) DRx4 (R/C-J) @ DDR667 needs to adjust CS/ODT setup time */ if (pDCTstat->Speed == 3 || pDCTstat->Speed == 4) { val = pDCTstat->Dimmx4Present; if (dct == 0) { val &= 0x55; } else { val &= 0xAA; val >>= 1; } val &= pDCTstat->DIMMValid; if (val) { //FIXME: skip for Ax valx = pDCTstat->DimmDRPresent; if (dct == 0) { valx &= 0x55; } else { valx &= 0xAA; valx >>= 1; } if (mctGet_NVbits(NV_MAX_DIMMS) == 8) { val &= valx; if (val != 0) { pDCTstat->CH_ADDR_TMG[dct] &= 0xFFFF00FF; pDCTstat->CH_ADDR_TMG[dct] |= 0x00002F00; } } else { val &= valx; if (val != 0) { if (pDCTstat->Speed == 3 || pDCTstat->Speed == 3) { pDCTstat->CH_ADDR_TMG[dct] &= 0xFFFF00FF; pDCTstat->CH_ADDR_TMG[dct] |= 0x00002F00; } } } } }
static u32 mct_MR2(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel) { u32 dev = pDCTstat->dev_dct; u32 dword, ret; /* The formula for chip select number is: CS = dimm*2+rank */ uint8_t dimm = MrsChipSel / 2; uint8_t rank = MrsChipSel % 2; if (is_fam15h()) { uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE); /* FIXME: These parameters should be configurable * For now, err on the side of caution and enable automatic 2x refresh * when the DDR temperature rises above the internal limits */ uint8_t force_2x_self_refresh = 0; /* ASR */ uint8_t auto_2x_self_refresh = 1; /* SRT */ ret = 0x80000; ret |= (MrsChipSel << 21); /* Set self refresh parameters */ ret |= (force_2x_self_refresh << 6); ret |= (auto_2x_self_refresh << 7); /* Obtain Tcwl, adjust, and set CWL with the adjusted value */ dword = Get_NB32_DCT(dev, dct, 0x20c) & 0x1f; ret |= ((dword - 5) << 3); /* Obtain and set RttWr */ ret |= (fam15_rttwr(pDCTstat, dct, dimm, rank, package_type) << 9); } else { ret = 0x20000; ret |= (MrsChipSel << 20); /* program MrsAddress[5:3]=CAS write latency (CWL): * based on F2x[1,0]84[Tcwl] */ dword = Get_NB32_DCT(dev, dct, 0x84); dword = mct_AdjustSPDTimings(pMCTstat, pDCTstat, dword); ret |= ((dword >> 20) & 7) << 3; /* program MrsAddress[6]=auto self refresh method (ASR): * based on F2x[1,0]84[ASR] * program MrsAddress[7]=self refresh temperature range (SRT): * based on F2x[1,0]84[ASR and SRT] */ ret |= ((dword >> 18) & 3) << 6; /* program MrsAddress[10:9]=dynamic termination during writes (RTT_WR) * based on F2x[1,0]84[DramTermDyn] */ ret |= ((dword >> 10) & 3) << 9; } printk(BIOS_SPEW, "Going to send DCT %d DIMM %d rank %d MR2 control word %08x\n", dct, dimm, rank, ret); return ret; }
static uint8_t fam15_rttwr(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t rank, uint8_t package_type) { uint8_t term = 0; uint8_t number_of_dimms = pDCTstat->MAdimms[dct]; uint8_t frequency_index; uint8_t rank_count = pDCTstat->DimmRanks[(dimm * 2) + dct]; uint8_t rank_count_dimm0; uint8_t rank_count_dimm1; uint8_t rank_count_dimm2; if (is_fam15h()) frequency_index = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f; else frequency_index = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x7; uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); if (is_fam15h()) { if (pDCTstat->Status & (1 << SB_LoadReduced)) { /* TODO * LRDIMM unimplemented */ } else if (pDCTstat->Status & (1 << SB_Registered)) { /* RDIMM */ if (package_type == PT_GR) { /* Socket G34: Fam15h BKDG v3.14 Table 57 */ if (MaxDimmsInstallable == 1) { if ((frequency_index == 0x4) || (frequency_index == 0x6) || (frequency_index == 0xa) || (frequency_index == 0xe)) { /* DDR3-667 - DDR3-1333 */ if (rank_count < 3) term = 0x0; else term = 0x2; } else { /* DDR3-1600 */ term = 0x0; } } else if (MaxDimmsInstallable == 2) { rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; if ((frequency_index == 0x4) || (frequency_index == 0x6)) { /* DDR3-667 - DDR3-800 */ if ((number_of_dimms == 1) && ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4))) term = 0x0; else term = 0x2; } else if (frequency_index == 0xa) { /* DDR3-1066 */ if (number_of_dimms == 1) { if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) term = 0x0; else term = 0x2; } else { term = 0x1; } } else if (frequency_index == 0xe) { /* DDR3-1333 */ term = 0x2; } else { /* DDR3-1600 */ if (number_of_dimms == 1) term = 0x0; else term = 0x1; } } else if (MaxDimmsInstallable == 3) { rank_count_dimm2 = pDCTstat->DimmRanks[(2 * 2) + dct]; if ((frequency_index == 0xa) || (frequency_index == 0xe)) { /* DDR3-1066 - DDR3-1333 */ if (rank_count_dimm2 < 4) term = 0x1; else term = 0x2; } else if (frequency_index == 0x12) { /* DDR3-1600 */ term = 0x1; } else { term = 0x2; } } } else { /* TODO * Other sockets unimplemented */ } } else { /* UDIMM */ if (package_type == PT_GR) { /* Socket G34: Fam15h BKDG v3.14 Table 56 */ if (MaxDimmsInstallable == 1) { term = 0x0; } else if (MaxDimmsInstallable == 2) { if ((number_of_dimms == 2) && (frequency_index == 0x12)) { term = 0x1; } else if (number_of_dimms == 1) { term = 0x0; } else { term = 0x2; } } else if (MaxDimmsInstallable == 3) { if (number_of_dimms == 1) { if (frequency_index <= 0xa) { term = 0x2; } else { if (rank_count < 3) { term = 0x1; } else { term = 0x2; } } } else if (number_of_dimms == 2) { term = 0x2; } } } else { /* TODO * Other sockets unimplemented */ } } } return term; }
/* * In: MAAdimms - number of DIMMs on the channel * : Speed - Speed (see DCTStatstruc.Speed for definition) * : MAAload - number of address bus loads on the channel * : DATAAload - number of ranks on the channel * Out: AddrTmgCTL - Address Timing Control Register Value * : ODC_CTL - Output Driver Compensation Control Register Value * : CMDmode - CMD mode */ static void Get_ChannelPS_Cfg0_D( u8 MAAdimms, u8 Speed, u8 MAAload, u8 DATAAload, u32 *AddrTmgCTL, u32 *ODC_CTL, u8 *CMDmode) { *AddrTmgCTL = 0; *ODC_CTL = 0; *CMDmode = 1; if (mctGet_NVbits(NV_MAX_DIMMS) == 4) { if(Speed == 4) { *AddrTmgCTL = 0x00000000; } else if (Speed == 5) { *AddrTmgCTL = 0x003C3C3C; if (MAAdimms > 1) *AddrTmgCTL = 0x003A3C3A; } else if (Speed == 6) { if (MAAdimms == 1) *AddrTmgCTL = 0x003A3A3A; else *AddrTmgCTL = 0x00383A38; } else { if (MAAdimms == 1) *AddrTmgCTL = 0x00373937; else *AddrTmgCTL = 0x00353935; } } else { if(Speed == 4) { *AddrTmgCTL = 0x00000000; if (MAAdimms == 3) *AddrTmgCTL = 0x00380038; } else if (Speed == 5) { if (MAAdimms == 1) *AddrTmgCTL = 0x003C3C3C; else if (MAAdimms == 2) *AddrTmgCTL = 0x003A3C3A; else *AddrTmgCTL = 0x00373C37; } else if (Speed == 6) { if (MAAdimms == 1) *AddrTmgCTL = 0x003A3A3A; else if (MAAdimms == 2) *AddrTmgCTL = 0x00383A38; else *AddrTmgCTL = 0x00343A34; } else { if (MAAdimms == 1) *AddrTmgCTL = 0x00393939; else if (MAAdimms == 2) *AddrTmgCTL = 0x00363936; else *AddrTmgCTL = 0x00303930; } } if ((MAAdimms == 1) && (MAAload < 4)) *ODC_CTL = 0x20113222; else *ODC_CTL = 0x20223222; *CMDmode = 1; }
/** * * * This function set Rtt_Nom for registered DDR3 dimms on targeted dimm. * * @param *pMCTData * @param[in] *pDCTData - Pointer to buffer with information about each DCT * @param dimm - targeted dimm * @param wl - current mode, either write levelization mode or normal mode * @param MemClkFreq - current frequency * @param rank * * @return tempW1 - Rtt_Nom */ u32 RttNomTargetRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl, u8 MemClkFreq, u8 rank) { u32 tempW1; tempW1 = 0; if (wl) { switch (mctGet_NVbits(NV_MAX_DIMMS_PER_CH)) { case 2: /* 2 dimms per channel */ if (pDCTData->MaxDimmsInstalled == 1) { if ((pDCTData->DimmRanks[dimm] == 2) && (rank == 0)) { tempW1 = 0x00; /* Rtt_Nom = OFF */ } else if (pDCTData->DimmRanks[dimm] == 4) { if (rank == 1) { tempW1 = 0x00; /* Rtt_Nom = OFF on second and forth rank of QR dimm */ } else { if (MemClkFreq == 6) { tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ } else { tempW1 = 0x40; /* Rtt_Nom = 120 ohms */ } } } else { tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ } } else if (pDCTData->MaxDimmsInstalled == 2) { if (((pDCTData->DimmRanks[dimm] == 2) || (pDCTData->DimmRanks[dimm] == 4)) && (rank == 1)) { tempW1 = 0x00; /* Rtt_Nom = OFF */ } else if ((pDCTData->DimmRanks[dimm] == 4) || (pDCTData->DctCSPresent & 0xF0)) { if (MemClkFreq == 3) { tempW1 = 0x40; /* Rtt_Nom = 120 ohms */ } else { tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ } } else { if (MemClkFreq == 6) { tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ } else { tempW1 = 0x40; /* Rtt_Nom = 120 ohms */ } } } break; case 3: /* 3 dimms per channel */ /* QR not supported in this case on L1 package. */ if (pDCTData->MaxDimmsInstalled == 1) { if ((pDCTData->DimmRanks[dimm] == 2) && (rank == 1)) { tempW1 = 0x00; /* Rtt_Nom = OFF */ } else { tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ } } else { tempW1 = 0x40; /* Rtt_Nom = 120 ohms */ } break; default: die("modtrdim.c: WTF?"); } } else { switch (mctGet_NVbits(NV_MAX_DIMMS_PER_CH)) { case 2: /* 2 dimms per channel */ if ((pDCTData->DimmRanks[dimm] == 4) && (rank == 1)) { tempW1 = 0x00; /* Rtt_Nom = OFF */ } else if ((pDCTData->MaxDimmsInstalled == 1) || (pDCTData->DimmRanks[dimm] == 4)) { tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ } else { if (pDCTData->DctCSPresent & 0xF0) { tempW1 = 0x0204; /* Rtt_Nom = 30 ohms */ } else { if (MemClkFreq < 5) { tempW1 = 0x44; /* Rtt_Nom = 40 ohms */ } else { tempW1 = 0x0204; /* Rtt_Nom = 30 ohms */ } } } break; case 3: /* 3 dimms per channel */ /* L1 package does not support QR dimms this case. */ if (rank == 1) { tempW1 = 0x00; /* Rtt_Nom = OFF */ } else if (pDCTData->MaxDimmsInstalled == 1) { tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ } else if ((MemClkFreq < 5) || (pDCTData->MaxDimmsInstalled == 3)) { tempW1 = 0x44; /* Rtt_Nom = 40 ohms */ } else { tempW1 = 0x0204; /* Rtt_Nom = 30 ohms */ } break; default: die("modtrdim.c: WTF?"); } } return tempW1; }
static uint8_t fam15h_rdimm_rc2_ibt_code(struct DCTStatStruc *pDCTstat, uint8_t dct) { uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); uint8_t package_type; uint8_t control_code = 0; package_type = mctGet_NVbits(NV_PACK_TYPE); uint16_t MemClkFreq = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f; /* Obtain number of DIMMs on channel */ uint8_t dimm_count = pDCTstat->MAdimms[dct]; /* FIXME * Assume there is only one register on the RDIMM for now */ uint8_t num_registers = 1; if (package_type == PT_GR) { /* Socket G34 */ /* Fam15h BKDG Rev. 3.14 section 2.10.5.7.1.2.1 Table 85 */ if (MaxDimmsInstallable == 1) { if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { /* DDR3-667 - DDR3-800 */ control_code = 0x1; } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) { /* DDR3-1066 - DDR3-1333 */ if (num_registers == 1) { control_code = 0x0; } else { control_code = 0x1; } } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { /* DDR3-1600 - DDR3-1866 */ control_code = 0x0; } } else if (MaxDimmsInstallable == 2) { if (dimm_count == 1) { /* 1 DIMM detected */ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { /* DDR3-667 - DDR3-800 */ control_code = 0x1; } else if ((MemClkFreq >= 0xa) && (MemClkFreq <= 0x12)) { /* DDR3-1066 - DDR3-1600 */ if (num_registers == 1) { control_code = 0x0; } else { control_code = 0x1; } } } else if (dimm_count == 2) { /* 2 DIMMs detected */ if (num_registers == 1) { control_code = 0x1; } else { control_code = 0x8; } } } else if (MaxDimmsInstallable == 3) { /* TODO * 3 DIMM/channel support unimplemented */ } } else if (package_type == PT_C3) { /* Socket C32 */ /* Fam15h BKDG Rev. 3.14 section 2.10.5.7.1.2.1 Table 86 */ if (MaxDimmsInstallable == 1) { if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { /* DDR3-667 - DDR3-800 */ control_code = 0x1; } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) { /* DDR3-1066 - DDR3-1333 */ if (num_registers == 1) { control_code = 0x0; } else { control_code = 0x1; } } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { /* DDR3-1600 - DDR3-1866 */ control_code = 0x0; } } else if (MaxDimmsInstallable == 2) { if (dimm_count == 1) { /* 1 DIMM detected */ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { /* DDR3-667 - DDR3-800 */ control_code = 0x1; } else if ((MemClkFreq >= 0xa) && (MemClkFreq <= 0x12)) { /* DDR3-1066 - DDR3-1600 */ if (num_registers == 1) { control_code = 0x0; } else { control_code = 0x1; } } } else if (dimm_count == 2) { /* 2 DIMMs detected */ if (num_registers == 1) { control_code = 0x1; } else { control_code = 0x8; } } } else if (MaxDimmsInstallable == 3) { /* TODO * 3 DIMM/channel support unimplemented */ } } else { /* TODO * Other socket support unimplemented */ } return control_code; }