summaryrefslogtreecommitdiff
path: root/plat/xilinx
diff options
context:
space:
mode:
authorSoren Brinkmann <soren.brinkmann@xilinx.com>2016-09-30 14:24:25 -0700
committerSoren Brinkmann <soren.brinkmann@xilinx.com>2016-11-16 15:55:58 -0800
commit300cbb0bdb762dbbf716acc9606529535fd6c038 (patch)
treebf3a87e399a960ccbd771c1c70a4ed13ccdf5714 /plat/xilinx
parenta76c3697a0e898c5d135194f7f31afd13b72ef81 (diff)
zynqmp: pm: Add SiP call to obtain PM callback data
The callback IRQ is delivered to the NS OS. Provide an interface to allow the NS OS to obtain the callback data from the secure HW. Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
Diffstat (limited to 'plat/xilinx')
-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);