xref: /rk3399_ARM-atf/plat/rockchip/common/plat_pm.c (revision f32ab4445a669cb44d51c97f388bb363ad22b824)
16fba6e04STony Xie /*
26fba6e04STony Xie  * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
36fba6e04STony Xie  *
46fba6e04STony Xie  * Redistribution and use in source and binary forms, with or without
56fba6e04STony Xie  * modification, are permitted provided that the following conditions are met:
66fba6e04STony Xie  *
76fba6e04STony Xie  * Redistributions of source code must retain the above copyright notice, this
86fba6e04STony Xie  * list of conditions and the following disclaimer.
96fba6e04STony Xie  *
106fba6e04STony Xie  * Redistributions in binary form must reproduce the above copyright notice,
116fba6e04STony Xie  * this list of conditions and the following disclaimer in the documentation
126fba6e04STony Xie  * and/or other materials provided with the distribution.
136fba6e04STony Xie  *
146fba6e04STony Xie  * Neither the name of ARM nor the names of its contributors may be used
156fba6e04STony Xie  * to endorse or promote products derived from this software without specific
166fba6e04STony Xie  * prior written permission.
176fba6e04STony Xie  *
186fba6e04STony Xie  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
196fba6e04STony Xie  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
206fba6e04STony Xie  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
216fba6e04STony Xie  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
226fba6e04STony Xie  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
236fba6e04STony Xie  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
246fba6e04STony Xie  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
256fba6e04STony Xie  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
266fba6e04STony Xie  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
276fba6e04STony Xie  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
286fba6e04STony Xie  * POSSIBILITY OF SUCH DAMAGE.
296fba6e04STony Xie  */
306fba6e04STony Xie 
316fba6e04STony Xie #include <arch_helpers.h>
326fba6e04STony Xie #include <assert.h>
336fba6e04STony Xie #include <console.h>
346fba6e04STony Xie #include <errno.h>
356fba6e04STony Xie #include <debug.h>
366fba6e04STony Xie #include <psci.h>
376fba6e04STony Xie #include <delay_timer.h>
386fba6e04STony Xie #include <platform_def.h>
396fba6e04STony Xie #include <plat_private.h>
406fba6e04STony Xie 
416fba6e04STony Xie /* Macros to read the rk power domain state */
426fba6e04STony Xie #define RK_CORE_PWR_STATE(state) \
436fba6e04STony Xie 	((state)->pwr_domain_state[MPIDR_AFFLVL0])
446fba6e04STony Xie #define RK_CLUSTER_PWR_STATE(state) \
456fba6e04STony Xie 	((state)->pwr_domain_state[MPIDR_AFFLVL1])
466fba6e04STony Xie #define RK_SYSTEM_PWR_STATE(state) \
476fba6e04STony Xie 	((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
486fba6e04STony Xie 
496fba6e04STony Xie static uintptr_t rockchip_sec_entrypoint;
506fba6e04STony Xie 
51*f32ab444Stony.xie #pragma weak rockchip_soc_cores_pwr_dm_on
52*f32ab444Stony.xie #pragma weak rockchip_soc_hlvl_pwr_dm_off
53*f32ab444Stony.xie #pragma weak rockchip_soc_cores_pwr_dm_off
54*f32ab444Stony.xie #pragma weak rockchip_soc_sys_pwr_dm_suspend
55*f32ab444Stony.xie #pragma weak rockchip_soc_cores_pwr_dm_suspend
56*f32ab444Stony.xie #pragma weak rockchip_soc_hlvl_pwr_dm_suspend
57*f32ab444Stony.xie #pragma weak rockchip_soc_hlvl_pwr_dm_on_finish
58*f32ab444Stony.xie #pragma weak rockchip_soc_cores_pwr_dm_on_finish
59*f32ab444Stony.xie #pragma weak rockchip_soc_sys_pwr_dm_resume
60*f32ab444Stony.xie #pragma weak rockchip_soc_hlvl_pwr_dm_resume
61*f32ab444Stony.xie #pragma weak rockchip_soc_cores_pwr_dm_resume
62*f32ab444Stony.xie #pragma weak rockchip_soc_soft_reset
63*f32ab444Stony.xie #pragma weak rockchip_soc_system_off
64*f32ab444Stony.xie #pragma weak rockchip_soc_sys_pd_pwr_dn_wfi
65*f32ab444Stony.xie #pragma weak rockchip_soc_cores_pd_pwr_dn_wfi
66*f32ab444Stony.xie 
67*f32ab444Stony.xie int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint)
68*f32ab444Stony.xie {
69*f32ab444Stony.xie 	return PSCI_E_NOT_SUPPORTED;
70*f32ab444Stony.xie }
71*f32ab444Stony.xie 
72*f32ab444Stony.xie int rockchip_soc_hlvl_pwr_dm_off(uint32_t lvl,
73*f32ab444Stony.xie 				 plat_local_state_t lvl_state)
74*f32ab444Stony.xie {
75*f32ab444Stony.xie 	return PSCI_E_NOT_SUPPORTED;
76*f32ab444Stony.xie }
77*f32ab444Stony.xie 
78*f32ab444Stony.xie int rockchip_soc_cores_pwr_dm_off(void)
79*f32ab444Stony.xie {
80*f32ab444Stony.xie 	return PSCI_E_NOT_SUPPORTED;
81*f32ab444Stony.xie }
82*f32ab444Stony.xie 
83*f32ab444Stony.xie int rockchip_soc_sys_pwr_dm_suspend(void)
84*f32ab444Stony.xie {
85*f32ab444Stony.xie 	return PSCI_E_NOT_SUPPORTED;
86*f32ab444Stony.xie }
87*f32ab444Stony.xie 
88*f32ab444Stony.xie int rockchip_soc_cores_pwr_dm_suspend(void)
89*f32ab444Stony.xie {
90*f32ab444Stony.xie 	return PSCI_E_NOT_SUPPORTED;
91*f32ab444Stony.xie }
92*f32ab444Stony.xie 
93*f32ab444Stony.xie int rockchip_soc_hlvl_pwr_dm_suspend(uint32_t lvl,
94*f32ab444Stony.xie 				     plat_local_state_t lvl_state)
95*f32ab444Stony.xie {
96*f32ab444Stony.xie 	return PSCI_E_NOT_SUPPORTED;
97*f32ab444Stony.xie }
98*f32ab444Stony.xie 
99*f32ab444Stony.xie int rockchip_soc_hlvl_pwr_dm_on_finish(uint32_t lvl,
100*f32ab444Stony.xie 				       plat_local_state_t lvl_state)
101*f32ab444Stony.xie {
102*f32ab444Stony.xie 	return PSCI_E_NOT_SUPPORTED;
103*f32ab444Stony.xie }
104*f32ab444Stony.xie 
105*f32ab444Stony.xie int rockchip_soc_cores_pwr_dm_on_finish(void)
106*f32ab444Stony.xie {
107*f32ab444Stony.xie 	return PSCI_E_NOT_SUPPORTED;
108*f32ab444Stony.xie }
109*f32ab444Stony.xie 
110*f32ab444Stony.xie int rockchip_soc_sys_pwr_dm_resume(void)
111*f32ab444Stony.xie {
112*f32ab444Stony.xie 	return PSCI_E_NOT_SUPPORTED;
113*f32ab444Stony.xie }
114*f32ab444Stony.xie 
115*f32ab444Stony.xie int rockchip_soc_hlvl_pwr_dm_resume(uint32_t lvl,
116*f32ab444Stony.xie 				    plat_local_state_t lvl_state)
117*f32ab444Stony.xie {
118*f32ab444Stony.xie 	return PSCI_E_NOT_SUPPORTED;
119*f32ab444Stony.xie }
120*f32ab444Stony.xie 
121*f32ab444Stony.xie int rockchip_soc_cores_pwr_dm_resume(void)
122*f32ab444Stony.xie {
123*f32ab444Stony.xie 	return PSCI_E_NOT_SUPPORTED;
124*f32ab444Stony.xie }
125*f32ab444Stony.xie 
126*f32ab444Stony.xie void __dead2 rockchip_soc_soft_reset(void)
127*f32ab444Stony.xie {
128*f32ab444Stony.xie 	while (1)
129*f32ab444Stony.xie 		;
130*f32ab444Stony.xie }
131*f32ab444Stony.xie 
132*f32ab444Stony.xie void __dead2 rockchip_soc_system_off(void)
133*f32ab444Stony.xie {
134*f32ab444Stony.xie 	while (1)
135*f32ab444Stony.xie 		;
136*f32ab444Stony.xie }
137*f32ab444Stony.xie 
138*f32ab444Stony.xie void __dead2 rockchip_soc_cores_pd_pwr_dn_wfi(
139*f32ab444Stony.xie 				const psci_power_state_t *target_state)
140*f32ab444Stony.xie {
141*f32ab444Stony.xie 	psci_power_down_wfi();
142*f32ab444Stony.xie }
143*f32ab444Stony.xie 
144*f32ab444Stony.xie void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void)
145*f32ab444Stony.xie {
146*f32ab444Stony.xie 	psci_power_down_wfi();
147*f32ab444Stony.xie }
1486fba6e04STony Xie 
1496fba6e04STony Xie /*******************************************************************************
1506fba6e04STony Xie  * Rockchip standard platform handler called to check the validity of the power
1516fba6e04STony Xie  * state parameter.
1526fba6e04STony Xie  ******************************************************************************/
1536fba6e04STony Xie int rockchip_validate_power_state(unsigned int power_state,
1546fba6e04STony Xie 				  psci_power_state_t *req_state)
1556fba6e04STony Xie {
1566fba6e04STony Xie 	int pstate = psci_get_pstate_type(power_state);
1576fba6e04STony Xie 	int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
1586fba6e04STony Xie 	int i;
1596fba6e04STony Xie 
1606fba6e04STony Xie 	assert(req_state);
1616fba6e04STony Xie 
1626fba6e04STony Xie 	if (pwr_lvl > PLAT_MAX_PWR_LVL)
1636fba6e04STony Xie 		return PSCI_E_INVALID_PARAMS;
1646fba6e04STony Xie 
1656fba6e04STony Xie 	/* Sanity check the requested state */
1666fba6e04STony Xie 	if (pstate == PSTATE_TYPE_STANDBY) {
1676fba6e04STony Xie 		/*
1686fba6e04STony Xie 		 * It's probably to enter standby only on power level 0
1696fba6e04STony Xie 		 * ignore any other power level.
1706fba6e04STony Xie 		 */
1716fba6e04STony Xie 		if (pwr_lvl != MPIDR_AFFLVL0)
1726fba6e04STony Xie 			return PSCI_E_INVALID_PARAMS;
1736fba6e04STony Xie 
1746fba6e04STony Xie 		req_state->pwr_domain_state[MPIDR_AFFLVL0] =
1756fba6e04STony Xie 					PLAT_MAX_RET_STATE;
1766fba6e04STony Xie 	} else {
1776fba6e04STony Xie 		for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
1786fba6e04STony Xie 			req_state->pwr_domain_state[i] =
1796fba6e04STony Xie 					PLAT_MAX_OFF_STATE;
1809ec78bdfSTony Xie 
1819ec78bdfSTony Xie 		for (i = (pwr_lvl + 1); i <= PLAT_MAX_PWR_LVL; i++)
1829ec78bdfSTony Xie 			req_state->pwr_domain_state[i] =
1839ec78bdfSTony Xie 					PLAT_MAX_RET_STATE;
1846fba6e04STony Xie 	}
1856fba6e04STony Xie 
1866fba6e04STony Xie 	/* We expect the 'state id' to be zero */
1876fba6e04STony Xie 	if (psci_get_pstate_id(power_state))
1886fba6e04STony Xie 		return PSCI_E_INVALID_PARAMS;
1896fba6e04STony Xie 
1906fba6e04STony Xie 	return PSCI_E_SUCCESS;
1916fba6e04STony Xie }
1926fba6e04STony Xie 
1936fba6e04STony Xie void rockchip_get_sys_suspend_power_state(psci_power_state_t *req_state)
1946fba6e04STony Xie {
1956fba6e04STony Xie 	int i;
1966fba6e04STony Xie 
1976fba6e04STony Xie 	for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
1986fba6e04STony Xie 		req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
1996fba6e04STony Xie }
2006fba6e04STony Xie 
2016fba6e04STony Xie /*******************************************************************************
2026fba6e04STony Xie  * RockChip handler called when a CPU is about to enter standby.
2036fba6e04STony Xie  ******************************************************************************/
2046fba6e04STony Xie void rockchip_cpu_standby(plat_local_state_t cpu_state)
2056fba6e04STony Xie {
2066fba6e04STony Xie 	unsigned int scr;
2076fba6e04STony Xie 
2086fba6e04STony Xie 	assert(cpu_state == PLAT_MAX_RET_STATE);
2096fba6e04STony Xie 
2106fba6e04STony Xie 	scr = read_scr_el3();
2116fba6e04STony Xie 	/* Enable PhysicalIRQ bit for NS world to wake the CPU */
2126fba6e04STony Xie 	write_scr_el3(scr | SCR_IRQ_BIT);
2136fba6e04STony Xie 	isb();
2146fba6e04STony Xie 	dsb();
2156fba6e04STony Xie 	wfi();
2166fba6e04STony Xie 
2176fba6e04STony Xie 	/*
2186fba6e04STony Xie 	 * Restore SCR to the original value, synchronisation of scr_el3 is
2196fba6e04STony Xie 	 * done by eret while el3_exit to save some execution cycles.
2206fba6e04STony Xie 	 */
2216fba6e04STony Xie 	write_scr_el3(scr);
2226fba6e04STony Xie }
2236fba6e04STony Xie 
2246fba6e04STony Xie /*******************************************************************************
2256fba6e04STony Xie  * RockChip handler called when a power domain is about to be turned on. The
2266fba6e04STony Xie  * mpidr determines the CPU to be turned on.
2276fba6e04STony Xie  ******************************************************************************/
2286fba6e04STony Xie int rockchip_pwr_domain_on(u_register_t mpidr)
2296fba6e04STony Xie {
230*f32ab444Stony.xie 	return rockchip_soc_cores_pwr_dm_on(mpidr, rockchip_sec_entrypoint);
2316fba6e04STony Xie }
2326fba6e04STony Xie 
2336fba6e04STony Xie /*******************************************************************************
2346fba6e04STony Xie  * RockChip handler called when a power domain is about to be turned off. The
2356fba6e04STony Xie  * target_state encodes the power state that each level should transition to.
2366fba6e04STony Xie  ******************************************************************************/
2376fba6e04STony Xie void rockchip_pwr_domain_off(const psci_power_state_t *target_state)
2386fba6e04STony Xie {
2399ec78bdfSTony Xie 	uint32_t lvl;
2409ec78bdfSTony Xie 	plat_local_state_t lvl_state;
241*f32ab444Stony.xie 	int ret;
2429ec78bdfSTony Xie 
2436fba6e04STony Xie 	assert(RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE);
2446fba6e04STony Xie 
2456fba6e04STony Xie 	plat_rockchip_gic_cpuif_disable();
2466fba6e04STony Xie 
2476fba6e04STony Xie 	if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
2486fba6e04STony Xie 		plat_cci_disable();
2499ec78bdfSTony Xie 
250*f32ab444Stony.xie 	rockchip_soc_cores_pwr_dm_off();
2519ec78bdfSTony Xie 
2529ec78bdfSTony Xie 	for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) {
2539ec78bdfSTony Xie 		lvl_state = target_state->pwr_domain_state[lvl];
254*f32ab444Stony.xie 		ret = rockchip_soc_hlvl_pwr_dm_off(lvl, lvl_state);
255*f32ab444Stony.xie 		if (ret == PSCI_E_NOT_SUPPORTED)
256*f32ab444Stony.xie 			break;
2579ec78bdfSTony Xie 	}
2586fba6e04STony Xie }
2596fba6e04STony Xie 
2606fba6e04STony Xie /*******************************************************************************
2616fba6e04STony Xie  * RockChip handler called when a power domain is about to be suspended. The
2626fba6e04STony Xie  * target_state encodes the power state that each level should transition to.
2636fba6e04STony Xie  ******************************************************************************/
2646fba6e04STony Xie void rockchip_pwr_domain_suspend(const psci_power_state_t *target_state)
2656fba6e04STony Xie {
2669ec78bdfSTony Xie 	uint32_t lvl;
2679ec78bdfSTony Xie 	plat_local_state_t lvl_state;
268*f32ab444Stony.xie 	int ret;
2699ec78bdfSTony Xie 
2709ec78bdfSTony Xie 	if (RK_CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
2716fba6e04STony Xie 		return;
2726fba6e04STony Xie 
273*f32ab444Stony.xie 	if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
274*f32ab444Stony.xie 		rockchip_soc_sys_pwr_dm_suspend();
275*f32ab444Stony.xie 	else
276*f32ab444Stony.xie 		rockchip_soc_cores_pwr_dm_suspend();
2776fba6e04STony Xie 
2786fba6e04STony Xie 	/* Prevent interrupts from spuriously waking up this cpu */
2796fba6e04STony Xie 	plat_rockchip_gic_cpuif_disable();
2806fba6e04STony Xie 
2816fba6e04STony Xie 	/* Perform the common cluster specific operations */
2826fba6e04STony Xie 	if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
2836fba6e04STony Xie 		plat_cci_disable();
2849ec78bdfSTony Xie 
28563ebf051STony Xie 	if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
28663ebf051STony Xie 		return;
28763ebf051STony Xie 
2889ec78bdfSTony Xie 	for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) {
2899ec78bdfSTony Xie 		lvl_state = target_state->pwr_domain_state[lvl];
290*f32ab444Stony.xie 		ret = rockchip_soc_hlvl_pwr_dm_suspend(lvl, lvl_state);
291*f32ab444Stony.xie 		if (ret == PSCI_E_NOT_SUPPORTED)
292*f32ab444Stony.xie 			break;
2939ec78bdfSTony Xie 	}
2946fba6e04STony Xie }
2956fba6e04STony Xie 
2966fba6e04STony Xie /*******************************************************************************
2976fba6e04STony Xie  * RockChip handler called when a power domain has just been powered on after
2986fba6e04STony Xie  * being turned off earlier. The target_state encodes the low power state that
2996fba6e04STony Xie  * each level has woken up from.
3006fba6e04STony Xie  ******************************************************************************/
3016fba6e04STony Xie void rockchip_pwr_domain_on_finish(const psci_power_state_t *target_state)
3026fba6e04STony Xie {
3039ec78bdfSTony Xie 	uint32_t lvl;
3049ec78bdfSTony Xie 	plat_local_state_t lvl_state;
305*f32ab444Stony.xie 	int ret;
3069ec78bdfSTony Xie 
3076fba6e04STony Xie 	assert(RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE);
3086fba6e04STony Xie 
3099ec78bdfSTony Xie 	for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) {
3109ec78bdfSTony Xie 		lvl_state = target_state->pwr_domain_state[lvl];
311*f32ab444Stony.xie 		ret = rockchip_soc_hlvl_pwr_dm_on_finish(lvl, lvl_state);
312*f32ab444Stony.xie 		if (ret == PSCI_E_NOT_SUPPORTED)
313*f32ab444Stony.xie 			break;
3149ec78bdfSTony Xie 	}
3159ec78bdfSTony Xie 
316*f32ab444Stony.xie 	rockchip_soc_cores_pwr_dm_on_finish();
3176fba6e04STony Xie 
3186fba6e04STony Xie 	/* Perform the common cluster specific operations */
3196fba6e04STony Xie 	if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
3206fba6e04STony Xie 		/* Enable coherency if this cluster was off */
3216fba6e04STony Xie 		plat_cci_enable();
3226fba6e04STony Xie 	}
3236fba6e04STony Xie 
3246fba6e04STony Xie 	/* Enable the gic cpu interface */
3256fba6e04STony Xie 	plat_rockchip_gic_pcpu_init();
3266fba6e04STony Xie 
3276fba6e04STony Xie 	/* Program the gic per-cpu distributor or re-distributor interface */
3286fba6e04STony Xie 	plat_rockchip_gic_cpuif_enable();
3296fba6e04STony Xie }
3306fba6e04STony Xie 
3316fba6e04STony Xie /*******************************************************************************
3326fba6e04STony Xie  * RockChip handler called when a power domain has just been powered on after
3336fba6e04STony Xie  * having been suspended earlier. The target_state encodes the low power state
3346fba6e04STony Xie  * that each level has woken up from.
3356fba6e04STony Xie  * TODO: At the moment we reuse the on finisher and reinitialize the secure
3366fba6e04STony Xie  * context. Need to implement a separate suspend finisher.
3376fba6e04STony Xie  ******************************************************************************/
3386fba6e04STony Xie void rockchip_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
3396fba6e04STony Xie {
3409ec78bdfSTony Xie 	uint32_t lvl;
3419ec78bdfSTony Xie 	plat_local_state_t lvl_state;
342*f32ab444Stony.xie 	int ret;
3439ec78bdfSTony Xie 
3446fba6e04STony Xie 	/* Nothing to be done on waking up from retention from CPU level */
3459ec78bdfSTony Xie 	if (RK_CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
3466fba6e04STony Xie 		return;
3476fba6e04STony Xie 
34863ebf051STony Xie 	if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
349*f32ab444Stony.xie 		rockchip_soc_sys_pwr_dm_resume();
35063ebf051STony Xie 		goto comm_finish;
35163ebf051STony Xie 	}
35263ebf051STony Xie 
3539ec78bdfSTony Xie 	for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) {
3549ec78bdfSTony Xie 		lvl_state = target_state->pwr_domain_state[lvl];
355*f32ab444Stony.xie 		ret = rockchip_soc_hlvl_pwr_dm_resume(lvl, lvl_state);
356*f32ab444Stony.xie 		if (ret == PSCI_E_NOT_SUPPORTED)
357*f32ab444Stony.xie 			break;
3589ec78bdfSTony Xie 	}
3599ec78bdfSTony Xie 
360*f32ab444Stony.xie 	rockchip_soc_cores_pwr_dm_resume();
361*f32ab444Stony.xie 
3629ec78bdfSTony Xie 	/*
36363ebf051STony Xie 	 * Program the gic per-cpu distributor or re-distributor interface.
3647e1bedb6SCaesar Wang 	 * For sys power domain operation, resuming of the gic needs to operate
365*f32ab444Stony.xie 	 * in rockchip_soc_sys_pwr_dm_resume(), according to the sys power mode
3667e1bedb6SCaesar Wang 	 * implements.
3679ec78bdfSTony Xie 	 */
3689ec78bdfSTony Xie 	plat_rockchip_gic_cpuif_enable();
3696fba6e04STony Xie 
37063ebf051STony Xie comm_finish:
3716fba6e04STony Xie 	/* Perform the common cluster specific operations */
3726fba6e04STony Xie 	if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
3736fba6e04STony Xie 		/* Enable coherency if this cluster was off */
3746fba6e04STony Xie 		plat_cci_enable();
3756fba6e04STony Xie 	}
3766fba6e04STony Xie }
3776fba6e04STony Xie 
3786fba6e04STony Xie /*******************************************************************************
3796fba6e04STony Xie  * RockChip handlers to reboot the system
3806fba6e04STony Xie  ******************************************************************************/
3816fba6e04STony Xie static void __dead2 rockchip_system_reset(void)
3826fba6e04STony Xie {
383*f32ab444Stony.xie 	rockchip_soc_soft_reset();
3846fba6e04STony Xie }
3856fba6e04STony Xie 
3866fba6e04STony Xie /*******************************************************************************
38786c253e4SCaesar Wang  * RockChip handlers to power off the system
38886c253e4SCaesar Wang  ******************************************************************************/
38986c253e4SCaesar Wang static void __dead2 rockchip_system_poweroff(void)
39086c253e4SCaesar Wang {
391*f32ab444Stony.xie 	rockchip_soc_system_off();
392*f32ab444Stony.xie }
39386c253e4SCaesar Wang 
394*f32ab444Stony.xie static void __dead2 rockchip_pd_pwr_down_wfi(
395*f32ab444Stony.xie 		const psci_power_state_t *target_state)
396*f32ab444Stony.xie {
397*f32ab444Stony.xie 	if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
398*f32ab444Stony.xie 		rockchip_soc_sys_pd_pwr_dn_wfi();
399*f32ab444Stony.xie 	else
400*f32ab444Stony.xie 		rockchip_soc_cores_pd_pwr_dn_wfi(target_state);
40186c253e4SCaesar Wang }
40286c253e4SCaesar Wang 
40386c253e4SCaesar Wang /*******************************************************************************
4046fba6e04STony Xie  * Export the platform handlers via plat_rockchip_psci_pm_ops. The rockchip
4056fba6e04STony Xie  * standard
4066fba6e04STony Xie  * platform layer will take care of registering the handlers with PSCI.
4076fba6e04STony Xie  ******************************************************************************/
4086fba6e04STony Xie const plat_psci_ops_t plat_rockchip_psci_pm_ops = {
4096fba6e04STony Xie 	.cpu_standby = rockchip_cpu_standby,
4106fba6e04STony Xie 	.pwr_domain_on = rockchip_pwr_domain_on,
4116fba6e04STony Xie 	.pwr_domain_off = rockchip_pwr_domain_off,
4126fba6e04STony Xie 	.pwr_domain_suspend = rockchip_pwr_domain_suspend,
4136fba6e04STony Xie 	.pwr_domain_on_finish = rockchip_pwr_domain_on_finish,
4146fba6e04STony Xie 	.pwr_domain_suspend_finish = rockchip_pwr_domain_suspend_finish,
4156fba6e04STony Xie 	.system_reset = rockchip_system_reset,
41686c253e4SCaesar Wang 	.system_off = rockchip_system_poweroff,
4176fba6e04STony Xie 	.validate_power_state = rockchip_validate_power_state,
4186fba6e04STony Xie 	.get_sys_suspend_power_state = rockchip_get_sys_suspend_power_state
4196fba6e04STony Xie };
4206fba6e04STony Xie 
4216fba6e04STony Xie int plat_setup_psci_ops(uintptr_t sec_entrypoint,
4226fba6e04STony Xie 			const plat_psci_ops_t **psci_ops)
4236fba6e04STony Xie {
4246fba6e04STony Xie 	*psci_ops = &plat_rockchip_psci_pm_ops;
4256fba6e04STony Xie 	rockchip_sec_entrypoint = sec_entrypoint;
4266fba6e04STony Xie 	return 0;
4276fba6e04STony Xie }
4286fba6e04STony Xie 
4299ec78bdfSTony Xie uintptr_t plat_get_sec_entrypoint(void)
4309ec78bdfSTony Xie {
4319ec78bdfSTony Xie 	assert(rockchip_sec_entrypoint);
4329ec78bdfSTony Xie 	return rockchip_sec_entrypoint;
4339ec78bdfSTony Xie }
434