From dc0c5a42d61e5efc7d85fffffc22a910130227d2 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Thu, 22 Sep 2016 11:35:47 -0700 Subject: [PATCH] zynqmp: pm: Allow obtaining additional return values from FW Allow reading more than just a single value from the message buffer. Signed-off-by: Soren Brinkmann --- plat/xilinx/zynqmp/pm_service/pm_api_sys.c | 24 +++++++++++----------- plat/xilinx/zynqmp/pm_service/pm_ipi.c | 19 ++++++++++------- plat/xilinx/zynqmp/pm_service/pm_ipi.h | 2 +- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c index e859ee39..a4666871 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -101,7 +101,7 @@ enum pm_ret_status pm_self_suspend(enum pm_node_id nid, /* Send request to the PMU */ PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency, state, address, (address >> 32)); - return pm_ipi_send_sync(proc, payload, NULL); + return pm_ipi_send_sync(proc, payload, NULL, 0); } /** @@ -123,7 +123,7 @@ enum pm_ret_status pm_req_suspend(enum pm_node_id target, /* Send request to the PMU */ PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state); if (ack == REQ_ACK_BLOCKING) - return pm_ipi_send_sync(primary_proc, payload, NULL); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); else return pm_ipi_send(primary_proc, payload); } @@ -165,7 +165,7 @@ enum pm_ret_status pm_req_wakeup(enum pm_node_id target, encoded_address >> 32, ack); if (ack == REQ_ACK_BLOCKING) - return pm_ipi_send_sync(primary_proc, payload, NULL); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); else return pm_ipi_send(primary_proc, payload); } @@ -187,7 +187,7 @@ enum pm_ret_status pm_force_powerdown(enum pm_node_id target, PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack); if (ack == REQ_ACK_BLOCKING) - return pm_ipi_send_sync(primary_proc, payload, NULL); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); else return pm_ipi_send(primary_proc, payload); } @@ -272,7 +272,7 @@ enum pm_ret_status pm_req_node(enum pm_node_id nid, PM_PACK_PAYLOAD5(payload, PM_REQ_NODE, nid, capabilities, qos, ack); if (ack == REQ_ACK_BLOCKING) - return pm_ipi_send_sync(primary_proc, payload, NULL); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); else return pm_ipi_send(primary_proc, payload); } @@ -299,7 +299,7 @@ enum pm_ret_status pm_set_requirement(enum pm_node_id nid, ack); if (ack == REQ_ACK_BLOCKING) - return pm_ipi_send_sync(primary_proc, payload, NULL); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); else return pm_ipi_send(primary_proc, payload); } @@ -348,7 +348,7 @@ enum pm_ret_status pm_get_api_version(unsigned int *version) /* Send request to the PMU */ PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION); - return pm_ipi_send_sync(primary_proc, payload, version); + return pm_ipi_send_sync(primary_proc, payload, version, 1); } /** @@ -418,7 +418,7 @@ enum pm_ret_status pm_get_op_characteristic(enum pm_node_id nid, /* Send request to the PMU */ PM_PACK_PAYLOAD3(payload, PM_GET_OP_CHARACTERISTIC, nid, type); - return pm_ipi_send_sync(primary_proc, payload, result); + return pm_ipi_send_sync(primary_proc, payload, result, 1); } /* Direct-Control API functions */ @@ -454,7 +454,7 @@ enum pm_ret_status pm_reset_get_status(unsigned int reset, /* Send request to the PMU */ PM_PACK_PAYLOAD2(payload, PM_RESET_GET_STATUS, reset); - return pm_ipi_send_sync(primary_proc, payload, reset_status); + return pm_ipi_send_sync(primary_proc, payload, reset_status, 1); } /** @@ -476,7 +476,7 @@ enum pm_ret_status pm_mmio_write(uintptr_t address, /* Send request to the PMU */ PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value); - return pm_ipi_send_sync(primary_proc, payload, NULL); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); } /** @@ -495,7 +495,7 @@ enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value) /* Send request to the PMU */ PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address); - return pm_ipi_send_sync(primary_proc, payload, value); + return pm_ipi_send_sync(primary_proc, payload, value, 1); } /** @@ -539,5 +539,5 @@ enum pm_ret_status pm_fpga_get_status(unsigned int *value) /* Send request to the PMU */ PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS); - return pm_ipi_send_sync(primary_proc, payload, value); + return pm_ipi_send_sync(primary_proc, payload, value, 1); } diff --git a/plat/xilinx/zynqmp/pm_service/pm_ipi.c b/plat/xilinx/zynqmp/pm_service/pm_ipi.c index c3e7ccb5..6648fec7 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_ipi.c +++ b/plat/xilinx/zynqmp/pm_service/pm_ipi.c @@ -188,13 +188,15 @@ enum pm_ret_status pm_ipi_send(const struct pm_proc *proc, /** * pm_ipi_buff_read() - Reads IPI response after PMU has handled interrupt * @proc Pointer to the processor who is waiting and reading response - * @value Used to return value from 2nd IPI buffer element (optional) + * @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 */ static enum pm_ret_status pm_ipi_buff_read(const struct pm_proc *proc, - unsigned int *value) + unsigned int *value, size_t count) { + size_t i; uintptr_t buffer_base = proc->ipi->buffer_base + IPI_BUFFER_TARGET_PMU_OFFSET + IPI_BUFFER_RESP_OFFSET; @@ -208,8 +210,10 @@ static enum pm_ret_status pm_ipi_buff_read(const struct pm_proc *proc, * buf-2: unused * buf-3: unused */ - if (value != NULL) - *value = mmio_read_32(buffer_base + PAYLOAD_ARG_SIZE); + for (i = 1; i <= count; i++) { + *value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE)); + value++; + } return mmio_read_32(buffer_base); } @@ -218,7 +222,8 @@ static enum pm_ret_status pm_ipi_buff_read(const struct pm_proc *proc, * 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 - * @value Used to return value from 2nd IPI buffer element (optional) + * @value Used to return value from IPI buffer element (optional) + * @count Number of values to return in @value * * Send an IPI request to the power controller and wait for it to be handled. * @@ -227,7 +232,7 @@ static enum pm_ret_status pm_ipi_buff_read(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) + unsigned int *value, size_t count) { enum pm_ret_status ret; @@ -237,7 +242,7 @@ enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc, if (ret != PM_RET_SUCCESS) goto unlock; - ret = pm_ipi_buff_read(proc, value); + ret = pm_ipi_buff_read(proc, value, count); unlock: bakery_lock_release(&pm_secure_lock); diff --git a/plat/xilinx/zynqmp/pm_service/pm_ipi.h b/plat/xilinx/zynqmp/pm_service/pm_ipi.h index d92e648c..108aef49 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_ipi.h +++ b/plat/xilinx/zynqmp/pm_service/pm_ipi.h @@ -39,6 +39,6 @@ enum pm_ret_status pm_ipi_send(const struct pm_proc *proc, uint32_t payload[PAYLOAD_ARG_CNT]); enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc, uint32_t payload[PAYLOAD_ARG_CNT], - unsigned int *value); + unsigned int *value, size_t count); #endif /* _PM_IPI_H_ */ -- 2.30.2