diff --git a/lib/sw_apps/zynqmp_pmufw/src/pm_binding.c b/lib/sw_apps/zynqmp_pmufw/src/pm_binding.c index 5597e65c..e92b0dc7 100644 --- a/lib/sw_apps/zynqmp_pmufw/src/pm_binding.c +++ b/lib/sw_apps/zynqmp_pmufw/src/pm_binding.c @@ -64,6 +64,9 @@ void XPfw_PmInit(void) * XPfw_PmIpiHandler() - Call from IPI interrupt handler to process PM API call * @isrMask IPI's ISR register value. Needed to determine buffer holding the * payload + * @isrClr Pointer to a variable in which PM returns an ISR mask of the master + * whose request is handled (mask to write in ISR register to clear + * interrupt) * @apiId PM API id that was read from master's IPI buffer and validated as * existing * @@ -86,8 +89,7 @@ void XPfw_PmInit(void) * be cleared after this function returns to make PM API call * atomic. */ -int XPfw_PmIpiHandler(const u32 isrMask, - const u32 apiId) +int XPfw_PmIpiHandler(const u32 isrMask, const u32 apiId, u32* const isrClr) { int status = XST_SUCCESS; u32 i; @@ -96,8 +98,8 @@ int XPfw_PmIpiHandler(const u32 isrMask, u32 offset = 0U; const PmMaster* master = PmGetMasterByIpiMask(isrMask); - if (NULL == master) { - /* Never happens if IPI interrupt routine is implemented correctly */ + if ((NULL == isrClr) || (NULL == master)) { + /* Never happens if IPI irq handler is implemented correctly */ PmDbg("ERROR: IPI source not supported %d\n", isrMask); status = XST_INVALID_PARAM; goto done; @@ -113,6 +115,12 @@ int XPfw_PmIpiHandler(const u32 isrMask, PmProcessRequest(master, payload); + /* + * Master's bitfield in isr register will be cleared based on isrClr + * variable value (master's request is handled) + */ + *isrClr = master->ipiMask; + done: return status; } diff --git a/lib/sw_apps/zynqmp_pmufw/src/pm_binding.h b/lib/sw_apps/zynqmp_pmufw/src/pm_binding.h index b2811fa4..7fa25a73 100644 --- a/lib/sw_apps/zynqmp_pmufw/src/pm_binding.h +++ b/lib/sw_apps/zynqmp_pmufw/src/pm_binding.h @@ -58,7 +58,7 @@ void XPfw_PmInit(void); XPfw_PmIpiStatus XPfw_PmCheckIpiRequest(const u32 isrVal, u32* const apiId); /* Call from IPI interrupt routine to handle PM API request */ -int XPfw_PmIpiHandler(const u32 isrMask, const u32 apiId); +int XPfw_PmIpiHandler(const u32 isrMask, const u32 apiId, u32* const isrClr); /* Call from GPI2 interrupt routine to handle processor sleep request */ int XPfw_PmWfiHandler(const u32 srcMask); diff --git a/lib/sw_apps/zynqmp_pmufw/src/pm_master.c b/lib/sw_apps/zynqmp_pmufw/src/pm_master.c index d363fe5a..222cbc71 100644 --- a/lib/sw_apps/zynqmp_pmufw/src/pm_master.c +++ b/lib/sw_apps/zynqmp_pmufw/src/pm_master.c @@ -530,7 +530,7 @@ const PmMaster* PmGetMasterByIpiMask(const u32 mask) const PmMaster *mst = NULL; for (i = 0U; i < ARRAY_SIZE(pmAllMasters); i++) { - if (mask == pmAllMasters[i]->ipiMask) { + if (mask & pmAllMasters[i]->ipiMask) { mst = pmAllMasters[i]; break; } diff --git a/lib/sw_apps/zynqmp_pmufw/src/xpfw_user_startup.c b/lib/sw_apps/zynqmp_pmufw/src/xpfw_user_startup.c index e09c38d4..e9adf05e 100644 --- a/lib/sw_apps/zynqmp_pmufw/src/xpfw_user_startup.c +++ b/lib/sw_apps/zynqmp_pmufw/src/xpfw_user_startup.c @@ -46,8 +46,9 @@ #ifdef ENABLE_PM static void PmIpiHandler(const XPfw_Module_t *ModPtr, u32 IpiNum, u32 SrcMask) { - u32 isrVal, apiId; + u32 isrVal, isrClr, apiId; XPfw_PmIpiStatus ipiStatus; + XStatus status; switch (IpiNum) { case 0: @@ -56,12 +57,24 @@ static void PmIpiHandler(const XPfw_Module_t *ModPtr, u32 IpiNum, u32 SrcMask) ipiStatus = XPfw_PmCheckIpiRequest(isrVal, &apiId); if (XPFW_PM_IPI_IS_PM_CALL == ipiStatus) { /* Power management API processing */ - XPfw_PmIpiHandler(isrVal, apiId); + status = XPfw_PmIpiHandler(isrVal, apiId, &isrClr); + if (XST_SUCCESS == status) { + /* Clear only irq for handled PM request */ + XPfw_Write32(IPI_PMU_0_ISR, isrClr); + } } else { + status = XST_NO_FEATURE; fw_printf("MOD-%d: Non-PM IPI-%d call received\r\n", ModPtr->ModId, IpiNum); } - XPfw_Write32(IPI_PMU_0_ISR, isrVal); + if (XST_SUCCESS != status) { + /* + * Clear all irqs if something went wrong, to avoid + * system looping in interrupt handler because of error + */ + XPfw_Write32(IPI_PMU_0_ISR, isrVal); + fw_printf("ERROR #%d : IPI-%d\r\n", status, IpiNum); + } break; case 1: diff --git a/lib/sw_apps/zynqmp_pmufw/src/xpfw_version.h b/lib/sw_apps/zynqmp_pmufw/src/xpfw_version.h index 29571a21..b6aa7d60 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.1-swbeta2-36-gccb91daa0515" + #define ZYNQMP_XPFW_VERSION "2015.1-swbeta2-37-g79629747082f" #endif