summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniil Egranov <daniil.egranov@arm.com>2018-05-17 20:41:43 -0500
committerThomas Abraham <thomas.abraham@arm.com>2020-04-15 21:22:49 +0530
commitfd10b408cc7c12868e2f964a7cac99fab7d04252 (patch)
tree0ace5814ba1689f5f98fabeac50b7f47ca900823
parentc7990f105a92f08056b06ff8692de2f7790a7ee5 (diff)
RAS: Added StandaloneMM DMC620 RAS driver
The StandaloneMM RAS DMC driver implements: - DMC RAS event handler - ACPI CPER update procedure - Error injection https://jira.arm.com/browse/PLATFORMS-660 https://jira.arm.com/browse/PLATFORMS-772 Change-Id: I5fac64a899f2b73e43d4ba22717dd7b496dccda8 Signed-off-by: Sughosh Ganu <sughosh.ganu@arm.com>
-rw-r--r--Platform/ARM/ARM.dec7
-rw-r--r--Platform/ARM/Drivers/StandaloneMmDmc620RasDriver/StandaloneMmDmc620ErrorInjection.c166
-rw-r--r--Platform/ARM/Drivers/StandaloneMmDmc620RasDriver/StandaloneMmDmc620RasDriver.c591
-rw-r--r--Platform/ARM/Drivers/StandaloneMmDmc620RasDriver/StandaloneMmDmc620RasDriver.h686
-rw-r--r--Platform/ARM/Drivers/StandaloneMmDmc620RasDriver/StandaloneMmDmc620RasDriver.inf59
5 files changed, 1509 insertions, 0 deletions
diff --git a/Platform/ARM/ARM.dec b/Platform/ARM/ARM.dec
index 5175b313..c9f21a61 100644
--- a/Platform/ARM/ARM.dec
+++ b/Platform/ARM/ARM.dec
@@ -20,3 +20,10 @@
[Guids]
gArmBootMonFsFileInfoGuid = { 0x41e26b9c, 0xada6, 0x45b3, { 0x80, 0x8e, 0x23, 0x57, 0xa3, 0x5b, 0x60, 0xd6 } }
+ gEfiMmDmcErrorInjectEventGuid = { 0x09148301, 0xa50f, 0x43eb, { 0x8e, 0x2a, 0x74, 0x88, 0x9a, 0xdd, 0x89, 0x92 }}
+ gEfiMmDmcRasEventGuid = { 0x5ef0afd5, 0xe01a, 0x4c30, { 0x86, 0x19, 0x45, 0x46, 0x26, 0x91, 0x80, 0x98 }}
+ gEfiSmmVariableProtocolGuid = { 0xed32d533, 0x99e6, 0x4209, { 0x9c, 0xc0, 0x2d, 0x72, 0xcd, 0xd9, 0x98, 0xa7 }}
+
+[PcdsFixedAtBuild, PcdsPatchableInModule]
+ ## DMC620 memory error threshold.
+ gStandaloneMmPkgTokenSpaceGuid.PcdDmcCorrectableErrorThreshold|1|UINT32|0x00000001
diff --git a/Platform/ARM/Drivers/StandaloneMmDmc620RasDriver/StandaloneMmDmc620ErrorInjection.c b/Platform/ARM/Drivers/StandaloneMmDmc620RasDriver/StandaloneMmDmc620ErrorInjection.c
new file mode 100644
index 00000000..1d07dee9
--- /dev/null
+++ b/Platform/ARM/Drivers/StandaloneMmDmc620RasDriver/StandaloneMmDmc620ErrorInjection.c
@@ -0,0 +1,166 @@
+/** @file
+*
+* Copyright (c) 2017-2018, ARM Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+#include "StandaloneMmDmc620RasDriver.h"
+
+/**
+ Private copy of the MM system table for future use
+**/
+extern EFI_MM_SYSTEM_TABLE *mMmst;
+
+/**
+ This function sets DMC to the test mode required for the error injection
+
+ @param DmcCtrl A pointer to DMC620 control registers
+ @param TstEnable Enable or diasble test mode
+
+ @return Status Code
+
+**/
+static
+EFI_STATUS
+Dmc620SetErrorInjectionMode (
+ IN DMC620_REGS_TYPE *DmcCtrl,
+ IN BOOLEAN TstEnable
+ )
+{
+ UINT32 DmcCtrlData;
+
+ if (DmcCtrl == NULL ) {
+ DEBUG ((DEBUG_ERROR, "Dmc620SetErrorInjectionMode: Invalid DMC control registers address\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (TstEnable == TRUE) {
+ DmcCtrlData = DmcCtrl->IntegCfg | TST_MODE_ENABLE;
+ } else {
+ DmcCtrlData = (DmcCtrl->IntegCfg >> 1) << 1;
+ }
+
+ DmcCtrl->IntegCfg = DmcCtrlData;
+ Dmc620DrainCmd (DmcCtrl);
+
+ DEBUG ((DEBUG_INFO, "DMC620 RAS injection mode: 0x%x\n", DmcCtrl->IntegCfg));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets the injection bits
+
+ @param DmcCtrl A pointer to DMC620 control registers
+ @param InjectBit Injection type
+
+ @return Status Code
+
+**/
+static
+EFI_STATUS
+Dmc620SetErrorInjectionBit (
+ IN DMC620_REGS_TYPE *DmcCtrl,
+ IN ERR_INJECT_TYPE InjectType
+ )
+{
+ UINT32 *ErrMemLocation;
+ EFI_STATUS Status;
+ UINT32 DmcCtrlData;
+
+ if (DmcCtrl == NULL ) {
+ DEBUG ((DEBUG_ERROR, "Dmc620SetErrorInjectionBit: Invalid DMC control registers address\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Allocate memory for error injection
+ Status = mMmst->MmAllocatePool(EfiRuntimeServicesData, sizeof(UINT32), (VOID **) &ErrMemLocation);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "Dmc620ErrorInjectEventHandler: Memory allocation failed\n"));
+ return Status;
+ }
+
+ // Disarm trigger bit
+ DmcCtrlData = DmcCtrl->IntegCfg & (~InjectType);
+ DmcCtrl->IntegCfg = DmcCtrlData;
+ Dmc620DrainCmd (DmcCtrl);
+
+ // Arm trigger bit
+ DmcCtrlData = DmcCtrl->IntegCfg | InjectType;
+ DmcCtrl->IntegCfg = DmcCtrlData;
+ Dmc620DrainCmd (DmcCtrl);
+
+ *(volatile UINT32*)ErrMemLocation = 0xaceddead;
+
+ DEBUG ((DEBUG_INFO, "DMC620 RAS error injection address: 0x%x\n", ErrMemLocation));
+ DEBUG ((DEBUG_INFO, "DMC620 RAS injection bits: 0x%x\n", DmcCtrl->IntegCfg));
+ DEBUG ((DEBUG_INFO, "DMC620 RAS correctable error counter: 0x%x\n", DmcCtrl->Err4Misc2));
+
+ mMmst->MmFreePool (ErrMemLocation);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is the entry point for DMC620 error injection event
+
+ @param DispatchHandle The unique handle assigned to this handler by MmiHandlerRegister().
+ @param Context Points to an optional handler context which was specified when the handler was registered.
+ @param CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-MM environment into an MM environment.
+ @param CommBufferSize The size of the CommBuffer.
+
+ @return Status Code
+
+**/
+EFI_STATUS
+EFIAPI
+Dmc620ErrorInjectEventHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *Context, OPTIONAL
+ IN OUT VOID *CommBuffer, OPTIONAL
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ DMC620_REGS_TYPE *DmcCtrl;
+
+ ASSERT (Context == NULL);
+
+ Status = EFI_SUCCESS;
+ DmcCtrl = DMC620_0;
+
+ DEBUG ((DEBUG_INFO, "DMC620 error inject: CommBuffer - 0x%x, CommBufferSize - 0x%x\n",
+ CommBuffer,
+ *CommBufferSize));
+
+ // Check DMC controller status
+ Status = Dmc620Status (DmcCtrl);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, "Dmc620ErrorInjectEventHandler: Invalid DMC status\n"));
+ return Status;
+ }
+
+ // Enable error injection
+ Status = Dmc620SetErrorInjectionMode (DmcCtrl, TRUE);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, "Dmc620ErrorInjectEventHandler: Failed to enable error injection\n"));
+ return Status;
+ }
+
+ // Inject the single bit error
+ Status = Dmc620SetErrorInjectionBit (DmcCtrl, SINGLE_BIT_INJECT);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, "Dmc620ErrorInjectEventHandler: Failed to set injection type\n"));
+ return Status;
+ }
+
+ return Status;
+}
diff --git a/Platform/ARM/Drivers/StandaloneMmDmc620RasDriver/StandaloneMmDmc620RasDriver.c b/Platform/ARM/Drivers/StandaloneMmDmc620RasDriver/StandaloneMmDmc620RasDriver.c
new file mode 100644
index 00000000..fc2ea7cb
--- /dev/null
+++ b/Platform/ARM/Drivers/StandaloneMmDmc620RasDriver/StandaloneMmDmc620RasDriver.c
@@ -0,0 +1,591 @@
+/** @file
+*
+* Copyright (c) 2017-2018, ARM Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include "StandaloneMmDmc620RasDriver.h"
+
+//
+// Private copy of the MM system table for future use
+//
+EFI_MM_SYSTEM_TABLE *mMmst = NULL;
+
+static EFI_GUID DMC620_CPER_GUID[RAS_DMC620_ERROR_SOURCE_TOTAL] =
+{
+ { 0xb4c19352, 0xf224, 0x4586, { 0x9f, 0x7e, 0x13, 0xb3, 0xa3, 0xc9, 0x2d, 0xbd }}, // 804 Event
+ { 0xce920f02, 0x6203, 0x46ed, { 0xac, 0x63, 0x67, 0x0a, 0x0f, 0xea, 0x35, 0x30 }} // 805 Event
+};
+
+EFI_MM_RAS_ERROR_SOURCE_INFO_PROTOCOL mEfiMmDmcErrorSourceInfo = {
+ EFI_MM_RAS_ERROR_SOURCE_INFO_REVISION,
+ Dmc620ErrorSourceInfoGet
+};
+
+static EFI_GUID ErrorSectionType[1] = {
+ EFI_ERROR_SECTION_PLATFORM_MEMORY_GUID
+};
+
+struct ErrorDataStruct {
+ EFI_PLATFORM_MEMORY_ERROR_DATA MemoryError;
+};
+
+static struct ErrorDataStruct ErrorData;
+
+static SECTIONS_INFO ErrorSectionInfo = { 1, sizeof(ErrorData), ErrorSectionType, &ErrorData };
+
+EFI_HANDLE mDmcHandle = NULL;
+
+static
+EFI_STATUS
+EFIAPI
+GenerateCperBlob (
+ IN OUT SECTIONS_INFO **SectionInfo
+ )
+{
+ DEBUG((DEBUG_INFO, "Configure CPER\n"));
+ *SectionInfo = &ErrorSectionInfo;
+
+ ErrorData.MemoryError.ValidFields = EFI_PLATFORM_MEMORY_PHY_ADDRESS_VALID |
+ EFI_PLATFORM_MEMORY_PHY_ADDRESS_MASK_VALID |
+ EFI_PLATFORM_MEMORY_ERROR_TYPE_VALID;
+ ErrorData.MemoryError.ErrorStatus.Type = ErrorMemStorage;
+ ErrorData.MemoryError.ErrorStatus.DataSignal = 1;
+ ErrorData.MemoryError.ErrorStatus.DetectedByResponder = 1;
+ ErrorData.MemoryError.PhysicalAddress = 0x4001FFF0;
+ ErrorData.MemoryError.PhysicalAddressMask = 0xFFFFFFFFFFFFF000;
+ ErrorData.MemoryError.Node = 0;
+ ErrorData.MemoryError.Card = 0;
+ ErrorData.MemoryError.ModuleRank = 0;
+ ErrorData.MemoryError.Bank = 5;
+ ErrorData.MemoryError.Device = 0;
+ ErrorData.MemoryError.Row = 0xA;
+ ErrorData.MemoryError.Column = 5;
+ ErrorData.MemoryError.BitPosition = 8;
+ ErrorData.MemoryError.RequestorId = 0xFFFFFFFFFFFFFFFF;
+ ErrorData.MemoryError.ResponderId = 0xAA55AA55AA55AA55;
+ ErrorData.MemoryError.TargetId = 0xFFFFFFFFFFFFFFFF;
+ ErrorData.MemoryError.ErrorType = EFI_PLATFORM_MEMORY_ERROR_PARITY;
+ ErrorData.MemoryError.Extended = 0;
+ ErrorData.MemoryError.RankNum = 0;
+ ErrorData.MemoryError.CardHandle = 0;
+ ErrorData.MemoryError.ModuleHandle = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets the correctable errors threshold
+
+ @param DmcRegs A pointer to the specific type of DMC error registers
+ @param ErrRecType A type of the DMC error register
+ @param ErrThreshold Error threshold value
+
+ @return Status Code
+
+**/
+EFI_STATUS
+Dmc620RasSetCorrectableErrorThreshold (
+ IN volatile DMC620_ERR_REGS_TYPE *DmcRegs,
+ IN ERR_RECORD_TABLE_TYPE ErrRecType,
+ IN UINT32 ErrThreshold
+ )
+{
+ if (DmcRegs == NULL) {
+ DEBUG ((DEBUG_ERROR, "Dmc620SetCorrectableErrorCounterThreshold: Invalid DMC control registers address\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //TODO: Error counters for other errors
+ switch (ErrRecType) {
+ case DRAM_ECC_CORRECTED_FH:
+ break;
+ case DRAM_ECC_FH:
+ break;
+ case CHI_FH:
+ break;
+ case SRAM_ECC_CORRECTED_FH:
+ DmcRegs->ErrMisc2 = 0x8000 - ErrThreshold;
+ DEBUG ((DEBUG_INFO, "DMC620 RAS correctable error counter: 0x%x\n", DmcRegs->ErrMisc2));
+ break;
+ case SRAM_ECC_FH:
+ break;
+ case DMC_ERROR_RECOVERY:
+ break;
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function will drain the last DMC command
+
+ @param DmcCtrl A pointer to DMC620 control registers
+
+ @return none
+
+**/
+VOID
+Dmc620DrainCmd (
+ IN volatile DMC620_REGS_TYPE *DmcCtrl
+ )
+{
+ DmcCtrl->MemcCmd = EXECUTE_DRAIN;
+ while (((UINT32)DmcCtrl->MemcStatus & STATE_MASK) != READY_STATE) {
+ continue;
+ }
+}
+
+/**
+ This function gets the DMC Status string
+
+ @param DmcCtrl A pointer to DMC620 control registers
+ @param StatusMask A bit mask for the status
+
+ @return none
+
+**/
+static
+CONST
+CHAR16*
+GetSupportStatusString (
+ IN volatile DMC620_REGS_TYPE *DmcCtrl,
+ IN UINT32 StatusMask
+ )
+{
+ static CHAR16 Controllable[] = L"CONTROLLABLE";
+ static CHAR16 None[] = L"NONE";
+
+ if ((DmcCtrl->Err0Fr & StatusMask) == StatusMask) {
+ return Controllable;
+ }
+
+ return None;
+}
+
+/**
+ This function prints out DMC supported features
+
+ @param DmcCtrl A pointer to DMC620 control registers
+
+ @return none
+
+**/
+static
+VOID
+Dmc620RasSupportCheck (
+ IN volatile DMC620_REGS_TYPE *DmcCtrl
+ )
+{
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Available Features:\n"));
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Error Detection : %s\n", GetSupportStatusString (DmcCtrl, ED_FE_ENABLED)));
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Error on Writes deferred : %s\n",
+ GetSupportStatusString (DmcCtrl, DE_FE_ENABLED)));
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Uncorrected Error Recovery Interrupt : %s\n",
+ GetSupportStatusString (DmcCtrl, UI_FE_ENABLED)));
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Fault Handling Interrupt : %s\n",
+ GetSupportStatusString (DmcCtrl, FI_FE_ENABLED)));
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Uncorrected Error Reporting : %s\n",
+ GetSupportStatusString (DmcCtrl, UE_FE_ENABLED)));
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Corrected Fault Handling Interrupt : %s\n",
+ GetSupportStatusString (DmcCtrl, CFI_FE_ENABLED)));
+}
+
+/**
+ This function parses DMC RAS errors
+
+ @param DmcRegs A pointer to the specific type of DMC error registers
+ @param DmcCtrl A pointer to DMC620 control registers
+ @param ErrRecType A type of the DMC error register
+
+ @return none
+
+**/
+static
+VOID
+Dmc620RasProcessError (
+ IN volatile DMC620_ERR_REGS_TYPE *DmcErrRegs,
+ IN volatile DMC620_REGS_TYPE *DmcCtrl,
+ IN ERR_RECORD_TABLE_TYPE ErrRecType
+ )
+{
+ UINT32 ResetReg;
+ UINT32 ErrorRank;
+ BOOLEAN CEValid;
+ UINTN NumMiscRegs;
+ UINTN RegsCount;
+ UINT32 MiscReg[6];
+ UINT32 ErrThreshold;
+ EFI_STATUS Status;
+ SECTIONS_INFO *SectionInfo;
+
+ ErrorRank = 0xFFFF;
+ CEValid = FALSE;
+ NumMiscRegs = 0;
+
+ while (DmcErrRegs->ErrStatus != 0) {
+ GenerateCperBlob (&SectionInfo);
+ if (DmcErrRegs->ErrStatus & ERR_STATUS_V) {
+ DEBUG ((DEBUG_INFO, "*************************************\n"));
+ switch (ErrRecType) {
+ case DRAM_ECC_CORRECTED_FH:
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Error: DRAM ECC Corrected Fault\nError Dump:\n"));
+ ErrorRank = (DmcErrRegs->ErrStatus & ERR_STATUS_IERR) >> ERR_STATUS_RANK_BIT;
+ CEValid = TRUE;
+ NumMiscRegs = 6;
+ break;
+ case DRAM_ECC_FH:
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Error: DRAM ECC Fault Handling\nError Dump:\n"));
+ NumMiscRegs = 6;
+ break;
+ case CHI_FH:
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Error: CHI Fault\nError Dump:\n"));
+ CEValid = TRUE;
+ NumMiscRegs = 2;
+ break;
+ case SRAM_ECC_CORRECTED_FH:
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Error: SRAM ECC Corrected Fault\nError Dump:\n"));
+ CEValid = TRUE;
+ NumMiscRegs = 3;
+ break;
+ case SRAM_ECC_FH:
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Error: SRAM ECC Fault\nError Dump:\n"));
+ NumMiscRegs = 3;
+ break;
+ case DMC_ERROR_RECOVERY:
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Error: DMC Error Recovery\nError Dump:\n"));
+ NumMiscRegs = 2;
+ break;
+ default:
+ break;
+ }
+
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Error Type : "));
+ if ((DmcErrRegs->ErrStatus & ERR_STATUS_ECC_ERR_SRAM) == ERR_STATUS_ECC_ERR_SRAM) {
+ DEBUG ((DEBUG_INFO, "SRAM\n"));
+ } else if ((DmcErrRegs->ErrStatus & ERR_STATUS_ECC_ERR_SDRAM) == ERR_STATUS_ECC_ERR_SDRAM) {
+ DEBUG ((DEBUG_INFO, "DRAM\n"));
+ } else if ((DmcErrRegs->ErrStatus & ERR_STATUS_ECC_ERR_DBP) == ERR_STATUS_ECC_ERR_DBP) {
+ DEBUG ((DEBUG_INFO, "DPB\n"));
+ } else {
+ DEBUG ((DEBUG_INFO, "NONE\n"));
+ }
+
+ if (ErrorRank != 0xFFFF) {
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Error Rank : %d\n", ErrorRank));
+ }
+
+ if (CEValid) {
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Corrected Error Recorded : "));
+ if ((DmcErrRegs->ErrStatus & ERR_STATUS_CE_PERSISTENT) == ERR_STATUS_CE_PERSISTENT) {
+ DEBUG ((DEBUG_INFO, "PERSISTENT\n"));
+ } else if ((DmcErrRegs->ErrStatus & ERR_STATUS_CE_CORRECTED) == ERR_STATUS_CE_CORRECTED) {
+ DEBUG ((DEBUG_INFO, "CORRECTED\n"));
+ } else if ((DmcErrRegs->ErrStatus & ERR_STATUS_CE_TRANSIENT) == ERR_STATUS_CE_TRANSIENT) {
+ DEBUG ((DEBUG_INFO, "TRANSIENT\n"));
+ } else {
+ DEBUG ((DEBUG_INFO, "NONE\n"));
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Correctable Error Counter Overflow : "));
+ if (DmcErrRegs->ErrStatus & ERR_STATUS_OF) {
+ DEBUG ((DEBUG_INFO, "YES\n"));
+ } else {
+ DEBUG ((DEBUG_INFO, "NO\n"));
+ }
+
+ if ((DmcErrRegs->ErrStatus & ERR_STATUS_AV) == ERR_STATUS_AV) {
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Error Address Registers Are Valid\n"));
+ DEBUG ((DEBUG_INFO, "---------------------------------\n"));
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Error Address 0 : 0x%x\n", DmcErrRegs->ErrAddr0));
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Error Address 1 : 0x%x\n", DmcErrRegs->ErrAddr1));
+ DEBUG ((DEBUG_INFO, "---------------------------------\n"));
+ ErrorData.MemoryError.PhysicalAddress = DmcErrRegs->ErrAddr1;
+ ErrorData.MemoryError.PhysicalAddress = ErrorData.MemoryError.PhysicalAddress << 32 | DmcErrRegs->ErrAddr0;
+ ErrorData.MemoryError.ErrorType = EFI_PLATFORM_MEMORY_ERROR_PARITY;
+ }
+
+ if ((DmcErrRegs->ErrStatus & ERR_STATUS_MV) == ERR_STATUS_MV) {
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Misc Registers Are Valid\n"));
+
+ MiscReg[0] = DmcErrRegs->ErrMisc0;
+ MiscReg[1] = DmcErrRegs->ErrMisc1;
+ MiscReg[2] = DmcErrRegs->ErrMisc2;
+ MiscReg[3] = DmcErrRegs->ErrMisc3;
+ MiscReg[4] = DmcErrRegs->ErrMisc4;
+ MiscReg[5] = DmcErrRegs->ErrMisc5;
+
+ DEBUG ((DEBUG_INFO, "---------------------------------\n"));
+ for (RegsCount = 0; RegsCount < NumMiscRegs; RegsCount++) {
+ DEBUG ((DEBUG_INFO, "DMC620 RAS Error Misc %d : 0x%x\n", RegsCount, MiscReg[RegsCount]));
+ }
+ DEBUG ((DEBUG_INFO, "---------------------------------\n"));
+ }
+ DEBUG ((DEBUG_INFO, "*************************************\n"));
+ }
+
+ if (((UINT32)DmcErrRegs->ErrStatus & ERR_STATUS_OF) == ERR_STATUS_OF) {
+ ErrThreshold = PcdGet32(PcdDmcCorrectableErrorThreshold);
+ Dmc620RasSetCorrectableErrorThreshold (DmcErrRegs, ErrRecType, ErrThreshold);
+ }
+
+ ResetReg = DmcErrRegs->ErrStatus;
+ DmcErrRegs->ErrStatus = ResetReg;
+ Dmc620DrainCmd (DmcCtrl);
+ Status = CperWrite(SectionInfo, PcdGet64 (PcdCperBufferBase));
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to Write CPER blob.\n"));
+ }
+ }
+}
+
+/**
+ This function checks if DMC status is valid
+
+ @param DmcCtrl A pointer to DMC620 control registers
+
+ @return Status Code
+
+**/
+EFI_STATUS
+Dmc620Status (
+ IN volatile DMC620_REGS_TYPE *DmcCtrl
+ )
+{
+ if (DmcCtrl == NULL) {
+ DEBUG ((DEBUG_ERROR, "Dmc620EnableRAS: Invalid DMC control registers address\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((DmcCtrl->MemcStatus & STATE_MASK) != READY_STATE) {
+ DEBUG ((DEBUG_ERROR, "Dmc620EnableRAS: Invalid DMC state\n"));
+ return RETURN_DEVICE_ERROR;
+ }
+
+ DEBUG ((DEBUG_INFO, "DMC620 RAS ctrl0: 0x%x\n", DmcCtrl->Err0Ctlr0));
+ DEBUG ((DEBUG_INFO, "DMC620 RAS ctrl1: 0x%x\n", DmcCtrl->Err0Ctlr1));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This is an initialize procedure for the driver.
+
+ The driver handler will be dispatched by CPU driver and does not
+ require and CPU save restore mechanisms.
+
+**/
+EFI_STATUS
+Dmc620RasDriverInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DispatchHandle;
+ volatile DMC620_REGS_TYPE *DmcCtrl;
+ UINT32 ErrThreshold;
+
+ ASSERT (SystemTable != NULL);
+ mMmst = SystemTable;
+
+ //TODO: Support all DMCX
+ DmcCtrl = DMC620_0;
+
+ // register the RAS event handle
+ Status = mMmst->MmiHandlerRegister (Dmc620RasEventHandler, &gEfiMmDmcRasEventGuid, &DispatchHandle);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, "Dmc620RasDriverInitialize: DMC620 RAS registration failed\n"));
+ return Status;
+ }
+
+ // Install error source information protocol
+ Status = mMmst->MmInstallProtocolInterface (&mDmcHandle,
+ &gEfiMmRasErrorSourceInfoProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mEfiMmDmcErrorSourceInfo);
+
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, "Dmc620RasDriverInitialize: DMC620 RAS error source info protocol failed\n"));
+ return Status;
+ }
+
+ DEBUG ((DEBUG_INFO, "DMC620 RAS registered\n"));
+
+ // register the inject error handle
+ Status = mMmst->MmiHandlerRegister (Dmc620ErrorInjectEventHandler,
+ &gEfiMmDmcErrorInjectEventGuid,
+ &DispatchHandle);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, "MM DMC620 error injection registration failed\n"));
+ return Status;
+ }
+
+ // Set error threshold for correctable errors
+ ErrThreshold = PcdGet32 (PcdDmcCorrectableErrorThreshold);
+ Status = Dmc620RasSetCorrectableErrorThreshold ((DMC620_ERR_REGS_TYPE *)((UINTN)&DmcCtrl->Err4Fr),
+ SRAM_ECC_CORRECTED_FH,
+ ErrThreshold);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, "Dmc620RasDriverInitialize: Failed to set error threshold\n"));
+ return Status;
+ }
+
+ DEBUG ((DEBUG_INFO, "DMC620 error injection registered\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get RAS Error Source Information.
+
+ @param This Instance pointer for this protocol
+
+ @retval Buffer RAE Error Source Information buffer.
+ @retval ErrorSourceCount Number of supported RAS Error Sources.
+ The Buffer parameter points to the begining
+ of Error Source records.
+ @retval EFI_SUCCESS Device supports RAS error sources.
+ @retval EFI_UNSUPPORTED Device does not support RAS error sources.
+ @retval EFI_DEVICE_ERROR Device device read error.
+**/
+EFI_STATUS
+EFIAPI
+Dmc620ErrorSourceInfoGet (
+ IN EFI_MM_RAS_ERROR_SOURCE_INFO_PROTOCOL *This,
+ OUT EFI_APEI_ERROR_SOURCE **Buffer,
+ OUT UINTN *ErrorSourceCount
+ )
+{
+ EFI_STATUS Status;
+ EFI_APEI_ERROR_SOURCE *Source;
+ UINTN Index;
+ UINTN NextErrorAddress;
+
+ Status = mMmst->MmAllocatePool (EfiRuntimeServicesData,
+ (sizeof(EFI_APEI_ERROR_SOURCE) * RAS_DMC620_ERROR_SOURCE_TOTAL),
+ (VOID **) &Source);
+
+ if (Buffer == NULL) {
+ *ErrorSourceCount = RAS_DMC620_ERROR_SOURCE_TOTAL;
+ return EFI_SUCCESS;
+ }
+
+ *Buffer = NULL;
+ *ErrorSourceCount = 0;
+
+ if (!EFI_ERROR(Status)) {
+ *Buffer = Source;
+ *ErrorSourceCount = RAS_DMC620_ERROR_SOURCE_TOTAL;
+
+ for (Index = 0; Index < RAS_DMC620_ERROR_SOURCE_TOTAL; Index++) {
+ NextErrorAddress = PcdGet64 (PcdCperBufferBase) +
+ (RAS_DMC620_ERROR_CPER_RECORD_SIZE + RAS_DMC620_ERROR_ACK_REGISTER_SIZE) * Index;
+
+ Source->SourceId = 1 + Index;
+ Source->GhesType = RAS_DMC620_ERROR_GHES_TYPE_V2;
+ Source->EventId = RAS_DMC620_ERROR_SOURCE_START_EVENT + Index;
+ Source->NumberRecordstoPreAllocate = 1;
+ Source->MaxSectionsPerRecord = 1;
+ Source->MaxRawDataLength = RAS_DMC620_ERROR_CPER_RECORD_SIZE;
+ Source->ErrorStatusBlockLength = RAS_DMC620_ERROR_CPER_RECORD_SIZE;
+
+ // TODO: Implement a malloc type function for allocating a CPER memory from the CPER memory pool.
+ // Replace the PCD variable with a malloc function.
+ Source->ErrorStatusAddress.AddrerssSpaceId = RAS_DMC620_ERROR_ADDRESS_SPACE;
+ Source->ErrorStatusAddress.RegisterBitWidth = RAS_DMC620_ERROR_REGISTER_WIDTH_BIT;
+ Source->ErrorStatusAddress.RegisterBitOffset = RAS_DMC620_ERROR_REGISTER_OFFSET_BIT;
+ Source->ErrorStatusAddress.AccessSize = RAS_DMC620_ERROR_ACCESS_SIZE;
+ Source->ErrorStatusAddress.Address = NextErrorAddress;
+
+ // GHESv2 acknowledgment register
+ Source->ReadAckRegister.AddrerssSpaceId = RAS_DMC620_ERROR_ADDRESS_SPACE;
+ Source->ReadAckRegister.RegisterBitWidth = RAS_DMC620_ERROR_REGISTER_WIDTH_BIT;
+ Source->ReadAckRegister.RegisterBitOffset = RAS_DMC620_ERROR_REGISTER_OFFSET_BIT;
+ Source->ReadAckRegister.AccessSize = RAS_DMC620_ERROR_ACCESS_SIZE;
+ Source->ReadAckRegister.Address = NextErrorAddress + RAS_DMC620_ERROR_CPER_RECORD_SIZE;
+ Source->ReadAckPreserve = 0;
+ Source->ReadAckWrite = 0;
+ CopyGuid(&Source->HandlerGuid, &DMC620_CPER_GUID[Index]);
+ Source++;
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "Dmc620RasDriverInitialize: DMC620 RAS memory allocation failed\n"));
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is the entry point for DMC620 RAS event handler
+
+ @param DispatchHandle The unique handle assigned to this handler by MmiHandlerRegister().
+ @param Context Points to an optional handler context which was specified when the handler was registered.
+ @param CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-MM environment into an MM environment.
+ @param CommBufferSize The size of the CommBuffer.
+
+ @return Status Code
+
+**/
+EFI_STATUS
+EFIAPI
+Dmc620RasEventHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *Context, OPTIONAL
+ IN OUT VOID *CommBuffer, OPTIONAL
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ volatile DMC620_REGS_TYPE *DmcCtrl;
+ volatile DMC620_ERR_REGS_TYPE *DmcRasErrRegs;
+ ERR_RECORD_TABLE_TYPE ErrRecTypeIndex;
+ UINTN ErrRecSize;
+ UINTN ErrRecOffset;
+
+ ASSERT (Context == NULL);
+
+ Status = EFI_SUCCESS;
+ /* TODO: Support all DMC620_X */
+ DmcCtrl = DMC620_0;
+
+ DEBUG ((DEBUG_INFO, "DMC620 RAS: CommBuffer - 0x%x, CommBufferSize - 0x%x\n",
+ CommBuffer,
+ *CommBufferSize));
+
+ /* Check DMC controller status */
+ Status = Dmc620Status (DmcCtrl);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, "Dmc620RasHandler: Invalid DMC status\n"));
+ return Status;
+ }
+
+ /* Check DMC features */
+ Dmc620RasSupportCheck(DmcCtrl);
+
+ ErrRecSize = (UINTN)&DmcCtrl->Err2Fr - (UINTN)&DmcCtrl->Err1Fr;
+ // Checking for 0x8000000 is a work around for the FVP issue JIRA SDDKW-42565, remove when fixed
+ if (DmcCtrl->Errgsr || DmcCtrl->Err4Status == 0x8000000) {
+ for (ErrRecTypeIndex = DRAM_ECC_CORRECTED_FH; ErrRecTypeIndex < DMC_ERROR_RECOVERY; ErrRecTypeIndex++) {
+ ErrRecOffset = ((UINTN)ErrRecTypeIndex - 1) * ErrRecSize;
+ DmcRasErrRegs = (DMC620_ERR_REGS_TYPE *)((UINTN)&DmcCtrl->Err1Fr + ErrRecOffset);
+ Dmc620RasProcessError (DmcRasErrRegs, DmcCtrl, ErrRecTypeIndex);
+ }
+ }
+
+ return Status;
+}
diff --git a/Platform/ARM/Drivers/StandaloneMmDmc620RasDriver/StandaloneMmDmc620RasDriver.h b/Platform/ARM/Drivers/StandaloneMmDmc620RasDriver/StandaloneMmDmc620RasDriver.h
new file mode 100644
index 00000000..ab80fcd0
--- /dev/null
+++ b/Platform/ARM/Drivers/StandaloneMmDmc620RasDriver/StandaloneMmDmc620RasDriver.h
@@ -0,0 +1,686 @@
+/** @file
+*
+* Copyright (c) 2017-2018, ARM Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#ifndef _DMC620_RAS_DRIVER_H_
+#define _DMC620_RAS_DRIVER_H_
+
+#include <Base.h>
+#include <Guid/MpInformation.h>
+
+#include <Library/ArmSvcLib.h>
+#include <Library/ArmLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CperLib.h>
+#include <Library/DebugLib.h>
+
+#include <Pi/PiSmmCis.h>
+
+#include <Protocol/DebugSupport.h> // for EFI_SYSTEM_CONTEXT
+#include <Protocol/MmConfiguration.h>
+#include <Protocol/RasErrorSourceInfo.h>
+#include <Protocol/MmCpu.h>
+
+#include <Guid/Cper.h>
+#include <IndustryStandard/Acpi.h>
+
+/* DMC-620 base address */
+#define MEMORY_CONTROLLER_BASE 0x4E000000
+
+/* DMC-620 config commands and states */
+#define STATE_MASK 0x7
+#define CONFIG_STATE 0x0 /* Enter the CONFIG architectural state */
+#define LOW_POWER_STATE 0x1 /* Enter the LOW_POWER architectural state */
+#define PAUSED_STATE 0x2 /* Enter the PAUSED architectural state */
+#define READY_STATE 0x3 /* Enter the READY architectural state */
+#define EXECUTE 0x4 /* Performs any directCmd operations */
+#define EXECUTE_DRAIN 0x5 /* Performs any directCmd operations after first draining the controller*/
+#define ABORT_CLR 0x6 /* Enter the RECOVER architectural state */
+
+/* DNC-620 RAS features */
+#define ED_FE_ENABLED 0x2 /* Indicates if error detection is enabled */
+#define DE_FE_ENABLED 0x8 /* Indicates if errors on writes are deferred */
+#define UI_FE_ENABLED 0x20 /* Indicates if uncorrected error recovery interrupt is enabled */
+#define FI_FE_ENABLED 0x80 /* Indicates if fault handling interrupt is enabled */
+#define UE_FE_ENABLED 0x200 /* Indicates if uncorrected error reporting is enabled */
+#define CFI_FE_ENABLED 0x800 /* Indicates if corrected fault handling interrupt is enabled */
+
+/* DMC-620 RAS Control 0 */
+#define ED_ENABLE 0x1 /* ECC detection on reads */
+#define DE_ENABLE 0x2 /* Defer on reads */
+#define UI_ENABLE 0x4 /* Uncorrectable error recovery interrupt */
+#define FI_INT_ENABLE 0x8 /* ECC FHI Interrupt */
+#define CFI_INT_ENABLE 0x100 /* CFI interrupt */
+
+/* DMC-620 RAS Control 1 */
+#define ECC_PROTECTION_SECDED 0x1 /* ECC protection */
+#define ECC_PROTECTION_SYMBOL 0x2 /* ECC protection */
+#define WB_ENABLE 0x4 /* Program to enable or disable write-back of ECC corrected data */
+#define RETRY_ENABLE 0x8 /* Program to enable or disable retry of ECC uncorrectable data operations */
+#define RMW_ENABLE 0x10 /* Enable read-modify-write operations */
+#define WDE_ENABLE 0x20 /* Write Defer Enable */
+#define CPI_ENABLE 0x40 /* Ignore parity bits from CHI */
+#define CDI_ENABLE 0x80 /* Ignore poison or defer indication from CHI */
+
+#define ECC_NO 0x0 /* No DRAM ECC */
+#define ECC_SECDED 0x1 /* SECDED ECC */
+#define ECC_SYMBOL 0x2 /* Symbol ECC */
+
+#define DMC620_ACCESS_ADDRESS_COUNT 8
+
+/* DMC-620 RAS Status */
+#define ERR_STATUS_ECC_ERR_SRAM 0x6 /* Indicates the type of error SRAM or SDRAM */
+#define ERR_STATUS_ECC_ERR_SDRAM 0xC /* Indicates the type of error SRAM or SDRAM */
+#define ERR_STATUS_ECC_ERR_DBP 0xA /* DBP error passed in from chi interface */
+#define ERR_STATUS_IERR 0xFF00 /* Indicates which rank counter has overflowed */
+#define ERR_STATUS_UI_CT_UER 0x300000 /* Recoverable (uninfected containable) error */
+#define ERR_STATUS_PN 0x400000 /* Poison was detected */
+#define ERR_STATUS_DE 0x800000 /* An uncorrectable ECC error was detected and deferred */
+#define ERR_STATUS_CE_TRANSIENT 0x1000000 /* An non-overflowing error was detected and syndrome for the error has been captured */
+#define ERR_STATUS_CE_CORRECTED 0x2000000 /* Reserved */
+#define ERR_STATUS_CE_PERSISTENT 0x3000000 /* An error counter belonging to this record has overflowed asserting a CFH interrupt */
+#define ERR_STATUS_MV 0x4000000 /* Miscellaneous Registers Valid */
+#define ERR_STATUS_OF 0x8000000 /* This bit is directly tied to the errc counter(s) of this record */
+#define ERR_STATUS_V 0x40000000 /* This register is valid and at least one error has been recorded */
+#define ERR_STATUS_AV 0x80000000 /* Indicates that the ERRXADDR register for this record contains a physical address */
+
+#define ERR_STATUS_RANK_BIT 8 /* Error rank bit position */
+
+#define RAS_DMC620_ERROR_GHES_TYPE_V1 0x9 /* GHESv1 type identifier */
+#define RAS_DMC620_ERROR_GHES_TYPE_V2 0xA /* GHESv2 type identifier */
+#define RAS_DMC620_ERROR_SOURCE_TOTAL 2 /* Number of error sources supported by the driver */
+#define RAS_DMC620_ERROR_SOURCE_START_EVENT 804 /* First event number */
+#define RAS_DMC620_ERROR_CPER_RECORD_SIZE 0x1000 /* Size of CPER record associated with each error source */
+#define RAS_DMC620_ERROR_ADDRESS_SPACE 0x0 /* Type of address space: System memory address space */
+#define RAS_DMC620_ERROR_REGISTER_WIDTH_BIT 0x40 /* Size of access register */
+#define RAS_DMC620_ERROR_REGISTER_OFFSET_BIT 0x0 /* Bit offset of access register */
+#define RAS_DMC620_ERROR_ACCESS_SIZE 0x4 /* Address space access size */
+#define RAS_DMC620_ERROR_ACK_REGISTER_SIZE 0x8 /* Size of GHESv2 acknowledgment register */
+
+/* DMC-620 error injection */
+#define TST_MODE_ENABLE 0x1 /* Enable test mode */
+typedef enum {
+ SINGLE_BIT_INJECT = 0x2, /* Inject single-bit error */
+ DOUBLE_BIT_INJECT = 0x6 /* Inject double-bit error */
+} ERR_INJECT_TYPE;
+
+/* DMC Error Record Types */
+typedef enum {
+ DRAM_ECC_CORRECTED_FH = 0x1, /* DRAM ECC reporting through a CFH interrupt */
+ DRAM_ECC_FH = 0x2, /* DRAM ECC reporting through an FH interrupt */
+ CHI_FH = 0x3, /* CHI DBP reporting through an FH interrupt */
+ SRAM_ECC_CORRECTED_FH = 0x4, /* SRAM ECC reporting through a CFH interrupt */
+ SRAM_ECC_FH = 0x5, /* SRAM ECC reporting through an FH interrupt */
+ DMC_ERROR_RECOVERY = 0x6 /* DMC reporting through an ER interrupt */
+} ERR_RECORD_TABLE_TYPE;
+
+#pragma pack(1)
+
+/* Access address next registers */
+typedef struct DMC620_ADDRESS_NEXT {
+ UINT32 Min_31_00;
+ UINT32 Min_43_32;
+ UINT32 Max_31_00;
+ UINT32 Max_43_32;
+} DMC620_ADDRESS_NEXT_TYPE;
+
+/* Access address next registers */
+typedef struct DMC620_ADDRESS_NOW {
+ UINT32 Min_31_00;
+ UINT32 Min_43_32;
+ UINT32 Max_31_00;
+ UINT32 Max_43_32;
+} DMC620_ADDRESS_NOW_TYPE;
+
+/* PMU payload information operation register */
+typedef struct DMC620_PMC_COUNTER {
+ UINT32 Mask_31_00;
+ UINT32 Mask_63_32;
+ UINT32 Match_31_00;
+ UINT32 Match_63_32;
+ UINT32 Control;
+ UINT32 Reserved0;
+ UINT32 SnapshotValue_31_00;
+ UINT32 Reserved1;
+ UINT32 Value_31_00;
+ UINT32 Reserved2;
+} DMC620_PMC_COUNTER_TYPE;
+
+/* DMC-620 register definitions */
+typedef struct DMC620_REGS {
+ UINT32 MemcStatus; /* DMC status */
+ UINT32 MemcConfig; /* DMC configuration data */
+ UINT32 MemcCmd; /* Change the state of DMC, or execute queued manager operations */
+ UINT32 Reserved1; /* Reserved */
+ UINT32 AddressControlNext; /* Configures the DRAM address parameters */
+ UINT32 DecodeControlNext; /* Configures how the DRAM address is decoded from the system address */
+ UINT32 FormatControl; /* Configures the memory burst access parameters */
+ UINT32 AddressMapNext; /* Configures the system address mapping options */
+ UINT32 LowPowerControlNext; /* Configures the low-power features */
+ UINT32 Reserved2; /* Reserved */
+ UINT32 TurnaroundControlNext; /* Configures arbitration between read and write and rank to rank traffic on the DRAM bus */
+ UINT32 HitTurnaroundControlNext; /* Configures the settings for preventing starvation of non-hits in the presence of in-row hit streams */
+ UINT32 QosClassControlNext; /* Configures the priority class for each QoS encoding */
+ UINT32 EscalationControlNext; /* Configures the settings for escalating the priority of entries in the queue */
+ UINT32 QvControl_31_00_Next; /* Configures the priority settings for each QoS encoding */
+ UINT32 QvControl_63_32_Next; /* Configures the priority settings for each QoS encoding */
+ UINT32 RtControl_31_00_Next; /* Configures the timeout settings for each QoS encoding */
+ UINT32 RtControl_63_32_Next; /* Configures the timeout settings for each QoS encoding */
+ UINT32 TimeoutControlNext; /* Configures the prescaler applied to timeout values */
+ UINT32 CreditControlNext; /* Configures the settings for preventing starvation of CHI protocol retries */
+ UINT32 WritePriorityControl_31_00_Next; /* Configures the priority settings for write requests within the DMC */
+ UINT32 WritePriorityControl_63_32_Next; /* Configures the priority settings for write requests within the DMC */
+ UINT32 QueueThresholdControl_31_00_Next; /* Configures the threshold settings for requests in the DMC */
+ UINT32 QueueThresholdControl_63_32_Next; /* Configures the threshold settings for requests in the DMC */
+ UINT32 AddressShutter_31_00_Next; /* Configures the address shuttering due to channel striping in the interconnect*/
+ UINT32 AddressShutter_63_32_Next; /* Configures the address shuttering due to channel striping in the interconnect*/
+ UINT32 AddressShutter_95_64_Next; /* Configures the address shuttering due to channel striping in the interconnect*/
+ UINT32 AddressShutter_127_96_Next; /* Configures the address shuttering due to channel striping in the interconnect*/
+ UINT32 AddressShutter_159_128_Next; /* Configures the address shuttering due to channel striping in the interconnect*/
+ UINT32 AddressShutter_191_160_Next; /* Configures the address shuttering due to channel striping in the interconnect*/
+ UINT32 MemoryAddressMax_31_00_Next; /* Configures the address space control for the DMC default region */
+ UINT32 MemoryAddressMax_43_32_Next; /* Configures the address space control for the DMC default region */
+ DMC620_ADDRESS_NEXT_TYPE AccessAddressNext[DMC620_ACCESS_ADDRESS_COUNT]; /*!< Configures the address space control for address regions */
+ UINT32 ChannelStatus; /* Holds the current status of the memory channel */
+ UINT32 ChannelStatus_63_32; /* Holds the current status of the memory channel */
+ UINT32 DirectAddr; /* Sets the direct command address field for direct commands */
+ UINT32 DirectCmd; /* Generates direct commands from the manager */
+ UINT32 DciReplayTypeNext; /* Configures the behavior of the DMC if a DRAM or PHY error is received when executing a direct command */
+ UINT32 DirectControlNext; /* Represents the training configuration of the DMC executed by a direct command */
+ UINT32 DciStrb; /* Configures the write data strobe values used during direct_cmd WRITE operations */
+ UINT32 DciData; /* Read returns read data received a result of a READ command. Write sets the data to be used for direct_cmd WRITE commands */
+ UINT32 RefreshControlNext; /* Configures the type of refresh commands issued by the DMC */
+ UINT32 Reserved3; /* Reserved */
+ UINT32 MemoryTypeNext; /* Configures the attached memory type */
+ UINT32 Reserved4; /* Reserved */
+ UINT32 FeatureConfig; /* Control register for DMC features */
+ UINT32 Reserved5; /* Reserved */
+ UINT32 NibbleFailed_031_000; /* Inform the DMC that nibble has failed */
+ UINT32 NibbleFailed_063_032; /* Inform the DMC that nibble has failed */
+ UINT32 NibbleFailed_095_064; /* Inform the DMC that nibble has failed */
+ UINT32 NibbleFailed_127_096; /* Inform the DMC that nibble has failed */
+ UINT32 QueueAllocateControl_031_000; /* Inform the DMC that a queue (RAM) entry has failed, where 0 means failed and not included for allocation */
+ UINT32 QueueAllocateControl_063_032; /* Inform the DMC that a queue (RAM) entry has failed, where 0 means failed and not included for allocation */
+ UINT32 QueueAllocateControl_095_064; /* Inform the DMC that a queue (RAM) entry has failed, where 0 means failed and not included for allocation */
+ UINT32 QueueAllocateControl_127_096; /* Inform the DMC that a queue (RAM) entry has failed, where 0 means failed and not included for allocation */
+ UINT8 Reserved6[0x16c - 0x158]; /* Reserved */
+ UINT32 LinkErrCount; /* Counter register for link errors. The counter increments on detection of a new link error (dfi_alert_n or dfi_err) */
+ UINT32 ScrubControl0Next; /* Scrub engine channel control register */
+ UINT32 ScrubAddressMin0Next; /* Configures the address space control for the scrub engine channel */
+ UINT32 ScrubAddressMax0Next; /* Configures the address space control for the scrub engine channel */
+ UINT32 ScrubAddressCurrent0; /* Current the address space for the scrub engine channel */
+ UINT32 ScrubControl1Next; /* Scrub engine channel control register */
+ UINT32 ScrubAddressMin1Next; /* Configures the address space control for the scrub engine channel */
+ UINT32 ScrubAddressMax1Next; /* Configures the address space control for the scrub engine channel */
+ UINT32 ScrubAddressCurrent1; /* Current the address space for the scrub engine channel */
+ UINT8 Reserved7[0x1a0 - 0x190]; /* Reserved */
+ UINT32 CsRemapControl_31_00_Next; /* Control register for CS remap */
+ UINT32 CsRemapControl_63_32_Next; /* Control register for CS remap */
+ UINT32 CsRemapControl_95_64_Next; /* Control register for CS remap */
+ UINT32 CsRemapControl_127_96_Next; /* Control register for CS remap */
+ UINT32 CidRemapControl_31_00_Next; /* Control register for dfi_CID remap */
+ UINT32 CidRemapControl_63_32_Next; /* Control register for dfi_CID remap */
+ UINT8 Reserved8[0x1c0 - 0x1b8]; /* Reserved */
+ UINT32 CkeRemapControlNext; /* Control register for CKE remap */
+ UINT32 RstRemapControlNext; /* Control register for RST remap */
+ UINT32 CkRemapControlNext; /* Control register for CK remap */
+ UINT32 Reserved9; /* Reserved */
+ UINT32 PowerGroupControl_31_00_Next; /* Power Group Control register for power managing ranks together */
+ UINT32 PowerGroupControl_63_32_Next; /* Power Group Control register for power managing ranks together */
+ UINT32 PowerGroupControl_95_64_Next; /* Power Group Control register for power managing ranks together */
+ UINT32 PowerGroupControl_127_96_Next; /* Power Group Control register for power managing ranks together */
+ UINT32 PhyRdwrdataCsMask_31_00; /* Maps a logical rank to the physical rank phy_rd/wrdata_cs output pins */
+ UINT32 PhyRdwrdataCsMask_63_32; /* Maps a logical rank to the physical rank phy_rd/wrdata_cs output pins */
+ UINT32 PhyRequestCsRemap; /* Maps PHY traning request from a physical chip select to DMC internal logical chip select */
+ UINT32 Reserved10; /* Reserved */
+ UINT32 FeatureControlNext; /* Control register for DMC features */
+ UINT32 MuxControlNext; /* Control muxing options */
+ UINT32 RankRemapControlNext; /* Control register for rank remap */
+ UINT32 Reserved11; /* Reserved */
+ UINT32 TRefiNext; /* Configures the refresh interval timing parameter */
+ UINT32 TRfcNext; /* Configures the tRFC timing parameter */
+ UINT32 TMrrNext; /* Configures the tMRR timing parameter */
+ UINT32 TMrwNext; /* Configures the tMRW timing parameter */
+ UINT8 Reserved12[0x218 - 0x210]; /* Reserved */
+ UINT32 TRcdNext; /* Configures the tRCD timing parameter */
+ UINT32 TRasNext; /* Configures the tRAS timing parameter */
+ UINT32 TRpNext; /* Configures the tRP timing parameter */
+ UINT32 TRpallNext; /* Configures the tRPALL timing parameter */
+ UINT32 TRrdNext; /* Configures the tRRD timing parameter */
+ UINT32 TActWindowNext; /* Configures the tFAW and tMAWi timing parameter */
+ UINT32 Reserved13; /* Reserved */
+ UINT32 TRtrNext; /* Configures the read-to-read timing parameter */
+ UINT32 TRtwNext; /* Configures the read-to-write timing parameter */
+ UINT32 TRtpNext; /* Configures the read-to-precharge timing parameter */
+ UINT32 Reserved14; /* Reserved */
+ UINT32 TWrNext; /* Configures the tWR timing parameter */
+ UINT32 TWtrNext; /* Configures the write-to-read timing parameter */
+ UINT32 TWtwNext; /* Configures the write-to-write timing parameter */
+ UINT32 Reserved15; /* Reserved */
+ UINT32 TXmpdNext; /* Configures the command delay between exiting Maximum Power Down and a subsequent command to that rank */
+ UINT32 TEpNext; /* Configures the enter power-down timing parameter */
+ UINT32 TXpNext; /* Configures the exit power-down timing parameter for operations that do not require a DLL (tXP), and those that do (tXPDLL) */
+ UINT32 TEsrNext; /* Configures the enter self-refresh timing parameter */
+ UINT32 TXsrNext; /* Configures the exit self-refresh timing parameter */
+ UINT32 TEsrckNext; /* Configures the delay between entering self-refresh and disabling the DRAM clock */
+ UINT32 TCkxsrNext; /* Configures the delay between DRAM clock enable and exiting self-refresh */
+ UINT32 TCmdNext; /* Configures command signaling timing */
+ UINT32 TParityNext; /* Parity latencies t_parinlat and t_completion */
+ UINT32 TZqcsNext; /* Configures the delay to apply following a ZQC-Short calibration command */
+ UINT32 TRwOdtClrNext; /* Timing parameter applies extra guard-band between the last issued rd/wr command and potential ZQC, SREF, and MES commands */
+ UINT8 Reserved16[0x300 - 0x280]; /* Reserved */
+ UINT32 TRddataEnNext; /* Determines the time between a READ command commencing on the DFI interface, and the assertion of the dfi_read_en signal */
+ UINT32 TPhyrdlatNext; /* Determines the maximum possible time between the assertion of the dfi_read_en signal, and the assertion of the dfi_rddata_valid signal by the PHY */
+ UINT32 TPhywrlatNext; /* Determines the time between a WRITE command commencing on the DFI interface, and the assertion of the dfi_wrdata_en, dfi_wrdata_cs and dfi_wrdata signals */
+ UINT32 Reserved17; /* Reserved */
+ UINT32 RdlvlControlNext; /* Determines the DMC behavior during read training operations */
+ UINT32 RdlvlMrsNext; /* Determines the Mode Register command to use to place the DRAM into a training mode for read training */
+ UINT32 TRdlvlEnNext; /* Configures the t_rdlvl_en timing parameter */
+ UINT32 TRdlvlRrNext; /* Configures the t_rdlvl_rr timing parameter */
+ UINT32 WrlvlControlNext; /* Determines the DMC behavior during write training operations */
+ UINT32 WrlvlMrsNext; /* Determines the Mode Register command that the DMC must use to put the DRAM into a training mode for write levelling */
+ UINT32 TWrlvlEnNext; /* Configures the t_wrlvl_en timing parameter */
+ UINT32 TWrlvlWwNext; /* Configures the t_wrlvl_ww timing parameter */
+ UINT32 Reserved18; /* Reserved */
+ UINT32 TrainingWrlvlSliceStatus; /* Shows slice information relating to the wrlvl training request status of DMC */
+ UINT32 TrainingRdlvlSliceStatus; /* Shows slice information relating to the rdlvl training request status of DMC */
+ UINT32 TrainingRdlvlGateSliceStatus; /* Shows slice information relating to the rdlvl gate training request status of DMC */
+ UINT32 TrainingWdqlvlSliceStatus; /* Shows slice information relating to the WrDQ training request status of DMC */
+ UINT32 TrainingWdqlvlSliceResult; /* Shows per slice result from the PHY in response to the WrDQ training request to the DMC */
+ UINT32 PhyPowerControlNext; /* Configures the low-power requests made to the PHY for the different channel states */
+ UINT32 TLprespNext; /* Configures the minimum cycle delay to apply for PHY low-power handshakes */
+ UINT32 PhyUpdateControlNext; /* Configures the update mechanism to use in response to PHY training requests */
+ UINT32 TOdthNext; /* Configures the ODTH8 timing parameter */
+ UINT32 OdtTimingNext; /* Configures the ODT on and off timing */
+ UINT32 Reserved19; /* Reserved */
+ UINT32 OdtWrControl_31_00_Next; /* Configures the ODT on and off settings for active and inactive ranks during writes */
+ UINT32 OdtWrControl_63_32_Next; /* Configures the ODT on and off settings for active and inactive ranks during writes */
+ UINT32 OdtRdControl_31_00_Next; /* Configures the ODT on and off settings for active and inactive ranks during writes */
+ UINT32 OdtRdControl_63_32_Next; /* Configures the ODT on and off settings for active and inactive ranks during writes */
+ UINT32 TemperatureReadout; /* Holds the status of the temperature information */
+ UINT32 Reserved20; /* Reserved */
+ UINT32 TrainingStatus; /* Shows information relating to the update request status */
+ UINT32 TrainingStatus_63_32; /* Shows information relating to the update request status */
+ UINT32 DqMapControl_15_00_Next; /* Controls the DQ mapping compensation applied for CRC calculation */
+ UINT32 DqMapControl_31_16_Next; /* Controls the DQ mapping compensation applied for CRC calculation */
+ UINT32 DqMapControl_47_32_Next; /* Controls the DQ mapping compensation applied for CRC calculation */
+ UINT32 DqMapControl_63_48_Next; /* Controls the DQ mapping compensation applied for CRC calculation */
+ UINT32 DqMapControl_71_64_Next; /* Controls the DQ mapping compensation applied for CRC calculation */
+ UINT32 Reserved21; /* Reserved */
+ UINT32 RankStatus; /* Shows the current status of geardown, MPD and CAL */
+ UINT32 ModeChangeStatus; /* Shows the current status of the sequence that is currently being processed */
+ UINT8 Reserved22[0x3b0 - 0x3a0]; /* Reserved */
+ UINT32 OdtCpControl_31_00_Next; /* Determines which of the 8 dfi_odt[7:0] output signals are connected to a logically address rank */
+ UINT32 OdtCpControl_63_32_Next; /* Determines which of the 8 dfi_odt[7:0] output signals are driven during a write a DRAM */
+ UINT8 Reserved23[0x400 - 0x3b8]; /* Reserved */
+ UINT32 UserStatus; /* Shows the value of the input user_status signals */
+ UINT32 Reserved24; /* Reserved */
+ UINT32 UserConfig0Next; /* Drives the output user_config0 signal */
+ UINT32 UserConfig1Next; /* Drives the output user_config1 signal */
+ UINT32 UserConfig2; /* Drives the output user_config2 signal */
+ UINT32 UserConfig3; /* Drives the output user_config3 signal */
+ UINT8 Reserved25[0x500 - 0x418]; /* Reserved */
+ UINT32 InterruptControl; /* Configures interrupt behavior */
+ UINT32 Reserved26; /* Reserved */
+ UINT32 InterruptClr; /* Clear interrupts */
+ UINT32 Reserved27; /* Reserved */
+ UINT32 InterruptStatus; /* Status register for interrupts (pre-mask) */
+ UINT8 Reserved28[0x538 - 0x514]; /* Reserved */
+ UINT32 FailedAccessIntInfo_31_00; /* Shows information relating to the interrupt */
+ UINT32 FailedAccessIntInfo_63_32; /* Shows information relating to the interrupt */
+ UINT32 FailedProgIntInfo_31_00; /* Shows information relating to the interrupt */
+ UINT32 FailedProgIntInfo_63_32; /* Shows information relating to the interrupt */
+ UINT32 LinkErrIntInfo_31_00; /* Shows information relating to the interrupt */
+ UINT32 LinkErrIntInfo_63_32; /* Shows information relating to the interrupt */
+ UINT32 ArchFsmIntInfo_31_00; /* Shows information relating to the interrupt */
+ UINT32 ArchFsmIntInfo_63_32; /* Shows information relating to the interrupt */
+ UINT8 Reserved29[0x610 - 0x558]; /* Reserved */
+ UINT32 TDbTrainRespNext; /* Configures the t_db_train_resp timing parameter for DB-DRAM Training */
+ UINT32 TLvlDisconnectNext; /* Configures the t_lvl timing parameter for all DFI training interfaces */
+ UINT8 Reserved30[0x620 - 0x618]; /* Reserved */
+ UINT32 WdqlvlControlNext; /* Determines the DMC behavior during write-DQ training operations */
+ UINT32 WdqlvlVrefdqTrainMrsNext; /* Determines the Mode register command to use to place the DRAM into a VrefDQ training mode */
+ UINT32 WdqlvlAddress_31_00_Next; /* Programs the row and column address that is used in WrDQ training */
+ UINT32 WdqlvlAddress_63_32_Next; /* Programs the address that is used in WrDQ training */
+ UINT32 TWdqlvlEnNext; /* Configures the t_wdqlvl_en timing parameters */
+ UINT32 TWdqlvlWwNext; /* Configures the t_wdqlvl_ww timing parameters */
+ UINT32 TWdqlvlRwNext; /* Configures the t_wdqlvl_rw timing parameters */
+ UINT32 TrainingWdqlvlSliceResp; /* Shows per slice response from the PHY in response to the WrDQ training request to DMC */
+ UINT32 TrainingRdlvlSliceResp; /* Shows per slice response from the PHY in response to the rdlvl training request to DMC */
+ UINT8 Reserved31[0x654 - 0x644]; /* Reserved */
+ UINT32 PhymstrControlNext; /* Determines the DMC behavior during write training operations */
+ UINT8 Reserved32[0x700 - 0x658]; /* Reserved */
+ UINT32 Err0Fr; /* This record defines which are common to all RAS error records in this section */
+ UINT32 Reserved33; /* Reserved */
+ UINT32 Err0Ctlr0; /* This register is the global control regsiter for the DMC RAS functions */
+ UINT32 Err0Ctlr1; /* This register is the global control regsiter for the DMC RAS functions */
+ UINT32 Err0Status; /* This status register reports error type, status, and contains valid bits for extra syndrome registers */
+ UINT8 Reserved34[0x740 - 0x714]; /* Reserved */
+ UINT32 Err1Fr; /* Returns the same value programmed in the ERR0FR Global Control Record Feature Register */
+ UINT32 Reserved35; /* Reserved */
+ UINT32 Err1Ctlr; /* This register is reserved */
+ UINT32 Reserved36; /* Reserved */
+ UINT32 Err1Status; /* This status register reports error type, status, and contains valid bits for extra syndrome registers */
+ UINT32 Reserved37; /* Reserved */
+ UINT32 Err1Addr0; /* Contains the physical address LSB's associated with the error */
+ UINT32 Err1Addr1; /* Contains the physical address MSB's associated with the error */
+ UINT32 Err1Misc0; /* This register gives the Physical Rank, Row, and Column of the last error detected before an interrupt is asserted */
+ UINT32 Err1Misc1; /* This register gives the Physical Rank, Logical Rank, and failed nobble location the last error detected before an interrupt is asserted */
+ UINT32 Err1Misc2; /* DRAM correctable Error Counter Access restrictions */
+ UINT32 Err1Misc3; /* DRAM correctable Error Counter Access restrictions */
+ UINT32 Err1Misc4; /* DRAM correctable Error Counter Access restrictions */
+ UINT32 Err1Misc5; /* DRAM correctable Error Counter Access restrictions */
+ UINT8 Reserved38[0x780 - 0x778]; /* Reserved */
+ UINT32 Err2Fr; /* Returns the same value programmed in the ERR0FR Global Control Record Feature Register */
+ UINT32 Reserved39; /* Reserved */
+ UINT32 Err2Ctlr; /* This register is reserved */
+ UINT32 Reserved40; /* Reserved */
+ UINT32 Err2Status; /* This status register reports error type, status, and contains valid bits for extra syndrome registers */
+ UINT32 Reserved41; /* Reserved */
+ UINT32 Err2Addr0; /* Contains the physical address LSB's associated with the error */
+ UINT32 Err2Addr1; /* Contains the physical address MSB's associated with the error */
+ UINT32 Err2Misc0; /* This register gives the Physical Rank, Row, and Column of the last error detected before an interrupt is asserted */
+ UINT32 Err2Misc1; /* This register gives the bank and logical rank of the first error detected since the last clear */
+ UINT32 Err2Misc2; /* DRAM uncorrectable Error Counter Access restrictions */
+ UINT32 Err2Misc3; /* DRAM uncorrectable Error Counter Access restrictions */
+ UINT32 Err2Misc4; /* DRAM uncorrectable Error Counter Access restrictions */
+ UINT32 Err2Misc5; /* DRAM uncorrectable Error Counter Access restrictions */
+ UINT8 Reserved42[0x7c0 - 0x7b8]; /* Reserved */
+ UINT32 Err3Fr; /* Returns the same value programmed in the ERR0FR Global Control Record Feature Register */
+ UINT32 Reserved43; /* Reserved */
+ UINT32 Err3Ctlr; /* This register is reserved */
+ UINT32 Reserved44; /* Reserved */
+ UINT32 Err3Status; /* This status register reports error type, status, and contains valid bits for extra syndrome registers */
+ UINT32 Reserved45; /* Reserved */
+ UINT32 Err3Addr0; /* Contains the physical address LSB's associated with the error */
+ UINT32 Err3Addr1; /* Contains the physical address MSB's associated with the error */
+ UINT8 Reserved46[0x800 - 0x7e0]; /* Reserved */
+ UINT32 Err4Fr; /* Returns the same value programmed in the ERR0FR Global Control Record Feature Register */
+ UINT32 Reserved47; /* Reserved */
+ UINT32 Err4Ctlr; /* This register is reserved */
+ UINT32 Reserved48; /* Reserved */
+ UINT32 Err4Status; /* This status register reports error type, status, and contains valid bits for extra syndrome registers */
+ UINT32 Reserved49; /* Reserved */
+ UINT32 Err4Addr0; /* Contains the physical address LSB's associated with the error */
+ UINT32 Err4Addr1; /* Contains the physical address MSB's associated with the error */
+ UINT32 Err4Misc0; /* This register gives the Physical Rank, Row, and Column of the last error detected before an interrupt is asserted */
+ UINT32 Err4Misc1; /* This register gives the bank and logical rank of the first error detected since the last clear */
+ UINT32 Err4Misc2; /* RAM correctable Error Counter Access restrictions */
+ UINT8 Reserved50[0x840 - 0x82c]; /* Reserved */
+ UINT32 Err5Fr; /* Returns the same value programmed in the ERR0FR Global Control Record Feature Register */
+ UINT32 Reserved51; /* Reserved */
+ UINT32 Err5Ctlr; /* This register is reserved */
+ UINT32 Reserved52; /* Reserved */
+ UINT32 Err5Status; /* This status register reports error type, status, and contains valid bits for extra syndrome registers */
+ UINT32 Reserved53; /* Reserved */
+ UINT32 Err5Addr0; /* Contains the physical address LSB's associated with the error */
+ UINT32 Err5Addr1; /* Contains the physical address MSB's associated with the error */
+ UINT32 Err5Misc0; /* This register gives the bank and logical rank of the first error detected since the last clear */
+ UINT32 Err5Misc1; /* This register gives the bank and logical rank of the first error detected since the last clear */
+ UINT32 Err5Misc2; /* RAM correctable Error Counter Access restrictions */
+ UINT8 Reserved54[0x880 - 0x86c]; /* Reserved */
+ UINT32 Err6Fr; /* Returns the same value programmed in the ERR0FR Global Control Record Feature Register */
+ UINT32 Reserved55; /* Reserved */
+ UINT32 Err6Ctlr; /* This register is reserved */
+ UINT32 Reserved56; /* Reserved */
+ UINT32 Err6Status; /* This status register reports error type, status, and contains valid bits for extra syndrome registers */
+ UINT32 Reserved57; /* Reserved */
+ UINT32 Err6Addr0; /* Contains the physical address LSB's associated with the error */
+ UINT32 Err6Addr1; /* Contains the physical address MSB's associated with the error */
+ UINT32 Err6Misc0; /* This register gives the Physical Rank, Row, and Column of the first error detected since last cleared*/
+ UINT32 Err6Misc1; /* This register gives the bank and logical rank of the first error detected since the last clear */
+ UINT8 Reserved58[0x920 - 0x8a8]; /* Reserved */
+ UINT32 Errgsr; /* This register shows the status of all the DMC error records */
+ UINT8 Reserved59[0xa00 - 0x924]; /* Reserved */
+ UINT32 PmuSnapshotReq; /* Generates PMU snapshot request Access restrictions */
+ UINT32 PmuSnapshotAck; /* Indicates PMU snapshot acknowledge Access restrictions */
+ UINT32 PmuOverflowStatusClkdiv2; /* Indicates which clkdiv2 counters have overflowed Access restrictions */
+ UINT32 PmuOverflowStatusClk; /* Indicates which clk domain counters have overflowed Access restrictions */
+ DMC620_PMC_COUNTER_TYPE pmcClkdiv2Count[8];
+ DMC620_PMC_COUNTER_TYPE pmcClkCount[2];
+ UINT8 Reserved60[0xe00 - 0xba0]; /* Reserved */
+ UINT32 IntegCfg; /* Integration test register to enable integration test mode */
+ UINT32 Reserved61; /* Reserved */
+ UINT32 IntegOutputs; /* Drives the value of outputs when in integration test mode */
+ UINT8 Reserved62[0x1010 - 0xe0c]; /* Reserved */
+ UINT32 AddressControlNow; /* Configures the DRAM address parameters */
+ UINT32 DecodeControlNow; /* Configures how the DRAM address is decoded from the system address */
+ UINT32 Reserved63; /* Reserved */
+ UINT32 AddressMapNow; /* Configures the system address mapping options */
+ UINT32 LowPowerControlNow; /* Configures the low-power features */
+ UINT32 Reserved64; /* Reserved */
+ UINT32 TurnaroundControlNow; /* Configures the settings for arbitration between read and write and rank to rank traffic on the DRAM bus */
+ UINT32 HitTurnaroundControlNow; /* Configures the settings for preventing starvation of non-hits in the presence of in-row hit streams */
+ UINT32 QosClassControlNow; /* Configures the priority class for each QoS encoding */
+ UINT32 EscalationControlNow; /* Configures the settings for escalating the priority of entries in the queu */
+ UINT32 QvControl_31_00_Now; /* Configures the priority settings for each QoS encoding */
+ UINT32 QvControl_63_32_Now; /* Configures the priority settings for each QoS encoding */
+ UINT32 RtControl_31_00_Now; /* Configures the timeout settings for each QoS encoding */
+ UINT32 RtControl_63_32_Now; /* Configures the timeout settings for each QoS encoding */
+ UINT32 TimeoutControlNow; /* Configures the prescaler applied to timeout values */
+ UINT32 CreditControlNow; /* Configures the settings for preventing starvation of CHI protocol retries */
+ UINT32 WritePriorityControl_31_00_Now; /* Configures the priority settings for write requests */
+ UINT32 WritePriorityControl_63_32_Now; /* Configures the priority settings for write requests */
+ UINT32 QueueThresholdControl_31_00_Now; /* Configures the threshold settings for requests in the DMC */
+ UINT32 QueueThresholdControl_63_32_Now; /* Configures the threshold settings for requests in the DMC */
+ UINT32 AddressShutter_31_00_Now; /* Configures the address shuttering due to channel striping in the interconnect*/
+ UINT32 AddressShutter_63_32_Now; /* Configures the address shuttering due to channel striping in the interconnect*/
+ UINT32 AddressShutter_95_64_Now; /* Configures the address shuttering due to channel striping in the interconnect*/
+ UINT32 AddressShutter_127_96_Now; /* Configures the address shuttering due to channel striping in the interconnect*/
+ UINT32 AddressShutter_159_128_Now; /* Configures the address shuttering due to channel striping in the interconnect*/
+ UINT32 AddressShutter_191_160_Now; /* Configures the address shuttering due to channel striping in the interconnect*/
+ UINT32 MemoryAddressMax_31_00_Now; /* Configures the address space control for the DMC default region */
+ UINT32 MemoryAddressMax_43_32_Now; /* Configures the address space control for the DMC default region */
+ DMC620_ADDRESS_NOW_TYPE AccessAddressNow[DMC620_ACCESS_ADDRESS_COUNT]; /*!< Configures the address space control for DMC regions */
+ UINT8 Reserved65[0x1110 - 0x1100]; /* Reserved */
+ UINT32 DciReplayTypeNow; /* Configures the behavior of the DMC if a DRAM or PHY error is received when executing a direct command */
+ UINT32 DirectControlNow; /* Represents the training configuration of the DMC executed by a direct command */
+ UINT8 Reserved66[0x1120 - 0x1118]; /* Reserved */
+ UINT32 RefreshControlNow; /* Configures the type of refresh commands issued by the DMC */
+ UINT32 Reserved67; /* Reserved */
+ UINT32 MemoryTypeNow; /* Configures the DMC for the attached memory type */
+ UINT8 Reserved68[0x1170 - 0x112c]; /* Reserved */
+ UINT32 ScrubControl0Now; /* Scrub engine channel control register */
+ UINT32 ScrubAddressMin0Now; /* Configures the address space control for the scrub engine channel */
+ UINT32 ScrubAddressMax0Now; /* Configures the address space control for the scrub engine channel */
+ UINT32 Reserved69; /* Reserved */
+ UINT32 ScrubControl1Now; /* Scrub engine channel control register */
+ UINT32 ScrubAddressMin1Now; /* Configures the address space control for the scrub engine channel */
+ UINT32 ScrubAddressMax1Now; /* Configures the address space control for the scrub engine channel */
+ UINT8 Reserved70[0x11a0 - 0x118c]; /* Reserved */
+ UINT32 CsRemapControl_31_00_Now; /* Control register for CS remap */
+ UINT32 CsRemapControl_63_32_Now; /* Control register for CS remap */
+ UINT32 CsRemapControl_95_64_Now; /* Control register for CS remap */
+ UINT32 CsRemapControl_127_96_Now; /* Control register for CS remap */
+ UINT32 CidRemapControl_31_00_Now; /* Control register for CID remap */
+ UINT32 CidRemapControl_63_32_Now; /* Control register for CID remap */
+ UINT8 Reserved71[0x11c0 - 0x11b8]; /* Reserved */
+ UINT32 CkeRemapControl_31_00_Now; /* Control register for CKE remap */
+ UINT32 RstRemapControl_31_00_Now; /* Control register for RST remap */
+ UINT32 CkRemapControl_31_00_Now; /* Control register for CK remap */
+ UINT32 PowerGroupControl_31_00_Now; /* Power Group Control register for power managing ranks together */
+ UINT32 PowerGroupControl_63_32_Now; /* Power Group Control register for power managing ranks together */
+ UINT32 PowerGroupControl_95_64_Now; /* Power Group Control register for power managing ranks together */
+ UINT32 PowerGroupControl_127_96_Now; /* Power Group Control register for power managing ranks together */
+ UINT8 Reserved72[0x11f0 - 0x11e0]; /* Reserved */
+ UINT32 FeatureControlNow; /* Control register for DMC features */
+ UINT32 MuxControlNow; /* Control muxing options for the DMC */
+ UINT32 RankRemapControlNow; /* Control register for rank remap */
+ UINT32 Reserved73; /* Reserved */
+ UINT32 TRefiNow; /* Configures the refresh interval timing parameter */
+ UINT32 TRfcNow; /* Configures the tRFC timing parameter */
+ UINT32 TMrrNow; /* Configures the tMRR timing parameter */
+ UINT32 TMrwNow; /* Configures the tMRW timing parameter */
+ UINT8 Reserved74[0x1218 - 0x1210]; /* Reserved */
+ UINT32 TRcdNow; /* Configures the tRCD timing parameter */
+ UINT32 TRasNow; /* Configures the tRAS timing parameter */
+ UINT32 TRpNow; /* Configures the tRP timing parameter */
+ UINT32 TRpallNow; /* Configures the tRPALL timing parameter */
+ UINT32 TRrdNow; /* Configures the tRRD timing parameter */
+ UINT32 TActWindowNow; /* Configures the tFAW and tMAWi timing parameter */
+ UINT32 Reserved75; /* Reserved */
+ UINT32 TRtrNow; /* Configures the read-to-read timing parameter */
+ UINT32 TRtwNow; /* Configures the read-to-write timing parameter */
+ UINT32 TRtpNow; /* Configures the read-to-precharge timing parameter */
+ UINT32 Reserved76; /* Reserved */
+ UINT32 TWrNow; /* Configures the tWR timing parameter */
+ UINT32 TWtrNow; /* Configures the tMRW timing parameter */
+ UINT32 TWtwNow; /* Configures the tMRW timing parameter */
+ UINT32 Reserved77; /* Reserved */
+ UINT32 TXmpdNow; /* Configures the command delay between exiting Maximum Power Down and a subsequent command to that rank */
+ UINT32 TEpNow; /* Configures the enter power-down timing parameter */
+ UINT32 TXpNow; /* Configures the exit power-down timing parameter */
+ UINT32 TEsrNow; /* Configures the enter self-refresh timing parameter */
+ UINT32 TXsrNow; /* Configures the exit self-refresh timing parameter */
+ UINT32 TEsrckNow; /* Configures the delay between entering self-refresh and disabling the DRAM clock */
+ UINT32 TCkxsrNow; /* CConfigures the delay between DRAM clock enable and exiting self-refresh */
+ UINT32 TCmdNow; /* Configures command signaling timing */
+ UINT32 TParityNow; /* Parity latencies t_parinlat and t_completion */
+ UINT32 TZqcsNow; /* Configures the delay to apply following a ZQC-Short calibration command */
+ UINT32 TRwOdtClrNow; /* Applies extra guard-band between the last issued rd/wr command and potential ZQC, SREF, and MRS comamnds */
+ UINT8 Reserved78[0x1300 - 0x1280]; /* Reserved */
+ UINT32 TRddataEnNow; /* Determines the time between a READ command commencing on the DFI interface, and the assertion of the dfi_read_en signal */
+ UINT32 TPhyrdlatNow; /* Determines the maximum possible time between the assertion of the dfi_read_en signal, and the assertion of the dfi_rddata_valid signal by the PHY */
+ UINT32 TPhywrlatNow; /* Determines the time between a WRITE command commencing on the DFI interface, and the assertion of the dfi_wrdata_en, dfi_wrdata_cs and dfi_wrdata signals */
+ UINT32 Reserved79; /* Reserved */
+ UINT32 RdlvlControlNow; /* Determines the DMC behavior during read training operations */
+ UINT32 RdlvlMrsNow; /* Determines the Mode Register command to use to place the DRAM into a training mode for read training */
+ UINT32 TRdlvlEnNow; /* Configures the t_rdlvl_en timing parameter */
+ UINT32 TRdlvlRrNow; /* Configures the t_rdlvl_rr timing parameter */
+ UINT32 WrlvlControlNow; /* Determines the DMC behavior during write training operations */
+ UINT32 WrlvlMrsNow; /* Determines the Mode Register command that the DMC must use to put the DRAM into a training mode for write levelling */
+ UINT32 TWrlvlEnNow; /* Configures the t_wrlvl_en timing parameter */
+ UINT32 TWrlvlWwNow; /* Configures the t_wrlvl_ww timing parameter */
+ UINT8 Reserved80[0x1348 - 0x1330]; /* Reserved */
+ UINT32 PhyPowerControlNow; /* Configures the low-power requests made to the PHY for the different channel states */
+ UINT32 TLprespNow; /* Configures the minimum cycle delay to apply for PHY low-power handshakes */
+ UINT32 PhyUpdateControlNow; /* Configures the update mechanism to use in response to PHY training requests */
+ UINT32 TOdthNow; /* Configures the ODTH8 timing parameter as timed from Write command registered with ODT high Access restrictions */
+ UINT32 OdtTimingNow; /* Configures the ODT on and off timing */
+ UINT32 Reserved81; /* Reserved */
+ UINT32 OdtWrControl_31_00_Now; /* Configures the ODT on and off settings for active and inactive ranks during writes */
+ UINT32 OdtWrControl_63_32_Now; /* Configures the ODT on and off settings for active and inactive ranks during writes */
+ UINT32 OdtRdControl_31_00_Now; /* Configures the ODT on and off settings for active and inactive ranks during reads */
+ UINT32 OdtRdControl_63_32_Now; /* Configures the ODT on and off settings for active and inactive ranks during reads */
+ UINT8 Reserved82[0x1380 - 0x1370]; /* Reserved */
+ UINT32 DqMapControl_15_00_Now; /* Controls the DQ mapping compensation applied for CRC calculation */
+ UINT32 DqMapControl_31_16_8_Now; /* Controls the DQ mapping compensation applied for CRC calculation */
+ UINT32 DqMapControl_47_32_Now; /* Controls the DQ mapping compensation applied for CRC calculation */
+ UINT32 DqMapControl_63_48_Now; /* Controls the DQ mapping compensation applied for CRC calculation */
+ UINT32 DqMapControl_71_64_Now; /* Controls the DQ mapping compensation applied for CRC calculation */
+ UINT8 Reserved83[0x13b0 - 0x1394]; /* Reserved */
+ UINT32 OdtCpControl_31_00_Now; /* Determines which of the 8 dfi_odt[7:0] output signals are connected to a logically address rank */
+ UINT32 OdtCpControl_63_32_Now; /* Determines which of the 8 dfi_odt[7:0] output signals are driven during a write a DRAM */
+ UINT8 Reserved84[0x1408 - 0x13b8]; /* Reserved */
+ UINT32 UserConfig0Now; /* Drives the output user_config0 signal */
+ UINT32 UserConfig1Now; /* Drives the output user_config1 signal */
+ UINT8 Reserved85[0x1610 - 0x1410]; /* Reserved */
+ UINT32 TDbTrainRespNow; /* Configures the t_db_train_resp timing parameter for DB-DRAM Training */
+ UINT32 TLvlDisconnectNow; /* Configures the t_lvl timing parameter for all DFI training interfaces */
+ UINT8 Reserved86[0x1620 - 0x1618]; /* Reserved */
+ UINT32 WdqlvlControlNow; /* Determines the DMC behavior during write-DQ training operations */
+ UINT32 WdqlvlVrefdqTrainMrsNow; /* Determines the Mode register command to use to place the DRAM into a VrefDQ training mode */
+ UINT32 WdqlvlAddress_31_00_Now; /* Programs the row and column address that is used in WrDQ training */
+ UINT32 WdqlvlAddress_63_32_Now; /* Programs the address that is used in WrDQ training */
+ UINT32 TWdqlvlEnNow; /* Configures the t_wdqlvl_en timing parameters */
+ UINT32 TWdqlvlWwNow; /* Configures the t_wdqlvl_ww timing parameters */
+ UINT32 TWdqlvlRwNow; /* Configures the t_wdqlvl_rw timing parameters */
+ UINT8 Reserved87[0x1654 - 0x163c]; /* Reserved */
+ UINT32 PhymstrControlNow; /* Determines the DMC behavior during write training operations */
+ UINT8 Reserved88[0x1fd0 - 0x1658]; /* Reserved */
+ UINT32 PeriphId4; /* Peripheral ID register */
+ UINT8 Reserved89[0x1fe0 - 0x1fd4]; /* Reserved */
+ UINT32 PeriphId0; /* Peripheral ID register */
+ UINT32 PeriphId1; /* Peripheral ID register */
+ UINT32 PeriphId2; /* Peripheral ID register */
+ UINT32 PeriphId3; /* Peripheral ID register */
+ UINT32 ComponentId0; /* Component ID register */
+ UINT32 ComponentId1; /* Component ID register */
+ UINT32 ComponentId2; /* Component ID register */
+ UINT32 ComponentId3; /* Component ID register */
+} DMC620_REGS_TYPE;
+
+/* DMC-620 register definitions */
+typedef struct DMC620_ERR_REGS {
+ UINT32 ErrFr; /* Returns the same value programmed in the ERR0FR Global Control Record Feature Register */
+ UINT32 Reserved; /* Reserved */
+ UINT32 ErrCtlr; /* This register is reserved */
+ UINT32 Reserve1; /* Reserved */
+ UINT32 ErrStatus; /* This status register reports error type, status, and contains valid bits for extra syndrome registers */
+ UINT32 Reserved2; /* Reserved */
+ UINT32 ErrAddr0; /* Contains the physical address LSB's associated with the error */
+ UINT32 ErrAddr1; /* Contains the physical address MSB's associated with the error */
+ UINT32 ErrMisc0; /* This register gives the Physical Rank, Row, and Column of the last error detected before an interrupt is asserted */
+ UINT32 ErrMisc1; /* This register gives the Physical Rank, Logical Rank, and failed nobble location the last error detected before an interrupt is asserted */
+ UINT32 ErrMisc2; /* DRAM correctable Error Counter Access restrictions */
+ UINT32 ErrMisc3; /* DRAM correctable Error Counter Access restrictions */
+ UINT32 ErrMisc4; /* DRAM correctable Error Counter Access restrictions */
+ UINT32 ErrMisc5; /* DRAM correctable Error Counter Access restrictions */
+ UINT8 Reserved3[0x780 - 0x778]; /* Reserved */
+} DMC620_ERR_REGS_TYPE;
+
+#define DMC620_0 ((DMC620_REGS_TYPE *)(MEMORY_CONTROLLER_BASE + 0x00000000))
+#define DMC620_1 ((DMC620_REGS_TYPE *)(MEMORY_CONTROLLER_BASE + 0x00100000))
+#define DMC620_2 ((DMC620_REGS_TYPE *)(MEMORY_CONTROLLER_BASE + 0x00200000))
+#define DMC620_3 ((DMC620_REGS_TYPE *)(MEMORY_CONTROLLER_BASE + 0x00300000))
+
+EFI_STATUS
+Dmc620RasInitialize (
+ IN EFI_HANDLE mageHandle,
+ IN EFI_SMM_SYSTEM_TABLE2 *SystemTable
+ );
+
+EFI_STATUS
+EFIAPI
+Dmc620RasEventHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *Context, OPTIONAL
+ IN OUT VOID *CommBuffer, OPTIONAL
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+Dmc620ErrorInjectEventHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *Context, OPTIONAL
+ IN OUT VOID *CommBuffer, OPTIONAL
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ );
+
+EFI_STATUS
+Dmc620RasSetCorrectableErrorThreshold (
+ IN volatile DMC620_ERR_REGS_TYPE *DmcRegs,
+ IN ERR_RECORD_TABLE_TYPE ErrRecType,
+ IN UINT32 ErrThreshold
+ );
+
+EFI_STATUS
+Dmc620Status (
+ IN volatile DMC620_REGS_TYPE *DmcCtrl
+ );
+
+VOID
+Dmc620DrainCmd (
+ IN volatile DMC620_REGS_TYPE *DmcCtrl
+ );
+
+EFI_STATUS
+EFIAPI
+Dmc620ErrorSourceInfoGet (
+ IN EFI_MM_RAS_ERROR_SOURCE_INFO_PROTOCOL *This,
+ OUT EFI_APEI_ERROR_SOURCE **Buffer,
+ OUT UINTN *ErrorSourceCount
+ );
+
+#endif /* _DMC620_RAS_DRIVER_H_ */
diff --git a/Platform/ARM/Drivers/StandaloneMmDmc620RasDriver/StandaloneMmDmc620RasDriver.inf b/Platform/ARM/Drivers/StandaloneMmDmc620RasDriver/StandaloneMmDmc620RasDriver.inf
new file mode 100644
index 00000000..0e2bf396
--- /dev/null
+++ b/Platform/ARM/Drivers/StandaloneMmDmc620RasDriver/StandaloneMmDmc620RasDriver.inf
@@ -0,0 +1,59 @@
+#/** @file
+#
+# Copyright (c) 2017-2018, ARM Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = StandaloneMmDmc620RasDriver
+ FILE_GUID = CB53ACD9-A1A1-43B3-A638-AC74DA5D9DA2
+ MODULE_TYPE = MM_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ ENTRY_POINT = Dmc620RasDriverInitialize
+
+[Sources]
+ StandaloneMmDmc620RasDriver.c
+ StandaloneMmDmc620ErrorInjection.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ edk2-platforms/Platform/ARM/ARM.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ StandaloneMmPkg/StandaloneMmPkg.dec
+
+[LibraryClasses]
+ StandaloneMmDriverEntryPoint
+ DebugLib
+ ArmSvcLib
+ ArmLib
+ BaseMemoryLib
+ CperLib
+
+[Protocols]
+ gEfiMmRasErrorSourceInfoProtocolGuid
+
+[Pcd]
+ gStandaloneMmPkgTokenSpaceGuid.PcdDmcCorrectableErrorThreshold
+
+[FixedPcd]
+ gStandaloneMmPkgTokenSpaceGuid.PcdCperBufferBase
+ gStandaloneMmPkgTokenSpaceGuid.PcdCperBufferSize
+
+[Guids]
+ gEfiMmDmcRasEventGuid
+ gEfiMmDmcErrorInjectEventGuid
+
+[Depex]
+ TRUE
+