diff options
| -rw-r--r-- | plat/xilinx/zynqmp/pm_service/pm_api_sys.c | 13 | ||||
| -rw-r--r-- | plat/xilinx/zynqmp/pm_service/pm_api_sys.h | 1 | ||||
| -rw-r--r-- | plat/xilinx/zynqmp/pm_service/pm_ipi.c | 30 | ||||
| -rw-r--r-- | plat/xilinx/zynqmp/pm_service/pm_ipi.h | 2 | ||||
| -rw-r--r-- | plat/xilinx/zynqmp/pm_service/pm_svc_main.c | 12 |
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); |
