rng: nuvoton: Add NPCM7xx rng driver
Add Nuvoton BMC NPCM750 rng driver. Signed-off-by: Jim Liu <JJLIU0@nuvoton.com>
This commit is contained in:
parent
b5d3625f27
commit
866eab1d28
3 changed files with 164 additions and 0 deletions
|
@ -31,6 +31,13 @@ config RNG_MSM
|
||||||
This driver provides support for the Random Number
|
This driver provides support for the Random Number
|
||||||
Generator hardware found on Qualcomm SoCs.
|
Generator hardware found on Qualcomm SoCs.
|
||||||
|
|
||||||
|
config RNG_NPCM
|
||||||
|
bool "Nuvoton NPCM SoCs Random Number Generator support"
|
||||||
|
depends on DM_RNG
|
||||||
|
help
|
||||||
|
Enable random number generator on NPCM SoCs.
|
||||||
|
This unit can provide 750 to 1000 random bits per second
|
||||||
|
|
||||||
config RNG_OPTEE
|
config RNG_OPTEE
|
||||||
bool "OP-TEE based Random Number Generator support"
|
bool "OP-TEE based Random Number Generator support"
|
||||||
depends on DM_RNG && OPTEE
|
depends on DM_RNG && OPTEE
|
||||||
|
|
|
@ -7,6 +7,7 @@ obj-$(CONFIG_DM_RNG) += rng-uclass.o
|
||||||
obj-$(CONFIG_RNG_MESON) += meson-rng.o
|
obj-$(CONFIG_RNG_MESON) += meson-rng.o
|
||||||
obj-$(CONFIG_RNG_SANDBOX) += sandbox_rng.o
|
obj-$(CONFIG_RNG_SANDBOX) += sandbox_rng.o
|
||||||
obj-$(CONFIG_RNG_MSM) += msm_rng.o
|
obj-$(CONFIG_RNG_MSM) += msm_rng.o
|
||||||
|
obj-$(CONFIG_RNG_NPCM) += npcm_rng.o
|
||||||
obj-$(CONFIG_RNG_OPTEE) += optee_rng.o
|
obj-$(CONFIG_RNG_OPTEE) += optee_rng.o
|
||||||
obj-$(CONFIG_RNG_STM32MP1) += stm32mp1_rng.o
|
obj-$(CONFIG_RNG_STM32MP1) += stm32mp1_rng.o
|
||||||
obj-$(CONFIG_RNG_ROCKCHIP) += rockchip_rng.o
|
obj-$(CONFIG_RNG_ROCKCHIP) += rockchip_rng.o
|
||||||
|
|
156
drivers/rng/npcm_rng.c
Normal file
156
drivers/rng/npcm_rng.c
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 Nuvoton Technology Corp.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <rng.h>
|
||||||
|
#include <uboot_aes.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
#define RNGCS_RNGE BIT(0)
|
||||||
|
#define RNGCS_DVALID BIT(1)
|
||||||
|
#define RNGCS_CLKP(range) ((0x0f & (range)) << 2)
|
||||||
|
#define RNGMODE_M1ROSEL_VAL (0x02) /* Ring Oscillator Select for Method I */
|
||||||
|
|
||||||
|
enum {
|
||||||
|
RNG_CLKP_80_100_MHZ = 0x00, /*default */
|
||||||
|
RNG_CLKP_60_80_MHZ = 0x01,
|
||||||
|
RNG_CLKP_50_60_MHZ = 0x02,
|
||||||
|
RNG_CLKP_40_50_MHZ = 0x03,
|
||||||
|
RNG_CLKP_30_40_MHZ = 0x04,
|
||||||
|
RNG_CLKP_25_30_MHZ = 0x05,
|
||||||
|
RNG_CLKP_20_25_MHZ = 0x06,
|
||||||
|
RNG_CLKP_5_20_MHZ = 0x07,
|
||||||
|
RNG_CLKP_2_15_MHZ = 0x08,
|
||||||
|
RNG_CLKP_9_12_MHZ = 0x09,
|
||||||
|
RNG_CLKP_7_9_MHZ = 0x0A,
|
||||||
|
RNG_CLKP_6_7_MHZ = 0x0B,
|
||||||
|
RNG_CLKP_5_6_MHZ = 0x0C,
|
||||||
|
RNG_CLKP_4_5_MHZ = 0x0D,
|
||||||
|
RNG_CLKP_3_4_MHZ = 0x0E,
|
||||||
|
RNG_NUM_OF_CLKP
|
||||||
|
};
|
||||||
|
|
||||||
|
struct npcm_rng_regs {
|
||||||
|
unsigned int rngcs;
|
||||||
|
unsigned int rngd;
|
||||||
|
unsigned int rngmode;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct npcm_rng_priv {
|
||||||
|
struct npcm_rng_regs *regs;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct npcm_rng_priv *rng_priv;
|
||||||
|
|
||||||
|
void npcm_rng_init(void)
|
||||||
|
{
|
||||||
|
struct npcm_rng_regs *regs = rng_priv->regs;
|
||||||
|
int init;
|
||||||
|
|
||||||
|
/* check if rng enabled */
|
||||||
|
init = readb(®s->rngcs);
|
||||||
|
if ((init & RNGCS_RNGE) == 0) {
|
||||||
|
/* init rng */
|
||||||
|
writeb(RNGCS_CLKP(RNG_CLKP_20_25_MHZ) | RNGCS_RNGE, ®s->rngcs);
|
||||||
|
writeb(RNGMODE_M1ROSEL_VAL, ®s->rngmode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void npcm_rng_disable(void)
|
||||||
|
{
|
||||||
|
struct npcm_rng_regs *regs = rng_priv->regs;
|
||||||
|
|
||||||
|
/* disable rng */
|
||||||
|
writeb(0, ®s->rngcs);
|
||||||
|
writeb(0, ®s->rngmode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void srand(unsigned int seed)
|
||||||
|
{
|
||||||
|
/* no need to seed for now */
|
||||||
|
}
|
||||||
|
|
||||||
|
int npcm_rng_read(struct udevice *dev, void *data, size_t max)
|
||||||
|
{
|
||||||
|
struct npcm_rng_regs *regs = rng_priv->regs;
|
||||||
|
int i;
|
||||||
|
int ret_val = 0;
|
||||||
|
char *buf = data;
|
||||||
|
|
||||||
|
npcm_rng_init();
|
||||||
|
|
||||||
|
printf("NPCM HW RNG\n");
|
||||||
|
/* Wait for RNG done (max bytes) */
|
||||||
|
for (i = 0; i < max; i++) {
|
||||||
|
/* wait until DVALID is set */
|
||||||
|
while ((readb(®s->rngcs) & RNGCS_DVALID) == 0)
|
||||||
|
;
|
||||||
|
buf[i] = ((unsigned int)readb(®s->rngd) & 0x000000FF);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int rand_r(unsigned int *seedp)
|
||||||
|
{
|
||||||
|
struct npcm_rng_regs *regs = rng_priv->regs;
|
||||||
|
int i;
|
||||||
|
unsigned int ret_val = 0;
|
||||||
|
|
||||||
|
npcm_rng_init();
|
||||||
|
|
||||||
|
/* Wait for RNG done (4 bytes) */
|
||||||
|
for (i = 0; i < 4 ; i++) {
|
||||||
|
/* wait until DVALID is set */
|
||||||
|
while ((readb(®s->rngcs) & RNGCS_DVALID) == 0)
|
||||||
|
;
|
||||||
|
ret_val |= (((unsigned int)readb(®s->rngd) & 0x000000FF) << (i * 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int rand(void)
|
||||||
|
{
|
||||||
|
return rand_r(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int npcm_rng_bind(struct udevice *dev)
|
||||||
|
{
|
||||||
|
rng_priv = calloc(1, sizeof(struct npcm_rng_priv));
|
||||||
|
if (!rng_priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
rng_priv->regs = dev_remap_addr_index(dev, 0);
|
||||||
|
if (!rng_priv->regs) {
|
||||||
|
printf("Cannot find rng reg address, binding failed\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("RNG: NPCM RNG module bind OK\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct udevice_id npcm_rng_ids[] = {
|
||||||
|
{ .compatible = "nuvoton,npcm845-rng" },
|
||||||
|
{ .compatible = "nuvoton,npcm750-rng" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct dm_rng_ops npcm_rng_ops = {
|
||||||
|
.read = npcm_rng_read,
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(npcm_rng) = {
|
||||||
|
.name = "npcm_rng",
|
||||||
|
.id = UCLASS_RNG,
|
||||||
|
.ops = &npcm_rng_ops,
|
||||||
|
.of_match = npcm_rng_ids,
|
||||||
|
.priv_auto = sizeof(struct npcm_rng_priv),
|
||||||
|
.bind = npcm_rng_bind,
|
||||||
|
};
|
Loading…
Reference in a new issue