Browse Source

feat(fvp): add cpu power control

Most newer CPU's have DSU and CPU power control core-off bit which
means before turning off CPUs from base power controller we need to
turn individual cores off from CPU Power control.

However there are certain older CPU's that don't have DSU and
don't support CPUPWRCTRL_EL1, so populate them as a list
and ignore setting core-off bit for those older CPU's as all newer
CPU's have them.

Note: unfortunately there is no mechanism to identify if a DSU is
present and CPUPWRCTRL_EL1 is supported through any CPU control
registers and CPUPWRCTRL_EL1 is supported only for ARM64 platforms
and not available in ARM32 platforms.

Change-Id: Iba6c3c8db60dbeb177cead7ebc65df8265860da7
Signed-off-by: Govindraj Raja <govindraj.raja@arm.com>
pull/2000/merge
Govindraj Raja 5 months ago
parent
commit
d38c64d246
  1. 25
      include/drivers/arm/fvp/fvp_cpu_pwr.h
  2. 19
      plat/arm/board/fvp/aarch64/fvp_helpers.S
  3. 45
      plat/arm/board/fvp/fvp_cpu_pwr.c
  4. 6
      plat/arm/board/fvp/platform.mk

25
include/drivers/arm/fvp/fvp_cpu_pwr.h

@ -0,0 +1,25 @@
/*
* Copyright (c) 2024, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FVP_CPU_PWR_H
#define FVP_CPU_PWR_H
#ifndef __ASSEMBLER__
#include <stdbool.h>
#include <stdint.h>
#if __aarch64__
bool check_cpupwrctrl_el1_is_available(void);
#endif /* __aarch64__ */
#endif /* __ASSEMBLER__ */
/*******************************************************************************
* CPU Power Control register specific definitions
******************************************************************************/
#define CPUPWRCTLR_EL1 S3_0_C15_C2_7
#define CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1)
#endif /* FVP_CPU_PWR_H */

19
plat/arm/board/fvp/aarch64/fvp_helpers.S

@ -6,9 +6,10 @@
#include <arch.h>
#include <asm_macros.S>
#include <drivers/arm/fvp/fvp_cpu_pwr.h>
#include <drivers/arm/fvp/fvp_pwrc.h>
#include <drivers/arm/gicv2.h>
#include <drivers/arm/gicv3.h>
#include <drivers/arm/fvp/fvp_pwrc.h>
#include <platform_def.h>
.globl plat_secondary_cold_boot_setup
@ -29,6 +30,21 @@
*/
func plat_secondary_cold_boot_setup
#ifndef EL3_PAYLOAD_BASE
/* --------------------------------------------
* Check if core supports powering down, if it
* supports power down then set core power down
* bit before requesting for the cores to be
* powered off from base power controller.
* ---------------------------------------------
*/
bl check_cpupwrctrl_el1_is_available
cbz x0, base_power_off
mrs x1, CPUPWRCTLR_EL1
orr x1, x1, #CPUPWRCTLR_EL1_CORE_PWRDN_BIT
msr CPUPWRCTLR_EL1, x1
/* ---------------------------------------------
* Power down this cpu.
* TODO: Do we need to worry about powering the
@ -37,6 +53,7 @@ func plat_secondary_cold_boot_setup
* loader zeroes out the zi section.
* ---------------------------------------------
*/
base_power_off:
mrs x0, mpidr_el1
mov_imm x1, PWRC_BASE
str w0, [x1, #PPOFFR_OFF]

45
plat/arm/board/fvp/fvp_cpu_pwr.c

@ -0,0 +1,45 @@
/*
* Copyright (c) 2024, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#if __aarch64__
#include <aem_generic.h>
#include <arch_helpers.h>
#include <cortex_a35.h>
#include <cortex_a53.h>
#include <cortex_a57.h>
#include <cortex_a72.h>
#include <cortex_a73.h>
#include <cortex_a78_ae.h>
#include <drivers/arm/fvp/fvp_cpu_pwr.h>
#include <lib/utils_def.h>
#include <neoverse_e1.h>
bool check_cpupwrctrl_el1_is_available(void)
{
/* Poupulate list of CPU midr that doesn't support CPUPWRCTL_EL1 */
const unsigned int midr_no_cpupwrctl[] = {
BASE_AEM_MIDR,
CORTEX_A35_MIDR,
CORTEX_A53_MIDR,
CORTEX_A57_MIDR,
CORTEX_A72_MIDR,
CORTEX_A73_MIDR,
CORTEX_A78_AE_MIDR,
NEOVERSE_E1_MIDR
};
unsigned int midr = (unsigned int)read_midr();
for (unsigned int i = 0U; i < ARRAY_SIZE(midr_no_cpupwrctl); i++) {
if (midr_no_cpupwrctl[i] == midr) {
return false;
}
}
return true;
}
#endif /* __arch64__ */

6
plat/arm/board/fvp/platform.mk

@ -222,6 +222,7 @@ BL1_SOURCES += drivers/arm/smmu/smmu_v3.c \
lib/semihosting/${ARCH}/semihosting_call.S \
plat/arm/board/fvp/${ARCH}/fvp_helpers.S \
plat/arm/board/fvp/fvp_bl1_setup.c \
plat/arm/board/fvp/fvp_cpu_pwr.c \
plat/arm/board/fvp/fvp_err.c \
plat/arm/board/fvp/fvp_io_storage.c \
plat/arm/board/fvp/fvp_topology.c \
@ -252,7 +253,8 @@ BL2_SOURCES += plat/arm/common/fconf/fconf_nv_cntr_getter.c
endif
ifeq (${ENABLE_RME},1)
BL2_SOURCES += plat/arm/board/fvp/aarch64/fvp_helpers.S
BL2_SOURCES += plat/arm/board/fvp/aarch64/fvp_helpers.S \
plat/arm/board/fvp/fvp_cpu_pwr.c
BL31_SOURCES += plat/arm/board/fvp/fvp_plat_attest_token.c \
plat/arm/board/fvp/fvp_realm_attest_key.c
@ -264,6 +266,7 @@ endif
ifeq (${RESET_TO_BL2},1)
BL2_SOURCES += plat/arm/board/fvp/${ARCH}/fvp_helpers.S \
plat/arm/board/fvp/fvp_cpu_pwr.c \
plat/arm/board/fvp/fvp_bl2_el3_setup.c \
${FVP_CPU_LIBS} \
${FVP_INTERCONNECT_SOURCES}
@ -290,6 +293,7 @@ BL31_SOURCES += drivers/arm/fvp/fvp_pwrc.c \
plat/arm/board/fvp/fvp_pm.c \
plat/arm/board/fvp/fvp_topology.c \
plat/arm/board/fvp/aarch64/fvp_helpers.S \
plat/arm/board/fvp/fvp_cpu_pwr.c \
plat/arm/common/arm_nor_psci_mem_protect.c \
${FVP_CPU_LIBS} \
${FVP_GIC_SOURCES} \

Loading…
Cancel
Save