xilinx: zynqmp: Add support for Error Management
Adding the EM specific smc handler for the EM-related requests.
Signed-off-by: Venkatesh Yadav Abbarapu <venkatesh.abbarapu@xilinx.com>
Signed-off-by: Rajan Vaja <rajan.vaja@xilinx.com>
Change-Id: I98122d49604a01a2f6bd1e509a5896ee68069dd0
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
index 3427149..9a53408 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -65,6 +65,10 @@
PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4); \
}
+#define EM_PACK_PAYLOAD1(pl, arg0) { \
+ pl[0] = (uint16_t)(0xE) << 16 | (uint16_t)arg0; \
+}
+
/**
* pm_self_suspend() - PM call for processor to suspend itself
* @nid Node id of the processor or subsystem
@@ -1615,5 +1619,32 @@
/* Send request to the PMU */
PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+enum pm_ret_status em_set_action(unsigned int *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ EM_PACK_PAYLOAD1(payload, EM_SET_ACTION);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+enum pm_ret_status em_remove_action(unsigned int *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ EM_PACK_PAYLOAD1(payload, EM_REMOVE_ACTION);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+enum pm_ret_status em_send_errors(unsigned int *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS);
return pm_ipi_send_sync(primary_proc, payload, value, 1);
}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
index b3ebb27..b0c2652 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
@@ -198,5 +198,8 @@
enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode);
enum pm_ret_status pm_efuse_access(uint32_t address_high,
uint32_t address_low, uint32_t *value);
+enum pm_ret_status em_set_action(unsigned int *value);
+enum pm_ret_status em_remove_action(unsigned int *value);
+enum pm_ret_status em_send_errors(unsigned int *value);
#endif /* PM_API_SYS_H */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h
index da87893..ee31c92 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_defs.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h
@@ -33,6 +33,7 @@
#define PM_STATE_CPU_IDLE 0x0U
#define PM_STATE_SUSPEND_TO_RAM 0xFU
+#define EM_FUNID_NUM_MASK 0xF0000U
/*********************************************************************
* Enum definitions
********************************************************************/
@@ -323,4 +324,13 @@
PM_CLOCK_DIV1_ID,
};
+/**
+ * EM API IDs
+ */
+enum em_api_id {
+ EM_SET_ACTION = 1,
+ EM_REMOVE_ACTION,
+ EM_SEND_ERRORS,
+};
+
#endif /* PM_DEFS_H */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
index 5b3e737..a4bc1ac 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
@@ -628,3 +628,56 @@
SMC_RET1(handle, SMC_UNK);
}
}
+
+/**
+ * em_smc_handler() - SMC handler for EM-API calls coming from EL1/EL2.
+ * @smc_fid - Function Identifier
+ * @x1 - x4 - Arguments
+ * @cookie - Unused
+ * @handler - Pointer to caller's context structure
+ *
+ * @return - Unused
+ *
+ * Determines that smc_fid is valid and supported EM SMC Function ID from the
+ * list of em_api_ids, otherwise completes the request with
+ * the unknown SMC Function ID
+ *
+ * The SMC calls for EM service are forwarded from SIP Service SMC handler
+ * function with rt_svc_handle signature
+ */
+uint64_t em_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, void *cookie, void *handle, uint64_t flags)
+{
+ enum pm_ret_status ret;
+
+ switch (smc_fid & FUNCID_NUM_MASK) {
+ /* EM API Functions */
+ case EM_SET_ACTION:
+ {
+ uint32_t value;
+
+ ret = em_set_action(&value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case EM_REMOVE_ACTION:
+ {
+ uint32_t value;
+
+ ret = em_remove_action(&value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case EM_SEND_ERRORS:
+ {
+ uint32_t value;
+
+ ret = em_send_errors(&value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ default:
+ WARN("Unimplemented EM Service Call: 0x%x\n", smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.h b/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
index 0968f64..abadd40 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -14,4 +14,7 @@
uint64_t x4, void *cookie, void *handle,
uint64_t flags);
+uint64_t em_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, void *cookie, void *handle,
+ uint64_t flags);
#endif /* PM_SVC_MAIN_H */
diff --git a/plat/xilinx/zynqmp/sip_svc_setup.c b/plat/xilinx/zynqmp/sip_svc_setup.c
index 9b18274..4c29da2 100644
--- a/plat/xilinx/zynqmp/sip_svc_setup.c
+++ b/plat/xilinx/zynqmp/sip_svc_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -25,6 +25,9 @@
#define PM_FID_MASK 0xf000u
#define PM_FID_VALUE 0u
#define IPI_FID_VALUE 0x1000u
+#define EM_FID_MASK 0xf0000u
+#define EM_FID_VALUE 0xE0000u
+#define is_em_fid(_fid) (((_fid) & EM_FID_MASK) == EM_FID_VALUE)
#define is_pm_fid(_fid) (((_fid) & PM_FID_MASK) == PM_FID_VALUE)
#define is_ipi_fid(_fid) (((_fid) & PM_FID_MASK) == IPI_FID_VALUE)
@@ -61,8 +64,12 @@
void *handle,
u_register_t flags)
{
+ /* Let EM SMC handler deal with EM-related requests */
+ if (is_em_fid(smc_fid)) {
+ return em_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
+ flags);
+ } else if (is_pm_fid(smc_fid)) {
/* Let PM SMC handler deal with PM-related requests */
- if (is_pm_fid(smc_fid)) {
return pm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
flags);
}