Please bear with me - another rename checkin. This qualifies as trivial, no
[coreboot.git] / src / northbridge / amd / amdmct / mct / mctpro_d.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2007 Advanced Micro Devices, Inc.
5  *
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.
9  *
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.
14  *
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
18  */
19
20
21 static u32 CheckNBCOFAutoPrechg(struct DCTStatStruc *pDCTstat, u32 dct);
22 static u8 mct_AdjustDQSPosDelay_D(struct DCTStatStruc *pDCTstat, u8 dly);
23
24 void EarlySampleSupport_D(void)
25 {
26 }
27
28
29 u32 procOdtWorkaround(struct DCTStatStruc *pDCTstat, u32 dct, u32 val)
30 {
31         u32 tmp;
32         tmp = pDCTstat->LogicalCPUID;
33         if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
34                 val &= 0x0FFFFFFF;
35                 if(pDCTstat->MAdimms[dct] > 1)
36                         val |= 0x10000000;
37         }
38
39         return val;
40 }
41
42
43 u32 OtherTiming_A_D(struct DCTStatStruc *pDCTstat, u32 val)
44 {
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.
49          */
50         u32 tmp;
51         tmp = pDCTstat->LogicalCPUID;
52         if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
53                 if(!(val & (3<<12) ))
54                         val |= 1<<12;
55         }
56         return val;
57 }
58
59
60 void mct_ForceAutoPrecharge_D(struct DCTStatStruc *pDCTstat, u32 dct)
61 {
62         u32 tmp;
63         u32 reg;
64         u32 reg_off;
65         u32 dev;
66         u32 val;
67
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);
79
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);
84                 }
85         }
86 }
87
88
89 void mct_EndDQSTraining_D(struct MCTStatStruc *pMCTstat,
90                                 struct DCTStatStruc *pDCTstatA)
91 {
92         /* Bug#13341: Prefetch is getting killed when the limit is reached in
93          * PrefDramTrainMode
94          * Solution: Explicitly clear the PrefDramTrainMode bit after training
95          * sequence in order to ensure resumption of normal HW prefetch
96          * behavior.
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
99          * stand out).
100          * Silicon Status: Fixed in Rev B ( confirm)
101          * FIXME: check this.
102          */
103
104         u32 tmp;
105         u32 dev;
106         u32 reg;
107         u32 val;
108         u32 Node;
109
110         for(Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
111                 struct DCTStatStruc *pDCTstat;
112                 pDCTstat = pDCTstatA + Node;
113
114                 if(!pDCTstat->NodePresent) break;
115
116                 tmp = pDCTstat->LogicalCPUID;
117                 if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
118                         dev = pDCTstat->dev_dct;
119                         reg = 0x11c;
120                         val = Get_NB32(dev, reg);
121                         val &= ~(1<<PrefDramTrainMode);
122                         Set_NB32(dev, reg, val);
123                 }
124         }
125 }
126
127
128
129
130 void mct_BeforeDQSTrain_Samp_D(struct MCTStatStruc *pMCTstat,
131                                 struct DCTStatStruc *pDCTstat)
132 {
133         /* Bug#15115: Uncertainty In The Sync Chain Leads To Setup Violations
134          *  In TX FIFO
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
138          */
139
140         /* Bug#15880: Determine validity of reset settings for DDR PHY timing
141          *   regi..
142          * Solutiuon: At least, set WrDqs fine delay to be 0 for DDR2 training.
143          */
144
145         u32 dev;
146         u32 reg_off;
147         u32 index_reg;
148         u32 index;
149         u32 reg;
150         u32 val;
151         u32 tmp;
152         u32 Channel;
153
154
155         tmp = pDCTstat->LogicalCPUID;
156         if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
157
158                 dev = pDCTstat->dev_dct;
159                 index = 0;
160
161                 for(Channel = 0; Channel<2; Channel++) {
162                         index_reg = 0x98 + 0x100 * Channel;
163                         val = Get_NB32_index_wait(dev, index_reg, 0x0d004007);
164                         val |= 0x3ff;
165                         Set_NB32_index_wait(dev, index_reg, 0x0d0f4f07, val);
166                 }
167
168                 for(Channel = 0; Channel<2; Channel++) {
169                         if(pDCTstat->GangedMode && Channel)
170                                 break;
171                         reg_off = 0x100 * Channel;
172                         reg = 0x78 + reg_off;
173                         val = Get_NB32(dev, reg);
174                         val &= ~(0x07);
175                         val |= 5;
176                         Set_NB32(dev, reg, val);
177                 }
178
179                 for(Channel = 0; Channel<2; Channel++) {
180                         reg_off = 0x100 * Channel;
181                         val = 0;
182                         index_reg = 0x98 + reg_off;
183                         for( index = 0x30; index < (0x45 + 1); index++) {
184                                 Set_NB32_index_wait(dev, index_reg, index, val);
185                         }
186                 }
187
188         }
189 }
190
191
192 u32 Modify_D3CMP(struct DCTStatStruc *pDCTstat, u32 dct, u32 value)
193 {
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
198          * as follows:
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
203          * as follows:
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
208          */
209
210         u32 dev;
211         u32 index_reg;
212         u32 index;
213         u32 val;
214         u32 tmp;
215
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;
220                 index = 0x0D004201;
221                 val = Get_NB32_index_wait(dev, index_reg, index);
222                 value &= ~(1<<27);
223                 value |= ((val>>10) & 1) << 27;
224         }
225         return value;
226 }
227
228
229 void SyncSetting(struct DCTStatStruc *pDCTstat)
230 {
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
241          * other controller.
242          * Silicon Status: Fix TBD
243          */
244
245         u32 tmp;
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];
250         }
251 }
252
253
254 static u32 CheckNBCOFAutoPrechg(struct DCTStatStruc *pDCTstat, u32 dct)
255 {
256         u32 ret = 0;
257         u32 lo, hi;
258         u32 msr;
259         u32 val;
260         u32 valx, valy;
261         u32 NbDid;
262
263         /* 3 * (Fn2xD4[NBFid]+4)/(2^NbDid)/(3+Fn2x94[MemClkFreq]) */
264         msr = 0xC0010071;
265         _RDMSR(msr, &lo, &hi);
266         NbDid = (lo>>22) & 1;
267
268         val = Get_NB32(pDCTstat->dev_dct, 0x94 + 0x100 * dct);
269         valx = ((val & 0x07) + 3)<<NbDid;
270         print_tx("MemClk:", valx >> NbDid);
271
272         val = Get_NB32(pDCTstat->dev_nbmisc, 0xd4);
273         valy = ((val & 0x1f) + 4) * 3;
274         print_tx("NB COF:", valy >> NbDid);
275
276         val = valy/valx;
277         if((val==3) && (valy%valx))  /* 3 < NClk/MemClk < 4 */
278                 ret = 1;
279
280         return ret;
281 }
282
283
284 void mct_BeforeDramInit_D(struct DCTStatStruc *pDCTstat, u32 dct)
285 {
286         u32 tmp;
287         u32 Speed;
288         u32 ch, ch_start, ch_end;
289         u32 index_reg;
290         u32 index;
291         u32 dev;
292         u32 val;
293
294
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) {
301                                 ch_start = 0;
302                                 ch_end = 2;
303                         } else {
304                                 ch_start = dct;
305                                 ch_end = dct+1;
306                         }
307                         dev = pDCTstat->dev_dct;
308                         index = 0x0D00E001;
309                         for(ch=ch_start; ch<ch_end; ch++) {
310                                 index_reg = 0x98 + 0x100 * ch;
311                                 val = Get_NB32_index(dev, index_reg, 0x0D00E001);
312                                 val &= ~(0xf0);
313                                 val |= 0x80;
314                                 Set_NB32_index(dev, index_reg, 0x0D01E001, val);
315                         }
316                 }
317
318         }
319 }
320
321
322 static u8 mct_AdjustDelay_D(struct DCTStatStruc *pDCTstat, u8 dly)
323 {
324         u8 skip = 0;
325         dly &= 0x1f;
326         if ((dly >= MIN_FENCE) && (dly <= MAX_FENCE))
327                 skip = 1;
328
329         return skip;
330 }
331
332
333 static u8 mct_checkFenceHoleAdjust_D(struct MCTStatStruc *pMCTstat,
334                                 struct DCTStatStruc *pDCTstat, u8 DQSDelay,
335                                 u8 ChipSel,  u8 *result)
336 {
337         u8 ByteLane;
338         u32 tmp;
339
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)) {
344                                 if(DQSDelay == 13) {
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);
351                                                 }
352                                                 return 1;
353                                         }
354                                 }
355                         }
356                         if (mct_AdjustDQSPosDelay_D(pDCTstat, DQSDelay)) {
357                                 *result = 0;
358                         }
359                 }
360         }
361         return 0;
362 }
363
364
365 static u8 mct_AdjustDQSPosDelay_D(struct DCTStatStruc *pDCTstat, u8 dly)
366 {
367         u8 skip = 0;
368
369         dly &= 0x1f;
370         if ((dly >= MIN_DQS_WR_FENCE) && (dly <= MAX_DQS_WR_FENCE))
371                 skip = 1;
372
373         return skip;
374
375 }
376
377 static void beforeInterleaveChannels_D(struct DCTStatStruc *pDCTstatA, u8 *enabled) {
378
379         if (pDCTstatA->LogicalCPUID & (AMD_DR_Ax))
380                 *enabled = 0;
381 }
382
383
384 static u8 mctDoAxRdPtrInit_D(struct DCTStatStruc *pDCTstat, u8 *Rdtr)
385 {
386         u32 tmp;
387
388         tmp = pDCTstat->LogicalCPUID;
389         if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
390                 *Rdtr = 5;
391                 return 1;
392         }
393         return 0;
394 }
395
396
397 static void mct_AdjustScrub_D(struct DCTStatStruc *pDCTstat, u16 *scrub_request) {
398
399         /* Erratum #202: disable DCache scrubber for Ax parts */
400
401         if (pDCTstat->LogicalCPUID & (AMD_DR_Ax)) {
402                 *scrub_request = 0;
403                 pDCTstat->ErrStatus |= 1 << SB_DCBKScrubDis;
404         }
405 }
406