+++ /dev/null
-/** @file\r
-HTE handling routines for MRC use.\r
-\r
-Copyright (c) 2013-2015 Intel Corporation.\r
-\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\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