--- /dev/null
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+
+#include "ethosn_big_fw.h"
+
+/* Magic (FourCC) number to identify the big firmware binary */
+#define ETHOSN_BIG_FW_MAGIC ('E' | ('N' << 8) | ('F' << 16) | ('W' << 24))
+
+/* Supported big firmware version */
+#define ETHOSN_BIG_FW_VERSION_MAJOR 9
+
+#define ETHOSN_ARCH_VER_MAJOR_MASK U(0xF000)
+#define ETHOSN_ARCH_VER_MAJOR_SHIFT U(0xC)
+#define ETHOSN_ARCH_VER_MINOR_MASK U(0xF00)
+#define ETHOSN_ARCH_VER_MINOR_SHIFT U(0x8)
+#define ETHOSN_ARCH_VER_REV_MASK U(0xFF)
+
+/* Convert Arm(R) Ethos(TM)-N NPU architecture version to big firmware format */
+#define ETHOSN_BIG_FW_FORMAT_ARCH_VER(arch_ver) \
+ (arch_ver & ETHOSN_ARCH_VER_MAJOR_MASK) << ETHOSN_ARCH_VER_MAJOR_SHIFT | \
+ (arch_ver & ETHOSN_ARCH_VER_MINOR_MASK) << ETHOSN_ARCH_VER_MINOR_SHIFT | \
+ (arch_ver & ETHOSN_ARCH_VER_REV_MASK)
+
+
+bool ethosn_big_fw_verify_header(const struct ethosn_big_fw *big_fw,
+ uint32_t npu_arch_ver)
+{
+ const uint32_t arch_ver = ETHOSN_BIG_FW_FORMAT_ARCH_VER(npu_arch_ver);
+
+ if (big_fw->fw_magic != ETHOSN_BIG_FW_MAGIC) {
+ ERROR("ETHOSN: Unable to find firmware. Invalid magic value: 0x%02x\n",
+ big_fw->fw_magic);
+
+ return false;
+ }
+
+ if (big_fw->fw_ver_major != ETHOSN_BIG_FW_VERSION_MAJOR) {
+ ERROR("ETHOSN: Unsupported firmware version: %u.%u.%u. Expected Version %u.x.x.\n",
+ big_fw->fw_ver_major, big_fw->fw_ver_minor,
+ big_fw->fw_ver_patch, ETHOSN_BIG_FW_VERSION_MAJOR);
+
+ return false;
+ }
+
+ if (big_fw->arch_min > arch_ver || arch_ver > big_fw->arch_max) {
+ ERROR("ETHOSN: Firmware is not compatbile with architecture version: 0x%02x\n",
+ npu_arch_ver);
+ return false;
+ }
+
+ return true;
+}
--- /dev/null
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/*
+ * Big FW binary structure.
+ * Must be kept in sync with the Arm(R) Ethos(TM)-N NPU firmware binary layout.
+ */
+struct ethosn_big_fw {
+ uint32_t fw_magic;
+ uint32_t fw_ver_major;
+ uint32_t fw_ver_minor;
+ uint32_t fw_ver_patch;
+ uint32_t arch_min;
+ uint32_t arch_max;
+ uint32_t offset;
+ uint32_t size;
+ uint32_t code_offset;
+ uint32_t code_size;
+ uint32_t ple_offset;
+ uint32_t ple_size;
+ uint32_t vector_table_offset;
+ uint32_t vector_table_size;
+ uint32_t unpriv_stack_offset;
+ uint32_t unpriv_stack_size;
+ uint32_t priv_stack_offset;
+ uint32_t priv_stack_size;
+} __packed;
+
+bool ethosn_big_fw_verify_header(const struct ethosn_big_fw *big_fw,
+ uint32_t npu_arch_ver);
#include <platform_def.h>
+#if ARM_ETHOSN_NPU_TZMP1
+#include "ethosn_big_fw.h"
+#endif
+
/*
* Number of Arm(R) Ethos(TM)-N NPU (NPU) devices available
*/
#define SEC_MMUSID_REG_BASE U(0x3008)
#define SEC_MMUSID_OFFSET U(0x1000)
+#define SEC_NPU_ID_REG U(0xF000)
+#define SEC_NPU_ID_ARCH_VER_SHIFT U(0X10)
+
#define INPUT_STREAM_INDEX U(0x6)
#define INTERMEDIATE_STREAM_INDEX U(0x7)
#define OUTPUT_STREAM_INDEX U(0x8)
+#if ARM_ETHOSN_NPU_TZMP1
+CASSERT(ARM_ETHOSN_NPU_FW_IMAGE_BASE > 0U, assert_ethosn_invalid_fw_image_base);
+static const struct ethosn_big_fw *big_fw;
+#endif
+
static bool ethosn_get_device_and_core(uintptr_t core_addr,
const struct ethosn_device_t **dev_match,
const struct ethosn_core_t **core_match)
}
#if ARM_ETHOSN_NPU_TZMP1
+static uint32_t ethosn_core_read_arch_version(uintptr_t core_addr)
+{
+ uint32_t npu_id = mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr,
+ SEC_NPU_ID_REG));
+
+ return (npu_id >> SEC_NPU_ID_ARCH_VER_SHIFT);
+}
+
static void ethosn_configure_stream_nsaid(const struct ethosn_core_t *core,
bool is_protected)
{
int ethosn_smc_setup(void)
{
+#if ARM_ETHOSN_NPU_TZMP1
+ struct ethosn_device_t *dev;
+ uint32_t arch_ver;
+#endif
+
if (ETHOSN_NUM_DEVICES == 0U) {
ERROR("ETHOSN: No NPU found\n");
return ETHOSN_FAILURE;
}
+#if ARM_ETHOSN_NPU_TZMP1
+
+ /* Only one NPU core is supported in the TZMP1 setup */
+ if ((ETHOSN_NUM_DEVICES != 1U) ||
+ (ETHOSN_GET_DEVICE(0U)->num_cores != 1U)) {
+ ERROR("ETHOSN: TZMP1 doesn't support multiple NPU cores\n");
+ return ETHOSN_FAILURE;
+ }
+
+ dev = ETHOSN_GET_DEVICE(0U);
+ arch_ver = ethosn_core_read_arch_version(dev->cores[0U].addr);
+ big_fw = (struct ethosn_big_fw *)ARM_ETHOSN_NPU_FW_IMAGE_BASE;
+
+ if (!ethosn_big_fw_verify_header(big_fw, arch_ver)) {
+ return ETHOSN_FAILURE;
+ }
+
+ NOTICE("ETHOSN: TZMP1 setup succeeded with firmware version %u.%u.%u\n",
+ big_fw->fw_ver_major, big_fw->fw_ver_minor,
+ big_fw->fw_ver_patch);
+#else
+ NOTICE("ETHOSN: Setup succeeded\n");
+#endif
+
return 0;
}
MT_MEMORY | MT_RO | MT_NS)
#ifdef JUNO_ETHOSN_TZMP1
+#define JUNO_ETHOSN_PROT_FW_RO MAP_REGION_FLAT( \
+ JUNO_ETHOSN_FW_TZC_PROT_DRAM2_BASE, \
+ JUNO_ETHOSN_FW_TZC_PROT_DRAM2_SIZE, \
+ MT_RO_DATA | MT_SECURE)
+
#define JUNO_ETHOSN_PROT_FW_RW MAP_REGION_FLAT( \
JUNO_ETHOSN_FW_TZC_PROT_DRAM2_BASE, \
JUNO_ETHOSN_FW_TZC_PROT_DRAM2_SIZE, \
#endif
#ifdef IMAGE_BL31
-# define PLAT_ARM_MMAP_ENTRIES 7
-# define MAX_XLAT_TABLES 5
+# define PLAT_ARM_MMAP_ENTRIES 8
+# define MAX_XLAT_TABLES 6
#endif
#ifdef IMAGE_BL32
#endif
SOC_CSS_MAP_DEVICE,
ARM_DTB_DRAM_NS,
+#ifdef JUNO_ETHOSN_TZMP1
+ JUNO_ETHOSN_PROT_FW_RO,
+#endif
{0}
};
#endif
ARM_SVC_HANDLER_SRCS += plat/arm/common/fconf/fconf_ethosn_getter.c \
drivers/delay_timer/delay_timer.c \
drivers/arm/ethosn/ethosn_smc.c
+ifeq (${ARM_ETHOSN_NPU_TZMP1},1)
+ARM_SVC_HANDLER_SRCS += drivers/arm/ethosn/ethosn_big_fw.c
+endif
endif
ifeq (${ARCH}, aarch64)