void mct_ForceAutoPrecharge_D(struct DCTStatStruc *pDCTstat, u32 dct) { uint64_t tmp; u32 reg; u32 reg_off; u32 dev; u32 val; tmp = pDCTstat->LogicalCPUID; if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) { if (CheckNBCOFAutoPrechg(pDCTstat, dct)) { dev = pDCTstat->dev_dct; reg_off = 0x100 * dct; reg = 0x90 + reg_off; /* Dram Configuration Lo */ val = Get_NB32(dev, reg); val |= 1<<ForceAutoPchg; if (!pDCTstat->GangedMode) val |= 1<<BurstLength32; Set_NB32(dev, reg, val); reg = 0x88 + reg_off; /* cx=Dram Timing Lo */ val = Get_NB32(dev, reg); val |= 0x000F0000; /* Trc = 0Fh */ Set_NB32(dev, reg, val); } } }
static inline uint32_t Get_NB32_DCT(uint32_t dev, uint8_t dct, uint32_t reg) { if (is_fam15h()) { /* Obtain address of function 0x1 */ uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12); fam15h_switch_dct(dev_map, dct); return Get_NB32(dev, reg); } else { return Get_NB32(dev, (0x100 * dct) + reg); } }
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] = MaxRdLatVal; } else { pDCTstat->CH_MaxRdLat[Channel] = MaxRdLatVal; } dev = pDCTstat->dev_dct; reg = 0x78 + Channel * 0x100; val = Get_NB32(dev, reg); val &= ~(0x3ff<<22); val |= MaxRdLatVal << 22; /* program MaxRdLatency to correspond with current delay */ Set_NB32(dev, reg, val); }
static void vErratum414(struct DCTStatStruc *pDCTstat) { int dct=0; for(; dct < 2 ; dct++) { int dRAMConfigHi = Get_NB32(pDCTstat->dev_dct,0x94 + (0x100 * dct)); int powerDown = dRAMConfigHi & (1 << PowerDownEn ); int ddr3 = dRAMConfigHi & (1 << Ddr3Mode ); int dRAMMRS = Get_NB32(pDCTstat->dev_dct,0x84 + (0x100 * dct)); int pchgPDModeSel = dRAMMRS & (1 << PchgPDModeSel); if (powerDown && ddr3 && pchgPDModeSel ) { Set_NB32(pDCTstat->dev_dct,0x84 + (0x100 * dct), dRAMMRS & ~(1 << PchgPDModeSel) ); } } }
void mct_BeforeDQSTrain_Samp_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat) { /* Bug#15115: Uncertainty In The Sync Chain Leads To Setup Violations * In TX FIFO * Solution: BIOS should program DRAM Control Register[RdPtrInit] = 5h, * (F2x[1, 0]78[3:0] = 5h). * Silicon Status: Fixed In Rev B0 */ /* Bug#15880: Determine validity of reset settings for DDR PHY timing * regi.. * Solution: At least, set WrDqs fine delay to be 0 for DDR2 training. */ u32 dev; u32 reg_off; u32 index_reg; u32 index; u32 reg; u32 val; u32 tmp; u32 Channel; tmp = pDCTstat->LogicalCPUID; if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) { dev = pDCTstat->dev_dct; index = 0; for(Channel = 0; Channel<2; Channel++) { index_reg = 0x98 + 0x100 * Channel; val = Get_NB32_index_wait(dev, index_reg, 0x0d004007); val |= 0x3ff; Set_NB32_index_wait(dev, index_reg, 0x0d0f4f07, val); } for(Channel = 0; Channel<2; Channel++) { if(pDCTstat->GangedMode && Channel) break; reg_off = 0x100 * Channel; reg = 0x78 + reg_off; val = Get_NB32(dev, reg); val &= ~(0x07); val |= 5; Set_NB32(dev, reg, val); } for(Channel = 0; Channel<2; Channel++) { reg_off = 0x100 * Channel; val = 0; index_reg = 0x98 + reg_off; for( index = 0x30; index < (0x45 + 1); index++) { Set_NB32_index_wait(dev, index_reg, index, val); } } } }
static inline void fam15h_switch_nb_pstate_config_reg(uint32_t dev, uint8_t nb_pstate) { uint32_t dword; dword = Get_NB32(dev, 0x10c); dword &= ~(0x3 << 4); dword |= (nb_pstate & 0x3) << 4; Set_NB32(dev, 0x10c, dword); }
static inline void fam15h_switch_dct(uint32_t dev, uint8_t dct) { uint32_t dword; dword = Get_NB32(dev, 0x10c); dword &= ~0x1; dword |= (dct & 0x1); Set_NB32(dev, 0x10c, dword); }
void mct_BeforeDQSTrainSamp(struct DCTStatStruc *pDCTstat) { u32 val; if (pDCTstat->LogicalCPUID & AMD_DR_Bx) { Set_NB32(pDCTstat->dev_dct, 0x98, 0x0D004007); val = Get_NB32(pDCTstat->dev_dct, 0x9C); val |= 0x3FF; Set_NB32(pDCTstat->dev_dct, 0x9C, val); Set_NB32(pDCTstat->dev_dct, 0x98, 0x4D0F4F07); Set_NB32(pDCTstat->dev_dct, 0x198, 0x0D004007); val = Get_NB32(pDCTstat->dev_dct, 0x19C); val |= 0x3FF; Set_NB32(pDCTstat->dev_dct, 0x19C, val); Set_NB32(pDCTstat->dev_dct, 0x198, 0x4D0F4F07); } }
static void set_fam10_ext_cfg_enable_bits(pci_devfn_t fam10_dev, u32 reg_pos, u32 mask, u32 val) { u32 reg_old, reg; reg = reg_old = Get_NB32(fam10_dev, reg_pos); reg &= ~mask; reg |= val; if (reg != reg_old) { Set_NB32(fam10_dev, reg_pos, reg); } }
void mct_DramInit_Hw_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct) { u32 val; u32 reg; u32 dev = pDCTstat->dev_dct; /*flag for selecting HW/SW DRAM Init HW DRAM Init */ reg = 0x90 + 0x100 * dct; /*DRAM Configuration Low */ val = Get_NB32(dev, reg); val |= (1<<InitDram); Set_NB32(dev, reg, val); }
void mct_ExtMCTConfig_Dx(struct DCTStatStruc *pDCTstat) { uint32_t dword; if (pDCTstat->LogicalCPUID & AMD_DR_Dx) { dword = 0x0ce00f00 | 0x1 << 29; /* FlushWrOnStpGnt */ if (!(pDCTstat->GangedMode)) dword |= 0x18 << 2; /* MctWrLimit = 0x18 for unganged mode */ else dword |= 0x10 << 2; /* MctWrLimit = 0x10 for ganged mode */ Set_NB32(pDCTstat->dev_dct, 0x11c, dword); dword = Get_NB32(pDCTstat->dev_dct, 0x1b0); dword &= ~0x3; /* AdapPrefMissRatio = 0x1 */ dword |= 0x1; dword &= ~(0x3 << 2); /* AdapPrefPositiveStep = 0x0 */ dword &= ~(0x3 << 4); /* AdapPrefNegativeStep = 0x0 */ dword &= ~(0x7 << 8); /* CohPrefPrbLmt = 0x1 */ dword |= (0x1 << 8); dword |= (0x7 << 22); /* PrefFourConf = 0x7 */ dword |= (0x7 << 25); /* PrefFiveConf = 0x7 */ if (!(pDCTstat->GangedMode)) dword |= (0x1 << 12); /* EnSplitDctLimits = 0x1 */ else dword &= ~(0x1 << 12); /* EnSplitDctLimits = 0x0 */ dword &= ~(0xf << 28); /* DcqBwThrotWm = ... */ switch (pDCTstat->Speed) { case 4: dword |= (0x5 << 28); /* ...5 for DDR800 */ break; case 5: dword |= (0x6 << 28); /* ...6 for DDR1066 */ break; case 6: dword |= (0x8 << 28); /* ...8 for DDR800 */ break; default: dword |= (0x9 << 28); /* ...9 for DDR1600 */ break; } Set_NB32(pDCTstat->dev_dct, 0x1b0, dword); } }
void mct_EndDQSTraining_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA) { /* Bug#13341: Prefetch is getting killed when the limit is reached in * PrefDramTrainMode * Solution: Explicitly clear the PrefDramTrainMode bit after training * sequence in order to ensure resumption of normal HW prefetch * behavior. * NOTE -- this has been documented with a note at the end of this * section in the BKDG (although, admittedly, the note does not really * stand out). * Silicon Status: Fixed in Rev B ( confirm) * FIXME: check this. */ uint64_t tmp; u32 dev; u32 reg; u32 val; u32 Node; for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { struct DCTStatStruc *pDCTstat; pDCTstat = pDCTstatA + Node; if (!pDCTstat->NodePresent) break; tmp = pDCTstat->LogicalCPUID; if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) { dev = pDCTstat->dev_dct; reg = 0x11c; val = Get_NB32(dev, reg); val &= ~(1<<PrefDramTrainMode); Set_NB32(dev, reg, val); } } }
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 reg_off; u32 dev; if (pDCTstat->GangedMode) Channel = 0; index_reg = 0x98 + 0x100 * Channel; reg_off = 0x100 * Channel; dev = pDCTstat->dev_dct; /* Multiply the CAS Latency by two to get a number of 1/2 MEMCLKs units.*/ val = Get_NB32(dev, 0x88 + reg_off); 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(dev, 0x90 + reg_off); 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(dev, 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(dev, 0x78 + reg_off); 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(dev, 0x94 + reg_off); /* SubTotal div 4 to scale 1/4 MemClk back to MemClk */ val &= 7; if (val == 4) { val++; /* adjust for DDR2-1066 */ } valx = (val + 3) << 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; }