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