diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst index be3f0bb0ff10266797818080c9918c68e599565f..906daf8110494f915453a620243b6000d5eb5a5c 100644 --- a/docs/getting_started/porting-guide.rst +++ b/docs/getting_started/porting-guide.rst @@ -1742,9 +1742,9 @@ In Arm standard platforms, the arguments received are : which is list of executable images following BL31, arg1 - Points to load address of SOC_FW_CONFIG if present - except in case of Arm FVP platform. + except in case of Arm FVP and Juno platform. - In case of Arm FVP platform, Points to load address + In case of Arm FVP and Juno platform, points to load address of FW_CONFIG. arg2 - Points to load address of HW_CONFIG if present diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst index a1d2313575bf4fc67bbb71569a7dc9a6ce03840a..2aa973890af3b1192203a04e329e171797300259 100644 --- a/docs/plat/arm/arm-build-options.rst +++ b/docs/plat/arm/arm-build-options.rst @@ -91,6 +91,12 @@ Arm Platform Build Options platforms. If this option is specified, then the path to the CryptoCell SBROM library must be specified via ``CCSBROM_LIB_PATH`` flag. +- ``ARM_ETHOSN_NPU_DRIVER``: boolean option to enable a SiP service that can + configure an Arm Ethos-N NPU. To use this service the target platform's + ``HW_CONFIG`` must include the device tree nodes for the NPU. Currently, only + the Arm Juno platform has this included in its ``HW_CONFIG`` and the platform + only loads the ``HW_CONFIG`` in AArch64 builds. Default is 0. + - ``ARM_SPMC_MANIFEST_DTS`` : path to an alternate manifest file used as the SPMC Core manifest. Valid when ``SPD=spmd`` is selected. @@ -128,4 +134,4 @@ Arm CSS Platform-Specific Build Options -------------- -*Copyright (c) 2019-2020, Arm Limited. All rights reserved.* +*Copyright (c) 2019-2021, Arm Limited. All rights reserved.* diff --git a/drivers/arm/ethosn/ethosn_smc.c b/drivers/arm/ethosn/ethosn_smc.c new file mode 100644 index 0000000000000000000000000000000000000000..299d07c02b2aa9fd10d59c295558b3aa0c1cce27 --- /dev/null +++ b/drivers/arm/ethosn/ethosn_smc.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +/* Arm Ethos-N NPU (NPU) status */ +#define ETHOSN_STATUS \ + FCONF_GET_PROPERTY(hw_config, ethosn_config, status) + +/* Number of NPU cores available */ +#define ETHOSN_NUM_CORES \ + FCONF_GET_PROPERTY(hw_config, ethosn_config, num_cores) + +/* Address to an NPU core */ +#define ETHOSN_CORE_ADDR(core_idx) \ + FCONF_GET_PROPERTY(hw_config, ethosn_core_addr, core_idx) + +/* NPU core sec registry address */ +#define ETHOSN_CORE_SEC_REG(core_addr, reg_offset) \ + (core_addr + reg_offset) + +/* Reset timeout in us */ +#define ETHOSN_RESET_TIMEOUT_US U(10 * 1000 * 1000) +#define ETHOSN_RESET_WAIT_US U(1) + +#define SEC_DEL_REG U(0x0004) +#define SEC_DEL_VAL U(0x81C) +#define SEC_DEL_EXCC_MASK U(0x20) + +#define SEC_SECCTLR_REG U(0x0010) +#define SEC_SECCTLR_VAL U(0x3) + +#define SEC_DEL_MMUSID_REG U(0x2008) +#define SEC_DEL_MMUSID_VAL U(0x3FFFF) + +#define SEC_DEL_ADDR_EXT_REG U(0x201C) +#define SEC_DEL_ADDR_EXT_VAL U(0x15) + +#define SEC_SYSCTRL0_REG U(0x0018) +#define SEC_SYSCTRL0_SOFT_RESET U(3U << 29) +#define SEC_SYSCTRL0_HARD_RESET U(1U << 31) + +static void ethosn_delegate_to_ns(uintptr_t core_addr) +{ + mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG), + SEC_SECCTLR_VAL); + + mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG), + SEC_DEL_VAL); + + mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_MMUSID_REG), + SEC_DEL_MMUSID_VAL); + + mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_ADDR_EXT_REG), + SEC_DEL_ADDR_EXT_VAL); +} + +static int ethosn_is_sec(void) +{ + if ((mmio_read_32(ETHOSN_CORE_SEC_REG(ETHOSN_CORE_ADDR(0), SEC_DEL_REG)) + & SEC_DEL_EXCC_MASK) != 0U) { + return 0; + } + + return 1; +} + +static bool ethosn_reset(uintptr_t core_addr, int hard_reset) +{ + unsigned int timeout; + const uintptr_t sysctrl0_reg = + ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG); + const uint32_t reset_val = (hard_reset != 0) ? SEC_SYSCTRL0_HARD_RESET + : SEC_SYSCTRL0_SOFT_RESET; + + mmio_write_32(sysctrl0_reg, reset_val); + + /* Wait for reset to complete */ + for (timeout = 0U; timeout < ETHOSN_RESET_TIMEOUT_US; + timeout += ETHOSN_RESET_WAIT_US) { + + if ((mmio_read_32(sysctrl0_reg) & reset_val) == 0U) { + break; + } + + udelay(ETHOSN_RESET_WAIT_US); + } + + return timeout < ETHOSN_RESET_TIMEOUT_US; +} + +uintptr_t ethosn_smc_handler(uint32_t smc_fid, + u_register_t core_idx, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + uintptr_t core_addr; + int hard_reset = 0; + + /* Only SiP fast calls are expected */ + if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) || + (GET_SMC_OEN(smc_fid) != OEN_SIP_START)) { + SMC_RET1(handle, SMC_UNK); + } + + /* Truncate parameters to 32-bits for SMC32 */ + if (GET_SMC_CC(smc_fid) == SMC_32) { + core_idx &= 0xFFFFFFFF; + x2 &= 0xFFFFFFFF; + x3 &= 0xFFFFFFFF; + x4 &= 0xFFFFFFFF; + } + + if (!is_ethosn_fid(smc_fid)) { + SMC_RET1(handle, SMC_UNK); + } + + if (ETHOSN_STATUS == ETHOSN_STATUS_DISABLED) { + WARN("ETHOSN: Arm Ethos-N NPU not available\n"); + SMC_RET1(handle, ETHOSN_NOT_SUPPORTED); + } + + switch (smc_fid & FUNCID_NUM_MASK) { + case ETHOSN_FNUM_VERSION: + SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR); + case ETHOSN_FNUM_IS_SEC: + SMC_RET1(handle, ethosn_is_sec()); + case ETHOSN_FNUM_HARD_RESET: + hard_reset = 1; + /* Fallthrough */ + case ETHOSN_FNUM_SOFT_RESET: + if (core_idx >= ETHOSN_NUM_CORES) { + WARN("ETHOSN: core index out of range\n"); + SMC_RET1(handle, ETHOSN_CORE_IDX_OUT_OF_RANGE); + } + + core_addr = ETHOSN_CORE_ADDR(core_idx); + + if (!ethosn_reset(core_addr, hard_reset)) { + SMC_RET1(handle, ETHOSN_FAILURE); + } + + ethosn_delegate_to_ns(core_addr); + + SMC_RET1(handle, ETHOSN_SUCCESS); + default: + SMC_RET1(handle, SMC_UNK); + } +} diff --git a/fdts/juno-ethosn.dtsi b/fdts/juno-ethosn.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..87ab378a2d0a6faed744b809999d257ba324f722 --- /dev/null +++ b/fdts/juno-ethosn.dtsi @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/ { + #address-cells = <2>; + #size-cells = <2>; + + ethosn: ethosn@6f300000 { + compatible = "ethosn"; + reg = <0 0x6f300000 0 0x00100000>; + status = "okay"; + + /* + * Single-core NPU. For multi-core NPU, additional core nodes + * and reg values must be added. + */ + core0 { + compatible = "ethosn-core"; + status = "okay"; + }; + }; +}; diff --git a/fdts/juno.dts b/fdts/juno.dts new file mode 100644 index 0000000000000000000000000000000000000000..56fe1676f65d95efcde150748cfd7ca205ffeaa5 --- /dev/null +++ b/fdts/juno.dts @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + +}; + +#if ARM_ETHOSN_NPU_DRIVER + #include "juno-ethosn.dtsi" +#endif diff --git a/include/drivers/arm/ethosn.h b/include/drivers/arm/ethosn.h new file mode 100644 index 0000000000000000000000000000000000000000..6de2abb85fdd6593403cccddaaa6e5519064f878 --- /dev/null +++ b/include/drivers/arm/ethosn.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ETHOSN_H +#define ETHOSN_H + +#include + +/* Function numbers */ +#define ETHOSN_FNUM_VERSION U(0x50) +#define ETHOSN_FNUM_IS_SEC U(0x51) +#define ETHOSN_FNUM_HARD_RESET U(0x52) +#define ETHOSN_FNUM_SOFT_RESET U(0x53) +/* 0x54-0x5F reserved for future use */ + +/* SMC64 function IDs */ +#define ETHOSN_FID_64(func_num) U(0xC2000000 | func_num) +#define ETHOSN_FID_VERSION_64 ETHOSN_FID_64(ETHOSN_FNUM_VERSION) +#define ETHOSN_FID_IS_SEC_64 ETHOSN_FID_64(ETHOSN_FNUM_IS_SEC) +#define ETHOSN_FID_HARD_RESET_64 ETHOSN_FID_64(ETHOSN_FNUM_HARD_RESET) +#define ETHOSN_FID_SOFT_RESET_64 ETHOSN_FID_64(ETHOSN_FNUM_SOFT_RESET) + +/* SMC32 function IDs */ +#define ETHOSN_FID_32(func_num) U(0x82000000 | func_num) +#define ETHOSN_FID_VERSION_32 ETHOSN_FID_32(ETHOSN_FNUM_VERSION) +#define ETHOSN_FID_IS_SEC_32 ETHOSN_FID_32(ETHOSN_FNUM_IS_SEC) +#define ETHOSN_FID_HARD_RESET_32 ETHOSN_FID_32(ETHOSN_FNUM_HARD_RESET) +#define ETHOSN_FID_SOFT_RESET_32 ETHOSN_FID_32(ETHOSN_FNUM_SOFT_RESET) + +#define ETHOSN_NUM_SMC_CALLS 8 + +/* Macro to identify function calls */ +#define ETHOSN_FID_MASK U(0xFFF0) +#define ETHOSN_FID_VALUE U(0x50) +#define is_ethosn_fid(_fid) (((_fid) & ETHOSN_FID_MASK) == ETHOSN_FID_VALUE) + +/* Service version */ +#define ETHOSN_VERSION_MAJOR U(0) +#define ETHOSN_VERSION_MINOR U(1) + +/* Return codes for function calls */ +#define ETHOSN_SUCCESS 0 +#define ETHOSN_NOT_SUPPORTED -1 +/* -2 Reserved for NOT_REQUIRED */ +/* -3 Reserved for INVALID_PARAMETER */ +#define ETHOSN_FAILURE -4 +#define ETHOSN_CORE_IDX_OUT_OF_RANGE -5 + +uintptr_t ethosn_smc_handler(uint32_t smc_fid, + u_register_t core_idx, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags); + +#endif /* ETHOSN_H */ diff --git a/include/plat/arm/common/arm_sip_svc.h b/include/plat/arm/common/arm_sip_svc.h index 85fdb289f1c1c2474b69c7485167bfebb957f001..2eeed95f0229c876473b00ae94a1a0850904b4a7 100644 --- a/include/plat/arm/common/arm_sip_svc.h +++ b/include/plat/arm/common/arm_sip_svc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2019,2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -25,6 +25,12 @@ /* DEBUGFS_SMC_32 0x82000030U */ /* DEBUGFS_SMC_64 0xC2000030U */ +/* + * Arm Ethos-N NPU SiP SMC function IDs + * 0xC2000050-0xC200005F + * 0x82000050-0x8200005F + */ + /* ARM SiP Service Calls version numbers */ #define ARM_SIP_SVC_VERSION_MAJOR U(0x0) #define ARM_SIP_SVC_VERSION_MINOR U(0x2) diff --git a/include/plat/arm/common/fconf_ethosn_getter.h b/include/plat/arm/common/fconf_ethosn_getter.h new file mode 100644 index 0000000000000000000000000000000000000000..0fd1f025a8debae9a7c9717eb9457118b31b6d28 --- /dev/null +++ b/include/plat/arm/common/fconf_ethosn_getter.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_ETHOSN_GETTER_H +#define FCONF_ETHOSN_GETTER_H + +#include + +#include + +#define hw_config__ethosn_config_getter(prop) ethosn_config.prop +#define hw_config__ethosn_core_addr_getter(idx) __extension__ ({ \ + assert(idx < ethosn_config.num_cores); \ + ethosn_config.core_addr[idx]; \ +}) + +#define ETHOSN_STATUS_DISABLED U(0) +#define ETHOSN_STATUS_ENABLED U(1) + +#define ETHOSN_CORE_NUM_MAX U(64) + +struct ethosn_config_t { + uint8_t status; + uint32_t num_cores; + uint64_t core_addr[ETHOSN_CORE_NUM_MAX]; +}; + +int fconf_populate_arm_ethosn(uintptr_t config); + +extern struct ethosn_config_t ethosn_config; + +#endif /* FCONF_ETHOSN_GETTER_H */ diff --git a/plat/arm/board/juno/fdts/juno_fw_config.dts b/plat/arm/board/juno/fdts/juno_fw_config.dts index c0538f8639e03a39b73b15707c275d552749f8ca..4b88efe8c0142eb0c18fd2e9d7522529bb681bba 100644 --- a/plat/arm/board/juno/fdts/juno_fw_config.dts +++ b/plat/arm/board/juno/fdts/juno_fw_config.dts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020, ARM Limited. All rights reserved. + * Copyright (c) 2019-2021, ARM Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -17,5 +17,11 @@ max-size = <0x200>; id = ; }; + + hw-config { + load-address = <0x0 0x82000000>; + max-size = <0x8000>; + id = ; + }; }; }; diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h index 91c3ae7e0c8a528de8c7adfa4035afdc08898f6c..5299a7b8a9070cf436778d866d39281f942a3656 100644 --- a/plat/arm/board/juno/include/platform_def.h +++ b/plat/arm/board/juno/include/platform_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -53,6 +53,14 @@ #define PLAT_ARM_DRAM2_BASE ULL(0x880000000) #define PLAT_ARM_DRAM2_SIZE ULL(0x180000000) +#define PLAT_HW_CONFIG_DTB_BASE ULL(0x82000000) +#define PLAT_HW_CONFIG_DTB_SIZE ULL(0x00008000) /* 32KB */ + +#define ARM_DTB_DRAM_NS MAP_REGION_FLAT( \ + PLAT_HW_CONFIG_DTB_BASE, \ + PLAT_HW_CONFIG_DTB_SIZE, \ + MT_MEMORY | MT_RO | MT_NS) + /* virtual address used by dynamic mem_protect for chunk_base */ #define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000) @@ -108,7 +116,7 @@ #ifdef IMAGE_BL31 # define PLAT_ARM_MMAP_ENTRIES 7 -# define MAX_XLAT_TABLES 3 +# define MAX_XLAT_TABLES 5 #endif #ifdef IMAGE_BL32 diff --git a/plat/arm/board/juno/juno_bl2_setup.c b/plat/arm/board/juno/juno_bl2_setup.c index 95ef77c0d04b4c7e4a028875928c484e4362ce55..849acd6c98944e9c0b04340034554eb968626484 100644 --- a/plat/arm/board/juno/juno_bl2_setup.c +++ b/plat/arm/board/juno/juno_bl2_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2017,2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,6 +8,9 @@ #include #include +#include +#include + #include #if JUNO_AARCH32_EL3_RUNTIME @@ -30,4 +33,41 @@ int arm_bl2_plat_handle_post_image_load(unsigned int image_id) return err; } + +#else + +/******************************************************************************* + * This function returns the list of executable images + ******************************************************************************/ +struct bl_params *plat_get_next_bl_params(void) +{ + struct bl_params *arm_bl_params = arm_get_next_bl_params(); + +#if __aarch64__ + const struct dyn_cfg_dtb_info_t *fw_config_info; + bl_mem_params_node_t *param_node; + uintptr_t fw_config_base = 0U; + entry_point_info_t *ep_info; + + /* Get BL31 image node */ + param_node = get_bl_mem_params_node(BL31_IMAGE_ID); + assert(param_node != NULL); + + /* Get fw_config load address */ + fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID); + assert(fw_config_info != NULL); + + fw_config_base = fw_config_info->config_addr; + assert(fw_config_base != 0U); + + /* + * Get the entry point info of BL31 image and override + * arg1 of entry point info with fw_config base address + */ + ep_info = ¶m_node->ep_info; + ep_info->args.arg1 = (uint32_t)fw_config_base; +#endif /* __aarch64__ */ + + return arm_bl_params; +} #endif /* JUNO_AARCH32_EL3_RUNTIME */ diff --git a/plat/arm/board/juno/juno_bl31_setup.c b/plat/arm/board/juno/juno_bl31_setup.c new file mode 100644 index 0000000000000000000000000000000000000000..7a0a6d97bcbe871bb9197af341754b6e83748a7b --- /dev/null +++ b/plat/arm/board/juno/juno_bl31_setup.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include + +void __init bl31_early_platform_setup2(u_register_t arg0, + u_register_t arg1, u_register_t arg2, u_register_t arg3) +{ + const struct dyn_cfg_dtb_info_t *soc_fw_config_info; + + INFO("BL31 FCONF: FW_CONFIG address = %lx\n", (uintptr_t)arg1); + + /* Fill the properties struct with the info from the config dtb */ + fconf_populate("FW_CONFIG", arg1); + + soc_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, SOC_FW_CONFIG_ID); + if (soc_fw_config_info != NULL) { + arg1 = soc_fw_config_info->config_addr; + } + + arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + plat_arm_interconnect_init(); + + /* + * Enable Interconnect coherency for the primary CPU's cluster. + * Earlier bootloader stages might already do this (e.g. Trusted + * Firmware's BL1 does it) but we can't assume so. There is no harm in + * executing this code twice anyway. + * Platform specific PSCI code will enable coherency for other + * clusters. + */ + plat_arm_interconnect_enter_coherency(); +} + +void __init bl31_plat_arch_setup(void) +{ + arm_bl31_plat_arch_setup(); + + /* HW_CONFIG was also loaded by BL2 */ + const struct dyn_cfg_dtb_info_t *hw_config_info; + + hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID); + assert(hw_config_info != NULL); + + fconf_populate("HW_CONFIG", hw_config_info->config_addr); +} diff --git a/plat/arm/board/juno/juno_common.c b/plat/arm/board/juno/juno_common.c index da4918cf20f3f0b9b85a54fc480c744157ca847a..cb183d53942c91c40ea314d21575b18f9d6af020 100644 --- a/plat/arm/board/juno/juno_common.c +++ b/plat/arm/board/juno/juno_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -75,6 +75,7 @@ const mmap_region_t plat_arm_mmap[] = { ARM_V2M_MAP_MEM_PROTECT, #endif SOC_CSS_MAP_DEVICE, + ARM_DTB_DRAM_NS, {0} }; #endif diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk index 5cf57497a824350646b5f19c45d9974a86e2ad91..92fbf3598d3e99b67844d537d1cdee109785012b 100644 --- a/plat/arm/board/juno/platform.mk +++ b/plat/arm/board/juno/platform.mk @@ -83,6 +83,10 @@ BL31_SOURCES += drivers/cfi/v2m/v2m_flash.c \ lib/cpus/aarch64/cortex_a57.S \ lib/cpus/aarch64/cortex_a72.S \ lib/utils/mem_region.c \ + common/fdt_wrappers.c \ + lib/fconf/fconf.c \ + lib/fconf/fconf_dyn_cfg_getter.c \ + plat/arm/board/juno/juno_bl31_setup.c \ plat/arm/board/juno/juno_pm.c \ plat/arm/board/juno/juno_topology.c \ plat/arm/common/arm_nor_psci_mem_protect.c \ @@ -174,15 +178,19 @@ BL32_CPPFLAGS += -march=armv8-a+crc # Add the FDT_SOURCES and options for Dynamic Config FDT_SOURCES += plat/arm/board/juno/fdts/${PLAT}_fw_config.dts \ - plat/arm/board/juno/fdts/${PLAT}_tb_fw_config.dts + plat/arm/board/juno/fdts/${PLAT}_tb_fw_config.dts \ + fdts/${PLAT}.dts FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb +HW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}.dtb # Add the FW_CONFIG to FIP and specify the same to certtool $(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG})) # Add the TB_FW_CONFIG to FIP and specify the same to certtool $(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG})) +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${HW_CONFIG},--hw-config,${HW_CONFIG})) include plat/arm/board/common/board_common.mk include plat/arm/common/arm_common.mk diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk index a225b405297c9f779564cc7129a9b71b5d0ba048..232d56242035bd85f4cd7bd6aa7a26a9d60722a8 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -100,6 +100,11 @@ ifeq (${ARM_LINUX_KERNEL_AS_BL33},1) $(eval $(call add_define,ARM_PRELOADED_DTB_BASE)) endif +# Arm Ethos-N NPU SiP service +ARM_ETHOSN_NPU_DRIVER := 0 +$(eval $(call assert_boolean,ARM_ETHOSN_NPU_DRIVER)) +$(eval $(call add_define,ARM_ETHOSN_NPU_DRIVER)) + # Use an implementation of SHA-256 with a smaller memory footprint but reduced # speed. $(eval $(call add_define,MBEDTLS_SHA256_SMALLER)) @@ -248,14 +253,26 @@ BL31_SOURCES += plat/arm/common/arm_bl31_setup.c \ plat/arm/common/arm_topology.c \ plat/common/plat_psci_common.c -ifeq (${ENABLE_PMF}, 1) +ifneq ($(filter 1,${ENABLE_PMF} ${ARM_ETHOSN_NPU_DRIVER}),) +ARM_SVC_HANDLER_SRCS := + +ifeq (${ENABLE_PMF},1) +ARM_SVC_HANDLER_SRCS += lib/pmf/pmf_smc.c +endif + +ifeq (${ARM_ETHOSN_NPU_DRIVER},1) +ARM_SVC_HANDLER_SRCS += plat/arm/common/fconf/fconf_ethosn_getter.c \ + drivers/delay_timer/delay_timer.c \ + drivers/arm/ethosn/ethosn_smc.c +endif + ifeq (${ARCH}, aarch64) BL31_SOURCES += plat/arm/common/aarch64/execution_state_switch.c\ plat/arm/common/arm_sip_svc.c \ - lib/pmf/pmf_smc.c + ${ARM_SVC_HANDLER_SRCS} else BL32_SOURCES += plat/arm/common/arm_sip_svc.c \ - lib/pmf/pmf_smc.c + ${ARM_SVC_HANDLER_SRCS} endif endif diff --git a/plat/arm/common/arm_sip_svc.c b/plat/arm/common/arm_sip_svc.c index 9f5d4557c6b28b426de37003d95809162800eeaa..6456c78411b2dba34a15b76b17aaf4e2892d4730 100644 --- a/plat/arm/common/arm_sip_svc.c +++ b/plat/arm/common/arm_sip_svc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2019,2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -50,6 +51,8 @@ static uintptr_t arm_sip_handler(unsigned int smc_fid, { int call_count = 0; +#if ENABLE_PMF + /* * Dispatch PMF calls to PMF SMC handler and return its return * value @@ -59,6 +62,8 @@ static uintptr_t arm_sip_handler(unsigned int smc_fid, handle, flags); } +#endif /* ENABLE_PMF */ + #if USE_DEBUGFS if (is_debugfs_fid(smc_fid)) { @@ -68,6 +73,15 @@ static uintptr_t arm_sip_handler(unsigned int smc_fid, #endif /* USE_DEBUGFS */ +#if ARM_ETHOSN_NPU_DRIVER + + if (is_ethosn_fid(smc_fid)) { + return ethosn_smc_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } + +#endif /* ARM_ETHOSN_NPU_DRIVER */ + switch (smc_fid) { case ARM_SIP_SVC_EXE_STATE_SWITCH: { /* Execution state can be switched only if EL3 is AArch64 */ @@ -92,6 +106,11 @@ static uintptr_t arm_sip_handler(unsigned int smc_fid, /* PMF calls */ call_count += PMF_NUM_SMC_CALLS; +#if ARM_ETHOSN_NPU_DRIVER + /* ETHOSN calls */ + call_count += ETHOSN_NUM_SMC_CALLS; +#endif /* ARM_ETHOSN_NPU_DRIVER */ + /* State switch call */ call_count += 1; diff --git a/plat/arm/common/fconf/fconf_ethosn_getter.c b/plat/arm/common/fconf/fconf_ethosn_getter.c new file mode 100644 index 0000000000000000000000000000000000000000..1ba9f3a23a2f978e5ec0544d743a5d6d7ef977d1 --- /dev/null +++ b/plat/arm/common/fconf/fconf_ethosn_getter.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +struct ethosn_config_t ethosn_config; + +static uint8_t fdt_node_get_status(const void *fdt, int node) +{ + int len; + uint8_t status = ETHOSN_STATUS_DISABLED; + const char *node_status; + + node_status = fdt_getprop(fdt, node, "status", &len); + if (node_status == NULL || + (len == 5 && /* Includes null character */ + strncmp(node_status, "okay", 4U) == 0)) { + status = ETHOSN_STATUS_ENABLED; + } + + return status; +} + +int fconf_populate_ethosn_config(uintptr_t config) +{ + int ethosn_node; + int sub_node; + uint8_t ethosn_status; + uint32_t core_count = 0U; + uint32_t core_addr_idx = 0U; + const void *hw_conf_dtb = (const void *)config; + + /* Find offset to node with 'ethosn' compatible property */ + ethosn_node = fdt_node_offset_by_compatible(hw_conf_dtb, -1, "ethosn"); + if (ethosn_node < 0) { + ERROR("FCONF: Can't find 'ethosn' compatible node in dtb\n"); + return ethosn_node; + } + + /* If the Arm Ethos-N NPU is disabled the core check can be skipped */ + ethosn_status = fdt_node_get_status(hw_conf_dtb, ethosn_node); + if (ethosn_status == ETHOSN_STATUS_DISABLED) { + return 0; + } + + fdt_for_each_subnode(sub_node, hw_conf_dtb, ethosn_node) { + int err; + uintptr_t addr; + uint8_t status; + + /* Check that the sub node is "ethosn-core" compatible */ + if (fdt_node_check_compatible(hw_conf_dtb, sub_node, + "ethosn-core") != 0) { + /* Ignore incompatible sub node */ + continue; + } + + /* Including disabled cores */ + if (core_addr_idx >= ETHOSN_CORE_NUM_MAX) { + ERROR("FCONF: Reached max number of Arm Ethos-N NPU cores\n"); + return -1; + } + + status = fdt_node_get_status(hw_conf_dtb, ethosn_node); + if (status == ETHOSN_STATUS_DISABLED) { + ++core_addr_idx; + continue; + } + + err = fdt_get_reg_props_by_index(hw_conf_dtb, ethosn_node, + core_addr_idx, &addr, NULL); + if (err < 0) { + ERROR("FCONF: Failed to read reg property for Arm Ethos-N NPU core %u\n", + core_addr_idx); + return err; + } + + ethosn_config.core_addr[core_count++] = addr; + ++core_addr_idx; + } + + if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) { + ERROR("FCONF: Failed to parse sub nodes\n"); + return sub_node; + } + + /* The Arm Ethos-N NPU can't be used if no cores were found */ + if (core_count == 0) { + ERROR("FCONF: No Arm Ethos-N NPU cores found\n"); + return -1; + } + + ethosn_config.num_cores = core_count; + ethosn_config.status = ethosn_status; + + return 0; +} + +FCONF_REGISTER_POPULATOR(HW_CONFIG, ethosn_config, fconf_populate_ethosn_config);