.endm
/* -----------------------------------------------------
- * unsigned int plat_is_my_cpu_primary(void);
+ * bool plat_is_my_cpu_primary(void);
*
* This function checks if this is the Primary CPU
+ *
+ * Registers clobbered: x0, x1
* -----------------------------------------------------
*/
func plat_is_my_cpu_primary
mrs x0, mpidr_el1
- and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
- cmp x0, #TEGRA_PRIMARY_CPU
+ adr x1, tegra_primary_cpu_mpid
+ ldr x1, [x1]
+ cmp x0, x1
cset x0, eq
ret
endfunc plat_is_my_cpu_primary
adr x18, bl31_entrypoint
str x18, [x17]
+ /* -----------------------------------
+ * save the boot CPU MPID value
+ * -----------------------------------
+ */
+ mrs x0, mpidr_el1
+ adr x1, tegra_primary_cpu_mpid
+ str x0, [x1]
+
1: cpu_init_common
ret
*/
tegra_console_base:
.quad 0
+
+ /* --------------------------------------------------
+ * MPID value for the boot CPU
+ * --------------------------------------------------
+ */
+tegra_primary_cpu_mpid:
+ .quad 0
/*
* Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2020-2023, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
return tegra_soc_pwr_domain_on(mpidr);
}
+/*******************************************************************************
+ * Handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
+ * Return error if CPU off sequence is not allowed for the current core.
+ ******************************************************************************/
+static int tegra_pwr_domain_off_early(const psci_power_state_t *target_state)
+{
+ return tegra_soc_pwr_domain_off_early(target_state);
+}
+
/*******************************************************************************
* Handler called when a power domain is about to be turned off. The
* target_state encodes the power state that each level should transition to.
static plat_psci_ops_t tegra_plat_psci_ops = {
.cpu_standby = tegra_cpu_standby,
.pwr_domain_on = tegra_pwr_domain_on,
+ .pwr_domain_off_early = tegra_pwr_domain_off_early,
.pwr_domain_off = tegra_pwr_domain_off,
.pwr_domain_suspend_pwrdown_early = tegra_pwr_domain_suspend_pwrdown_early,
.pwr_domain_suspend = tegra_pwr_domain_suspend,
#define PLATFORM_STACK_SIZE U(0x400)
#endif
-#define TEGRA_PRIMARY_CPU U(0x0)
-
#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \
PLATFORM_MAX_CPUS_PER_CLUSTER)
/*
* Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2020-2023, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
int32_t tegra_fiq_get_intr_context(void);
void tegra_fiq_set_ns_entrypoint(uint64_t entrypoint);
+/* Declarations for tegra_helpers.S */
+bool plat_is_my_cpu_primary(void);
+
/* Declarations for tegra_security.c */
void tegra_security_setup(void);
void tegra_security_setup_videomem(uintptr_t base, uint64_t size);
int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state);
int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state);
int32_t tegra_soc_pwr_domain_on(u_register_t mpidr);
+int32_t tegra_soc_pwr_domain_off_early(const psci_power_state_t *target_state);
int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state);
int32_t tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state);
int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state);
return PSCI_E_SUCCESS;
}
+int32_t tegra_soc_pwr_domain_off_early(const psci_power_state_t *target_state)
+{
+ /* Do not power off the boot CPU */
+ if (plat_is_my_cpu_primary()) {
+ return PSCI_E_DENIED;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
{
uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & (uint64_t)MIDR_IMPL_MASK;
return PSCI_E_SUCCESS;
}
+int32_t tegra_soc_pwr_domain_off_early(const psci_power_state_t *target_state)
+{
+ /* Do not power off the boot CPU */
+ if (plat_is_my_cpu_primary()) {
+ return PSCI_E_DENIED;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
{
uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
return PSCI_E_SUCCESS;
}
+int32_t tegra_soc_pwr_domain_off_early(const psci_power_state_t *target_state)
+{
+ /* Do not power off the boot CPU */
+ if (plat_is_my_cpu_primary()) {
+ return PSCI_E_DENIED;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
{
tegra_fc_cpu_off(read_mpidr() & MPIDR_CPU_MASK);