From 89c58a5087f12f0e965ce8fdf946038d5799d07d Mon Sep 17 00:00:00 2001 From: Jagdish Gediya Date: Fri, 2 Feb 2024 06:01:44 +0000 Subject: [PATCH] feat(tc): setup ni-tower non-secure access for TC3 NI-Tower's component's registers are need to be accessed from kernel NI-PMU driver so enable NS access to it. Change-Id: I83a8b3a1d2778baf767ff93263e246d127ef8114 Signed-off-by: Jagdish Gediya Signed-off-by: Leo Yan --- include/plat/arm/common/plat_arm.h | 1 + plat/arm/board/tc/platform.mk | 3 +- plat/arm/board/tc/tc_bl31_setup.c | 1 + plat/arm/common/arm_ni.c | 167 +++++++++++++++++++++++++++++ 4 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 plat/arm/common/arm_ni.c diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index 3ea29eb14..83a5cd21f 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -362,6 +362,7 @@ void plat_arm_interconnect_enter_coherency(void); void plat_arm_interconnect_exit_coherency(void); void plat_arm_program_trusted_mailbox(uintptr_t address); bool plat_arm_bl1_fwu_needed(void); +int plat_arm_ni_setup(uintptr_t global_cfg); __dead2 void plat_arm_error_handler(int err); __dead2 void plat_arm_system_reset(void); diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk index 78b694577..fb7050081 100644 --- a/plat/arm/board/tc/platform.mk +++ b/plat/arm/board/tc/platform.mk @@ -121,7 +121,8 @@ TC_CPU_SOURCES += lib/cpus/aarch64/cortex_a520.S \ lib/cpus/aarch64/cortex_x925.S endif -INTERCONNECT_SOURCES := ${TC_BASE}/tc_interconnect.c +INTERCONNECT_SOURCES := ${TC_BASE}/tc_interconnect.c \ + plat/arm/common/arm_ni.c PLAT_BL_COMMON_SOURCES += ${TC_BASE}/tc_plat.c \ ${TC_BASE}/include/tc_helpers.S diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c index 7d1bc9c93..53404dfcc 100644 --- a/plat/arm/board/tc/tc_bl31_setup.c +++ b/plat/arm/board/tc/tc_bl31_setup.c @@ -110,6 +110,7 @@ void bl31_platform_setup(void) #if TARGET_PLATFORM == 3 enable_ns_mcn_pmu(); set_mcn_slc_alloc_mode(); + plat_arm_ni_setup(NCI_BASE_ADDR); #endif } diff --git a/plat/arm/common/arm_ni.c b/plat/arm/common/arm_ni.c new file mode 100644 index 000000000..b3ad8b386 --- /dev/null +++ b/plat/arm/common/arm_ni.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2024, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#define NI_CHILD_NODE_COUNT 4 +#define NI_CHILD_POINTERS_START 8 + +#define NI_PMU_SECURE_CTRL 0x100 +#define NI_PMU_SECURE_EVENT_OBSERVATION 0x108 +#define NI_PMU_DEBUG_ENABLE 0x110 +#define NI_COMP_NUM_SUBFEATURES 0x100 +#define NI_COMP_SUBFEATURE_TYPE_START 0x108 +#define NI_COMP_SUBFEATURE_SECURE_CTRL_START 0x308 + +#define SECURE_OVERRIDE_DEFAULT BIT(0) +#define SECURE_EVENT_ENABLE BIT(2) +#define NA_EVENT_ENABLE BIT(3) +#define PMU_ENABLE BIT(0) + +#define NI_NODE_MASK 0x0000ffff +#define NI_NODE_TYPE(node_info) (node_info & NI_NODE_MASK) +#define NI_CHILD_POINTER(i) (NI_CHILD_POINTERS_START + (i * 4)) +#define NI_COMP_SUBFEATURE_TYPE(i) (NI_COMP_SUBFEATURE_TYPE_START + (i * 8)) +#define NI_COMP_SUBFEATURE_SECURE_CTRL(i) (NI_COMP_SUBFEATURE_SECURE_CTRL_START + (i * 8)) + +#define NI_PERIPHERAL_ID0 0xfe0 +#define NI_PIDR0_PART_MASK 0xff +#define NI_PERIPHERAL_ID1 0xfe4 +#define NI_PIDR1_PART_MASK 0xf +#define NI_PIDR1_PART_SHIFT 8 + +enum ni_part { + NI_700 = 0x43b, + NI_710AE = 0x43d, + NI_TOWER = 0x43f, +}; + +enum ni_node_type { + NI_INVALID_NODE = 0, + NI_VOLTAGE_DOMAIN = 1, + NI_POWER_DOMAIN = 2, + NI_CLOCK_DOMAIN = 3, + NI_ASNI = 4, + NI_AMNI = 5, + NI_PMU = 6, + NI_HSNI = 7, + NI_HMNI = 8, + NI_PMNI = 9, + NI_CMNI = 14, + NI_CFGNI = 15 +}; + +enum ni_subfeature_type { + NI_SUBFEATURE_APU = 0, + NI_SUBFEATURE_ADDR_MAP = 1, + NI_SUBFEATURE_FCU = 2, + NI_SUBFEATURE_IDM = 3 +}; + +static void ni_enable_pmu(uintptr_t pmu_addr) +{ + mmio_setbits_32(pmu_addr + NI_PMU_DEBUG_ENABLE, PMU_ENABLE); +} + +static void ni_enable_fcu_ns_access(uintptr_t comp_addr) +{ + uint32_t subfeature_type; + uint32_t subfeature_count; + uint32_t subfeature_secure_ctrl; + + subfeature_count = mmio_read_32(comp_addr + NI_COMP_NUM_SUBFEATURES); + for (uint32_t i = 0U; i < subfeature_count; i++) { + subfeature_type = + NI_NODE_TYPE(mmio_read_32(comp_addr + NI_COMP_SUBFEATURE_TYPE(i))); + if (subfeature_type == NI_SUBFEATURE_FCU) { + subfeature_secure_ctrl = comp_addr + NI_COMP_SUBFEATURE_SECURE_CTRL(i); + mmio_setbits_32(subfeature_secure_ctrl, SECURE_OVERRIDE_DEFAULT); + } + } +} + +static void ni_enable_pmu_ns_access(uintptr_t comp_addr) +{ + mmio_setbits_32(comp_addr + NI_PMU_SECURE_CTRL, SECURE_OVERRIDE_DEFAULT); + mmio_setbits_32(comp_addr + NI_PMU_SECURE_EVENT_OBSERVATION, + SECURE_EVENT_ENABLE | NA_EVENT_ENABLE); +} + +static void ni_setup_component(uintptr_t comp_addr) +{ + uint32_t node_info; + + node_info = mmio_read_32(comp_addr); + + switch (NI_NODE_TYPE(node_info)) { + case NI_ASNI: + case NI_AMNI: + case NI_HSNI: + case NI_HMNI: + case NI_PMNI: + ni_enable_fcu_ns_access(comp_addr); + break; + case NI_PMU: + ni_enable_pmu_ns_access(comp_addr); + ni_enable_pmu(comp_addr); + break; + default: + return; + } +} + +int plat_arm_ni_setup(uintptr_t global_cfg) +{ + uintptr_t vd_addr; + uintptr_t pd_addr; + uintptr_t cd_addr; + uintptr_t comp_addr; + uint32_t vd_count; + uint32_t pd_count; + uint32_t cd_count; + uint32_t comp_count; + uint32_t part; + uint32_t reg; + + reg = mmio_read_32(global_cfg + NI_PERIPHERAL_ID0); + part = reg & NI_PIDR0_PART_MASK; + reg = mmio_read_32(global_cfg + NI_PERIPHERAL_ID1); + part |= ((reg & NI_PIDR1_PART_MASK) << NI_PIDR1_PART_SHIFT); + + if (part != NI_TOWER) { + ERROR("0x%x is not supported\n", part); + return -EINVAL; + } + + vd_count = mmio_read_32(global_cfg + NI_CHILD_NODE_COUNT); + + for (uint32_t i = 0U; i < vd_count; i++) { + vd_addr = global_cfg + mmio_read_32(global_cfg + NI_CHILD_POINTER(i)); + pd_count = mmio_read_32(vd_addr + NI_CHILD_NODE_COUNT); + + for (uint32_t j = 0U; j < pd_count; j++) { + pd_addr = global_cfg + mmio_read_32(vd_addr + NI_CHILD_POINTER(j)); + cd_count = mmio_read_32(pd_addr + NI_CHILD_NODE_COUNT); + + for (uint32_t k = 0U; k < cd_count; k++) { + cd_addr = global_cfg + mmio_read_32(pd_addr + NI_CHILD_POINTER(k)); + comp_count = mmio_read_32(cd_addr + NI_CHILD_NODE_COUNT); + + for (uint32_t l = 0U; l < comp_count; l++) { + comp_addr = global_cfg + + mmio_read_32(cd_addr + NI_CHILD_POINTER(l)); + ni_setup_component(comp_addr); + } + } + } + } + + return 0; +}