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