blob: 8b7a0590303d9e798f7b90aa72a85611c6870066 [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;
Varun Wadekara78bb1b2015-08-07 10:03:00 +053047extern uint64_t tegra_sec_entry_point;
Varun Wadekarb316e242015-05-19 16:48:04 +053048
49/*
50 * The following platform setup functions are weakly defined. They
51 * provide typical implementations that will be overridden by a SoC.
52 */
Varun Wadekara78bb1b2015-08-07 10:03:00 +053053#pragma weak tegra_soc_pwr_domain_suspend
54#pragma weak tegra_soc_pwr_domain_on
55#pragma weak tegra_soc_pwr_domain_off
56#pragma weak tegra_soc_pwr_domain_on_finish
Varun Wadekar8b82fae2015-11-09 17:39:28 -080057#pragma weak tegra_soc_prepare_system_reset
Varun Wadekarb316e242015-05-19 16:48:04 +053058
Varun Wadekara78bb1b2015-08-07 10:03:00 +053059int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
Varun Wadekarb316e242015-05-19 16:48:04 +053060{
61 return PSCI_E_NOT_SUPPORTED;
62}
63
Varun Wadekara78bb1b2015-08-07 10:03:00 +053064int tegra_soc_pwr_domain_on(u_register_t mpidr)
Varun Wadekarb316e242015-05-19 16:48:04 +053065{
66 return PSCI_E_SUCCESS;
67}
68
Varun Wadekara78bb1b2015-08-07 10:03:00 +053069int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
Varun Wadekarb316e242015-05-19 16:48:04 +053070{
71 return PSCI_E_SUCCESS;
72}
73
Varun Wadekara78bb1b2015-08-07 10:03:00 +053074int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
Varun Wadekarb316e242015-05-19 16:48:04 +053075{
76 return PSCI_E_SUCCESS;
77}
78
Varun Wadekar8b82fae2015-11-09 17:39:28 -080079int tegra_soc_prepare_system_reset(void)
80{
81 return PSCI_E_SUCCESS;
82}
83
Varun Wadekarb316e242015-05-19 16:48:04 +053084/*******************************************************************************
Varun Wadekara78bb1b2015-08-07 10:03:00 +053085 * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND`
86 * call to get the `power_state` parameter. This allows the platform to encode
87 * the appropriate State-ID field within the `power_state` parameter which can
88 * be utilized in `pwr_domain_suspend()` to suspend to system affinity level.
89******************************************************************************/
90void tegra_get_sys_suspend_power_state(psci_power_state_t *req_state)
Varun Wadekarb316e242015-05-19 16:48:04 +053091{
Varun Wadekara78bb1b2015-08-07 10:03:00 +053092 /* lower affinities use PLAT_MAX_OFF_STATE */
93 for (int i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++)
94 req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
Varun Wadekarb316e242015-05-19 16:48:04 +053095
Varun Wadekara78bb1b2015-08-07 10:03:00 +053096 /* max affinity uses system suspend state id */
97 req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = PSTATE_ID_SOC_POWERDN;
Varun Wadekarb316e242015-05-19 16:48:04 +053098}
99
100/*******************************************************************************
101 * Handler called when an affinity instance is about to enter standby.
102 ******************************************************************************/
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530103void tegra_cpu_standby(plat_local_state_t cpu_state)
Varun Wadekarb316e242015-05-19 16:48:04 +0530104{
105 /*
106 * Enter standby state
107 * dsb is good practice before using wfi to enter low power states
108 */
109 dsb();
110 wfi();
111}
112
113/*******************************************************************************
Varun Wadekarb316e242015-05-19 16:48:04 +0530114 * Handler called when an affinity instance is about to be turned on. The
115 * level and mpidr determine the affinity instance.
116 ******************************************************************************/
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530117int tegra_pwr_domain_on(u_register_t mpidr)
Varun Wadekarb316e242015-05-19 16:48:04 +0530118{
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530119 return tegra_soc_pwr_domain_on(mpidr);
Varun Wadekarb316e242015-05-19 16:48:04 +0530120}
121
122/*******************************************************************************
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530123 * Handler called when a power domain is about to be turned off. The
124 * target_state encodes the power state that each level should transition to.
Varun Wadekarb316e242015-05-19 16:48:04 +0530125 ******************************************************************************/
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530126void tegra_pwr_domain_off(const psci_power_state_t *target_state)
Varun Wadekarb316e242015-05-19 16:48:04 +0530127{
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530128 tegra_soc_pwr_domain_off(target_state);
Varun Wadekarb316e242015-05-19 16:48:04 +0530129}
130
131/*******************************************************************************
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530132 * Handler called when called when a power domain is about to be suspended. The
133 * target_state encodes the power state that each level should transition to.
Varun Wadekarb316e242015-05-19 16:48:04 +0530134 ******************************************************************************/
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530135void tegra_pwr_domain_suspend(const psci_power_state_t *target_state)
Varun Wadekarb316e242015-05-19 16:48:04 +0530136{
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530137 tegra_soc_pwr_domain_suspend(target_state);
Varun Wadekarb316e242015-05-19 16:48:04 +0530138
139 /* disable GICC */
140 tegra_gic_cpuif_deactivate();
141}
142
143/*******************************************************************************
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530144 * Handler called when a power domain has just been powered on after
145 * being turned off earlier. The target_state encodes the low power state that
146 * each level has woken up from.
Varun Wadekarb316e242015-05-19 16:48:04 +0530147 ******************************************************************************/
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530148void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state)
Varun Wadekarb316e242015-05-19 16:48:04 +0530149{
150 plat_params_from_bl2_t *plat_params;
151
152 /*
Varun Wadekarb316e242015-05-19 16:48:04 +0530153 * Initialize the GIC cpu and distributor interfaces
154 */
155 tegra_gic_setup();
156
157 /*
158 * Check if we are exiting from deep sleep.
159 */
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530160 if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] ==
161 PSTATE_ID_SOC_POWERDN) {
Varun Wadekarb316e242015-05-19 16:48:04 +0530162
163 /*
164 * Lock scratch registers which hold the CPU vectors.
165 */
166 tegra_pmc_lock_cpu_vectors();
167
168 /*
169 * SMMU configuration.
170 */
171 tegra_memctrl_setup();
172
173 /*
174 * Security configuration to allow DRAM/device access.
175 */
176 plat_params = bl31_get_plat_params();
Varun Wadekar6bb62462015-10-06 12:49:31 +0530177 tegra_memctrl_tzdram_setup(plat_params->tzdram_base,
Varun Wadekarb316e242015-05-19 16:48:04 +0530178 plat_params->tzdram_size);
179 }
180
181 /*
182 * Reset hardware settings.
183 */
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530184 tegra_soc_pwr_domain_on_finish(target_state);
Varun Wadekarb316e242015-05-19 16:48:04 +0530185}
186
187/*******************************************************************************
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530188 * Handler called when a power domain has just been powered on after
189 * having been suspended earlier. The target_state encodes the low power state
190 * that each level has woken up from.
Varun Wadekarb316e242015-05-19 16:48:04 +0530191 ******************************************************************************/
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530192void tegra_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
Varun Wadekarb316e242015-05-19 16:48:04 +0530193{
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530194 tegra_pwr_domain_on_finish(target_state);
Varun Wadekarb316e242015-05-19 16:48:04 +0530195}
196
197/*******************************************************************************
198 * Handler called when the system wants to be powered off
199 ******************************************************************************/
200__dead2 void tegra_system_off(void)
201{
202 ERROR("Tegra System Off: operation not handled.\n");
203 panic();
204}
205
206/*******************************************************************************
207 * Handler called when the system wants to be restarted.
208 ******************************************************************************/
209__dead2 void tegra_system_reset(void)
210{
Varun Wadekar8b82fae2015-11-09 17:39:28 -0800211 /* per-SoC system reset handler */
212 tegra_soc_prepare_system_reset();
213
Varun Wadekarb316e242015-05-19 16:48:04 +0530214 /*
215 * Program the PMC in order to restart the system.
216 */
217 tegra_pmc_system_reset();
218}
219
220/*******************************************************************************
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530221 * Handler called to check the validity of the power state parameter.
222 ******************************************************************************/
223int32_t tegra_validate_power_state(unsigned int power_state,
224 psci_power_state_t *req_state)
225{
226 int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
227
228 assert(req_state);
229
230 if (pwr_lvl > PLAT_MAX_PWR_LVL)
231 return PSCI_E_INVALID_PARAMS;
232
233 return tegra_soc_validate_power_state(power_state, req_state);
234}
235
236/*******************************************************************************
237 * Platform handler called to check the validity of the non secure entrypoint.
238 ******************************************************************************/
239int tegra_validate_ns_entrypoint(uintptr_t entrypoint)
240{
241 /*
242 * Check if the non secure entrypoint lies within the non
243 * secure DRAM.
244 */
245 if ((entrypoint >= TEGRA_DRAM_BASE) && (entrypoint <= TEGRA_DRAM_END))
246 return PSCI_E_SUCCESS;
247
248 return PSCI_E_INVALID_ADDRESS;
249}
250
251/*******************************************************************************
Varun Wadekarb316e242015-05-19 16:48:04 +0530252 * Export the platform handlers to enable psci to invoke them
253 ******************************************************************************/
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530254static const plat_psci_ops_t tegra_plat_psci_ops = {
255 .cpu_standby = tegra_cpu_standby,
256 .pwr_domain_on = tegra_pwr_domain_on,
257 .pwr_domain_off = tegra_pwr_domain_off,
258 .pwr_domain_suspend = tegra_pwr_domain_suspend,
259 .pwr_domain_on_finish = tegra_pwr_domain_on_finish,
260 .pwr_domain_suspend_finish = tegra_pwr_domain_suspend_finish,
261 .system_off = tegra_system_off,
262 .system_reset = tegra_system_reset,
263 .validate_power_state = tegra_validate_power_state,
264 .validate_ns_entrypoint = tegra_validate_ns_entrypoint,
265 .get_sys_suspend_power_state = tegra_get_sys_suspend_power_state,
Varun Wadekarb316e242015-05-19 16:48:04 +0530266};
267
268/*******************************************************************************
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530269 * Export the platform specific power ops and initialize Power Controller
Varun Wadekarb316e242015-05-19 16:48:04 +0530270 ******************************************************************************/
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530271int plat_setup_psci_ops(uintptr_t sec_entrypoint,
272 const plat_psci_ops_t **psci_ops)
Varun Wadekarb316e242015-05-19 16:48:04 +0530273{
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530274 psci_power_state_t target_state = { { PSCI_LOCAL_STATE_RUN } };
275
276 /*
277 * Flush entrypoint variable to PoC since it will be
278 * accessed after a reset with the caches turned off.
279 */
280 tegra_sec_entry_point = sec_entrypoint;
281 flush_dcache_range((uint64_t)&tegra_sec_entry_point, sizeof(uint64_t));
282
Varun Wadekarb316e242015-05-19 16:48:04 +0530283 /*
284 * Reset hardware settings.
285 */
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530286 tegra_soc_pwr_domain_on_finish(&target_state);
Varun Wadekarb316e242015-05-19 16:48:04 +0530287
288 /*
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530289 * Initialize PSCI ops struct
Varun Wadekarb316e242015-05-19 16:48:04 +0530290 */
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530291 *psci_ops = &tegra_plat_psci_ops;
Varun Wadekarb316e242015-05-19 16:48:04 +0530292
293 return 0;
294}