mediatek: mt8183: add MTK SPM driver

Add MTK SPM driver for suspend/resume scenario.

Change-Id: I8207eea95914da9e63c62f3afc8329f3ccd9a22c
diff --git a/plat/mediatek/mt8183/plat_pm.c b/plat/mediatek/mt8183/plat_pm.c
index 83c8d4c..9e0a920 100644
--- a/plat/mediatek/mt8183/plat_pm.c
+++ b/plat/mediatek/mt8183/plat_pm.c
@@ -25,6 +25,8 @@
 #include <plat_private.h>
 #include <power_tracer.h>
 #include <pmic.h>
+#include <spm.h>
+#include <spm_suspend.h>
 #include <rtc.h>
 
 #define MTK_LOCAL_STATE_OFF     2
@@ -147,6 +149,54 @@
 	panic();
 }
 
+static void plat_mtk_power_domain_suspend(const psci_power_state_t *state)
+{
+	uint64_t mpidr = read_mpidr();
+	int cpu = MPIDR_AFFLVL0_VAL(mpidr);
+	int cluster = MPIDR_AFFLVL1_VAL(mpidr);
+
+	spm_system_suspend();
+
+	/* init cpu reset arch as AARCH64 */
+	mcucfg_init_archstate(cluster, cpu, 1);
+	mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
+	spm_set_bootaddr(secure_entrypoint);
+
+	/* Prevent interrupts from spuriously waking up this cpu */
+	mt_gic_cpuif_disable();
+	mt_gic_irq_save();
+
+	if (state->pwr_domain_state[MPIDR_AFFLVL2] == MTK_LOCAL_STATE_OFF) {
+		plat_mtk_cci_disable();
+		disable_scu(mpidr);
+	}
+}
+
+static void plat_mtk_power_domain_suspend_finish(const psci_power_state_t *state)
+{
+	uint64_t mpidr = read_mpidr();
+
+	mt_gic_init();
+	mt_gic_irq_restore();
+
+	if (state->pwr_domain_state[MPIDR_AFFLVL2] == MTK_LOCAL_STATE_OFF) {
+		enable_scu(mpidr);
+		plat_mtk_cci_enable();
+		plat_dcm_restore_cluster_on(mpidr);
+	}
+
+	mmio_write_32(EMI_WFIFO, 0xf);
+	spm_system_suspend_finish();
+}
+
+static void plat_mtk_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+	assert(PLAT_MAX_PWR_LVL >= 2);
+
+	for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
+		req_state->pwr_domain_state[i] = MTK_LOCAL_STATE_OFF;
+}
+
 /*******************************************************************************
  * MTK_platform handler called when an affinity instance is about to be turned
  * on. The level and mpidr determine the affinity instance.
@@ -156,12 +206,12 @@
 	.pwr_domain_on			= plat_mtk_power_domain_on,
 	.pwr_domain_on_finish		= plat_mtk_power_domain_on_finish,
 	.pwr_domain_off			= plat_mtk_power_domain_off,
-	.pwr_domain_suspend		= NULL,
-	.pwr_domain_suspend_finish	= NULL,
+	.pwr_domain_suspend		= plat_mtk_power_domain_suspend,
+	.pwr_domain_suspend_finish	= plat_mtk_power_domain_suspend_finish,
 	.system_off			= plat_mtk_system_off,
 	.system_reset			= plat_mtk_system_reset,
 	.validate_power_state		= NULL,
-	.get_sys_suspend_power_state	= NULL,
+	.get_sys_suspend_power_state	= plat_mtk_get_sys_suspend_power_state,
 };
 
 int plat_setup_psci_ops(uintptr_t sec_entrypoint,