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 <soren.brinkmann@xilinx.com>
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
index e859ee3..a466687 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 @@
 	/* 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 @@
 	/* 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 @@
 			 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 @@
 	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 @@
 	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 @@
 			 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 @@
 
 	/* 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 @@
 
 	/* 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 @@
 
 	/* 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 @@
 
 	/* 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 @@
 
 	/* 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 @@
 
 	/* 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 c3e7ccb..6648fec 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_ipi.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_ipi.c
@@ -188,13 +188,15 @@
 /**
  * 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 @@
 	 * 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 @@
  * 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 @@
  */
 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 @@
 	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 d92e648..108aef4 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_ipi.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_ipi.h
@@ -39,6 +39,6 @@
 			       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_ */