plat_psci_handlers.c 16.4 KB
Newer Older
1
/*
2
 * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
3
 * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
4
 *
dp-arm's avatar
dp-arm committed
5
 * SPDX-License-Identifier: BSD-3-Clause
6
7
8
 */

#include <assert.h>
9
#include <cortex_a57.h>
10
11
12
13
14
15
16
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>
#include <lib/psci/psci.h>
#include <plat/common/platform.h>

17
#include <bpmp.h>
18
#include <flowctrl.h>
19
#include <lib/utils.h>
20
#include <memctrl.h>
21
#include <pmc.h>
22
23
#include <platform_def.h>
#include <security_engine.h>
24
25
#include <tegra_def.h>
#include <tegra_private.h>
26
#include <tegra_platform.h>
27

28
29
30
31
32
33
34
/*
 * Register used to clear CPU reset signals. Each CPU has two reset
 * signals: CPU reset (3:0) and Core reset (19:16).
 */
#define CPU_CMPLX_RESET_CLR		0x454
#define CPU_CORE_RESET_MASK		0x10001

35
36
37
38
39
/* Clock and Reset controller registers for system clock's settings */
#define SCLK_RATE			0x30
#define SCLK_BURST_POLICY		0x28
#define SCLK_BURST_POLICY_DEFAULT	0x10000000

40
static int cpu_powergate_mask[PLATFORM_MAX_CPUS_PER_CLUSTER];
41
static bool tegra_bpmp_available = true;
42

43
44
int32_t tegra_soc_validate_power_state(unsigned int power_state,
					psci_power_state_t *req_state)
45
{
46
	int state_id = psci_get_pstate_id(power_state);
47
	const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
48

49
	/* Sanity check the requested state id */
50
	switch (state_id) {
51
	case PSTATE_ID_CORE_POWERDN:
52
53
54
55
56
57
58
		/*
		 * Core powerdown request only for afflvl 0
		 */
		req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id & 0xff;

		break;

59
	case PSTATE_ID_CLUSTER_IDLE:
60

61
		/*
62
		 * Cluster idle request for afflvl 0
63
		 */
64
		req_state->pwr_domain_state[MPIDR_AFFLVL0] = PSTATE_ID_CORE_POWERDN;
65
		req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id;
66
67
		break;

68
	case PSTATE_ID_SOC_POWERDN:
69
70
71
72
73
74
75
76
77

		/*
		 * sc7entry-fw must be present in the system when the bpmp
		 * firmware is not present, for a successful System Suspend
		 * entry.
		 */
		if (!tegra_bpmp_init() && !plat_params->sc7entry_fw_base)
			return PSCI_E_NOT_SUPPORTED;

78
79
80
		/*
		 * System powerdown request only for afflvl 2
		 */
81
		for (uint32_t i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++)
82
83
84
85
86
			req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;

		req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] =
			PLAT_SYS_SUSPEND_STATE_ID;

87
88
89
		break;

	default:
90
91
		ERROR("%s: unsupported state id (%d)\n", __func__, state_id);
		return PSCI_E_INVALID_PARAMS;
92
93
94
95
96
	}

	return PSCI_E_SUCCESS;
}

97
98
/*******************************************************************************
 * Platform handler to calculate the proper target power level at the
99
 * specified affinity level.
100
101
102
103
104
 ******************************************************************************/
plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl,
					     const plat_local_state_t *states,
					     unsigned int ncpu)
{
105
	plat_local_state_t target = PSCI_LOCAL_STATE_RUN;
106
107
	int cpu = plat_my_core_pos();
	int core_pos = read_mpidr() & MPIDR_CPU_MASK;
108
	uint32_t bpmp_reply, data[3], val;
109
	int ret;
110
111
112
113
114
115
116

	/* get the power state at this level */
	if (lvl == MPIDR_AFFLVL1)
		target = *(states + core_pos);
	if (lvl == MPIDR_AFFLVL2)
		target = *(states + cpu);

117
118
119
	if ((lvl == MPIDR_AFFLVL1) && (target == PSTATE_ID_CLUSTER_IDLE)) {

		/* initialize the bpmp interface */
120
121
		ret = tegra_bpmp_init();
		if (ret != 0U) {
122

123
124
125
126
127
128
129
			/*
			 * flag to indicate that BPMP firmware is not
			 * available and the CPU has to handle entry/exit
			 * for all power states
			 */
			tegra_bpmp_available = false;

130
131
			/* Cluster idle not allowed */
			target = PSCI_LOCAL_STATE_RUN;
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

			/*******************************************
			 * BPMP is not present, so handle CC6 entry
			 * from the CPU
			 ******************************************/

			/* check if cluster idle state has been enabled */
			val = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL);
			if (val == ENABLE_CLOSED_LOOP) {
				/*
				 * Acquire the cluster idle lock to stop
				 * other CPUs from powering up.
				 */
				tegra_fc_ccplex_pgexit_lock();

				/* Cluster idle only from the last standing CPU */
				if (tegra_pmc_is_last_on_cpu() && tegra_fc_is_ccx_allowed()) {
					/* Cluster idle allowed */
					target = PSTATE_ID_CLUSTER_IDLE;
				} else {
					/* release cluster idle lock */
					tegra_fc_ccplex_pgexit_unlock();
				}
			}
156
157
		} else {

158
			/* Cluster power-down */
159
160
161
162
163
164
165
166
			data[0] = (uint32_t)cpu;
			data[1] = TEGRA_PM_CC6;
			data[2] = TEGRA_PM_SC1;
			ret = tegra_bpmp_send_receive_atomic(MRQ_DO_IDLE,
					(void *)&data, (int)sizeof(data),
					(void *)&bpmp_reply,
					(int)sizeof(bpmp_reply));

167
			/* check if cluster power down is allowed */
168
169
			if ((ret != 0L) || (bpmp_reply != BPMP_CCx_ALLOWED)) {

170
				/* Cluster power down not allowed */
171
172
				target = PSCI_LOCAL_STATE_RUN;
			}
173
		}
174

175
176
177
178
179
180
181
182
183
184
185
	} else if (((lvl == MPIDR_AFFLVL2) || (lvl == MPIDR_AFFLVL1)) &&
	    (target == PSTATE_ID_SOC_POWERDN)) {

		/* System Suspend */
		target = PSTATE_ID_SOC_POWERDN;

	} else {
		; /* do nothing */
	}

	return target;
186
187
}

188
189
190
191
192
193
int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state)
{
	(void)cpu_state;
	return PSCI_E_SUCCESS;
}

194
int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
195
{
196
197
198
199
200
201
	u_register_t mpidr = read_mpidr();
	const plat_local_state_t *pwr_domain_state =
		target_state->pwr_domain_state;
	unsigned int stateid_afflvl2 = pwr_domain_state[MPIDR_AFFLVL2];
	unsigned int stateid_afflvl1 = pwr_domain_state[MPIDR_AFFLVL1];
	unsigned int stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0];
202
	uint32_t cfg;
203
	int ret = PSCI_E_SUCCESS;
204
	uint32_t val;
205

206
	if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
207

208
		assert((stateid_afflvl0 == PLAT_MAX_OFF_STATE) ||
209
			(stateid_afflvl0 == PSTATE_ID_SOC_POWERDN));
210
		assert((stateid_afflvl1 == PLAT_MAX_OFF_STATE) ||
211
212
213
			(stateid_afflvl1 == PSTATE_ID_SOC_POWERDN));

		if (tegra_chipid_is_t210_b01()) {
214

215
216
217
218
219
			/* Suspend se/se2 and pka1 */
			if (tegra_se_suspend() != 0) {
				ret = PSCI_E_INTERN_FAIL;
			}
		}
220

221
	} else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_IDLE) {
222

223
		assert(stateid_afflvl0 == PSTATE_ID_CORE_POWERDN);
224

225
226
		if (!tegra_bpmp_available) {

227
228
229
230
231
232
233
234
235
			/*
			 * When disabled, DFLL loses its state. Enable
			 * open loop state for the DFLL as we dont want
			 * garbage values being written to the pmic
			 * when we enter cluster idle state.
			 */
			mmio_write_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL,
				      ENABLE_OPEN_LOOP);

236
			/* Find if the platform uses OVR2/MAX77621 PMIC */
237
238
			cfg = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_OUTPUT_CFG);
			if (cfg & DFLL_OUTPUT_CFG_CLK_EN_BIT) {
239
240
241
				/* OVR2 */

				/* PWM tristate */
242
243
244
				val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM);
				val |= PINMUX_PWM_TRISTATE;
				mmio_write_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM, val);
245
246
247
248
249
250
251
252
253
254
255

				/*
				 * SCRATCH201[1] is being used to identify CPU
				 * PMIC in warmboot code.
				 * 0 : OVR2
				 * 1 : MAX77621
				 */
				tegra_pmc_write_32(PMC_SCRATCH201, 0x0);
			} else {
				/* MAX77621 */
				tegra_pmc_write_32(PMC_SCRATCH201, 0x2);
256
257
258
			}
		}

259
260
		/* Prepare for cluster idle */
		tegra_fc_cluster_idle(mpidr);
261

262
263
264
265
266
267
	} else if (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN) {

		/* Prepare for cpu powerdn */
		tegra_fc_cpu_powerdn(mpidr);

	} else {
268
269
		ERROR("%s: Unknown state id (%d, %d, %d)\n", __func__,
			stateid_afflvl2, stateid_afflvl1, stateid_afflvl0);
270
		ret = PSCI_E_NOT_SUPPORTED;
271
272
	}

273
	return ret;
274
275
}

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
static void tegra_reset_all_dma_masters(void)
{
	uint32_t val, mask;

	/*
	 * Reset all possible DMA masters in the system.
	 */
	val = GPU_RESET_BIT;
	mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET, val);

	val = NVENC_RESET_BIT | TSECB_RESET_BIT | APE_RESET_BIT |
	      NVJPG_RESET_BIT | NVDEC_RESET_BIT;
	mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_Y, val);

	val = HOST1X_RESET_BIT | ISP_RESET_BIT | USBD_RESET_BIT |
	      VI_RESET_BIT | SDMMC4_RESET_BIT | SDMMC1_RESET_BIT |
	      SDMMC2_RESET_BIT;
	mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_L, val);

	val = USB2_RESET_BIT | APBDMA_RESET_BIT | AHBDMA_RESET_BIT;
	mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_H, val);

	val = XUSB_DEV_RESET_BIT | XUSB_HOST_RESET_BIT | TSEC_RESET_BIT |
	      PCIE_RESET_BIT | SDMMC3_RESET_BIT;
	mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_U, val);

	val = SE_RESET_BIT | HDA_RESET_BIT | SATA_RESET_BIT;
	mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_V, val);

	/*
	 * If any of the DMA masters are still alive, assume
	 * that the system has been compromised and reboot.
	 */
	val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET);
	mask = GPU_RESET_BIT;
	if ((val & mask) != mask)
		tegra_pmc_system_reset();

	mask = NVENC_RESET_BIT | TSECB_RESET_BIT | APE_RESET_BIT |
	      NVJPG_RESET_BIT | NVDEC_RESET_BIT;
	val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_Y);
	if ((val & mask) != mask)
		tegra_pmc_system_reset();

	mask = HOST1X_RESET_BIT | ISP_RESET_BIT | USBD_RESET_BIT |
	       VI_RESET_BIT | SDMMC4_RESET_BIT | SDMMC1_RESET_BIT |
	       SDMMC2_RESET_BIT;
	val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_L);
	if ((val & mask) != mask)
		tegra_pmc_system_reset();

	mask = USB2_RESET_BIT | APBDMA_RESET_BIT | AHBDMA_RESET_BIT;
	val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_H);
	if ((val & mask) != mask)
		tegra_pmc_system_reset();

	mask = XUSB_DEV_RESET_BIT | XUSB_HOST_RESET_BIT | TSEC_RESET_BIT |
	       PCIE_RESET_BIT | SDMMC3_RESET_BIT;
	val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_U);
	if ((val & mask) != mask)
		tegra_pmc_system_reset();

	val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_V);
	mask = SE_RESET_BIT | HDA_RESET_BIT | SATA_RESET_BIT;
	if ((val & mask) != mask)
		tegra_pmc_system_reset();
}

344
345
346
347
348
349
int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
{
	u_register_t mpidr = read_mpidr();
	const plat_local_state_t *pwr_domain_state =
		target_state->pwr_domain_state;
	unsigned int stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL];
350
351
	const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
	uint32_t val;
352
353
354
355
356
357
358
359

	if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {

		if (tegra_chipid_is_t210_b01()) {
			/* Save tzram contents */
			tegra_se_save_tzram();
		}

360
361
362
		/* de-init the interface */
		tegra_bpmp_suspend();

363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
		/*
		 * The CPU needs to load the System suspend entry firmware
		 * if nothing is running on the BPMP.
		 */
		if (!tegra_bpmp_available) {

			/*
			 * BPMP firmware is not running on the co-processor, so
			 * we need to explicitly load the firmware to enable
			 * entry/exit to/from System Suspend and set the BPMP
			 * on its way.
			 */

			/* Power off BPMP before we proceed */
			tegra_fc_bpmp_off();

379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
			/* bond out IRAM banks B, C and D */
			mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_BOND_OUT_U,
				IRAM_B_LOCK_BIT | IRAM_C_LOCK_BIT |
				IRAM_D_LOCK_BIT);

			/* bond out APB/AHB DMAs */
			mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_BOND_OUT_H,
				APB_DMA_LOCK_BIT | AHB_DMA_LOCK_BIT);

			/* Power off BPMP before we proceed */
			tegra_fc_bpmp_off();

			/*
			 * Reset all the hardware blocks that can act as DMA
			 * masters on the bus.
			 */
			tegra_reset_all_dma_masters();

397
398
399
400
401
402
403
404
405
			/*
			 * Mark PMC as accessible to the non-secure world
			 * to allow the COP to execute System Suspend
			 * sequence
			 */
			val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE);
			val &= ~PMC_SECURITY_EN_BIT;
			mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val);

406
407
408
409
			/* clean up IRAM of any cruft */
			zeromem((void *)(uintptr_t)TEGRA_IRAM_BASE,
					TEGRA_IRAM_A_SIZE);

410
411
			/* Copy the firmware to BPMP's internal RAM */
			(void)memcpy((void *)(uintptr_t)TEGRA_IRAM_BASE,
412
413
				(const void *)(plat_params->sc7entry_fw_base + SC7ENTRY_FW_HEADER_SIZE_BYTES),
				plat_params->sc7entry_fw_size - SC7ENTRY_FW_HEADER_SIZE_BYTES);
414
415
416
417
418
419
420
421
422
423

			/* Power on the BPMP and execute from IRAM base */
			tegra_fc_bpmp_on(TEGRA_IRAM_BASE);

			/* Wait until BPMP powers up */
			do {
				val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET);
			} while (val != SIGN_OF_LIFE);
		}

424
425
426
427
428
429
430
		/* enter system suspend */
		tegra_fc_soc_powerdn(mpidr);
	}

	return PSCI_E_SUCCESS;
}

431
432
433
434
435
int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state)
{
	return PSCI_E_NOT_SUPPORTED;
}

436
int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
437
{
438
	const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
439
	uint32_t cfg;
440
	uint32_t val, entrypoint = 0;
441
	uint64_t offset;
442

443
444
445
446
447
448
449
450
	/* platform parameter passed by the previous bootloader */
	if (plat_params->l2_ecc_parity_prot_dis != 1) {
		/* Enable ECC Parity Protection for Cortex-A57 CPUs */
		val = read_l2ctlr_el1();
		val |= (uint64_t)CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT;
		write_l2ctlr_el1(val);
	}

451
452
453
	/*
	 * Check if we are exiting from SOC_POWERDN.
	 */
454
455
	if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] ==
			PLAT_SYS_SUSPEND_STATE_ID) {
456

457
458
459
460
461
462
463
		/*
		 * Security engine resume
		 */
		if (tegra_chipid_is_t210_b01()) {
			tegra_se_resume();
		}

464
465
466
467
468
		/*
		 * Lock scratch registers which hold the CPU vectors
		 */
		tegra_pmc_lock_cpu_vectors();

469
470
471
472
473
474
475
476
477
		/*
		 * Enable WRAP to INCR burst type conversions for
		 * incoming requests on the AXI slave ports.
		 */
		val = mmio_read_32(TEGRA_MSELECT_BASE + MSELECT_CONFIG);
		val &= ~ENABLE_UNSUP_TX_ERRORS;
		val |= ENABLE_WRAP_TO_INCR_BURSTS;
		mmio_write_32(TEGRA_MSELECT_BASE + MSELECT_CONFIG, val);

478
479
		/*
		 * Restore Boot and Power Management Processor (BPMP) reset
480
		 * address and reset it, if it is supported by the platform.
481
		 */
482
483
484
485
486
		if (!tegra_bpmp_available) {
			tegra_fc_bpmp_off();
		} else {
			entrypoint = tegra_pmc_read_32(PMC_SCRATCH39);
			tegra_fc_bpmp_on(entrypoint);
487
488
489

			/* initialise the interface */
			tegra_bpmp_resume();
490
		}
491
492

		if (plat_params->sc7entry_fw_base != 0U) {
493
			/* sc7entry-fw is part of TZDRAM area */
494
495
496
			offset = plat_params->tzdram_base - plat_params->sc7entry_fw_base;
			tegra_memctrl_tzdram_setup(plat_params->sc7entry_fw_base,
				plat_params->tzdram_size + offset);
497
		}
498

499
		if (!tegra_chipid_is_t210_b01()) {
500
501
502
503
			/* restrict PMC access to secure world */
			val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE);
			val |= PMC_SECURITY_EN_BIT;
			mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val);
504
		}
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
	}

	/*
	 * Check if we are exiting cluster idle state
	 */
	if (target_state->pwr_domain_state[MPIDR_AFFLVL1] ==
			PSTATE_ID_CLUSTER_IDLE) {

		if (!tegra_bpmp_available) {

			/* PWM un-tristate */
			cfg = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_OUTPUT_CFG);
			if (cfg & DFLL_OUTPUT_CFG_CLK_EN_BIT) {
				val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM);
				val &= ~PINMUX_PWM_TRISTATE;
				mmio_write_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM, val);
521
522
523
524

				/* make sure the setting took effect */
				val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM);
				assert((val & PINMUX_PWM_TRISTATE) == 0U);
525
526
			}

527
528
529
530
531
532
533
			/*
			 * Restore operation mode for the DFLL ring
			 * oscillator
			 */
			mmio_write_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL,
				      ENABLE_CLOSED_LOOP);

534
535
536
			/* release cluster idle lock */
			tegra_fc_ccplex_pgexit_unlock();
		}
537
538
539
540
541
542
543
	}

	/*
	 * T210 has a dedicated ARMv7 boot and power mgmt processor, BPMP. It's
	 * used for power management and boot purposes. Inform the BPMP that
	 * we have completed the cluster power up.
	 */
544
	tegra_fc_lock_active_cluster();
545

546
	/*
547
548
549
	 * Resume PMC hardware block for Tegra210 platforms
	 */
	if (!tegra_chipid_is_t210_b01()) {
550
		tegra_pmc_resume();
551
	}
552

553
554
555
	return PSCI_E_SUCCESS;
}

556
int tegra_soc_pwr_domain_on(u_register_t mpidr)
557
558
{
	int cpu = mpidr & MPIDR_CPU_MASK;
559
560
561
562
	uint32_t mask = CPU_CORE_RESET_MASK << cpu;

	/* Deassert CPU reset signals */
	mmio_write_32(TEGRA_CAR_RESET_BASE + CPU_CMPLX_RESET_CLR, mask);
563
564
565
566
567
568
569
570
571
572
573
574

	/* Turn on CPU using flow controller or PMC */
	if (cpu_powergate_mask[cpu] == 0) {
		tegra_pmc_cpu_on(cpu);
		cpu_powergate_mask[cpu] = 1;
	} else {
		tegra_fc_cpu_on(cpu);
	}

	return PSCI_E_SUCCESS;
}

575
int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
576
{
577
	tegra_fc_cpu_off(read_mpidr() & MPIDR_CPU_MASK);
578
579
	return PSCI_E_SUCCESS;
}
580
581
582
583
584
585
586
587

int tegra_soc_prepare_system_reset(void)
{
	/*
	 * Set System Clock (SCLK) to POR default so that the clock source
	 * for the PMC APB clock would not be changed due to system reset.
	 */
	mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_BURST_POLICY,
588
		SCLK_BURST_POLICY_DEFAULT);
589
590
591
592
593
	mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_RATE, 0);

	/* Wait 1 ms to make sure clock source/device logic is stabilized. */
	mdelay(1);

594
595
596
597
598
	/*
	 * Program the PMC in order to restart the system.
	 */
	tegra_pmc_system_reset();

599
600
	return PSCI_E_SUCCESS;
}
601
602
603
604
605
606

__dead2 void tegra_soc_prepare_system_off(void)
{
	ERROR("Tegra System Off: operation not handled.\n");
	panic();
}