xref: /rk3399_ARM-atf/plat/mediatek/mt8186/plat_pm.c (revision 06cb65ef079941d0525dca75dd0e110e9330906d)
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 /* common headers */
81da57e54SGarmin.Chang #include <assert.h>
91da57e54SGarmin.Chang 
101da57e54SGarmin.Chang #include <arch_helpers.h>
115bc88ec6SJames Lo #include <common/debug.h>
1227132f13SRex-BC Chen #include <lib/psci/psci.h>
1327132f13SRex-BC Chen 
141da57e54SGarmin.Chang /* platform specific headers */
151da57e54SGarmin.Chang #include <mt_gic_v3.h>
161da57e54SGarmin.Chang #include <mtspmc.h>
171da57e54SGarmin.Chang #include <plat/common/platform.h>
181da57e54SGarmin.Chang #include <plat_mtk_lpm.h>
191da57e54SGarmin.Chang #include <plat_params.h>
201da57e54SGarmin.Chang #include <plat_pm.h>
211da57e54SGarmin.Chang 
221da57e54SGarmin.Chang /*
231da57e54SGarmin.Chang  * Cluster state request:
241da57e54SGarmin.Chang  * [0] : The CPU requires cluster power down
251da57e54SGarmin.Chang  * [1] : The CPU requires cluster power on
261da57e54SGarmin.Chang  */
271da57e54SGarmin.Chang #define coordinate_cluster(onoff)	write_clusterpwrdn_el1(onoff)
281da57e54SGarmin.Chang #define coordinate_cluster_pwron()	coordinate_cluster(1)
291da57e54SGarmin.Chang #define coordinate_cluster_pwroff()	coordinate_cluster(0)
301da57e54SGarmin.Chang 
311da57e54SGarmin.Chang /* platform secure entry point */
321da57e54SGarmin.Chang static uintptr_t secure_entrypoint;
331da57e54SGarmin.Chang /* per-CPU power state */
341da57e54SGarmin.Chang static unsigned int plat_power_state[PLATFORM_CORE_COUNT];
351da57e54SGarmin.Chang 
361da57e54SGarmin.Chang /* platform CPU power domain - ops */
371da57e54SGarmin.Chang static const struct mt_lpm_tz *plat_mt_pm;
381da57e54SGarmin.Chang 
391da57e54SGarmin.Chang static inline int plat_mt_pm_invoke(int (*func)(unsigned int cpu,
401da57e54SGarmin.Chang 						const psci_power_state_t *state),
411da57e54SGarmin.Chang 				    int cpu, const psci_power_state_t *state)
421da57e54SGarmin.Chang {
431da57e54SGarmin.Chang 	int ret = -1;
441da57e54SGarmin.Chang 
451da57e54SGarmin.Chang 	if (func != NULL) {
461da57e54SGarmin.Chang 		ret = func(cpu, state);
471da57e54SGarmin.Chang 	}
481da57e54SGarmin.Chang 	return ret;
491da57e54SGarmin.Chang }
501da57e54SGarmin.Chang 
511da57e54SGarmin.Chang /*
521da57e54SGarmin.Chang  * Common MTK_platform operations to power on/off a
531da57e54SGarmin.Chang  * CPU in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
541da57e54SGarmin.Chang  */
551da57e54SGarmin.Chang static void plat_cpu_pwrdwn_common(unsigned int cpu,
561da57e54SGarmin.Chang 		const psci_power_state_t *state, unsigned int req_pstate)
571da57e54SGarmin.Chang {
581da57e54SGarmin.Chang 	assert(cpu == plat_my_core_pos());
591da57e54SGarmin.Chang 	assert(plat_mt_pm != NULL);
601da57e54SGarmin.Chang 
611da57e54SGarmin.Chang 	(void)plat_mt_pm_invoke(plat_mt_pm->pwr_cpu_dwn, cpu, state);
621da57e54SGarmin.Chang 
631da57e54SGarmin.Chang 	if ((psci_get_pstate_pwrlvl(req_pstate) >= MTK_AFFLVL_CLUSTER) ||
641da57e54SGarmin.Chang 			(req_pstate == 0U)) { /* hotplug off */
651da57e54SGarmin.Chang 		coordinate_cluster_pwroff();
661da57e54SGarmin.Chang 	}
671da57e54SGarmin.Chang 
681da57e54SGarmin.Chang 	/* Prevent interrupts from spuriously waking up this CPU */
691da57e54SGarmin.Chang 	mt_gic_rdistif_save();
701da57e54SGarmin.Chang 	gicv3_cpuif_disable(cpu);
711da57e54SGarmin.Chang 	gicv3_rdistif_off(cpu);
721da57e54SGarmin.Chang }
731da57e54SGarmin.Chang 
741da57e54SGarmin.Chang static void plat_cpu_pwron_common(unsigned int cpu,
751da57e54SGarmin.Chang 		const psci_power_state_t *state, unsigned int req_pstate)
761da57e54SGarmin.Chang {
771da57e54SGarmin.Chang 	assert(cpu == plat_my_core_pos());
781da57e54SGarmin.Chang 	assert(plat_mt_pm != NULL);
791da57e54SGarmin.Chang 
801da57e54SGarmin.Chang 	(void)plat_mt_pm_invoke(plat_mt_pm->pwr_cpu_on, cpu, state);
811da57e54SGarmin.Chang 
821da57e54SGarmin.Chang 	coordinate_cluster_pwron();
831da57e54SGarmin.Chang 
841da57e54SGarmin.Chang 	/*
851da57e54SGarmin.Chang 	 * If mcusys does power down before then restore
861da57e54SGarmin.Chang 	 * all CPUs' GIC Redistributors
871da57e54SGarmin.Chang 	 */
881da57e54SGarmin.Chang 	if (IS_MCUSYS_OFF_STATE(state)) {
891da57e54SGarmin.Chang 		mt_gic_rdistif_restore_all();
901da57e54SGarmin.Chang 	} else {
911da57e54SGarmin.Chang 		gicv3_rdistif_on(cpu);
921da57e54SGarmin.Chang 		gicv3_cpuif_enable(cpu);
931da57e54SGarmin.Chang 		mt_gic_rdistif_init();
941da57e54SGarmin.Chang 		mt_gic_rdistif_restore();
951da57e54SGarmin.Chang 	}
961da57e54SGarmin.Chang }
971da57e54SGarmin.Chang 
981da57e54SGarmin.Chang /*
991da57e54SGarmin.Chang  * Common MTK_platform operations to power on/off a
1001da57e54SGarmin.Chang  * cluster in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
1011da57e54SGarmin.Chang  */
1021da57e54SGarmin.Chang static void plat_cluster_pwrdwn_common(unsigned int cpu,
1031da57e54SGarmin.Chang 		const psci_power_state_t *state, unsigned int req_pstate)
1041da57e54SGarmin.Chang {
1051da57e54SGarmin.Chang 	assert(cpu == plat_my_core_pos());
1061da57e54SGarmin.Chang 	assert(plat_mt_pm != NULL);
1071da57e54SGarmin.Chang 
1081da57e54SGarmin.Chang 	if (plat_mt_pm_invoke(plat_mt_pm->pwr_cluster_dwn, cpu, state) != 0) {
1091da57e54SGarmin.Chang 		coordinate_cluster_pwron();
1101da57e54SGarmin.Chang 
1111da57e54SGarmin.Chang 		/*
1121da57e54SGarmin.Chang 		 * TODO:
1131da57e54SGarmin.Chang 		 * Return on fail and add a 'return' here before
1141da57e54SGarmin.Chang 		 * adding any code following the if-block.
1151da57e54SGarmin.Chang 		 */
1161da57e54SGarmin.Chang 	}
1171da57e54SGarmin.Chang }
1181da57e54SGarmin.Chang 
1191da57e54SGarmin.Chang static void plat_cluster_pwron_common(unsigned int cpu,
1201da57e54SGarmin.Chang 		const psci_power_state_t *state, unsigned int req_pstate)
1211da57e54SGarmin.Chang {
1221da57e54SGarmin.Chang 	assert(cpu == plat_my_core_pos());
1231da57e54SGarmin.Chang 	assert(plat_mt_pm != NULL);
1241da57e54SGarmin.Chang 
1251da57e54SGarmin.Chang 	if (plat_mt_pm_invoke(plat_mt_pm->pwr_cluster_on, cpu, state) != 0) {
1261da57e54SGarmin.Chang 		/*
1271da57e54SGarmin.Chang 		 * TODO:
1281da57e54SGarmin.Chang 		 * return on fail and add a 'return' here before
1291da57e54SGarmin.Chang 		 * adding any code following the if-block.
1301da57e54SGarmin.Chang 		 */
1311da57e54SGarmin.Chang 	}
1321da57e54SGarmin.Chang }
1331da57e54SGarmin.Chang 
1341da57e54SGarmin.Chang /*
1351da57e54SGarmin.Chang  * Common MTK_platform operations to power on/off a
1361da57e54SGarmin.Chang  * mcusys in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
1371da57e54SGarmin.Chang  */
1381da57e54SGarmin.Chang static void plat_mcusys_pwrdwn_common(unsigned int cpu,
1391da57e54SGarmin.Chang 		const psci_power_state_t *state, unsigned int req_pstate)
1401da57e54SGarmin.Chang {
1411da57e54SGarmin.Chang 	assert(cpu == plat_my_core_pos());
1421da57e54SGarmin.Chang 	assert(plat_mt_pm != NULL);
1431da57e54SGarmin.Chang 
1441da57e54SGarmin.Chang 	if (plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_dwn, cpu, state) != 0) {
1451da57e54SGarmin.Chang 		return;		/* return on fail */
1461da57e54SGarmin.Chang 	}
1471da57e54SGarmin.Chang 
1481da57e54SGarmin.Chang 	mt_gic_distif_save();
1491da57e54SGarmin.Chang 	gic_sgi_save_all();
1501da57e54SGarmin.Chang }
1511da57e54SGarmin.Chang 
1521da57e54SGarmin.Chang static void plat_mcusys_pwron_common(unsigned int cpu,
1531da57e54SGarmin.Chang 		const psci_power_state_t *state, unsigned int req_pstate)
1541da57e54SGarmin.Chang {
1551da57e54SGarmin.Chang 	assert(cpu == plat_my_core_pos());
1561da57e54SGarmin.Chang 	assert(plat_mt_pm != NULL);
1571da57e54SGarmin.Chang 
1581da57e54SGarmin.Chang 	if (plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_on, cpu, state) != 0) {
1591da57e54SGarmin.Chang 		/* return on fail */
1601da57e54SGarmin.Chang 		return;
1611da57e54SGarmin.Chang 	}
1621da57e54SGarmin.Chang 
1631da57e54SGarmin.Chang 	mt_gic_init();
1641da57e54SGarmin.Chang 	mt_gic_distif_restore();
1651da57e54SGarmin.Chang 	gic_sgi_restore_all();
1661da57e54SGarmin.Chang 
1671da57e54SGarmin.Chang 	(void)plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_on_finished, cpu, state);
1681da57e54SGarmin.Chang }
1691da57e54SGarmin.Chang 
1701da57e54SGarmin.Chang /* plat_psci_ops implementation */
1711da57e54SGarmin.Chang static void plat_cpu_standby(plat_local_state_t cpu_state)
1721da57e54SGarmin.Chang {
1731da57e54SGarmin.Chang 	uint64_t scr;
1741da57e54SGarmin.Chang 
1751da57e54SGarmin.Chang 	scr = read_scr_el3();
1761da57e54SGarmin.Chang 	write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
1771da57e54SGarmin.Chang 
1781da57e54SGarmin.Chang 	isb();
1791da57e54SGarmin.Chang 	dsb();
1801da57e54SGarmin.Chang 	wfi();
1811da57e54SGarmin.Chang 
1821da57e54SGarmin.Chang 	write_scr_el3(scr);
1831da57e54SGarmin.Chang }
1841da57e54SGarmin.Chang 
1851da57e54SGarmin.Chang static int plat_power_domain_on(u_register_t mpidr)
1861da57e54SGarmin.Chang {
1871da57e54SGarmin.Chang 	unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
1881da57e54SGarmin.Chang 	unsigned int cluster = 0U;
1891da57e54SGarmin.Chang 
1901da57e54SGarmin.Chang 	if (cpu >= PLATFORM_CORE_COUNT) {
1911da57e54SGarmin.Chang 		return PSCI_E_INVALID_PARAMS;
1921da57e54SGarmin.Chang 	}
1931da57e54SGarmin.Chang 
1941da57e54SGarmin.Chang 	if (!spm_get_cluster_powerstate(cluster)) {
1951da57e54SGarmin.Chang 		spm_poweron_cluster(cluster);
1961da57e54SGarmin.Chang 	}
1971da57e54SGarmin.Chang 
1981da57e54SGarmin.Chang 	/* init CPU reset arch as AARCH64 */
1991da57e54SGarmin.Chang 	mcucfg_init_archstate(cluster, cpu, true);
2001da57e54SGarmin.Chang 	mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
2011da57e54SGarmin.Chang 	spm_poweron_cpu(cluster, cpu);
2021da57e54SGarmin.Chang 
2031da57e54SGarmin.Chang 	return PSCI_E_SUCCESS;
2041da57e54SGarmin.Chang }
2051da57e54SGarmin.Chang 
2061da57e54SGarmin.Chang static void plat_power_domain_on_finish(const psci_power_state_t *state)
2071da57e54SGarmin.Chang {
2081da57e54SGarmin.Chang 	unsigned long mpidr = read_mpidr_el1();
2091da57e54SGarmin.Chang 	unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
2101da57e54SGarmin.Chang 
2111da57e54SGarmin.Chang 	assert(cpu < PLATFORM_CORE_COUNT);
2121da57e54SGarmin.Chang 
2131da57e54SGarmin.Chang 	/* Allow IRQs to wakeup this core in IDLE flow */
2141da57e54SGarmin.Chang 	mcucfg_enable_gic_wakeup(0U, cpu);
2151da57e54SGarmin.Chang 
2161da57e54SGarmin.Chang 	if (IS_CLUSTER_OFF_STATE(state)) {
2171da57e54SGarmin.Chang 		plat_cluster_pwron_common(cpu, state, 0U);
2181da57e54SGarmin.Chang 	}
2191da57e54SGarmin.Chang 
2201da57e54SGarmin.Chang 	plat_cpu_pwron_common(cpu, state, 0U);
2211da57e54SGarmin.Chang }
2221da57e54SGarmin.Chang 
2231da57e54SGarmin.Chang static void plat_power_domain_off(const psci_power_state_t *state)
2241da57e54SGarmin.Chang {
2251da57e54SGarmin.Chang 	unsigned long mpidr = read_mpidr_el1();
2261da57e54SGarmin.Chang 	unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
2271da57e54SGarmin.Chang 
2281da57e54SGarmin.Chang 	assert(cpu < PLATFORM_CORE_COUNT);
2291da57e54SGarmin.Chang 
2301da57e54SGarmin.Chang 	plat_cpu_pwrdwn_common(cpu, state, 0U);
2311da57e54SGarmin.Chang 	spm_poweroff_cpu(0U, cpu);
2321da57e54SGarmin.Chang 
2331da57e54SGarmin.Chang 	/* prevent unintended IRQs from waking up the hot-unplugged core */
2341da57e54SGarmin.Chang 	mcucfg_disable_gic_wakeup(0U, cpu);
2351da57e54SGarmin.Chang 
2361da57e54SGarmin.Chang 	if (IS_CLUSTER_OFF_STATE(state)) {
2371da57e54SGarmin.Chang 		plat_cluster_pwrdwn_common(cpu, state, 0U);
2381da57e54SGarmin.Chang 	}
2391da57e54SGarmin.Chang }
2401da57e54SGarmin.Chang 
2411da57e54SGarmin.Chang static void plat_power_domain_suspend(const psci_power_state_t *state)
2421da57e54SGarmin.Chang {
2431da57e54SGarmin.Chang 	unsigned int cpu = plat_my_core_pos();
2441da57e54SGarmin.Chang 
2451da57e54SGarmin.Chang 	assert(cpu < PLATFORM_CORE_COUNT);
2461da57e54SGarmin.Chang 	assert(plat_mt_pm != NULL);
2471da57e54SGarmin.Chang 
2481da57e54SGarmin.Chang 	(void)plat_mt_pm_invoke(plat_mt_pm->pwr_prompt, cpu, state);
2491da57e54SGarmin.Chang 
2501da57e54SGarmin.Chang 	/* Perform the common CPU specific operations */
2511da57e54SGarmin.Chang 	plat_cpu_pwrdwn_common(cpu, state, plat_power_state[cpu]);
2521da57e54SGarmin.Chang 
2531da57e54SGarmin.Chang 	if (IS_CLUSTER_OFF_STATE(state)) {
2541da57e54SGarmin.Chang 		/* Perform the common cluster specific operations */
2551da57e54SGarmin.Chang 		plat_cluster_pwrdwn_common(cpu, state, plat_power_state[cpu]);
2561da57e54SGarmin.Chang 	}
2571da57e54SGarmin.Chang 
2581da57e54SGarmin.Chang 	if (IS_MCUSYS_OFF_STATE(state)) {
2591da57e54SGarmin.Chang 		/* Perform the common mcusys specific operations */
2601da57e54SGarmin.Chang 		plat_mcusys_pwrdwn_common(cpu, state, plat_power_state[cpu]);
2611da57e54SGarmin.Chang 	}
2621da57e54SGarmin.Chang }
2631da57e54SGarmin.Chang 
2641da57e54SGarmin.Chang static void plat_power_domain_suspend_finish(const psci_power_state_t *state)
2651da57e54SGarmin.Chang {
2661da57e54SGarmin.Chang 	unsigned int cpu = plat_my_core_pos();
2671da57e54SGarmin.Chang 
2681da57e54SGarmin.Chang 	assert(cpu < PLATFORM_CORE_COUNT);
2691da57e54SGarmin.Chang 	assert(plat_mt_pm != NULL);
2701da57e54SGarmin.Chang 
2711da57e54SGarmin.Chang 	if (IS_MCUSYS_OFF_STATE(state)) {
2721da57e54SGarmin.Chang 		/* Perform the common mcusys specific operations */
2731da57e54SGarmin.Chang 		plat_mcusys_pwron_common(cpu, state, plat_power_state[cpu]);
2741da57e54SGarmin.Chang 	}
2751da57e54SGarmin.Chang 
2761da57e54SGarmin.Chang 	if (IS_CLUSTER_OFF_STATE(state)) {
2771da57e54SGarmin.Chang 		/* Perform the common cluster specific operations */
2781da57e54SGarmin.Chang 		plat_cluster_pwron_common(cpu, state, plat_power_state[cpu]);
2791da57e54SGarmin.Chang 	}
2801da57e54SGarmin.Chang 
2811da57e54SGarmin.Chang 	/* Perform the common CPU specific operations */
2821da57e54SGarmin.Chang 	plat_cpu_pwron_common(cpu, state, plat_power_state[cpu]);
2831da57e54SGarmin.Chang 
2841da57e54SGarmin.Chang 	(void)plat_mt_pm_invoke(plat_mt_pm->pwr_reflect, cpu, state);
2851da57e54SGarmin.Chang }
2861da57e54SGarmin.Chang 
2871da57e54SGarmin.Chang static int plat_validate_power_state(unsigned int power_state,
2881da57e54SGarmin.Chang 					psci_power_state_t *req_state)
2891da57e54SGarmin.Chang {
2901da57e54SGarmin.Chang 	unsigned int pstate = psci_get_pstate_type(power_state);
2911da57e54SGarmin.Chang 	unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state);
2921da57e54SGarmin.Chang 	unsigned int cpu = plat_my_core_pos();
2931da57e54SGarmin.Chang 
2941da57e54SGarmin.Chang 	if (aff_lvl > PLAT_MAX_PWR_LVL) {
2951da57e54SGarmin.Chang 		return PSCI_E_INVALID_PARAMS;
2961da57e54SGarmin.Chang 	}
2971da57e54SGarmin.Chang 
2981da57e54SGarmin.Chang 	if (pstate == PSTATE_TYPE_STANDBY) {
2991da57e54SGarmin.Chang 		req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE;
3001da57e54SGarmin.Chang 	} else {
3011da57e54SGarmin.Chang 		unsigned int i;
3021da57e54SGarmin.Chang 		unsigned int pstate_id = psci_get_pstate_id(power_state);
3031da57e54SGarmin.Chang 		plat_local_state_t s = MTK_LOCAL_STATE_OFF;
3041da57e54SGarmin.Chang 
3051da57e54SGarmin.Chang 		/* Use pstate_id to be power domain state */
3061da57e54SGarmin.Chang 		if (pstate_id > s) {
3071da57e54SGarmin.Chang 			s = (plat_local_state_t)pstate_id;
3081da57e54SGarmin.Chang 		}
3091da57e54SGarmin.Chang 
3101da57e54SGarmin.Chang 		for (i = 0U; i <= aff_lvl; i++) {
3111da57e54SGarmin.Chang 			req_state->pwr_domain_state[i] = s;
3121da57e54SGarmin.Chang 		}
3131da57e54SGarmin.Chang 	}
3141da57e54SGarmin.Chang 
3151da57e54SGarmin.Chang 	plat_power_state[cpu] = power_state;
3161da57e54SGarmin.Chang 	return PSCI_E_SUCCESS;
3171da57e54SGarmin.Chang }
3181da57e54SGarmin.Chang 
3191da57e54SGarmin.Chang static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state)
3201da57e54SGarmin.Chang {
3211da57e54SGarmin.Chang 	unsigned int lv;
3221da57e54SGarmin.Chang 	unsigned int cpu = plat_my_core_pos();
3231da57e54SGarmin.Chang 
3241da57e54SGarmin.Chang 	for (lv = PSCI_CPU_PWR_LVL; lv <= PLAT_MAX_PWR_LVL; lv++) {
3251da57e54SGarmin.Chang 		req_state->pwr_domain_state[lv] = PLAT_MAX_OFF_STATE;
3261da57e54SGarmin.Chang 	}
3271da57e54SGarmin.Chang 
3281da57e54SGarmin.Chang 	plat_power_state[cpu] =
3291da57e54SGarmin.Chang 			psci_make_powerstate(
3301da57e54SGarmin.Chang 				MT_PLAT_PWR_STATE_SYSTEM_SUSPEND,
3311da57e54SGarmin.Chang 				PSTATE_TYPE_POWERDOWN, PLAT_MAX_PWR_LVL);
3321da57e54SGarmin.Chang 
3331da57e54SGarmin.Chang 	flush_dcache_range((uintptr_t)
3341da57e54SGarmin.Chang 			&plat_power_state[cpu],
3351da57e54SGarmin.Chang 			sizeof(plat_power_state[cpu]));
3361da57e54SGarmin.Chang }
3371da57e54SGarmin.Chang 
33827132f13SRex-BC Chen static const plat_psci_ops_t plat_psci_ops = {
3391da57e54SGarmin.Chang 	.cpu_standby			= plat_cpu_standby,
3401da57e54SGarmin.Chang 	.pwr_domain_on			= plat_power_domain_on,
3411da57e54SGarmin.Chang 	.pwr_domain_on_finish		= plat_power_domain_on_finish,
3421da57e54SGarmin.Chang 	.pwr_domain_off			= plat_power_domain_off,
3431da57e54SGarmin.Chang 	.pwr_domain_suspend		= plat_power_domain_suspend,
3441da57e54SGarmin.Chang 	.pwr_domain_suspend_finish	= plat_power_domain_suspend_finish,
3451da57e54SGarmin.Chang 	.validate_power_state		= plat_validate_power_state,
3461da57e54SGarmin.Chang 	.get_sys_suspend_power_state	= plat_get_sys_suspend_power_state
34727132f13SRex-BC Chen };
34827132f13SRex-BC Chen 
34927132f13SRex-BC Chen int plat_setup_psci_ops(uintptr_t sec_entrypoint,
35027132f13SRex-BC Chen 			const plat_psci_ops_t **psci_ops)
35127132f13SRex-BC Chen {
35227132f13SRex-BC Chen 	*psci_ops = &plat_psci_ops;
3531da57e54SGarmin.Chang 	secure_entrypoint = sec_entrypoint;
3541da57e54SGarmin.Chang 
3551da57e54SGarmin.Chang 	/*
3561da57e54SGarmin.Chang 	 * init the warm reset config for boot CPU
3571da57e54SGarmin.Chang 	 * reset arch as AARCH64
3581da57e54SGarmin.Chang 	 * reset addr as function bl31_warm_entrypoint()
3591da57e54SGarmin.Chang 	 */
3601da57e54SGarmin.Chang 	mcucfg_init_archstate(0U, 0U, true);
3611da57e54SGarmin.Chang 	mcucfg_set_bootaddr(0U, 0U, secure_entrypoint);
3621da57e54SGarmin.Chang 
3631da57e54SGarmin.Chang 	spmc_init();
364*06cb65efSGarmin.Chang 	plat_mt_pm = mt_plat_cpu_pm_init();
36527132f13SRex-BC Chen 
36627132f13SRex-BC Chen 	return 0;
36727132f13SRex-BC Chen }
368