]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.c
QuarkSocPkg/QncSmmDispatcher: Fix context passed to SMI handlers
[mirror_edk2.git] / QuarkSocPkg / QuarkNorthCluster / MemoryInit / Pei / hte.c
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
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
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
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
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
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
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
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
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
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
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