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 543