127132f13SRex-BC Chen /*
227132f13SRex-BC Chen * Copyright (c) 2021, MediaTek Inc. All rights reserved.
327132f13SRex-BC Chen *
427132f13SRex-BC Chen * SPDX-License-Identifier: BSD-3-Clause
527132f13SRex-BC Chen */
627132f13SRex-BC Chen
71da57e54SGarmin.Chang #include <assert.h>
81da57e54SGarmin.Chang #include <arch_helpers.h>
95bc88ec6SJames Lo #include <common/debug.h>
1024dd5a7bSRex-BC Chen #include <drivers/gpio.h>
1127132f13SRex-BC Chen #include <lib/psci/psci.h>
1227132f13SRex-BC Chen
131da57e54SGarmin.Chang #include <mt_gic_v3.h>
141da57e54SGarmin.Chang #include <mtspmc.h>
151da57e54SGarmin.Chang #include <plat/common/platform.h>
16*e46e9df0SRex-BC Chen #include <plat_dfd.h>
171da57e54SGarmin.Chang #include <plat_mtk_lpm.h>
181da57e54SGarmin.Chang #include <plat_params.h>
191da57e54SGarmin.Chang #include <plat_pm.h>
20a68346a7SRex-BC Chen #include <pmic.h>
21a68346a7SRex-BC Chen #include <rtc.h>
221da57e54SGarmin.Chang
231da57e54SGarmin.Chang /*
241da57e54SGarmin.Chang * Cluster state request:
251da57e54SGarmin.Chang * [0] : The CPU requires cluster power down
261da57e54SGarmin.Chang * [1] : The CPU requires cluster power on
271da57e54SGarmin.Chang */
281da57e54SGarmin.Chang #define coordinate_cluster(onoff) write_clusterpwrdn_el1(onoff)
291da57e54SGarmin.Chang #define coordinate_cluster_pwron() coordinate_cluster(1)
301da57e54SGarmin.Chang #define coordinate_cluster_pwroff() coordinate_cluster(0)
311da57e54SGarmin.Chang
321da57e54SGarmin.Chang /* platform secure entry point */
331da57e54SGarmin.Chang static uintptr_t secure_entrypoint;
341da57e54SGarmin.Chang /* per-CPU power state */
351da57e54SGarmin.Chang static unsigned int plat_power_state[PLATFORM_CORE_COUNT];
361da57e54SGarmin.Chang
371da57e54SGarmin.Chang /* platform CPU power domain - ops */
381da57e54SGarmin.Chang static const struct mt_lpm_tz *plat_mt_pm;
391da57e54SGarmin.Chang
plat_mt_pm_invoke(int (* func)(unsigned int cpu,const psci_power_state_t * state),int cpu,const psci_power_state_t * state)401da57e54SGarmin.Chang static inline int plat_mt_pm_invoke(int (*func)(unsigned int cpu,
411da57e54SGarmin.Chang const psci_power_state_t *state),
421da57e54SGarmin.Chang int cpu, const psci_power_state_t *state)
431da57e54SGarmin.Chang {
441da57e54SGarmin.Chang int ret = -1;
451da57e54SGarmin.Chang
461da57e54SGarmin.Chang if (func != NULL) {
471da57e54SGarmin.Chang ret = func(cpu, state);
481da57e54SGarmin.Chang }
491da57e54SGarmin.Chang return ret;
501da57e54SGarmin.Chang }
511da57e54SGarmin.Chang
521da57e54SGarmin.Chang /*
531da57e54SGarmin.Chang * Common MTK_platform operations to power on/off a
541da57e54SGarmin.Chang * CPU in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
551da57e54SGarmin.Chang */
plat_cpu_pwrdwn_common(unsigned int cpu,const psci_power_state_t * state,unsigned int req_pstate)561da57e54SGarmin.Chang static void plat_cpu_pwrdwn_common(unsigned int cpu,
571da57e54SGarmin.Chang const psci_power_state_t *state, unsigned int req_pstate)
581da57e54SGarmin.Chang {
591da57e54SGarmin.Chang assert(cpu == plat_my_core_pos());
601da57e54SGarmin.Chang assert(plat_mt_pm != NULL);
611da57e54SGarmin.Chang
621da57e54SGarmin.Chang (void)plat_mt_pm_invoke(plat_mt_pm->pwr_cpu_dwn, cpu, state);
631da57e54SGarmin.Chang
641da57e54SGarmin.Chang if ((psci_get_pstate_pwrlvl(req_pstate) >= MTK_AFFLVL_CLUSTER) ||
651da57e54SGarmin.Chang (req_pstate == 0U)) { /* hotplug off */
661da57e54SGarmin.Chang coordinate_cluster_pwroff();
671da57e54SGarmin.Chang }
681da57e54SGarmin.Chang
691da57e54SGarmin.Chang /* Prevent interrupts from spuriously waking up this CPU */
701da57e54SGarmin.Chang mt_gic_rdistif_save();
711da57e54SGarmin.Chang gicv3_cpuif_disable(cpu);
721da57e54SGarmin.Chang gicv3_rdistif_off(cpu);
731da57e54SGarmin.Chang }
741da57e54SGarmin.Chang
plat_cpu_pwron_common(unsigned int cpu,const psci_power_state_t * state,unsigned int req_pstate)751da57e54SGarmin.Chang static void plat_cpu_pwron_common(unsigned int cpu,
761da57e54SGarmin.Chang const psci_power_state_t *state, unsigned int req_pstate)
771da57e54SGarmin.Chang {
781da57e54SGarmin.Chang assert(cpu == plat_my_core_pos());
791da57e54SGarmin.Chang assert(plat_mt_pm != NULL);
801da57e54SGarmin.Chang
811da57e54SGarmin.Chang (void)plat_mt_pm_invoke(plat_mt_pm->pwr_cpu_on, cpu, state);
821da57e54SGarmin.Chang
831da57e54SGarmin.Chang coordinate_cluster_pwron();
841da57e54SGarmin.Chang
851da57e54SGarmin.Chang /*
861da57e54SGarmin.Chang * If mcusys does power down before then restore
871da57e54SGarmin.Chang * all CPUs' GIC Redistributors
881da57e54SGarmin.Chang */
891da57e54SGarmin.Chang if (IS_MCUSYS_OFF_STATE(state)) {
901da57e54SGarmin.Chang mt_gic_rdistif_restore_all();
911da57e54SGarmin.Chang } else {
921da57e54SGarmin.Chang gicv3_rdistif_on(cpu);
931da57e54SGarmin.Chang gicv3_cpuif_enable(cpu);
941da57e54SGarmin.Chang mt_gic_rdistif_init();
951da57e54SGarmin.Chang mt_gic_rdistif_restore();
961da57e54SGarmin.Chang }
971da57e54SGarmin.Chang }
981da57e54SGarmin.Chang
991da57e54SGarmin.Chang /*
1001da57e54SGarmin.Chang * Common MTK_platform operations to power on/off a
1011da57e54SGarmin.Chang * cluster in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
1021da57e54SGarmin.Chang */
plat_cluster_pwrdwn_common(unsigned int cpu,const psci_power_state_t * state,unsigned int req_pstate)1031da57e54SGarmin.Chang static void plat_cluster_pwrdwn_common(unsigned int cpu,
1041da57e54SGarmin.Chang const psci_power_state_t *state, unsigned int req_pstate)
1051da57e54SGarmin.Chang {
1061da57e54SGarmin.Chang assert(cpu == plat_my_core_pos());
1071da57e54SGarmin.Chang assert(plat_mt_pm != NULL);
1081da57e54SGarmin.Chang
1091da57e54SGarmin.Chang if (plat_mt_pm_invoke(plat_mt_pm->pwr_cluster_dwn, cpu, state) != 0) {
1101da57e54SGarmin.Chang coordinate_cluster_pwron();
1111da57e54SGarmin.Chang
1121da57e54SGarmin.Chang /*
1131da57e54SGarmin.Chang * TODO:
1141da57e54SGarmin.Chang * Return on fail and add a 'return' here before
1151da57e54SGarmin.Chang * adding any code following the if-block.
1161da57e54SGarmin.Chang */
1171da57e54SGarmin.Chang }
1181da57e54SGarmin.Chang }
1191da57e54SGarmin.Chang
plat_cluster_pwron_common(unsigned int cpu,const psci_power_state_t * state,unsigned int req_pstate)1201da57e54SGarmin.Chang static void plat_cluster_pwron_common(unsigned int cpu,
1211da57e54SGarmin.Chang const psci_power_state_t *state, unsigned int req_pstate)
1221da57e54SGarmin.Chang {
1231da57e54SGarmin.Chang assert(cpu == plat_my_core_pos());
1241da57e54SGarmin.Chang assert(plat_mt_pm != NULL);
1251da57e54SGarmin.Chang
1261da57e54SGarmin.Chang if (plat_mt_pm_invoke(plat_mt_pm->pwr_cluster_on, cpu, state) != 0) {
1271da57e54SGarmin.Chang /*
1281da57e54SGarmin.Chang * TODO:
1291da57e54SGarmin.Chang * return on fail and add a 'return' here before
1301da57e54SGarmin.Chang * adding any code following the if-block.
1311da57e54SGarmin.Chang */
1321da57e54SGarmin.Chang }
1331da57e54SGarmin.Chang }
1341da57e54SGarmin.Chang
1351da57e54SGarmin.Chang /*
1361da57e54SGarmin.Chang * Common MTK_platform operations to power on/off a
1371da57e54SGarmin.Chang * mcusys in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
1381da57e54SGarmin.Chang */
plat_mcusys_pwrdwn_common(unsigned int cpu,const psci_power_state_t * state,unsigned int req_pstate)1391da57e54SGarmin.Chang static void plat_mcusys_pwrdwn_common(unsigned int cpu,
1401da57e54SGarmin.Chang const psci_power_state_t *state, unsigned int req_pstate)
1411da57e54SGarmin.Chang {
1421da57e54SGarmin.Chang assert(cpu == plat_my_core_pos());
1431da57e54SGarmin.Chang assert(plat_mt_pm != NULL);
1441da57e54SGarmin.Chang
1451da57e54SGarmin.Chang if (plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_dwn, cpu, state) != 0) {
1461da57e54SGarmin.Chang return; /* return on fail */
1471da57e54SGarmin.Chang }
1481da57e54SGarmin.Chang
1491da57e54SGarmin.Chang mt_gic_distif_save();
1501da57e54SGarmin.Chang gic_sgi_save_all();
1511da57e54SGarmin.Chang }
1521da57e54SGarmin.Chang
plat_mcusys_pwron_common(unsigned int cpu,const psci_power_state_t * state,unsigned int req_pstate)1531da57e54SGarmin.Chang static void plat_mcusys_pwron_common(unsigned int cpu,
1541da57e54SGarmin.Chang const psci_power_state_t *state, unsigned int req_pstate)
1551da57e54SGarmin.Chang {
1561da57e54SGarmin.Chang assert(cpu == plat_my_core_pos());
1571da57e54SGarmin.Chang assert(plat_mt_pm != NULL);
1581da57e54SGarmin.Chang
1591da57e54SGarmin.Chang if (plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_on, cpu, state) != 0) {
1601da57e54SGarmin.Chang /* return on fail */
1611da57e54SGarmin.Chang return;
1621da57e54SGarmin.Chang }
1631da57e54SGarmin.Chang
1641da57e54SGarmin.Chang mt_gic_init();
1651da57e54SGarmin.Chang mt_gic_distif_restore();
1661da57e54SGarmin.Chang gic_sgi_restore_all();
1671da57e54SGarmin.Chang
168*e46e9df0SRex-BC Chen dfd_resume();
169*e46e9df0SRex-BC Chen
1701da57e54SGarmin.Chang (void)plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_on_finished, cpu, state);
1711da57e54SGarmin.Chang }
1721da57e54SGarmin.Chang
1731da57e54SGarmin.Chang /* plat_psci_ops implementation */
plat_cpu_standby(plat_local_state_t cpu_state)1741da57e54SGarmin.Chang static void plat_cpu_standby(plat_local_state_t cpu_state)
1751da57e54SGarmin.Chang {
1761da57e54SGarmin.Chang uint64_t scr;
1771da57e54SGarmin.Chang
1781da57e54SGarmin.Chang scr = read_scr_el3();
1791da57e54SGarmin.Chang write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
1801da57e54SGarmin.Chang
1811da57e54SGarmin.Chang isb();
1821da57e54SGarmin.Chang dsb();
1831da57e54SGarmin.Chang wfi();
1841da57e54SGarmin.Chang
1851da57e54SGarmin.Chang write_scr_el3(scr);
1861da57e54SGarmin.Chang }
1871da57e54SGarmin.Chang
plat_power_domain_on(u_register_t mpidr)1881da57e54SGarmin.Chang static int plat_power_domain_on(u_register_t mpidr)
1891da57e54SGarmin.Chang {
1901da57e54SGarmin.Chang unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
1911da57e54SGarmin.Chang unsigned int cluster = 0U;
1921da57e54SGarmin.Chang
1931da57e54SGarmin.Chang if (cpu >= PLATFORM_CORE_COUNT) {
1941da57e54SGarmin.Chang return PSCI_E_INVALID_PARAMS;
1951da57e54SGarmin.Chang }
1961da57e54SGarmin.Chang
1971da57e54SGarmin.Chang if (!spm_get_cluster_powerstate(cluster)) {
1981da57e54SGarmin.Chang spm_poweron_cluster(cluster);
1991da57e54SGarmin.Chang }
2001da57e54SGarmin.Chang
2011da57e54SGarmin.Chang /* init CPU reset arch as AARCH64 */
2021da57e54SGarmin.Chang mcucfg_init_archstate(cluster, cpu, true);
2031da57e54SGarmin.Chang mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
2041da57e54SGarmin.Chang spm_poweron_cpu(cluster, cpu);
2051da57e54SGarmin.Chang
2061da57e54SGarmin.Chang return PSCI_E_SUCCESS;
2071da57e54SGarmin.Chang }
2081da57e54SGarmin.Chang
plat_power_domain_on_finish(const psci_power_state_t * state)2091da57e54SGarmin.Chang static void plat_power_domain_on_finish(const psci_power_state_t *state)
2101da57e54SGarmin.Chang {
2111da57e54SGarmin.Chang unsigned long mpidr = read_mpidr_el1();
2121da57e54SGarmin.Chang unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
2131da57e54SGarmin.Chang
2141da57e54SGarmin.Chang assert(cpu < PLATFORM_CORE_COUNT);
2151da57e54SGarmin.Chang
2161da57e54SGarmin.Chang /* Allow IRQs to wakeup this core in IDLE flow */
2171da57e54SGarmin.Chang mcucfg_enable_gic_wakeup(0U, cpu);
2181da57e54SGarmin.Chang
2191da57e54SGarmin.Chang if (IS_CLUSTER_OFF_STATE(state)) {
2201da57e54SGarmin.Chang plat_cluster_pwron_common(cpu, state, 0U);
2211da57e54SGarmin.Chang }
2221da57e54SGarmin.Chang
2231da57e54SGarmin.Chang plat_cpu_pwron_common(cpu, state, 0U);
2241da57e54SGarmin.Chang }
2251da57e54SGarmin.Chang
plat_power_domain_off(const psci_power_state_t * state)2261da57e54SGarmin.Chang static void plat_power_domain_off(const psci_power_state_t *state)
2271da57e54SGarmin.Chang {
2281da57e54SGarmin.Chang unsigned long mpidr = read_mpidr_el1();
2291da57e54SGarmin.Chang unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
2301da57e54SGarmin.Chang
2311da57e54SGarmin.Chang assert(cpu < PLATFORM_CORE_COUNT);
2321da57e54SGarmin.Chang
2331da57e54SGarmin.Chang plat_cpu_pwrdwn_common(cpu, state, 0U);
2341da57e54SGarmin.Chang spm_poweroff_cpu(0U, cpu);
2351da57e54SGarmin.Chang
2361da57e54SGarmin.Chang /* prevent unintended IRQs from waking up the hot-unplugged core */
2371da57e54SGarmin.Chang mcucfg_disable_gic_wakeup(0U, cpu);
2381da57e54SGarmin.Chang
2391da57e54SGarmin.Chang if (IS_CLUSTER_OFF_STATE(state)) {
2401da57e54SGarmin.Chang plat_cluster_pwrdwn_common(cpu, state, 0U);
2411da57e54SGarmin.Chang }
2421da57e54SGarmin.Chang }
2431da57e54SGarmin.Chang
plat_power_domain_suspend(const psci_power_state_t * state)2441da57e54SGarmin.Chang static void plat_power_domain_suspend(const psci_power_state_t *state)
2451da57e54SGarmin.Chang {
2461da57e54SGarmin.Chang unsigned int cpu = plat_my_core_pos();
2471da57e54SGarmin.Chang
2481da57e54SGarmin.Chang assert(cpu < PLATFORM_CORE_COUNT);
2491da57e54SGarmin.Chang assert(plat_mt_pm != NULL);
2501da57e54SGarmin.Chang
2511da57e54SGarmin.Chang (void)plat_mt_pm_invoke(plat_mt_pm->pwr_prompt, cpu, state);
2521da57e54SGarmin.Chang
2531da57e54SGarmin.Chang /* Perform the common CPU specific operations */
2541da57e54SGarmin.Chang plat_cpu_pwrdwn_common(cpu, state, plat_power_state[cpu]);
2551da57e54SGarmin.Chang
2561da57e54SGarmin.Chang if (IS_CLUSTER_OFF_STATE(state)) {
2571da57e54SGarmin.Chang /* Perform the common cluster specific operations */
2581da57e54SGarmin.Chang plat_cluster_pwrdwn_common(cpu, state, plat_power_state[cpu]);
2591da57e54SGarmin.Chang }
2601da57e54SGarmin.Chang
2611da57e54SGarmin.Chang if (IS_MCUSYS_OFF_STATE(state)) {
2621da57e54SGarmin.Chang /* Perform the common mcusys specific operations */
2631da57e54SGarmin.Chang plat_mcusys_pwrdwn_common(cpu, state, plat_power_state[cpu]);
2641da57e54SGarmin.Chang }
2651da57e54SGarmin.Chang }
2661da57e54SGarmin.Chang
plat_power_domain_suspend_finish(const psci_power_state_t * state)2671da57e54SGarmin.Chang static void plat_power_domain_suspend_finish(const psci_power_state_t *state)
2681da57e54SGarmin.Chang {
2691da57e54SGarmin.Chang unsigned int cpu = plat_my_core_pos();
2701da57e54SGarmin.Chang
2711da57e54SGarmin.Chang assert(cpu < PLATFORM_CORE_COUNT);
2721da57e54SGarmin.Chang assert(plat_mt_pm != NULL);
2731da57e54SGarmin.Chang
2741da57e54SGarmin.Chang if (IS_MCUSYS_OFF_STATE(state)) {
2751da57e54SGarmin.Chang /* Perform the common mcusys specific operations */
2761da57e54SGarmin.Chang plat_mcusys_pwron_common(cpu, state, plat_power_state[cpu]);
2771da57e54SGarmin.Chang }
2781da57e54SGarmin.Chang
2791da57e54SGarmin.Chang if (IS_CLUSTER_OFF_STATE(state)) {
2801da57e54SGarmin.Chang /* Perform the common cluster specific operations */
2811da57e54SGarmin.Chang plat_cluster_pwron_common(cpu, state, plat_power_state[cpu]);
2821da57e54SGarmin.Chang }
2831da57e54SGarmin.Chang
2841da57e54SGarmin.Chang /* Perform the common CPU specific operations */
2851da57e54SGarmin.Chang plat_cpu_pwron_common(cpu, state, plat_power_state[cpu]);
2861da57e54SGarmin.Chang
2871da57e54SGarmin.Chang (void)plat_mt_pm_invoke(plat_mt_pm->pwr_reflect, cpu, state);
2881da57e54SGarmin.Chang }
2891da57e54SGarmin.Chang
plat_validate_power_state(unsigned int power_state,psci_power_state_t * req_state)2901da57e54SGarmin.Chang static int plat_validate_power_state(unsigned int power_state,
2911da57e54SGarmin.Chang psci_power_state_t *req_state)
2921da57e54SGarmin.Chang {
2931da57e54SGarmin.Chang unsigned int pstate = psci_get_pstate_type(power_state);
2941da57e54SGarmin.Chang unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state);
2951da57e54SGarmin.Chang unsigned int cpu = plat_my_core_pos();
2961da57e54SGarmin.Chang
2971da57e54SGarmin.Chang if (aff_lvl > PLAT_MAX_PWR_LVL) {
2981da57e54SGarmin.Chang return PSCI_E_INVALID_PARAMS;
2991da57e54SGarmin.Chang }
3001da57e54SGarmin.Chang
3011da57e54SGarmin.Chang if (pstate == PSTATE_TYPE_STANDBY) {
3021da57e54SGarmin.Chang req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE;
3031da57e54SGarmin.Chang } else {
3041da57e54SGarmin.Chang unsigned int i;
3051da57e54SGarmin.Chang unsigned int pstate_id = psci_get_pstate_id(power_state);
3061da57e54SGarmin.Chang plat_local_state_t s = MTK_LOCAL_STATE_OFF;
3071da57e54SGarmin.Chang
3081da57e54SGarmin.Chang /* Use pstate_id to be power domain state */
3091da57e54SGarmin.Chang if (pstate_id > s) {
3101da57e54SGarmin.Chang s = (plat_local_state_t)pstate_id;
3111da57e54SGarmin.Chang }
3121da57e54SGarmin.Chang
3131da57e54SGarmin.Chang for (i = 0U; i <= aff_lvl; i++) {
3141da57e54SGarmin.Chang req_state->pwr_domain_state[i] = s;
3151da57e54SGarmin.Chang }
3161da57e54SGarmin.Chang }
3171da57e54SGarmin.Chang
3181da57e54SGarmin.Chang plat_power_state[cpu] = power_state;
3191da57e54SGarmin.Chang return PSCI_E_SUCCESS;
3201da57e54SGarmin.Chang }
3211da57e54SGarmin.Chang
plat_get_sys_suspend_power_state(psci_power_state_t * req_state)3221da57e54SGarmin.Chang static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state)
3231da57e54SGarmin.Chang {
3241da57e54SGarmin.Chang unsigned int lv;
3251da57e54SGarmin.Chang unsigned int cpu = plat_my_core_pos();
3261da57e54SGarmin.Chang
3271da57e54SGarmin.Chang for (lv = PSCI_CPU_PWR_LVL; lv <= PLAT_MAX_PWR_LVL; lv++) {
3281da57e54SGarmin.Chang req_state->pwr_domain_state[lv] = PLAT_MAX_OFF_STATE;
3291da57e54SGarmin.Chang }
3301da57e54SGarmin.Chang
3311da57e54SGarmin.Chang plat_power_state[cpu] =
3321da57e54SGarmin.Chang psci_make_powerstate(
3331da57e54SGarmin.Chang MT_PLAT_PWR_STATE_SYSTEM_SUSPEND,
3341da57e54SGarmin.Chang PSTATE_TYPE_POWERDOWN, PLAT_MAX_PWR_LVL);
3351da57e54SGarmin.Chang
3361da57e54SGarmin.Chang flush_dcache_range((uintptr_t)
3371da57e54SGarmin.Chang &plat_power_state[cpu],
3381da57e54SGarmin.Chang sizeof(plat_power_state[cpu]));
3391da57e54SGarmin.Chang }
3401da57e54SGarmin.Chang
34124dd5a7bSRex-BC Chen /*******************************************************************************
34224dd5a7bSRex-BC Chen * MTK handlers to shutdown/reboot the system
34324dd5a7bSRex-BC Chen ******************************************************************************/
plat_mtk_system_reset(void)34424dd5a7bSRex-BC Chen static void __dead2 plat_mtk_system_reset(void)
34524dd5a7bSRex-BC Chen {
34624dd5a7bSRex-BC Chen struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset();
34724dd5a7bSRex-BC Chen
34824dd5a7bSRex-BC Chen INFO("MTK System Reset\n");
34924dd5a7bSRex-BC Chen
35024dd5a7bSRex-BC Chen gpio_set_value(gpio_reset->index, gpio_reset->polarity);
35124dd5a7bSRex-BC Chen
35224dd5a7bSRex-BC Chen wfi();
35324dd5a7bSRex-BC Chen ERROR("MTK System Reset: operation not handled.\n");
35424dd5a7bSRex-BC Chen panic();
35524dd5a7bSRex-BC Chen }
35624dd5a7bSRex-BC Chen
plat_mtk_system_off(void)357a68346a7SRex-BC Chen static void __dead2 plat_mtk_system_off(void)
358a68346a7SRex-BC Chen {
359a68346a7SRex-BC Chen INFO("MTK System Off\n");
360a68346a7SRex-BC Chen
361a68346a7SRex-BC Chen rtc_power_off_sequence();
362a68346a7SRex-BC Chen pmic_power_off();
363a68346a7SRex-BC Chen
364a68346a7SRex-BC Chen wfi();
365a68346a7SRex-BC Chen ERROR("MTK System Off: operation not handled.\n");
366a68346a7SRex-BC Chen panic();
367a68346a7SRex-BC Chen }
368a68346a7SRex-BC Chen
36927132f13SRex-BC Chen static const plat_psci_ops_t plat_psci_ops = {
3701da57e54SGarmin.Chang .cpu_standby = plat_cpu_standby,
3711da57e54SGarmin.Chang .pwr_domain_on = plat_power_domain_on,
3721da57e54SGarmin.Chang .pwr_domain_on_finish = plat_power_domain_on_finish,
3731da57e54SGarmin.Chang .pwr_domain_off = plat_power_domain_off,
3741da57e54SGarmin.Chang .pwr_domain_suspend = plat_power_domain_suspend,
3751da57e54SGarmin.Chang .pwr_domain_suspend_finish = plat_power_domain_suspend_finish,
3761da57e54SGarmin.Chang .validate_power_state = plat_validate_power_state,
377a68346a7SRex-BC Chen .get_sys_suspend_power_state = plat_get_sys_suspend_power_state,
378a68346a7SRex-BC Chen .system_off = plat_mtk_system_off,
37924dd5a7bSRex-BC Chen .system_reset = plat_mtk_system_reset,
38027132f13SRex-BC Chen };
38127132f13SRex-BC Chen
plat_setup_psci_ops(uintptr_t sec_entrypoint,const plat_psci_ops_t ** psci_ops)38227132f13SRex-BC Chen int plat_setup_psci_ops(uintptr_t sec_entrypoint,
38327132f13SRex-BC Chen const plat_psci_ops_t **psci_ops)
38427132f13SRex-BC Chen {
38527132f13SRex-BC Chen *psci_ops = &plat_psci_ops;
3861da57e54SGarmin.Chang secure_entrypoint = sec_entrypoint;
3871da57e54SGarmin.Chang
3881da57e54SGarmin.Chang /*
3891da57e54SGarmin.Chang * init the warm reset config for boot CPU
3901da57e54SGarmin.Chang * reset arch as AARCH64
3911da57e54SGarmin.Chang * reset addr as function bl31_warm_entrypoint()
3921da57e54SGarmin.Chang */
3931da57e54SGarmin.Chang mcucfg_init_archstate(0U, 0U, true);
3941da57e54SGarmin.Chang mcucfg_set_bootaddr(0U, 0U, secure_entrypoint);
3951da57e54SGarmin.Chang
3961da57e54SGarmin.Chang spmc_init();
39706cb65efSGarmin.Chang plat_mt_pm = mt_plat_cpu_pm_init();
39827132f13SRex-BC Chen
39927132f13SRex-BC Chen return 0;
40027132f13SRex-BC Chen }
401