static inline uint32_t Get_NB32_index_wait_DCT(uint32_t dev, uint8_t dct, uint32_t index_reg, uint32_t index) { 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_index_wait(dev, index_reg, index); } else { return Get_NB32_index_wait(dev, (0x100 * dct) + index_reg, index); } }
u32 Modify_D3CMP(struct DCTStatStruc *pDCTstat, u32 dct, u32 value) { /* Errata#189: Reads To Phy Driver Calibration Register and Phy * Predriver Calibration Register Do Not Return Bit 27. * Solution: See #41322 for details. * BIOS can modify bit 27 of the Phy Driver Calibration register * as follows: * 1. Read F2x[1, 0]9C_x09 * 2. Read F2x[1, 0]9C_x0D004201 * 3. Set F2x[1, 0]9C_x09[27] = F2x[1, 0]9C_x0D004201[10] * BIOS can modify bit 27 of the Phy Predriver Calibration register * as follows: * 1. Read F2x[1, 0]9C_x0A * 2. Read F2x[1, 0]9C_x0D004209 * 3. Set F2x[1, 0]9C_x0A[27] = F2x[1, 0]9C_x0D004209[10] * Silicon Status: Fixed planned for DR-B0 */ u32 dev; u32 index_reg; u32 index; u32 val; uint64_t tmp; tmp = pDCTstat->LogicalCPUID; if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) { dev = pDCTstat->dev_dct; index_reg = 0x98 + 0x100 * dct; index = 0x0D004201; val = Get_NB32_index_wait(dev, index_reg, index); value &= ~(1<<27); value |= ((val>>10) & 1) << 27; }
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); } } } }
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; }