[PATCH v1] drivers: rng: add check status bit feature

neil.armstrong at linaro.org neil.armstrong at linaro.org
Thu Jun 22 18:18:28 CEST 2023


Hi,

On 21/06/2023 12:24, Alexey Romanov wrote:
> For some Amlogic SOC's, the mechanism for obtain a random number
> has been changed. For example, S4 now uses a status bit wait algo.

Thanks for the change, but could you add this first in Linux with the
associated bindings update and DT changes then port it to U-boot ?

Thanks,
Neil

> 
> Signed-off-by: Alexey Romanov <avromanov at sberdevices.ru>
> ---
>   drivers/rng/meson-rng.c | 73 +++++++++++++++++++++++++++++++++++++----
>   1 file changed, 67 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/rng/meson-rng.c b/drivers/rng/meson-rng.c
> index e0a1e8c7e04..3bf2eb9cf87 100644
> --- a/drivers/rng/meson-rng.c
> +++ b/drivers/rng/meson-rng.c
> @@ -11,36 +11,82 @@
>   #include <rng.h>
>   #include <asm/io.h>
>   
> +struct meson_rng_data {
> +	bool check_status_bit;
> +};
> +
>   struct meson_rng_plat {
>   	fdt_addr_t base;
>   	struct clk clk;
> +	struct meson_rng_data *data;
>   };
>   
> +#define RETRY_CNT 100
> +#define RNG_OUT_OFFSET 0x08
> +
> +#define SEED_READY_STS_BIT 0
> +#define RUN_BIT 31
> +
> +static int meson_rng_wait_status(struct meson_rng_plat *pdata, int bit)
> +{
> +	u32 status;
> +	u32 cnt = 0;
> +
> +	pr_debug("Poll status of bit: %d\n", bit);
> +
> +	do {
> +		status = readl(pdata->base) & BIT(bit);
> +	} while (status && (cnt++ < RETRY_CNT));
> +
> +	if (cnt == RETRY_CNT) {
> +		pr_err("Can't get random number, try again");
> +		return -EBUSY;
> +	}
> +
> +	return 0;
> +}
> +
>   /**
>    * meson_rng_read() - fill buffer with random bytes
>    *
>    * @buffer:	buffer to receive data
>    * @size:	size of buffer
>    *
> - * Return:	0
> + * Return:	0 on success or -errno in failure
>    */
>   static int meson_rng_read(struct udevice *dev, void *data, size_t len)
>   {
>   	struct meson_rng_plat *pdata = dev_get_plat(dev);
> +	struct meson_rng_data *rng_data = pdata->data;
>   	char *buffer = (char *)data;
> +	int err;
>   
>   	while (len) {
> -		u32 rand = readl(pdata->base);
> +		u32 rand;
>   		size_t step;
>   
> -		if (len >= 4)
> -			step = 4;
> -		else
> -			step = len;
> +		if (rng_data->check_status_bit) {
> +			writel(readl(pdata->base) | BIT(SEED_READY_STS_BIT), pdata->base);
> +
> +			err = meson_rng_wait_status(pdata, SEED_READY_STS_BIT);
> +			if (err)
> +				return err;
> +
> +			err = meson_rng_wait_status(pdata, RUN_BIT);
> +			if (err)
> +				return err;
> +
> +			rand = readl(pdata->base + RNG_OUT_OFFSET);
> +		} else {
> +			rand = readl(pdata->base);
> +		}
> +
> +		step = min_t(u32, len, 4);
>   		memcpy(buffer, &rand, step);
>   		buffer += step;
>   		len -= step;
>   	}
> +
>   	return 0;
>   }
>   
> @@ -90,6 +136,8 @@ static int meson_rng_of_to_plat(struct udevice *dev)
>   	if (!pdata->base)
>   		return -ENODEV;
>   
> +	pdata->data = (struct meson_rng_data *)dev_get_driver_data(dev);
> +
>   	/* Get optional "core" clock */
>   	err = clk_get_by_name_optional(dev, "core", &pdata->clk);
>   	if (err)
> @@ -102,9 +150,22 @@ static const struct dm_rng_ops meson_rng_ops = {
>   	.read = meson_rng_read,
>   };
>   
> +static const struct meson_rng_data meson_rng_data = {
> +	.check_status_bit = false,
> +};
> +
> +static const struct meson_rng_data meson_rng_data_s4 = {
> +	.check_status_bit = true,
> +};
> +
>   static const struct udevice_id meson_rng_match[] = {
>   	{
>   		.compatible = "amlogic,meson-rng",
> +		.data = (ulong)&meson_rng_data,
> +	},
> +	{
> +		.compatible = "amlogic,meson-rng-s4",
> +		.data = (ulong)&meson_rng_data_s4,
>   	},
>   	{},
>   };



More information about the U-Boot mailing list