This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 60abe4744fa arch/mips/jz4780: Add hardware Random Number Generator
(RNG) support
60abe4744fa is described below
commit 60abe4744fa8d5bf7b751dec0cc5647a301f8ab9
Author: Lwazi Dube <[email protected]>
AuthorDate: Fri Aug 7 01:37:08 2026 -0400
arch/mips/jz4780: Add hardware Random Number Generator (RNG) support
Add support for the hardware Random Number Generator (RNG) module found
on the Ingenic JZ4780 SoC.
Changes include:
- Update jz4780 chip.h with power management controllor base
address JZPMC_BASE and register offsets for the RNG registers.
- A new file jz4780_rng.c to provide character driver interfaces
for `/dev/random` and `/dev/urandom` utilizing the hardware
RNG block.
Signed-off-by: Lwazi Dube <[email protected]>
---
arch/mips/include/jz4780/chip.h | 28 +++--
arch/mips/src/jz4780/Kconfig | 6 +
arch/mips/src/jz4780/Make.defs | 4 +
arch/mips/src/jz4780/jz4780_rng.c | 233 ++++++++++++++++++++++++++++++++++++++
4 files changed, 260 insertions(+), 11 deletions(-)
diff --git a/arch/mips/include/jz4780/chip.h b/arch/mips/include/jz4780/chip.h
index ec1908fba6c..6a15381b786 100644
--- a/arch/mips/include/jz4780/chip.h
+++ b/arch/mips/include/jz4780/chip.h
@@ -33,10 +33,10 @@
* Pre-processor Definitions
****************************************************************************/
-#define CKPCR 0xB0003040
+#define CKPCR 0xb0003040
#define CKPCR_CK32CTL_RTCLK (3 << 1)
-#define JZINTC_BASE 0xB0001000
+#define JZINTC_BASE 0xb0001000
#define ICMSR0 (JZINTC_BASE + 0x08)
#define ICMCR0 (JZINTC_BASE + 0x0C)
@@ -45,7 +45,7 @@
#define ICMCR1 (JZINTC_BASE + 0x2C)
#define ICPR1 (JZINTC_BASE + 0x30)
-#define JZTMR_BASE 0xB0002000
+#define JZTMR_BASE 0xb0002000
#define WD_TDR (JZTMR_BASE + 0x00) // u16: Watchdog Timer Data
#define WD_TCER (JZTMR_BASE + 0x04) // u8 : Watchdog Counter Enable
@@ -87,37 +87,43 @@
#define TCSR(n) (JZTMR_BASE + 0x4C + (n)*0x10)
#define TDFR(n) (JZTMR_BASE + 0x40 + (n)*0x10)
-#define CLKGR0_REG 0xb0000020
+#define JZPMC_BASE 0xb0000000
+
+#define CLKGR0_REG (JZPMC_BASE + 0x20)
# define CLKGR0_OTG0 (1 << 2)
# define CLKGR0_UHC (1 << 24)
# define CLKGR0_LCD (1 << 28)
# define CLKGR0_TVE (1 << 27)
-#define OPCR_REG 0xb0000024
+#define OPCR_REG (JZPMC_BASE + 0x24)
# define OPCR_SPENDN1 (1 << 6)
-#define CLKGR1_REG 0xb0000028
+#define CLKGR1_REG (JZPMC_BASE + 0x28)
# define CLKGR1_HDMI (1 << 9)
-#define USBPCR_REG 0xb000003c
+#define USBPCR_REG (JZPMC_BASE + 0x3c)
# define USBPCR_POR (1 << 22)
-#define USBPCR1_REG 0xb0000048
+#define USBPCR1_REG (JZPMC_BASE + 0x48)
# define REFCLK_DIV_MSK 0xfcffffff /* clears bits 25:24 */
# define REFCLK_DIV_48MHZ 0x02000000 /* bits 25:24 */
# define WORD_IF_16BIT 0x000c0000 /* bits 19:18 */
-#define LP1CDR_REG 0xb0000054
+#define LP1CDR_REG (JZPMC_BASE + 0x54)
# define LPCDR_VAL 0x15
# define LPCS_VPLL 0X80000000
# define CE_LCD (1 << 28)
# define LCD_BUSY (1 << 27)
-#define HDMICDR_REG 0xb000008c
+#define HDMICDR_REG (JZPMC_BASE + 0x8c)
-#define SRBC_REG 0xb00000c4
+#define SRBC_REG (JZPMC_BASE + 0xc4)
# define SRBC_UHC_SR (1 << 14)
+#define ERNG_REG (JZPMC_BASE + 0xd8)
+# define ENABLE_RNG (1 << 0)
+#define RNG_REG (JZPMC_BASE + 0xdc)
+
#define TICKS_PER_MS (48000/16)
#define CHIP_JZ4780 1
diff --git a/arch/mips/src/jz4780/Kconfig b/arch/mips/src/jz4780/Kconfig
index a363c1f16cc..9d0616ad150 100644
--- a/arch/mips/src/jz4780/Kconfig
+++ b/arch/mips/src/jz4780/Kconfig
@@ -7,6 +7,12 @@ if ARCH_CHIP_JZ4780
comment "JZ4780 Configuration Options"
menu "JZ4780 Peripheral Support"
+
+config JZ4780_RNG
+ bool "Random Number Generator (RNG)"
+ default y
+ select ARCH_HAVE_RNG
+
config JZ4780_LCD
bool "LCD controller"
default n
diff --git a/arch/mips/src/jz4780/Make.defs b/arch/mips/src/jz4780/Make.defs
index 7b434dd545e..58b1f21f9e4 100644
--- a/arch/mips/src/jz4780/Make.defs
+++ b/arch/mips/src/jz4780/Make.defs
@@ -52,6 +52,10 @@ CHIP_CSRCS = jz4780_lowinit.c jz4780_exception.c
jz4780_decodeirq.c
CHIP_CSRCS += jz4780_irq.c jz4780_timerisr.c jz4780_gpio.c
CHIP_CSRCS += jz4780_cache.c
+ifeq ($(CONFIG_JZ4780_RNG),y)
+CHIP_CSRCS += jz4780_rng.c
+endif
+
ifeq ($(CONFIG_USBHOST),y)
CHIP_CSRCS += jz_usbhost.c
diff --git a/arch/mips/src/jz4780/jz4780_rng.c
b/arch/mips/src/jz4780/jz4780_rng.c
new file mode 100644
index 00000000000..e8e6a807660
--- /dev/null
+++ b/arch/mips/src/jz4780/jz4780_rng.c
@@ -0,0 +1,233 @@
+/****************************************************************************
+ * arch/mips/src/jz4780/jz4780_rng.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 <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/param.h>
+
+#include <nuttx/debug.h>
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/mutex.h>
+#include <nuttx/drivers/drivers.h>
+
+#include "mips_internal.h"
+
+#if defined(CONFIG_DEV_RANDOM) || defined(CONFIG_DEV_URANDOM_ARCH)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define ENTROPY_DELAY 10
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int jz_rng_initialize(void);
+static ssize_t jz_rng_read(struct file *filep, char *buffer, size_t);
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct rng_dev_s
+{
+ mutex_t rd_lock;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct rng_dev_s g_rngdev =
+{
+ .rd_lock = NXMUTEX_INITIALIZER,
+};
+
+static const struct file_operations g_rngops =
+{
+ NULL, /* open */
+ NULL, /* close */
+ jz_rng_read, /* read */
+};
+
+/****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: jz_rng_initialize
+ *
+ * Description:
+ * Enable the random number generator
+ *
+ * Returned Value:
+ * OK on success; negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int jz_rng_initialize(void)
+{
+ uint32_t retval;
+ struct rng_dev_s *priv = (struct rng_dev_s *)&g_rngdev;
+
+ if (nxmutex_lock(&priv->rd_lock) != OK)
+ {
+ return -EBUSY;
+ }
+
+ /* Enable RNG if it is disabled */
+
+ if ((getreg32(ERNG_REG) & ENABLE_RNG) == 0)
+ {
+ putreg32(ENABLE_RNG, ERNG_REG);
+ }
+
+ up_mdelay(1);
+
+ retval = (getreg32(ERNG_REG) & ENABLE_RNG) ? OK : -EIO;
+
+ if (retval != OK)
+ {
+ _err("Failed to initialize RNG\n");
+ }
+
+ nxmutex_unlock(&priv->rd_lock);
+ return retval;
+}
+
+/****************************************************************************
+ * Name: jz_rng_read
+ *
+ * Description:
+ * This is the standard, NuttX character driver read method
+ *
+ * Input Parameters:
+ * filep - The VFS file instance
+ * buffer - Buffer in which to return the random samples
+ * buflen - The length of the buffer
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+static ssize_t jz_rng_read(struct file *filep, char *buffer, size_t buflen)
+{
+ struct rng_dev_s *priv = (struct rng_dev_s *)&g_rngdev;
+ ssize_t bytes_left = buflen;
+ uint8_t *rd_buf = (uint8_t *)buffer;
+ uint32_t last_word;
+
+ if (nxmutex_lock(&priv->rd_lock) != OK)
+ {
+ return -EBUSY;
+ }
+
+ last_word = getreg32(RNG_REG);
+ while (bytes_left > 0)
+ {
+ up_mdelay(ENTROPY_DELAY);
+ uint32_t word = getreg32(RNG_REG);
+ if (word == last_word)
+ {
+ /* Try again if the same number is repeated */
+
+ continue;
+ }
+
+ last_word = word;
+
+ uint32_t count = MIN(sizeof(word), bytes_left);
+
+ memcpy(rd_buf, &word, count);
+ rd_buf += count;
+ bytes_left -= count;
+ }
+
+ nxmutex_unlock(&priv->rd_lock);
+ return buflen;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: devrandom_register
+ *
+ * Description:
+ * Initialize the RNG hardware and register the /dev/random driver.
+ * Must be called BEFORE devurandom_register.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEV_RANDOM
+void devrandom_register(void)
+{
+ if (jz_rng_initialize() == OK)
+ {
+ register_driver("/dev/random", &g_rngops, 0444, NULL);
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: devurandom_register
+ *
+ * Description:
+ * Register /dev/urandom
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEV_URANDOM_ARCH
+void devurandom_register(void)
+{
+ if (jz_rng_initialize() == OK)
+ {
+ register_driver("/dev/urandom", &g_rngops, 0444, NULL);
+ }
+}
+#endif
+
+#endif /* CONFIG_DEV_RANDOM || CONFIG_DEV_URANDOM_ARCH */