Home | History | Annotate | Download | only in Pei
      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