feat(ethos-n): add SMC call to get FW properties
When the Arm(R) Ethos(TM)-N NPU firmware is loaded by BL2 into protected
memory, the Linux kernel NPU driver cannot access the firmware. To still
allow the kernel driver to access some information about the firmware,
SMC calls have been added so it can check compatibility and get the
necessary information to map the firmware into the SMMU for the NPU.
The API version has been given a minor version bump with this change to
indicate the added functionality.
Signed-off-by: Mikael Olsson <mikael.olsson@arm.com>
Change-Id: Idb076b7bcf54ed7e8eb39be80114dc1d1c45336d
diff --git a/drivers/arm/ethosn/ethosn_smc.c b/drivers/arm/ethosn/ethosn_smc.c
index 124de92..b5cb040 100644
--- a/drivers/arm/ethosn/ethosn_smc.c
+++ b/drivers/arm/ethosn/ethosn_smc.c
@@ -34,6 +34,10 @@
#define ETHOSN_CORE_SEC_REG(core_addr, reg_offset) \
(core_addr + reg_offset)
+#define ETHOSN_FW_VA_BASE 0x20000000UL
+#define ETHOSN_WORKING_DATA_VA_BASE 0x40000000UL
+#define ETHOSN_COMMAND_STREAM_VA_BASE 0x60000000UL
+
/* Reset timeout in us */
#define ETHOSN_RESET_TIMEOUT_US U(10 * 1000 * 1000)
#define ETHOSN_RESET_WAIT_US U(1)
@@ -304,6 +308,38 @@
}
}
+static uintptr_t ethosn_smc_fw_prop_handler(u_register_t fw_property,
+ void *handle)
+{
+#if ARM_ETHOSN_NPU_TZMP1
+ switch (fw_property) {
+ case ETHOSN_FW_PROP_VERSION:
+ SMC_RET4(handle, ETHOSN_SUCCESS,
+ big_fw->fw_ver_major,
+ big_fw->fw_ver_minor,
+ big_fw->fw_ver_patch);
+ case ETHOSN_FW_PROP_MEM_INFO:
+ SMC_RET3(handle, ETHOSN_SUCCESS,
+ ((void *)big_fw) + big_fw->offset,
+ big_fw->size);
+ case ETHOSN_FW_PROP_OFFSETS:
+ SMC_RET3(handle, ETHOSN_SUCCESS,
+ big_fw->ple_offset,
+ big_fw->unpriv_stack_offset);
+ case ETHOSN_FW_PROP_VA_MAP:
+ SMC_RET4(handle, ETHOSN_SUCCESS,
+ ETHOSN_FW_VA_BASE,
+ ETHOSN_WORKING_DATA_VA_BASE,
+ ETHOSN_COMMAND_STREAM_VA_BASE);
+ default:
+ WARN("ETHOSN: Unknown firmware property\n");
+ SMC_RET1(handle, ETHOSN_INVALID_PARAMETER);
+ }
+#else
+ SMC_RET1(handle, ETHOSN_NOT_SUPPORTED);
+#endif
+}
+
uintptr_t ethosn_smc_handler(uint32_t smc_fid,
u_register_t x1,
u_register_t x2,
@@ -329,13 +365,16 @@
x4 &= 0xFFFFFFFF;
}
- if (!is_ethosn_fid(smc_fid) || (fid > ETHOSN_FNUM_IS_SLEEPING)) {
+ if (!is_ethosn_fid(smc_fid) || (fid > ETHOSN_FNUM_GET_FW_PROP)) {
WARN("ETHOSN: Unknown SMC call: 0x%x\n", smc_fid);
SMC_RET1(handle, SMC_UNK);
}
- if (fid == ETHOSN_FNUM_VERSION) {
+ switch (fid) {
+ case ETHOSN_FNUM_VERSION:
SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR);
+ case ETHOSN_FNUM_GET_FW_PROP:
+ return ethosn_smc_fw_prop_handler(x1, handle);
}
return ethosn_smc_core_handler(fid, x1, x2, x3, x4, handle);
diff --git a/include/drivers/arm/ethosn.h b/include/drivers/arm/ethosn.h
index 01868e3..cfdad8e 100644
--- a/include/drivers/arm/ethosn.h
+++ b/include/drivers/arm/ethosn.h
@@ -15,7 +15,14 @@
#define ETHOSN_FNUM_HARD_RESET U(0x52)
#define ETHOSN_FNUM_SOFT_RESET U(0x53)
#define ETHOSN_FNUM_IS_SLEEPING U(0x54)
-/* 0x55-0x5F reserved for future use */
+#define ETHOSN_FNUM_GET_FW_PROP U(0x55)
+/* 0x56-0x5F reserved for future use */
+
+/* Properties for ETHOSN_FNUM_TZMP_GET_FW_PROP */
+#define ETHOSN_FW_PROP_VERSION U(0xF00)
+#define ETHOSN_FW_PROP_MEM_INFO U(0xF01)
+#define ETHOSN_FW_PROP_OFFSETS U(0xF02)
+#define ETHOSN_FW_PROP_VA_MAP U(0xF03)
/* SMC64 function IDs */
#define ETHOSN_FID_64(func_num) U(0xC2000000 | func_num)
@@ -40,7 +47,7 @@
/* Service version */
#define ETHOSN_VERSION_MAJOR U(2)
-#define ETHOSN_VERSION_MINOR U(3)
+#define ETHOSN_VERSION_MINOR U(4)
/* Return codes for function calls */
#define ETHOSN_SUCCESS 0