[PATCH 1/5] arm: dts: rockchip: rk3399: add and enable rng node

Add rng node in rk3399-u-boot.dtsi and enable it in rk3399-evb-u-boot.dtsi.
Signed-off-by: Lin Jinhan troy.lin@rock-chips.com --- arch/arm/dts/rk3399-evb-u-boot.dtsi | 5 +++++ arch/arm/dts/rk3399-u-boot.dtsi | 6 ++++++ 2 files changed, 11 insertions(+)
diff --git a/arch/arm/dts/rk3399-evb-u-boot.dtsi b/arch/arm/dts/rk3399-evb-u-boot.dtsi index ccb33d34d1..5b50c5ba30 100644 --- a/arch/arm/dts/rk3399-evb-u-boot.dtsi +++ b/arch/arm/dts/rk3399-evb-u-boot.dtsi @@ -11,3 +11,8 @@ u-boot,spl-boot-order = &sdhci, &sdmmc; }; }; + +&rng { + status = "okay"; +}; + diff --git a/arch/arm/dts/rk3399-u-boot.dtsi b/arch/arm/dts/rk3399-u-boot.dtsi index 8b857ccfc7..757b8c10a2 100644 --- a/arch/arm/dts/rk3399-u-boot.dtsi +++ b/arch/arm/dts/rk3399-u-boot.dtsi @@ -25,6 +25,12 @@ clock-names = "pclk_ddr_mon"; };
+ rng: rng@ff8b8000 { + compatible = "rockchip,cryptov1-rng"; + reg = <0x0 0xff8b8000 0x0 0x1000>; + status = "disabled"; + }; + dmc: dmc { u-boot,dm-pre-reloc; compatible = "rockchip,rk3399-dmc";

Add enable rng node in px30-evb-u-boot.dtsi.
Signed-off-by: Lin Jinhan troy.lin@rock-chips.com --- arch/arm/dts/px30-evb-u-boot.dtsi | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/arch/arm/dts/px30-evb-u-boot.dtsi b/arch/arm/dts/px30-evb-u-boot.dtsi index a2a2c07dcc..a73c215c05 100644 --- a/arch/arm/dts/px30-evb-u-boot.dtsi +++ b/arch/arm/dts/px30-evb-u-boot.dtsi @@ -12,6 +12,13 @@ chosen { u-boot,spl-boot-order = &emmc, &sdmmc; }; + + rng: rng@ff0b0000 { + compatible = "rockchip,cryptov2-rng"; + reg = <0x0 0xff0b0000 0x0 0x4000>; + status = "okay"; + }; + };
&dmc {

On 2020/3/31 下午5:39, Lin Jinhan wrote:
Add enable rng node in px30-evb-u-boot.dtsi.
Signed-off-by: Lin Jinhan troy.lin@rock-chips.com
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
arch/arm/dts/px30-evb-u-boot.dtsi | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/arch/arm/dts/px30-evb-u-boot.dtsi b/arch/arm/dts/px30-evb-u-boot.dtsi index a2a2c07dcc..a73c215c05 100644 --- a/arch/arm/dts/px30-evb-u-boot.dtsi +++ b/arch/arm/dts/px30-evb-u-boot.dtsi @@ -12,6 +12,13 @@ chosen { u-boot,spl-boot-order = &emmc, &sdmmc; };
rng: rng@ff0b0000 {
compatible = "rockchip,cryptov2-rng";
reg = <0x0 0xff0b0000 0x0 0x4000>;
status = "okay";
};
};
&dmc {

Add a driver for the rng device found on rockchip platforms. Support rng module of crypto v1 and crypto v2.
Signed-off-by: Lin Jinhan troy.lin@rock-chips.com --- drivers/rng/Kconfig | 8 ++ drivers/rng/Makefile | 1 + drivers/rng/rockchip_rng.c | 224 +++++++++++++++++++++++++++++++++++++ 3 files changed, 233 insertions(+) create mode 100644 drivers/rng/rockchip_rng.c
diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig index edb6152bb9..e4b22d79eb 100644 --- a/drivers/rng/Kconfig +++ b/drivers/rng/Kconfig @@ -31,4 +31,12 @@ config RNG_STM32MP1 help Enable STM32MP1 rng driver.
+config RNG_ROCKCHIP + bool "Enable random number generator for rockchip crypto rng" + depends on ARCH_ROCKCHIP && DM_RNG + default n + help + Enable random number generator for rockchip.This driver is + support rng module of crypto v1 and crypto v2. + endif diff --git a/drivers/rng/Makefile b/drivers/rng/Makefile index 6a8a66779b..44a0003917 100644 --- a/drivers/rng/Makefile +++ b/drivers/rng/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_DM_RNG) += rng-uclass.o obj-$(CONFIG_RNG_MESON) += meson-rng.o obj-$(CONFIG_RNG_SANDBOX) += sandbox_rng.o obj-$(CONFIG_RNG_STM32MP1) += stm32mp1_rng.o +obj-$(CONFIG_RNG_ROCKCHIP) += rockchip_rng.o diff --git a/drivers/rng/rockchip_rng.c b/drivers/rng/rockchip_rng.c new file mode 100644 index 0000000000..47fb140077 --- /dev/null +++ b/drivers/rng/rockchip_rng.c @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 Fuzhou Rockchip Electronics Co., Ltd + */ +#include <asm/arch-rockchip/hardware.h> +#include <asm/io.h> +#include <common.h> +#include <dm.h> +#include <linux/iopoll.h> +#include <linux/string.h> +#include <rng.h> + +#define RK_HW_RNG_MAX 32 + +#define _SBF(s, v) ((v) << (s)) + +/* start of CRYPTO V1 register define */ +#define CRYPTO_V1_CTRL 0x0008 +#define CRYPTO_V1_RNG_START BIT(8) +#define CRYPTO_V1_RNG_FLUSH BIT(9) + +#define CRYPTO_V1_TRNG_CTRL 0x0200 +#define CRYPTO_V1_OSC_ENABLE BIT(16) +#define CRYPTO_V1_TRNG_SAMPLE_PERIOD(x) (x) + +#define CRYPTO_V1_TRNG_DOUT_0 0x0204 +/* end of CRYPTO V1 register define */ + +/* start of CRYPTO V2 register define */ +#define CRYPTO_V2_RNG_CTL 0x0400 +#define CRYPTO_V2_RNG_64_BIT_LEN _SBF(4, 0x00) +#define CRYPTO_V2_RNG_128_BIT_LEN _SBF(4, 0x01) +#define CRYPTO_V2_RNG_192_BIT_LEN _SBF(4, 0x02) +#define CRYPTO_V2_RNG_256_BIT_LEN _SBF(4, 0x03) +#define CRYPTO_V2_RNG_FATESY_SOC_RING _SBF(2, 0x00) +#define CRYPTO_V2_RNG_SLOWER_SOC_RING_0 _SBF(2, 0x01) +#define CRYPTO_V2_RNG_SLOWER_SOC_RING_1 _SBF(2, 0x02) +#define CRYPTO_V2_RNG_SLOWEST_SOC_RING _SBF(2, 0x03) +#define CRYPTO_V2_RNG_ENABLE BIT(1) +#define CRYPTO_V2_RNG_START BIT(0) +#define CRYPTO_V2_RNG_SAMPLE_CNT 0x0404 +#define CRYPTO_V2_RNG_DOUT_0 0x0410 +/* end of CRYPTO V2 register define */ + +#define RK_RNG_TIME_OUT 50000 /* max 50ms */ + +struct rk_rng_soc_data { + int (*rk_rng_read)(struct udevice *dev, void *data, size_t len); +}; + +struct rk_rng_platdata { + fdt_addr_t base; + struct rk_rng_soc_data *soc_data; +}; + +static int rk_rng_read_regs(fdt_addr_t addr, void *buf, size_t size) +{ + u32 count = RK_HW_RNG_MAX / sizeof(u32); + u32 reg, tmp_len; + + if (size > RK_HW_RNG_MAX) + return -EINVAL; + + while (size && count) { + reg = readl(addr); + tmp_len = min(size, sizeof(u32)); + memcpy(buf, ®, tmp_len); + addr += sizeof(u32); + buf += tmp_len; + size -= tmp_len; + count--; + } + + return 0; +} + +static int rk_v1_rng_read(struct udevice *dev, void *data, size_t len) +{ + struct rk_rng_platdata *pdata = dev_get_priv(dev); + u32 reg = 0; + int retval; + + if (len > RK_HW_RNG_MAX) + return -EINVAL; + + /* enable osc_ring to get entropy, sample period is set as 100 */ + writel(CRYPTO_V1_OSC_ENABLE | CRYPTO_V1_TRNG_SAMPLE_PERIOD(100), + pdata->base + CRYPTO_V1_TRNG_CTRL); + + rk_clrsetreg(pdata->base + CRYPTO_V1_CTRL, CRYPTO_V1_RNG_START, + CRYPTO_V1_RNG_START); + + retval = readl_poll_timeout(pdata->base + CRYPTO_V1_CTRL, reg, + !(reg & CRYPTO_V1_RNG_START), + RK_RNG_TIME_OUT); + if (retval) + goto exit; + + rk_rng_read_regs(pdata->base + CRYPTO_V1_TRNG_DOUT_0, data, len); + +exit: + /* close TRNG */ + rk_clrreg(pdata->base + CRYPTO_V1_CTRL, CRYPTO_V1_RNG_START); + + return 0; +} + +static int rk_v2_rng_read(struct udevice *dev, void *data, size_t len) +{ + struct rk_rng_platdata *pdata = dev_get_priv(dev); + u32 reg = 0; + int retval; + + if (len > RK_HW_RNG_MAX) + return -EINVAL; + + /* enable osc_ring to get entropy, sample period is set as 100 */ + writel(100, pdata->base + CRYPTO_V2_RNG_SAMPLE_CNT); + + reg |= CRYPTO_V2_RNG_256_BIT_LEN; + reg |= CRYPTO_V2_RNG_SLOWER_SOC_RING_0; + reg |= CRYPTO_V2_RNG_ENABLE; + reg |= CRYPTO_V2_RNG_START; + + rk_clrsetreg(pdata->base + CRYPTO_V2_RNG_CTL, 0xffff, reg); + + retval = readl_poll_timeout(pdata->base + CRYPTO_V2_RNG_CTL, reg, + !(reg & CRYPTO_V2_RNG_START), + RK_RNG_TIME_OUT); + if (retval) + goto exit; + + rk_rng_read_regs(pdata->base + CRYPTO_V2_RNG_DOUT_0, data, len); + +exit: + /* close TRNG */ + rk_clrreg(pdata->base + CRYPTO_V2_RNG_CTL, 0xffff); + + return retval; +} + +static int rockchip_rng_read(struct udevice *dev, void *data, size_t len) +{ + unsigned char *buf = data; + unsigned int i; + int ret = -EIO; + + struct rk_rng_platdata *pdata = dev_get_priv(dev); + + if (!len) + return 0; + + if (!pdata->soc_data || !pdata->soc_data->rk_rng_read) + return -EINVAL; + + for (i = 0; i < len / RK_HW_RNG_MAX; i++, buf += RK_HW_RNG_MAX) { + ret = pdata->soc_data->rk_rng_read(dev, buf, RK_HW_RNG_MAX); + if (ret) + goto exit; + } + + if (len % RK_HW_RNG_MAX) + ret = pdata->soc_data->rk_rng_read(dev, buf, + len % RK_HW_RNG_MAX); + +exit: + return ret; +} + +static int rockchip_rng_ofdata_to_platdata(struct udevice *dev) +{ + struct rk_rng_platdata *pdata = dev_get_priv(dev); + + memset(pdata, 0x00, sizeof(*pdata)); + + pdata->base = (fdt_addr_t)dev_read_addr_ptr(dev); + if (!pdata->base) + return -ENOMEM; + + return 0; +} + +static int rockchip_rng_probe(struct udevice *dev) +{ + struct rk_rng_platdata *pdata = dev_get_priv(dev); + + pdata->soc_data = (struct rk_rng_soc_data *)dev_get_driver_data(dev); + + return 0; +} + +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_rng_v2_soc_data = { + .rk_rng_read = rk_v2_rng_read, +}; + +static const struct dm_rng_ops rockchip_rng_ops = { + .read = rockchip_rng_read, +}; + +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_rng_v2_soc_data, + }, + {}, +}; + +U_BOOT_DRIVER(rockchip_rng) = { + .name = "rockchip-rng", + .id = UCLASS_RNG, + .of_match = rockchip_rng_match, + .ops = &rockchip_rng_ops, + .probe = rockchip_rng_probe, + .ofdata_to_platdata = rockchip_rng_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct rk_rng_platdata), +};

Add a driver for the rng device found on rockchip platforms. Support rng module of crypto v1 and crypto v2.
Signed-off-by: Lin Jinhan troy.lin@rock-chips.com
Tested-by: Peter Robinson pbrobinson@gmail.com
Tested with UEFI RNG providing a seed for KASLR.
drivers/rng/Kconfig | 8 ++ drivers/rng/Makefile | 1 + drivers/rng/rockchip_rng.c | 224 +++++++++++++++++++++++++++++++++++++ 3 files changed, 233 insertions(+) create mode 100644 drivers/rng/rockchip_rng.c
diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig index edb6152bb9..e4b22d79eb 100644 --- a/drivers/rng/Kconfig +++ b/drivers/rng/Kconfig @@ -31,4 +31,12 @@ config RNG_STM32MP1 help Enable STM32MP1 rng driver.
+config RNG_ROCKCHIP
bool "Enable random number generator for rockchip crypto rng"
depends on ARCH_ROCKCHIP && DM_RNG
default n
help
Enable random number generator for rockchip.This driver is
support rng module of crypto v1 and crypto v2.
endif diff --git a/drivers/rng/Makefile b/drivers/rng/Makefile index 6a8a66779b..44a0003917 100644 --- a/drivers/rng/Makefile +++ b/drivers/rng/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_DM_RNG) += rng-uclass.o obj-$(CONFIG_RNG_MESON) += meson-rng.o obj-$(CONFIG_RNG_SANDBOX) += sandbox_rng.o obj-$(CONFIG_RNG_STM32MP1) += stm32mp1_rng.o +obj-$(CONFIG_RNG_ROCKCHIP) += rockchip_rng.o diff --git a/drivers/rng/rockchip_rng.c b/drivers/rng/rockchip_rng.c new file mode 100644 index 0000000000..47fb140077 --- /dev/null +++ b/drivers/rng/rockchip_rng.c @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- Copyright (c) 2020 Fuzhou Rockchip Electronics Co., Ltd
- */
+#include <asm/arch-rockchip/hardware.h> +#include <asm/io.h> +#include <common.h> +#include <dm.h> +#include <linux/iopoll.h> +#include <linux/string.h> +#include <rng.h>
+#define RK_HW_RNG_MAX 32
+#define _SBF(s, v) ((v) << (s))
+/* start of CRYPTO V1 register define */ +#define CRYPTO_V1_CTRL 0x0008 +#define CRYPTO_V1_RNG_START BIT(8) +#define CRYPTO_V1_RNG_FLUSH BIT(9)
+#define CRYPTO_V1_TRNG_CTRL 0x0200 +#define CRYPTO_V1_OSC_ENABLE BIT(16) +#define CRYPTO_V1_TRNG_SAMPLE_PERIOD(x) (x)
+#define CRYPTO_V1_TRNG_DOUT_0 0x0204 +/* end of CRYPTO V1 register define */
+/* start of CRYPTO V2 register define */ +#define CRYPTO_V2_RNG_CTL 0x0400 +#define CRYPTO_V2_RNG_64_BIT_LEN _SBF(4, 0x00) +#define CRYPTO_V2_RNG_128_BIT_LEN _SBF(4, 0x01) +#define CRYPTO_V2_RNG_192_BIT_LEN _SBF(4, 0x02) +#define CRYPTO_V2_RNG_256_BIT_LEN _SBF(4, 0x03) +#define CRYPTO_V2_RNG_FATESY_SOC_RING _SBF(2, 0x00) +#define CRYPTO_V2_RNG_SLOWER_SOC_RING_0 _SBF(2, 0x01) +#define CRYPTO_V2_RNG_SLOWER_SOC_RING_1 _SBF(2, 0x02) +#define CRYPTO_V2_RNG_SLOWEST_SOC_RING _SBF(2, 0x03) +#define CRYPTO_V2_RNG_ENABLE BIT(1) +#define CRYPTO_V2_RNG_START BIT(0) +#define CRYPTO_V2_RNG_SAMPLE_CNT 0x0404 +#define CRYPTO_V2_RNG_DOUT_0 0x0410 +/* end of CRYPTO V2 register define */
+#define RK_RNG_TIME_OUT 50000 /* max 50ms */
+struct rk_rng_soc_data {
int (*rk_rng_read)(struct udevice *dev, void *data, size_t len);
+};
+struct rk_rng_platdata {
fdt_addr_t base;
struct rk_rng_soc_data *soc_data;
+};
+static int rk_rng_read_regs(fdt_addr_t addr, void *buf, size_t size) +{
u32 count = RK_HW_RNG_MAX / sizeof(u32);
u32 reg, tmp_len;
if (size > RK_HW_RNG_MAX)
return -EINVAL;
while (size && count) {
reg = readl(addr);
tmp_len = min(size, sizeof(u32));
memcpy(buf, ®, tmp_len);
addr += sizeof(u32);
buf += tmp_len;
size -= tmp_len;
count--;
}
return 0;
+}
+static int rk_v1_rng_read(struct udevice *dev, void *data, size_t len) +{
struct rk_rng_platdata *pdata = dev_get_priv(dev);
u32 reg = 0;
int retval;
if (len > RK_HW_RNG_MAX)
return -EINVAL;
/* enable osc_ring to get entropy, sample period is set as 100 */
writel(CRYPTO_V1_OSC_ENABLE | CRYPTO_V1_TRNG_SAMPLE_PERIOD(100),
pdata->base + CRYPTO_V1_TRNG_CTRL);
rk_clrsetreg(pdata->base + CRYPTO_V1_CTRL, CRYPTO_V1_RNG_START,
CRYPTO_V1_RNG_START);
retval = readl_poll_timeout(pdata->base + CRYPTO_V1_CTRL, reg,
!(reg & CRYPTO_V1_RNG_START),
RK_RNG_TIME_OUT);
if (retval)
goto exit;
rk_rng_read_regs(pdata->base + CRYPTO_V1_TRNG_DOUT_0, data, len);
+exit:
/* close TRNG */
rk_clrreg(pdata->base + CRYPTO_V1_CTRL, CRYPTO_V1_RNG_START);
return 0;
+}
+static int rk_v2_rng_read(struct udevice *dev, void *data, size_t len) +{
struct rk_rng_platdata *pdata = dev_get_priv(dev);
u32 reg = 0;
int retval;
if (len > RK_HW_RNG_MAX)
return -EINVAL;
/* enable osc_ring to get entropy, sample period is set as 100 */
writel(100, pdata->base + CRYPTO_V2_RNG_SAMPLE_CNT);
reg |= CRYPTO_V2_RNG_256_BIT_LEN;
reg |= CRYPTO_V2_RNG_SLOWER_SOC_RING_0;
reg |= CRYPTO_V2_RNG_ENABLE;
reg |= CRYPTO_V2_RNG_START;
rk_clrsetreg(pdata->base + CRYPTO_V2_RNG_CTL, 0xffff, reg);
retval = readl_poll_timeout(pdata->base + CRYPTO_V2_RNG_CTL, reg,
!(reg & CRYPTO_V2_RNG_START),
RK_RNG_TIME_OUT);
if (retval)
goto exit;
rk_rng_read_regs(pdata->base + CRYPTO_V2_RNG_DOUT_0, data, len);
+exit:
/* close TRNG */
rk_clrreg(pdata->base + CRYPTO_V2_RNG_CTL, 0xffff);
return retval;
+}
+static int rockchip_rng_read(struct udevice *dev, void *data, size_t len) +{
unsigned char *buf = data;
unsigned int i;
int ret = -EIO;
struct rk_rng_platdata *pdata = dev_get_priv(dev);
if (!len)
return 0;
if (!pdata->soc_data || !pdata->soc_data->rk_rng_read)
return -EINVAL;
for (i = 0; i < len / RK_HW_RNG_MAX; i++, buf += RK_HW_RNG_MAX) {
ret = pdata->soc_data->rk_rng_read(dev, buf, RK_HW_RNG_MAX);
if (ret)
goto exit;
}
if (len % RK_HW_RNG_MAX)
ret = pdata->soc_data->rk_rng_read(dev, buf,
len % RK_HW_RNG_MAX);
+exit:
return ret;
+}
+static int rockchip_rng_ofdata_to_platdata(struct udevice *dev) +{
struct rk_rng_platdata *pdata = dev_get_priv(dev);
memset(pdata, 0x00, sizeof(*pdata));
pdata->base = (fdt_addr_t)dev_read_addr_ptr(dev);
if (!pdata->base)
return -ENOMEM;
return 0;
+}
+static int rockchip_rng_probe(struct udevice *dev) +{
struct rk_rng_platdata *pdata = dev_get_priv(dev);
pdata->soc_data = (struct rk_rng_soc_data *)dev_get_driver_data(dev);
return 0;
+}
+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_rng_v2_soc_data = {
.rk_rng_read = rk_v2_rng_read,
+};
+static const struct dm_rng_ops rockchip_rng_ops = {
.read = rockchip_rng_read,
+};
+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_rng_v2_soc_data,
},
{},
+};
+U_BOOT_DRIVER(rockchip_rng) = {
.name = "rockchip-rng",
.id = UCLASS_RNG,
.of_match = rockchip_rng_match,
.ops = &rockchip_rng_ops,
.probe = rockchip_rng_probe,
.ofdata_to_platdata = rockchip_rng_ofdata_to_platdata,
.priv_auto_alloc_size = sizeof(struct rk_rng_platdata),
+};
2.17.1

On 2020/3/31 下午5:39, Lin Jinhan wrote:
Add a driver for the rng device found on rockchip platforms. Support rng module of crypto v1 and crypto v2.
Signed-off-by: Lin Jinhan troy.lin@rock-chips.com
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
drivers/rng/Kconfig | 8 ++ drivers/rng/Makefile | 1 + drivers/rng/rockchip_rng.c | 224 +++++++++++++++++++++++++++++++++++++ 3 files changed, 233 insertions(+) create mode 100644 drivers/rng/rockchip_rng.c
diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig index edb6152bb9..e4b22d79eb 100644 --- a/drivers/rng/Kconfig +++ b/drivers/rng/Kconfig @@ -31,4 +31,12 @@ config RNG_STM32MP1 help Enable STM32MP1 rng driver.
+config RNG_ROCKCHIP
- bool "Enable random number generator for rockchip crypto rng"
- depends on ARCH_ROCKCHIP && DM_RNG
- default n
- help
Enable random number generator for rockchip.This driver is
support rng module of crypto v1 and crypto v2.
- endif
diff --git a/drivers/rng/Makefile b/drivers/rng/Makefile index 6a8a66779b..44a0003917 100644 --- a/drivers/rng/Makefile +++ b/drivers/rng/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_DM_RNG) += rng-uclass.o obj-$(CONFIG_RNG_MESON) += meson-rng.o obj-$(CONFIG_RNG_SANDBOX) += sandbox_rng.o obj-$(CONFIG_RNG_STM32MP1) += stm32mp1_rng.o +obj-$(CONFIG_RNG_ROCKCHIP) += rockchip_rng.o diff --git a/drivers/rng/rockchip_rng.c b/drivers/rng/rockchip_rng.c new file mode 100644 index 0000000000..47fb140077 --- /dev/null +++ b/drivers/rng/rockchip_rng.c @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- Copyright (c) 2020 Fuzhou Rockchip Electronics Co., Ltd
- */
+#include <asm/arch-rockchip/hardware.h> +#include <asm/io.h> +#include <common.h> +#include <dm.h> +#include <linux/iopoll.h> +#include <linux/string.h> +#include <rng.h>
+#define RK_HW_RNG_MAX 32
+#define _SBF(s, v) ((v) << (s))
+/* start of CRYPTO V1 register define */ +#define CRYPTO_V1_CTRL 0x0008 +#define CRYPTO_V1_RNG_START BIT(8) +#define CRYPTO_V1_RNG_FLUSH BIT(9)
+#define CRYPTO_V1_TRNG_CTRL 0x0200 +#define CRYPTO_V1_OSC_ENABLE BIT(16) +#define CRYPTO_V1_TRNG_SAMPLE_PERIOD(x) (x)
+#define CRYPTO_V1_TRNG_DOUT_0 0x0204 +/* end of CRYPTO V1 register define */
+/* start of CRYPTO V2 register define */ +#define CRYPTO_V2_RNG_CTL 0x0400 +#define CRYPTO_V2_RNG_64_BIT_LEN _SBF(4, 0x00) +#define CRYPTO_V2_RNG_128_BIT_LEN _SBF(4, 0x01) +#define CRYPTO_V2_RNG_192_BIT_LEN _SBF(4, 0x02) +#define CRYPTO_V2_RNG_256_BIT_LEN _SBF(4, 0x03) +#define CRYPTO_V2_RNG_FATESY_SOC_RING _SBF(2, 0x00) +#define CRYPTO_V2_RNG_SLOWER_SOC_RING_0 _SBF(2, 0x01) +#define CRYPTO_V2_RNG_SLOWER_SOC_RING_1 _SBF(2, 0x02) +#define CRYPTO_V2_RNG_SLOWEST_SOC_RING _SBF(2, 0x03) +#define CRYPTO_V2_RNG_ENABLE BIT(1) +#define CRYPTO_V2_RNG_START BIT(0) +#define CRYPTO_V2_RNG_SAMPLE_CNT 0x0404 +#define CRYPTO_V2_RNG_DOUT_0 0x0410 +/* end of CRYPTO V2 register define */
+#define RK_RNG_TIME_OUT 50000 /* max 50ms */
+struct rk_rng_soc_data {
- int (*rk_rng_read)(struct udevice *dev, void *data, size_t len);
+};
+struct rk_rng_platdata {
- fdt_addr_t base;
- struct rk_rng_soc_data *soc_data;
+};
+static int rk_rng_read_regs(fdt_addr_t addr, void *buf, size_t size) +{
- u32 count = RK_HW_RNG_MAX / sizeof(u32);
- u32 reg, tmp_len;
- if (size > RK_HW_RNG_MAX)
return -EINVAL;
- while (size && count) {
reg = readl(addr);
tmp_len = min(size, sizeof(u32));
memcpy(buf, ®, tmp_len);
addr += sizeof(u32);
buf += tmp_len;
size -= tmp_len;
count--;
- }
- return 0;
+}
+static int rk_v1_rng_read(struct udevice *dev, void *data, size_t len) +{
- struct rk_rng_platdata *pdata = dev_get_priv(dev);
- u32 reg = 0;
- int retval;
- if (len > RK_HW_RNG_MAX)
return -EINVAL;
- /* enable osc_ring to get entropy, sample period is set as 100 */
- writel(CRYPTO_V1_OSC_ENABLE | CRYPTO_V1_TRNG_SAMPLE_PERIOD(100),
pdata->base + CRYPTO_V1_TRNG_CTRL);
- rk_clrsetreg(pdata->base + CRYPTO_V1_CTRL, CRYPTO_V1_RNG_START,
CRYPTO_V1_RNG_START);
- retval = readl_poll_timeout(pdata->base + CRYPTO_V1_CTRL, reg,
!(reg & CRYPTO_V1_RNG_START),
RK_RNG_TIME_OUT);
- if (retval)
goto exit;
- rk_rng_read_regs(pdata->base + CRYPTO_V1_TRNG_DOUT_0, data, len);
+exit:
- /* close TRNG */
- rk_clrreg(pdata->base + CRYPTO_V1_CTRL, CRYPTO_V1_RNG_START);
- return 0;
+}
+static int rk_v2_rng_read(struct udevice *dev, void *data, size_t len) +{
- struct rk_rng_platdata *pdata = dev_get_priv(dev);
- u32 reg = 0;
- int retval;
- if (len > RK_HW_RNG_MAX)
return -EINVAL;
- /* enable osc_ring to get entropy, sample period is set as 100 */
- writel(100, pdata->base + CRYPTO_V2_RNG_SAMPLE_CNT);
- reg |= CRYPTO_V2_RNG_256_BIT_LEN;
- reg |= CRYPTO_V2_RNG_SLOWER_SOC_RING_0;
- reg |= CRYPTO_V2_RNG_ENABLE;
- reg |= CRYPTO_V2_RNG_START;
- rk_clrsetreg(pdata->base + CRYPTO_V2_RNG_CTL, 0xffff, reg);
- retval = readl_poll_timeout(pdata->base + CRYPTO_V2_RNG_CTL, reg,
!(reg & CRYPTO_V2_RNG_START),
RK_RNG_TIME_OUT);
- if (retval)
goto exit;
- rk_rng_read_regs(pdata->base + CRYPTO_V2_RNG_DOUT_0, data, len);
+exit:
- /* close TRNG */
- rk_clrreg(pdata->base + CRYPTO_V2_RNG_CTL, 0xffff);
- return retval;
+}
+static int rockchip_rng_read(struct udevice *dev, void *data, size_t len) +{
- unsigned char *buf = data;
- unsigned int i;
- int ret = -EIO;
- struct rk_rng_platdata *pdata = dev_get_priv(dev);
- if (!len)
return 0;
- if (!pdata->soc_data || !pdata->soc_data->rk_rng_read)
return -EINVAL;
- for (i = 0; i < len / RK_HW_RNG_MAX; i++, buf += RK_HW_RNG_MAX) {
ret = pdata->soc_data->rk_rng_read(dev, buf, RK_HW_RNG_MAX);
if (ret)
goto exit;
- }
- if (len % RK_HW_RNG_MAX)
ret = pdata->soc_data->rk_rng_read(dev, buf,
len % RK_HW_RNG_MAX);
+exit:
- return ret;
+}
+static int rockchip_rng_ofdata_to_platdata(struct udevice *dev) +{
- struct rk_rng_platdata *pdata = dev_get_priv(dev);
- memset(pdata, 0x00, sizeof(*pdata));
- pdata->base = (fdt_addr_t)dev_read_addr_ptr(dev);
- if (!pdata->base)
return -ENOMEM;
- return 0;
+}
+static int rockchip_rng_probe(struct udevice *dev) +{
- struct rk_rng_platdata *pdata = dev_get_priv(dev);
- pdata->soc_data = (struct rk_rng_soc_data *)dev_get_driver_data(dev);
- return 0;
+}
+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_rng_v2_soc_data = {
- .rk_rng_read = rk_v2_rng_read,
+};
+static const struct dm_rng_ops rockchip_rng_ops = {
- .read = rockchip_rng_read,
+};
+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_rng_v2_soc_data,
- },
- {},
+};
+U_BOOT_DRIVER(rockchip_rng) = {
- .name = "rockchip-rng",
- .id = UCLASS_RNG,
- .of_match = rockchip_rng_match,
- .ops = &rockchip_rng_ops,
- .probe = rockchip_rng_probe,
- .ofdata_to_platdata = rockchip_rng_ofdata_to_platdata,
- .priv_auto_alloc_size = sizeof(struct rk_rng_platdata),
+};

CONFIG_RNG_ROCKCHIP/CONFIG_DM_RNG is enabled.
Signed-off-by: Lin Jinhan troy.lin@rock-chips.com --- configs/evb-rk3399_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/evb-rk3399_defconfig b/configs/evb-rk3399_defconfig index 3f74be3b3c..7f14e18b1b 100644 --- a/configs/evb-rk3399_defconfig +++ b/configs/evb-rk3399_defconfig @@ -39,6 +39,8 @@ CONFIG_PMIC_RK8XX=y CONFIG_REGULATOR_PWM=y CONFIG_REGULATOR_RK8XX=y CONFIG_PWM_ROCKCHIP=y +CONFIG_DM_RNG=y +CONFIG_RNG_ROCKCHIP=y CONFIG_BAUDRATE=1500000 CONFIG_DEBUG_UART_SHIFT=2 CONFIG_SYSRESET=y

On Tue, Mar 31, 2020 at 12:36 PM Lin Jinhan troy.lin@rock-chips.com wrote:
CONFIG_RNG_ROCKCHIP/CONFIG_DM_RNG is enabled.
This should be universally available by default on all rk3399 devices shouldn't it or does it need external regulators or something that is per device? If so shouldn't we just enable it by default for the SoC?
Signed-off-by: Lin Jinhan troy.lin@rock-chips.com
configs/evb-rk3399_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/evb-rk3399_defconfig b/configs/evb-rk3399_defconfig index 3f74be3b3c..7f14e18b1b 100644 --- a/configs/evb-rk3399_defconfig +++ b/configs/evb-rk3399_defconfig @@ -39,6 +39,8 @@ CONFIG_PMIC_RK8XX=y CONFIG_REGULATOR_PWM=y CONFIG_REGULATOR_RK8XX=y CONFIG_PWM_ROCKCHIP=y +CONFIG_DM_RNG=y +CONFIG_RNG_ROCKCHIP=y CONFIG_BAUDRATE=1500000 CONFIG_DEBUG_UART_SHIFT=2 CONFIG_SYSRESET=y -- 2.17.1

Hi Peter,
On 2020/3/31 下午10:37, Peter Robinson wrote:
On Tue, Mar 31, 2020 at 12:36 PM Lin Jinhan troy.lin@rock-chips.com wrote:
CONFIG_RNG_ROCKCHIP/CONFIG_DM_RNG is enabled.
This should be universally available by default on all rk3399 devices shouldn't it or does it need external regulators or something that is per device? If so shouldn't we just enable it by default for the SoC?
This rng is a internal module, only need available clock and nothing to do with regulator,
it could default enable, but I'm not sure all the boards want to enable it, the U-Boot size is
already too big for me now.
Thanks,
- Kever
Signed-off-by: Lin Jinhan troy.lin@rock-chips.com
configs/evb-rk3399_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/evb-rk3399_defconfig b/configs/evb-rk3399_defconfig index 3f74be3b3c..7f14e18b1b 100644 --- a/configs/evb-rk3399_defconfig +++ b/configs/evb-rk3399_defconfig @@ -39,6 +39,8 @@ CONFIG_PMIC_RK8XX=y CONFIG_REGULATOR_PWM=y CONFIG_REGULATOR_RK8XX=y CONFIG_PWM_ROCKCHIP=y +CONFIG_DM_RNG=y +CONFIG_RNG_ROCKCHIP=y CONFIG_BAUDRATE=1500000 CONFIG_DEBUG_UART_SHIFT=2 CONFIG_SYSRESET=y -- 2.17.1

On 2020/3/31 下午5:40, Lin Jinhan wrote:
CONFIG_RNG_ROCKCHIP/CONFIG_DM_RNG is enabled.
Signed-off-by: Lin Jinhan troy.lin@rock-chips.com
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
configs/evb-rk3399_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/evb-rk3399_defconfig b/configs/evb-rk3399_defconfig index 3f74be3b3c..7f14e18b1b 100644 --- a/configs/evb-rk3399_defconfig +++ b/configs/evb-rk3399_defconfig @@ -39,6 +39,8 @@ CONFIG_PMIC_RK8XX=y CONFIG_REGULATOR_PWM=y CONFIG_REGULATOR_RK8XX=y CONFIG_PWM_ROCKCHIP=y +CONFIG_DM_RNG=y +CONFIG_RNG_ROCKCHIP=y CONFIG_BAUDRATE=1500000 CONFIG_DEBUG_UART_SHIFT=2 CONFIG_SYSRESET=y

CONFIG_RNG_ROCKCHIP/CONFIG_DM_RNG is enabled.
Signed-off-by: Lin Jinhan troy.lin@rock-chips.com --- configs/evb-px30_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/evb-px30_defconfig b/configs/evb-px30_defconfig index b5ba75cc6e..d2cf13e54a 100644 --- a/configs/evb-px30_defconfig +++ b/configs/evb-px30_defconfig @@ -85,6 +85,8 @@ CONFIG_SPL_RAM=y CONFIG_TPL_RAM=y CONFIG_ROCKCHIP_SDRAM_COMMON=y CONFIG_DM_RESET=y +CONFIG_DM_RNG=y +CONFIG_RNG_ROCKCHIP=y # CONFIG_SPECIFY_CONSOLE_INDEX is not set CONFIG_DEBUG_UART_SHIFT=2 CONFIG_DEBUG_UART_SKIP_INIT=y

On 2020/3/31 下午5:40, Lin Jinhan wrote:
CONFIG_RNG_ROCKCHIP/CONFIG_DM_RNG is enabled.
Signed-off-by: Lin Jinhan troy.lin@rock-chips.com
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
configs/evb-px30_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/evb-px30_defconfig b/configs/evb-px30_defconfig index b5ba75cc6e..d2cf13e54a 100644 --- a/configs/evb-px30_defconfig +++ b/configs/evb-px30_defconfig @@ -85,6 +85,8 @@ CONFIG_SPL_RAM=y CONFIG_TPL_RAM=y CONFIG_ROCKCHIP_SDRAM_COMMON=y CONFIG_DM_RESET=y +CONFIG_DM_RNG=y +CONFIG_RNG_ROCKCHIP=y # CONFIG_SPECIFY_CONSOLE_INDEX is not set CONFIG_DEBUG_UART_SHIFT=2 CONFIG_DEBUG_UART_SKIP_INIT=y

On Tue, Mar 31, 2020 at 12:35 PM Lin Jinhan troy.lin@rock-chips.com wrote:
Add rng node in rk3399-u-boot.dtsi and enable it in rk3399-evb-u-boot.dtsi.
Signed-off-by: Lin Jinhan troy.lin@rock-chips.com
Tested-by: Peter Robinson pbrobinson@gmail.com
Tested with UEFI RNG providing a seed for KASLR.
arch/arm/dts/rk3399-evb-u-boot.dtsi | 5 +++++ arch/arm/dts/rk3399-u-boot.dtsi | 6 ++++++ 2 files changed, 11 insertions(+)
diff --git a/arch/arm/dts/rk3399-evb-u-boot.dtsi b/arch/arm/dts/rk3399-evb-u-boot.dtsi index ccb33d34d1..5b50c5ba30 100644 --- a/arch/arm/dts/rk3399-evb-u-boot.dtsi +++ b/arch/arm/dts/rk3399-evb-u-boot.dtsi @@ -11,3 +11,8 @@ u-boot,spl-boot-order = &sdhci, &sdmmc; }; };
+&rng {
status = "okay";
+};
diff --git a/arch/arm/dts/rk3399-u-boot.dtsi b/arch/arm/dts/rk3399-u-boot.dtsi index 8b857ccfc7..757b8c10a2 100644 --- a/arch/arm/dts/rk3399-u-boot.dtsi +++ b/arch/arm/dts/rk3399-u-boot.dtsi @@ -25,6 +25,12 @@ clock-names = "pclk_ddr_mon"; };
rng: rng@ff8b8000 {
compatible = "rockchip,cryptov1-rng";
reg = <0x0 0xff8b8000 0x0 0x1000>;
status = "disabled";
};
dmc: dmc { u-boot,dm-pre-reloc; compatible = "rockchip,rk3399-dmc";
-- 2.17.1

On Tue, 31 Mar 2020 at 15:10, Lin Jinhan troy.lin@rock-chips.com wrote:
Add rng node in rk3399-u-boot.dtsi and enable it in rk3399-evb-u-boot.dtsi.
Signed-off-by: Lin Jinhan troy.lin@rock-chips.com
For the series
Reviewed-by: Sughosh Ganu sughosh.ganu@linaro.org
I guess Kever can pick it up directly in the rockchip tree. Thanks.
-sughosh
arch/arm/dts/rk3399-evb-u-boot.dtsi | 5 +++++ arch/arm/dts/rk3399-u-boot.dtsi | 6 ++++++ 2 files changed, 11 insertions(+)
diff --git a/arch/arm/dts/rk3399-evb-u-boot.dtsi b/arch/arm/dts/rk3399-evb-u-boot.dtsi index ccb33d34d1..5b50c5ba30 100644 --- a/arch/arm/dts/rk3399-evb-u-boot.dtsi +++ b/arch/arm/dts/rk3399-evb-u-boot.dtsi @@ -11,3 +11,8 @@ u-boot,spl-boot-order = &sdhci, &sdmmc; }; };
+&rng {
status = "okay";
+};
diff --git a/arch/arm/dts/rk3399-u-boot.dtsi b/arch/arm/dts/rk3399-u-boot.dtsi index 8b857ccfc7..757b8c10a2 100644 --- a/arch/arm/dts/rk3399-u-boot.dtsi +++ b/arch/arm/dts/rk3399-u-boot.dtsi @@ -25,6 +25,12 @@ clock-names = "pclk_ddr_mon"; };
rng: rng@ff8b8000 {
compatible = "rockchip,cryptov1-rng";
reg = <0x0 0xff8b8000 0x0 0x1000>;
status = "disabled";
};
dmc: dmc { u-boot,dm-pre-reloc; compatible = "rockchip,rk3399-dmc";
-- 2.17.1

On 2020/3/31 下午5:39, Lin Jinhan wrote:
Add rng node in rk3399-u-boot.dtsi and enable it in rk3399-evb-u-boot.dtsi.
Signed-off-by: Lin Jinhan troy.lin@rock-chips.com
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
arch/arm/dts/rk3399-evb-u-boot.dtsi | 5 +++++ arch/arm/dts/rk3399-u-boot.dtsi | 6 ++++++ 2 files changed, 11 insertions(+)
diff --git a/arch/arm/dts/rk3399-evb-u-boot.dtsi b/arch/arm/dts/rk3399-evb-u-boot.dtsi index ccb33d34d1..5b50c5ba30 100644 --- a/arch/arm/dts/rk3399-evb-u-boot.dtsi +++ b/arch/arm/dts/rk3399-evb-u-boot.dtsi @@ -11,3 +11,8 @@ u-boot,spl-boot-order = &sdhci, &sdmmc; }; };
+&rng {
- status = "okay";
+};
diff --git a/arch/arm/dts/rk3399-u-boot.dtsi b/arch/arm/dts/rk3399-u-boot.dtsi index 8b857ccfc7..757b8c10a2 100644 --- a/arch/arm/dts/rk3399-u-boot.dtsi +++ b/arch/arm/dts/rk3399-u-boot.dtsi @@ -25,6 +25,12 @@ clock-names = "pclk_ddr_mon"; };
- rng: rng@ff8b8000 {
compatible = "rockchip,cryptov1-rng";
reg = <0x0 0xff8b8000 0x0 0x1000>;
status = "disabled";
- };
- dmc: dmc { u-boot,dm-pre-reloc; compatible = "rockchip,rk3399-dmc";
participants (4)
-
Kever Yang
-
Lin Jinhan
-
Peter Robinson
-
Sughosh Ganu