blob: bcaaf412bf1c1fe75fa18a8644fac7b819b89dbb [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 */
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
59int tegra_prepare_cpu_suspend(unsigned int id, unsigned int afflvl)
60{
61 return PSCI_E_NOT_SUPPORTED;
62}
63
64int tegra_prepare_cpu_on(unsigned long mpidr)
65{
66 return PSCI_E_SUCCESS;
67}
68
69int tegra_prepare_cpu_off(unsigned long mpidr)
70{
71 return PSCI_E_SUCCESS;
72}
73
74int tegra_prepare_cpu_on_finish(unsigned long mpidr)
75{
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{
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 ******************************************************************************/
154int 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 ******************************************************************************/
189void 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 ******************************************************************************/
213void 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 ******************************************************************************/
242void 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 ******************************************************************************/
291void 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 ******************************************************************************/
320static 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,
Varun Wadekar81b13832015-07-03 16:31:28 +0530329 .validate_power_state = tegra_validate_power_state,
330 .get_sys_suspend_power_state = tegra_get_sys_suspend_power_state
Varun Wadekarb316e242015-05-19 16:48:04 +0530331};
332
333/*******************************************************************************
334 * Export the platform specific power ops & initialize the fvp power controller
335 ******************************************************************************/
336int 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}