/*
- * This file is part of the LinuxBIOS project.
+ * This file is part of the coreboot project.
*
- * Copyright (C) 2007 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* ordinarily in 64-bit mode.
*
* Trc precision does not use extra Jedec defined fractional component.
- * InsteadTrc (course) is rounded up to nearest 1 ns.
+ * Instead Trc (course) is rounded up to nearest 1 ns.
*
* Mini and Micro DIMM not supported. Only RDIMM, UDIMM, SO-DIMM defined types
* supported.
struct DCTStatStruc *pDCTstatA);
static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstatA);
-static void ResetNBECCstat_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstatA);
static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstatA);
static void MCTMemClr_D(struct MCTStatStruc *pMCTstat,
static void AfterDramInit_D(struct DCTStatStruc *pDCTstat, u8 dct);
static void mct_ResetDLL_D(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstat, u8 dct);
-
+static u32 mct_DisDllShutdownSR(struct MCTStatStruc *pMCTstat,
+ struct DCTStatStruc *pDCTstat, u32 DramConfigLo, u8 dct);
+static void mct_EnDllShutdownSR(struct MCTStatStruc *pMCTstat,
+ struct DCTStatStruc *pDCTstat, u8 dct);
/*See mctAutoInitMCT header for index relationships to CL and T*/
static const u16 Table_F_k[] = {00,200,266,333,400,533 };
static const u8 Table_Comp_Fall_Slew_20x[] = {7, 5, 3, 2, 0xFF};
static const u8 Table_Comp_Fall_Slew_15x[] = {7, 7, 5, 3, 0xFF};
-void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat,
+static void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstatA)
{
/*
* on setup options). It is the responsibility of PCI subsystem to
* create an uncacheable IO region below 4GB and to adjust TOP_MEM
* downward prior to any IO mapping or accesses. It is the same
- * responsibility of the CPU sub-system prior toaccessing LAPIC.
+ * responsibility of the CPU sub-system prior to accessing LAPIC.
*
* Slot Number is an external convention, and is determined by OEM with
* accompanying silk screening. OEM may choose to use Slot number
print_t("mctAutoInitMCT_D: DQSTiming_D\n");
DQSTiming_D(pMCTstat, pDCTstatA); /* Get Receiver Enable and DQS signal timing*/
+ print_t("mctAutoInitMCT_D: UMAMemTyping_D\n");
+ UMAMemTyping_D(pMCTstat, pDCTstatA); /* Fix up for UMA sizing */
+
print_t("mctAutoInitMCT_D: :OtherTiming\n");
mct_OtherTiming(pMCTstat, pDCTstatA);
}
mct_FinalMCT_D(pMCTstat, (pDCTstatA + 0) ); // Node 0
- print_t("All Done\n");
+ print_tx("mctAutoInitMCT_D Done: Global Status: ", pMCTstat->GStatus);
return;
fatalexit:
/* FIXME: BOZO- DQS training every time*/
nv_DQSTrainCTL = 1;
+ print_t("DQSTiming_D: mct_BeforeDQSTrain_D:\n");
+ mct_BeforeDQSTrain_D(pMCTstat, pDCTstatA);
+ phyAssistedMemFnceTraining(pMCTstat, pDCTstatA);
+
if (nv_DQSTrainCTL) {
- print_t("DQSTiming_D: mct_BeforeDQSTrain_D:\n");
- mct_BeforeDQSTrain_D(pMCTstat, pDCTstatA);;
- phyAssistedMemFnceTraining(pMCTstat, pDCTstatA);
- mctHookBeforeAnyTraining();
+ mctHookBeforeAnyTraining(pMCTstat, pDCTstatA);
print_t("DQSTiming_D: TrainReceiverEn_D FirstPass:\n");
TrainReceiverEn_D(pMCTstat, pDCTstatA, FirstPass);
}
}
-
+#ifdef UNUSED_CODE
+static void ResetNBECCstat_D(struct MCTStatStruc *pMCTstat,
+ struct DCTStatStruc *pDCTstatA);
static void ResetNBECCstat_D(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstatA)
{
}
}
}
-
+#endif
static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstatA)
u32 val;
u32 base;
u32 limit;
- u32 dev;
+ u32 dev, devx;
struct DCTStatStruc *pDCTstat;
_MemHoleRemap = mctGet_NVbits(NV_MemHole);
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
+ pDCTstat = pDCTstatA + Node;
+ devx = pDCTstat->dev_map;
DramSelBaseAddr = 0;
pDCTstat = pDCTstatA + Node;
if (!pDCTstat->GangedMode) {
base += NextBase;
limit += NextBase;
DramSelBaseAddr += NextBase;
- printk_debug(" Node: %02x base: %02x limit: %02x BottomIO: %02x\n", Node, base, limit, BottomIO);
+ printk(BIOS_DEBUG, " Node: %02x base: %02x limit: %02x BottomIO: %02x\n", Node, base, limit, BottomIO);
if (_MemHoleRemap) {
if ((base < BottomIO) && (limit >= BottomIO)) {
val <<= 8; /* shl 16, rol 24 */
val |= DramHoleBase << 24;
val |= 1 << DramHoleValid;
- Set_NB32(dev, 0xF0, val); /*Dram Hole Address Register*/
+ Set_NB32(devx, 0xF0, val); /* Dram Hole Address Reg */
pDCTstat->DCTSysLimit += HoleSize;
base = pDCTstat->DCTSysBase;
limit = pDCTstat->DCTSysLimit;
pMCTstat->SysLimit = limit;
}
Set_NB32(dev, 0x40 + (Node << 3), base); /* [Node] + Dram Base 0 */
- val = limit & 0xffff0000;
- val |= Node; /* set DstNode*/
+
+ /* if Node limit > 1GB then set it to 1GB boundary for each node */
+ if ((mctSetNodeBoundary_D()) && (limit > 0x00400000)) {
+ limit++;
+ limit &= 0xFFC00000;
+ limit--;
+ }
+ val = limit & 0xFFFF0000;
+ val |= Node;
Set_NB32(dev, 0x44 + (Node << 3), val); /* set DstNode */
limit = pDCTstat->DCTSysLimit;
if (limit) {
- NextBase = (limit & 0xffff0000) + 0x10000;
+ NextBase = (limit & 0xFFFF0000) + 0x10000;
+ if ((mctSetNodeBoundary_D()) && (NextBase > 0x00400000)) {
+ NextBase++;
+ NextBase &= 0xFFC00000;
+ NextBase--;
+ }
}
}
/* Copy dram map from Node 0 to Node 1-7 */
for (Node = 1; Node < MAX_NODES_SUPPORTED; Node++) {
- pDCTstat = pDCTstatA + Node;
u32 reg;
- u32 devx = pDCTstat->dev_map;
+ pDCTstat = pDCTstatA + Node;
+ devx = pDCTstat->dev_map;
if (pDCTstat->NodePresent) {
- printk_debug(" Copy dram map from Node 0 to Node %02x \n", Node);
+ printk(BIOS_DEBUG, " Copy dram map from Node 0 to Node %02x \n", Node);
reg = 0x40; /*Dram Base 0*/
do {
val = Get_NB32(dev, reg);
{
/* Initiates a memory clear operation for all node. The mem clr
- * is done in paralel. After the memclr is complete, all processors
+ * is done in parallel. After the memclr is complete, all processors
* status are checked to ensure that memclr has completed.
*/
u8 Node;
if (val == dword) /* current nodeID = requested nodeID ? */
ret = 1;
finish:
- ;
+ ;
}
return ret;
all of the MemClkDis bits should also be set.*/
val = 0xFF000000;
Set_NB32(pDCTstat->dev_dct, reg_off+0x88, val);
+ } else {
+ mct_EnDllShutdownSR(pMCTstat, pDCTstat, dct);
}
}
* HW memory clear process that the chip is capable of. The sooner
* that dram init is set for all nodes, the faster the memory system
* initialization can complete. Thus, the init loop is unrolled into
- * two loops so as to start the processeses for non BSP nodes sooner.
+ * two loops so as to start the processes for non BSP nodes sooner.
* This procedure will not wait for the process to finish.
* Synchronization is handled elsewhere.
*/
reg = 0x78 + reg_off;
val = Get_NB32(dev, reg);
/* Setting this bit forces a 1T window with hard left
- * pass/fail edge and a probabalistic right pass/fail
+ * pass/fail edge and a probabilistic right pass/fail
* edge. LEFT edge is referenced for final
* receiver enable position.*/
val |= 1 << DqsRcvEnTrain;
if ( mctGet_NVbits(NV_MCTUSRTMGMODE) == 2)
pDCTstat->Speed = mctGet_NVbits(NV_MemCkVal) + 1;
- mct_AfterGetCLT(pMCTstat, pDCTstat, dct);
}
+ mct_AfterGetCLT(pMCTstat, pDCTstat, dct);
/* Gather all DIMM mini-max values for cycle timing data */
Rows = 0;
for ( i = 0; i< MAX_DIMMS_SUPPORTED; i++) {
LDIMM = i >> 1;
if (pDCTstat->DIMMValid & (1 << i)) {
- smbaddr = Get_DIMMAddress_D(pDCTstat, i);
+ smbaddr = Get_DIMMAddress_D(pDCTstat, dct + i);
byte = mctRead_SPD(smbaddr, SPD_ROWSZ);
if (Rows < byte)
Rows = byte; /* keep track of largest row sz */
if ((val == 0) || (val == 0xFF)) {
pDCTstat->ErrStatus |= 1<<SB_NoTrcTrfc;
pDCTstat->ErrCode = SC_VarianceErr;
- val = Get_DefTrc_k_D(pDCTstat->DIMMAutoSpeed);
+ val = Get_DefTrc_k_D(pDCTstat->Speed);
} else {
byte = mctRead_SPD(smbaddr, SPD_TRCRFC);
if (byte & 0xF0) {
- val++; /* round up in case fractional extention is non-zero.*/
+ val++; /* round up in case fractional extension is non-zero.*/
}
- }
- if (Trc < val)
- Trc = val;
-
- /* dev density=rank size/#devs per rank */
- byte = mctRead_SPD(smbaddr, SPD_BANKSZ);
-
- val = ((byte >> 5) | (byte << 3)) & 0xFF;
- val <<= 2;
-
- byte = mctRead_SPD(smbaddr, SPD_DEVWIDTH) & 0xFE; /* dev density=2^(rows+columns+banks) */
- if (byte == 4) {
- val >>= 4;
- } else if (byte == 8) {
- val >>= 3;
- } else if (byte == 16) {
- val >>= 2;
- }
+ }
+ if (Trc < val)
+ Trc = val;
- byte = bsr(val);
+ /* dev density=rank size/#devs per rank */
+ byte = mctRead_SPD(smbaddr, SPD_BANKSZ);
+
+ val = ((byte >> 5) | (byte << 3)) & 0xFF;
+ val <<= 2;
+
+ byte = mctRead_SPD(smbaddr, SPD_DEVWIDTH) & 0xFE; /* dev density=2^(rows+columns+banks) */
+ if (byte == 4) {
+ val >>= 4;
+ } else if (byte == 8) {
+ val >>= 3;
+ } else if (byte == 16) {
+ val >>= 2;
+ }
- if (Trfc[LDIMM] < byte)
- Trfc[LDIMM] = byte;
+ byte = bsr(val);
- byte = mctRead_SPD(smbaddr, SPD_TRAS);
- if (Tras < byte)
- Tras = byte;
+ if (Trfc[LDIMM] < byte)
+ Trfc[LDIMM] = byte;
+
+ byte = mctRead_SPD(smbaddr, SPD_TRAS);
+ if (Tras < byte)
+ Tras = byte;
} /* Dimm Present */
}
/* Convert DRAM CycleTiming values and store into DCT structure */
DDR2_1066 = 0;
- byte = pDCTstat->DIMMAutoSpeed;
+ byte = pDCTstat->Speed;
if (byte == 5)
DDR2_1066 = 1;
Tk40 = Get_40Tk_D(byte);
}
pDCTstat->Trp = val;
- /*Trrd*/
+ /*Trrd*/
dword = Trrd * 10;
pDCTstat->DIMMTrrd = dword;
val = dword / Tk40;
dword = Trtp * 10;
pDCTstat->DIMMTrtp = dword;
val = pDCTstat->Speed;
- if (val <= 2) {
- val = 2; /* Calculate by 7.75ns / Speed in ns to get clock # */
- } else if (val == 4) { /* Note a speed of 3 will be a Trtp of 3 */
- val = 3;
- } else if (val == 5){
- val = 2;
+ if (val <= 2) { /* 7.75ns / Speed in ns to get clock # */
+ val = 2; /* for DDR400/DDR533 */
+ } else { /* Note a speed of 3 will be a Trtp of 3 */
+ val = 3; /* for DDR667/DDR800/DDR1066 */
}
pDCTstat->Trtp = val;
DramConfigMisc = 0;
DramConfigMisc2 = 0;
- /* set bank addessing and Masks, plus CS pops */
+ /* set bank addressing and Masks, plus CS pops */
SPDSetBanks_D(pMCTstat, pDCTstat, dct);
if (pDCTstat->ErrCode == SC_StopError)
goto AutoConfig_exit;
}
if (!(Status & (1 << SB_Registered)))
- DramConfigLo |= 1 << UnBuffDimm; /* Unbufferd DIMMs */
+ DramConfigLo |= 1 << UnBuffDimm; /* Unbuffered DIMMs */
if (mctGet_NVbits(NV_ECC_CAP))
if (Status & (1 << SB_ECCDIMMs))
if ( mctGet_NVbits(NV_ECC))
DramConfigLo |= 1 << DimmEcEn;
-
+ DramConfigLo = mct_DisDllShutdownSR(pMCTstat, pDCTstat, DramConfigLo, dct);
/* Build Dram Config Hi Register Value */
dword = pDCTstat->Speed;
/* SetCKETriState */
SetODTTriState(pMCTstat, pDCTstat, dct);
- if ( pDCTstat->Status & 1<<SB_128bitmode) {
+ if (pDCTstat->Status & (1 << SB_128bitmode)) {
SetCSTriState(pMCTstat, pDCTstat, 1); /* force dct1) */
SetODTTriState(pMCTstat, pDCTstat, 1); /* force dct1) */
}
reg = 0x40 + (q << 2) + reg_off; /* Base[q] reg.*/
val = Get_NB32(dev, reg);
if (!(val & 3)) { /* (CSEnable|Spare==1)bank is enabled already? */
- reg = 0x60 + (q << 1) + reg_off; /*Mask[q] reg.*/
+ reg = 0x60 + ((q << 1) & 0xc) + reg_off; /*Mask[q] reg.*/
val = Get_NB32(dev, reg);
val >>= 19;
val++;
pDCTstat->DimmECCPresent |= 1 << i;
}
if (byte & JED_ADRCPAR) {
- /* DIMM is ECC capable */
- pDCTstat->DimmPARPresent |= 1 << i;
+ /* DIMM is ECC capable */
+ pDCTstat->DimmPARPresent |= 1 << i;
}
/* Check if x4 device */
devwidth = mctRead_SPD(smbaddr, SPD_DEVWIDTH) & 0xFE;
mct_BeforeDramInit_Prod_D(pMCTstat, pDCTstat);
// FIXME: for rev A: mct_BeforeDramInit_D(pDCTstat, dct);
- /* Disable auto refresh before Dram init when in ganged mode */
- if (pDCTstat->GangedMode) {
- val = Get_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct));
- val |= 1 << DisAutoRefresh;
- Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val);
+ /* Disable auto refresh before Dram init when in ganged mode (Erratum 278) */
+ if (pDCTstat->LogicalCPUID & (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_BA)) {
+ if (pDCTstat->GangedMode) {
+ val = Get_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct));
+ val |= 1 << DisAutoRefresh;
+ Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val);
+ }
}
mct_DramInit_Hw_D(pMCTstat, pDCTstat, dct);
/* Re-enable auto refresh after Dram init when in ganged mode
- * to ensure both DCTs are in sync
+ * to ensure both DCTs are in sync (Erratum 278)
*/
- if (pDCTstat->GangedMode) {
- do {
- val = Get_NB32(pDCTstat->dev_dct, 0x90 + (0x100 * dct));
- } while (!(val & (1 << InitDram)));
-
- WaitRoutine_D(50);
-
- val = Get_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct));
- val &= ~(1 << DisAutoRefresh);
- val |= 1 << DisAutoRefresh;
- val &= ~(1 << DisAutoRefresh);
+ if (pDCTstat->LogicalCPUID & (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_BA)) {
+ if (pDCTstat->GangedMode) {
+ do {
+ val = Get_NB32(pDCTstat->dev_dct, 0x90 + (0x100 * dct));
+ } while (!(val & (1 << InitDram)));
+
+ WaitRoutine_D(50);
+
+ val = Get_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct));
+ val &= ~(1 << DisAutoRefresh);
+ Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val);
+ val |= 1 << DisAutoRefresh;
+ Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val);
+ val &= ~(1 << DisAutoRefresh);
+ Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val);
+ }
}
}
if (byte != bytex) {
pDCTstat->ErrStatus &= ~(1 << SB_DimmMismatchO);
} else {
- if ( mctGet_NVbits(NV_Unganged) )
- pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO);
+ if ( mctGet_NVbits(NV_Unganged) )
+ pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO);
if (!(pDCTstat->ErrStatus & (1 << SB_DimmMismatchO))) {
pDCTstat->GangedMode = 1;
u32 Get_NB32(u32 dev, u32 reg)
{
- u32 addr;
-
- addr = (dev>>4) | (reg & 0xFF) | ((reg & 0xf00)<<16);
- outl((1<<31) | (addr & ~3), 0xcf8);
-
- return inl(0xcfc);
+ return pci_read_config32(dev, reg);
}
void Set_NB32(u32 dev, u32 reg, u32 val)
{
- u32 addr;
-
- addr = (dev>>4) | (reg & 0xFF) | ((reg & 0xf00)<<16);
- outl((1<<31) | (addr & ~3), 0xcf8);
- outl(val, 0xcfc);
+ pci_write_config32(dev, reg, val);
}
if (!pDCTstat->GangedMode) {
dev = pDCTstat->dev_dct;
pDCTstat->NodeSysLimit += pDCTstat->DCTSysLimit;
- /* if DCT0 and DCT1 exist both, set DctSelBaseAddr[47:27] */
+ /* if DCT0 and DCT1 both exist, set DctSelBaseAddr[47:27] to the top of DCT0 */
if (dct == 0) {
if (pDCTstat->DIMMValidDCT[1] > 0) {
dword = pDCTstat->DCTSysLimit + 1;
pMCTstat->HoleBase = (DramHoleBase & 0xFFFFF800) << 8;
val = pMCTstat->HoleBase;
val >>= 16;
- val &= ~(0xFF);
- val |= (((~val) & 0xFF) + 1);
+ val = (((~val) & 0xFF) + 1);
val <<= 8;
dword += val;
}
val |= 3; /* Set F2x110[DctSelHiRngEn], F2x110[DctSelHi] */
Set_NB32(dev, reg, val);
print_tx("AfterStitch DCT0 and DCT1: DRAM Controller Select Low Register = ", val);
+ print_tx("AfterStitch DCT0 and DCT1: DRAM Controller Select High Register = ", dword);
reg = 0x114;
val = dword;
if (pDCTstat->DIMMValidDCT[0] == 0) {
dword = pDCTstat->NodeSysBase;
dword >>= 8;
- if (dword >= DramHoleBase) {
+ if ((dword >= DramHoleBase) && _MemHoleRemap) {
pMCTstat->HoleBase = (DramHoleBase & 0xFFFFF800) << 8;
val = pMCTstat->HoleBase;
val >>= 8;
val |= 3; /* Set F2x110[DctSelHiRngEn], F2x110[DctSelHi] */
Set_NB32(dev, reg, val);
print_tx("AfterStitch DCT1 only: DRAM Controller Select Low Register = ", val);
+ print_tx("AfterStitch DCT1 only: DRAM Controller Select High Register = ", dword);
}
}
} else {
dword = bsr(pDCTstat->DIMMValid);
if (dword != val && dword != 0) {
/*the largest WrDatGrossDlyByte of any DIMM minus the
- WrDatGrossDlyByte of any other DIMM is equal to CGDD */
+ WrDatGrossDlyByte of any other DIMM is equal to CGDD */
val = Get_WrDatGross_Diff(pDCTstat, dct, dev, index_reg);
}
if (val == 0)
static void Get_Twrrd(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstat, u8 dct)
{
- u8 byte, bytex;
+ u8 byte, bytex, val;
u32 index_reg = 0x98 + 0x100 * dct;
u32 dev = pDCTstat->dev_dct;
/* On any given byte lane, the largest WrDatGrossDlyByte delay of
any DIMM minus the DqsRcvEnGrossDelay delay of any other DIMM is
equal to the Critical Gross Delay Difference (CGDD) for Twrrd.*/
- pDCTstat->Twrrd = 0;
+
+ /* WrDatGrossDlyByte only use one set register when DDR400~DDR667
+ DDR800 have two set register for DIMM0 and DIMM1 */
+ if (pDCTstat->Speed > 3) {
+ val = Get_WrDatGross_Diff(pDCTstat, dct, dev, index_reg);
+ } else {
+ val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 1); /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM0 */
+ pDCTstat->WrDatGrossH = (u8) val; /* low byte = max value */
+ }
+
Get_DqsRcvEnGross_Diff(pDCTstat, dev, index_reg);
- Get_WrDatGross_Diff(pDCTstat, dct, dev, index_reg);
+
bytex = pDCTstat->DqsRcvEnGrossL;
byte = pDCTstat->WrDatGrossH;
if (byte > bytex) {
u8 i;
u32 val;
u8 byte;
+ u8 ecc_reg = 0;
Smallest_0 = 0xFF;
Smallest_1 = 0xFF;
Largest_0 = 0;
Largest_1 = 0;
+ if (index == 0x12)
+ ecc_reg = 1;
+
for (i=0; i < 8; i+=2) {
if ( pDCTstat->DIMMValid & (1 << i)) {
val = Get_NB32_index_wait(dev, index_reg, index);
Smallest_0 = byte;
if (byte > Largest_0)
Largest_0 = byte;
- byte = (val >> 16) & 0xFF;
- if (byte < Smallest_1)
- Smallest_1 = byte;
- if (byte > Largest_1)
- Largest_1 = byte;
+ if (!(ecc_reg)) {
+ byte = (val >> 16) & 0xFF;
+ if (byte < Smallest_1)
+ Smallest_1 = byte;
+ if (byte > Largest_1)
+ Largest_1 = byte;
+ }
}
index += 3;
} /* while ++i */
two DIMMs is less than half of a MEMCLK */
if ((Largest_0 - Smallest_0) > 31)
return 1;
- if ((Largest_1 - Smallest_1) > 31)
- return 1;
+ if (!(ecc_reg))
+ if ((Largest_1 - Smallest_1) > 31)
+ return 1;
return 0;
}
u8 byte;
u32 val;
u16 word;
+ u8 ecc_reg = 0;
Smallest = 7;
Largest = 0;
+ if (index == 0x12)
+ ecc_reg = 1;
+
for (i=0; i < 8; i+=2) {
if ( pDCTstat->DIMMValid & (1 << i)) {
val = Get_NB32_index_wait(dev, index_reg, index);
Smallest = byte;
if (byte > Largest)
Largest = byte;
- byte = (val >> (16 + 5)) & 0xFF;
- if (byte < Smallest)
- Smallest = byte;
- if (byte > Largest)
- Largest = byte;
+ if (!(ecc_reg)) {
+ byte = (val >> (16 + 5)) & 0xFF;
+ if (byte < Smallest)
+ Smallest = byte;
+ if (byte > Largest)
+ Largest = byte;
+ }
}
- index += 3;
+ index += 3;
} /* while ++i */
word = Smallest;
print_t("\tmct_FinalMCT_D: Clr Cl, Wb\n");
- mct_ClrClToNB_D(pMCTstat, pDCTstat);
+ /* ClrClToNB_D postponed until we're done executing from ROM */
mct_ClrWbEnhWsbDis_D(pMCTstat, pDCTstat);
}
dev = pDCTstat->dev_map;
/* Copy dram map from F1x40/44,F1x48/4c,
- to F1x120/124(Node0),F1x120/124(Node1),...*/
+ to F1x120/124(Node0),F1x120/124(Node1),...*/
for (Node=0; Node < MAX_NODES_SUPPORTED; Node++) {
pDCTstat = pDCTstatA + Node;
devx = pDCTstat->dev_map;
}
-
+#ifdef UNUSED_CODE
static void SetCKETriState(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstat, u8 dct)
{
Set_NB32_index_wait(dev, index_reg, index, val);
}
-
+#endif
static void SetODTTriState(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstat, u8 dct)
u32 index_reg = 0x98 + 0x100 * dct;
u8 cs;
u32 index;
- u16 word;
-
- /* Tri-state unused ODTs when motherboard termination is available */
+ u8 odt;
+ u8 max_dimms;
// FIXME: skip for Ax
dev = pDCTstat->dev_dct;
- word = 0;
+
+ /* Tri-state unused ODTs when motherboard termination is available */
+ max_dimms = (u8) mctGet_NVbits(NV_MAX_DIMMS);
+ odt = 0x0F; /* tristate all the pins then clear the used ones. */
+
for (cs = 0; cs < 8; cs += 2) {
- if (!(pDCTstat->CSPresent & (1 << cs))) {
- if (!(pDCTstat->CSPresent & (1 << (cs + 1))))
- word |= (1 << (cs >> 1));
+ if (pDCTstat->CSPresent & (1 << cs)) {
+ odt &= ~(1 << (cs / 2));
+
+ /* if quad-rank capable platform clear additional pins */
+ if (max_dimms != MAX_CS_SUPPORTED) {
+ if (pDCTstat->CSPresent & (1 << (cs + 1)))
+ odt &= ~(4 << (cs / 2));
+ }
}
}
index = 0x0C;
val = Get_NB32_index_wait(dev, index_reg, index);
- val |= (word << 8);
+ val |= (odt << 8);
Set_NB32_index_wait(dev, index_reg, index, val);
+
}
}
/* Override/Exception */
- if ((pDCTstat->Speed == 2) && (pDCTstat->MAdimms[dct] == 4))
- dword &= 0xF18FFF18;
+ if (!pDCTstat->GangedMode) {
+ i = 0; /* use i for the dct setting required */
+ if (pDCTstat->MAdimms[0] < 4)
+ i = 1;
+ if (((pDCTstat->Speed == 2) || (pDCTstat->Speed == 3)) && (pDCTstat->MAdimms[i] == 4)) {
+ dword &= 0xF18FFF18;
+ index_reg = 0x98; /* force dct = 0 */
+ }
+ }
Set_NB32_index_wait(dev, index_reg, 0x0a, dword);
}
u8 Node;
u32 i;
struct DCTStatStruc *pDCTstat;
- u16 start, stop;
+ u32 start, stop;
u8 *p;
u16 host_serv1, host_serv2;
p = (u8 *) pDCTstat;
start = 0;
- stop = ((u16) &((struct DCTStatStruc *)0)->CH_MaxRdLat[2]);
+ stop = (u32)(&((struct DCTStatStruc *)0)->CH_MaxRdLat[2]);
for (i = start; i < stop ; i++) {
p[i] = 0;
}
- start = ((u16) &((struct DCTStatStruc *)0)->CH_D_BC_RCVRDLY[2][4]);
+ start = (u32)(&((struct DCTStatStruc *)0)->CH_D_BC_RCVRDLY[2][4]);
stop = sizeof(struct DCTStatStruc);
for (i = start; i < stop; i++) {
p[i] = 0;
}
-void mct_AdjustDelayRange_D(struct MCTStatStruc *pMCTstat,
+static void mct_AdjustDelayRange_D(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstat, u8 *dqs_pos)
{
// FIXME: Skip for Ax
}
}
+static u32 mct_DisDllShutdownSR(struct MCTStatStruc *pMCTstat,
+ struct DCTStatStruc *pDCTstat, u32 DramConfigLo, u8 dct)
+{
+ u32 reg_off = 0x100 * dct;
+ u32 dev = pDCTstat->dev_dct;
+
+ /* Write 0000_07D0h to register F2x[1, 0]98_x4D0FE006 */
+ if (pDCTstat->LogicalCPUID & (AMD_DA_C2 | AMD_RB_C3)) {
+ Set_NB32(dev, 0x9C + reg_off, 0x7D0);
+ Set_NB32(dev, 0x98 + reg_off, 0x4D0FE006);
+ Set_NB32(dev, 0x9C + reg_off, 0x190);
+ Set_NB32(dev, 0x98 + reg_off, 0x4D0FE007);
+ }
+
+ return DramConfigLo | /* DisDllShutdownSR */ 1 << 27;
+}
+
+static void mct_EnDllShutdownSR(struct MCTStatStruc *pMCTstat,
+ struct DCTStatStruc *pDCTstat, u8 dct)
+{
+ u32 reg_off = 0x100 * dct;
+ u32 dev = pDCTstat->dev_dct, val;
+
+ /* Write 0000_07D0h to register F2x[1, 0]98_x4D0FE006 */
+ if (pDCTstat->LogicalCPUID & (AMD_DA_C2 | AMD_RB_C3)) {
+ Set_NB32(dev, 0x9C + reg_off, 0x1C);
+ Set_NB32(dev, 0x98 + reg_off, 0x4D0FE006);
+ Set_NB32(dev, 0x9C + reg_off, 0x13D);
+ Set_NB32(dev, 0x98 + reg_off, 0x4D0FE007);
+
+ val = Get_NB32(dev, 0x90 + reg_off);
+ val &= ~(1 << 27/* DisDllShutdownSR */);
+ Set_NB32(dev, 0x90 + reg_off, val);
+ }
+}
void mct_SetClToNB_D(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstat)
Set_NB32_index_wait(dev, index_reg, index, val | (1 << DisAutoComp));
//FIXME: check for Bx Cx CPU
- // if Ax mct_SetDramConfigHi_Samp_D
+ // if Ax mct_SetDramConfigHi_Samp_D
/* errata#177 */
index = 0x4D014F00; /* F2x[1, 0]9C_x[D0FFFFF:D000000] DRAM Phy Debug Registers */
* Silicon Status: Fixed In Rev B0
*
* Bug#15880: Determine validity of reset settings for DDR PHY timing.
- * Solutiuon: At least, set WrDqs fine delay to be 0 for DDR2 training.
+ * Solution: At least, set WrDqs fine delay to be 0 for DDR2 training.
*/
for (Node = 0; Node < 8; Node++) {
pDCTstat = pDCTstatA + Node;
- if (pDCTstat->NodePresent)
+ if (pDCTstat->NodePresent) {
mct_BeforeDQSTrain_Samp_D(pMCTstat, pDCTstat);
mct_ResetDLL_D(pMCTstat, pDCTstat, 0);
mct_ResetDLL_D(pMCTstat, pDCTstat, 1);
-
+ }
}
}
struct DCTStatStruc *pDCTstat, u8 dct)
{
u8 Receiver;
- u32 val;
u32 dev = pDCTstat->dev_dct;
u32 reg_off = 0x100 * dct;
u32 addr;
+ u32 lo, hi;
+ u8 wrap32dis = 0;
u8 valid = 0;
+ /* Skip reset DLL for B3 */
+ if (pDCTstat->LogicalCPUID & AMD_DR_B3) {
+ return;
+ }
+
+ addr = HWCR;
+ _RDMSR(addr, &lo, &hi);
+ if(lo & (1<<17)) { /* save the old value */
+ wrap32dis = 1;
+ }
+ lo |= (1<<17); /* HWCR.wrap32dis */
+ lo &= ~(1<<15); /* SSEDIS */
+ /* Setting wrap32dis allows 64-bit memory references in 32bit mode */
+ _WRMSR(addr, lo, hi);
+
+
pDCTstat->Channel = dct;
Receiver = mct_InitReceiver_D(pDCTstat, dct);
/* there are four receiver pairs, loosely associated with chipselects.*/
addr = mct_GetRcvrSysAddr_D(pMCTstat, pDCTstat, dct, Receiver, &valid);
if (valid) {
mct_Read1LTestPattern_D(pMCTstat, pDCTstat, addr); /* cache fills */
- Set_NB32(dev, 0x98 + reg_off, 0x0D00000C);
- val = Get_NB32(dev, 0x9C + reg_off);
- val |= 1 << 15;
- Set_NB32(dev, 0x9C + reg_off, val);
- Set_NB32(dev, 0x98 + reg_off, 0x4D0F0F0C);
- mct_Wait_10ns(60); /* wait >= 300ns */
-
- Set_NB32(dev, 0x98 + reg_off, 0x0D00000C);
- val = Get_NB32(dev, 0x9C + reg_off);
- val &= ~(1 << 15);
- Set_NB32(dev, 0x9C + reg_off, val);
- Set_NB32(dev, 0x98 + reg_off, 0x4D0F0F0C);
- mct_Wait_10ns(400); /* wait >= 2us */
+
+ /* Write 0000_8000h to register F2x[1,0]9C_xD080F0C */
+ Set_NB32_index_wait(dev, 0x98 + reg_off, 0x4D080F0C, 0x00008000);
+ mct_Wait(80); /* wait >= 300ns */
+
+ /* Write 0000_0000h to register F2x[1,0]9C_xD080F0C */
+ Set_NB32_index_wait(dev, 0x98 + reg_off, 0x4D080F0C, 0x00000000);
+ mct_Wait(800); /* wait >= 2us */
break;
}
}
}
+ if(!wrap32dis) {
+ addr = HWCR;
+ _RDMSR(addr, &lo, &hi);
+ lo &= ~(1<<17); /* restore HWCR.wrap32dis */
+ _WRMSR(addr, lo, hi);
+ }
}
// FIXME Skip for Cx
dev = pDCTstat->dev_nbmisc;
val = Get_NB32(dev, 0x8C); // NB Configuration Hi
- val |= 36-32; // DisDatMask
+ val |= 1 << (36-32); // DisDatMask
Set_NB32(dev, 0x8C, val);
}
}
-
+#ifdef UNUSED_CODE
static void mct_SetupSync_D(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstat)
{
Set_NB32(dev, 0x78, val);
}
}
+#endif
static void AfterDramInit_D(struct DCTStatStruc *pDCTstat, u8 dct) {
u32 reg_off = 0x100 * dct;
u32 dev = pDCTstat->dev_dct;
- if (pDCTstat->LogicalCPUID & AMD_DR_B2) {
- mct_Wait_10ns(5000); /* Wait 50 us*/
+ if (pDCTstat->LogicalCPUID & (AMD_DR_B2 | AMD_DR_B3)) {
+ mct_Wait(10000); /* Wait 50 us*/
val = Get_NB32(dev, 0x110);
if ( val & (1 << DramEnabled)) {
/* If 50 us expires while DramEnable =0 then do the following */