xref: /rk3399_ARM-atf/plat/socionext/synquacer/sq_psci.c (revision 753701ccb07d5e58a63535b05baa2f041e9566e1)
1*753701ccSSumit Garg /*
2*753701ccSSumit Garg  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3*753701ccSSumit Garg  *
4*753701ccSSumit Garg  * SPDX-License-Identifier: BSD-3-Clause
5*753701ccSSumit Garg  */
6*753701ccSSumit Garg 
7*753701ccSSumit Garg #include <arch_helpers.h>
8*753701ccSSumit Garg #include <assert.h>
9*753701ccSSumit Garg #include <cassert.h>
10*753701ccSSumit Garg #include <debug.h>
11*753701ccSSumit Garg #include <delay_timer.h>
12*753701ccSSumit Garg #include <errno.h>
13*753701ccSSumit Garg #include <generic_delay_timer.h>
14*753701ccSSumit Garg #include <platform_def.h>
15*753701ccSSumit Garg #include <sq_common.h>
16*753701ccSSumit Garg #include "sq_scpi.h"
17*753701ccSSumit Garg #include <psci.h>
18*753701ccSSumit Garg 
19*753701ccSSumit Garg /* Macros to read the SQ power domain state */
20*753701ccSSumit Garg #define SQ_PWR_LVL0	MPIDR_AFFLVL0
21*753701ccSSumit Garg #define SQ_PWR_LVL1	MPIDR_AFFLVL1
22*753701ccSSumit Garg #define SQ_PWR_LVL2	MPIDR_AFFLVL2
23*753701ccSSumit Garg 
24*753701ccSSumit Garg #define SQ_CORE_PWR_STATE(state)	(state)->pwr_domain_state[SQ_PWR_LVL0]
25*753701ccSSumit Garg #define SQ_CLUSTER_PWR_STATE(state)	(state)->pwr_domain_state[SQ_PWR_LVL1]
26*753701ccSSumit Garg #define SQ_SYSTEM_PWR_STATE(state)	((PLAT_MAX_PWR_LVL > SQ_PWR_LVL1) ?\
27*753701ccSSumit Garg 				(state)->pwr_domain_state[SQ_PWR_LVL2] : 0)
28*753701ccSSumit Garg 
29*753701ccSSumit Garg uintptr_t sq_sec_entrypoint;
30*753701ccSSumit Garg 
31*753701ccSSumit Garg int sq_pwr_domain_on(u_register_t mpidr)
32*753701ccSSumit Garg {
33*753701ccSSumit Garg 	/*
34*753701ccSSumit Garg 	 * SCP takes care of powering up parent power domains so we
35*753701ccSSumit Garg 	 * only need to care about level 0
36*753701ccSSumit Garg 	 */
37*753701ccSSumit Garg 	scpi_set_sq_power_state(mpidr, scpi_power_on, scpi_power_on,
38*753701ccSSumit Garg 				 scpi_power_on);
39*753701ccSSumit Garg 
40*753701ccSSumit Garg 	return PSCI_E_SUCCESS;
41*753701ccSSumit Garg }
42*753701ccSSumit Garg 
43*753701ccSSumit Garg static void sq_pwr_domain_on_finisher_common(
44*753701ccSSumit Garg 		const psci_power_state_t *target_state)
45*753701ccSSumit Garg {
46*753701ccSSumit Garg 	assert(SQ_CORE_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF);
47*753701ccSSumit Garg 
48*753701ccSSumit Garg 	/*
49*753701ccSSumit Garg 	 * Perform the common cluster specific operations i.e enable coherency
50*753701ccSSumit Garg 	 * if this cluster was off.
51*753701ccSSumit Garg 	 */
52*753701ccSSumit Garg 	if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF)
53*753701ccSSumit Garg 		plat_sq_interconnect_enter_coherency();
54*753701ccSSumit Garg }
55*753701ccSSumit Garg 
56*753701ccSSumit Garg void sq_pwr_domain_on_finish(const psci_power_state_t *target_state)
57*753701ccSSumit Garg {
58*753701ccSSumit Garg 	/* Assert that the system power domain need not be initialized */
59*753701ccSSumit Garg 	assert(SQ_SYSTEM_PWR_STATE(target_state) == SQ_LOCAL_STATE_RUN);
60*753701ccSSumit Garg 
61*753701ccSSumit Garg 	sq_pwr_domain_on_finisher_common(target_state);
62*753701ccSSumit Garg 
63*753701ccSSumit Garg 	/* Program the gic per-cpu distributor or re-distributor interface */
64*753701ccSSumit Garg 	sq_gic_pcpu_init();
65*753701ccSSumit Garg 
66*753701ccSSumit Garg 	/* Enable the gic cpu interface */
67*753701ccSSumit Garg 	sq_gic_cpuif_enable();
68*753701ccSSumit Garg }
69*753701ccSSumit Garg 
70*753701ccSSumit Garg static void sq_power_down_common(const psci_power_state_t *target_state)
71*753701ccSSumit Garg {
72*753701ccSSumit Garg 	uint32_t cluster_state = scpi_power_on;
73*753701ccSSumit Garg 	uint32_t system_state = scpi_power_on;
74*753701ccSSumit Garg 
75*753701ccSSumit Garg 	/* Prevent interrupts from spuriously waking up this cpu */
76*753701ccSSumit Garg 	sq_gic_cpuif_disable();
77*753701ccSSumit Garg 
78*753701ccSSumit Garg 	/* Check if power down at system power domain level is requested */
79*753701ccSSumit Garg 	if (SQ_SYSTEM_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF)
80*753701ccSSumit Garg 		system_state = scpi_power_retention;
81*753701ccSSumit Garg 
82*753701ccSSumit Garg 	/* Cluster is to be turned off, so disable coherency */
83*753701ccSSumit Garg 	if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) {
84*753701ccSSumit Garg 		plat_sq_interconnect_exit_coherency();
85*753701ccSSumit Garg 		cluster_state = scpi_power_off;
86*753701ccSSumit Garg 	}
87*753701ccSSumit Garg 
88*753701ccSSumit Garg 	/*
89*753701ccSSumit Garg 	 * Ask the SCP to power down the appropriate components depending upon
90*753701ccSSumit Garg 	 * their state.
91*753701ccSSumit Garg 	 */
92*753701ccSSumit Garg 	scpi_set_sq_power_state(read_mpidr_el1(),
93*753701ccSSumit Garg 				 scpi_power_off,
94*753701ccSSumit Garg 				 cluster_state,
95*753701ccSSumit Garg 				 system_state);
96*753701ccSSumit Garg }
97*753701ccSSumit Garg 
98*753701ccSSumit Garg void sq_pwr_domain_off(const psci_power_state_t *target_state)
99*753701ccSSumit Garg {
100*753701ccSSumit Garg 	sq_power_down_common(target_state);
101*753701ccSSumit Garg }
102*753701ccSSumit Garg 
103*753701ccSSumit Garg void __dead2 sq_system_off(void)
104*753701ccSSumit Garg {
105*753701ccSSumit Garg 	volatile uint32_t *gpio = (uint32_t *)PLAT_SQ_GPIO_BASE;
106*753701ccSSumit Garg 
107*753701ccSSumit Garg 	/* set PD[9] high to power off the system */
108*753701ccSSumit Garg 	gpio[5] |= 0x2;		/* set output */
109*753701ccSSumit Garg 	gpio[1] |= 0x2;		/* set high */
110*753701ccSSumit Garg 	dmbst();
111*753701ccSSumit Garg 
112*753701ccSSumit Garg 	generic_delay_timer_init();
113*753701ccSSumit Garg 
114*753701ccSSumit Garg 	mdelay(1);
115*753701ccSSumit Garg 
116*753701ccSSumit Garg 	while (1) {
117*753701ccSSumit Garg 		gpio[1] &= ~0x2;	/* set low */
118*753701ccSSumit Garg 		dmbst();
119*753701ccSSumit Garg 
120*753701ccSSumit Garg 		mdelay(1);
121*753701ccSSumit Garg 
122*753701ccSSumit Garg 		gpio[1] |= 0x2;		/* set high */
123*753701ccSSumit Garg 		dmbst();
124*753701ccSSumit Garg 
125*753701ccSSumit Garg 		mdelay(100);
126*753701ccSSumit Garg 	}
127*753701ccSSumit Garg 
128*753701ccSSumit Garg 	wfi();
129*753701ccSSumit Garg 	ERROR("SQ System Off: operation not handled.\n");
130*753701ccSSumit Garg 	panic();
131*753701ccSSumit Garg }
132*753701ccSSumit Garg 
133*753701ccSSumit Garg void __dead2 sq_system_reset(void)
134*753701ccSSumit Garg {
135*753701ccSSumit Garg 	uint32_t response;
136*753701ccSSumit Garg 
137*753701ccSSumit Garg 	/* Send the system reset request to the SCP */
138*753701ccSSumit Garg 	response = scpi_sys_power_state(scpi_system_reboot);
139*753701ccSSumit Garg 
140*753701ccSSumit Garg 	if (response != SCP_OK) {
141*753701ccSSumit Garg 		ERROR("SQ System Reset: SCP error %u.\n", response);
142*753701ccSSumit Garg 		panic();
143*753701ccSSumit Garg 	}
144*753701ccSSumit Garg 	wfi();
145*753701ccSSumit Garg 	ERROR("SQ System Reset: operation not handled.\n");
146*753701ccSSumit Garg 	panic();
147*753701ccSSumit Garg }
148*753701ccSSumit Garg 
149*753701ccSSumit Garg void sq_cpu_standby(plat_local_state_t cpu_state)
150*753701ccSSumit Garg {
151*753701ccSSumit Garg 	unsigned int scr;
152*753701ccSSumit Garg 
153*753701ccSSumit Garg 	assert(cpu_state == SQ_LOCAL_STATE_RET);
154*753701ccSSumit Garg 
155*753701ccSSumit Garg 	scr = read_scr_el3();
156*753701ccSSumit Garg 	/* Enable PhysicalIRQ bit for NS world to wake the CPU */
157*753701ccSSumit Garg 	write_scr_el3(scr | SCR_IRQ_BIT);
158*753701ccSSumit Garg 	isb();
159*753701ccSSumit Garg 	dsb();
160*753701ccSSumit Garg 	wfi();
161*753701ccSSumit Garg 
162*753701ccSSumit Garg 	/*
163*753701ccSSumit Garg 	 * Restore SCR to the original value, synchronisation of scr_el3 is
164*753701ccSSumit Garg 	 * done by eret while el3_exit to save some execution cycles.
165*753701ccSSumit Garg 	 */
166*753701ccSSumit Garg 	write_scr_el3(scr);
167*753701ccSSumit Garg }
168*753701ccSSumit Garg 
169*753701ccSSumit Garg const plat_psci_ops_t sq_psci_ops = {
170*753701ccSSumit Garg 	.pwr_domain_on		= sq_pwr_domain_on,
171*753701ccSSumit Garg 	.pwr_domain_off		= sq_pwr_domain_off,
172*753701ccSSumit Garg 	.pwr_domain_on_finish	= sq_pwr_domain_on_finish,
173*753701ccSSumit Garg 	.cpu_standby		= sq_cpu_standby,
174*753701ccSSumit Garg 	.system_off		= sq_system_off,
175*753701ccSSumit Garg 	.system_reset		= sq_system_reset,
176*753701ccSSumit Garg };
177*753701ccSSumit Garg 
178*753701ccSSumit Garg int plat_setup_psci_ops(uintptr_t sec_entrypoint,
179*753701ccSSumit Garg 			const struct plat_psci_ops **psci_ops)
180*753701ccSSumit Garg {
181*753701ccSSumit Garg 	sq_sec_entrypoint = sec_entrypoint;
182*753701ccSSumit Garg 	flush_dcache_range((uint64_t)&sq_sec_entrypoint,
183*753701ccSSumit Garg 			   sizeof(sq_sec_entrypoint));
184*753701ccSSumit Garg 
185*753701ccSSumit Garg 	*psci_ops = &sq_psci_ops;
186*753701ccSSumit Garg 
187*753701ccSSumit Garg 	return 0;
188*753701ccSSumit Garg }
189