blob: 095614e42330db9870dfdd46c162f3d3fdfdcbc0 [file] [log] [blame]
Varun Wadekar921b9062015-08-25 17:03:14 +05301/*
Varun Wadekarc2c3a2a2016-01-08 17:38:51 -08002 * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
Varun Wadekar921b9062015-08-25 17:03:14 +05303 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Varun Wadekar921b9062015-08-25 17:03:14 +05305 */
6
Varun Wadekarabd153c2015-09-14 09:31:39 +05307#include <arch.h>
8#include <arch_helpers.h>
Varun Wadekara64806a2016-01-05 15:17:41 -08009#include <assert.h>
10#include <bl_common.h>
11#include <context.h>
12#include <context_mgmt.h>
Varun Wadekarabd153c2015-09-14 09:31:39 +053013#include <debug.h>
Varun Wadekar89645092016-02-09 14:55:44 -080014#include <denver.h>
Varun Wadekarabd153c2015-09-14 09:31:39 +053015#include <mce.h>
Varun Wadekar4a0b37a2016-04-09 00:36:42 -070016#include <platform.h>
Varun Wadekar921b9062015-08-25 17:03:14 +053017#include <psci.h>
Varun Wadekarb8776152016-03-03 13:52:52 -080018#include <smmu.h>
Varun Wadekar93bed2a2016-03-18 13:07:33 -070019#include <string.h>
Varun Wadekar782c83d2017-03-14 14:25:35 -070020#include <t18x_ari.h>
Varun Wadekar921b9062015-08-25 17:03:14 +053021#include <tegra_private.h>
22
Varun Wadekard66ee542016-02-29 10:24:30 -080023extern void prepare_cpu_pwr_dwn(void);
Varun Wadekar93bed2a2016-03-18 13:07:33 -070024extern void tegra186_cpu_reset_handler(void);
Varun Wadekar27155fc2017-04-20 18:56:09 -070025extern uint32_t __tegra186_cpu_reset_handler_end,
26 __tegra186_smmu_context;
Varun Wadekard66ee542016-02-29 10:24:30 -080027
Varun Wadekar42236572016-01-18 19:03:19 -080028/* state id mask */
29#define TEGRA186_STATE_ID_MASK 0xF
30/* constants to get power state's wake time */
Krishna Sitaraman86569d12016-08-18 15:41:21 -070031#define TEGRA186_WAKE_TIME_MASK 0x0FFFFFF0
Varun Wadekar42236572016-01-18 19:03:19 -080032#define TEGRA186_WAKE_TIME_SHIFT 4
Varun Wadekar698e7c62016-03-28 15:05:03 -070033/* default core wake mask for CPU_SUSPEND */
34#define TEGRA186_CORE_WAKE_MASK 0x180c
Varun Wadekarb8776152016-03-03 13:52:52 -080035/* context size to save during system suspend */
Varun Wadekar93bed2a2016-03-18 13:07:33 -070036#define TEGRA186_SE_CONTEXT_SIZE 3
Varun Wadekar42236572016-01-18 19:03:19 -080037
Varun Wadekarb8776152016-03-03 13:52:52 -080038static uint32_t se_regs[TEGRA186_SE_CONTEXT_SIZE];
Mustafa Yigit Bilgenf40bc2c2016-09-02 19:30:22 -070039static struct t18x_psci_percpu_data {
40 unsigned int wake_time;
41} __aligned(CACHE_WRITEBACK_GRANULE) percpu_data[PLATFORM_CORE_COUNT];
Varun Wadekar42236572016-01-18 19:03:19 -080042
Varun Wadekard66ee542016-02-29 10:24:30 -080043/* System power down state */
44uint32_t tegra186_system_powerdn_state = TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF;
45
Varun Wadekarc2c3a2a2016-01-08 17:38:51 -080046int32_t tegra_soc_validate_power_state(unsigned int power_state,
47 psci_power_state_t *req_state)
Varun Wadekar921b9062015-08-25 17:03:14 +053048{
Varun Wadekar42236572016-01-18 19:03:19 -080049 int state_id = psci_get_pstate_id(power_state) & TEGRA186_STATE_ID_MASK;
Varun Wadekar4a0b37a2016-04-09 00:36:42 -070050 int cpu = plat_my_core_pos();
Varun Wadekar89645092016-02-09 14:55:44 -080051
Krishna Sitaraman86569d12016-08-18 15:41:21 -070052 /* save the core wake time (in TSC ticks)*/
53 percpu_data[cpu].wake_time = (power_state & TEGRA186_WAKE_TIME_MASK)
54 << TEGRA186_WAKE_TIME_SHIFT;
Varun Wadekar42236572016-01-18 19:03:19 -080055
Mustafa Yigit Bilgenf40bc2c2016-09-02 19:30:22 -070056 /*
57 * Clean percpu_data[cpu] to DRAM. This needs to be done to ensure that
58 * the correct value is read in tegra_soc_pwr_domain_suspend(), which
59 * is called with caches disabled. It is possible to read a stale value
60 * from DRAM in that function, because the L2 cache is not flushed
61 * unless the cluster is entering CC6/CC7.
62 */
63 clean_dcache_range((uint64_t)&percpu_data[cpu],
64 sizeof(percpu_data[cpu]));
65
Varun Wadekar42236572016-01-18 19:03:19 -080066 /* Sanity check the requested state id */
67 switch (state_id) {
68 case PSTATE_ID_CORE_IDLE:
69 case PSTATE_ID_CORE_POWERDN:
Varun Wadekar4a0b37a2016-04-09 00:36:42 -070070
71 /* Core powerdown request */
Varun Wadekar42236572016-01-18 19:03:19 -080072 req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id;
Varun Wadekar4a0b37a2016-04-09 00:36:42 -070073 req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id;
Varun Wadekar42236572016-01-18 19:03:19 -080074
75 break;
76
77 default:
78 ERROR("%s: unsupported state id (%d)\n", __func__, state_id);
79 return PSCI_E_INVALID_PARAMS;
80 }
81
82 return PSCI_E_SUCCESS;
83}
84
85int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
86{
87 const plat_local_state_t *pwr_domain_state;
Varun Wadekarb8776152016-03-03 13:52:52 -080088 unsigned int stateid_afflvl0, stateid_afflvl2;
Varun Wadekar4a0b37a2016-04-09 00:36:42 -070089 int cpu = plat_my_core_pos();
Varun Wadekar93bed2a2016-03-18 13:07:33 -070090 plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
Varun Wadekar4a0b37a2016-04-09 00:36:42 -070091 mce_cstate_info_t cstate_info = { 0 };
Varun Wadekar93bed2a2016-03-18 13:07:33 -070092 uint64_t smmu_ctx_base;
Varun Wadekarb8776152016-03-03 13:52:52 -080093 uint32_t val;
94
Varun Wadekar42236572016-01-18 19:03:19 -080095 /* get the state ID */
96 pwr_domain_state = target_state->pwr_domain_state;
97 stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0] &
98 TEGRA186_STATE_ID_MASK;
Varun Wadekarb8776152016-03-03 13:52:52 -080099 stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
100 TEGRA186_STATE_ID_MASK;
Varun Wadekar42236572016-01-18 19:03:19 -0800101
Varun Wadekar4a0b37a2016-04-09 00:36:42 -0700102 if ((stateid_afflvl0 == PSTATE_ID_CORE_IDLE) ||
103 (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN)) {
Varun Wadekar42236572016-01-18 19:03:19 -0800104
Varun Wadekar4a0b37a2016-04-09 00:36:42 -0700105 /* Enter CPU idle/powerdown */
106 val = (stateid_afflvl0 == PSTATE_ID_CORE_IDLE) ?
107 TEGRA_ARI_CORE_C6 : TEGRA_ARI_CORE_C7;
108 (void)mce_command_handler(MCE_CMD_ENTER_CSTATE, val,
Mustafa Yigit Bilgenf40bc2c2016-09-02 19:30:22 -0700109 percpu_data[cpu].wake_time, 0);
Varun Wadekarc2c3a2a2016-01-08 17:38:51 -0800110
Varun Wadekarb8776152016-03-03 13:52:52 -0800111 } else if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
112
Varun Wadekarb8776152016-03-03 13:52:52 -0800113 /* save SE registers */
114 se_regs[0] = mmio_read_32(TEGRA_SE0_BASE +
115 SE_MUTEX_WATCHDOG_NS_LIMIT);
116 se_regs[1] = mmio_read_32(TEGRA_RNG1_BASE +
117 RNG_MUTEX_WATCHDOG_NS_LIMIT);
118 se_regs[2] = mmio_read_32(TEGRA_PKA1_BASE +
119 PKA_MUTEX_WATCHDOG_NS_LIMIT);
120
121 /* save 'Secure Boot' Processor Feature Config Register */
122 val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG);
123 mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV6, val);
124
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700125 /* save SMMU context to TZDRAM */
126 smmu_ctx_base = params_from_bl2->tzdram_base +
Varun Wadekar27155fc2017-04-20 18:56:09 -0700127 ((uintptr_t)&__tegra186_smmu_context -
128 (uintptr_t)tegra186_cpu_reset_handler);
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700129 tegra_smmu_save_context((uintptr_t)smmu_ctx_base);
Varun Wadekarb8776152016-03-03 13:52:52 -0800130
131 /* Prepare for system suspend */
Varun Wadekar4a0b37a2016-04-09 00:36:42 -0700132 cstate_info.cluster = TEGRA_ARI_CLUSTER_CC7;
133 cstate_info.system = TEGRA_ARI_SYSTEM_SC7;
134 cstate_info.system_state_force = 1;
135 cstate_info.update_wake_mask = 1;
136 mce_update_cstate_info(&cstate_info);
Varun Wadekarb8776152016-03-03 13:52:52 -0800137
Varun Wadekara9002bb2016-03-28 15:11:43 -0700138 /* Loop until system suspend is allowed */
139 do {
140 val = mce_command_handler(MCE_CMD_IS_SC7_ALLOWED,
141 TEGRA_ARI_CORE_C7,
142 MCE_CORE_SLEEP_TIME_INFINITE,
143 0);
144 } while (val == 0);
145
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700146 /* Instruct the MCE to enter system suspend state */
Varun Wadekarb8776152016-03-03 13:52:52 -0800147 (void)mce_command_handler(MCE_CMD_ENTER_CSTATE,
148 TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0);
Varun Wadekar921b9062015-08-25 17:03:14 +0530149 }
150
151 return PSCI_E_SUCCESS;
152}
Varun Wadekarabd153c2015-09-14 09:31:39 +0530153
Varun Wadekar4a0b37a2016-04-09 00:36:42 -0700154/*******************************************************************************
155 * Platform handler to calculate the proper target power level at the
156 * specified affinity level
157 ******************************************************************************/
158plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl,
159 const plat_local_state_t *states,
160 unsigned int ncpu)
161{
162 plat_local_state_t target = *states;
163 int cpu = plat_my_core_pos(), ret, cluster_powerdn = 1;
164 int core_pos = read_mpidr() & MPIDR_CPU_MASK;
165 mce_cstate_info_t cstate_info = { 0 };
166
Varun Wadekar4e49a7b2017-04-06 17:33:31 -0700167 /* get the power state at this level */
168 if (lvl == MPIDR_AFFLVL1)
169 target = *(states + core_pos);
170 if (lvl == MPIDR_AFFLVL2)
171 target = *(states + cpu);
Varun Wadekar4a0b37a2016-04-09 00:36:42 -0700172
173 /* CPU suspend */
174 if (lvl == MPIDR_AFFLVL1 && target == PSTATE_ID_CORE_POWERDN) {
175
176 /* Program default wake mask */
177 cstate_info.wake_mask = TEGRA186_CORE_WAKE_MASK;
178 cstate_info.update_wake_mask = 1;
179 mce_update_cstate_info(&cstate_info);
180
181 /* Check if CCx state is allowed. */
182 ret = mce_command_handler(MCE_CMD_IS_CCX_ALLOWED,
Mustafa Yigit Bilgenf40bc2c2016-09-02 19:30:22 -0700183 TEGRA_ARI_CORE_C7, percpu_data[cpu].wake_time,
184 0);
Varun Wadekar4a0b37a2016-04-09 00:36:42 -0700185 if (ret)
186 return PSTATE_ID_CORE_POWERDN;
187 }
188
189 /* CPU off */
190 if (lvl == MPIDR_AFFLVL1 && target == PLAT_MAX_OFF_STATE) {
191
192 /* find out the number of ON cpus in the cluster */
193 do {
194 target = *states++;
195 if (target != PLAT_MAX_OFF_STATE)
196 cluster_powerdn = 0;
197 } while (--ncpu);
198
199 /* Enable cluster powerdn from last CPU in the cluster */
200 if (cluster_powerdn) {
201
202 /* Enable CC7 state and turn off wake mask */
203 cstate_info.cluster = TEGRA_ARI_CLUSTER_CC7;
204 cstate_info.update_wake_mask = 1;
205 mce_update_cstate_info(&cstate_info);
206
207 /* Check if CCx state is allowed. */
208 ret = mce_command_handler(MCE_CMD_IS_CCX_ALLOWED,
209 TEGRA_ARI_CORE_C7,
210 MCE_CORE_SLEEP_TIME_INFINITE,
211 0);
212 if (ret)
213 return PSTATE_ID_CORE_POWERDN;
214
215 } else {
216
217 /* Turn off wake_mask */
218 cstate_info.update_wake_mask = 1;
219 mce_update_cstate_info(&cstate_info);
220 }
221 }
222
223 /* System Suspend */
Varun Wadekar4e49a7b2017-04-06 17:33:31 -0700224 if (((lvl == MPIDR_AFFLVL2) || (lvl == MPIDR_AFFLVL1)) &&
225 (target == PSTATE_ID_SOC_POWERDN))
Varun Wadekar4a0b37a2016-04-09 00:36:42 -0700226 return PSTATE_ID_SOC_POWERDN;
227
228 /* default state */
229 return PSCI_LOCAL_STATE_RUN;
230}
231
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700232int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
233{
234 const plat_local_state_t *pwr_domain_state =
235 target_state->pwr_domain_state;
236 plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
237 unsigned int stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
238 TEGRA186_STATE_ID_MASK;
Steven Kao235e9c32016-12-23 15:43:17 +0800239 uint64_t val;
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700240
241 if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
242 /*
243 * The TZRAM loses power when we enter system suspend. To
244 * allow graceful exit from system suspend, we need to copy
245 * BL3-1 over to TZDRAM.
246 */
247 val = params_from_bl2->tzdram_base +
248 ((uintptr_t)&__tegra186_cpu_reset_handler_end -
249 (uintptr_t)tegra186_cpu_reset_handler);
250 memcpy16((void *)(uintptr_t)val, (void *)(uintptr_t)BL31_BASE,
251 (uintptr_t)&__BL31_END__ - (uintptr_t)BL31_BASE);
252 }
253
254 return PSCI_E_SUCCESS;
255}
256
Varun Wadekarc2c3a2a2016-01-08 17:38:51 -0800257int tegra_soc_pwr_domain_on(u_register_t mpidr)
Varun Wadekarabd153c2015-09-14 09:31:39 +0530258{
Varun Wadekar66231d12017-06-07 09:57:42 -0700259 uint32_t target_cpu = mpidr & MPIDR_CPU_MASK;
260 uint32_t target_cluster = (mpidr & MPIDR_CLUSTER_MASK) >>
Varun Wadekarabd153c2015-09-14 09:31:39 +0530261 MPIDR_AFFINITY_BITS;
262
263 if (target_cluster > MPIDR_AFFLVL1) {
264 ERROR("%s: unsupported CPU (0x%lx)\n", __func__, mpidr);
265 return PSCI_E_NOT_PRESENT;
266 }
267
268 /* construct the target CPU # */
269 target_cpu |= (target_cluster << 2);
270
271 mce_command_handler(MCE_CMD_ONLINE_CORE, target_cpu, 0, 0);
272
273 return PSCI_E_SUCCESS;
274}
275
Varun Wadekarb8776152016-03-03 13:52:52 -0800276int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
277{
Varun Wadekar5a402562016-04-29 11:25:46 -0700278 int stateid_afflvl2 = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL];
279 int stateid_afflvl0 = target_state->pwr_domain_state[MPIDR_AFFLVL0];
Varun Wadekar4a0b37a2016-04-09 00:36:42 -0700280 mce_cstate_info_t cstate_info = { 0 };
Varun Wadekarb8776152016-03-03 13:52:52 -0800281
282 /*
Varun Wadekar5a402562016-04-29 11:25:46 -0700283 * Reset power state info for CPUs when onlining, we set
284 * deepest power when offlining a core but that may not be
285 * requested by non-secure sw which controls idle states. It
286 * will re-init this info from non-secure software when the
287 * core come online.
Varun Wadekard2da47a2016-04-09 00:40:45 -0700288 */
Varun Wadekar5a402562016-04-29 11:25:46 -0700289 if (stateid_afflvl0 == PLAT_MAX_OFF_STATE) {
290
Varun Wadekar4a0b37a2016-04-09 00:36:42 -0700291 cstate_info.cluster = TEGRA_ARI_CLUSTER_CC1;
292 cstate_info.update_wake_mask = 1;
293 mce_update_cstate_info(&cstate_info);
Varun Wadekar5a402562016-04-29 11:25:46 -0700294 }
Varun Wadekard2da47a2016-04-09 00:40:45 -0700295
296 /*
Varun Wadekarb8776152016-03-03 13:52:52 -0800297 * Check if we are exiting from deep sleep and restore SE
298 * context if we are.
299 */
Varun Wadekar5a402562016-04-29 11:25:46 -0700300 if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
301
Varun Wadekarb8776152016-03-03 13:52:52 -0800302 mmio_write_32(TEGRA_SE0_BASE + SE_MUTEX_WATCHDOG_NS_LIMIT,
303 se_regs[0]);
304 mmio_write_32(TEGRA_RNG1_BASE + RNG_MUTEX_WATCHDOG_NS_LIMIT,
305 se_regs[1]);
306 mmio_write_32(TEGRA_PKA1_BASE + PKA_MUTEX_WATCHDOG_NS_LIMIT,
307 se_regs[2]);
308
309 /* Init SMMU */
310 tegra_smmu_init();
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700311
312 /*
Varun Wadekar4a0b37a2016-04-09 00:36:42 -0700313 * Reset power state info for the last core doing SC7
314 * entry and exit, we set deepest power state as CC7
315 * and SC7 for SC7 entry which may not be requested by
316 * non-secure SW which controls idle states.
Varun Wadekar93bed2a2016-03-18 13:07:33 -0700317 */
Varun Wadekar4a0b37a2016-04-09 00:36:42 -0700318 cstate_info.cluster = TEGRA_ARI_CLUSTER_CC7;
319 cstate_info.system = TEGRA_ARI_SYSTEM_SC1;
320 cstate_info.update_wake_mask = 1;
321 mce_update_cstate_info(&cstate_info);
Varun Wadekarb8776152016-03-03 13:52:52 -0800322 }
323
324 return PSCI_E_SUCCESS;
325}
326
Varun Wadekarc2c3a2a2016-01-08 17:38:51 -0800327int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
Varun Wadekarabd153c2015-09-14 09:31:39 +0530328{
Varun Wadekare26a55a2016-02-26 11:09:21 -0800329 int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
Varun Wadekara64806a2016-01-05 15:17:41 -0800330
Varun Wadekare26a55a2016-02-26 11:09:21 -0800331 /* Disable Denver's DCO operations */
332 if (impl == DENVER_IMPL)
333 denver_disable_dco();
334
Varun Wadekarabd153c2015-09-14 09:31:39 +0530335 /* Turn off CPU */
Varun Wadekar4a0b37a2016-04-09 00:36:42 -0700336 (void)mce_command_handler(MCE_CMD_ENTER_CSTATE, TEGRA_ARI_CORE_C7,
Varun Wadekar89645092016-02-09 14:55:44 -0800337 MCE_CORE_SLEEP_TIME_INFINITE, 0);
Varun Wadekar4a0b37a2016-04-09 00:36:42 -0700338
339 return PSCI_E_SUCCESS;
Varun Wadekarabd153c2015-09-14 09:31:39 +0530340}
Varun Wadekar782c83d2017-03-14 14:25:35 -0700341
342__dead2 void tegra_soc_prepare_system_off(void)
343{
Varun Wadekar4a0b37a2016-04-09 00:36:42 -0700344 mce_cstate_info_t cstate_info = { 0 };
Varun Wadekard66ee542016-02-29 10:24:30 -0800345 uint32_t val;
346
347 if (tegra186_system_powerdn_state == TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF) {
348
349 /* power off the entire system */
350 mce_enter_ccplex_state(tegra186_system_powerdn_state);
351
352 } else if (tegra186_system_powerdn_state == TEGRA_ARI_SYSTEM_SC8) {
353
Varun Wadekara9002bb2016-03-28 15:11:43 -0700354 /* Prepare for quasi power down */
Varun Wadekar4a0b37a2016-04-09 00:36:42 -0700355 cstate_info.cluster = TEGRA_ARI_CLUSTER_CC7;
356 cstate_info.system = TEGRA_ARI_SYSTEM_SC8;
357 cstate_info.system_state_force = 1;
358 cstate_info.update_wake_mask = 1;
359 mce_update_cstate_info(&cstate_info);
Varun Wadekara9002bb2016-03-28 15:11:43 -0700360
Varun Wadekard66ee542016-02-29 10:24:30 -0800361 /* loop until other CPUs power down */
362 do {
363 val = mce_command_handler(MCE_CMD_IS_SC7_ALLOWED,
364 TEGRA_ARI_CORE_C7,
365 MCE_CORE_SLEEP_TIME_INFINITE,
366 0);
367 } while (val == 0);
368
Varun Wadekard66ee542016-02-29 10:24:30 -0800369 /* Enter quasi power down state */
370 (void)mce_command_handler(MCE_CMD_ENTER_CSTATE,
371 TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0);
372
373 /* disable GICC */
374 tegra_gic_cpuif_deactivate();
375
376 /* power down core */
377 prepare_cpu_pwr_dwn();
378
Varun Wadekar4a0b37a2016-04-09 00:36:42 -0700379 /* flush L1/L2 data caches */
380 dcsw_op_all(DCCISW);
381
Varun Wadekard66ee542016-02-29 10:24:30 -0800382 } else {
383 ERROR("%s: unsupported power down state (%d)\n", __func__,
384 tegra186_system_powerdn_state);
385 }
386
387 wfi();
388
389 /* wait for the system to power down */
390 for (;;) {
391 ;
392 }
Varun Wadekar782c83d2017-03-14 14:25:35 -0700393}
Varun Wadekar38020c92016-01-07 14:36:12 -0800394
395int tegra_soc_prepare_system_reset(void)
396{
397 mce_enter_ccplex_state(TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT);
398
399 return PSCI_E_SUCCESS;
400}