summaryrefslogtreecommitdiff
path: root/plat/marvell/a8k/common/plat_pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'plat/marvell/a8k/common/plat_pm.c')
-rw-r--r--plat/marvell/a8k/common/plat_pm.c86
1 files changed, 78 insertions, 8 deletions
diff --git a/plat/marvell/a8k/common/plat_pm.c b/plat/marvell/a8k/common/plat_pm.c
index efed0a83..ccdccc18 100644
--- a/plat/marvell/a8k/common/plat_pm.c
+++ b/plat/marvell/a8k/common/plat_pm.c
@@ -33,10 +33,14 @@
*/
#include <plat_marvell.h>
+#include <platform.h>
+#include <console.h>
#include <gicv2.h>
#include <mmio.h>
#include <debug.h>
#include <delay_timer.h>
+#include <cache_llc.h>
+#include <marvell_pm.h>
#ifdef SCP_IMAGE
#include <bakery_lock.h>
@@ -295,6 +299,48 @@ void plat_marvell_system_reset(void)
mmio_write_32(MVEBU_RFU_BASE + MVEBU_RFU_GLOBL_SW_RST, 0x0);
}
+/*
+ * This function should be called on restore from
+ * "suspend to RAM" state when the execution flow
+ * has to bypass BootROM image to RAM copy and speed up
+ * the system recovery
+ *
+ */
+static void plat_exit_bootrom(void)
+{
+ exit_bootrom(PLAT_MARVELL_TRUSTED_ROM_BASE);
+}
+
+/*
+ * Send a command to external PMIC to cut off the power rail
+ */
+void plat_marvell_power_suspend_to_ram(void)
+{
+ uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE;
+
+ INFO("Suspending to RAM\n");
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ gicv2_cpuif_disable();
+
+ mailbox[MBOX_IDX_SUSPEND_MAGIC] = MVEBU_MAILBOX_SUSPEND_STATE;
+ mailbox[MBOX_IDX_ROM_EXIT_ADDR] = (uintptr_t)&plat_exit_bootrom;
+
+#if PLAT_MARVELL_SHARED_RAM_CACHED
+ flush_dcache_range(PLAT_MARVELL_MAILBOX_BASE +
+ MBOX_IDX_SUSPEND_MAGIC * sizeof(uintptr_t),
+ 2 * sizeof(uintptr_t));
+#endif
+
+ isb();
+ /*
+ * Do not halt here!
+ * The function must return for allowing the caller function
+ * psci_power_up_finish() to do the proper context saving and
+ * to release the CPU lock.
+ */
+}
+
/*******************************************************************************
* A8K handler called to check the validity of the power state
* parameter.
@@ -401,10 +447,7 @@ void a8k_pwr_domain_off(const psci_power_state_t *target_state)
/* Prevent interrupts from spuriously waking up this cpu */
gicv2_cpuif_disable();
- /*
- * pm system synchronization - used to synchronize
- * multiple core access to MSS
- */
+ /* pm system synchronization - used to synchronize multiple core access to MSS */
bakery_lock_get(&pm_sys_lock);
/* send CPU OFF IPC Message to MSS */
@@ -453,8 +496,8 @@ void a8k_pwr_domain_suspend(const psci_power_state_t *target_state)
/* trace message */
PM_TRACE(TRACE_PWR_DOMAIN_SUSPEND, idx);
#else
- INFO("a8k_pwr_domain_suspend is not supported without SCP\n");
- return;
+ /* Suspend to RAM */
+ plat_marvell_power_suspend_to_ram();
#endif /* SCP_IMAGE */
}
@@ -497,8 +540,35 @@ void a8k_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
/* trace message */
PM_TRACE(TRACE_PWR_DOMAIN_SUSPEND_FINISH, idx);
#else
- INFO("a8k_pwr_domain_on_finish is not supported without SCP\n");
- return;
+ uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE;
+
+ /* Only primary CPU requres platform init */
+ if (!plat_my_core_pos()) {
+ /* Initialize the console to provide early debug support */
+ console_init(PLAT_MARVELL_BOOT_UART_BASE,
+ PLAT_MARVELL_BOOT_UART_CLK_IN_HZ,
+ MARVELL_CONSOLE_BAUDRATE);
+ bl31_plat_arch_setup();
+ marvell_bl31_platform_setup();
+ /*
+ * Remove suspend to RAM marker from the mailbox
+ * for treating a regular reset as a cold boot
+ */
+ mailbox[MBOX_IDX_SUSPEND_MAGIC] = 0;
+ mailbox[MBOX_IDX_ROM_EXIT_ADDR] = 0;
+#if PLAT_MARVELL_SHARED_RAM_CACHED
+ flush_dcache_range(PLAT_MARVELL_MAILBOX_BASE +
+ MBOX_IDX_SUSPEND_MAGIC * sizeof(uintptr_t),
+ 2 * sizeof(uintptr_t));
+#endif
+ return;
+ }
+
+ /* arch specific configuration */
+ psci_arch_init();
+
+ /* Interrupt initialization */
+ gicv2_cpuif_enable();
#endif /* SCP_IMAGE */
}