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 e5d895912827be50517e13cb333e9ef423e3372f
Author: Felipe Moura <[email protected]>
AuthorDate: Sun Jun 7 23:23:43 2026 -0300

    drivers/crypto: add Microchip RNG90 driver
    
    Add Microchip RNG90 TRNG driver with board integration for esp32c3 and 
rng90 defconfig support.
    
    Signed-off-by: Felipe Moura <[email protected]>
---
 .../esp32c3/common/include/esp_board_rng90.h       |  74 ++++
 boards/risc-v/esp32c3/common/src/CMakeLists.txt    |   4 +
 boards/risc-v/esp32c3/common/src/Make.defs         |   4 +
 boards/risc-v/esp32c3/common/src/esp_board_rng90.c |  95 ++++++
 .../esp32c3/esp32c3-devkit/configs/rng90/defconfig |  51 +++
 .../esp32c3/esp32c3-devkit/src/esp32c3_bringup.c   |  13 +
 drivers/crypto/CMakeLists.txt                      |   4 +
 drivers/crypto/Kconfig                             |  10 +
 drivers/crypto/Make.defs                           |   4 +
 drivers/crypto/rng90.c                             | 372 +++++++++++++++++++++
 include/nuttx/crypto/rng90.h                       |  66 ++++
 11 files changed, 697 insertions(+)

diff --git a/boards/risc-v/esp32c3/common/include/esp_board_rng90.h 
b/boards/risc-v/esp32c3/common/include/esp_board_rng90.h
new file mode 100644
index 00000000000..f316efe866b
--- /dev/null
+++ b/boards/risc-v/esp32c3/common/include/esp_board_rng90.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+ * boards/risc-v/esp32c3/common/include/esp_board_rng90.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 __BOARDS_RISCV_ESP32C3_COMMON_INCLUDE_ESP_BOARD_RNG90_H
+#define __BOARDS_RISCV_ESP32C3_COMMON_INCLUDE_ESP_BOARD_RNG90_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_rng90_initialize
+ *
+ * Description:
+ *   Initialize and register the RNG90 True Random Number Generator driver.
+ *
+ * Input Parameters:
+ *   devno - The device number, used to build the device path as /dev/rngN
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value on failure.
+ ****************************************************************************/
+
+#ifdef CONFIG_DEV_RNG90
+int board_rng90_initialize(int devno);
+#endif /* CONFIG_DEV_RNG90 */
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __BOARDS_RISCV_ESP32C3_COMMON_INCLUDE_ESP_BOARD_RNG90_H */
\ No newline at end of file
diff --git a/boards/risc-v/esp32c3/common/src/CMakeLists.txt 
b/boards/risc-v/esp32c3/common/src/CMakeLists.txt
index d8b1323adb3..23feed738c0 100644
--- a/boards/risc-v/esp32c3/common/src/CMakeLists.txt
+++ b/boards/risc-v/esp32c3/common/src/CMakeLists.txt
@@ -76,6 +76,10 @@ if(CONFIG_ARCH_BOARD_COMMON)
     list(APPEND SRCS esp_board_bmp280.c)
   endif()
 
+  if(CONFIG_DEV_RNG90)
+    list(APPEND SRCS esp_board_rng90.c)
+  endif()
+
   if(CONFIG_MMCSD_SPI)
     list(APPEND SRCS esp_board_mmcsd.c)
   endif()
diff --git a/boards/risc-v/esp32c3/common/src/Make.defs 
b/boards/risc-v/esp32c3/common/src/Make.defs
index 03d09271575..4f7a968440b 100644
--- a/boards/risc-v/esp32c3/common/src/Make.defs
+++ b/boards/risc-v/esp32c3/common/src/Make.defs
@@ -74,6 +74,10 @@ ifeq ($(CONFIG_SENSORS_BMP280),y)
   CSRCS += esp_board_bmp280.c
 endif
 
+ifeq ($(CONFIG_DEV_RNG90),y)
+  CSRCS += esp_board_rng90.c
+endif
+
 ifeq ($(CONFIG_MMCSD_SPI),y)
   CSRCS += esp_board_mmcsd.c
 endif
diff --git a/boards/risc-v/esp32c3/common/src/esp_board_rng90.c 
b/boards/risc-v/esp32c3/common/src/esp_board_rng90.c
new file mode 100644
index 00000000000..3d14b53806a
--- /dev/null
+++ b/boards/risc-v/esp32c3/common/src/esp_board_rng90.c
@@ -0,0 +1,95 @@
+/****************************************************************************
+ * boards/risc-v/esp32c3/common/src/esp_board_rng90.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 <stdio.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/crypto/rng90.h>
+#include <nuttx/debug.h>
+#include <nuttx/i2c/i2c_master.h>
+
+#ifndef CONFIG_ESPRESSIF_I2C_BITBANG
+#  include "espressif/esp_i2c.h"
+#else
+#  include "espressif/esp_i2c_bitbang.h"
+#endif
+
+#include "esp_board_rng90.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: board_rng90_initialize
+ *
+ * Description:
+ *   Initialize and register the RNG90 True Random Number Generator driver.
+ *
+ * Input Parameters:
+ *   devno - The device number, used to build the device path as /dev/rngN
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value on failure.
+ ****************************************************************************/
+
+int board_rng90_initialize(int devno)
+{
+  struct i2c_master_s *i2c;
+  char devpath[16];
+  int ret;
+
+  sninfo("Initializing RNG90\n");
+
+  /* Initialize I2C */
+
+#ifndef CONFIG_ESPRESSIF_I2C_BITBANG
+  i2c = esp_i2cbus_initialize(ESPRESSIF_I2C0);
+#else
+  i2c = esp_i2cbus_bitbang_initialize();
+#endif
+
+  if (i2c == NULL)
+    {
+      snerr("ERROR: Failed to initialize I2C for RNG90\n");
+      return -ENODEV;
+    }
+
+  /* Register the RNG90 driver at "/dev/rngN" */
+
+  snprintf(devpath, sizeof(devpath), "/dev/rng%d", devno);
+  ret = rng90_register(devpath, i2c, RNG90_I2C_ADDR);
+  if (ret < 0)
+    {
+      snerr("ERROR: Failed to register RNG90 driver: %d\n", ret);
+      return ret;
+    }
+
+  return OK;
+}
+
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/configs/rng90/defconfig 
b/boards/risc-v/esp32c3/esp32c3-devkit/configs/rng90/defconfig
new file mode 100644
index 00000000000..170cbd0ecb1
--- /dev/null
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/configs/rng90/defconfig
@@ -0,0 +1,51 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed 
.config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that 
includes your
+# modifications.
+#
+# CONFIG_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+CONFIG_ARCH="risc-v"
+CONFIG_ARCH_BOARD="esp32c3-devkit"
+CONFIG_ARCH_BOARD_COMMON=y
+CONFIG_ARCH_BOARD_ESP32C3_DEVKIT=y
+CONFIG_ARCH_CHIP="esp32c3"
+CONFIG_ARCH_CHIP_ESP32C3=y
+CONFIG_ARCH_INTERRUPTSTACK=1536
+CONFIG_ARCH_IRQ_TO_NDX=y
+CONFIG_ARCH_MINIMAL_VECTORTABLE_DYNAMIC=y
+CONFIG_ARCH_NUSER_INTERRUPTS=17
+CONFIG_ARCH_RISCV=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BOARDCTL_RESET=y
+CONFIG_BOARD_LOOPSPERMSEC=15000
+CONFIG_BUILTIN=y
+CONFIG_CRYPTO=y
+CONFIG_DEV_RNG90=y
+CONFIG_ESPRESSIF_I2C0=y
+CONFIG_EXAMPLES_RNG90=y
+CONFIG_FS_PROCFS=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INTELHEX_BINARY=y
+CONFIG_LIBC_PERROR_STDOUT=y
+CONFIG_LIBC_STRERROR=y
+CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_READLINE=y
+CONFIG_NSH_STRERROR=y
+CONFIG_PREALLOC_TIMERS=0
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_BACKTRACE=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_START_DAY=29
+CONFIG_START_MONTH=11
+CONFIG_START_YEAR=2019
+CONFIG_SYSTEM_DUMPSTACK=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_TESTING_GETPRIME=y
+CONFIG_TESTING_OSTEST=y
+CONFIG_UART0_SERIAL_CONSOLE=y
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c 
b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c
index 942d6a1def0..36023aa21c2 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c
@@ -41,6 +41,10 @@
 #include "esp_board_i2c.h"
 #include "esp_board_bmp180.h"
 
+#ifdef CONFIG_DEV_RNG90
+#  include "esp_board_rng90.h"
+#endif
+
 #include "espressif/esp_start.h"
 
 #ifdef CONFIG_ESPRESSIF_ADC
@@ -404,6 +408,15 @@ int esp_bringup(void)
     }
 #endif
 
+#ifdef CONFIG_DEV_RNG90
+  ret = board_rng90_initialize(0);
+
+  if (ret < 0)
+    {
+      syslog(LOG_ERR, "Failed to initialize RNG90 driver: %d\n", ret);
+    }
+#endif
+
 #ifdef CONFIG_ESP_SDM
   struct esp_sdm_chan_config_s config =
   {
diff --git a/drivers/crypto/CMakeLists.txt b/drivers/crypto/CMakeLists.txt
index f310ae115e5..3c93183635e 100644
--- a/drivers/crypto/CMakeLists.txt
+++ b/drivers/crypto/CMakeLists.txt
@@ -23,3 +23,7 @@
 if(CONFIG_DEV_URANDOM AND NOT CONFIG_DEV_URANDOM_ARCH)
   target_sources(drivers PRIVATE dev_urandom.c)
 endif()
+
+if(CONFIG_DEV_RNG90)
+  target_sources(drivers PRIVATE rng90.c)
+endif()
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 00b4d3f9155..e53927894a0 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -137,3 +137,13 @@ config SE05X_LOG_DEBUG
 endchoice # SE05x debug log level
 
 endif #DEV_SE05X
+
+config DEV_RNG90
+       bool "Enable Microchip RNG90 TRNG"
+       depends on I2C
+       depends on CRYPTO
+       default n
+       ---help---
+               Enable support for /dev/rng90 random number generator provided 
by
+               Microchip RNG90 TRNG.
+
diff --git a/drivers/crypto/Make.defs b/drivers/crypto/Make.defs
index 240ba5ceab8..e243bd916fa 100644
--- a/drivers/crypto/Make.defs
+++ b/drivers/crypto/Make.defs
@@ -31,6 +31,10 @@ ifeq ($(CONFIG_DEV_SE05X),y)
   include crypto/pnt/Make.defs
 endif
 
+ifeq ($(CONFIG_DEV_RNG90),y)
+  CSRCS += rng90.c
+endif
+
 # Include crypto device driver build support
 
 DEPPATH += --dep-path crypto
diff --git a/drivers/crypto/rng90.c b/drivers/crypto/rng90.c
new file mode 100644
index 00000000000..3c7b065fe69
--- /dev/null
+++ b/drivers/crypto/rng90.c
@@ -0,0 +1,372 @@
+/****************************************************************************
+ * drivers/crypto/rng90.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 <errno.h>
+#include <string.h>
+#include <sys/param.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/debug.h>
+#include <nuttx/mutex.h>
+#include <nuttx/crypto/rng90.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/i2c/i2c_master.h>
+#include <nuttx/kmalloc.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define RNG90_WAKE_I2C_ADDR       0x00
+#define RNG90_WAKE_I2C_MAXFREQ    100000
+#define RNG90_WAKE_RETRIES        3
+#define RNG90_WAKE_DELAY_MS       5
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct rng90_dev_s
+{
+  FAR struct i2c_master_s *i2c;
+  uint8_t addr;
+  mutex_t lock;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static bool rng90_wakeup(FAR struct rng90_dev_s *priv);
+static bool rng90_sleep(FAR struct rng90_dev_s *priv);
+static void rng90_send_wake_token(FAR struct rng90_dev_s *priv);
+static void rng90_i2c_config(FAR struct i2c_config_s *config,
+                             uint32_t frequency, uint8_t address);
+static bool rng90_genrnd(FAR struct rng90_dev_s *priv, FAR uint8_t *buffer,
+                          size_t buflen);
+
+/* Character driver methods */
+
+static int rng90_open(FAR struct file *filep);
+static int rng90_close(FAR struct file *filep);
+static ssize_t rng90_read(FAR struct file *filep, FAR char *buffer,
+                          size_t buflen);
+static int rng90_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_rng90_fops =
+{
+  rng90_open, rng90_close, rng90_read, NULL,
+  NULL,       rng90_ioctl, NULL
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int rng90_open(FAR struct file *filep)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct rng90_dev_s *priv = inode->i_private;
+
+  /* The close path puts the device into explicit sleep, so wake it here. */
+
+  nxmutex_lock(&priv->lock);
+  if (!rng90_wakeup(priv))
+    {
+      crypterr("ERROR: Failed to wake rng90 device\n");
+    }
+
+  nxmutex_unlock(&priv->lock);
+
+  return OK;
+}
+
+static int rng90_close(FAR struct file *filep)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct rng90_dev_s *priv = inode->i_private;
+
+  nxmutex_lock(&priv->lock);
+  if (!rng90_sleep(priv))
+    {
+      crypterr("ERROR: Failed to put rng90 device to sleep\n");
+    }
+
+  nxmutex_unlock(&priv->lock);
+  return OK;
+}
+
+static ssize_t rng90_read(FAR struct file *filep, FAR char *buffer,
+                          size_t buflen)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct rng90_dev_s *priv = inode->i_private;
+  bool ret;
+
+  nxmutex_lock(&priv->lock);
+  ret = rng90_genrnd(priv, (FAR uint8_t *)buffer, buflen);
+  nxmutex_unlock(&priv->lock);
+
+  /* rng90 always returns 32 bytes */
+
+  return ret ? (ssize_t)MIN(buflen, 32u) : -EIO;
+}
+
+static int rng90_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct rng90_dev_s *priv = inode->i_private;
+  int ret;
+
+  ret = nxmutex_lock(&priv->lock);
+  if (ret != 0)
+    {
+      return ret;
+    }
+
+  switch (cmd)
+    {
+      case RNG90_IOC_WAKEUP:
+        ret = rng90_wakeup(priv) ? OK : ERROR;
+        break;
+
+      case RNG90_IOC_SLEEP:
+        ret = rng90_sleep(priv) ? OK : ERROR;
+        break;
+
+      case RNG90_IOC_GENRND:
+        ret = rng90_genrnd(priv, (FAR uint8_t *)arg, 32) ? OK : ERROR;
+        break;
+
+      default:
+        crypterr("ERROR: Unrecognized cmd: %d\n", cmd);
+        ret = -ENOTTY;
+        break;
+    }
+
+  nxmutex_unlock(&priv->lock);
+  return ret;
+}
+
+static void rng90_i2c_config(FAR struct i2c_config_s *config,
+                             uint32_t frequency, uint8_t address)
+{
+  config->frequency = frequency;
+  config->address   = address;
+  config->addrlen   = 7;
+}
+
+static bool rng90_is_wake_response(FAR const uint8_t *response)
+{
+  return response[0] == 0x04 && response[1] == 0x11 &&
+         response[2] == 0x33 && response[3] == 0x43;
+}
+
+static void rng90_send_wake_token(FAR struct rng90_dev_s *priv)
+{
+  struct i2c_config_s config;
+  uint8_t wake_token = 0x01;
+  uint32_t wake_freq;
+
+  /* Wake is an SDA-low pulse, not a normal transaction with an ACK. */
+
+  wake_freq = MIN(RNG90_I2C_FREQ, RNG90_WAKE_I2C_MAXFREQ);
+  rng90_i2c_config(&config, wake_freq, RNG90_WAKE_I2C_ADDR);
+  i2c_write(priv->i2c, &config, &wake_token, 1);
+  up_mdelay(RNG90_WAKE_DELAY_MS);
+}
+
+static bool rng90_wakeup(FAR struct rng90_dev_s *priv)
+{
+  struct i2c_config_s config;
+  uint8_t response[4];
+  int attempt;
+  int ret;
+
+  for (attempt = 0; attempt < RNG90_WAKE_RETRIES; attempt++)
+    {
+      rng90_send_wake_token(priv);
+
+      rng90_i2c_config(&config, RNG90_I2C_FREQ, priv->addr);
+      ret = i2c_read(priv->i2c, &config, response, sizeof(response));
+      if (ret >= 0 && rng90_is_wake_response(response))
+        {
+          return true;
+        }
+    }
+
+  return false;
+}
+
+static bool rng90_sleep(FAR struct rng90_dev_s *priv)
+{
+  struct i2c_config_s config;
+  uint8_t word_address = 0x01;
+  int ret;
+
+  rng90_i2c_config(&config, RNG90_I2C_FREQ, priv->addr);
+
+  /* Sleep sequence: device address + word address 0x01 + Stop condition */
+
+  ret = i2c_write(priv->i2c, &config, &word_address, 1);
+  return (ret >= 0);
+}
+
+static uint16_t rng90_crc16(FAR const uint8_t *data, size_t len)
+{
+  uint16_t crc = 0x0000;
+  size_t i;
+
+  for (i = 0; i < len; i++)
+    {
+      uint8_t byte = data[i];
+      uint8_t shift;
+
+      for (shift = 0x01; shift != 0; shift <<= 1)
+        {
+          bool dbit = (byte & shift) != 0;
+          bool cbit = (crc & 0x8000) != 0;
+
+          crc <<= 1;
+          if (dbit != cbit)
+            {
+              crc ^= 0x8005;
+            }
+        }
+    }
+
+  return crc;
+}
+
+static bool rng90_genrnd(FAR struct rng90_dev_s *priv, FAR uint8_t *buffer,
+                          size_t buflen)
+{
+  struct i2c_config_s config;
+  uint8_t response[35];
+  int ret;
+  int attempt;
+
+  /* Random command packet (datasheet section 6.2) */
+
+  uint8_t pkt[28];
+  uint16_t crc;
+
+  pkt[0]  = 0x03;   /* word address: command */
+  pkt[1]  = 27;     /* count */
+  pkt[2]  = 0x16;   /* opcode: Random */
+  pkt[3]  = 0x00;   /* param1 */
+  pkt[4]  = 0x00;   /* param2 lo */
+  pkt[5]  = 0x00;   /* param2 hi */
+
+  /* data: 20 bytes, any value */
+
+  memset(&pkt[6], 0x00, 20);
+
+  /* CRC over count + packet (pkt[1] through pkt[25]) */
+
+  crc     = rng90_crc16(&pkt[1], 25);
+  pkt[26] = (uint8_t)(crc & 0xff);  /* CRC lo */
+  pkt[27] = (uint8_t)(crc >> 8);    /* CRC hi */
+
+  rng90_i2c_config(&config, RNG90_I2C_FREQ, priv->addr);
+
+  for (attempt = 0; attempt < 2; attempt++)
+    {
+      if (attempt > 0)
+        {
+          rng90_wakeup(priv);
+        }
+
+      ret = i2c_write(priv->i2c, &config, pkt, sizeof(pkt));
+      if (ret < 0)
+        {
+          continue;
+        }
+
+      /* Wait for command execution (datasheet section 5.6.2) */
+
+      up_mdelay(72);
+
+      /* Response: [count=35][32 random bytes][crc_lo][crc_hi] */
+
+      ret = i2c_read(priv->i2c, &config, response, sizeof(response));
+      if (ret >= 0)
+        {
+          memcpy(buffer, &response[1], MIN(buflen, 32u));
+          return true;
+        }
+    }
+
+  return false;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int rng90_register(FAR const char *devpath, FAR struct i2c_master_s *i2c,
+                   uint8_t addr)
+{
+  int ret;
+  FAR struct rng90_dev_s *priv;
+
+  /* Sanity check */
+
+  DEBUGASSERT(devpath != NULL);
+  DEBUGASSERT(i2c != NULL);
+
+  /* Initialize the device's structure */
+
+  priv = (FAR struct rng90_dev_s *)kmm_malloc(sizeof(*priv));
+  if (priv == NULL)
+    {
+      crypterr("ERROR: Failed to allocate instance\n");
+      return -ENOMEM;
+    }
+
+  priv->i2c = i2c;
+  priv->addr = addr;
+  nxmutex_init(&priv->lock);
+
+  /* Register the character driver */
+
+  ret = register_driver(devpath, &g_rng90_fops, 0666, priv);
+  if (ret < 0)
+    {
+      crypterr("ERROR: Failed to register driver: %d\n", ret);
+      nxmutex_destroy(&priv->lock);
+      kmm_free(priv);
+      return ret;
+    }
+
+  return OK;
+}
diff --git a/include/nuttx/crypto/rng90.h b/include/nuttx/crypto/rng90.h
new file mode 100644
index 00000000000..a83afd1db7b
--- /dev/null
+++ b/include/nuttx/crypto/rng90.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+ * include/nuttx/crypto/rng90.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 __INCLUDE_NUTTX_CRYPTO_RNG90_H
+#define __INCLUDE_NUTTX_CRYPTO_RNG90_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/fs/ioctl.h>
+
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#if defined(CONFIG_I2C) && defined(CONFIG_DEV_RNG90)
+
+#define RNG90_I2C_ADDR 0x40
+#define RNG90_I2C_FREQ 400000
+
+#define _RNG90IOCBASE   (0x3b00) /* RNG90 ioctl base */
+#define _RNG90IOC(nr)   _IOC(_RNG90IOCBASE, nr)
+
+#define RNG90_IOC_WAKEUP   _RNG90IOC(0x01)
+#define RNG90_IOC_SLEEP    _RNG90IOC(0x02)
+#define RNG90_IOC_GENRND   _RNG90IOC(0x03)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct i2c_master_s;
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+int rng90_register(FAR const char *devpath,
+                   FAR struct i2c_master_s *i2c,
+                   uint8_t addr);
+
+#endif /* CONFIG_I2C && CONFIG_DEV_RNG90 */
+#endif /* __INCLUDE_NUTTX_CRYPTO_RNG90_H */

Reply via email to