From a414510d6a007cbac6f36c5f4efbbdddf8c8befa Mon Sep 17 00:00:00 2001 From: Jyotheeswar Reddy Date: Thu, 6 Aug 2015 11:02:25 -0700 Subject: [PATCH] PMUFW: EM: Add new error management framework A framework to enable handling of HW errors reported via ERROR_1 and ERROR_2 registers in PMU GLOBAL space is provided. User can choose to register an action for an error by using the provided API. An API is provided to enable Error reporting via PSERR pin. Signed-off-by: Jyotheeswar Reddy --- .../zynqmp_pmufw/src/xpfw_error_manager.c | 317 ++++++++++++++++++ .../zynqmp_pmufw/src/xpfw_error_manager.h | 123 +++++++ lib/sw_apps/zynqmp_pmufw/src/xpfw_version.h | 2 +- 3 files changed, 441 insertions(+), 1 deletion(-) create mode 100644 lib/sw_apps/zynqmp_pmufw/src/xpfw_error_manager.c create mode 100644 lib/sw_apps/zynqmp_pmufw/src/xpfw_error_manager.h diff --git a/lib/sw_apps/zynqmp_pmufw/src/xpfw_error_manager.c b/lib/sw_apps/zynqmp_pmufw/src/xpfw_error_manager.c new file mode 100644 index 00000000..09c0b32c --- /dev/null +++ b/lib/sw_apps/zynqmp_pmufw/src/xpfw_error_manager.c @@ -0,0 +1,317 @@ +/****************************************************************************** +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +******************************************************************************/ +#include "xpfw_error_manager.h" + +/* Data Structure to hold Error Info */ +struct XPfw_Error_t { + const u32 RegMask; + XPfw_ErrorHandler_t Handler; + const u8 Type; + u8 Action; +}; + + +static struct XPfw_Error_t ErrorTable[] = { + [EM_ERR_ID_INVALID] = {.Type = (u8)0U, .RegMask = MASK32_ALL_LOW, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_CSU_ROM] = { .Type = EM_ERR_TYPE_2, .RegMask = PMU_GLOBAL_ERROR_STATUS_2_CSU_ROM_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_PMU_PB] = { .Type = EM_ERR_TYPE_2, .RegMask = PMU_GLOBAL_ERROR_STATUS_2_PMU_PB_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_PMU_SERVICE] = { .Type = EM_ERR_TYPE_2, .RegMask = PMU_GLOBAL_ERROR_STATUS_2_PMU_SERVICE_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_PMU_FW] = { .Type = EM_ERR_TYPE_2, .RegMask = PMU_GLOBAL_ERROR_STATUS_2_PMU_FW_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_PMU_UC] = { .Type = EM_ERR_TYPE_2, .RegMask = PMU_GLOBAL_ERROR_STATUS_2_PMU_UC_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_CSU] = { .Type = EM_ERR_TYPE_2, .RegMask = PMU_GLOBAL_ERROR_STATUS_2_CSU_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_PLL_LOCK] = { .Type = EM_ERR_TYPE_2, .RegMask = PMU_GLOBAL_ERROR_STATUS_2_PLL_LOCK_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_PL] = { .Type = EM_ERR_TYPE_2, .RegMask = PMU_GLOBAL_ERROR_STATUS_2_PL_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_TO] = { .Type = EM_ERR_TYPE_2, .RegMask = PMU_GLOBAL_ERROR_STATUS_2_TO_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_AUX3] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_AUX3_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_AUX2] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_AUX2_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_AUX1] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_AUX1_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_AUX0] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_AUX0_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_DFT] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_DFT_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_CLK_MON] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_CLK_MON_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_XMPU] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_XMPU_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_PWR_SUPPLY] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_PWR_SUPPLY_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_FPD_SWDT] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_FPD_SWDT_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_LPD_SWDT] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_LPD_SWDT_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_RPU_CCF] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_RPU_CCF_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_RPU_LS] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_RPU_LS_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_FPD_TEMP] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_FPD_TEMP_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_LPD_TEMP] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_LPD_TEMP_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_RPU1] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_RPU1_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_RPU0] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_RPU0_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_OCM_ECC] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_OCM_ECC_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, + [EM_ERR_ID_DDR_ECC] = { .Type = EM_ERR_TYPE_1, .RegMask = PMU_GLOBAL_ERROR_STATUS_1_DDR_ECC_MASK, .Action = EM_ACTION_NONE, .Handler = NULL}, +}; + +static s32 XPfw_EmDisable(u8 ErrorId) +{ + s32 Status; + if (!((ErrorId > EM_ERR_ID_INVALID) && (ErrorId < EM_ERR_ID_MAX))) { + /* Invalid Error ID */ + Status = XST_FAILURE; + goto Done; + } + + /* Set the Handler to NULL */ + ErrorTable[ErrorId].Handler = NULL; + + switch (ErrorTable[ErrorId].Type) { + case EM_ERR_TYPE_1: + /* Disable POR, SRST and Interrupt */ + XPfw_Write32(PMU_GLOBAL_ERROR_POR_DIS_1, ErrorTable[ErrorId].RegMask); + XPfw_Write32(PMU_GLOBAL_ERROR_SRST_DIS_1, ErrorTable[ErrorId].RegMask); + XPfw_Write32(PMU_GLOBAL_ERROR_INT_DIS_1, ErrorTable[ErrorId].RegMask); + Status = XST_SUCCESS; + break; + case EM_ERR_TYPE_2: + /* Disable POR, SRST and Interrupt */ + XPfw_Write32(PMU_GLOBAL_ERROR_POR_DIS_2, ErrorTable[ErrorId].RegMask); + XPfw_Write32(PMU_GLOBAL_ERROR_SRST_DIS_2, ErrorTable[ErrorId].RegMask); + XPfw_Write32(PMU_GLOBAL_ERROR_INT_DIS_2, ErrorTable[ErrorId].RegMask); + Status = XST_SUCCESS; + break; + default: + /* Invalid Error Type */ + Status = XST_FAILURE; + } + +Done: + return Status; +} + +static s32 XPfw_EmEnablePOR(u8 ErrorId) +{ + s32 Status; + if (!((ErrorId > EM_ERR_ID_INVALID) && (ErrorId < EM_ERR_ID_MAX))) { + Status = XST_FAILURE; + goto Done; + } + switch (ErrorTable[ErrorId].Type) { + case EM_ERR_TYPE_1: + XPfw_Write32(PMU_GLOBAL_ERROR_POR_EN_1, ErrorTable[ErrorId].RegMask); + Status = XST_SUCCESS; + break; + case EM_ERR_TYPE_2: + XPfw_Write32(PMU_GLOBAL_ERROR_POR_EN_2, ErrorTable[ErrorId].RegMask); + Status = XST_SUCCESS; + break; + default: + Status = XST_FAILURE; + + } + +Done: + return Status; +} + +static s32 XPfw_EmEnableSRST(u8 ErrorId) +{ + s32 Status; + if (!((ErrorId > EM_ERR_ID_INVALID) && (ErrorId < EM_ERR_ID_MAX))) { + Status = XST_FAILURE; + goto Done; + } + switch (ErrorTable[ErrorId].Type) { + case EM_ERR_TYPE_1: + XPfw_Write32(PMU_GLOBAL_ERROR_SRST_EN_1, ErrorTable[ErrorId].RegMask); + Status = XST_SUCCESS; + break; + case EM_ERR_TYPE_2: + XPfw_Write32(PMU_GLOBAL_ERROR_SRST_EN_2, ErrorTable[ErrorId].RegMask); + Status = XST_SUCCESS; + break; + default: + Status = XST_FAILURE; + } + +Done: + return Status; +} + +static s32 XPfw_EmEnableInt(u8 ErrorId) +{ + s32 Status; + if (!((ErrorId > EM_ERR_ID_INVALID) && (ErrorId < EM_ERR_ID_MAX))) { + /* Invalid Error Id */ + Status = XST_FAILURE; + goto Done; + } + switch (ErrorTable[ErrorId].Type) { + case EM_ERR_TYPE_1: + XPfw_Write32(PMU_GLOBAL_ERROR_INT_EN_1, ErrorTable[ErrorId].RegMask); + Status = XST_SUCCESS; + break; + case EM_ERR_TYPE_2: + XPfw_Write32(PMU_GLOBAL_ERROR_INT_EN_2, ErrorTable[ErrorId].RegMask); + Status = XST_SUCCESS; + break; + default: + /* Invalid Err Type */ + Status = XST_FAILURE; + } + +Done: + return Status; +} + +void XPfw_EmInit(void) +{ + u8 ErrorId; + /* Disable all the Error Actions */ + for (ErrorId = 1U; ErrorId < EM_ERR_ID_MAX; ErrorId++) { + XPfw_EmDisable(ErrorId); + } + + /* Enable all error signals in HW */ + XPfw_Write32(PMU_GLOBAL_ERROR_EN_1, MASK32_ALL_HIGH); + XPfw_Write32(PMU_GLOBAL_ERROR_EN_2, MASK32_ALL_HIGH); + +} + +s32 XPfw_EmSetAction(u8 ErrorId, u8 ActionId, + XPfw_ErrorHandler_t ErrorHandler) +{ + s32 Status; + /* Check for Valid Error ID */ + if (!((ErrorId > EM_ERR_ID_INVALID) && (ErrorId < EM_ERR_ID_MAX))) { + /* Invalid Error Id */ + Status = XST_FAILURE; + goto Done; + } + + switch (ActionId) { + + case EM_ACTION_POR: + XPfw_EmDisable(ErrorId); + ErrorTable[ErrorId].Action = ActionId; + Status = XPfw_EmEnablePOR(ErrorId); + break; + + case EM_ACTION_SRST: + XPfw_EmDisable(ErrorId); + ErrorTable[ErrorId].Action = ActionId; + Status = XPfw_EmEnableSRST(ErrorId); + break; + + case EM_ACTION_CUSTOM: + if (ErrorHandler != NULL) { + XPfw_EmDisable(ErrorId); + ErrorTable[ErrorId].Action = ActionId; + ErrorTable[ErrorId].Handler = ErrorHandler; + Status = XPfw_EmEnableInt(ErrorId); + } else { + /* Null handler */ + Status = XST_FAILURE; + } + break; + + default: + /* Invalid Action Id */ + Status = XST_FAILURE; + + } + +Done: + return Status; +} + +s32 XPfw_EmProcessError(u8 ErrorType) +{ + s32 Status; + u32 ErrRegVal; + u8 Index; + u32 RegAddress; + + switch (ErrorType) { + case EM_ERR_TYPE_1: + RegAddress = PMU_GLOBAL_ERROR_STATUS_1; + ErrRegVal = XPfw_Read32(RegAddress); + Status = XST_SUCCESS; + break; + + case EM_ERR_TYPE_2: + RegAddress = PMU_GLOBAL_ERROR_STATUS_2; + ErrRegVal = XPfw_Read32(RegAddress); + Status = XST_SUCCESS; + break; + + default: + Status = XST_FAILURE; + } + + /* Proceed only if ErrorType is Valid */ + if (Status != XST_SUCCESS) { + goto Done; + } + for (Index = 1U; Index < EM_ERR_ID_MAX; Index++) { + if (ErrorTable[Index].Type == ErrorType) { + /* check if this error is triggered */ + if ((ErrRegVal & ErrorTable[Index].RegMask) != 0U) { + if ((ErrorTable[Index].Handler != NULL) + && (ErrorTable[Index].Action == EM_ACTION_CUSTOM)) { + /* Call the Error Handler */ + ErrorTable[Index].Handler(Index); + } + } + + } + } + /* Ack the Processed Error */ + XPfw_Write32(RegAddress, ErrRegVal); + +Done: + return Status; +} + +s32 XPfw_EmEnablePSError(u8 ErrorId) +{ + s32 Status; + /* If Error ID is not in range, fail*/ + if (!((ErrorId > EM_ERR_ID_INVALID) && (ErrorId < EM_ERR_ID_MAX))) { + Status = XST_FAILURE; + goto Done; + } + + /* Enable the specified Error to propagate to PSERR pin */ + switch (ErrorTable[ErrorId].Type) { + case EM_ERR_TYPE_1: + XPfw_Write32(PMU_GLOBAL_ERROR_SIG_EN_1, ErrorTable[ErrorId].RegMask); + Status = XST_SUCCESS; + break; + case EM_ERR_TYPE_2: + XPfw_Write32(PMU_GLOBAL_ERROR_SIG_EN_2, ErrorTable[ErrorId].RegMask); + Status = XST_SUCCESS; + break; + default: + Status = XST_FAILURE; + } + +Done: + return Status; +} diff --git a/lib/sw_apps/zynqmp_pmufw/src/xpfw_error_manager.h b/lib/sw_apps/zynqmp_pmufw/src/xpfw_error_manager.h new file mode 100644 index 00000000..742a1d3e --- /dev/null +++ b/lib/sw_apps/zynqmp_pmufw/src/xpfw_error_manager.h @@ -0,0 +1,123 @@ +/****************************************************************************** +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +******************************************************************************/ + +#ifndef XPFW_ERROR_MANAGER_H_ +#define XPFW_ERROR_MANAGER_H_ + +#include "xpfw_default.h" + +/* Error IDs to identify each Error */ +#define EM_ERR_ID_INVALID 0U + +#define EM_ERR_ID_CSU_ROM 1U +#define EM_ERR_ID_PMU_PB 2U +#define EM_ERR_ID_PMU_SERVICE 3U +#define EM_ERR_ID_PMU_FW 4U +#define EM_ERR_ID_PMU_UC 5U +#define EM_ERR_ID_CSU 6U +#define EM_ERR_ID_PLL_LOCK 7U +#define EM_ERR_ID_PL 8U +#define EM_ERR_ID_TO 9U +#define EM_ERR_ID_AUX3 10U +#define EM_ERR_ID_AUX2 11U +#define EM_ERR_ID_AUX1 12U +#define EM_ERR_ID_AUX0 13U +#define EM_ERR_ID_DFT 14U +#define EM_ERR_ID_CLK_MON 15U +#define EM_ERR_ID_XMPU 16U +#define EM_ERR_ID_PWR_SUPPLY 17U +#define EM_ERR_ID_FPD_SWDT 18U +#define EM_ERR_ID_LPD_SWDT 19U +#define EM_ERR_ID_RPU_CCF 20U +#define EM_ERR_ID_RPU_LS 21U +#define EM_ERR_ID_FPD_TEMP 22U +#define EM_ERR_ID_LPD_TEMP 23U +#define EM_ERR_ID_RPU1 24U +#define EM_ERR_ID_RPU0 25U +#define EM_ERR_ID_OCM_ECC 26U +#define EM_ERR_ID_DDR_ECC 27U + +#define EM_ERR_ID_MAX 28U + + + +/* Error Type identifies the HW register */ +#define EM_ERR_TYPE_1 1U +#define EM_ERR_TYPE_2 2U + + +/* Action to be taken when an error occurs */ +#define EM_ACTION_NONE 0U +#define EM_ACTION_POR 1U +#define EM_ACTION_SRST 2U +#define EM_ACTION_CUSTOM 3U +#define EM_ACTION_MAX 4U + + +/* Pointer to Error Handler Function */ +typedef void (*XPfw_ErrorHandler_t) (u8 ErrorId); + +/** + * Init the Error Management Framework + * All error signals in HW are enabled and Actions are disabled + */ +void XPfw_EmInit(void); + +/** + * Set action to be taken when a specific error occurs + * + * @param ErrorId is the ID for error as defined in this file + * @param ActionId is one of the actions defined in this file + * @param ErrorHandler is the handler to be called in case of custom action + * + * @return XST_SUCCESS if the action was successfully registered + * XST_FAILURE if the registration fails + */ +s32 XPfw_EmSetAction(u8 ErrorId, u8 ActionId, XPfw_ErrorHandler_t ErrorHandler); + +/** + * Process the errors of specified type and call the handlers of triggered errors + * + * @param ErrorType is either TYPE_1 or TYPE_2 as defined in this file + * + * @return XST_SUCCESS if the error was handled successfully + * XST_FAILURE in case of failure + */ +s32 XPfw_EmProcessError(u8 ErrorType); + +/** + * Enable Report out of error via PSERR pin + * + * @param ErrorId is the ID for error to be reported out + * + */ +s32 XPfw_EmEnablePSError(u8 ErrorId); + +#endif /* XPFW_ERROR_MANAGER_H_ */ diff --git a/lib/sw_apps/zynqmp_pmufw/src/xpfw_version.h b/lib/sw_apps/zynqmp_pmufw/src/xpfw_version.h index 99fb6825..36a9dcd3 100644 --- a/lib/sw_apps/zynqmp_pmufw/src/xpfw_version.h +++ b/lib/sw_apps/zynqmp_pmufw/src/xpfw_version.h @@ -1,4 +1,4 @@ #ifndef ZYNQMP_XPFW_VERSION__H_ #define ZYNQMP_XPFW_VERSION__H_ - #define ZYNQMP_XPFW_VERSION "2015.3-rc1-12-gef6c4fa7956e" + #define ZYNQMP_XPFW_VERSION "2015.3-rc1-13-g4ae8a5e895b2" #endif