Beispiel #1
0
static u32 mct_MR3(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()) {
		ret = 0xc0000;
		ret |= (MrsChipSel << 21);

		/* Program MPR and MPRLoc to 0 */
		// ret |= 0x0;		/* MPR */
		// ret |= (0x0 << 2);	/* MPRLoc */
	} else {
		ret = 0x30000;
		ret |= (MrsChipSel << 20);

		/* program MrsAddress[1:0]=multi purpose register address location
		 * (MPR Location):based on F2x[1,0]84[MprLoc]
		 * program MrsAddress[2]=multi purpose register
		 * (MPR):based on F2x[1,0]84[MprEn]
		 */
		dword = Get_NB32_DCT(dev, dct, 0x84);
		ret |= (dword >> 24) & 7;
	}

	printk(BIOS_SPEW, "Going to send DCT %d DIMM %d rank %d MR3 control word %08x\n", dct, dimm, rank, ret);

	return ret;
}
Beispiel #2
0
static void mct_SendMrsCmd(struct DCTStatStruc *pDCTstat, u8 dct, u32 EMRS)
{
	u32 dev = pDCTstat->dev_dct;
	u32 val;

	printk(BIOS_DEBUG, "%s: Start\n", __func__);

	val = Get_NB32_DCT(dev, dct, 0x7c);
	val &= ~0x00ffffff;
	val |= EMRS;
	val |= 1 << SendMrsCmd;
	Set_NB32_DCT(dev, dct, 0x7c, val);

	do {
		val = Get_NB32_DCT(dev, dct, 0x7c);
	} while (val & (1 << SendMrsCmd));

	printk(BIOS_DEBUG, "%s: Done\n", __func__);
}
Beispiel #3
0
static void mct_DCTAccessDone(struct DCTStatStruc *pDCTstat, u8 dct)
{
	u32 dev = pDCTstat->dev_dct;
	u32 val;

	printk(BIOS_DEBUG, "%s: Start\n", __func__);

	do {
		val = Get_NB32_DCT(dev, dct, 0x98);
	} while (!(val & (1 << DctAccessDone)));

	printk(BIOS_DEBUG, "%s: Done\n", __func__);
}
Beispiel #4
0
static void mct_setMaxRdLatTrnVal_D(struct DCTStatStruc *pDCTstat,
					u8 Channel, u16 MaxRdLatVal)
{
	u8 i;
	u32 reg;
	u32 dev;
	u32 val;

	if (pDCTstat->GangedMode) {
		Channel = 0; /* for safe */
		for (i = 0; i < 2; i++)
			pDCTstat->CH_MaxRdLat[i][0] = MaxRdLatVal;
	} else {
		pDCTstat->CH_MaxRdLat[Channel][0] = MaxRdLatVal;
	}

	dev = pDCTstat->dev_dct;
	reg = 0x78;
	val = Get_NB32_DCT(dev, Channel, reg);
	val &= ~(0x3ff<<22);
	val |= MaxRdLatVal<<22;
	/* program MaxRdLatency to correspond with current delay */
	Set_NB32_DCT(dev, Channel, reg, val);
}
Beispiel #5
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 #6
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 #7
0
		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 {
		ret = 0x10000;
		ret |= (MrsChipSel << 20);

		/* program MrsAddress[5,1]=output driver impedance control (DIC):
		 * based on F2x[1,0]84[DrvImpCtrl]
		 */
		dword = Get_NB32_DCT(dev, dct, 0x84);
		if (dword & (1 << 3))
			ret |= 1 << 5;
		if (dword & (1 << 2))
			ret |= 1 << 1;

		/* program MrsAddress[9,6,2]=nominal termination resistance of ODT (RTT):
		 * based on F2x[1,0]84[DramTerm]
		 */
		if (!(pDCTstat->Status & (1 << SB_Registered))) {
			if (dword & (1 << 9))
				ret |= 1 << 9;
			if (dword & (1 << 8))
				ret |= 1 << 6;
			if (dword & (1 << 7))
				ret |= 1 << 2;
Beispiel #8
0
u8 mct_GetStartMaxRdLat_D(struct MCTStatStruc *pMCTstat,
				struct DCTStatStruc *pDCTstat,
				u8 Channel, u8 DQSRcvEnDly, u32 *Margin)
{
	u32 SubTotal;
	u32 val;
	u32 valx;
	u32 valxx;
	u32 index_reg;
	u32 dev;

	if (pDCTstat->GangedMode)
		Channel =  0;

	index_reg = 0x98;

	dev = pDCTstat->dev_dct;

	/* Multiply the CAS Latency by two to get a number of 1/2 MEMCLKs units.*/
	val = Get_NB32_DCT(dev, Channel, 0x88);
	SubTotal = ((val & 0x0f) + 1) << 1;	/* SubTotal is 1/2 Memclk unit */

	/* If registered DIMMs are being used then add 1 MEMCLK to the sub-total*/
	val = Get_NB32_DCT(dev, Channel, 0x90);
	if (!(val & (1 << UnBuffDimm)))
		SubTotal += 2;

	/*If the address prelaunch is setup for 1/2 MEMCLKs then add 1,
	 *  else add 2 to the sub-total. if (AddrCmdSetup || CsOdtSetup
	 *  || CkeSetup) then K := K + 2; */
	val = Get_NB32_index_wait_DCT(dev, Channel, index_reg, 0x04);
	if (!(val & 0x00202020))
		SubTotal += 1;
	else
		SubTotal += 2;

	/* If the F2x[1, 0]78[RdPtrInit] field is 4, 5, 6 or 7 MEMCLKs,
	 *  then add 4, 3, 2, or 1 MEMCLKs, respectively to the sub-total. */
	val = Get_NB32_DCT(dev, Channel, 0x78);
	SubTotal += 8 - (val & 0x0f);

	/* Convert bits 7-5 (also referred to as the course delay) of the current
	 * (or worst case) DQS receiver enable delay to 1/2 MEMCLKs units,
	 * rounding up, and add this to the sub-total. */
	SubTotal += DQSRcvEnDly >> 5;	/*BOZO-no rounding up */

	SubTotal <<= 1;			/*scale 1/2 MemClk to 1/4 MemClk */

	/* Convert the sub-total (in 1/2 MEMCLKs) to northbridge clocks (NCLKs)
	 * as follows (assuming DDR400 and assuming that no P-state or link speed
	 * changes have occurred). */

	/*New formula:
	SubTotal *= 3*(Fn2xD4[NBFid]+4)/(3+Fn2x94[MemClkFreq])/2 */
	val = Get_NB32_DCT(dev, Channel, 0x94);
	/* SubTotal div 4 to scale 1/4 MemClk back to MemClk */
	val &= 7;
	if (val >= 3) {
		val <<= 1;
	} else
		val += 3;
	valx = (val) << 2;	/* SubTotal div 4 to scale 1/4 MemClk back to MemClk */

	val = Get_NB32(pDCTstat->dev_nbmisc, 0xD4);
	val = ((val & 0x1f) + 4) * 3;

	/* Calculate 1 MemClk + 1 NCLK delay in NCLKs for margin */
	valxx = val << 2;
	valxx /= valx;
	if (valxx % valx)
		valxx++;	/* round up */
	valxx++;		/* add 1NCLK */
	*Margin = valxx;	/* one MemClk delay in NCLKs and one additional NCLK */

	val *= SubTotal;

	val /= valx;
	if (val % valx)
		val++;		/* round up */

	return val;
}
Beispiel #9
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;
}