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