blob: c2c73f63063f3076f500855fdd21850e468c7d0d [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 Wadekar8b82fae2015-11-09 17:39:28 -080058#pragma weak tegra_soc_prepare_system_reset
Varun Wadekarb316e242015-05-19 16:48:04 +053059
Varun Wadekar254441d2015-07-23 10:07:54 +053060int tegra_soc_prepare_cpu_suspend(unsigned int id, unsigned int afflvl)
Varun Wadekarb316e242015-05-19 16:48:04 +053061{
62 return PSCI_E_NOT_SUPPORTED;
63}
64
Varun Wadekar254441d2015-07-23 10:07:54 +053065int tegra_soc_prepare_cpu_on(unsigned long mpidr)
Varun Wadekarb316e242015-05-19 16:48:04 +053066{
67 return PSCI_E_SUCCESS;
68}
69
Varun Wadekar254441d2015-07-23 10:07:54 +053070int tegra_soc_prepare_cpu_off(unsigned long mpidr)
Varun Wadekarb316e242015-05-19 16:48:04 +053071{
72 return PSCI_E_SUCCESS;
73}
74
Varun Wadekar254441d2015-07-23 10:07:54 +053075int tegra_soc_prepare_cpu_on_finish(unsigned long mpidr)
Varun Wadekarb316e242015-05-19 16:48:04 +053076{
77 return PSCI_E_SUCCESS;
78}
79
Varun Wadekar8b82fae2015-11-09 17:39:28 -080080int tegra_soc_prepare_system_reset(void)
81{
82 return PSCI_E_SUCCESS;
83}
84
Varun Wadekarb316e242015-05-19 16:48:04 +053085/*******************************************************************************
86 * Track system suspend entry.
87 ******************************************************************************/
88void tegra_pm_system_suspend_entry(void)
89{
90 system_suspended = 1;
91}
92
93/*******************************************************************************
94 * Track system suspend exit.
95 ******************************************************************************/
96void tegra_pm_system_suspend_exit(void)
97{
98 system_suspended = 0;
99}
100
101/*******************************************************************************
102 * Get the system suspend state.
103 ******************************************************************************/
104int tegra_system_suspended(void)
105{
106 return system_suspended;
107}
108
109/*******************************************************************************
110 * Handler called when an affinity instance is about to enter standby.
111 ******************************************************************************/
112void tegra_affinst_standby(unsigned int power_state)
113{
114 /*
115 * Enter standby state
116 * dsb is good practice before using wfi to enter low power states
117 */
118 dsb();
119 wfi();
120}
121
122/*******************************************************************************
Varun Wadekar81b13832015-07-03 16:31:28 +0530123 * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND`
124 * call to get the `power_state` parameter. This allows the platform to encode
125 * the appropriate State-ID field within the `power_state` parameter which can
126 * be utilized in `affinst_suspend()` to suspend to system affinity level.
127******************************************************************************/
128unsigned int tegra_get_sys_suspend_power_state(void)
129{
130 unsigned int power_state;
131
132 power_state = psci_make_powerstate(PLAT_SYS_SUSPEND_STATE_ID,
133 PSTATE_TYPE_POWERDOWN, MPIDR_AFFLVL2);
134
135 return power_state;
136}
137
138/*******************************************************************************
Varun Wadekarb316e242015-05-19 16:48:04 +0530139 * Handler called to check the validity of the power state parameter.
140 ******************************************************************************/
141int32_t tegra_validate_power_state(unsigned int power_state)
142{
Varun Wadekar254441d2015-07-23 10:07:54 +0530143 return tegra_soc_validate_power_state(power_state);
Varun Wadekarb316e242015-05-19 16:48:04 +0530144}
145
146/*******************************************************************************
147 * Handler called when an affinity instance is about to be turned on. The
148 * level and mpidr determine the affinity instance.
149 ******************************************************************************/
150int tegra_affinst_on(unsigned long mpidr,
151 unsigned long sec_entrypoint,
152 unsigned int afflvl,
153 unsigned int state)
154{
155 int cpu = mpidr & MPIDR_CPU_MASK;
156
157 /*
158 * Support individual CPU power on only.
159 */
160 if (afflvl > MPIDR_AFFLVL0)
161 return PSCI_E_SUCCESS;
162
163 /*
164 * Flush entrypoint variable to PoC since it will be
165 * accessed after a reset with the caches turned off.
166 */
167 sec_entry_point[cpu] = sec_entrypoint;
168 flush_dcache_range((uint64_t)&sec_entry_point[cpu], sizeof(uint64_t));
169
Varun Wadekar254441d2015-07-23 10:07:54 +0530170 return tegra_soc_prepare_cpu_on(mpidr);
Varun Wadekarb316e242015-05-19 16:48:04 +0530171}
172
173/*******************************************************************************
174 * Handler called when an affinity instance is about to be turned off. The
175 * level determines the affinity instance. The 'state' arg. allows the
176 * platform to decide whether the cluster is being turned off and take apt
177 * actions.
178 *
179 * CAUTION: This function is called with coherent stacks so that caches can be
180 * turned off, flushed and coherency disabled. There is no guarantee that caches
181 * will remain turned on across calls to this function as each affinity level is
182 * dealt with. So do not write & read global variables across calls. It will be
183 * wise to do flush a write to the global to prevent unpredictable results.
184 ******************************************************************************/
185void tegra_affinst_off(unsigned int afflvl, unsigned int state)
186{
187 /*
188 * Support individual CPU power off only.
189 */
190 if (afflvl > MPIDR_AFFLVL0)
191 return;
192
Varun Wadekar254441d2015-07-23 10:07:54 +0530193 tegra_soc_prepare_cpu_off(read_mpidr());
Varun Wadekarb316e242015-05-19 16:48:04 +0530194}
195
196/*******************************************************************************
197 * Handler called when an affinity instance is about to be suspended. The
198 * level and mpidr determine the affinity instance. The 'state' arg. allows the
199 * platform to decide whether the cluster is being turned off and take apt
200 * actions.
201 *
202 * CAUTION: This function is called with coherent stacks so that caches can be
203 * turned off, flushed and coherency disabled. There is no guarantee that caches
204 * will remain turned on across calls to this function as each affinity level is
205 * dealt with. So do not write & read global variables across calls. It will be
206 * wise to flush a write to the global variable, to prevent unpredictable
207 * results.
208 ******************************************************************************/
209void tegra_affinst_suspend(unsigned long sec_entrypoint,
210 unsigned int afflvl,
211 unsigned int state)
212{
213 int id = psci_get_suspend_stateid();
214 int cpu = read_mpidr() & MPIDR_CPU_MASK;
215
216 if (afflvl > PLATFORM_MAX_AFFLVL)
217 return;
218
219 /*
220 * Flush entrypoint variable to PoC since it will be
221 * accessed after a reset with the caches turned off.
222 */
223 sec_entry_point[cpu] = sec_entrypoint;
224 flush_dcache_range((uint64_t)&sec_entry_point[cpu], sizeof(uint64_t));
225
Varun Wadekar254441d2015-07-23 10:07:54 +0530226 tegra_soc_prepare_cpu_suspend(id, afflvl);
Varun Wadekarb316e242015-05-19 16:48:04 +0530227
228 /* disable GICC */
229 tegra_gic_cpuif_deactivate();
230}
231
232/*******************************************************************************
233 * Handler called when an affinity instance has just been powered on after
234 * being turned off earlier. The level determines the affinity instance.
235 * The 'state' arg. allows the platform to decide whether the cluster was
236 * turned off prior to wakeup and do what's necessary to set it up.
237 ******************************************************************************/
238void tegra_affinst_on_finish(unsigned int afflvl, unsigned int state)
239{
240 plat_params_from_bl2_t *plat_params;
241
242 /*
243 * Support individual CPU power on only.
244 */
245 if (afflvl > MPIDR_AFFLVL0)
246 return;
247
248 /*
249 * Initialize the GIC cpu and distributor interfaces
250 */
251 tegra_gic_setup();
252
253 /*
254 * Check if we are exiting from deep sleep.
255 */
256 if (tegra_system_suspended()) {
257
258 /*
259 * Lock scratch registers which hold the CPU vectors.
260 */
261 tegra_pmc_lock_cpu_vectors();
262
263 /*
264 * SMMU configuration.
265 */
266 tegra_memctrl_setup();
267
268 /*
269 * Security configuration to allow DRAM/device access.
270 */
271 plat_params = bl31_get_plat_params();
272 tegra_memctrl_tzdram_setup(tegra_bl31_phys_base,
273 plat_params->tzdram_size);
274 }
275
276 /*
277 * Reset hardware settings.
278 */
Varun Wadekar254441d2015-07-23 10:07:54 +0530279 tegra_soc_prepare_cpu_on_finish(read_mpidr());
Varun Wadekarb316e242015-05-19 16:48:04 +0530280}
281
282/*******************************************************************************
283 * Handler called when an affinity instance has just been powered on after
284 * having been suspended earlier. The level and mpidr determine the affinity
285 * instance.
286 ******************************************************************************/
287void tegra_affinst_suspend_finish(unsigned int afflvl, unsigned int state)
288{
289 if (afflvl == MPIDR_AFFLVL0)
290 tegra_affinst_on_finish(afflvl, state);
291}
292
293/*******************************************************************************
294 * Handler called when the system wants to be powered off
295 ******************************************************************************/
296__dead2 void tegra_system_off(void)
297{
298 ERROR("Tegra System Off: operation not handled.\n");
299 panic();
300}
301
302/*******************************************************************************
303 * Handler called when the system wants to be restarted.
304 ******************************************************************************/
305__dead2 void tegra_system_reset(void)
306{
Varun Wadekar8b82fae2015-11-09 17:39:28 -0800307 /* per-SoC system reset handler */
308 tegra_soc_prepare_system_reset();
309
Varun Wadekarb316e242015-05-19 16:48:04 +0530310 /*
311 * Program the PMC in order to restart the system.
312 */
313 tegra_pmc_system_reset();
314}
315
316/*******************************************************************************
317 * Export the platform handlers to enable psci to invoke them
318 ******************************************************************************/
319static const plat_pm_ops_t tegra_plat_pm_ops = {
320 .affinst_standby = tegra_affinst_standby,
321 .affinst_on = tegra_affinst_on,
322 .affinst_off = tegra_affinst_off,
323 .affinst_suspend = tegra_affinst_suspend,
324 .affinst_on_finish = tegra_affinst_on_finish,
325 .affinst_suspend_finish = tegra_affinst_suspend_finish,
326 .system_off = tegra_system_off,
327 .system_reset = tegra_system_reset,
Varun Wadekar81b13832015-07-03 16:31:28 +0530328 .validate_power_state = tegra_validate_power_state,
329 .get_sys_suspend_power_state = tegra_get_sys_suspend_power_state
Varun Wadekarb316e242015-05-19 16:48:04 +0530330};
331
332/*******************************************************************************
333 * Export the platform specific power ops & initialize the fvp power controller
334 ******************************************************************************/
335int platform_setup_pm(const plat_pm_ops_t **plat_ops)
336{
337 /*
338 * Reset hardware settings.
339 */
Varun Wadekar254441d2015-07-23 10:07:54 +0530340 tegra_soc_prepare_cpu_on_finish(read_mpidr());
Varun Wadekarb316e242015-05-19 16:48:04 +0530341
342 /*
343 * Initialize PM ops struct
344 */
345 *plat_ops = &tegra_plat_pm_ops;
346
347 return 0;
348}