blob: 4c49386bbfae414160cdba7dac2ccc8ee21fea1a [file] [log] [blame]
Varun Wadekarb316e242015-05-19 16:48:04 +05301/*
Varun Wadekarba313282018-02-13 20:31:12 -08002 * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
Varun Wadekarb316e242015-05-19 16:48:04 +05303 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Varun Wadekarb316e242015-05-19 16:48:04 +05305 */
6
Varun Wadekarb316e242015-05-19 16:48:04 +05307#include <assert.h>
Sam Payne71ce6ed2017-05-08 12:42:49 -07008#include <cortex_a57.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00009#include <arch_helpers.h>
10#include <common/debug.h>
11#include <drivers/delay_timer.h>
12#include <lib/mmio.h>
13#include <lib/psci/psci.h>
14#include <plat/common/platform.h>
15
Varun Wadekara6a357f2017-05-05 09:20:59 -070016#include <bpmp.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000017#include <flowctrl.h>
Varun Wadekarb316e242015-05-19 16:48:04 +053018#include <pmc.h>
Varun Wadekara6a357f2017-05-05 09:20:59 -070019#include <platform_def.h>
20#include <security_engine.h>
Varun Wadekarb316e242015-05-19 16:48:04 +053021#include <tegra_def.h>
22#include <tegra_private.h>
Marvin Hsu21eea972017-04-11 11:00:48 +080023#include <tegra_platform.h>
Varun Wadekarb316e242015-05-19 16:48:04 +053024
Varun Wadekar071b7872015-07-08 17:42:02 +053025/*
26 * Register used to clear CPU reset signals. Each CPU has two reset
27 * signals: CPU reset (3:0) and Core reset (19:16).
28 */
29#define CPU_CMPLX_RESET_CLR 0x454
30#define CPU_CORE_RESET_MASK 0x10001
31
Varun Wadekar8b82fae2015-11-09 17:39:28 -080032/* Clock and Reset controller registers for system clock's settings */
33#define SCLK_RATE 0x30
34#define SCLK_BURST_POLICY 0x28
35#define SCLK_BURST_POLICY_DEFAULT 0x10000000
36
Varun Wadekarb316e242015-05-19 16:48:04 +053037static int cpu_powergate_mask[PLATFORM_MAX_CPUS_PER_CLUSTER];
Varun Wadekarba313282018-02-13 20:31:12 -080038static bool tegra_bpmp_available = true;
Varun Wadekarb316e242015-05-19 16:48:04 +053039
Varun Wadekara78bb1b2015-08-07 10:03:00 +053040int32_t tegra_soc_validate_power_state(unsigned int power_state,
41 psci_power_state_t *req_state)
Varun Wadekar254441d2015-07-23 10:07:54 +053042{
Varun Wadekara78bb1b2015-08-07 10:03:00 +053043 int state_id = psci_get_pstate_id(power_state);
Varun Wadekarf07d6de2018-02-27 14:33:57 -080044 const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
Varun Wadekara78bb1b2015-08-07 10:03:00 +053045
Varun Wadekar254441d2015-07-23 10:07:54 +053046 /* Sanity check the requested state id */
Varun Wadekara78bb1b2015-08-07 10:03:00 +053047 switch (state_id) {
Varun Wadekar254441d2015-07-23 10:07:54 +053048 case PSTATE_ID_CORE_POWERDN:
Varun Wadekara78bb1b2015-08-07 10:03:00 +053049 /*
50 * Core powerdown request only for afflvl 0
51 */
Varun Wadekara78bb1b2015-08-07 10:03:00 +053052 req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id & 0xff;
53
54 break;
55
Varun Wadekar254441d2015-07-23 10:07:54 +053056 case PSTATE_ID_CLUSTER_IDLE:
Varun Wadekarba313282018-02-13 20:31:12 -080057
Varun Wadekara78bb1b2015-08-07 10:03:00 +053058 /*
Varun Wadekarba313282018-02-13 20:31:12 -080059 * Cluster idle request for afflvl 0
Varun Wadekara78bb1b2015-08-07 10:03:00 +053060 */
Varun Wadekara6a357f2017-05-05 09:20:59 -070061 req_state->pwr_domain_state[MPIDR_AFFLVL0] = PSTATE_ID_CORE_POWERDN;
Varun Wadekarba313282018-02-13 20:31:12 -080062 req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id;
Varun Wadekara78bb1b2015-08-07 10:03:00 +053063 break;
64
Varun Wadekar254441d2015-07-23 10:07:54 +053065 case PSTATE_ID_SOC_POWERDN:
Varun Wadekarf07d6de2018-02-27 14:33:57 -080066
67 /*
68 * sc7entry-fw must be present in the system when the bpmp
69 * firmware is not present, for a successful System Suspend
70 * entry.
71 */
72 if (!tegra_bpmp_init() && !plat_params->sc7entry_fw_base)
73 return PSCI_E_NOT_SUPPORTED;
74
Varun Wadekara78bb1b2015-08-07 10:03:00 +053075 /*
76 * System powerdown request only for afflvl 2
77 */
Varun Wadekar66231d12017-06-07 09:57:42 -070078 for (uint32_t i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++)
Varun Wadekara78bb1b2015-08-07 10:03:00 +053079 req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
80
81 req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] =
82 PLAT_SYS_SUSPEND_STATE_ID;
83
Varun Wadekar254441d2015-07-23 10:07:54 +053084 break;
85
86 default:
Varun Wadekara78bb1b2015-08-07 10:03:00 +053087 ERROR("%s: unsupported state id (%d)\n", __func__, state_id);
88 return PSCI_E_INVALID_PARAMS;
Varun Wadekar254441d2015-07-23 10:07:54 +053089 }
90
91 return PSCI_E_SUCCESS;
92}
93
Varun Wadekarb91b5fc2017-04-18 11:22:01 -070094/*******************************************************************************
95 * Platform handler to calculate the proper target power level at the
Varun Wadekarba313282018-02-13 20:31:12 -080096 * specified affinity level.
Varun Wadekarb91b5fc2017-04-18 11:22:01 -070097 ******************************************************************************/
98plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl,
99 const plat_local_state_t *states,
100 unsigned int ncpu)
101{
Varun Wadekara6a357f2017-05-05 09:20:59 -0700102 plat_local_state_t target = PSCI_LOCAL_STATE_RUN;
Varun Wadekarb91b5fc2017-04-18 11:22:01 -0700103 int cpu = plat_my_core_pos();
104 int core_pos = read_mpidr() & MPIDR_CPU_MASK;
Varun Wadekarba313282018-02-13 20:31:12 -0800105 uint32_t bpmp_reply, data[3], val;
Varun Wadekara6a357f2017-05-05 09:20:59 -0700106 int ret;
Varun Wadekarb91b5fc2017-04-18 11:22:01 -0700107
108 /* get the power state at this level */
109 if (lvl == MPIDR_AFFLVL1)
110 target = *(states + core_pos);
111 if (lvl == MPIDR_AFFLVL2)
112 target = *(states + cpu);
113
Varun Wadekara6a357f2017-05-05 09:20:59 -0700114 if ((lvl == MPIDR_AFFLVL1) && (target == PSTATE_ID_CLUSTER_IDLE)) {
115
116 /* initialize the bpmp interface */
Varun Wadekara9a3a102017-08-23 10:19:25 -0700117 ret = tegra_bpmp_init();
118 if (ret != 0U) {
Varun Wadekarb91b5fc2017-04-18 11:22:01 -0700119
Varun Wadekara6a357f2017-05-05 09:20:59 -0700120 /* Cluster idle not allowed */
121 target = PSCI_LOCAL_STATE_RUN;
Varun Wadekarba313282018-02-13 20:31:12 -0800122
123 /*******************************************
124 * BPMP is not present, so handle CC6 entry
125 * from the CPU
126 ******************************************/
127
128 /* check if cluster idle state has been enabled */
129 val = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL);
130 if (val == ENABLE_CLOSED_LOOP) {
131 /*
132 * flag to indicate that BPMP firmware is not
133 * available and the CPU has to handle entry/exit
134 * for all power states
135 */
136 tegra_bpmp_available = false;
137
138 /*
139 * Acquire the cluster idle lock to stop
140 * other CPUs from powering up.
141 */
142 tegra_fc_ccplex_pgexit_lock();
143
144 /* Cluster idle only from the last standing CPU */
145 if (tegra_pmc_is_last_on_cpu() && tegra_fc_is_ccx_allowed()) {
146 /* Cluster idle allowed */
147 target = PSTATE_ID_CLUSTER_IDLE;
148 } else {
149 /* release cluster idle lock */
150 tegra_fc_ccplex_pgexit_unlock();
151 }
152 }
Varun Wadekara9a3a102017-08-23 10:19:25 -0700153 } else {
154
Varun Wadekarba313282018-02-13 20:31:12 -0800155 /* Cluster power-down */
Varun Wadekara9a3a102017-08-23 10:19:25 -0700156 data[0] = (uint32_t)cpu;
157 data[1] = TEGRA_PM_CC6;
158 data[2] = TEGRA_PM_SC1;
159 ret = tegra_bpmp_send_receive_atomic(MRQ_DO_IDLE,
160 (void *)&data, (int)sizeof(data),
161 (void *)&bpmp_reply,
162 (int)sizeof(bpmp_reply));
163
Varun Wadekarba313282018-02-13 20:31:12 -0800164 /* check if cluster power down is allowed */
Varun Wadekara9a3a102017-08-23 10:19:25 -0700165 if ((ret != 0L) || (bpmp_reply != BPMP_CCx_ALLOWED)) {
166
Varun Wadekarba313282018-02-13 20:31:12 -0800167 /* Cluster power down not allowed */
Varun Wadekara9a3a102017-08-23 10:19:25 -0700168 target = PSCI_LOCAL_STATE_RUN;
169 }
Varun Wadekara6a357f2017-05-05 09:20:59 -0700170 }
171
Varun Wadekara6a357f2017-05-05 09:20:59 -0700172 } else if (((lvl == MPIDR_AFFLVL2) || (lvl == MPIDR_AFFLVL1)) &&
173 (target == PSTATE_ID_SOC_POWERDN)) {
174
175 /* System Suspend */
176 target = PSTATE_ID_SOC_POWERDN;
177
178 } else {
179 ; /* do nothing */
180 }
181
182 return target;
Varun Wadekarb91b5fc2017-04-18 11:22:01 -0700183}
184
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530185int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
Varun Wadekarb316e242015-05-19 16:48:04 +0530186{
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530187 u_register_t mpidr = read_mpidr();
188 const plat_local_state_t *pwr_domain_state =
189 target_state->pwr_domain_state;
190 unsigned int stateid_afflvl2 = pwr_domain_state[MPIDR_AFFLVL2];
191 unsigned int stateid_afflvl1 = pwr_domain_state[MPIDR_AFFLVL1];
192 unsigned int stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0];
Varun Wadekarba313282018-02-13 20:31:12 -0800193 uint32_t cfg;
Marvin Hsu21eea972017-04-11 11:00:48 +0800194 int ret = PSCI_E_SUCCESS;
Varun Wadekarba313282018-02-13 20:31:12 -0800195 uint32_t val;
Varun Wadekarb316e242015-05-19 16:48:04 +0530196
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530197 if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
Varun Wadekarb316e242015-05-19 16:48:04 +0530198
Harvey Hsieh20e9fef2016-12-28 21:53:18 +0800199 assert((stateid_afflvl0 == PLAT_MAX_OFF_STATE) ||
Marvin Hsu21eea972017-04-11 11:00:48 +0800200 (stateid_afflvl0 == PSTATE_ID_SOC_POWERDN));
Harvey Hsieh20e9fef2016-12-28 21:53:18 +0800201 assert((stateid_afflvl1 == PLAT_MAX_OFF_STATE) ||
Marvin Hsu21eea972017-04-11 11:00:48 +0800202 (stateid_afflvl1 == PSTATE_ID_SOC_POWERDN));
203
204 if (tegra_chipid_is_t210_b01()) {
Varun Wadekara6a357f2017-05-05 09:20:59 -0700205
Marvin Hsu21eea972017-04-11 11:00:48 +0800206 /* Suspend se/se2 and pka1 */
207 if (tegra_se_suspend() != 0) {
208 ret = PSCI_E_INTERN_FAIL;
209 }
Marvin Hsu21eea972017-04-11 11:00:48 +0800210 }
Varun Wadekarb316e242015-05-19 16:48:04 +0530211
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530212 } else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_IDLE) {
Varun Wadekarb316e242015-05-19 16:48:04 +0530213
Varun Wadekara6a357f2017-05-05 09:20:59 -0700214 assert(stateid_afflvl0 == PSTATE_ID_CORE_POWERDN);
Varun Wadekarb316e242015-05-19 16:48:04 +0530215
Varun Wadekarba313282018-02-13 20:31:12 -0800216 if (!tegra_bpmp_available) {
217
Varun Wadekarf07d6de2018-02-27 14:33:57 -0800218 /* Find if the platform uses OVR2/MAX77621 PMIC */
Varun Wadekarba313282018-02-13 20:31:12 -0800219 cfg = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_OUTPUT_CFG);
220 if (cfg & DFLL_OUTPUT_CFG_CLK_EN_BIT) {
Varun Wadekarf07d6de2018-02-27 14:33:57 -0800221 /* OVR2 */
222
223 /* PWM tristate */
Varun Wadekarba313282018-02-13 20:31:12 -0800224 val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM);
225 val |= PINMUX_PWM_TRISTATE;
226 mmio_write_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM, val);
Varun Wadekarf07d6de2018-02-27 14:33:57 -0800227
228 /*
229 * SCRATCH201[1] is being used to identify CPU
230 * PMIC in warmboot code.
231 * 0 : OVR2
232 * 1 : MAX77621
233 */
234 tegra_pmc_write_32(PMC_SCRATCH201, 0x0);
235 } else {
236 /* MAX77621 */
237 tegra_pmc_write_32(PMC_SCRATCH201, 0x2);
Varun Wadekarba313282018-02-13 20:31:12 -0800238 }
239 }
240
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530241 /* Prepare for cluster idle */
242 tegra_fc_cluster_idle(mpidr);
Varun Wadekarb316e242015-05-19 16:48:04 +0530243
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530244 } else if (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN) {
245
246 /* Prepare for cpu powerdn */
247 tegra_fc_cpu_powerdn(mpidr);
248
249 } else {
Varun Wadekara6a357f2017-05-05 09:20:59 -0700250 ERROR("%s: Unknown state id (%d, %d, %d)\n", __func__,
251 stateid_afflvl2, stateid_afflvl1, stateid_afflvl0);
Marvin Hsu21eea972017-04-11 11:00:48 +0800252 ret = PSCI_E_NOT_SUPPORTED;
Varun Wadekarb316e242015-05-19 16:48:04 +0530253 }
254
Marvin Hsu21eea972017-04-11 11:00:48 +0800255 return ret;
Varun Wadekarb316e242015-05-19 16:48:04 +0530256}
257
Harvey Hsieha16d4ea2017-06-15 16:28:43 -0700258int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
259{
260 u_register_t mpidr = read_mpidr();
261 const plat_local_state_t *pwr_domain_state =
262 target_state->pwr_domain_state;
263 unsigned int stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL];
Varun Wadekarf07d6de2018-02-27 14:33:57 -0800264 const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
265 uint32_t val;
Harvey Hsieha16d4ea2017-06-15 16:28:43 -0700266
267 if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
268
269 if (tegra_chipid_is_t210_b01()) {
270 /* Save tzram contents */
271 tegra_se_save_tzram();
272 }
273
Varun Wadekarf07d6de2018-02-27 14:33:57 -0800274 /*
275 * The CPU needs to load the System suspend entry firmware
276 * if nothing is running on the BPMP.
277 */
278 if (!tegra_bpmp_available) {
279
280 /*
281 * BPMP firmware is not running on the co-processor, so
282 * we need to explicitly load the firmware to enable
283 * entry/exit to/from System Suspend and set the BPMP
284 * on its way.
285 */
286
287 /* Power off BPMP before we proceed */
288 tegra_fc_bpmp_off();
289
290 /* Copy the firmware to BPMP's internal RAM */
291 (void)memcpy((void *)(uintptr_t)TEGRA_IRAM_BASE,
292 (const void *)plat_params->sc7entry_fw_base,
293 plat_params->sc7entry_fw_size);
294
295 /* Power on the BPMP and execute from IRAM base */
296 tegra_fc_bpmp_on(TEGRA_IRAM_BASE);
297
298 /* Wait until BPMP powers up */
299 do {
300 val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET);
301 } while (val != SIGN_OF_LIFE);
302 }
303
Harvey Hsieha16d4ea2017-06-15 16:28:43 -0700304 /* enter system suspend */
305 tegra_fc_soc_powerdn(mpidr);
306 }
307
308 return PSCI_E_SUCCESS;
309}
310
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530311int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
Varun Wadekarb316e242015-05-19 16:48:04 +0530312{
Sam Payne71ce6ed2017-05-08 12:42:49 -0700313 const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
Varun Wadekarba313282018-02-13 20:31:12 -0800314 uint32_t cfg;
Varun Wadekarf07d6de2018-02-27 14:33:57 -0800315 uint32_t val, entrypoint = 0;
Varun Wadekarbc787442015-07-27 13:00:50 +0530316
Sam Payne71ce6ed2017-05-08 12:42:49 -0700317 /* platform parameter passed by the previous bootloader */
318 if (plat_params->l2_ecc_parity_prot_dis != 1) {
319 /* Enable ECC Parity Protection for Cortex-A57 CPUs */
320 val = read_l2ctlr_el1();
321 val |= (uint64_t)CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT;
322 write_l2ctlr_el1(val);
323 }
324
Varun Wadekarb316e242015-05-19 16:48:04 +0530325 /*
326 * Check if we are exiting from SOC_POWERDN.
327 */
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530328 if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] ==
329 PLAT_SYS_SUSPEND_STATE_ID) {
Varun Wadekarb316e242015-05-19 16:48:04 +0530330
331 /*
Marvin Hsu21eea972017-04-11 11:00:48 +0800332 * Security engine resume
333 */
334 if (tegra_chipid_is_t210_b01()) {
335 tegra_se_resume();
336 }
337
338 /*
Varun Wadekar6eec6d62016-03-03 13:28:10 -0800339 * Lock scratch registers which hold the CPU vectors
340 */
341 tegra_pmc_lock_cpu_vectors();
342
343 /*
Varun Wadekarbc787442015-07-27 13:00:50 +0530344 * Enable WRAP to INCR burst type conversions for
345 * incoming requests on the AXI slave ports.
346 */
347 val = mmio_read_32(TEGRA_MSELECT_BASE + MSELECT_CONFIG);
348 val &= ~ENABLE_UNSUP_TX_ERRORS;
349 val |= ENABLE_WRAP_TO_INCR_BURSTS;
350 mmio_write_32(TEGRA_MSELECT_BASE + MSELECT_CONFIG, val);
351
352 /*
Varun Wadekarb316e242015-05-19 16:48:04 +0530353 * Restore Boot and Power Management Processor (BPMP) reset
Varun Wadekarf07d6de2018-02-27 14:33:57 -0800354 * address and reset it, if it is supported by the platform.
Varun Wadekarb316e242015-05-19 16:48:04 +0530355 */
Varun Wadekarf07d6de2018-02-27 14:33:57 -0800356 if (!tegra_bpmp_available) {
357 tegra_fc_bpmp_off();
358 } else {
359 entrypoint = tegra_pmc_read_32(PMC_SCRATCH39);
360 tegra_fc_bpmp_on(entrypoint);
361 }
Varun Wadekarba313282018-02-13 20:31:12 -0800362 }
363
364 /*
365 * Check if we are exiting cluster idle state
366 */
367 if (target_state->pwr_domain_state[MPIDR_AFFLVL1] ==
368 PSTATE_ID_CLUSTER_IDLE) {
369
370 if (!tegra_bpmp_available) {
371
372 /* PWM un-tristate */
373 cfg = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_OUTPUT_CFG);
374 if (cfg & DFLL_OUTPUT_CFG_CLK_EN_BIT) {
375 val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM);
376 val &= ~PINMUX_PWM_TRISTATE;
377 mmio_write_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM, val);
378 }
379
380 /* release cluster idle lock */
381 tegra_fc_ccplex_pgexit_unlock();
382 }
Varun Wadekarb316e242015-05-19 16:48:04 +0530383 }
384
385 /*
386 * T210 has a dedicated ARMv7 boot and power mgmt processor, BPMP. It's
387 * used for power management and boot purposes. Inform the BPMP that
388 * we have completed the cluster power up.
389 */
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530390 tegra_fc_lock_active_cluster();
Varun Wadekarb316e242015-05-19 16:48:04 +0530391
392 return PSCI_E_SUCCESS;
393}
394
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530395int tegra_soc_pwr_domain_on(u_register_t mpidr)
Varun Wadekarb316e242015-05-19 16:48:04 +0530396{
397 int cpu = mpidr & MPIDR_CPU_MASK;
Varun Wadekar071b7872015-07-08 17:42:02 +0530398 uint32_t mask = CPU_CORE_RESET_MASK << cpu;
399
400 /* Deassert CPU reset signals */
401 mmio_write_32(TEGRA_CAR_RESET_BASE + CPU_CMPLX_RESET_CLR, mask);
Varun Wadekarb316e242015-05-19 16:48:04 +0530402
403 /* Turn on CPU using flow controller or PMC */
404 if (cpu_powergate_mask[cpu] == 0) {
405 tegra_pmc_cpu_on(cpu);
406 cpu_powergate_mask[cpu] = 1;
407 } else {
408 tegra_fc_cpu_on(cpu);
409 }
410
411 return PSCI_E_SUCCESS;
412}
413
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530414int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
Varun Wadekarb316e242015-05-19 16:48:04 +0530415{
Varun Wadekara78bb1b2015-08-07 10:03:00 +0530416 tegra_fc_cpu_off(read_mpidr() & MPIDR_CPU_MASK);
Varun Wadekarb316e242015-05-19 16:48:04 +0530417 return PSCI_E_SUCCESS;
418}
Varun Wadekar8b82fae2015-11-09 17:39:28 -0800419
420int tegra_soc_prepare_system_reset(void)
421{
422 /*
423 * Set System Clock (SCLK) to POR default so that the clock source
424 * for the PMC APB clock would not be changed due to system reset.
425 */
426 mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_BURST_POLICY,
Marvin Hsu21eea972017-04-11 11:00:48 +0800427 SCLK_BURST_POLICY_DEFAULT);
Varun Wadekar8b82fae2015-11-09 17:39:28 -0800428 mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_RATE, 0);
429
430 /* Wait 1 ms to make sure clock source/device logic is stabilized. */
431 mdelay(1);
432
433 return PSCI_E_SUCCESS;
434}