1 /** @file
2 HTE handling routines for MRC use.
3 
4 Copyright (c) 2013-2015 Intel Corporation.
5 
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution.  The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10 
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include "mrc.h"
17 #include "memory_options.h"
18 #include "io.h"
19 
20 #include "hte.h"
21 
22 
23 #ifdef SIM
24 VOID delay_n(UINT32 nanoseconds);
25 #define MySimStall(a)   delay_n(a/1000)
26 #endif
27 
EnableAllHteErrors(UINT8 Mask)28 STATIC VOID EnableAllHteErrors(
29     UINT8 Mask)
30 /*++
31 
32  Routine Description:
33 
34  This function enables to HTE to detect all possible errors for
35  the given training parameters (per-bit or full byte lane).
36 
37  Returns:
38 
39  None
40 
41  --*/
42 {
43   isbW32m(HTE, 0x000200A2, 0xFFFFFFFF);
44   isbW32m(HTE, 0x000200A3, 0x000000FF);
45   isbW32m(HTE, 0x000200A4, 0x00000000);
46 }
47 
CheckHteErrors(VOID)48 STATIC UINT32 CheckHteErrors(
49     VOID)
50 /*++
51 
52  Routine Description:
53 
54  This function goes and reads the HTE register in order to find any error
55 
56  Returns:
57 
58  The errors detected in the HTE status register
59 
60  --*/
61 {
62   return isbR32m(HTE, 0x000200A7);
63 }
64 
WaitForHteComplete(VOID)65 STATIC VOID WaitForHteComplete(
66     VOID)
67 /*++
68 
69  Routine Description:
70 
71  This function waits until HTE finishes
72 
73  Returns:
74 
75  None
76 
77  --*/
78 {
79   UINT32 Tmp;
80 
81   ENTERFN();
82 
83   //
84   // Is the test done?
85   //
86   do
87   {
88 #ifdef SIM
89     MySimStall (35000); // 35 ns delay
90 #endif
91   } while (0 != (isbR32m(HTE, 0x00020012) & BIT30));
92 
93   Tmp = isbR32m(HTE, 0x00020011);
94   Tmp = Tmp | BIT9;
95   Tmp = Tmp & ~(BIT13 | BIT12);
96   isbW32m(HTE, 0x00020011, Tmp);
97 
98   LEAVEFN();
99 }
100 
ClearHteErrorRegisters(VOID)101 STATIC VOID ClearHteErrorRegisters(
102     VOID)
103 /*++
104 
105  Routine Description:
106 
107  Clears registers related with errors in the HTE.
108 
109  Returns:
110 
111  None
112 
113  --*/
114 {
115   UINT32 Tmp;
116 
117   //
118   // Clear all HTE errors and enable error checking
119   // for burst and chunk.
120   //
121   Tmp = isbR32m(HTE, 0x000200A1);
122   Tmp |= BIT8;
123   isbW32m(HTE, 0x000200A1, Tmp);
124 }
125 
HteMemInit(MRC_PARAMS * CurrentMrcData,UINT8 MemInitFlag,UINT8 HaltHteEngineOnError)126 UINT32 HteMemInit(
127     MRC_PARAMS *CurrentMrcData,
128     UINT8 MemInitFlag,
129     UINT8 HaltHteEngineOnError)
130 
131 /*++
132 
133  Routine Description:
134 
135  Uses HW HTE engine to initialize or test all memory attached to a given DUNIT.
136  If MemInitFlag is 1, this routine writes 0s to all memory locations to initialize
137  ECC.
138  If MemInitFlag is 0, this routine will send an 5AA55AA5 pattern to all memory
139  locations on the RankMask and then read it back.  Then it sends an A55AA55A
140  pattern to all memory locations on the RankMask and reads it back.
141 
142  Arguments:
143 
144  CurrentMrcData: Host struture for all MRC global data.
145  MemInitFlag: 0 for memtest, 1 for meminit.
146  HaltHteEngineOnError:  Halt the HTE engine on first error observed, or keep
147  running to see how many errors are found.
148 
149  Returns:
150  Errors register showing HTE failures.
151  Also prints out which rank failed the HTE test if failure occurs.
152  For rank detection to work, the address map must be left in its default
153  state.  If MRC changes the address map, this function must be modified
154  to change it back to default at the beginning, then restore it at the end.
155 
156  --*/
157 {
158   UINT32 Offset;
159   UINT8 TestNum;
160   UINT8 i;
161 
162   //
163   // Clear out the error registers at the start of each memory
164   // init or memory test run.
165   //
166   ClearHteErrorRegisters();
167 
168   isbW32m(HTE, 0x00020062, 0x00000015);
169 
170   for (Offset = 0x80; Offset <= 0x8F; Offset++)
171   {
172     isbW32m(HTE, Offset, ((Offset & 1) ? 0xA55A : 0x5AA5));
173   }
174 
175   isbW32m(HTE, 0x00020021, 0x00000000);
176 #ifdef QUICKSIM
177   // Just do 4 cache lines for simulation memtest to save time.
178   isbW32m(HTE, 0x00020022, 4-1);
179 #else
180   isbW32m(HTE, 0x00020022, (CurrentMrcData->mem_size >> 6) - 1);
181 #endif
182 
183   isbW32m(HTE, 0x00020063, 0xAAAAAAAA);
184   isbW32m(HTE, 0x00020064, 0xCCCCCCCC);
185   isbW32m(HTE, 0x00020065, 0xF0F0F0F0);
186   isbW32m(HTE, 0x00020066, 0x03000000);
187 
188   switch (MemInitFlag)
189   {
190   case MrcMemInit:
191     TestNum = 1; // Only 1 write pass through memory is needed to initialize ECC.
192     break;
193   case MrcMemTest:
194     TestNum = 4; // Write/read then write/read with inverted pattern.
195     break;
196   default:
197     DPF(D_INFO, "Unknown parameter for MemInitFlag: %d\n", MemInitFlag);
198     return 0xFFFFFFFF;
199     break;
200   }
201 
202   DPF(D_INFO, "HteMemInit");
203   for (i = 0; i < TestNum; i++)
204   {
205     DPF(D_INFO, ".");
206 
207     if (i == 0)
208     {
209       isbW32m(HTE, 0x00020061, 0x00000000);
210       isbW32m(HTE, 0x00020020, 0x00110010);
211     }
212     else if (i == 1)
213     {
214       isbW32m(HTE, 0x00020061, 0x00000000);
215       isbW32m(HTE, 0x00020020, 0x00010010);
216     }
217     else if (i == 2)
218     {
219       isbW32m(HTE, 0x00020061, 0x00010100);
220       isbW32m(HTE, 0x00020020, 0x00110010);
221     }
222     else
223     {
224       isbW32m(HTE, 0x00020061, 0x00010100);
225       isbW32m(HTE, 0x00020020, 0x00010010);
226     }
227 
228     isbW32m(HTE, 0x00020011, 0x00111000);
229     isbW32m(HTE, 0x00020011, 0x00111100);
230 
231     WaitForHteComplete();
232 
233     //
234     // If this is a READ pass, check for errors at the end.
235     //
236     if ((i % 2) == 1)
237     {
238       //
239       // Return immediately if  error.
240       //
241       if (CheckHteErrors())
242       {
243         break;
244       }
245     }
246   }
247 
248   DPF(D_INFO, "done\n", i);
249   return CheckHteErrors();
250 }
251 
BasicDataCompareHte(MRC_PARAMS * CurrentMrcData,UINT32 Address,UINT8 FirstRun,UINT8 Mode)252 STATIC UINT16 BasicDataCompareHte(
253     MRC_PARAMS *CurrentMrcData,
254     UINT32 Address,
255     UINT8 FirstRun,
256     UINT8 Mode)
257 /*++
258 
259  Routine Description:
260 
261  Execute basic single cache line memory write/read/verify test using simple constant
262  pattern (different for READ_RAIN and WRITE_TRAIN modes.
263  See BasicWriteReadHTE which is external visible wrapper.
264 
265  Arguments:
266 
267  CurrentMrcData: Host struture for all MRC global data.
268  Address: memory adress being tested (must hit specific channel/rank)
269  FirstRun: If set then hte registers are configured, otherwise
270  it is assumed configuration is done and just re-run the test.
271  Mode: READ_TRAIN or WRITE_TRAIN (the difference is in the pattern)
272 
273  Returns:
274  Returns byte lane failure on each bit (for Quark only bit0 and bit1)
275 
276  --*/
277 {
278   UINT32 Pattern;
279   UINT32 Offset;
280 
281   if (FirstRun)
282   {
283     isbW32m(HTE, 0x00020020, 0x01B10021);
284     isbW32m(HTE, 0x00020021, 0x06000000);
285     isbW32m(HTE, 0x00020022, Address >> 6);
286     isbW32m(HTE, 0x00020062, 0x00800015);
287     isbW32m(HTE, 0x00020063, 0xAAAAAAAA);
288     isbW32m(HTE, 0x00020064, 0xCCCCCCCC);
289     isbW32m(HTE, 0x00020065, 0xF0F0F0F0);
290     isbW32m(HTE, 0x00020061, 0x00030008);
291 
292     if (Mode == WRITE_TRAIN)
293     {
294       Pattern = 0xC33C0000;
295     }
296     else // READ_TRAIN
297     {
298       Pattern = 0xAA5555AA;
299     }
300 
301     for (Offset = 0x80; Offset <= 0x8F; Offset++)
302     {
303       isbW32m(HTE, Offset, Pattern);
304     }
305   }
306 
307   isbW32m(HTE, 0x000200A1, 0xFFFF1000);
308 
309   isbW32m(HTE, 0x00020011, 0x00011000);
310   isbW32m(HTE, 0x00020011, 0x00011100);
311 
312   WaitForHteComplete();
313 
314   //
315   // Return bits 15:8 of HTE_CH0_ERR_XSTAT to check for any bytelane errors.
316   //
317   return ((CheckHteErrors() >> 8) & 0xFF);
318 }
319 
ReadWriteDataCompareHte(MRC_PARAMS * CurrentMrcData,UINT32 Address,UINT8 LoopCount,UINT32 LfsrSeedVictim,UINT32 LfsrSeedAggressor,UINT8 VictimBit,UINT8 FirstRun)320 STATIC UINT16 ReadWriteDataCompareHte(
321     MRC_PARAMS *CurrentMrcData,
322     UINT32 Address,
323     UINT8 LoopCount,
324     UINT32 LfsrSeedVictim,
325     UINT32 LfsrSeedAggressor,
326     UINT8 VictimBit,
327     UINT8 FirstRun)
328 /*++
329 
330  Routine Description:
331 
332  Examines single cache line memory with write/read/verify test using
333  multiple data patterns (victim-aggressor algorithm).
334  See WriteStressBitLanesHTE which is external visible wrapper.
335 
336  Arguments:
337 
338  CurrentMrcData: host struture for all MRC global data.
339  Address: memory adress being tested (must hit specific channel/rank)
340  LoopCount: number of test iterations
341  LfsrSeedXxx: victim aggressor data pattern seed
342  VictimBit: should be 0 as auto rotate feature is in use.
343  FirstRun: If set then hte registers are configured, otherwise
344  it is assumed configuration is done and just re-run the test.
345 
346  Returns:
347  Returns byte lane failure on each bit (for Quark only bit0 and bit1)
348 
349  --*/
350 {
351   UINT32 Offset;
352   UINT32 Tmp;
353 
354   if (FirstRun)
355   {
356     isbW32m(HTE, 0x00020020, 0x00910024);
357     isbW32m(HTE, 0x00020023, 0x00810024);
358     isbW32m(HTE, 0x00020021, 0x06070000);
359     isbW32m(HTE, 0x00020024, 0x06070000);
360     isbW32m(HTE, 0x00020022, Address >> 6);
361     isbW32m(HTE, 0x00020025, Address >> 6);
362     isbW32m(HTE, 0x00020062, 0x0000002A);
363     isbW32m(HTE, 0x00020063, LfsrSeedVictim);
364     isbW32m(HTE, 0x00020064, LfsrSeedAggressor);
365     isbW32m(HTE, 0x00020065, LfsrSeedVictim);
366 
367     //
368     // Write the pattern buffers to select the victim bit. Start with bit0.
369     //
370     for (Offset = 0x80; Offset <= 0x8F; Offset++)
371     {
372       if ((Offset % 8) == VictimBit)
373       {
374         isbW32m(HTE, Offset, 0x55555555);
375       }
376       else
377       {
378         isbW32m(HTE, Offset, 0xCCCCCCCC);
379       }
380     }
381 
382     isbW32m(HTE, 0x00020061, 0x00000000);
383     isbW32m(HTE, 0x00020066, 0x03440000);
384     isbW32m(HTE, 0x000200A1, 0xFFFF1000);
385   }
386 
387   Tmp = 0x10001000 | (LoopCount << 16);
388   isbW32m(HTE, 0x00020011, Tmp);
389   isbW32m(HTE, 0x00020011, Tmp | BIT8);
390 
391   WaitForHteComplete();
392 
393   return (CheckHteErrors() >> 8) & 0xFF;
394 }
395 
BasicWriteReadHTE(MRC_PARAMS * CurrentMrcData,UINT32 Address,UINT8 FirstRun,UINT8 Mode)396 UINT16 BasicWriteReadHTE(
397     MRC_PARAMS *CurrentMrcData,
398     UINT32 Address,
399     UINT8 FirstRun,
400     UINT8 Mode)
401 /*++
402 
403  Routine Description:
404 
405  Execute basic single cache line memory write/read/verify test using simple constant
406  pattern (different for READ_RAIN and WRITE_TRAIN modes.
407 
408  Arguments:
409 
410  CurrentMrcData: Host struture for all MRC global data.
411  Address: memory adress being tested (must hit specific channel/rank)
412  FirstRun: If set then hte registers are configured, otherwise
413  it is assumed configuration is done and just re-run the test.
414  Mode: READ_TRAIN or WRITE_TRAIN (the difference is in the pattern)
415 
416  Returns:
417  Returns byte lane failure on each bit (for Quark only bit0 and bit1)
418 
419  --*/
420 {
421   UINT16 ByteLaneErrors;
422 
423   ENTERFN();
424 
425   //
426   // Enable all error reporting in preparation for HTE test.
427   //
428   EnableAllHteErrors(0xFF);
429   ClearHteErrorRegisters();
430 
431   ByteLaneErrors = BasicDataCompareHte(CurrentMrcData, Address, FirstRun,
432       Mode);
433 
434   LEAVEFN();
435   return ByteLaneErrors;
436 }
437 
WriteStressBitLanesHTE(MRC_PARAMS * CurrentMrcData,UINT32 Address,UINT8 FirstRun)438 UINT16 WriteStressBitLanesHTE(
439     MRC_PARAMS *CurrentMrcData,
440     UINT32 Address,
441     UINT8 FirstRun)
442 /*++
443 
444  Routine Description:
445 
446  Examines single cache line memory with write/read/verify test using
447  multiple data patterns (victim-aggressor algorithm).
448 
449  Arguments:
450 
451  CurrentMrcData: host struture for all MRC global data.
452  Address: memory adress being tested (must hit specific channel/rank)
453  FirstRun: If set then hte registers are configured, otherwise
454  it is assumed configuration is done and just re-run the test.
455 
456  Returns:
457  Returns byte lane failure on each bit (for Quark only bit0 and bit1)
458 
459  --*/
460 {
461   UINT16 ByteLaneErrors;
462   UINT8 VictimBit = 0;
463 
464   ENTERFN();
465 
466   //
467   // Enable all error reporting in preparation for HTE test.
468   //
469   EnableAllHteErrors(0xFF);
470   ClearHteErrorRegisters();
471 
472   //
473   // Loop through each bit in the bytelane.  Each pass creates a victim bit
474   // while keeping all other bits the same - as aggressors.
475   // AVN HTE adds an auto-rotate feature which allows us to program the entire victim/aggressor
476   // sequence in 1 step. The victim bit rotates on each pass so no need to have software implement
477   // a victim bit loop like on VLV.
478   //
479   ByteLaneErrors = ReadWriteDataCompareHte(CurrentMrcData, Address,
480       HTE_LOOP_CNT, HTE_LFSR_VICTIM_SEED, HTE_LFSR_AGRESSOR_SEED, VictimBit,
481       FirstRun);
482 
483   LEAVEFN();
484   return ByteLaneErrors;
485 }
486 
HteMemOp(UINT32 Address,UINT8 FirstRun,UINT8 IsWrite)487 VOID HteMemOp(
488     UINT32 Address,
489     UINT8 FirstRun,
490     UINT8 IsWrite)
491 /*++
492 
493  Routine Description:
494 
495  Execute basic single cache line memory write or read.
496  This is just for receive enable / fine write levelling purpose.
497 
498  Arguments:
499 
500  CurrentMrcData: Host structure for all MRC global data.
501  Address: memory address used (must hit specific channel/rank)
502  FirstRun: If set then hte registers are configured, otherwise
503  it is assumed configuration is done and just re-run the test.
504  IsWrite: When non-zero memory write operation executed, otherwise read
505 
506  Returns:
507  None
508 
509  --*/
510 {
511   UINT32 Offset;
512   UINT32 Tmp;
513 
514   EnableAllHteErrors(0xFF);
515   ClearHteErrorRegisters();
516 
517   if (FirstRun)
518   {
519     Tmp = IsWrite ? 0x01110021 : 0x01010021;
520     isbW32m(HTE, 0x00020020, Tmp);
521 
522     isbW32m(HTE, 0x00020021, 0x06000000);
523     isbW32m(HTE, 0x00020022, Address >> 6);
524     isbW32m(HTE, 0x00020062, 0x00800015);
525     isbW32m(HTE, 0x00020063, 0xAAAAAAAA);
526     isbW32m(HTE, 0x00020064, 0xCCCCCCCC);
527     isbW32m(HTE, 0x00020065, 0xF0F0F0F0);
528     isbW32m(HTE, 0x00020061, 0x00030008);
529 
530     for (Offset = 0x80; Offset <= 0x8F; Offset++)
531     {
532       isbW32m(HTE, Offset, 0xC33C0000);
533     }
534   }
535 
536   isbW32m(HTE, 0x000200A1, 0xFFFF1000);
537   isbW32m(HTE, 0x00020011, 0x00011000);
538   isbW32m(HTE, 0x00020011, 0x00011100);
539 
540   WaitForHteComplete();
541 }
542 
543