Merge changes I9d06e0ee,I6980e84f into integration

* changes:
  feat(tegra): implement 'pwr_domain_off_early' handler
  feat(psci): introduce 'pwr_domain_off_early' hook
This commit is contained in:
Manish Pandey 2023-05-03 15:10:45 +02:00 committed by TrustedFirmware Code Review
commit f50107d3df
10 changed files with 100 additions and 7 deletions

View file

@ -2785,6 +2785,22 @@ Perform the platform specific actions to power on a CPU, specified
by the ``MPIDR`` (first argument). The generic code expects the platform to
return PSCI_E_SUCCESS on success or PSCI_E_INTERN_FAIL for any failure.
plat_psci_ops.pwr_domain_off_early() [optional]
...............................................
This optional function performs the platform specific actions to check if
powering off the calling CPU and its higher parent power domain levels as
indicated by the ``target_state`` (first argument) is possible or allowed.
The ``target_state`` encodes the platform coordinated target local power states
for the CPU power domain and its parent power domain levels.
For this handler, the local power state for the CPU power domain will be a
power down state where as it could be either power down, retention or run state
for the higher power domain levels depending on the result of state
coordination. The generic code expects PSCI_E_DENIED return code if the
platform thinks that CPU_OFF should not proceed on the calling CPU.
plat_psci_ops.pwr_domain_off()
..............................

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -317,6 +318,7 @@ typedef struct plat_psci_ops {
void (*cpu_standby)(plat_local_state_t cpu_state);
int (*pwr_domain_on)(u_register_t mpidr);
void (*pwr_domain_off)(const psci_power_state_t *target_state);
int (*pwr_domain_off_early)(const psci_power_state_t *target_state);
void (*pwr_domain_suspend_pwrdown_early)(
const psci_power_state_t *target_state);
#if PSCI_OS_INIT_MODE

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -56,6 +57,19 @@ int psci_do_cpu_off(unsigned int end_pwrlvl)
/* Construct the psci_power_state for CPU_OFF */
psci_set_power_off_state(&state_info);
/*
* Call the platform provided early CPU_OFF handler to allow
* platforms to perform any housekeeping activities before
* actually powering the CPU off. PSCI_E_DENIED indicates that
* the CPU off sequence should be aborted at this time.
*/
if (psci_plat_pm_ops->pwr_domain_off_early) {
rc = psci_plat_pm_ops->pwr_domain_off_early(&state_info);
if (rc == PSCI_E_DENIED) {
return rc;
}
}
/*
* Get the parent nodes here, this is important to do before we
* initiate the power down sequence as after that point the core may

View file

@ -125,15 +125,18 @@
.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
@ -251,6 +254,14 @@ _end: mov x0, x20
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
@ -426,3 +437,10 @@ tegra_bl31_phys_base:
*/
tegra_console_base:
.quad 0
/* --------------------------------------------------
* MPID value for the boot CPU
* --------------------------------------------------
*/
tegra_primary_cpu_mpid:
.quad 0

View file

@ -1,6 +1,6 @@
/*
* 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
*/
@ -89,6 +89,16 @@ static int32_t tegra_pwr_domain_on(u_register_t mpidr)
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.
@ -268,6 +278,7 @@ static int32_t tegra_validate_ns_entrypoint(uintptr_t entrypoint)
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,

View file

@ -41,8 +41,6 @@
#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)

View file

@ -1,6 +1,6 @@
/*
* 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
*/
@ -98,6 +98,9 @@ void tegra_fiq_handler_setup(void);
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);
@ -109,6 +112,7 @@ int32_t tegra_system_suspended(void);
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);

View file

@ -433,6 +433,16 @@ int32_t tegra_soc_pwr_domain_on_finish(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;

View file

@ -463,6 +463,16 @@ int32_t tegra_soc_pwr_domain_on_finish(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) & MIDR_IMPL_MASK;

View file

@ -575,6 +575,16 @@ int tegra_soc_pwr_domain_on(u_register_t mpidr)
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);