blob: 243407d16efd569c05b79cdb889a801c6dfd1ac3 [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/*******************************************************************************
117 * Handler called to check the validity of the power state parameter.
118 ******************************************************************************/
119int32_t tegra_validate_power_state(unsigned int power_state)
120{
121 /* Sanity check the requested state */
122 if (psci_get_pstate_type(power_state) == PSTATE_TYPE_STANDBY) {
123 /*
124 * It's possible to enter standby only on affinity level 0 i.e.
125 * a cpu on Tegra. Ignore any other affinity level.
126 */
127 if (psci_get_pstate_afflvl(power_state) != MPIDR_AFFLVL0)
128 return PSCI_E_INVALID_PARAMS;
129 }
130
131 return PSCI_E_SUCCESS;
132}
133
134/*******************************************************************************
135 * Handler called when an affinity instance is about to be turned on. The
136 * level and mpidr determine the affinity instance.
137 ******************************************************************************/
138int tegra_affinst_on(unsigned long mpidr,
139 unsigned long sec_entrypoint,
140 unsigned int afflvl,
141 unsigned int state)
142{
143 int cpu = mpidr & MPIDR_CPU_MASK;
144
145 /*
146 * Support individual CPU power on only.
147 */
148 if (afflvl > MPIDR_AFFLVL0)
149 return PSCI_E_SUCCESS;
150
151 /*
152 * Flush entrypoint variable to PoC since it will be
153 * accessed after a reset with the caches turned off.
154 */
155 sec_entry_point[cpu] = sec_entrypoint;
156 flush_dcache_range((uint64_t)&sec_entry_point[cpu], sizeof(uint64_t));
157
158 return tegra_prepare_cpu_on(mpidr);
159}
160
161/*******************************************************************************
162 * Handler called when an affinity instance is about to be turned off. The
163 * level determines the affinity instance. The 'state' arg. allows the
164 * platform to decide whether the cluster is being turned off and take apt
165 * actions.
166 *
167 * CAUTION: This function is called with coherent stacks so that caches can be
168 * turned off, flushed and coherency disabled. There is no guarantee that caches
169 * will remain turned on across calls to this function as each affinity level is
170 * dealt with. So do not write & read global variables across calls. It will be
171 * wise to do flush a write to the global to prevent unpredictable results.
172 ******************************************************************************/
173void tegra_affinst_off(unsigned int afflvl, unsigned int state)
174{
175 /*
176 * Support individual CPU power off only.
177 */
178 if (afflvl > MPIDR_AFFLVL0)
179 return;
180
181 tegra_prepare_cpu_off(read_mpidr());
182}
183
184/*******************************************************************************
185 * Handler called when an affinity instance is about to be suspended. The
186 * level and mpidr determine the affinity instance. The 'state' arg. allows the
187 * platform to decide whether the cluster is being turned off and take apt
188 * actions.
189 *
190 * CAUTION: This function is called with coherent stacks so that caches can be
191 * turned off, flushed and coherency disabled. There is no guarantee that caches
192 * will remain turned on across calls to this function as each affinity level is
193 * dealt with. So do not write & read global variables across calls. It will be
194 * wise to flush a write to the global variable, to prevent unpredictable
195 * results.
196 ******************************************************************************/
197void tegra_affinst_suspend(unsigned long sec_entrypoint,
198 unsigned int afflvl,
199 unsigned int state)
200{
201 int id = psci_get_suspend_stateid();
202 int cpu = read_mpidr() & MPIDR_CPU_MASK;
203
204 if (afflvl > PLATFORM_MAX_AFFLVL)
205 return;
206
207 /*
208 * Flush entrypoint variable to PoC since it will be
209 * accessed after a reset with the caches turned off.
210 */
211 sec_entry_point[cpu] = sec_entrypoint;
212 flush_dcache_range((uint64_t)&sec_entry_point[cpu], sizeof(uint64_t));
213
214 tegra_prepare_cpu_suspend(id, afflvl);
215
216 /* disable GICC */
217 tegra_gic_cpuif_deactivate();
218}
219
220/*******************************************************************************
221 * Handler called when an affinity instance has just been powered on after
222 * being turned off earlier. The level determines the affinity instance.
223 * The 'state' arg. allows the platform to decide whether the cluster was
224 * turned off prior to wakeup and do what's necessary to set it up.
225 ******************************************************************************/
226void tegra_affinst_on_finish(unsigned int afflvl, unsigned int state)
227{
228 plat_params_from_bl2_t *plat_params;
229
230 /*
231 * Support individual CPU power on only.
232 */
233 if (afflvl > MPIDR_AFFLVL0)
234 return;
235
236 /*
237 * Initialize the GIC cpu and distributor interfaces
238 */
239 tegra_gic_setup();
240
241 /*
242 * Check if we are exiting from deep sleep.
243 */
244 if (tegra_system_suspended()) {
245
246 /*
247 * Lock scratch registers which hold the CPU vectors.
248 */
249 tegra_pmc_lock_cpu_vectors();
250
251 /*
252 * SMMU configuration.
253 */
254 tegra_memctrl_setup();
255
256 /*
257 * Security configuration to allow DRAM/device access.
258 */
259 plat_params = bl31_get_plat_params();
260 tegra_memctrl_tzdram_setup(tegra_bl31_phys_base,
261 plat_params->tzdram_size);
262 }
263
264 /*
265 * Reset hardware settings.
266 */
267 tegra_prepare_cpu_on_finish(read_mpidr());
268}
269
270/*******************************************************************************
271 * Handler called when an affinity instance has just been powered on after
272 * having been suspended earlier. The level and mpidr determine the affinity
273 * instance.
274 ******************************************************************************/
275void tegra_affinst_suspend_finish(unsigned int afflvl, unsigned int state)
276{
277 if (afflvl == MPIDR_AFFLVL0)
278 tegra_affinst_on_finish(afflvl, state);
279}
280
281/*******************************************************************************
282 * Handler called when the system wants to be powered off
283 ******************************************************************************/
284__dead2 void tegra_system_off(void)
285{
286 ERROR("Tegra System Off: operation not handled.\n");
287 panic();
288}
289
290/*******************************************************************************
291 * Handler called when the system wants to be restarted.
292 ******************************************************************************/
293__dead2 void tegra_system_reset(void)
294{
295 /*
296 * Program the PMC in order to restart the system.
297 */
298 tegra_pmc_system_reset();
299}
300
301/*******************************************************************************
302 * Export the platform handlers to enable psci to invoke them
303 ******************************************************************************/
304static const plat_pm_ops_t tegra_plat_pm_ops = {
305 .affinst_standby = tegra_affinst_standby,
306 .affinst_on = tegra_affinst_on,
307 .affinst_off = tegra_affinst_off,
308 .affinst_suspend = tegra_affinst_suspend,
309 .affinst_on_finish = tegra_affinst_on_finish,
310 .affinst_suspend_finish = tegra_affinst_suspend_finish,
311 .system_off = tegra_system_off,
312 .system_reset = tegra_system_reset,
313 .validate_power_state = tegra_validate_power_state
314};
315
316/*******************************************************************************
317 * Export the platform specific power ops & initialize the fvp power controller
318 ******************************************************************************/
319int platform_setup_pm(const plat_pm_ops_t **plat_ops)
320{
321 /*
322 * Reset hardware settings.
323 */
324 tegra_prepare_cpu_on_finish(read_mpidr());
325
326 /*
327 * Initialize PM ops struct
328 */
329 *plat_ops = &tegra_plat_pm_ops;
330
331 return 0;
332}