2 * This file is part of the coreboot project.
4 * Copyright (C) 2007 Advanced Micro Devices, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 static u32 CheckNBCOFAutoPrechg(struct DCTStatStruc *pDCTstat, u32 dct);
22 static u8 mct_AdjustDQSPosDelay_D(struct DCTStatStruc *pDCTstat, u8 dly);
24 void EarlySampleSupport_D(void)
29 u32 procOdtWorkaround(struct DCTStatStruc *pDCTstat, u32 dct, u32 val)
32 tmp = pDCTstat->LogicalCPUID;
33 if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
35 if(pDCTstat->MAdimms[dct] > 1)
43 u32 OtherTiming_A_D(struct DCTStatStruc *pDCTstat, u32 val)
45 /* Bug#10695:One MEMCLK Bubble Writes Don't Do X4 X8 Switching Correctly
46 * Solution: BIOS should set DRAM Timing High[Twrwr] > 00b
47 * ( F2x[1, 0]8C[1:0] > 00b). Silicon Status: Fixed in Rev B
48 * FIXME: check if this is still required.
51 tmp = pDCTstat->LogicalCPUID;
52 if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
60 void mct_ForceAutoPrecharge_D(struct DCTStatStruc *pDCTstat, u32 dct)
68 tmp = pDCTstat->LogicalCPUID;
69 if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
70 if(CheckNBCOFAutoPrechg(pDCTstat, dct)) {
71 dev = pDCTstat->dev_dct;
72 reg_off = 0x100 * dct;
73 reg = 0x90 + reg_off; /* Dram Configuration Lo */
74 val = Get_NB32(dev, reg);
75 val |= 1<<ForceAutoPchg;
76 if(!pDCTstat->GangedMode)
77 val |= 1<<BurstLength32;
78 Set_NB32(dev, reg, val);
80 reg = 0x88 + reg_off; /* cx=Dram Timing Lo */
81 val = Get_NB32(dev, reg);
82 val |= 0x000F0000; /* Trc = 0Fh */
83 Set_NB32(dev, reg, val);
89 void mct_EndDQSTraining_D(struct MCTStatStruc *pMCTstat,
90 struct DCTStatStruc *pDCTstatA)
92 /* Bug#13341: Prefetch is getting killed when the limit is reached in
94 * Solution: Explicitly clear the PrefDramTrainMode bit after training
95 * sequence in order to ensure resumption of normal HW prefetch
97 * NOTE -- this has been documented with a note at the end of this
98 * section in the BKDG (although, admittedly, the note does not really
100 * Silicon Status: Fixed in Rev B ( confirm)
110 for(Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
111 struct DCTStatStruc *pDCTstat;
112 pDCTstat = pDCTstatA + Node;
114 if(!pDCTstat->NodePresent) break;
116 tmp = pDCTstat->LogicalCPUID;
117 if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
118 dev = pDCTstat->dev_dct;
120 val = Get_NB32(dev, reg);
121 val &= ~(1<<PrefDramTrainMode);
122 Set_NB32(dev, reg, val);
130 void mct_BeforeDQSTrain_Samp_D(struct MCTStatStruc *pMCTstat,
131 struct DCTStatStruc *pDCTstat)
133 /* Bug#15115: Uncertainty In The Sync Chain Leads To Setup Violations
135 * Solution: BIOS should program DRAM Control Register[RdPtrInit] = 5h,
136 * (F2x[1, 0]78[3:0] = 5h).
137 * Silicon Status: Fixed In Rev B0
140 /* Bug#15880: Determine validity of reset settings for DDR PHY timing
142 * Solutiuon: At least, set WrDqs fine delay to be 0 for DDR2 training.
155 tmp = pDCTstat->LogicalCPUID;
156 if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
158 dev = pDCTstat->dev_dct;
161 for(Channel = 0; Channel<2; Channel++) {
162 index_reg = 0x98 + 0x100 * Channel;
163 val = Get_NB32_index_wait(dev, index_reg, 0x0d004007);
165 Set_NB32_index_wait(dev, index_reg, 0x0d0f4f07, val);
168 for(Channel = 0; Channel<2; Channel++) {
169 if(pDCTstat->GangedMode && Channel)
171 reg_off = 0x100 * Channel;
172 reg = 0x78 + reg_off;
173 val = Get_NB32(dev, reg);
176 Set_NB32(dev, reg, val);
179 for(Channel = 0; Channel<2; Channel++) {
180 reg_off = 0x100 * Channel;
182 index_reg = 0x98 + reg_off;
183 for( index = 0x30; index < (0x45 + 1); index++) {
184 Set_NB32_index_wait(dev, index_reg, index, val);
192 u32 Modify_D3CMP(struct DCTStatStruc *pDCTstat, u32 dct, u32 value)
194 /* Errata#189: Reads To Phy Driver Calibration Register and Phy
195 * Predriver Calibration Register Do Not Return Bit 27.
196 * Solution: See #41322 for details.
197 * BIOS can modify bit 27 of the Phy Driver Calibration register
199 * 1. Read F2x[1, 0]9C_x09
200 * 2. Read F2x[1, 0]9C_x0D004201
201 * 3. Set F2x[1, 0]9C_x09[27] = F2x[1, 0]9C_x0D004201[10]
202 * BIOS can modify bit 27 of the Phy Predriver Calibration register
204 * 1. Read F2x[1, 0]9C_x0A
205 * 2. Read F2x[1, 0]9C_x0D004209
206 * 3. Set F2x[1, 0]9C_x0A[27] = F2x[1, 0]9C_x0D004209[10]
207 * Silicon Status: Fixed planned for DR-B0
216 tmp = pDCTstat->LogicalCPUID;
217 if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
218 dev = pDCTstat->dev_dct;
219 index_reg = 0x98 + 0x100 * dct;
221 val = Get_NB32_index_wait(dev, index_reg, index);
223 value |= ((val>>10) & 1) << 27;
229 void SyncSetting(struct DCTStatStruc *pDCTstat)
231 /* Errata#198: AddrCmdSetup, CsOdtSetup, and CkeSetup Require Identical
232 * Programming For Both Channels in Ganged Mode
233 * Solution: The BIOS must program the following DRAM timing parameters
234 * the same for both channels:
235 * 1. F2x[1, 0]9C_x04[21] (AddrCmdSetup)
236 * 2. F2x[1, 0]9C_x04[15] (CsOdtSetup)
237 * 3. F2x[1, 0]9C_x04[5]) (CkeSetup)
238 * That is, if the AddrCmdSetup, CsOdtSetup, or CkeSetup is
239 * set to 1'b1 for one of the controllers, then the corresponding
240 * AddrCmdSetup, CsOdtSetup, or CkeSetup must be set to 1'b1 for the
242 * Silicon Status: Fix TBD
246 tmp = pDCTstat->LogicalCPUID;
247 if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
248 pDCTstat->CH_ODC_CTL[1] = pDCTstat->CH_ODC_CTL[0];
249 pDCTstat->CH_ADDR_TMG[1] = pDCTstat->CH_ADDR_TMG[0];
254 static u32 CheckNBCOFAutoPrechg(struct DCTStatStruc *pDCTstat, u32 dct)
263 /* 3 * (Fn2xD4[NBFid]+4)/(2^NbDid)/(3+Fn2x94[MemClkFreq]) */
265 _RDMSR(msr, &lo, &hi);
266 NbDid = (lo>>22) & 1;
268 val = Get_NB32(pDCTstat->dev_dct, 0x94 + 0x100 * dct);
269 valx = ((val & 0x07) + 3)<<NbDid;
270 print_tx("MemClk:", valx >> NbDid);
272 val = Get_NB32(pDCTstat->dev_nbmisc, 0xd4);
273 valy = ((val & 0x1f) + 4) * 3;
274 print_tx("NB COF:", valy >> NbDid);
277 if((val==3) && (valy%valx)) /* 3 < NClk/MemClk < 4 */
284 void mct_BeforeDramInit_D(struct DCTStatStruc *pDCTstat, u32 dct)
288 u32 ch, ch_start, ch_end;
295 tmp = pDCTstat->LogicalCPUID;
296 if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
297 Speed = pDCTstat->Speed;
298 /* MemClkFreq = 333MHz or 533Mhz */
299 if((Speed == 3) || (Speed == 2)) {
300 if(pDCTstat->GangedMode) {
307 dev = pDCTstat->dev_dct;
309 for(ch=ch_start; ch<ch_end; ch++) {
310 index_reg = 0x98 + 0x100 * ch;
311 val = Get_NB32_index(dev, index_reg, 0x0D00E001);
314 Set_NB32_index(dev, index_reg, 0x0D01E001, val);
322 static u8 mct_AdjustDelay_D(struct DCTStatStruc *pDCTstat, u8 dly)
326 if ((dly >= MIN_FENCE) && (dly <= MAX_FENCE))
333 static u8 mct_checkFenceHoleAdjust_D(struct MCTStatStruc *pMCTstat,
334 struct DCTStatStruc *pDCTstat, u8 DQSDelay,
335 u8 ChipSel, u8 *result)
340 tmp = pDCTstat->LogicalCPUID;
341 if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
342 if (pDCTstat->Direction == DQS_WRITEDIR) {
343 if ((pDCTstat->Speed == 2) || (pDCTstat->Speed == 3)) {
345 if (*result == 0xFF) {
346 for (ByteLane = 0; ByteLane < 8; ByteLane++) {
347 pDCTstat->DQSDelay = 13;
348 pDCTstat->ByteLane = ByteLane;
349 /* store the value into the data structure */
350 StoreDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel);
356 if (mct_AdjustDQSPosDelay_D(pDCTstat, DQSDelay)) {
365 static u8 mct_AdjustDQSPosDelay_D(struct DCTStatStruc *pDCTstat, u8 dly)
370 if ((dly >= MIN_DQS_WR_FENCE) && (dly <= MAX_DQS_WR_FENCE))
377 static void beforeInterleaveChannels_D(struct DCTStatStruc *pDCTstatA, u8 *enabled) {
379 if (pDCTstatA->LogicalCPUID & (AMD_DR_Ax))
384 static u8 mctDoAxRdPtrInit_D(struct DCTStatStruc *pDCTstat, u8 *Rdtr)
388 tmp = pDCTstat->LogicalCPUID;
389 if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
397 static void mct_AdjustScrub_D(struct DCTStatStruc *pDCTstat, u16 *scrub_request) {
399 /* Erratum #202: disable DCache scrubber for Ax parts */
401 if (pDCTstat->LogicalCPUID & (AMD_DR_Ax)) {
403 pDCTstat->ErrStatus |= 1 << SB_DCBKScrubDis;