]> git.proxmox.com Git - mirror_edk2.git/blobdiff - QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.c
QuarkSocPkg: Add new package for Quark SoC X1000
[mirror_edk2.git] / QuarkSocPkg / QuarkNorthCluster / MemoryInit / Pei / hte.c
diff --git a/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.c b/QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/hte.c
new file mode 100644 (file)
index 0000000..92ec4ba
--- /dev/null
@@ -0,0 +1,542 @@
+/** @file\r
+HTE handling routines for MRC use.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "mrc.h"\r
+#include "memory_options.h"\r
+#include "io.h"\r
+\r
+#include "hte.h"\r
+\r
+\r
+#ifdef SIM\r
+VOID delay_n(UINT32 nanoseconds);\r
+#define MySimStall(a)   delay_n(a/1000)\r
+#endif\r
+\r
+STATIC VOID EnableAllHteErrors(\r
+    UINT8 Mask)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ This function enables to HTE to detect all possible errors for\r
+ the given training parameters (per-bit or full byte lane).\r
+\r
+ Returns:\r
+\r
+ None\r
+\r
+ --*/\r
+{\r
+  isbW32m(HTE, 0x000200A2, 0xFFFFFFFF);\r
+  isbW32m(HTE, 0x000200A3, 0x000000FF);\r
+  isbW32m(HTE, 0x000200A4, 0x00000000);\r
+}\r
+\r
+STATIC UINT32 CheckHteErrors(\r
+    VOID)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ This function goes and reads the HTE register in order to find any error\r
+\r
+ Returns:\r
+\r
+ The errors detected in the HTE status register\r
+\r
+ --*/\r
+{\r
+  return isbR32m(HTE, 0x000200A7);\r
+}\r
+\r
+STATIC VOID WaitForHteComplete(\r
+    VOID)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ This function waits until HTE finishes\r
+\r
+ Returns:\r
+\r
+ None\r
+\r
+ --*/\r
+{\r
+  UINT32 Tmp;\r
+\r
+  ENTERFN();\r
+\r
+  //\r
+  // Is the test done?\r
+  //\r
+  do\r
+  {\r
+#ifdef SIM\r
+    MySimStall (35000); // 35 ns delay\r
+#endif\r
+  } while (0 != (isbR32m(HTE, 0x00020012) & BIT30));\r
+\r
+  Tmp = isbR32m(HTE, 0x00020011);\r
+  Tmp = Tmp | BIT9;\r
+  Tmp = Tmp & ~(BIT13 | BIT12);\r
+  isbW32m(HTE, 0x00020011, Tmp);\r
+\r
+  LEAVEFN();\r
+}\r
+\r
+STATIC VOID ClearHteErrorRegisters(\r
+    VOID)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Clears registers related with errors in the HTE.\r
+\r
+ Returns:\r
+\r
+ None\r
+\r
+ --*/\r
+{\r
+  UINT32 Tmp;\r
+\r
+  //\r
+  // Clear all HTE errors and enable error checking\r
+  // for burst and chunk.\r
+  //\r
+  Tmp = isbR32m(HTE, 0x000200A1);\r
+  Tmp |= BIT8;\r
+  isbW32m(HTE, 0x000200A1, Tmp);\r
+}\r
+\r
+UINT32 HteMemInit(\r
+    MRC_PARAMS *CurrentMrcData,\r
+    UINT8 MemInitFlag,\r
+    UINT8 HaltHteEngineOnError)\r
+\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Uses HW HTE engine to initialize or test all memory attached to a given DUNIT.\r
+ If MemInitFlag is 1, this routine writes 0s to all memory locations to initialize\r
+ ECC.\r
+ If MemInitFlag is 0, this routine will send an 5AA55AA5 pattern to all memory\r
+ locations on the RankMask and then read it back.  Then it sends an A55AA55A\r
+ pattern to all memory locations on the RankMask and reads it back.\r
+\r
+ Arguments:\r
+\r
+ CurrentMrcData: Host struture for all MRC global data.\r
+ MemInitFlag: 0 for memtest, 1 for meminit.\r
+ HaltHteEngineOnError:  Halt the HTE engine on first error observed, or keep\r
+ running to see how many errors are found.\r
+\r
+ Returns:\r
+ Errors register showing HTE failures.\r
+ Also prints out which rank failed the HTE test if failure occurs.\r
+ For rank detection to work, the address map must be left in its default\r
+ state.  If MRC changes the address map, this function must be modified\r
+ to change it back to default at the beginning, then restore it at the end.\r
+\r
+ --*/\r
+{\r
+  UINT32 Offset;\r
+  UINT8 TestNum;\r
+  UINT8 i;\r
+\r
+  //\r
+  // Clear out the error registers at the start of each memory\r
+  // init or memory test run.\r
+  //\r
+  ClearHteErrorRegisters();\r
+\r
+  isbW32m(HTE, 0x00020062, 0x00000015);\r
+\r
+  for (Offset = 0x80; Offset <= 0x8F; Offset++)\r
+  {\r
+    isbW32m(HTE, Offset, ((Offset & 1) ? 0xA55A : 0x5AA5));\r
+  }\r
+\r
+  isbW32m(HTE, 0x00020021, 0x00000000);\r
+#ifdef QUICKSIM\r
+  // Just do 4 cache lines for simulation memtest to save time.\r
+  isbW32m(HTE, 0x00020022, 4-1);\r
+#else\r
+  isbW32m(HTE, 0x00020022, (CurrentMrcData->mem_size >> 6) - 1);\r
+#endif\r
+\r
+  isbW32m(HTE, 0x00020063, 0xAAAAAAAA);\r
+  isbW32m(HTE, 0x00020064, 0xCCCCCCCC);\r
+  isbW32m(HTE, 0x00020065, 0xF0F0F0F0);\r
+  isbW32m(HTE, 0x00020066, 0x03000000);\r
+\r
+  switch (MemInitFlag)\r
+  {\r
+  case MrcMemInit:\r
+    TestNum = 1; // Only 1 write pass through memory is needed to initialize ECC.\r
+    break;\r
+  case MrcMemTest:\r
+    TestNum = 4; // Write/read then write/read with inverted pattern.\r
+    break;\r
+  default:\r
+    DPF(D_INFO, "Unknown parameter for MemInitFlag: %d\n", MemInitFlag);\r
+    return 0xFFFFFFFF;\r
+    break;\r
+  }\r
+\r
+  DPF(D_INFO, "HteMemInit");\r
+  for (i = 0; i < TestNum; i++)\r
+  {\r
+    DPF(D_INFO, ".");\r
+\r
+    if (i == 0)\r
+    {\r
+      isbW32m(HTE, 0x00020061, 0x00000000);\r
+      isbW32m(HTE, 0x00020020, 0x00110010);\r
+    }\r
+    else if (i == 1)\r
+    {\r
+      isbW32m(HTE, 0x00020061, 0x00000000);\r
+      isbW32m(HTE, 0x00020020, 0x00010010);\r
+    }\r
+    else if (i == 2)\r
+    {\r
+      isbW32m(HTE, 0x00020061, 0x00010100);\r
+      isbW32m(HTE, 0x00020020, 0x00110010);\r
+    }\r
+    else\r
+    {\r
+      isbW32m(HTE, 0x00020061, 0x00010100);\r
+      isbW32m(HTE, 0x00020020, 0x00010010);\r
+    }\r
+\r
+    isbW32m(HTE, 0x00020011, 0x00111000);\r
+    isbW32m(HTE, 0x00020011, 0x00111100);\r
+\r
+    WaitForHteComplete();\r
+\r
+    //\r
+    // If this is a READ pass, check for errors at the end.\r
+    //\r
+    if ((i % 2) == 1)\r
+    {\r
+      //\r
+      // Return immediately if  error.\r
+      //\r
+      if (CheckHteErrors())\r
+      {\r
+        break;\r
+      }\r
+    }\r
+  }\r
+\r
+  DPF(D_INFO, "done\n", i);\r
+  return CheckHteErrors();\r
+}\r
+\r
+STATIC UINT16 BasicDataCompareHte(\r
+    MRC_PARAMS *CurrentMrcData,\r
+    UINT32 Address,\r
+    UINT8 FirstRun,\r
+    UINT8 Mode)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Execute basic single cache line memory write/read/verify test using simple constant\r
+ pattern (different for READ_RAIN and WRITE_TRAIN modes.\r
+ See BasicWriteReadHTE which is external visible wrapper.\r
+\r
+ Arguments:\r
+\r
+ CurrentMrcData: Host struture for all MRC global data.\r
+ Address: memory adress being tested (must hit specific channel/rank)\r
+ FirstRun: If set then hte registers are configured, otherwise\r
+ it is assumed configuration is done and just re-run the test.\r
+ Mode: READ_TRAIN or WRITE_TRAIN (the difference is in the pattern)\r
+\r
+ Returns:\r
+ Returns byte lane failure on each bit (for Quark only bit0 and bit1)\r
+\r
+ --*/\r
+{\r
+  UINT32 Pattern;\r
+  UINT32 Offset;\r
+\r
+  if (FirstRun)\r
+  {\r
+    isbW32m(HTE, 0x00020020, 0x01B10021);\r
+    isbW32m(HTE, 0x00020021, 0x06000000);\r
+    isbW32m(HTE, 0x00020022, Address >> 6);\r
+    isbW32m(HTE, 0x00020062, 0x00800015);\r
+    isbW32m(HTE, 0x00020063, 0xAAAAAAAA);\r
+    isbW32m(HTE, 0x00020064, 0xCCCCCCCC);\r
+    isbW32m(HTE, 0x00020065, 0xF0F0F0F0);\r
+    isbW32m(HTE, 0x00020061, 0x00030008);\r
+\r
+    if (Mode == WRITE_TRAIN)\r
+    {\r
+      Pattern = 0xC33C0000;\r
+    }\r
+    else // READ_TRAIN\r
+    {\r
+      Pattern = 0xAA5555AA;\r
+    }\r
+\r
+    for (Offset = 0x80; Offset <= 0x8F; Offset++)\r
+    {\r
+      isbW32m(HTE, Offset, Pattern);\r
+    }\r
+  }\r
+\r
+  isbW32m(HTE, 0x000200A1, 0xFFFF1000);\r
+\r
+  isbW32m(HTE, 0x00020011, 0x00011000);\r
+  isbW32m(HTE, 0x00020011, 0x00011100);\r
+\r
+  WaitForHteComplete();\r
+\r
+  //\r
+  // Return bits 15:8 of HTE_CH0_ERR_XSTAT to check for any bytelane errors.\r
+  //\r
+  return ((CheckHteErrors() >> 8) & 0xFF);\r
+}\r
+\r
+STATIC UINT16 ReadWriteDataCompareHte(\r
+    MRC_PARAMS *CurrentMrcData,\r
+    UINT32 Address,\r
+    UINT8 LoopCount,\r
+    UINT32 LfsrSeedVictim,\r
+    UINT32 LfsrSeedAggressor,\r
+    UINT8 VictimBit,\r
+    UINT8 FirstRun)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Examines single cache line memory with write/read/verify test using\r
+ multiple data patterns (victim-aggressor algorithm).\r
+ See WriteStressBitLanesHTE which is external visible wrapper.\r
+\r
+ Arguments:\r
+\r
+ CurrentMrcData: host struture for all MRC global data.\r
+ Address: memory adress being tested (must hit specific channel/rank)\r
+ LoopCount: number of test iterations\r
+ LfsrSeedXxx: victim aggressor data pattern seed\r
+ VictimBit: should be 0 as auto rotate feature is in use.\r
+ FirstRun: If set then hte registers are configured, otherwise\r
+ it is assumed configuration is done and just re-run the test.\r
+\r
+ Returns:\r
+ Returns byte lane failure on each bit (for Quark only bit0 and bit1)\r
+\r
+ --*/\r
+{\r
+  UINT32 Offset;\r
+  UINT32 Tmp;\r
+\r
+  if (FirstRun)\r
+  {\r
+    isbW32m(HTE, 0x00020020, 0x00910024);\r
+    isbW32m(HTE, 0x00020023, 0x00810024);\r
+    isbW32m(HTE, 0x00020021, 0x06070000);\r
+    isbW32m(HTE, 0x00020024, 0x06070000);\r
+    isbW32m(HTE, 0x00020022, Address >> 6);\r
+    isbW32m(HTE, 0x00020025, Address >> 6);\r
+    isbW32m(HTE, 0x00020062, 0x0000002A);\r
+    isbW32m(HTE, 0x00020063, LfsrSeedVictim);\r
+    isbW32m(HTE, 0x00020064, LfsrSeedAggressor);\r
+    isbW32m(HTE, 0x00020065, LfsrSeedVictim);\r
+\r
+    //\r
+    // Write the pattern buffers to select the victim bit. Start with bit0.\r
+    //\r
+    for (Offset = 0x80; Offset <= 0x8F; Offset++)\r
+    {\r
+      if ((Offset % 8) == VictimBit)\r
+      {\r
+        isbW32m(HTE, Offset, 0x55555555);\r
+      }\r
+      else\r
+      {\r
+        isbW32m(HTE, Offset, 0xCCCCCCCC);\r
+      }\r
+    }\r
+\r
+    isbW32m(HTE, 0x00020061, 0x00000000);\r
+    isbW32m(HTE, 0x00020066, 0x03440000);\r
+    isbW32m(HTE, 0x000200A1, 0xFFFF1000);\r
+  }\r
+\r
+  Tmp = 0x10001000 | (LoopCount << 16);\r
+  isbW32m(HTE, 0x00020011, Tmp);\r
+  isbW32m(HTE, 0x00020011, Tmp | BIT8);\r
+\r
+  WaitForHteComplete();\r
+\r
+  return (CheckHteErrors() >> 8) & 0xFF;\r
+}\r
+\r
+UINT16 BasicWriteReadHTE(\r
+    MRC_PARAMS *CurrentMrcData,\r
+    UINT32 Address,\r
+    UINT8 FirstRun,\r
+    UINT8 Mode)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Execute basic single cache line memory write/read/verify test using simple constant\r
+ pattern (different for READ_RAIN and WRITE_TRAIN modes.\r
+\r
+ Arguments:\r
+\r
+ CurrentMrcData: Host struture for all MRC global data.\r
+ Address: memory adress being tested (must hit specific channel/rank)\r
+ FirstRun: If set then hte registers are configured, otherwise\r
+ it is assumed configuration is done and just re-run the test.\r
+ Mode: READ_TRAIN or WRITE_TRAIN (the difference is in the pattern)\r
+\r
+ Returns:\r
+ Returns byte lane failure on each bit (for Quark only bit0 and bit1)\r
+\r
+ --*/\r
+{\r
+  UINT16 ByteLaneErrors;\r
+\r
+  ENTERFN();\r
+\r
+  //\r
+  // Enable all error reporting in preparation for HTE test.\r
+  //\r
+  EnableAllHteErrors(0xFF);\r
+  ClearHteErrorRegisters();\r
+\r
+  ByteLaneErrors = BasicDataCompareHte(CurrentMrcData, Address, FirstRun,\r
+      Mode);\r
+\r
+  LEAVEFN();\r
+  return ByteLaneErrors;\r
+}\r
+\r
+UINT16 WriteStressBitLanesHTE(\r
+    MRC_PARAMS *CurrentMrcData,\r
+    UINT32 Address,\r
+    UINT8 FirstRun)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Examines single cache line memory with write/read/verify test using\r
+ multiple data patterns (victim-aggressor algorithm).\r
+\r
+ Arguments:\r
+\r
+ CurrentMrcData: host struture for all MRC global data.\r
+ Address: memory adress being tested (must hit specific channel/rank)\r
+ FirstRun: If set then hte registers are configured, otherwise\r
+ it is assumed configuration is done and just re-run the test.\r
+\r
+ Returns:\r
+ Returns byte lane failure on each bit (for Quark only bit0 and bit1)\r
+\r
+ --*/\r
+{\r
+  UINT16 ByteLaneErrors;\r
+  UINT8 VictimBit = 0;\r
+\r
+  ENTERFN();\r
+\r
+  //\r
+  // Enable all error reporting in preparation for HTE test.\r
+  //\r
+  EnableAllHteErrors(0xFF);\r
+  ClearHteErrorRegisters();\r
+\r
+  //\r
+  // Loop through each bit in the bytelane.  Each pass creates a victim bit\r
+  // while keeping all other bits the same - as aggressors.\r
+  // AVN HTE adds an auto-rotate feature which allows us to program the entire victim/aggressor\r
+  // sequence in 1 step. The victim bit rotates on each pass so no need to have software implement\r
+  // a victim bit loop like on VLV.\r
+  //\r
+  ByteLaneErrors = ReadWriteDataCompareHte(CurrentMrcData, Address,\r
+      HTE_LOOP_CNT, HTE_LFSR_VICTIM_SEED, HTE_LFSR_AGRESSOR_SEED, VictimBit,\r
+      FirstRun);\r
+\r
+  LEAVEFN();\r
+  return ByteLaneErrors;\r
+}\r
+\r
+VOID HteMemOp(\r
+    UINT32 Address,\r
+    UINT8 FirstRun,\r
+    UINT8 IsWrite)\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Execute basic single cache line memory write or read.\r
+ This is just for receive enable / fine write levelling purpose.\r
+\r
+ Arguments:\r
+\r
+ CurrentMrcData: Host structure for all MRC global data.\r
+ Address: memory address used (must hit specific channel/rank)\r
+ FirstRun: If set then hte registers are configured, otherwise\r
+ it is assumed configuration is done and just re-run the test.\r
+ IsWrite: When non-zero memory write operation executed, otherwise read\r
+\r
+ Returns:\r
+ None\r
+\r
+ --*/\r
+{\r
+  UINT32 Offset;\r
+  UINT32 Tmp;\r
+\r
+  EnableAllHteErrors(0xFF);\r
+  ClearHteErrorRegisters();\r
+\r
+  if (FirstRun)\r
+  {\r
+    Tmp = IsWrite ? 0x01110021 : 0x01010021;\r
+    isbW32m(HTE, 0x00020020, Tmp);\r
+\r
+    isbW32m(HTE, 0x00020021, 0x06000000);\r
+    isbW32m(HTE, 0x00020022, Address >> 6);\r
+    isbW32m(HTE, 0x00020062, 0x00800015);\r
+    isbW32m(HTE, 0x00020063, 0xAAAAAAAA);\r
+    isbW32m(HTE, 0x00020064, 0xCCCCCCCC);\r
+    isbW32m(HTE, 0x00020065, 0xF0F0F0F0);\r
+    isbW32m(HTE, 0x00020061, 0x00030008);\r
+\r
+    for (Offset = 0x80; Offset <= 0x8F; Offset++)\r
+    {\r
+      isbW32m(HTE, Offset, 0xC33C0000);\r
+    }\r
+  }\r
+\r
+  isbW32m(HTE, 0x000200A1, 0xFFFF1000);\r
+  isbW32m(HTE, 0x00020011, 0x00011000);\r
+  isbW32m(HTE, 0x00020011, 0x00011100);\r
+\r
+  WaitForHteComplete();\r
+}\r
+\r