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