569d61c7b03ba572770fc0cebdfc1d4fd1100944
[coreboot.git] / src / northbridge / amd / amdmct / wrappers / mcti_d.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2007-2008 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 /* Call-backs */
21 #include <delay.h>
22
23 static u16 mctGet_NVbits(u8 index)
24 {
25         u16 val = 0;
26
27         switch (index) {
28         case NV_PACK_TYPE:
29 #if CONFIG_CPU_SOCKET_TYPE == 0x10      /* Socket F */
30                 val = 0;
31 #elif CONFIG_CPU_SOCKET_TYPE == 0x11    /* AM3 */
32                 val = 1;
33 #elif CONFIG_CPU_SOCKET_TYPE == 0x13    /* ASB2 */
34                 val = 4;
35 //#elif SYSTEM_TYPE == MOBILE
36 //              val = 2;
37 #endif
38                 break;
39         case NV_MAX_NODES:
40                 val = MAX_NODES_SUPPORTED;
41                 break;
42         case NV_MAX_DIMMS:
43                 val = MAX_DIMMS_SUPPORTED;
44                 //val = 8;
45                 break;
46         case NV_MAX_MEMCLK:
47                 /* Maximum platform supported memclk */
48                 //val =  200;   /* 200MHz(DDR400) */
49                 //val =  266;   /* 266MHz(DDR533) */
50                 //val =  333;   /* 333MHz(DDR667) */
51                 val =  400;     /* 400MHz(DDR800) */
52                 break;
53         case NV_ECC_CAP:
54 #if SYSTEM_TYPE == SERVER
55                 val = 1;        /* memory bus ECC capable */
56 #else
57                 val = 0;        /* memory bus ECC not capable */
58 #endif
59                 break;
60         case NV_4RANKType:
61                 /* Quad Rank DIMM slot type */
62                 val = 0;        /* normal */
63                 //val = 1;      /* R4 (registered DIMMs in AMD server configuration) */
64                 //val = 2;      /* S4 (Unbuffered SO-DIMMS) */
65                 break;
66         case NV_BYPMAX:
67 #if   (CONFIG_GFXUMA == 0)
68                 val = 4;
69 #elif  (CONFIG_GFXUMA == 1)
70                 val = 7;
71 #endif
72                 break;
73         case NV_RDWRQBYP:
74 #if  (CONFIG_GFXUMA == 0)
75                 val = 2;
76 #elif (CONFIG_GFXUMA == 1)
77                 val = 3;
78 #endif
79                 break;
80         case NV_MCTUSRTMGMODE:
81                 val = 0;        /* Automatic (recommended) */
82                 //val = 1;      /* Limited */
83                 //val = 2;      /* Manual */
84                 break;
85         case NV_MemCkVal:
86                 //val = 0;      /* 200MHz */
87                 //val = 1;      /* 266MHz */
88                 val = 2;        /* 333MHz */
89                 break;
90         case NV_BankIntlv:
91                 /* Bank (chip select) interleaving */
92                 //val = 0;      /* disabled */
93                 val = 1;        /* enabled (recommended) */
94                 break;
95         case NV_MemHole:
96                 //val = 0;      /* Disabled */
97                 val = 1;        /* Enabled (recommended) */
98                 break;
99         case NV_AllMemClks:
100                 val = 0;        /* Normal (only to slots that have enabled DIMMs) */
101                 //val = 1;      /* Enable all memclocks */
102                 break;
103         case NV_SPDCHK_RESTRT:
104                 val = 0;        /* Exit current node initialization if any DIMM has SPD checksum error */
105                 //val = 1;      /* Ignore faulty SPD checksum (DIMM will still be disabled), continue current node intialization */
106                 break;
107         case NV_DQSTrainCTL:
108                 //val = 0;      /*Skip dqs training */
109                 val = 1;        /* Perform dqs training */
110                 break;
111         case NV_NodeIntlv:
112                 val = 0;        /* Disabled (recommended) */
113                 //val = 1;      /* Enable */
114                 break;
115         case NV_BurstLen32:
116 #if (CONFIG_GFXUMA == 0)
117                 val = 0;        /* 64 byte mode */
118 #elif (CONFIG_GFXUMA == 1)
119                 val = 1;        /* 32 byte mode */
120 #endif
121                 break;
122         case NV_CKE_PDEN:
123                 //val = 0;      /* Disable */
124                 val = 1;        /* Enable */
125                 break;
126         case NV_CKE_CTL:
127                 val = 0;        /* per channel control */
128                 //val = 1;      /* per chip select control */
129                 break;
130         case NV_CLKHZAltVidC3:
131                 val = 0;        /* disable */
132                 //val = 1;      /* enable */
133                 break;
134         case NV_BottomIO:
135 #if (CONFIG_GFXUMA == 0)
136                 val = 0xE0;     /* address bits [31:24] */
137 #elif (CONFIG_GFXUMA == 1)
138                 val = 0xC0;     /* address bits [31:24] */
139 #endif
140                 break;
141         case NV_BottomUMA:
142 #if (CONFIG_GFXUMA == 0)
143                 val = 0xE0;     /* address bits [31:24] */
144 #elif (CONFIG_GFXUMA == 1)
145                 val = 0xC0;     /* address bits [31:24] */
146 #endif
147                 break;
148         case NV_ECC:
149 #if (SYSTEM_TYPE == SERVER)
150                 val = 1;        /* Enable */
151 #else
152                 val = 0;        /* Disable */
153 #endif
154                 break;
155         case NV_NBECC:
156 #if (SYSTEM_TYPE == SERVER)
157                 val = 1;        /* Enable */
158 #else
159                 val = 0;        /* Disable */
160 #endif
161                 break;
162         case NV_ChipKill:
163 #if (SYSTEM_TYPE == SERVER)
164                 val = 1;        /* Enable */
165 #else
166                 val = 0;        /* Disable */
167 #endif
168                 break;
169         case NV_ECCRedir:
170                 val = 0;        /* Disable */
171                 //val = 1;      /* Enable */
172                 break;
173         case NV_DramBKScrub:
174                 val = 0x00;     /* Disabled */
175                 //val = 0x01;   /* 40ns */
176                 //val = 0x02;   /* 80ns */
177                 //val = 0x03;   /* 160ns */
178                 //val = 0x04;   /* 320ns */
179                 //val = 0x05;   /* 640ns */
180                 //val = 0x06;   /* 1.28us */
181                 //val = 0x07;   /* 2.56us */
182                 //val = 0x08;   /* 5.12us */
183                 //val = 0x09;   /* 10.2us */
184                 //val = 0x0a;   /* 20.5us */
185                 //val = 0x0b;   /* 41us */
186                 //val = 0x0c;   /* 81.9us */
187                 //val = 0x0d;   /* 163.8us */
188                 //val = 0x0e;   /* 327.7us */
189                 //val = 0x0f;   /* 655.4us */
190                 //val = 0x10;   /* 1.31ms */
191                 //val = 0x11;   /* 2.62ms */
192                 //val = 0x12;   /* 5.24ms */
193                 //val = 0x13;   /* 10.49ms */
194                 //val = 0x14;   /* 20.97sms */
195                 //val = 0x15;   /* 42ms */
196                 //val = 0x16;   /* 84ms */
197                 break;
198         case NV_L2BKScrub:
199                 val = 0;        /* Disabled - See L2Scrub in BKDG */
200                 break;
201         case NV_DCBKScrub:
202                 val = 0;        /* Disabled - See DcacheScrub in BKDG */
203                 break;
204         case NV_CS_SpareCTL:
205                 val = 0;        /* Disabled */
206                 //val = 1;      /* Enabled */
207                 break;
208         case NV_SyncOnUnEccEn:
209                 val = 0;        /* Disabled */
210                 //val = 1;      /* Enabled */
211                 break;
212         case NV_Unganged:
213                 /* channel interleave is better performance than ganged mode at this time */
214                 val = 1;                /* Enabled */
215                 //val = 0;      /* Disabled */
216                 break;
217         case NV_ChannelIntlv:
218                 val = 5;        /* Not currently checked in mctchi_d.c */
219         /* Bit 0 =     0 - Disable
220          *             1 - Enable
221          * Bits[2:1] = 00b - Address bits 6
222          *             01b - Address bits 1
223          *             10b - Hash*, XOR of address bits [20:16, 6]
224          *             11b - Hash*, XOR of address bits [20:16, 9]
225          */
226                 break;
227         }
228
229         return val;
230 }
231
232
233 static void mctHookAfterDIMMpre(void)
234 {
235 }
236
237
238 static void mctGet_MaxLoadFreq(struct DCTStatStruc *pDCTstat)
239 {
240         pDCTstat->PresetmaxFreq = 400;
241 }
242
243 #ifdef UNUSED_CODE
244 static void mctAdjustAutoCycTmg(void)
245 {
246 }
247 #endif
248
249
250 static void mctAdjustAutoCycTmg_D(void)
251 {
252 }
253
254
255 static void mctHookAfterAutoCycTmg(void)
256 {
257 }
258
259
260 static void mctGetCS_ExcludeMap(void)
261 {
262 }
263
264
265 static void mctHookAfterAutoCfg(void)
266 {
267 }
268
269
270 static void mctHookAfterPSCfg(void)
271 {
272 }
273
274
275 static void mctHookAfterHTMap(void)
276 {
277 }
278
279
280 static void mctHookAfterCPU(void)
281 {
282 }
283
284
285 static void mctSaveDQSSigTmg_D(void)
286 {
287 }
288
289
290 static void mctGetDQSSigTmg_D(void)
291 {
292 }
293
294
295 static void mctHookBeforeECC(void)
296 {
297 }
298
299
300 static void mctHookAfterECC(void)
301 {
302 }
303
304 #ifdef UNUSED_CODE
305 static void mctInitMemGPIOs_A(void)
306 {
307 }
308 #endif
309
310
311 static void mctInitMemGPIOs_A_D(void)
312 {
313 }
314
315
316 static void mctNodeIDDebugPort_D(void)
317 {
318 }
319
320
321 #ifdef UNUSED_CODE
322 static void mctWarmReset(void)
323 {
324 }
325 #endif
326
327
328 static void mctWarmReset_D(void)
329 {
330 }
331
332
333 static void mctHookBeforeDramInit(void)
334 {
335 }
336
337
338 static void mctHookAfterDramInit(void)
339 {
340 }
341
342 #if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */
343 static void coreDelay(u32 microseconds)
344 {
345         msr_t now;
346         msr_t end;
347         u32 cycles;
348
349         /* delay ~40us
350            This seems like a hack to me...
351            It would be nice to have a central delay function. */
352
353         cycles = (microseconds * 100) << 3;  /* x8 (number of 1.25ns ticks) */
354
355         if (!(rdmsr(HWCR).lo & TSC_FREQ_SEL_MASK)) {
356             msr_t pstate_msr = rdmsr(CUR_PSTATE_MSR);
357             if (!(rdmsr(0xC0010064+pstate_msr.lo).lo & NB_DID_M_ON)) {
358               cycles = cycles <<1; // half freq, double cycles
359             }
360         } // else should we keep p0 freq at the time of setting TSC_FREQ_SEL_MASK somewhere and check it here ?
361
362         now = rdmsr(TSC_MSR);
363         // avoid overflow when called near 2^32 ticks ~ 5.3 s boundaries
364         if (0xffffffff - cycles >= now.lo ) {
365           end.hi =  now.hi;
366           end.lo = now.lo + cycles;
367         } else {
368           end.hi = now.hi +1; //
369           end.lo = cycles - (1+(0xffffffff - now.lo));
370         }
371         do {
372           now = rdmsr(TSC_MSR);
373         } while ((now.hi < end.hi) || ((now.hi == end.hi) && (now.lo < end.lo)));
374 }
375
376 /* Erratum 350 */
377 static void vErrata350(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat)
378 {
379         u8 u8Channel;
380         u8 u8Receiver;
381         u32 u32Addr;
382         u8 u8Valid;
383         u32 u32DctDev;
384
385         // 1. dummy read for each installed DIMM */
386         for (u8Channel = 0; u8Channel < 2; u8Channel++) {
387                 // This will be 0 for vaild DIMMS, eles 8
388                 u8Receiver = mct_InitReceiver_D(pDCTstat, u8Channel);
389
390                 for (; u8Receiver < 8; u8Receiver += 2) {
391                         u32Addr = mct_GetRcvrSysAddr_D(pMCTstat, pDCTstat, u8Channel, u8Receiver, &u8Valid);
392
393                         if(!u8Valid) {  /* Address not supported on current CS */
394                                 print_t("vErrata350: Address not supported on current CS\n");
395                                 continue;
396                         }
397                         print_t("vErrata350: dummy read \n");
398                         read32_fs(u32Addr);
399                 }
400         }
401
402         print_t("vErrata350: step 2a\n");
403
404         /* 2. Write 0000_8000h to register F2x[1, 0]9C_xD080F0C. */
405         u32DctDev = pDCTstat->dev_dct;
406         Set_NB32_index_wait(u32DctDev, 0x098, 0xD080F0C, 0x00008000);
407         /*                                                ^--- value
408                                                 ^---F2x[1, 0]9C_x0D080F0C, No description in BKDG.
409                                          ^----F2x[1, 0]98 DRAM Controller Additional Data Offset Register */
410
411         if(!pDCTstat->GangedMode) {
412                 print_t("vErrata350: step 2b\n");
413                 Set_NB32_index_wait(u32DctDev, 0x198, 0xD080F0C, 0x00008000);
414                 /*                                                ^--- value
415                                                         ^---F2x[1, 0]9C_x0D080F0C, No description in BKDG
416                                                 ^----F2x[1, 0]98 DRAM Controller Additional Data Offset Register */
417         }
418
419         print_t("vErrata350: step 3\n");
420         /* 3. Wait at least 300 nanoseconds. */
421         coreDelay(1);
422
423         print_t("vErrata350: step 4\n");
424         /* 4. Write 0000_0000h to register F2x[1, 0]9C_xD080F0C. */
425         Set_NB32_index_wait(u32DctDev, 0x098, 0xD080F0C, 0x00000000);
426
427         if(!pDCTstat->GangedMode) {
428                 print_t("vErrata350: step 4b\n");
429                 Set_NB32_index_wait(u32DctDev, 0x198, 0xD080F0C, 0x00000000);
430         }
431
432         print_t("vErrata350: step 5\n");
433         /* 5. Wait at least 2 microseconds. */
434         coreDelay(2);
435
436 }
437
438 static void vErratum372(struct DCTStatStruc *pDCTstat)
439 {
440         msr_t msr = rdmsr(NB_CFG_MSR);
441
442         int  nbPstate1supported = ! (msr.hi && (1 << (NB_GfxNbPstateDis -32))) ;
443
444         // is this the right way to check for NB pstate 1 or DDR3-1333 ?
445         if (((pDCTstat->PresetmaxFreq==1333)||(nbPstate1supported))
446             &&(!pDCTstat->GangedMode)) {
447                 /* DisableCf8ExtCfg */
448                 msr.hi &= ~(3 << (51 - 32));
449                 wrmsr(NB_CFG_MSR, msr);
450         }
451 }
452
453 static void vErratum414(struct DCTStatStruc *pDCTstat)
454 {
455      int dct=0;
456     for(; dct < 2 ; dct++)
457     {
458         int dRAMConfigHi = Get_NB32(pDCTstat->dev_dct,0x94 + (0x100 * dct));
459         int powerDown =  dRAMConfigHi && (1 << PowerDownEn ) ;
460         int ddr3 = dRAMConfigHi && (1 << Ddr3Mode ) ;
461         int dRAMMRS = Get_NB32(pDCTstat->dev_dct,0x84 + (0x100 * dct));
462         int pchgPDModeSel = dRAMMRS && (1 << PchgPDModeSel ) ;
463         if (powerDown && ddr3 && pchgPDModeSel )
464         {
465           Set_NB32(pDCTstat->dev_dct,0x84 + (0x100 * dct), dRAMMRS & ~(1 << PchgPDModeSel) );
466         }
467     }
468 }
469 #endif
470
471
472 static void mctHookBeforeAnyTraining(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
473 {
474 #if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */
475   /* FIXME :  as of 25.6.2010 errata 350 and 372 should apply to  ((RB|BL|DA)-C[23])|(HY-D[01])|(PH-E0) but I don't find constants for all of them */
476         if (pDCTstatA->LogicalCPUID & AMD_DRBH_Cx) {
477                 vErrata350(pMCTstat, pDCTstatA);
478                 vErratum372(pDCTstatA);
479                 vErratum414(pDCTstatA);
480         }
481 #endif
482 }
483
484 #if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */
485 static u32 mct_AdjustSPDTimings(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA, u32 val)
486 {
487         if (pDCTstatA->LogicalCPUID & AMD_DR_Bx) {
488                 if (pDCTstatA->Status & (1 << SB_Registered)) {
489                         val ++;
490                 }
491         }
492         return val;
493 }
494 #endif
495
496 static void mctHookAfterAnyTraining(void)
497 {
498 }
499
500 static u32 mctGetLogicalCPUID_D(u8 node)
501 {
502         return mctGetLogicalCPUID(node);
503 }
504
505 #if (CONFIG_DIMM_SUPPORT & 0x000F)!=0x0005 /* not needed for AMD_FAM10_DDR3 */
506 static u8 mctSetNodeBoundary_D(void)
507 {
508         return 0;
509 }
510 #endif