summaryrefslogtreecommitdiffstats
path: root/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c
diff options
context:
space:
mode:
Diffstat (limited to 'plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c')
-rw-r--r--plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c b/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c
new file mode 100644
index 0000000..a070583
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <string.h>
+
+#include <common/debug.h>
+#include <lib/psci/psci.h>
+#include <lib/mmio.h>
+
+#include <mss_pm_ipc.h>
+
+/*
+ * SISR is 32 bit interrupt register representing 32 interrupts
+ *
+ * +======+=============+=============+
+ * + Bits + 31 + 30 - 00 +
+ * +======+=============+=============+
+ * + Desc + MSS Msg Int + Reserved +
+ * +======+=============+=============+
+ */
+#define MSS_SISR (MVEBU_REGS_BASE + 0x5800D0)
+#define MSS_SISTR (MVEBU_REGS_BASE + 0x5800D8)
+
+#define MSS_MSG_INT_MASK (0x80000000)
+#define MSS_TIMER_BASE (MVEBU_REGS_BASE_MASK + 0x580110)
+#define MSS_TRIGGER_TIMEOUT (2000)
+
+/*****************************************************************************
+ * mss_pm_ipc_msg_send
+ *
+ * DESCRIPTION: create and transmit IPC message
+ *****************************************************************************
+ */
+int mss_pm_ipc_msg_send(unsigned int channel_id, unsigned int msg_id,
+ const psci_power_state_t *target_state)
+{
+ /* Transmit IPC message */
+#ifndef DISABLE_CLUSTER_LEVEL
+ mv_pm_ipc_msg_tx(channel_id, msg_id,
+ (unsigned int)target_state->pwr_domain_state[
+ MPIDR_AFFLVL1]);
+#else
+ mv_pm_ipc_msg_tx(channel_id, msg_id, 0);
+#endif
+
+ return 0;
+}
+
+/*****************************************************************************
+ * mss_pm_ipc_msg_trigger
+ *
+ * DESCRIPTION: Trigger IPC message interrupt to MSS
+ *****************************************************************************
+ */
+int mss_pm_ipc_msg_trigger(void)
+{
+ unsigned int timeout;
+ unsigned int t_end;
+ unsigned int t_start = mmio_read_32(MSS_TIMER_BASE);
+
+ mmio_write_32(MSS_SISR, MSS_MSG_INT_MASK);
+
+ do {
+ /* wait while SCP process incoming interrupt */
+ if (mmio_read_32(MSS_SISTR) != MSS_MSG_INT_MASK)
+ break;
+
+ /* check timeout */
+ t_end = mmio_read_32(MSS_TIMER_BASE);
+
+ timeout = ((t_start > t_end) ?
+ (t_start - t_end) : (t_end - t_start));
+ if (timeout > MSS_TRIGGER_TIMEOUT) {
+ ERROR("PM MSG Trigger Timeout\n");
+ break;
+ }
+
+ } while (1);
+
+ return 0;
+}