Merge changes from topic "arm_ethosn_npu_sip" into integration
* changes:
Add SiP service to configure Arm Ethos-N NPU
plat/arm/juno: Add support to use hw_config in BL31
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index be3f0bb..906daf8 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -1742,9 +1742,9 @@
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 a1d2313..2aa9738 100644
--- a/docs/plat/arm/arm-build-options.rst
+++ b/docs/plat/arm/arm-build-options.rst
@@ -91,6 +91,12 @@
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 @@
--------------
-*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 0000000..299d07c
--- /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 <stdint.h>
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <drivers/arm/ethosn.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <plat/arm/common/fconf_ethosn_getter.h>
+
+/* 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 0000000..87ab378
--- /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 0000000..56fe167
--- /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 0000000..6de2abb
--- /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 <lib/smccc.h>
+
+/* 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 85fdb28..2eeed95 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 0000000..0fd1f02
--- /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 <assert.h>
+
+#include <lib/fconf/fconf.h>
+
+#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 c0538f8..4b88efe 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 = <TB_FW_CONFIG_ID>;
};
+
+ hw-config {
+ load-address = <0x0 0x82000000>;
+ max-size = <0x8000>;
+ id = <HW_CONFIG_ID>;
+ };
};
};
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 91c3ae7..5299a7b 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 95ef77c..849acd6 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 <common/bl_common.h>
#include <common/desc_image_load.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+
#include <plat/arm/common/plat_arm.h>
#if JUNO_AARCH32_EL3_RUNTIME
@@ -30,4 +33,41 @@
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 0000000..7a0a6d9
--- /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 <assert.h>
+
+#include <common/debug.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+
+#include <plat/arm/common/plat_arm.h>
+
+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 da4918c..cb183d5 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 @@
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 5cf5749..92fbf35 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -83,6 +83,10 @@
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 @@
# 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 a225b40..232d562 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 @@
$(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 @@
plat/arm/common/arm_topology.c \
plat/common/plat_psci_common.c
+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 (${ENABLE_PMF}, 1)
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 9f5d455..6456c78 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 <common/debug.h>
#include <common/runtime_svc.h>
+#include <drivers/arm/ethosn.h>
#include <lib/debugfs.h>
#include <lib/pmf/pmf.h>
#include <plat/arm/common/arm_sip_svc.h>
@@ -50,6 +51,8 @@
{
int call_count = 0;
+#if ENABLE_PMF
+
/*
* Dispatch PMF calls to PMF SMC handler and return its return
* value
@@ -59,6 +62,8 @@
handle, flags);
}
+#endif /* ENABLE_PMF */
+
#if USE_DEBUGFS
if (is_debugfs_fid(smc_fid)) {
@@ -68,6 +73,15 @@
#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 @@
/* 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 0000000..1ba9f3a
--- /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 <assert.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <libfdt.h>
+#include <plat/arm/common/fconf_ethosn_getter.h>
+
+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);