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,