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