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 <lwazeh@gmail.com>
This commit is contained in:
Lwazi Dube 2026-08-07 01:37:08 -04:00 committed by Alan C. Assis
parent cda33ae4fc
commit 60abe4744f
4 changed files with 260 additions and 11 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 */