> -----Original Message----- > From: Jaehoon Chung <jh80.ch...@samsung.com> > Sent: Wednesday, November 1, 2023 9:52 AM > To: 'Chanho Park' <chanho61.p...@samsung.com>; 'Sughosh Ganu' > <sughosh.g...@linaro.org>; 'Heinrich Schuchardt' <xypron.g...@gmx.de>; > 'Rick Chen' <r...@andestech.com>; 'Leo' <ycli...@andestech.com>; u- > b...@lists.denx.de > Subject: RE: [PATCH v2 3/5] rng: Add StarFive JH7110 RNG driver > > > > > -----Original Message----- > > From: U-Boot <u-boot-boun...@lists.denx.de> On Behalf Of Chanho Park > > Sent: Wednesday, November 1, 2023 8:55 AM > > To: Sughosh Ganu <sughosh.g...@linaro.org>; Heinrich Schuchardt > <xypron.g...@gmx.de>; Rick Chen > > <r...@andestech.com>; Leo <ycli...@andestech.com>; u-boot@lists.denx.de > > Cc: Chanho Park <chanho61.p...@samsung.com> > > Subject: [PATCH v2 3/5] rng: Add StarFive JH7110 RNG driver > > > > Adds to support JH7110 TRNG driver which is based on linux kernel's > > jh7110-trng.c. This can support to generate 256-bit random numbers and > > 128-bit but this makes 256-bit default for convenience. > > > > Signed-off-by: Chanho Park <chanho61.p...@samsung.com> > > --- > > drivers/rng/Kconfig | 6 + > > drivers/rng/Makefile | 1 + > > drivers/rng/jh7110_rng.c | 258 +++++++++++++++++++++++++++++++++++++++ > > 3 files changed, 265 insertions(+) > > create mode 100644 drivers/rng/jh7110_rng.c > > > > diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig > > index 994cc35b2744..0dba1e06b429 100644 > > --- a/drivers/rng/Kconfig > > +++ b/drivers/rng/Kconfig > > @@ -91,4 +91,10 @@ config TPM_RNG > > functionality. Enable random number generator on TPM > > devices. > > > > +config RNG_JH7110 > > + bool "StarFive JH7110 Random Number Generator support" > > + depends on DM_RNG && STARFIVE_JH7110 > > + help > > + Enable True Random Number Generator in StarFive JH7110 SoCs. > > + > > endif > > diff --git a/drivers/rng/Makefile b/drivers/rng/Makefile > > index 47b323e61ee3..9de762c8a1c3 100644 > > --- a/drivers/rng/Makefile > > +++ b/drivers/rng/Makefile > > @@ -15,3 +15,4 @@ obj-$(CONFIG_RNG_IPROC200) += iproc_rng200.o > > obj-$(CONFIG_RNG_SMCCC_TRNG) += smccc_trng.o > > obj-$(CONFIG_RNG_ARM_RNDR) += arm_rndr.o > > obj-$(CONFIG_TPM_RNG) += tpm_rng.o > > +obj-$(CONFIG_RNG_JH7110) += jh7110_rng.o > > diff --git a/drivers/rng/jh7110_rng.c b/drivers/rng/jh7110_rng.c > > new file mode 100644 > > index 000000000000..37ea8cc39945 > > --- /dev/null > > +++ b/drivers/rng/jh7110_rng.c > > @@ -0,0 +1,258 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +/* > > + * TRNG driver for the StarFive JH7110 SoC > > + * > > + */ > > + > > +#include <clk.h> > > +#include <dm.h> > > +#include <reset.h> > > +#include <rng.h> > > +#include <asm/io.h> > > +#include <linux/iopoll.h> > > + > > +/* trng register offset */ > > +#define STARFIVE_CTRL 0x00 > > +#define STARFIVE_STAT 0x04 > > +#define STARFIVE_MODE 0x08 > > +#define STARFIVE_SMODE 0x0C > > +#define STARFIVE_IE 0x10 > > +#define STARFIVE_ISTAT 0x14 > > +#define STARFIVE_RAND0 0x20 > > +#define STARFIVE_RAND1 0x24 > > +#define STARFIVE_RAND2 0x28 > > +#define STARFIVE_RAND3 0x2C > > +#define STARFIVE_RAND4 0x30 > > +#define STARFIVE_RAND5 0x34 > > +#define STARFIVE_RAND6 0x38 > > +#define STARFIVE_RAND7 0x3C > > +#define STARFIVE_AUTO_RQSTS 0x60 > > +#define STARFIVE_AUTO_AGE 0x64 > > + > > +/* CTRL CMD */ > > +#define STARFIVE_CTRL_EXEC_NOP 0x0 > > +#define STARFIVE_CTRL_GENE_RANDNUM 0x1 > > +#define STARFIVE_CTRL_EXEC_RANDRESEED 0x2 > > + > > +/* STAT */ > > +#define STARFIVE_STAT_NONCE_MODE BIT(2) > > +#define STARFIVE_STAT_R256 BIT(3) > > +#define STARFIVE_STAT_MISSION_MODE BIT(8) > > +#define STARFIVE_STAT_SEEDED BIT(9) > > +#define STARFIVE_STAT_LAST_RESEED(x) ((x) << 16) > > +#define STARFIVE_STAT_SRVC_RQST BIT(27) > > +#define STARFIVE_STAT_RAND_GENERATING BIT(30) > > +#define STARFIVE_STAT_RAND_SEEDING BIT(31) > > +#define STARFIVE_STAT_RUNNING (STARFIVE_STAT_RAND_GENERATING > > | \ > > + STARFIVE_STAT_RAND_SEEDING) > > + > > +/* MODE */ > > +#define STARFIVE_MODE_R256 BIT(3) > > + > > +/* SMODE */ > > +#define STARFIVE_SMODE_NONCE_MODE BIT(2) > > +#define STARFIVE_SMODE_MISSION_MODE BIT(8) > > +#define STARFIVE_SMODE_MAX_REJECTS(x) ((x) << 16) > > + > > +/* IE */ > > +#define STARFIVE_IE_RAND_RDY_EN BIT(0) > > +#define STARFIVE_IE_SEED_DONE_EN BIT(1) > > +#define STARFIVE_IE_LFSR_LOCKUP_EN BIT(4) > > +#define STARFIVE_IE_GLBL_EN BIT(31) > > + > > +#define STARFIVE_IE_ALL (STARFIVE_IE_GLBL_EN | \ > > + STARFIVE_IE_RAND_RDY_EN | \ > > + STARFIVE_IE_SEED_DONE_EN | \ > > + STARFIVE_IE_LFSR_LOCKUP_EN) > > + > > +/* ISTAT */ > > +#define STARFIVE_ISTAT_RAND_RDY BIT(0) > > +#define STARFIVE_ISTAT_SEED_DONE BIT(1) > > +#define STARFIVE_ISTAT_LFSR_LOCKUP BIT(4) > > + > > +#define STARFIVE_RAND_LEN sizeof(u32) > > + > > +enum mode { > > + PRNG_128BIT, > > + PRNG_256BIT, > > +}; > > + > > +struct starfive_trng_plat { > > + void *base; > > + struct clk *hclk; > > + struct clk *ahb; > > + struct reset_ctl *rst; > > + u32 mode; > > +}; > > + > > +static inline int starfive_trng_wait_idle(struct starfive_trng_plat > *trng) > > +{ > > + u32 stat; > > + > > + return readl_relaxed_poll_timeout(trng->base + STARFIVE_STAT, stat, > > + !(stat & STARFIVE_STAT_RUNNING), > > + 100000); > > +} > > + > > +static inline void starfive_trng_irq_mask_clear(struct > starfive_trng_plat *trng) > > +{ > > + /* clear register: ISTAT */ > > + u32 data = readl(trng->base + STARFIVE_ISTAT); > > + > > + writel(data, trng->base + STARFIVE_ISTAT); > > +} > > + > > +static int starfive_trng_cmd(struct starfive_trng_plat *trng, u32 cmd) > > +{ > > + u32 stat, flg; > > + int ret; > > + > > + switch (cmd) { > > + case STARFIVE_CTRL_GENE_RANDNUM: > > + writel(cmd, trng->base + STARFIVE_CTRL); > > + flg = STARFIVE_ISTAT_RAND_RDY; > > + break; > > + case STARFIVE_CTRL_EXEC_RANDRESEED: > > + writel(cmd, trng->base + STARFIVE_CTRL); > > + flg = STARFIVE_ISTAT_SEED_DONE; > > + break; > > + default: > > + return -EINVAL; > > + } > > + > > + ret = readl_relaxed_poll_timeout(trng->base + STARFIVE_ISTAT, stat, > > + (stat & flg), 1000); > > + writel(flg, trng->base + STARFIVE_ISTAT); > > + > > + return ret; > > +} > > + > > +static int starfive_trng_read(struct udevice *dev, void *data, size_t > len) > > +{ > > + struct starfive_trng_plat *trng = dev_get_plat(dev); > > + u8 *buffer = data; > > + int iter_mask; > > + > > + if (trng->mode == PRNG_256BIT) > > + iter_mask = 7; > > + else > > + iter_mask = 3; > > + > > + for (int i = 0; len; ++i, i &= iter_mask) { > > + u32 val; > > + size_t step; > > + int ret; > > + > > + ret = starfive_trng_cmd(trng, STARFIVE_CTRL_GENE_RANDNUM); > > + if (ret) > > + return ret; > > + > > + val = readl(trng->base + STARFIVE_RAND0 + > > + (i * STARFIVE_RAND_LEN)); > > + step = min_t(size_t, len, STARFIVE_RAND_LEN); > > + memcpy(buffer, &val, step); > > + buffer += step; > > + len -= step; > > + } > > + > > + return 0; > > +} > > + > > +static int starfive_trng_init(struct starfive_trng_plat *trng) > > +{ > > + u32 mode, intr = 0; > > + > > + /* setup Auto Request/Age register */ > > + writel(0, trng->base + STARFIVE_AUTO_AGE); > > + writel(0, trng->base + STARFIVE_AUTO_RQSTS); > > + > > + /* clear register: ISTAT */ > > + starfive_trng_irq_mask_clear(trng); > > + > > + intr |= STARFIVE_IE_ALL; > > + writel(intr, trng->base + STARFIVE_IE); > > + > > + mode = readl(trng->base + STARFIVE_MODE); > > + > > + switch (trng->mode) { > > + case PRNG_128BIT: > > + mode &= ~STARFIVE_MODE_R256; > > + break; > > + case PRNG_256BIT: > > + mode |= STARFIVE_MODE_R256; > > + break; > > + default: > > + mode |= STARFIVE_MODE_R256; > > + break; > > + } > > + > > + writel(mode, trng->base + STARFIVE_MODE); > > + > > + return starfive_trng_cmd(trng, STARFIVE_CTRL_EXEC_RANDRESEED); > > +} > > + > > +static int starfive_trng_probe(struct udevice *dev) > > +{ > > + struct starfive_trng_plat *pdata = dev_get_plat(dev); > > + int err; > > + > > + err = clk_enable(pdata->hclk); > > + if (err) > > + return err; > > + > > + err = clk_enable(pdata->ahb); > > + if (err) > > Doesn't need to disable the previous clk about pdata->hclk? > > > > + return err; > > + > > + err = reset_deassert(pdata->rst); > > + if (err) > > Ditto about clocks of hclk and ahb? > > How about handle error? > > err = clk_enable(pdata->hclk); > if (err) > ... > > err = clk_enable(pdata->ahb); > if (err) > goto err_ahb; > > ... > > Return starfive_tring_init(pdata); > > goto_err_reset: > clk_disable(pdata->ahb); > goto err_ahb: > clk_disable(pdata->hclk); > > return err;
Thank you for your suggestion. I'll update the codes in the next patchset. Best Regards, Chanho Park > > > + return err; > > + > > + pdata->mode = PRNG_256BIT; > > + > > + return starfive_trng_init(pdata); > > +} > > + > > +static int starfive_trng_of_to_plat(struct udevice *dev) > > +{ > > + struct starfive_trng_plat *pdata = dev_get_plat(dev); > > + > > + pdata->base = (void *)dev_read_addr(dev); > > + if (!pdata->base) > > + return -ENODEV; > > + > > + pdata->hclk = devm_clk_get(dev, "hclk"); > > + if (IS_ERR(pdata->hclk)) > > + return -ENODEV; > > + > > + pdata->ahb = devm_clk_get(dev, "ahb"); > > + if (IS_ERR(pdata->ahb)) > > + return -ENODEV; > > + > > + pdata->rst = devm_reset_control_get(dev, NULL); > > + if (IS_ERR(pdata->rst)) > > + return -ENODEV; > > + > > + return 0; > > +} > > + > > +static const struct dm_rng_ops starfive_trng_ops = { > > + .read = starfive_trng_read, > > +}; > > + > > +static const struct udevice_id starfive_trng_match[] = { > > + { > > + .compatible = "starfive,jh7110-trng", > > + }, > > + {}, > > +}; > > + > > +U_BOOT_DRIVER(starfive_trng) = { > > + .name = "jh7110-trng", > > + .id = UCLASS_RNG, > > + .of_match = starfive_trng_match, > > + .probe = starfive_trng_probe, > > + .ops = &starfive_trng_ops, > > + .plat_auto = sizeof(struct starfive_trng_plat), > > + .of_to_plat = starfive_trng_of_to_plat, > > +}; > > -- > > 2.39.2 >