
On 2023/4/8 05:32, Chris Morgan wrote:
From: Chris Morgan macromorgan@hotmail.com
This adds support for the TRNG found in the RK3588 SoC to the rockchip_rng driver so that it can be used for things such as seeding randomness to Linux.
This code was taken wholesale from the Rockchip BSP U-Boot source located here: https://github.com/rockchip-linux/u-boot/commit/09f31aed858c36a8a5ee20789712...
Tested on an Indiedroid Nova with an RK3588s.
This code info and test info should be present at cover letter instead of patch commit message, please update it.
otherwise
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
Changes in V2:
- Modified Kconfig to note that the Rockchip RNG driver supports all versions of the hardware (v1, v2, and the trng in the rk3588).
Signed-off-by: Lin Jinhan troy.lin@rock-chips.com Signed-off-by: Chris Morgan macromorgan@hotmail.com
drivers/rng/Kconfig | 5 +- drivers/rng/rockchip_rng.c | 120 ++++++++++++++++++++++++++++++++++--- 2 files changed, 114 insertions(+), 11 deletions(-)
diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig index 5dcf68176a..5deb5db5b7 100644 --- a/drivers/rng/Kconfig +++ b/drivers/rng/Kconfig @@ -58,8 +58,9 @@ config RNG_ROCKCHIP bool "Enable random number generator for rockchip crypto rng" depends on ARCH_ROCKCHIP && DM_RNG help
Enable random number generator for rockchip.This driver is
support rng module of crypto v1 and crypto v2.
Enable random number generator for rockchip. This driver
supports the rng module of crypto v1, crypto v2, and the
trng module of the rk3588 series.
config RNG_IPROC200 bool "Broadcom iProc RNG200 random number generator"
diff --git a/drivers/rng/rockchip_rng.c b/drivers/rng/rockchip_rng.c index 800150f114..705b424cf3 100644 --- a/drivers/rng/rockchip_rng.c +++ b/drivers/rng/rockchip_rng.c @@ -43,9 +43,41 @@ #define CRYPTO_V2_RNG_DOUT_0 0x0410 /* end of CRYPTO V2 register define */
+/* start of TRNG V1 register define */ +#define TRNG_V1_CTRL 0x0000 +#define TRNG_V1_CTRL_NOP _SBF(0, 0x00) +#define TRNG_V1_CTRL_RAND _SBF(0, 0x01) +#define TRNG_V1_CTRL_SEED _SBF(0, 0x02)
+#define TRNG_V1_MODE 0x0008 +#define TRNG_V1_MODE_128_BIT _SBF(3, 0x00) +#define TRNG_V1_MODE_256_BIT _SBF(3, 0x01)
+#define TRNG_V1_IE 0x0010 +#define TRNG_V1_IE_GLBL_EN BIT(31) +#define TRNG_V1_IE_SEED_DONE_EN BIT(1) +#define TRNG_V1_IE_RAND_RDY_EN BIT(0)
+#define TRNG_V1_ISTAT 0x0014 +#define TRNG_V1_ISTAT_RAND_RDY BIT(0)
+/* RAND0 ~ RAND7 */ +#define TRNG_V1_RAND0 0x0020 +#define TRNG_V1_RAND7 0x003C
+#define TRNG_V1_AUTO_RQSTS 0x0060
+#define TRNG_V1_VERSION 0x00F0 +#define TRNG_v1_VERSION_CODE 0x46BC +/* end of TRNG V1 register define */
- #define RK_RNG_TIME_OUT 50000 /* max 50ms */
+#define trng_write(pdata, pos, val) writel(val, (pdata)->base + (pos)) +#define trng_read(pdata, pos) readl((pdata)->base + (pos))
- struct rk_rng_soc_data {
- int (*rk_rng_init)(struct udevice *dev); int (*rk_rng_read)(struct udevice *dev, void *data, size_t len); };
@@ -75,7 +107,7 @@ static int rk_rng_read_regs(fdt_addr_t addr, void *buf, size_t size) return 0; }
-static int rk_v1_rng_read(struct udevice *dev, void *data, size_t len) +static int rk_cryptov1_rng_read(struct udevice *dev, void *data, size_t len) { struct rk_rng_plat *pdata = dev_get_priv(dev); u32 reg = 0; @@ -106,7 +138,7 @@ exit: return 0; }
-static int rk_v2_rng_read(struct udevice *dev, void *data, size_t len) +static int rk_cryptov2_rng_read(struct udevice *dev, void *data, size_t len) { struct rk_rng_plat *pdata = dev_get_priv(dev); u32 reg = 0; @@ -140,6 +172,63 @@ exit: return retval; }
+static int rk_trngv1_init(struct udevice *dev) +{
- u32 status, version;
- u32 auto_reseed_cnt = 1000;
- struct rk_rng_plat *pdata = dev_get_priv(dev);
- version = trng_read(pdata, TRNG_V1_VERSION);
- if (version != TRNG_v1_VERSION_CODE) {
printf("wrong trng version, expected = %08x, actual = %08x",
TRNG_V1_VERSION, version);
return -EFAULT;
- }
- /* wait in case of RND_RDY triggered at firs power on */
- readl_poll_timeout(pdata->base + TRNG_V1_ISTAT, status,
(status & TRNG_V1_ISTAT_RAND_RDY),
RK_RNG_TIME_OUT);
- /* clear RAND_RDY flag for first power on */
- trng_write(pdata, TRNG_V1_ISTAT, status);
- /* auto reseed after (auto_reseed_cnt * 16) byte rand generate */
- trng_write(pdata, TRNG_V1_AUTO_RQSTS, auto_reseed_cnt);
- return 0;
+}
+static int rk_trngv1_rng_read(struct udevice *dev, void *data, size_t len) +{
- struct rk_rng_plat *pdata = dev_get_priv(dev);
- u32 reg = 0;
- int retval;
- if (len > RK_HW_RNG_MAX)
return -EINVAL;
- trng_write(pdata, TRNG_V1_MODE, TRNG_V1_MODE_256_BIT);
- trng_write(pdata, TRNG_V1_CTRL, TRNG_V1_CTRL_RAND);
- retval = readl_poll_timeout(pdata->base + TRNG_V1_ISTAT, reg,
(reg & TRNG_V1_ISTAT_RAND_RDY),
RK_RNG_TIME_OUT);
- /* clear ISTAT */
- trng_write(pdata, TRNG_V1_ISTAT, reg);
- if (retval)
goto exit;
- rk_rng_read_regs(pdata->base + TRNG_V1_RAND0, data, len);
+exit:
- /* close TRNG */
- trng_write(pdata, TRNG_V1_CTRL, TRNG_V1_CTRL_NOP);
- return retval;
+}
- static int rockchip_rng_read(struct udevice *dev, void *data, size_t len) { unsigned char *buf = data;
@@ -184,18 +273,27 @@ static int rockchip_rng_of_to_plat(struct udevice *dev) static int rockchip_rng_probe(struct udevice *dev) { struct rk_rng_plat *pdata = dev_get_priv(dev);
int ret = 0;
pdata->soc_data = (struct rk_rng_soc_data *)dev_get_driver_data(dev);
- return 0;
- if (pdata->soc_data->rk_rng_init)
ret = pdata->soc_data->rk_rng_init(dev);
- return ret; }
-static const struct rk_rng_soc_data rk_rng_v1_soc_data = {
- .rk_rng_read = rk_v1_rng_read,
+static const struct rk_rng_soc_data rk_cryptov1_soc_data = {
- .rk_rng_read = rk_cryptov1_rng_read,
+};
+static const struct rk_rng_soc_data rk_cryptov2_soc_data = {
- .rk_rng_read = rk_cryptov2_rng_read, };
-static const struct rk_rng_soc_data rk_rng_v2_soc_data = {
- .rk_rng_read = rk_v2_rng_read,
+static const struct rk_rng_soc_data rk_trngv1_soc_data = {
.rk_rng_init = rk_trngv1_init,
.rk_rng_read = rk_trngv1_rng_read, };
static const struct dm_rng_ops rockchip_rng_ops = {
@@ -205,11 +303,15 @@ static const struct dm_rng_ops rockchip_rng_ops = { static const struct udevice_id rockchip_rng_match[] = { { .compatible = "rockchip,cryptov1-rng",
.data = (ulong)&rk_rng_v1_soc_data,
}, { .compatible = "rockchip,cryptov2-rng",.data = (ulong)&rk_cryptov1_soc_data,
.data = (ulong)&rk_rng_v2_soc_data,
.data = (ulong)&rk_cryptov2_soc_data,
- },
- {
.compatible = "rockchip,trngv1",
}, {}, };.data = (ulong)&rk_trngv1_soc_data,