rng: rockchip: Add support for rkrng variant
authorLin Jinhan <troy.lin@rock-chips.com>
Mon, 7 Apr 2025 22:46:58 +0000 (22:46 +0000)
committerKever Yang <kever.yang@rock-chips.com>
Wed, 23 Apr 2025 14:12:04 +0000 (22:12 +0800)
Add support for rkrng variant, used by e.g. RK3528 and RK3576.

Imported from vendor U-Boot linux-6.1-stan-rkr5 tag with minor
adjustments for mainline.

Signed-off-by: Lin Jinhan <troy.lin@rock-chips.com>
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>
drivers/rng/rockchip_rng.c

index 6e4e3ab..d854ea9 100644 (file)
 #define TRNG_v1_VERSION_CODE                   0x46BC
 /* end of TRNG V1 register define */
 
+/* start of RKRNG register define */
+#define RKRNG_CTRL                             0x0010
+#define RKRNG_CTRL_INST_REQ                    BIT(0)
+#define RKRNG_CTRL_RESEED_REQ                  BIT(1)
+#define RKRNG_CTRL_TEST_REQ                    BIT(2)
+#define RKRNG_CTRL_SW_DRNG_REQ                 BIT(3)
+#define RKRNG_CTRL_SW_TRNG_REQ                 BIT(4)
+
+#define RKRNG_STATE                            0x0014
+#define RKRNG_STATE_INST_ACK                   BIT(0)
+#define RKRNG_STATE_RESEED_ACK                 BIT(1)
+#define RKRNG_STATE_TEST_ACK                   BIT(2)
+#define RKRNG_STATE_SW_DRNG_ACK                        BIT(3)
+#define RKRNG_STATE_SW_TRNG_ACK                        BIT(4)
+
+/* DRNG_DATA_0 ~ DNG_DATA_7 */
+#define RKRNG_DRNG_DATA_0                      0x0070
+#define RKRNG_DRNG_DATA_7                      0x008C
+
+/* end of RKRNG register define */
+
 #define RK_RNG_TIME_OUT        50000  /* max 50ms */
 
 #define trng_write(pdata, pos, val)    writel(val, (pdata)->base + (pos))
@@ -228,6 +249,49 @@ exit:
        return retval;
 }
 
+static int rkrng_init(struct udevice *dev)
+{
+       struct rk_rng_plat *pdata = dev_get_priv(dev);
+       u32 reg = 0;
+
+       rk_clrreg(pdata->base + RKRNG_CTRL, 0xffff);
+
+       reg = trng_read(pdata, RKRNG_STATE);
+       trng_write(pdata, RKRNG_STATE, reg);
+
+       return 0;
+}
+
+static int rkrng_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;
+
+       reg = RKRNG_CTRL_SW_DRNG_REQ;
+
+       rk_clrsetreg(pdata->base + RKRNG_CTRL, 0xffff, reg);
+
+       retval = readl_poll_timeout(pdata->base + RKRNG_STATE, reg,
+                                   (reg & RKRNG_STATE_SW_DRNG_ACK),
+                                   RK_RNG_TIME_OUT);
+       if (retval)
+               goto exit;
+
+       trng_write(pdata, RKRNG_STATE, reg);
+
+       rk_rng_read_regs(pdata->base + RKRNG_DRNG_DATA_0, data, len);
+
+exit:
+       /* close TRNG */
+       rk_clrreg(pdata->base + RKRNG_CTRL, 0xffff);
+
+       return retval;
+}
+
 static int rockchip_rng_read(struct udevice *dev, void *data, size_t len)
 {
        unsigned char *buf = data;
@@ -295,6 +359,11 @@ static const struct rk_rng_soc_data rk_trngv1_soc_data = {
        .rk_rng_read = rk_trngv1_rng_read,
 };
 
+static const struct rk_rng_soc_data rkrng_soc_data = {
+       .rk_rng_init = rkrng_init,
+       .rk_rng_read = rkrng_rng_read,
+};
+
 static const struct dm_rng_ops rockchip_rng_ops = {
        .read = rockchip_rng_read,
 };
@@ -324,6 +393,10 @@ static const struct udevice_id rockchip_rng_match[] = {
                .compatible = "rockchip,rk3588-rng",
                .data = (ulong)&rk_trngv1_soc_data,
        },
+       {
+               .compatible = "rockchip,rkrng",
+               .data = (ulong)&rkrng_soc_data,
+       },
        {},
 };