On 2025/4/8 06:46, Jonas Karlman wrote:
From: Lin Jinhan <troy....@rock-chips.com>

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....@rock-chips.com>
Signed-off-by: Jonas Karlman <jo...@kwiboo.se>
Reviewed-by: Kever Yang <kever.y...@rock-chips.com>

Thanks,
- Kever
---
v2: Rebase on "rockchip: Update rng compatible for RK356x and RK3588"
---
  drivers/rng/rockchip_rng.c | 73 ++++++++++++++++++++++++++++++++++++++
  1 file changed, 73 insertions(+)

diff --git a/drivers/rng/rockchip_rng.c b/drivers/rng/rockchip_rng.c
index 6e4e3abf08c8..d854ea900442 100644
--- a/drivers/rng/rockchip_rng.c
+++ b/drivers/rng/rockchip_rng.c
@@ -70,6 +70,27 @@
  #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,
+       },
        {},
  };

Reply via email to