xref: /rk3399_ARM-atf/plat/nvidia/tegra/common/tegra_pm.c (revision 82cb2c1ad9897473743f08437d0a3995bed561b9)
1 /*
2  * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <arch_helpers.h>
8 #include <assert.h>
9 #include <bl_common.h>
10 #include <context.h>
11 #include <context_mgmt.h>
12 #include <console.h>
13 #include <debug.h>
14 #include <memctrl.h>
15 #include <mmio.h>
16 #include <platform.h>
17 #include <platform_def.h>
18 #include <pmc.h>
19 #include <psci.h>
20 #include <tegra_def.h>
21 #include <tegra_private.h>
22 
23 extern uint64_t tegra_bl31_phys_base;
24 extern uint64_t tegra_sec_entry_point;
25 extern uint64_t tegra_console_base;
26 
27 /*
28  * tegra_fake_system_suspend acts as a boolean var controlling whether
29  * we are going to take fake system suspend code or normal system suspend code
30  * path. This variable is set inside the sip call handlers,when the kernel
31  * requests a SIP call to set the suspend debug flags.
32  */
33 uint8_t tegra_fake_system_suspend;
34 
35 /*
36  * The following platform setup functions are weakly defined. They
37  * provide typical implementations that will be overridden by a SoC.
38  */
39 #pragma weak tegra_soc_pwr_domain_suspend
40 #pragma weak tegra_soc_pwr_domain_on
41 #pragma weak tegra_soc_pwr_domain_off
42 #pragma weak tegra_soc_pwr_domain_on_finish
43 #pragma weak tegra_soc_pwr_domain_power_down_wfi
44 #pragma weak tegra_soc_prepare_system_reset
45 #pragma weak tegra_soc_prepare_system_off
46 #pragma weak tegra_soc_get_target_pwr_state
47 
48 int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
49 {
50 	return PSCI_E_NOT_SUPPORTED;
51 }
52 
53 int tegra_soc_pwr_domain_on(u_register_t mpidr)
54 {
55 	return PSCI_E_SUCCESS;
56 }
57 
58 int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
59 {
60 	return PSCI_E_SUCCESS;
61 }
62 
63 int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
64 {
65 	return PSCI_E_SUCCESS;
66 }
67 
68 int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
69 {
70 	return PSCI_E_SUCCESS;
71 }
72 
73 int tegra_soc_prepare_system_reset(void)
74 {
75 	return PSCI_E_SUCCESS;
76 }
77 
78 __dead2 void tegra_soc_prepare_system_off(void)
79 {
80 	ERROR("Tegra System Off: operation not handled.\n");
81 	panic();
82 }
83 
84 plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl,
85 					     const plat_local_state_t *states,
86 					     unsigned int ncpu)
87 {
88 	plat_local_state_t target = PLAT_MAX_OFF_STATE, temp;
89 
90 	assert(ncpu);
91 
92 	do {
93 		temp = *states++;
94 		if ((temp < target))
95 			target = temp;
96 	} while (--ncpu);
97 
98 	return target;
99 }
100 
101 /*******************************************************************************
102  * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND`
103  * call to get the `power_state` parameter. This allows the platform to encode
104  * the appropriate State-ID field within the `power_state` parameter which can
105  * be utilized in `pwr_domain_suspend()` to suspend to system affinity level.
106 ******************************************************************************/
107 void tegra_get_sys_suspend_power_state(psci_power_state_t *req_state)
108 {
109 	/* all affinities use system suspend state id */
110 	for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
111 		req_state->pwr_domain_state[i] = PSTATE_ID_SOC_POWERDN;
112 }
113 
114 /*******************************************************************************
115  * Handler called when an affinity instance is about to enter standby.
116  ******************************************************************************/
117 void tegra_cpu_standby(plat_local_state_t cpu_state)
118 {
119 	/*
120 	 * Enter standby state
121 	 * dsb is good practice before using wfi to enter low power states
122 	 */
123 	dsb();
124 	wfi();
125 }
126 
127 /*******************************************************************************
128  * Handler called when an affinity instance is about to be turned on. The
129  * level and mpidr determine the affinity instance.
130  ******************************************************************************/
131 int tegra_pwr_domain_on(u_register_t mpidr)
132 {
133 	return tegra_soc_pwr_domain_on(mpidr);
134 }
135 
136 /*******************************************************************************
137  * Handler called when a power domain is about to be turned off. The
138  * target_state encodes the power state that each level should transition to.
139  ******************************************************************************/
140 void tegra_pwr_domain_off(const psci_power_state_t *target_state)
141 {
142 	tegra_soc_pwr_domain_off(target_state);
143 }
144 
145 /*******************************************************************************
146  * Handler called when a power domain is about to be suspended. The
147  * target_state encodes the power state that each level should transition to.
148  ******************************************************************************/
149 void tegra_pwr_domain_suspend(const psci_power_state_t *target_state)
150 {
151 	tegra_soc_pwr_domain_suspend(target_state);
152 
153 	/* Disable console if we are entering deep sleep. */
154 	if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] ==
155 			PSTATE_ID_SOC_POWERDN)
156 		console_uninit();
157 
158 	/* disable GICC */
159 	tegra_gic_cpuif_deactivate();
160 }
161 
162 /*******************************************************************************
163  * Handler called at the end of the power domain suspend sequence. The
164  * target_state encodes the power state that each level should transition to.
165  ******************************************************************************/
166 __dead2 void tegra_pwr_domain_power_down_wfi(const psci_power_state_t
167 					     *target_state)
168 {
169 	uint8_t pwr_state = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL];
170 	uint64_t rmr_el3 = 0;
171 
172 	/* call the chip's power down handler */
173 	tegra_soc_pwr_domain_power_down_wfi(target_state);
174 
175 	/*
176 	 * If we are in fake system suspend mode, ensure we start doing
177 	 * procedures that help in looping back towards system suspend exit
178 	 * instead of calling WFI by requesting a warm reset.
179 	 * Else, just call WFI to enter low power state.
180 	 */
181 	if ((tegra_fake_system_suspend != 0U) &&
182 	    (pwr_state == (uint8_t)PSTATE_ID_SOC_POWERDN)) {
183 
184 		/* warm reboot */
185 		rmr_el3 = read_rmr_el3();
186 		write_rmr_el3(rmr_el3 | RMR_WARM_RESET_CPU);
187 
188 	} else {
189 		/* enter power down state */
190 		wfi();
191 	}
192 
193 	/* we can never reach here */
194 	panic();
195 }
196 
197 /*******************************************************************************
198  * Handler called when a power domain has just been powered on after
199  * being turned off earlier. The target_state encodes the low power state that
200  * each level has woken up from.
201  ******************************************************************************/
202 void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state)
203 {
204 	plat_params_from_bl2_t *plat_params;
205 
206 	/*
207 	 * Initialize the GIC cpu and distributor interfaces
208 	 */
209 	plat_gic_setup();
210 
211 	/*
212 	 * Check if we are exiting from deep sleep.
213 	 */
214 	if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] ==
215 			PSTATE_ID_SOC_POWERDN) {
216 
217 		/* Initialize the runtime console */
218 		if (tegra_console_base != (uint64_t)0) {
219 			console_init(tegra_console_base, TEGRA_BOOT_UART_CLK_IN_HZ,
220 				TEGRA_CONSOLE_BAUDRATE);
221 		}
222 
223 		/*
224 		 * Restore Memory Controller settings as it loses state
225 		 * during system suspend.
226 		 */
227 		tegra_memctrl_restore_settings();
228 
229 		/*
230 		 * Security configuration to allow DRAM/device access.
231 		 */
232 		plat_params = bl31_get_plat_params();
233 		tegra_memctrl_tzdram_setup(plat_params->tzdram_base,
234 			plat_params->tzdram_size);
235 
236 		/*
237 		 * Set up the TZRAM memory aperture to allow only secure world
238 		 * access
239 		 */
240 		tegra_memctrl_tzram_setup(TEGRA_TZRAM_BASE, TEGRA_TZRAM_SIZE);
241 	}
242 
243 	/*
244 	 * Reset hardware settings.
245 	 */
246 	tegra_soc_pwr_domain_on_finish(target_state);
247 }
248 
249 /*******************************************************************************
250  * Handler called when a power domain has just been powered on after
251  * having been suspended earlier. The target_state encodes the low power state
252  * that each level has woken up from.
253  ******************************************************************************/
254 void tegra_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
255 {
256 	tegra_pwr_domain_on_finish(target_state);
257 }
258 
259 /*******************************************************************************
260  * Handler called when the system wants to be powered off
261  ******************************************************************************/
262 __dead2 void tegra_system_off(void)
263 {
264 	INFO("Powering down system...\n");
265 
266 	tegra_soc_prepare_system_off();
267 }
268 
269 /*******************************************************************************
270  * Handler called when the system wants to be restarted.
271  ******************************************************************************/
272 __dead2 void tegra_system_reset(void)
273 {
274 	INFO("Restarting system...\n");
275 
276 	/* per-SoC system reset handler */
277 	tegra_soc_prepare_system_reset();
278 
279 	/*
280 	 * Program the PMC in order to restart the system.
281 	 */
282 	tegra_pmc_system_reset();
283 }
284 
285 /*******************************************************************************
286  * Handler called to check the validity of the power state parameter.
287  ******************************************************************************/
288 int32_t tegra_validate_power_state(unsigned int power_state,
289 				   psci_power_state_t *req_state)
290 {
291 	assert(req_state);
292 
293 	return tegra_soc_validate_power_state(power_state, req_state);
294 }
295 
296 /*******************************************************************************
297  * Platform handler called to check the validity of the non secure entrypoint.
298  ******************************************************************************/
299 int tegra_validate_ns_entrypoint(uintptr_t entrypoint)
300 {
301 	/*
302 	 * Check if the non secure entrypoint lies within the non
303 	 * secure DRAM.
304 	 */
305 	if ((entrypoint >= TEGRA_DRAM_BASE) && (entrypoint <= TEGRA_DRAM_END))
306 		return PSCI_E_SUCCESS;
307 
308 	return PSCI_E_INVALID_ADDRESS;
309 }
310 
311 /*******************************************************************************
312  * Export the platform handlers to enable psci to invoke them
313  ******************************************************************************/
314 static const plat_psci_ops_t tegra_plat_psci_ops = {
315 	.cpu_standby			= tegra_cpu_standby,
316 	.pwr_domain_on			= tegra_pwr_domain_on,
317 	.pwr_domain_off			= tegra_pwr_domain_off,
318 	.pwr_domain_suspend		= tegra_pwr_domain_suspend,
319 	.pwr_domain_on_finish		= tegra_pwr_domain_on_finish,
320 	.pwr_domain_suspend_finish	= tegra_pwr_domain_suspend_finish,
321 	.pwr_domain_pwr_down_wfi	= tegra_pwr_domain_power_down_wfi,
322 	.system_off			= tegra_system_off,
323 	.system_reset			= tegra_system_reset,
324 	.validate_power_state		= tegra_validate_power_state,
325 	.validate_ns_entrypoint		= tegra_validate_ns_entrypoint,
326 	.get_sys_suspend_power_state	= tegra_get_sys_suspend_power_state,
327 };
328 
329 /*******************************************************************************
330  * Export the platform specific power ops and initialize Power Controller
331  ******************************************************************************/
332 int plat_setup_psci_ops(uintptr_t sec_entrypoint,
333 			const plat_psci_ops_t **psci_ops)
334 {
335 	psci_power_state_t target_state = { { PSCI_LOCAL_STATE_RUN } };
336 
337 	/*
338 	 * Flush entrypoint variable to PoC since it will be
339 	 * accessed after a reset with the caches turned off.
340 	 */
341 	tegra_sec_entry_point = sec_entrypoint;
342 	flush_dcache_range((uint64_t)&tegra_sec_entry_point, sizeof(uint64_t));
343 
344 	/*
345 	 * Reset hardware settings.
346 	 */
347 	tegra_soc_pwr_domain_on_finish(&target_state);
348 
349 	/*
350 	 * Initialize PSCI ops struct
351 	 */
352 	*psci_ops = &tegra_plat_psci_ops;
353 
354 	return 0;
355 }
356 
357 /*******************************************************************************
358  * Platform handler to calculate the proper target power level at the
359  * specified affinity level
360  ******************************************************************************/
361 plat_local_state_t plat_get_target_pwr_state(unsigned int lvl,
362 					     const plat_local_state_t *states,
363 					     unsigned int ncpu)
364 {
365 	return tegra_soc_get_target_pwr_state(lvl, states, ncpu);
366 }
367