diff options
| author | Lin Jinhan <troy.lin@rock-chips.com> | 2025-04-07 22:46:58 +0000 | 
|---|---|---|
| committer | Kever Yang <kever.yang@rock-chips.com> | 2025-04-23 22:12:04 +0800 | 
| commit | 7fe0b79211d5440c29d39faeeb1afa2f4faabcf4 (patch) | |
| tree | b215e3daf21f5c9f9649ab6ee828d6534ee3b4f5 /drivers/rng/rockchip_rng.c | |
| parent | 6ef723af18b90bee9c2b0e917c8f8bf69556ee5d (diff) | |
rng: rockchip: Add support for rkrng variant
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>
Diffstat (limited to 'drivers/rng/rockchip_rng.c')
| -rw-r--r-- | drivers/rng/rockchip_rng.c | 73 | 
1 files changed, 73 insertions, 0 deletions
| diff --git a/drivers/rng/rockchip_rng.c b/drivers/rng/rockchip_rng.c index 6e4e3abf08c..d854ea90044 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, +	},  	{},  }; | 
