1724ca0640b8d258e42cce869f8751c03aa58a45
[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 void EarlySampleSupport_D(void)
21 {
22 }
23
24 u32 procOdtWorkaround(struct DCTStatStruc *pDCTstat, u32 dct, u32 val)
25 {
26         u32 tmp;
27         tmp = pDCTstat->LogicalCPUID;
28         if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
29                 val &= 0x0FFFFFFF;
30                 if(pDCTstat->MAdimms[dct] > 1)
31                         val |= 0x10000000;
32         }
33
34         return val;
35 }
36
37
38 u32 OtherTiming_A_D(struct DCTStatStruc *pDCTstat, u32 val)
39 {
40         /* Bug#10695:One MEMCLK Bubble Writes Don't Do X4 X8 Switching Correctly
41          * Solution: BIOS should set DRAM Timing High[Twrwr] > 00b
42          * ( F2x[1, 0]8C[1:0] > 00b).  Silicon Status: Fixed in Rev B
43          * FIXME: check if this is still required.
44          */
45         u32 tmp;
46         tmp = pDCTstat->LogicalCPUID;
47         if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
48                 if(!(val & (3<<12) ))
49                         val |= 1<<12;
50         }
51         return val;
52 }
53
54
55 void mct_ForceAutoPrecharge_D(struct DCTStatStruc *pDCTstat, u32 dct)
56 {
57         u32 tmp;
58         u32 reg;
59         u32 reg_off;
60         u32 dev;
61         u32 val;
62
63         tmp = pDCTstat->LogicalCPUID;
64         if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
65                 if(CheckNBCOFAutoPrechg(pDCTstat, dct)) {
66                         dev = pDCTstat->dev_dct;
67                         reg_off = 0x100 * dct;
68                         reg = 0x90 + reg_off;   /* Dram Configuration Lo */
69                         val = Get_NB32(dev, reg);
70                         val |= 1<<ForceAutoPchg;
71                         if(!pDCTstat->GangedMode)
72                                 val |= 1<<BurstLength32;
73                         Set_NB32(dev, reg, val);
74
75                         reg = 0x88 + reg_off;   /* cx=Dram Timing Lo */
76                         val = Get_NB32(dev, reg);
77                         val |= 0x000F0000;      /* Trc = 0Fh */
78                         Set_NB32(dev, reg, val);
79                 }
80         }
81 }
82
83
84 void mct_EndDQSTraining_D(struct MCTStatStruc *pMCTstat,
85                                 struct DCTStatStruc *pDCTstatA)
86 {
87         /* Bug#13341: Prefetch is getting killed when the limit is reached in
88          * PrefDramTrainMode
89          * Solution: Explicitly clear the PrefDramTrainMode bit after training
90          * sequence in order to ensure resumption of normal HW prefetch
91          * behavior.
92          * NOTE -- this has been documented with a note at the end of this
93          * section in the  BKDG (although, admittedly, the note does not really
94          * stand out).
95          * Silicon Status: Fixed in Rev B ( confirm)
96          * FIXME: check this.
97          */
98
99         u32 tmp;
100         u32 dev;
101         u32 reg;
102         u32 val;
103         u32 Node;
104
105         for(Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
106                 struct DCTStatStruc *pDCTstat;
107                 pDCTstat = pDCTstatA + Node;
108
109                 if(!pDCTstat->NodePresent) break;
110
111                 tmp = pDCTstat->LogicalCPUID;
112                 if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
113                         dev = pDCTstat->dev_dct;
114                         reg = 0x11c;
115                         val = Get_NB32(dev, reg);
116                         val &= ~(1<<PrefDramTrainMode);
117                         Set_NB32(dev, reg, val);
118                 }
119         }
120 }
121
122
123
124
125 void mct_BeforeDQSTrain_Samp_D(struct MCTStatStruc *pMCTstat,
126                                 struct DCTStatStruc *pDCTstat)
127 {
128         /* Bug#15115: Uncertainty In The Sync Chain Leads To Setup Violations
129          *  In TX FIFO
130          * Solution: BIOS should program DRAM Control Register[RdPtrInit] = 5h,
131          * (F2x[1, 0]78[3:0] = 5h).
132          *   Silicon Status: Fixed In Rev B0
133          */
134
135         /* Bug#15880: Determine validity of reset settings for DDR PHY timing
136          *   regi..
137          * Solutiuon: At least, set WrDqs fine delay to be 0 for DDR2 training.
138          */
139
140         u32 dev;
141         u32 reg_off;
142         u32 index_reg;
143         u32 index;
144         u32 reg;
145         u32 val;
146         u32 tmp;
147         u32 Channel;
148
149
150         tmp = pDCTstat->LogicalCPUID;
151         if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
152
153                 dev = pDCTstat->dev_dct;
154                 index = 0;
155
156                 for(Channel = 0; Channel<2; Channel++) {
157                         index_reg = 0x98 + 0x100 * Channel;
158                         val = Get_NB32_index_wait(dev, index_reg, 0x0d004007);
159                         val |= 0x3ff;
160                         Set_NB32_index_wait(dev, index_reg, 0x0d0f4f07, val);
161                 }
162
163                 for(Channel = 0; Channel<2; Channel++) {
164                         if(pDCTstat->GangedMode && Channel)
165                                 break;
166                         reg_off = 0x100 * Channel;
167                         reg = 0x78 + reg_off;
168                         val = Get_NB32(dev, reg);
169                         val &= ~(0x07);
170                         val |= 5;
171                         Set_NB32(dev, reg, val);
172                 }
173
174                 for(Channel = 0; Channel<2; Channel++) {
175                         reg_off = 0x100 * Channel;
176                         val = 0;
177                         index_reg = 0x98 + reg_off;
178                         for( index = 0x30; index < (0x45 + 1); index++) {
179                                 Set_NB32_index_wait(dev, index_reg, index, val);
180                         }
181                 }
182
183         }
184 }
185
186
187 u32 Modify_D3CMP(struct DCTStatStruc *pDCTstat, u32 dct, u32 value)
188 {
189         /* Errata#189: Reads To Phy Driver Calibration Register and Phy
190          *  Predriver Calibration Register Do Not Return Bit 27.
191          * Solution: See #41322 for details.
192          * BIOS can modify bit 27 of the Phy Driver Calibration register
193          * as follows:
194          *  1. Read F2x[1, 0]9C_x09
195          *  2. Read F2x[1, 0]9C_x0D004201
196          *  3. Set F2x[1, 0]9C_x09[27] = F2x[1, 0]9C_x0D004201[10]
197          * BIOS can modify bit 27 of the Phy Predriver Calibration register
198          * as follows:
199          *  1. Read F2x[1, 0]9C_x0A
200          *  2. Read F2x[1, 0]9C_x0D004209
201          *  3. Set F2x[1, 0]9C_x0A[27] = F2x[1, 0]9C_x0D004209[10]
202          * Silicon Status: Fixed planned for DR-B0
203          */
204
205         u32 dev;
206         u32 index_reg;
207         u32 index;
208         u32 val;
209         u32 tmp;
210
211         tmp = pDCTstat->LogicalCPUID;
212         if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
213                 dev = pDCTstat->dev_dct;
214                 index_reg = 0x98 + 0x100 * dct;
215                 index = 0x0D004201;
216                 val = Get_NB32_index_wait(dev, index_reg, index);
217                 value &= ~(1<<27);
218                 value |= ((val>>10) & 1) << 27;
219         }
220         return value;
221 }
222
223
224 void SyncSetting(struct DCTStatStruc *pDCTstat)
225 {
226         /* Errata#198: AddrCmdSetup, CsOdtSetup, and CkeSetup Require Identical
227          * Programming For Both Channels in Ganged Mode
228          * Solution: The BIOS must program the following DRAM timing parameters
229          * the same for both channels:
230          *  1. F2x[1, 0]9C_x04[21] (AddrCmdSetup)
231          *  2. F2x[1, 0]9C_x04[15] (CsOdtSetup)
232          *  3. F2x[1, 0]9C_x04[5]) (CkeSetup)
233          * That is, if the AddrCmdSetup, CsOdtSetup, or CkeSetup is
234          * set to 1'b1 for one of the controllers, then the corresponding
235          * AddrCmdSetup, CsOdtSetup, or CkeSetup must be set to 1'b1 for the
236          * other controller.
237          * Silicon Status: Fix TBD
238          */
239
240         u32 tmp;
241         tmp = pDCTstat->LogicalCPUID;
242         if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
243                 pDCTstat->CH_ODC_CTL[1] = pDCTstat->CH_ODC_CTL[0];
244                 pDCTstat->CH_ADDR_TMG[1] = pDCTstat->CH_ADDR_TMG[0];
245         }
246 }
247
248
249 u32 CheckNBCOFAutoPrechg(struct DCTStatStruc *pDCTstat, u32 dct)
250 {
251         u32 ret = 0;
252         u32 lo, hi;
253         u32 msr;
254         u32 val;
255         u32 valx, valy;
256         u32 NbDid;
257
258         /* 3 * (Fn2xD4[NBFid]+4)/(2^NbDid)/(3+Fn2x94[MemClkFreq]) */
259         msr = 0xC0010071;
260         _RDMSR(msr, &lo, &hi);
261         NbDid = (lo>>22) & 1;
262
263         val = Get_NB32(pDCTstat->dev_dct, 0x94 + 0x100 * dct);
264         valx = ((val & 0x07) + 3)<<NbDid;
265         print_tx("MemClk:", valx >> NbDid);
266
267         val = Get_NB32(pDCTstat->dev_nbmisc, 0xd4);
268         valy = ((val & 0x1f) + 4) * 3;
269         print_tx("NB COF:", valy >> NbDid);
270
271         val = valy/valx;
272         if((val==3) && (valy%valx))  /* 3 < NClk/MemClk < 4 */
273                 ret = 1;
274
275         return ret;
276 }
277
278
279 void mct_BeforeDramInit_D(struct DCTStatStruc *pDCTstat, u32 dct)
280 {
281         u32 tmp;
282         u32 Speed;
283         u32 ch, ch_start, ch_end;
284         u32 index_reg;
285         u32 index;
286         u32 dev;
287         u32 val;
288
289
290         tmp = pDCTstat->LogicalCPUID;
291         if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
292                 Speed = pDCTstat->Speed;
293                 /* MemClkFreq = 333MHz or 533Mhz */
294                 if((Speed == 3) || (Speed == 2)) {
295                         if(pDCTstat->GangedMode) {
296                                 ch_start = 0;
297                                 ch_end = 2;
298                         } else {
299                                 ch_start = dct;
300                                 ch_end = dct+1;
301                         }
302                         dev = pDCTstat->dev_dct;
303                         index = 0x0D00E001;
304                         for(ch=ch_start; ch<ch_end; ch++) {
305                                 index_reg = 0x98 + 0x100 * ch;
306                                 val = Get_NB32_index(dev, index_reg, 0x0D00E001);
307                                 val &= ~(0xf0);
308                                 val |= 0x80;
309                                 Set_NB32_index(dev, index_reg, 0x0D01E001, val);
310                         }
311                 }
312
313         }
314 }
315
316
317 static u8 mct_AdjustDelay_D(struct DCTStatStruc *pDCTstat, u8 dly)
318 {
319         u8 skip = 0;
320         dly &= 0x1f;
321         if ((dly >= MIN_FENCE) && (dly <= MAX_FENCE))
322                 skip = 1;
323
324         return skip;
325 }
326
327
328 static u8 mct_checkFenceHoleAdjust_D(struct MCTStatStruc *pMCTstat,
329                                 struct DCTStatStruc *pDCTstat, u8 DQSDelay,
330                                 u8 ChipSel,  u8 *result)
331 {
332         u8 ByteLane;
333         u32 tmp;
334
335         tmp = pDCTstat->LogicalCPUID;
336         if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
337                 if (pDCTstat->Direction == DQS_WRITEDIR) {
338                         if ((pDCTstat->Speed == 2) || (pDCTstat->Speed == 3)) {
339                                 if(DQSDelay == 13) {
340                                         if (*result == 0xFF) {
341                                                 for (ByteLane = 0; ByteLane < 8; ByteLane++) {
342                                                         pDCTstat->DQSDelay = 13;
343                                                         pDCTstat->ByteLane = ByteLane;
344                                                         /* store the value into the data structure */
345                                                         StoreDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel);
346                                                 }
347                                                 return 1;
348                                         }
349                                 }
350                         }
351                         if (mct_AdjustDQSPosDelay_D(pDCTstat, DQSDelay)) {
352                                 *result = 0;
353                         }
354                 }
355         }
356         return 0;
357 }
358
359
360 u8 mct_AdjustDQSPosDelay_D(struct DCTStatStruc *pDCTstat, u8 dly)
361 {
362         u8 skip = 0;
363
364         dly &= 0x1f;
365         if ((dly >= MIN_DQS_WR_FENCE) && (dly <= MAX_DQS_WR_FENCE))
366                 skip = 1;
367
368         return skip;
369
370 }
371
372 static void beforeInterleaveChannels_D(struct DCTStatStruc *pDCTstatA, u8 *enabled) {
373
374         if (pDCTstatA->LogicalCPUID & (AMD_DR_Ax))
375                 *enabled = 0;
376 }
377
378 #ifdef UNUSED_CODE
379 static u8 mctDoAxRdPtrInit_D(struct DCTStatStruc *pDCTstat, u8 *Rdtr)
380 {
381         u32 tmp;
382
383         tmp = pDCTstat->LogicalCPUID;
384         if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
385                 *Rdtr = 5;
386                 return 1;
387         }
388         return 0;
389 }
390 #endif
391
392 void mct_AdjustScrub_D(struct DCTStatStruc *pDCTstat, u16 *scrub_request) {
393
394         /* Erratum #202: disable DCache scrubber for Ax parts */
395
396         if (pDCTstat->LogicalCPUID & (AMD_DR_Ax)) {
397                 *scrub_request = 0;
398                 pDCTstat->ErrStatus |= 1 << SB_DCBKScrubDis;
399         }
400 }