xref: /rk3399_ARM-atf/plat/nvidia/tegra/common/tegra_pm.c (revision 31833aff6802a4b5bdc3b7007ce8b1871991e796)
1 /*
2  * Copyright (c) 2015, 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 <debug.h>
37 #include <memctrl.h>
38 #include <mmio.h>
39 #include <platform.h>
40 #include <platform_def.h>
41 #include <pmc.h>
42 #include <psci.h>
43 #include <tegra_def.h>
44 #include <tegra_private.h>
45 
46 extern uint64_t tegra_bl31_phys_base;
47 extern uint64_t sec_entry_point[PLATFORM_CORE_COUNT];
48 static int system_suspended;
49 
50 /*
51  * The following platform setup functions are weakly defined. They
52  * provide typical implementations that will be overridden by a SoC.
53  */
54 #pragma weak tegra_prepare_cpu_suspend
55 #pragma weak tegra_prepare_cpu_on
56 #pragma weak tegra_prepare_cpu_off
57 #pragma weak tegra_prepare_cpu_on_finish
58 
59 int tegra_prepare_cpu_suspend(unsigned int id, unsigned int afflvl)
60 {
61 	return PSCI_E_NOT_SUPPORTED;
62 }
63 
64 int tegra_prepare_cpu_on(unsigned long mpidr)
65 {
66 	return PSCI_E_SUCCESS;
67 }
68 
69 int tegra_prepare_cpu_off(unsigned long mpidr)
70 {
71 	return PSCI_E_SUCCESS;
72 }
73 
74 int tegra_prepare_cpu_on_finish(unsigned long mpidr)
75 {
76 	return PSCI_E_SUCCESS;
77 }
78 
79 /*******************************************************************************
80  * Track system suspend entry.
81  ******************************************************************************/
82 void tegra_pm_system_suspend_entry(void)
83 {
84 	system_suspended = 1;
85 }
86 
87 /*******************************************************************************
88  * Track system suspend exit.
89  ******************************************************************************/
90 void tegra_pm_system_suspend_exit(void)
91 {
92 	system_suspended = 0;
93 }
94 
95 /*******************************************************************************
96  * Get the system suspend state.
97  ******************************************************************************/
98 int tegra_system_suspended(void)
99 {
100 	return system_suspended;
101 }
102 
103 /*******************************************************************************
104  * Handler called when an affinity instance is about to enter standby.
105  ******************************************************************************/
106 void tegra_affinst_standby(unsigned int power_state)
107 {
108 	/*
109 	 * Enter standby state
110 	 * dsb is good practice before using wfi to enter low power states
111 	 */
112 	dsb();
113 	wfi();
114 }
115 
116 /*******************************************************************************
117  * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND`
118  * call to get the `power_state` parameter. This allows the platform to encode
119  * the appropriate State-ID field within the `power_state` parameter which can
120  * be utilized in `affinst_suspend()` to suspend to system affinity level.
121 ******************************************************************************/
122 unsigned int tegra_get_sys_suspend_power_state(void)
123 {
124 	unsigned int power_state;
125 
126 	power_state = psci_make_powerstate(PLAT_SYS_SUSPEND_STATE_ID,
127 			PSTATE_TYPE_POWERDOWN, MPIDR_AFFLVL2);
128 
129 	return power_state;
130 }
131 
132 /*******************************************************************************
133  * Handler called to check the validity of the power state parameter.
134  ******************************************************************************/
135 int32_t tegra_validate_power_state(unsigned int power_state)
136 {
137 	/* Sanity check the requested state */
138 	if (psci_get_pstate_type(power_state) == PSTATE_TYPE_STANDBY) {
139 		/*
140 		 * It's possible to enter standby only on affinity level 0 i.e.
141 		 * a cpu on Tegra. Ignore any other affinity level.
142 		 */
143 		if (psci_get_pstate_afflvl(power_state) != MPIDR_AFFLVL0)
144 			return PSCI_E_INVALID_PARAMS;
145 	}
146 
147 	return PSCI_E_SUCCESS;
148 }
149 
150 /*******************************************************************************
151  * Handler called when an affinity instance is about to be turned on. The
152  * level and mpidr determine the affinity instance.
153  ******************************************************************************/
154 int tegra_affinst_on(unsigned long mpidr,
155 		   unsigned long sec_entrypoint,
156 		   unsigned int afflvl,
157 		   unsigned int state)
158 {
159 	int cpu = mpidr & MPIDR_CPU_MASK;
160 
161 	/*
162 	 * Support individual CPU power on only.
163 	 */
164 	if (afflvl > MPIDR_AFFLVL0)
165 		return PSCI_E_SUCCESS;
166 
167 	/*
168 	 * Flush entrypoint variable to PoC since it will be
169 	 * accessed after a reset with the caches turned off.
170 	 */
171 	sec_entry_point[cpu] = sec_entrypoint;
172 	flush_dcache_range((uint64_t)&sec_entry_point[cpu], sizeof(uint64_t));
173 
174 	return tegra_prepare_cpu_on(mpidr);
175 }
176 
177 /*******************************************************************************
178  * Handler called when an affinity instance is about to be turned off. The
179  * level determines the affinity instance. The 'state' arg. allows the
180  * platform to decide whether the cluster is being turned off and take apt
181  * actions.
182  *
183  * CAUTION: This function is called with coherent stacks so that caches can be
184  * turned off, flushed and coherency disabled. There is no guarantee that caches
185  * will remain turned on across calls to this function as each affinity level is
186  * dealt with. So do not write & read global variables across calls. It will be
187  * wise to do flush a write to the global to prevent unpredictable results.
188  ******************************************************************************/
189 void tegra_affinst_off(unsigned int afflvl, unsigned int state)
190 {
191 	/*
192 	 * Support individual CPU power off only.
193 	 */
194 	if (afflvl > MPIDR_AFFLVL0)
195 		return;
196 
197 	tegra_prepare_cpu_off(read_mpidr());
198 }
199 
200 /*******************************************************************************
201  * Handler called when an affinity instance is about to be suspended. The
202  * level and mpidr determine the affinity instance. The 'state' arg. allows the
203  * platform to decide whether the cluster is being turned off and take apt
204  * actions.
205  *
206  * CAUTION: This function is called with coherent stacks so that caches can be
207  * turned off, flushed and coherency disabled. There is no guarantee that caches
208  * will remain turned on across calls to this function as each affinity level is
209  * dealt with. So do not write & read global variables across calls. It will be
210  * wise to flush a write to the global variable, to prevent unpredictable
211  * results.
212  ******************************************************************************/
213 void tegra_affinst_suspend(unsigned long sec_entrypoint,
214 			unsigned int afflvl,
215 			unsigned int state)
216 {
217 	int id = psci_get_suspend_stateid();
218 	int cpu = read_mpidr() & MPIDR_CPU_MASK;
219 
220 	if (afflvl > PLATFORM_MAX_AFFLVL)
221 		return;
222 
223 	/*
224 	 * Flush entrypoint variable to PoC since it will be
225 	 * accessed after a reset with the caches turned off.
226 	 */
227 	sec_entry_point[cpu] = sec_entrypoint;
228 	flush_dcache_range((uint64_t)&sec_entry_point[cpu], sizeof(uint64_t));
229 
230 	tegra_prepare_cpu_suspend(id, afflvl);
231 
232 	/* disable GICC */
233 	tegra_gic_cpuif_deactivate();
234 }
235 
236 /*******************************************************************************
237  * Handler called when an affinity instance has just been powered on after
238  * being turned off earlier. The level determines the affinity instance.
239  * The 'state' arg. allows the platform to decide whether the cluster was
240  * turned off prior to wakeup and do what's necessary to set it up.
241  ******************************************************************************/
242 void tegra_affinst_on_finish(unsigned int afflvl, unsigned int state)
243 {
244 	plat_params_from_bl2_t *plat_params;
245 
246 	/*
247 	 * Support individual CPU power on only.
248 	 */
249 	if (afflvl > MPIDR_AFFLVL0)
250 		return;
251 
252 	/*
253 	 * Initialize the GIC cpu and distributor interfaces
254 	 */
255 	tegra_gic_setup();
256 
257 	/*
258 	 * Check if we are exiting from deep sleep.
259 	 */
260 	if (tegra_system_suspended()) {
261 
262 		/*
263 		 * Lock scratch registers which hold the CPU vectors.
264 		 */
265 		tegra_pmc_lock_cpu_vectors();
266 
267 		/*
268 		 * SMMU configuration.
269 		 */
270 		tegra_memctrl_setup();
271 
272 		/*
273 		 * Security configuration to allow DRAM/device access.
274 		 */
275 		plat_params = bl31_get_plat_params();
276 		tegra_memctrl_tzdram_setup(tegra_bl31_phys_base,
277 			plat_params->tzdram_size);
278 	}
279 
280 	/*
281 	 * Reset hardware settings.
282 	 */
283 	tegra_prepare_cpu_on_finish(read_mpidr());
284 }
285 
286 /*******************************************************************************
287  * Handler called when an affinity instance has just been powered on after
288  * having been suspended earlier. The level and mpidr determine the affinity
289  * instance.
290  ******************************************************************************/
291 void tegra_affinst_suspend_finish(unsigned int afflvl, unsigned int state)
292 {
293 	if (afflvl == MPIDR_AFFLVL0)
294 		tegra_affinst_on_finish(afflvl, state);
295 }
296 
297 /*******************************************************************************
298  * Handler called when the system wants to be powered off
299  ******************************************************************************/
300 __dead2 void tegra_system_off(void)
301 {
302 	ERROR("Tegra System Off: operation not handled.\n");
303 	panic();
304 }
305 
306 /*******************************************************************************
307  * Handler called when the system wants to be restarted.
308  ******************************************************************************/
309 __dead2 void tegra_system_reset(void)
310 {
311 	/*
312 	 * Program the PMC in order to restart the system.
313 	 */
314 	tegra_pmc_system_reset();
315 }
316 
317 /*******************************************************************************
318  * Export the platform handlers to enable psci to invoke them
319  ******************************************************************************/
320 static const plat_pm_ops_t tegra_plat_pm_ops = {
321 	.affinst_standby	= tegra_affinst_standby,
322 	.affinst_on		= tegra_affinst_on,
323 	.affinst_off		= tegra_affinst_off,
324 	.affinst_suspend	= tegra_affinst_suspend,
325 	.affinst_on_finish	= tegra_affinst_on_finish,
326 	.affinst_suspend_finish	= tegra_affinst_suspend_finish,
327 	.system_off		= tegra_system_off,
328 	.system_reset		= tegra_system_reset,
329 	.validate_power_state	= tegra_validate_power_state,
330 	.get_sys_suspend_power_state = tegra_get_sys_suspend_power_state
331 };
332 
333 /*******************************************************************************
334  * Export the platform specific power ops & initialize the fvp power controller
335  ******************************************************************************/
336 int platform_setup_pm(const plat_pm_ops_t **plat_ops)
337 {
338 	/*
339 	 * Reset hardware settings.
340 	 */
341 	tegra_prepare_cpu_on_finish(read_mpidr());
342 
343 	/*
344 	 * Initialize PM ops struct
345 	 */
346 	*plat_ops = &tegra_plat_pm_ops;
347 
348 	return 0;
349 }
350