summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTejas Patel <tejas.patel@xilinx.com>2018-02-09 02:42:59 -0800
committerSiva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com>2018-05-17 15:19:14 +0530
commit7dae6137efb7286c7cc73a47a5b25545cc1fb799 (patch)
treebbfa662b3dd4037437dc721341c6bd1e245fa87f
parent3f0d4f1bd5fff2de5d6afedba04c799b5de55b72 (diff)
downloadarm-trusted-firmware-7dae6137efb7286c7cc73a47a5b25545cc1fb799.tar.gz
xilinx: zynqmp: pm_service: Fix APU only restart
Existing code blocks each IPI send request in ipi_mb_notify() function till pmu clears respective bit in ipi observation register. After sending PM_SYSTEM_SHUTDOWN request to PMU, PMU will restart APU. While PMU is restarting APU, ATF is running out of OCM, which can cause read/write hang from/to OCM. There is no need to wait for notification from PMU in case of SystemShutdown request in ATF, as APU is going to restart. This patch fixes APU only restart issue. Signed-off-by: Tejas Patel <tejasp@xilinx.com> Acked-by: Wendy Liang <wendy.liang@xilinx.com>
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_sys.c2
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_ipi.c38
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_ipi.h2
3 files changed, 37 insertions, 5 deletions
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
index 69bd53b2f..a3beaad95 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -244,7 +244,7 @@ enum pm_ret_status pm_system_shutdown(unsigned int type, unsigned int subtype)
}
PM_PACK_PAYLOAD3(payload, PM_SYSTEM_SHUTDOWN, type, subtype);
- return pm_ipi_send(primary_proc, payload);
+ return pm_ipi_send_non_blocking(primary_proc, payload);
}
/* APIs for managing PM slaves: */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_ipi.c b/plat/xilinx/zynqmp/pm_service/pm_ipi.c
index 58faf0e70..dc1ea4d12 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_ipi.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_ipi.c
@@ -26,6 +26,9 @@
#define IPI_BUFFER_REQ_OFFSET 0x0U
#define IPI_BUFFER_RESP_OFFSET 0x20U
+#define IPI_BLOCKING 1
+#define IPI_NON_BLOCKING 0
+
DEFINE_BAKERY_LOCK(pm_secure_lock);
const struct pm_ipi apu_ipi = {
@@ -63,7 +66,8 @@ int pm_ipi_init(const struct pm_proc *proc)
* @return Returns status, either success or error+reason
*/
static enum pm_ret_status pm_ipi_send_common(const struct pm_proc *proc,
- uint32_t payload[PAYLOAD_ARG_CNT])
+ uint32_t payload[PAYLOAD_ARG_CNT],
+ uint32_t is_blocking)
{
unsigned int offset = 0;
uintptr_t buffer_base = proc->ipi->buffer_base +
@@ -75,13 +79,39 @@ static enum pm_ret_status pm_ipi_send_common(const struct pm_proc *proc,
mmio_write_32(buffer_base + offset, payload[i]);
offset += PAYLOAD_ARG_SIZE;
}
+
/* Generate IPI to PMU */
- ipi_mb_notify(proc->ipi->apu_ipi_id, proc->ipi->pmu_ipi_id, 1);
+ ipi_mb_notify(proc->ipi->apu_ipi_id, proc->ipi->pmu_ipi_id,
+ is_blocking);
return PM_RET_SUCCESS;
}
/**
+ * pm_ipi_send_non_blocking() - Sends IPI request to the PMU without blocking
+ * notification
+ * @proc Pointer to the processor who is initiating request
+ * @payload API id and call arguments to be written in IPI buffer
+ *
+ * Send an IPI request to the power controller.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_ipi_send_non_blocking(const struct pm_proc *proc,
+ uint32_t payload[PAYLOAD_ARG_CNT])
+{
+ enum pm_ret_status ret;
+
+ bakery_lock_get(&pm_secure_lock);
+
+ ret = pm_ipi_send_common(proc, payload, IPI_NON_BLOCKING);
+
+ bakery_lock_release(&pm_secure_lock);
+
+ return ret;
+}
+
+/**
* pm_ipi_send() - 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
@@ -97,7 +127,7 @@ enum pm_ret_status pm_ipi_send(const struct pm_proc *proc,
bakery_lock_get(&pm_secure_lock);
- ret = pm_ipi_send_common(proc, payload);
+ ret = pm_ipi_send_common(proc, payload, IPI_BLOCKING);
bakery_lock_release(&pm_secure_lock);
@@ -179,7 +209,7 @@ enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc,
bakery_lock_get(&pm_secure_lock);
- ret = pm_ipi_send_common(proc, payload);
+ ret = pm_ipi_send_common(proc, payload, IPI_BLOCKING);
if (ret != PM_RET_SUCCESS)
goto unlock;
diff --git a/plat/xilinx/zynqmp/pm_service/pm_ipi.h b/plat/xilinx/zynqmp/pm_service/pm_ipi.h
index e6b36f529..439dcf444 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_ipi.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_ipi.h
@@ -13,6 +13,8 @@ int pm_ipi_init(const struct pm_proc *proc);
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_non_blocking(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, size_t count);