blob: 87f72403c849209a16a9dc856e7dd8e51c8cba8b [file] [log] [blame]
Varun Wadekarb316e242015-05-19 16:48:04 +05301/*
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
46extern uint64_t tegra_bl31_phys_base;
47extern uint64_t sec_entry_point[PLATFORM_CORE_COUNT];
48static 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 */
Varun Wadekar254441d2015-07-23 10:07:54 +053054#pragma weak tegra_soc_prepare_cpu_suspend
55#pragma weak tegra_soc_prepare_cpu_on
56#pragma weak tegra_soc_prepare_cpu_off
57#pragma weak tegra_soc_prepare_cpu_on_finish
Varun Wadekarb316e242015-05-19 16:48:04 +053058
Varun Wadekar254441d2015-07-23 10:07:54 +053059int tegra_soc_prepare_cpu_suspend(unsigned int id, unsigned int afflvl)
Varun Wadekarb316e242015-05-19 16:48:04 +053060{
61 return PSCI_E_NOT_SUPPORTED;
62}
63
Varun Wadekar254441d2015-07-23 10:07:54 +053064int tegra_soc_prepare_cpu_on(unsigned long mpidr)
Varun Wadekarb316e242015-05-19 16:48:04 +053065{
66 return PSCI_E_SUCCESS;
67}
68
Varun Wadekar254441d2015-07-23 10:07:54 +053069int tegra_soc_prepare_cpu_off(unsigned long mpidr)
Varun Wadekarb316e242015-05-19 16:48:04 +053070{
71 return PSCI_E_SUCCESS;
72}
73
Varun Wadekar254441d2015-07-23 10:07:54 +053074int tegra_soc_prepare_cpu_on_finish(unsigned long mpidr)
Varun Wadekarb316e242015-05-19 16:48:04 +053075{
76 return PSCI_E_SUCCESS;
77}
78
79/*******************************************************************************
80 * Track system suspend entry.
81 ******************************************************************************/
82void tegra_pm_system_suspend_entry(void)
83{
84 system_suspended = 1;
85}
86
87/*******************************************************************************
88 * Track system suspend exit.
89 ******************************************************************************/
90void tegra_pm_system_suspend_exit(void)
91{
92 system_suspended = 0;
93}
94
95/*******************************************************************************
96 * Get the system suspend state.
97 ******************************************************************************/
98int 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 ******************************************************************************/
106void 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/*******************************************************************************
Varun Wadekar81b13832015-07-03 16:31:28 +0530117 * 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******************************************************************************/
122unsigned 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/*******************************************************************************
Varun Wadekarb316e242015-05-19 16:48:04 +0530133 * Handler called to check the validity of the power state parameter.
134 ******************************************************************************/
135int32_t tegra_validate_power_state(unsigned int power_state)
136{
Varun Wadekar254441d2015-07-23 10:07:54 +0530137 return tegra_soc_validate_power_state(power_state);
Varun Wadekarb316e242015-05-19 16:48:04 +0530138}
139
140/*******************************************************************************
141 * Handler called when an affinity instance is about to be turned on. The
142 * level and mpidr determine the affinity instance.
143 ******************************************************************************/
144int tegra_affinst_on(unsigned long mpidr,
145 unsigned long sec_entrypoint,
146 unsigned int afflvl,
147 unsigned int state)
148{
149 int cpu = mpidr & MPIDR_CPU_MASK;
150
151 /*
152 * Support individual CPU power on only.
153 */
154 if (afflvl > MPIDR_AFFLVL0)
155 return PSCI_E_SUCCESS;
156
157 /*
158 * Flush entrypoint variable to PoC since it will be
159 * accessed after a reset with the caches turned off.
160 */
161 sec_entry_point[cpu] = sec_entrypoint;
162 flush_dcache_range((uint64_t)&sec_entry_point[cpu], sizeof(uint64_t));
163
Varun Wadekar254441d2015-07-23 10:07:54 +0530164 return tegra_soc_prepare_cpu_on(mpidr);
Varun Wadekarb316e242015-05-19 16:48:04 +0530165}
166
167/*******************************************************************************
168 * Handler called when an affinity instance is about to be turned off. The
169 * level determines the affinity instance. The 'state' arg. allows the
170 * platform to decide whether the cluster is being turned off and take apt
171 * actions.
172 *
173 * CAUTION: This function is called with coherent stacks so that caches can be
174 * turned off, flushed and coherency disabled. There is no guarantee that caches
175 * will remain turned on across calls to this function as each affinity level is
176 * dealt with. So do not write & read global variables across calls. It will be
177 * wise to do flush a write to the global to prevent unpredictable results.
178 ******************************************************************************/
179void tegra_affinst_off(unsigned int afflvl, unsigned int state)
180{
181 /*
182 * Support individual CPU power off only.
183 */
184 if (afflvl > MPIDR_AFFLVL0)
185 return;
186
Varun Wadekar254441d2015-07-23 10:07:54 +0530187 tegra_soc_prepare_cpu_off(read_mpidr());
Varun Wadekarb316e242015-05-19 16:48:04 +0530188}
189
190/*******************************************************************************
191 * Handler called when an affinity instance is about to be suspended. The
192 * level and mpidr determine the affinity instance. The 'state' arg. allows the
193 * platform to decide whether the cluster is being turned off and take apt
194 * actions.
195 *
196 * CAUTION: This function is called with coherent stacks so that caches can be
197 * turned off, flushed and coherency disabled. There is no guarantee that caches
198 * will remain turned on across calls to this function as each affinity level is
199 * dealt with. So do not write & read global variables across calls. It will be
200 * wise to flush a write to the global variable, to prevent unpredictable
201 * results.
202 ******************************************************************************/
203void tegra_affinst_suspend(unsigned long sec_entrypoint,
204 unsigned int afflvl,
205 unsigned int state)
206{
207 int id = psci_get_suspend_stateid();
208 int cpu = read_mpidr() & MPIDR_CPU_MASK;
209
210 if (afflvl > PLATFORM_MAX_AFFLVL)
211 return;
212
213 /*
214 * Flush entrypoint variable to PoC since it will be
215 * accessed after a reset with the caches turned off.
216 */
217 sec_entry_point[cpu] = sec_entrypoint;
218 flush_dcache_range((uint64_t)&sec_entry_point[cpu], sizeof(uint64_t));
219
Varun Wadekar254441d2015-07-23 10:07:54 +0530220 tegra_soc_prepare_cpu_suspend(id, afflvl);
Varun Wadekarb316e242015-05-19 16:48:04 +0530221
222 /* disable GICC */
223 tegra_gic_cpuif_deactivate();
224}
225
226/*******************************************************************************
227 * Handler called when an affinity instance has just been powered on after
228 * being turned off earlier. The level determines the affinity instance.
229 * The 'state' arg. allows the platform to decide whether the cluster was
230 * turned off prior to wakeup and do what's necessary to set it up.
231 ******************************************************************************/
232void tegra_affinst_on_finish(unsigned int afflvl, unsigned int state)
233{
234 plat_params_from_bl2_t *plat_params;
235
236 /*
237 * Support individual CPU power on only.
238 */
239 if (afflvl > MPIDR_AFFLVL0)
240 return;
241
242 /*
243 * Initialize the GIC cpu and distributor interfaces
244 */
245 tegra_gic_setup();
246
247 /*
248 * Check if we are exiting from deep sleep.
249 */
250 if (tegra_system_suspended()) {
251
252 /*
253 * Lock scratch registers which hold the CPU vectors.
254 */
255 tegra_pmc_lock_cpu_vectors();
256
257 /*
258 * SMMU configuration.
259 */
260 tegra_memctrl_setup();
261
262 /*
263 * Security configuration to allow DRAM/device access.
264 */
265 plat_params = bl31_get_plat_params();
266 tegra_memctrl_tzdram_setup(tegra_bl31_phys_base,
267 plat_params->tzdram_size);
268 }
269
270 /*
271 * Reset hardware settings.
272 */
Varun Wadekar254441d2015-07-23 10:07:54 +0530273 tegra_soc_prepare_cpu_on_finish(read_mpidr());
Varun Wadekarb316e242015-05-19 16:48:04 +0530274}
275
276/*******************************************************************************
277 * Handler called when an affinity instance has just been powered on after
278 * having been suspended earlier. The level and mpidr determine the affinity
279 * instance.
280 ******************************************************************************/
281void tegra_affinst_suspend_finish(unsigned int afflvl, unsigned int state)
282{
283 if (afflvl == MPIDR_AFFLVL0)
284 tegra_affinst_on_finish(afflvl, state);
285}
286
287/*******************************************************************************
288 * Handler called when the system wants to be powered off
289 ******************************************************************************/
290__dead2 void tegra_system_off(void)
291{
292 ERROR("Tegra System Off: operation not handled.\n");
293 panic();
294}
295
296/*******************************************************************************
297 * Handler called when the system wants to be restarted.
298 ******************************************************************************/
299__dead2 void tegra_system_reset(void)
300{
301 /*
302 * Program the PMC in order to restart the system.
303 */
304 tegra_pmc_system_reset();
305}
306
307/*******************************************************************************
308 * Export the platform handlers to enable psci to invoke them
309 ******************************************************************************/
310static const plat_pm_ops_t tegra_plat_pm_ops = {
311 .affinst_standby = tegra_affinst_standby,
312 .affinst_on = tegra_affinst_on,
313 .affinst_off = tegra_affinst_off,
314 .affinst_suspend = tegra_affinst_suspend,
315 .affinst_on_finish = tegra_affinst_on_finish,
316 .affinst_suspend_finish = tegra_affinst_suspend_finish,
317 .system_off = tegra_system_off,
318 .system_reset = tegra_system_reset,
Varun Wadekar81b13832015-07-03 16:31:28 +0530319 .validate_power_state = tegra_validate_power_state,
320 .get_sys_suspend_power_state = tegra_get_sys_suspend_power_state
Varun Wadekarb316e242015-05-19 16:48:04 +0530321};
322
323/*******************************************************************************
324 * Export the platform specific power ops & initialize the fvp power controller
325 ******************************************************************************/
326int platform_setup_pm(const plat_pm_ops_t **plat_ops)
327{
328 /*
329 * Reset hardware settings.
330 */
Varun Wadekar254441d2015-07-23 10:07:54 +0530331 tegra_soc_prepare_cpu_on_finish(read_mpidr());
Varun Wadekarb316e242015-05-19 16:48:04 +0530332
333 /*
334 * Initialize PM ops struct
335 */
336 *plat_ops = &tegra_plat_pm_ops;
337
338 return 0;
339}