summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_sys.c13
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_sys.h1
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_ipi.c30
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_ipi.h2
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_svc_main.c12
5 files changed, 58 insertions, 0 deletions
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
index c7b8b9a7..15e12fa8 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -557,3 +557,16 @@ enum pm_ret_status pm_get_chipid(uint32_t *value)
PM_PACK_PAYLOAD1(payload, PM_GET_CHIPID);
return pm_ipi_send_sync(primary_proc, payload, value, 2);
}
+
+/**
+ * pm_get_callbackdata() - Read from IPI response buffer
+ * @data - array of PAYLOAD_ARG_CNT elements
+ *
+ * Read value from ipi buffer response buffer.
+ */
+void pm_get_callbackdata(uint32_t *data, size_t count)
+{
+
+ pm_ipi_buff_read_callb(data, count);
+ pm_ipi_irq_clear();
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
index 8cbd13b2..7e229488 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
@@ -116,5 +116,6 @@ enum pm_ret_status pm_fpga_load(uint32_t address_high,
enum pm_ret_status pm_fpga_get_status(unsigned int *value);
enum pm_ret_status pm_get_chipid(uint32_t *value);
+void pm_get_callbackdata(uint32_t *data, size_t count);
#endif /* _PM_API_SYS_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_ipi.c b/plat/xilinx/zynqmp/pm_service/pm_ipi.c
index df3b854d..9148f909 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_ipi.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_ipi.c
@@ -56,6 +56,8 @@
#define IPI_BUFFER_TARGET_PL_3_OFFSET 0x180U
#define IPI_BUFFER_TARGET_PMU_OFFSET 0x1C0U
+#define IPI_BUFFER_MAX_WORDS 8
+
#define IPI_BUFFER_REQ_OFFSET 0x0U
#define IPI_BUFFER_RESP_OFFSET 0x20U
@@ -218,6 +220,29 @@ static enum pm_ret_status pm_ipi_buff_read(const struct pm_proc *proc,
}
/**
+ * pm_ipi_buff_read_callb() - Reads IPI response after PMU has handled interrupt
+ * @value Used to return value from IPI buffer element (optional)
+ * @count Number of values to return in @value
+ *
+ * @return Returns status, either success or error+reason
+ */
+void pm_ipi_buff_read_callb(unsigned int *value, size_t count)
+{
+ size_t i;
+ uintptr_t buffer_base = IPI_BUFFER_PMU_BASE +
+ IPI_BUFFER_TARGET_APU_OFFSET +
+ IPI_BUFFER_REQ_OFFSET;
+
+ if (count > IPI_BUFFER_MAX_WORDS)
+ count = IPI_BUFFER_MAX_WORDS;
+
+ for (i = 0; i <= count; i++) {
+ *value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
+ value++;
+ }
+}
+
+/**
* pm_ipi_send_sync() - Sends IPI request to the PMU
* @proc Pointer to the processor who is initiating request
* @payload API id and call arguments to be written in IPI buffer
@@ -258,3 +283,8 @@ void pm_ipi_irq_disable(void)
{
mmio_write_32(IPI_APU_IDR, IPI_APU_IXR_PMU_0_MASK);
}
+
+void pm_ipi_irq_clear(void)
+{
+ mmio_write_32(IPI_APU_ISR, IPI_APU_IXR_PMU_0_MASK);
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_ipi.h b/plat/xilinx/zynqmp/pm_service/pm_ipi.h
index fefe89ab..b314b80a 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_ipi.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_ipi.h
@@ -40,7 +40,9 @@ enum pm_ret_status pm_ipi_send(const struct pm_proc *proc,
enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc,
uint32_t payload[PAYLOAD_ARG_CNT],
unsigned int *value, size_t count);
+void pm_ipi_buff_read_callb(unsigned int *value, size_t count);
void pm_ipi_irq_enable(void);
void pm_ipi_irq_disable(void);
+void pm_ipi_irq_clear(void);
#endif /* _PM_IPI_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
index 8a4bba61..036ed8a2 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
@@ -42,6 +42,8 @@
#include "pm_ipi.h"
#include "../zynqmp_private.h"
+#define PM_GET_CALLBACK_DATA 0xa01
+
/* 0 - UP, !0 - DOWN */
static int32_t pm_down = !0;
@@ -257,6 +259,16 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
result[1]);
}
+ case PM_GET_CALLBACK_DATA:
+ {
+ uint32_t result[4];
+
+ pm_get_callbackdata(result, sizeof(result));
+ SMC_RET2(handle,
+ (uint64_t)result[0] | ((uint64_t)result[1] << 32),
+ (uint64_t)result[2] | ((uint64_t)result[3] << 32));
+ }
+
default:
WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
SMC_RET1(handle, SMC_UNK);