This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 438eadd880a366609e5e7c1f565e1fe48113dbad
Author: Jukka Laitinen <[email protected]>
AuthorDate: Tue Sep 1 15:17:48 2026 +0300

    arch/arm/imxrt: Port the imx93 ELE driver for iMXRT118x
    
    iMXRT118x uses the same security element as the imx93. Just add iMXRT 
specific
    register definitions and port over the driver code.
    
    Signed-off-by: Jukka Laitinen <[email protected]>
---
 arch/arm/src/imxrt/CMakeLists.txt                  |   4 +
 arch/arm/src/imxrt/Kconfig                         |   9 +
 arch/arm/src/imxrt/Make.defs                       |   4 +
 arch/arm/src/imxrt/hardware/rt118x/imxrt118x_ele.h | 125 ++++
 arch/arm/src/imxrt/imxrt118x_ele.c                 | 640 +++++++++++++++++++++
 arch/arm/src/imxrt/imxrt118x_ele.h                 | 367 ++++++++++++
 6 files changed, 1149 insertions(+)

diff --git a/arch/arm/src/imxrt/CMakeLists.txt 
b/arch/arm/src/imxrt/CMakeLists.txt
index 741a486bb68..b17af15dd10 100644
--- a/arch/arm/src/imxrt/CMakeLists.txt
+++ b/arch/arm/src/imxrt/CMakeLists.txt
@@ -155,4 +155,8 @@ if(CONFIG_IMXRT_TRDC)
   list(APPEND SRCS imxrt118x_trdc.c)
 endif()
 
+if(CONFIG_IMXRT_ELE)
+  list(APPEND SRCS imxrt118x_ele.c)
+endif()
+
 target_sources(arch PRIVATE ${SRCS})
diff --git a/arch/arm/src/imxrt/Kconfig b/arch/arm/src/imxrt/Kconfig
index 1ecb4ea7c77..fd46a6dc4a7 100644
--- a/arch/arm/src/imxrt/Kconfig
+++ b/arch/arm/src/imxrt/Kconfig
@@ -126,6 +126,7 @@ config ARCH_CHIP_MIMXRT1189CVM8C_CM33
        select ARCH_CORTEXM33
        select ARMV8M_HAVE_STACKCHECK
        select IMXRT_TRDC
+       select IMXRT_ELE
        ---help---
                Target the Cortex-M33 core on the RT1189 SoC.  Used to build a
                NuttX bootloader / minimal application that runs on the M33 out
@@ -424,6 +425,14 @@ config IMXRT_TRDC
                (arch/arm/src/imxrt/imxrt118x_trdc.c).  Present on RT118x-class
                SoCs.
 
+config IMXRT_ELE
+       bool
+       default n
+       ---help---
+               Enable the NXP EdgeLock Enclave (ELE) messaging driver
+               (arch/arm/src/imxrt/imxrt118x_ele.c).  Present on RT118x-class
+               SoCs.
+
 menu "i.MX RT Peripheral Selection"
 
 config IMXRT_EDMA
diff --git a/arch/arm/src/imxrt/Make.defs b/arch/arm/src/imxrt/Make.defs
index edf5683e17b..ab93227b025 100644
--- a/arch/arm/src/imxrt/Make.defs
+++ b/arch/arm/src/imxrt/Make.defs
@@ -150,3 +150,7 @@ endif
 ifeq ($(CONFIG_IMXRT_TRDC),y)
 CHIP_CSRCS += imxrt118x_trdc.c
 endif
+
+ifeq ($(CONFIG_IMXRT_ELE),y)
+CHIP_CSRCS += imxrt118x_ele.c
+endif
diff --git a/arch/arm/src/imxrt/hardware/rt118x/imxrt118x_ele.h 
b/arch/arm/src/imxrt/hardware/rt118x/imxrt118x_ele.h
new file mode 100644
index 00000000000..ed050eac0d1
--- /dev/null
+++ b/arch/arm/src/imxrt/hardware/rt118x/imxrt118x_ele.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+ * arch/arm/src/imxrt/hardware/rt118x/imxrt118x_ele.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_IMXRT_HARDWARE_RT118X_IMXRT118X_ELE_H
+#define __ARCH_ARM_SRC_IMXRT_HARDWARE_RT118X_IMXRT118X_ELE_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "hardware/imxrt_memorymap.h"
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define ELE_MAX_MSG               255U
+
+#define ELE_CMD_TAG               0x17
+#define ELE_VERSION               0x6
+#define ELE_VERSION_FW            0x7
+#define ELE_RESP_TAG              0xe1
+#define ELE_OK                    0xd6
+
+/* ELE commands. */
+
+#define ELE_LOAD_FW_REQ           0x02
+#define ELE_ENABLE_APC_REQ        0xd2
+#define ELE_RELEASE_RDC_REQ       0xc4
+#define ELE_GET_FW_VERSION_REQ    0x9d
+#define ELE_DERIVE_KEY_REQ        0xa9
+#define ELE_GET_EVENTS_REQ        0xa2
+#define ELE_GET_TRNG_STATE_REQ    0xa4
+#define ELE_GET_RNG_REQ           0xcd
+#define ELE_FWD_LIFECYCLE_UP_REQ  0x95
+#define ELE_OEM_CNTN_AUTH_REQ     0x87
+#define ELE_READ_FUSE_REQ         0x97
+#define ELE_RELEASE_CONTAINER_REQ 0x89
+#define ELE_START_RNG_REQ         0xa3
+#define ELE_VERIFY_IMAGE_REQ      0x88
+#define ELE_COMMIT_REQ            0xa8
+#define ELE_GET_INFO_REQ          0xda
+#define ELE_VOLTAGE_CHANGE_START_REQ  0x12
+#define ELE_VOLTAGE_CHANGE_FINISH_REQ 0x13
+
+/* RT118x RDC identifiers used by ELE_RELEASE_RDC_REQ, from NXP
+ * MCUXpresso SDK examples/_boards/evkmimxrt1180/board.c.
+ */
+
+#define ELE_TRDC_AON_ID           0x74
+#define ELE_TRDC_WAKEUP_ID        0x78
+#define ELE_TRDC_MEGA_ID          0x82
+
+#define ELE_CORE_CM33_ID          0x1
+#define ELE_CORE_CM7_ID           0x2
+
+/* GET_INFO returned data. */
+
+#define ELE_GET_INFO_BYTES        160
+#define ELE_GET_INFO_LC_WORD      2
+#define ELE_GET_INFO_LC_MASK      0xffff
+
+/* System 3 Messaging Unit A (IMXRT1180RM Ch. 65).
+ * The CM33 boots in Secure state and NXP's own SDK uses the Secure alias
+ * (0x57540000) rather than the Non-secure alias (0x47540000) for all ELE
+ * traffic — writes via the Non-secure alias may not reach the enclave
+ * even though reads mirror the same peripheral.
+ */
+
+#define ELE_MU_TCR                (IMXRT_S3MUA_BASE + 0x120)
+#define ELE_MU_TSR                (IMXRT_S3MUA_BASE + 0x124)
+#define ELE_MU_RCR                (IMXRT_S3MUA_BASE + 0x128)
+#define ELE_MU_RSR                (IMXRT_S3MUA_BASE + 0x12c)
+
+#define ELE_RR_NUM                4
+#define ELE_TR_NUM                8
+#define ELE_MU_TR(i)              (IMXRT_S3MUA_BASE + 0x200 + (i) * 4)
+#define ELE_MU_RR(i)              (IMXRT_S3MUA_BASE + 0x280 + (i) * 4)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct ele_header_t
+{
+  union
+    {
+      uint32_t data;
+      struct
+        {
+          uint32_t version : 8;
+          uint32_t size : 8;
+          uint32_t command : 8;
+          uint32_t tag : 8;
+        };
+    };
+};
+
+struct ele_msg
+{
+  struct ele_header_t header;
+  uint32_t data[(ELE_MAX_MSG - 1)];
+};
+
+#endif /* __ARCH_ARM_SRC_IMXRT_HARDWARE_RT118X_IMXRT118X_ELE_H */
diff --git a/arch/arm/src/imxrt/imxrt118x_ele.c 
b/arch/arm/src/imxrt/imxrt118x_ele.c
new file mode 100644
index 00000000000..77eaf8cfc01
--- /dev/null
+++ b/arch/arm/src/imxrt/imxrt118x_ele.c
@@ -0,0 +1,640 @@
+/****************************************************************************
+ * arch/arm/src/imxrt/imxrt118x_ele.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/nuttx.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <errno.h>
+#include <debug.h>
+
+#include "arm_internal.h"
+#include "hardware/rt118x/imxrt118x_memorymap.h"
+#include "imxrt118x_ele.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* The M7 core is Armv7-M and the M33 core is Armv8-M; pick whichever
+ * D-Cache line size macro chip.h provided for the core we're building
+ * for.
+ */
+
+#if defined(ARMV8M_DCACHE_LINESIZE)
+#  define DCACHE_LINESIZE ARMV8M_DCACHE_LINESIZE
+#else
+#  define DCACHE_LINESIZE ARMV7M_DCACHE_LINESIZE
+#endif
+
+#define upper_32_bits(n) ((uint32_t)(((n) >> 16) >> 16))
+#define lower_32_bits(n) ((uint32_t)(n))
+
+#define ELE_RNG_TIMEOUT_US    5000
+#define ELE_RNG_SLEEP_US      100
+#define ELE_TRNG_STATUS_READY 0x3
+#define ELE_CSAL_STATUS_READY 0x2
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct ele_trng_state
+{
+  uint8_t  trng_state;
+  uint8_t  csal_state;
+  uint16_t reserved;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct ele_msg g_msg;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: imxrt118x_ele_sendmsg
+ *
+ * Description:
+ *   Send a message to the EdgeLock Enclave over the System 3 Message Unit A.
+ *
+ ****************************************************************************/
+
+static void imxrt118x_ele_sendmsg(struct ele_msg *msg_ptr)
+{
+  /* Check that ele is ready to receive */
+
+  while (!((1) & getreg32(ELE_MU_TSR)));
+
+  /* write header to slot 0 */
+
+  putreg32(msg_ptr->header.data, ELE_MU_TR(0));
+
+  /* write data */
+
+  for (int i = 1; i < msg_ptr->header.size; i++)
+    {
+      int tx_channel;
+
+      tx_channel = i % ELE_TR_NUM;
+      while (!((1 << tx_channel) & getreg32(ELE_MU_TSR)));
+
+      /* Write data */
+
+      putreg32(msg_ptr->data[i - 1], ELE_MU_TR(tx_channel));
+    }
+}
+
+/****************************************************************************
+ * Name: imxrt118x_ele_receivemsg
+ *
+ * Description:
+ *   Receive a response message from the EdgeLock Enclave.
+ *
+ ****************************************************************************/
+
+static void imxrt118x_ele_receivemsg(struct ele_msg *msg_ptr)
+{
+  /* Check if data ready */
+
+  while (!((1) & getreg32(ELE_MU_RSR)));
+
+  /* Read Header from slot 0 */
+
+  msg_ptr->header.data = getreg32(ELE_MU_RR(0));
+
+  for (int i = 1; i < msg_ptr->header.size; i++)
+    {
+      /* Check if empty */
+
+      int rx_channel = (i) % ELE_RR_NUM;
+
+      while (!((1 << rx_channel) & getreg32(ELE_MU_RSR)));
+
+      /* Read data */
+
+      msg_ptr->data[i - 1] = getreg32(ELE_MU_RR(rx_channel));
+    }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void imxrt118x_ele_init(void)
+{
+  putreg32(0, ELE_MU_TCR);
+  putreg32(0, ELE_MU_RCR);
+
+  imxrt118x_ele_check_fw_version();
+}
+
+int imxrt118x_ele_load_fw(uint32_t fw_addr)
+{
+  g_msg.header.version = ELE_VERSION;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 4;
+  g_msg.header.command = ELE_LOAD_FW_REQ;
+  g_msg.data[0] = fw_addr;
+  g_msg.data[1] = 0;
+  g_msg.data[2] = fw_addr;
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+
+  if ((g_msg.data[0] & 0xff) == ELE_OK)
+    {
+      return 0;
+    }
+
+  return -EIO;
+}
+
+int imxrt118x_ele_release_rdc(uint32_t rdc_id)
+{
+  g_msg.header.version = ELE_VERSION;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 2;
+  g_msg.header.command = ELE_RELEASE_RDC_REQ;
+  g_msg.data[0] = rdc_id;
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+
+  if ((g_msg.data[0] & 0xff) == ELE_OK)
+    {
+      return 0;
+    }
+
+  return -EIO;
+}
+
+uint32_t imxrt118x_ele_read_common_fuse(uint32_t fuse_id)
+{
+  uint32_t value = 0;
+
+  g_msg.header.version = ELE_VERSION;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 2;
+  g_msg.header.command = ELE_READ_FUSE_REQ;
+  g_msg.data[0] = fuse_id;
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+
+  if ((g_msg.data[0] & 0xff) == ELE_OK)
+    {
+      value = g_msg.data[1];
+    }
+
+  return value;
+}
+
+int imxrt118x_ele_get_key(uint8_t *key, size_t key_size,
+                          uint8_t *ctx, size_t ctx_size)
+{
+  if (!key)
+    {
+      _err("Invalid key parameter\n");
+      return -EINVAL;
+    }
+
+  if (!ctx)
+    {
+      _err("Invalid context parameter\n");
+      return -EINVAL;
+    }
+
+  if ((key_size != 16) && (key_size != 32))
+    {
+      _err("Invalid key size\n");
+      return -EINVAL;
+    }
+
+  if (!IS_ALIGNED((uintptr_t)key, DCACHE_LINESIZE))
+    {
+      _err("Invalid key alignment\n");
+      return -EINVAL;
+    }
+
+  if (!IS_ALIGNED((uintptr_t)ctx, DCACHE_LINESIZE))
+    {
+      _err("Invalid context alignment\n");
+      return -EINVAL;
+    }
+
+  g_msg.header.version = ELE_VERSION;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 7;
+  g_msg.header.command = ELE_DERIVE_KEY_REQ;
+  g_msg.data[0] = upper_32_bits((uintptr_t)key);
+  g_msg.data[1] = lower_32_bits((uintptr_t)key);
+  g_msg.data[2] = upper_32_bits((uintptr_t)ctx);
+  g_msg.data[3] = lower_32_bits((uintptr_t)ctx);
+  g_msg.data[4] = ((ctx_size << 16) | key_size);
+
+  uint32_t crc = g_msg.header.data;
+
+  for (uint32_t i = 0; i < g_msg.header.size - 2; i++)
+    {
+      crc ^= g_msg.data[i];
+    }
+
+  g_msg.data[5] = crc;
+
+  up_flush_dcache((uintptr_t)ctx, (uintptr_t)(ctx + ctx_size));
+  up_invalidate_dcache((uintptr_t)key, (uintptr_t)(key + key_size));
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+
+  up_invalidate_dcache((uintptr_t)key, (uintptr_t)(key + key_size));
+
+  if ((g_msg.data[0] & 0xff) == ELE_OK)
+    {
+      return 0;
+    }
+
+  return -EIO;
+}
+
+int imxrt118x_ele_get_events(uint32_t *buffer, size_t buffer_size)
+{
+  size_t events_num;
+  size_t i;
+
+  g_msg.header.version = ELE_VERSION;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 1;
+  g_msg.header.command = ELE_GET_EVENTS_REQ;
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+
+  if ((g_msg.data[0] & 0xff) == ELE_OK)
+    {
+      events_num = g_msg.data[1] & 0xffff;
+      if (buffer)
+        {
+          for (i = 0; (i < buffer_size) && (i < events_num); i++)
+            {
+              buffer[i] =  g_msg.data[i + 2];
+            }
+
+          return (int)i;
+        }
+      else
+        {
+          return (int)events_num;
+        }
+    }
+
+  return -EIO;
+}
+
+int imxrt118x_ele_close_device(void)
+{
+  g_msg.header.version = ELE_VERSION;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 2;
+  g_msg.header.command = ELE_FWD_LIFECYCLE_UP_REQ;
+  g_msg.data[0] = 0x08;
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+
+  if ((g_msg.data[0] & 0xff) == ELE_OK)
+    {
+      return 0;
+    }
+
+  return -EIO;
+}
+
+uint32_t imxrt118x_ele_get_lifecycle(void)
+{
+  static uint8_t info[ELE_GET_INFO_BYTES]
+    aligned_data(DCACHE_LINESIZE);
+
+  uint32_t addr = (uint32_t)(uintptr_t)info;
+
+  g_msg.header.version = ELE_VERSION;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 4;
+  g_msg.header.command = ELE_GET_INFO_REQ;
+  g_msg.data[0] = upper_32_bits(addr);
+  g_msg.data[1] = lower_32_bits(addr);
+  g_msg.data[2] = sizeof(info);
+
+  up_invalidate_dcache(addr, addr + sizeof(info));
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+
+  if ((g_msg.data[0] & 0xff) != ELE_OK)
+    {
+      return 0;
+    }
+
+  up_invalidate_dcache(addr, addr + sizeof(info));
+
+  return ((uint32_t *)info)[ELE_GET_INFO_LC_WORD] & ELE_GET_INFO_LC_MASK;
+}
+
+int imxrt118x_ele_auth_oem_ctnr(unsigned long ctnr_addr, uint32_t *response)
+{
+  g_msg.header.version = ELE_VERSION;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 3;
+  g_msg.header.command = ELE_OEM_CNTN_AUTH_REQ;
+  g_msg.data[0] = upper_32_bits(ctnr_addr);
+  g_msg.data[1] = lower_32_bits(ctnr_addr);
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+  if (response)
+    {
+      *response = g_msg.data[0];
+    }
+
+  if ((g_msg.data[0] & 0xff) == ELE_OK)
+    {
+      return 0;
+    }
+
+  return -EIO;
+}
+
+int imxrt118x_ele_release_container(uint32_t *response)
+{
+  g_msg.header.version = ELE_VERSION;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 1;
+  g_msg.header.command = ELE_RELEASE_CONTAINER_REQ;
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+
+  if (response)
+    {
+      *response = g_msg.data[0];
+    }
+
+  if ((g_msg.data[0] & 0xff) == ELE_OK)
+    {
+      return 0;
+    }
+
+  return -EIO;
+}
+
+int imxrt118x_ele_verify_image(uint32_t img_id, uint32_t *response)
+{
+  g_msg.header.version = ELE_VERSION;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 2;
+  g_msg.header.command = ELE_VERIFY_IMAGE_REQ;
+  g_msg.data[0] = 1 << img_id;
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+
+  if (response)
+    {
+      *response = g_msg.data[0];
+    }
+
+  if ((g_msg.data[0] & 0xff) == ELE_OK)
+    {
+      return 0;
+    }
+
+  return -EIO;
+}
+
+int imxrt118x_ele_start_rng(void)
+{
+  g_msg.header.version = ELE_VERSION;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 1;
+  g_msg.header.command = ELE_START_RNG_REQ;
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+
+  if ((g_msg.data[0] & 0xff) == ELE_OK)
+    {
+      return 0;
+    }
+
+  return -EIO;
+}
+
+int imxrt118x_ele_get_trng_state(void)
+{
+  g_msg.header.version = ELE_VERSION;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 1;
+  g_msg.header.command = ELE_GET_TRNG_STATE_REQ;
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+
+  if ((g_msg.data[0] & 0xff) == ELE_OK)
+    {
+      struct ele_trng_state *ele_trng =
+        (struct ele_trng_state *)(g_msg.data + 1);
+
+      if (ele_trng->trng_state != ELE_TRNG_STATUS_READY ||
+          ele_trng->csal_state != ELE_CSAL_STATUS_READY)
+        {
+          /* Ensure imxrt118x_ele_start_rng() was called earlier or we
+           * will end up here.
+           */
+
+          return -EBUSY;
+        }
+      else
+        {
+          return 0;
+        }
+    }
+
+  return -EIO;
+}
+
+int imxrt118x_ele_get_random(uint32_t paddr, size_t len)
+{
+  uint16_t counter = 0;
+  uint16_t max_tries = ELE_RNG_TIMEOUT_US / ELE_RNG_SLEEP_US;
+
+  if (paddr == 0 || len == 0)
+    {
+      _err("Wrong input parameters!\n");
+      return -EINVAL;
+    }
+
+  while ((imxrt118x_ele_get_trng_state() != 0))
+    {
+      if (counter > max_tries)
+        {
+          _err("Timed out after %hu iterations!\n", counter);
+          return -EBUSY;
+        }
+
+      usleep(ELE_RNG_SLEEP_US);
+      counter++;
+    }
+
+  /* Flush the cache before sending the request to ELE. */
+
+  up_flush_dcache((uintptr_t)paddr, (uintptr_t)(paddr + len));
+
+  g_msg.header.version = ELE_VERSION_FW;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 4;
+  g_msg.header.command = ELE_GET_RNG_REQ;
+  g_msg.data[0] = 0;
+  g_msg.data[1] = paddr;
+  g_msg.data[2] = len;
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+
+  if ((g_msg.data[0] & 0xff) == ELE_OK)
+    {
+      /* Invalidate the cache so we can read the result from RAM. */
+
+      up_invalidate_dcache((uintptr_t)paddr,
+                           (uintptr_t)(paddr + len));
+      return 0;
+    }
+
+  return -EIO;
+}
+
+int imxrt118x_ele_commit(uint32_t info, uint32_t *response)
+{
+  g_msg.header.version = ELE_VERSION;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 2;
+  g_msg.header.command = ELE_COMMIT_REQ;
+  g_msg.data[0] = info;
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+
+  if (response)
+    {
+      *response = g_msg.data[0];
+    }
+
+  if ((g_msg.data[0] & 0xff) == ELE_OK)
+    {
+      return 0;
+    }
+
+  return -EIO;
+}
+
+int imxrt118x_ele_enable_apc(void)
+{
+  g_msg.header.version = ELE_VERSION;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 1;
+  g_msg.header.command = ELE_ENABLE_APC_REQ;
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+
+  if ((g_msg.data[0] & 0xff) == ELE_OK)
+    {
+      return 0;
+    }
+
+  return -EIO;
+}
+
+int imxrt118x_ele_voltage_change_start(void)
+{
+  g_msg.header.version = ELE_VERSION;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 1;
+  g_msg.header.command = ELE_VOLTAGE_CHANGE_START_REQ;
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+
+  if ((g_msg.data[0] & 0xff) == ELE_OK)
+    {
+      return 0;
+    }
+
+  return -EIO;
+}
+
+int imxrt118x_ele_voltage_change_finish(void)
+{
+  g_msg.header.version = ELE_VERSION;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 1;
+  g_msg.header.command = ELE_VOLTAGE_CHANGE_FINISH_REQ;
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+
+  if ((g_msg.data[0] & 0xff) == ELE_OK)
+    {
+      return 0;
+    }
+
+  return -EIO;
+}
+
+int imxrt118x_ele_check_fw_version(void)
+{
+  g_msg.header.version = ELE_VERSION;
+  g_msg.header.tag = ELE_CMD_TAG;
+  g_msg.header.size = 1;
+  g_msg.header.command = ELE_GET_FW_VERSION_REQ;
+
+  imxrt118x_ele_sendmsg(&g_msg);
+  imxrt118x_ele_receivemsg(&g_msg);
+
+  if ((g_msg.data[0] & 0xff) != ELE_OK)
+    {
+      return -EIO;
+    }
+
+  return 0;
+}
diff --git a/arch/arm/src/imxrt/imxrt118x_ele.h 
b/arch/arm/src/imxrt/imxrt118x_ele.h
new file mode 100644
index 00000000000..d2e443050f7
--- /dev/null
+++ b/arch/arm/src/imxrt/imxrt118x_ele.h
@@ -0,0 +1,367 @@
+/****************************************************************************
+ * arch/arm/src/imxrt/imxrt118x_ele.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_IMXRT_IMXRT118X_ELE_H
+#define __ARCH_ARM_SRC_IMXRT_IMXRT118X_ELE_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+
+#include "hardware/rt118x/imxrt118x_ele.h"
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: imxrt118x_ele_init
+ *
+ * Description:
+ *   Bring the EdgeLock Enclave up.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void imxrt118x_ele_init(void);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_load_fw
+ *
+ * Description:
+ *   Load the EdgeLock Enclave firmware.
+ *
+ * Input Parameters:
+ *   fw_addr - Address of the ELE firmware container.
+ *
+ * Returned Value:
+ *   OK on success, a negated errno value otherwise.
+ *
+ ****************************************************************************/
+
+int imxrt118x_ele_load_fw(uint32_t fw_addr);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_release_rdc
+ *
+ * Description:
+ *   Request ownership of one TRDC.
+ *
+ * Input Parameters:
+ *   rdc_id - Packed TRDC and core identifier.
+ *
+ * Returned Value:
+ *   OK on success, a negated errno value otherwise.
+ *
+ ****************************************************************************/
+
+int imxrt118x_ele_release_rdc(uint32_t rdc_id);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_read_common_fuse
+ *
+ * Description:
+ *   Read a common fuse value.
+ *
+ * Input Parameters:
+ *   fuse_id - Fuse ID
+ *
+ * Returned Value:
+ *   Fuse value. Returns zero if read failed.
+ *
+ ****************************************************************************/
+
+uint32_t imxrt118x_ele_read_common_fuse(uint32_t fuse_id);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_get_key
+ *
+ * Description:
+ *   Return HW unique key value.
+ *
+ * Input Parameters:
+ *   key           -  Key buffer, must be cache line aligned
+ *   key_size      -  Key size in bytes, must be 16 or 32
+ *   ctx           -  Context buffer, must be cache line aligned
+ *   ctx_size      -  Context buffer size
+ *
+ * Returned Value:
+ *   OK on success, a negated errno value otherwise.
+ *
+ ****************************************************************************/
+
+int imxrt118x_ele_get_key(uint8_t *key, size_t key_size,
+                          uint8_t *ctx, size_t ctx_size);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_get_events
+ *
+ * Description:
+ *   Return ELE events.
+ *
+ * Input Parameters:
+ *   buffer        -  Event buffer
+ *   buffer_size   -  Event buffer size
+ *
+ * Returned Value:
+ *   Zero (OK) is returned if no events. A negated errno value is returned
+ *   on failure. Positive value is number of events read.
+ *
+ ****************************************************************************/
+
+int imxrt118x_ele_get_events(uint32_t *buffer, size_t buffer_size);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_close_device
+ *
+ * Description:
+ *   Set device to OEM close state. This operation is irreversible.
+ *
+ * Returned Value:
+ *   OK on success, a negated errno value otherwise.
+ *
+ ****************************************************************************/
+
+int imxrt118x_ele_close_device(void);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_get_lifecycle
+ *
+ * Description:
+ *   Return the device's lifecycle value, queried from the ELE via
+ *   GET_INFO (RT118x has no i.MX9-style FSB lifecycle register).
+ *
+ * Returned Value:
+ *   Lifecycle value.
+ *
+ ****************************************************************************/
+
+uint32_t imxrt118x_ele_get_lifecycle(void);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_auth_oem_ctnr
+ *
+ * Description:
+ *   Authenticate container header.
+ *
+ * Input Parameters:
+ *   ctnr_addr - Address of the container header.
+ *
+ * Output Parameters:
+ *   response - ELE response, can be used for debugging.
+ *
+ * Returned Value:
+ *   OK on success, a negated errno value otherwise.
+ *
+ ****************************************************************************/
+
+int imxrt118x_ele_auth_oem_ctnr(unsigned long ctnr_addr, uint32_t *response);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_release_container
+ *
+ * Description:
+ *   Release the container from the ELE, used after
+ *   imxrt118x_ele_auth_oem_ctnr().
+ *
+ * Output Parameters:
+ *   response - ELE response, can be used for debugging.
+ *
+ * Returned Value:
+ *   OK on success, a negated errno value otherwise.
+ *
+ ****************************************************************************/
+
+int imxrt118x_ele_release_container(uint32_t *response);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_verify_image
+ *
+ * Description:
+ *   Verify the specified image, for the current container.
+ *
+ * Input Parameters:
+ *   img_id - The id of the image in the context of the current container.
+ *
+ * Output Parameters:
+ *   response - ELE response, can be used for debugging.
+ *
+ * Returned Value:
+ *   OK on success, a negated errno value otherwise.
+ *
+ ****************************************************************************/
+
+int imxrt118x_ele_verify_image(uint32_t img_id, uint32_t *response);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_start_rng
+ *
+ * Description:
+ *   Sends command to initialize the ELE RNG context.
+ *
+ * Returned Value:
+ *   OK on success, a negated errno value otherwise.
+ *
+ ****************************************************************************/
+
+int imxrt118x_ele_start_rng(void);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_get_trng_state
+ *
+ * Description:
+ *   Query the state of the True Random Number Generator.
+ *
+ * Returned Value:
+ *   Zero is returned if the Random Number Generator (RNG) is ready for
+ *   use. A negated errno value (-EBUSY) or another is returned on
+ *   failure.
+ *
+ ****************************************************************************/
+
+int imxrt118x_ele_get_trng_state(void);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_get_random
+ *
+ * Description:
+ *   Request from the ELE the generation of a random number of specified
+ *   length.
+ *
+ * Input Parameters:
+ *   paddr  -  32bit physical address to store the random number.
+ *   len    -  Length in bytes of the random number.
+ *
+ * Returned Value:
+ *   Zero is returned if ELE successfully generated the random number.
+ *   A negated errno value (-EBUSY) or another is returned on failure.
+ *
+ ****************************************************************************/
+
+int imxrt118x_ele_get_random(uint32_t paddr, size_t len);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_commit
+ *
+ * Description:
+ *   Sends commit command to the ELE.
+ *
+ * Input Parameters:
+ *   info - Information type to be committed
+ *
+ * Output Parameters:
+ *   response - ELE response, can be used for debugging.
+ *
+ * Returned Value:
+ *   OK on success, a negated errno value otherwise.
+ *
+ ****************************************************************************/
+
+int imxrt118x_ele_commit(uint32_t info, uint32_t *response);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_enable_apc
+ *
+ * Description:
+ *   Enable Access Permission Control for the M7.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   OK on success, a negated errno value otherwise.
+ *
+ ****************************************************************************/
+
+int imxrt118x_ele_enable_apc(void);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_voltage_change_start
+ *
+ * Description:
+ *   Begin an ELE-guarded VDD1P0 voltage change (VOLTAGE_CHANGE_START,
+ *   0x12).  When the digital glitch detector (GDET) is enabled, the DCDC
+ *   target must only be reprogrammed between this command and
+ *   imxrt118x_ele_voltage_change_finish(); otherwise the glitch detector
+ *   can trip on the transition and put the SoC into an unpredictable
+ *   (lockup/reset) state.  While the change is in progress the ELE accepts
+ *   no other command and aborts if FINISH is not issued within 50 ms.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   OK on success, a negated errno value otherwise.  ELE firmware that
+ *   does not implement the command simply rejects it, in which case the
+ *   caller may proceed with the (unguarded) voltage change.
+ *
+ ****************************************************************************/
+
+int imxrt118x_ele_voltage_change_start(void);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_voltage_change_finish
+ *
+ * Description:
+ *   Complete an ELE-guarded VDD1P0 voltage change (VOLTAGE_CHANGE_FINISH,
+ *   0x13), removing the GDET isolation started by
+ *   imxrt118x_ele_voltage_change_start().  Must be issued within 50 ms of
+ *   the START command.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   OK on success, a negated errno value otherwise.
+ *
+ ****************************************************************************/
+
+int imxrt118x_ele_voltage_change_finish(void);
+
+/****************************************************************************
+ * Name: imxrt118x_ele_check_fw_version
+ *
+ * Description:
+ *   Query the EdgeLock Enclave firmware version (GET_FW_VERSION) and log
+ *   it, so it can be verified that the intended ELE firmware is active.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   OK on success, a negated errno value otherwise.
+ *
+ ****************************************************************************/
+
+int imxrt118x_ele_check_fw_version(void);
+
+#endif /* __ARCH_ARM_SRC_IMXRT_IMXRT118X_ELE_H */

Reply via email to