Beispiel #1
0
/**
 *
 *
 *   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;
}
Beispiel #2
0
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;
			}
		}
Beispiel #3
0
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;
}
Beispiel #4
0
/**
 *
 *
 *   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. */
	}
}
Beispiel #5
0
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
	}
}
Beispiel #6
0
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 {
Beispiel #7
0
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;
}
Beispiel #8
0
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;
					}
				}

			}
		}
	}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
/*
 *  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;
}
Beispiel #12
0
/**
 *
 *
 *   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;
}
Beispiel #13
0
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;
}