[PATCH v3 1/1] drivers: rng: add support for Meson S4

neil.armstrong at linaro.org neil.armstrong at linaro.org
Thu Oct 12 13:37:37 CEST 2023


On 12/10/2023 09:58, Alexey Romanov wrote:
> For some Amlogic SOC's, mechanism to obtain random number
> has been changed. For example, S4 now uses status bit waiting algo.
> 
> Signed-off-by: Alexey Romanov <avromanov at salutedevices.com>
> ---
>   drivers/rng/meson-rng.c | 72 ++++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 71 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/rng/meson-rng.c b/drivers/rng/meson-rng.c
> index e0a1e8c7e0..fd2988e91b 100644
> --- a/drivers/rng/meson-rng.c
> +++ b/drivers/rng/meson-rng.c
> @@ -10,10 +10,23 @@
>   #include <dm.h>
>   #include <rng.h>
>   #include <asm/io.h>
> +#include <linux/iopoll.h>
> +
> +#define RNG_DATA	0x00
> +#define RNG_S4_DATA	0x08
> +#define RNG_S4_CFG	0x00
> +
> +#define RUN_BIT		BIT(0)
> +#define SEED_READY_STS_BIT	BIT(31)
> +
> +struct meson_rng_priv {
> +	u32 (*read)(fdt_addr_t base);
> +};
>   
>   struct meson_rng_plat {
>   	fdt_addr_t base;
>   	struct clk clk;
> +	struct meson_rng_priv *priv;
>   };
>   
>   /**
> @@ -27,10 +40,11 @@ struct meson_rng_plat {
>   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_priv *priv = pdata->priv;
>   	char *buffer = (char *)data;
>   
>   	while (len) {
> -		u32 rand = readl(pdata->base);
> +		u32 rand = priv->read(pdata->base);
>   		size_t step;
>   
>   		if (len >= 4)
> @@ -44,6 +58,47 @@ static int meson_rng_read(struct udevice *dev, void *data, size_t len)
>   	return 0;
>   }
>   
> +static int meson_rng_wait_status(void __iomem *cfg_addr, int bit)
> +{
> +	u32 status = 0;
> +	int ret;
> +
> +	ret = readl_relaxed_poll_timeout(cfg_addr,
> +					 status, !(status & bit),
> +					 10000);
> +	if (ret)
> +		return -EBUSY;
> +
> +	return 0;
> +}
> +
> +static u32 meson_common_rng_read(fdt_addr_t base)
> +{
> +	return readl(base);
> +}
> +
> +static u32 meson_s4_rng_read(fdt_addr_t base)
> +{
> +	void __iomem *cfg_addr = (void *)base + RNG_S4_CFG;
> +	int err;
> +
> +	writel_relaxed(readl_relaxed(cfg_addr) | SEED_READY_STS_BIT, cfg_addr);
> +
> +	err = meson_rng_wait_status(cfg_addr, SEED_READY_STS_BIT);
> +	if (err) {
> +		pr_err("Seed isn't ready, try again\n");
> +		return err;
> +	}
> +
> +	err = meson_rng_wait_status(cfg_addr, RUN_BIT);
> +	if (err) {
> +		pr_err("Can't get random number, try again\n");
> +		return err;
> +	}
> +
> +	return readl_relaxed(base + RNG_S4_DATA);
> +}
> +
>   /**
>    * meson_rng_probe() - probe rng device
>    *
> @@ -59,6 +114,8 @@ static int meson_rng_probe(struct udevice *dev)
>   	if (err)
>   		return err;
>   
> +	pdata->priv = (struct meson_rng_priv *)dev_get_driver_data(dev);
> +
>   	return 0;
>   }
>   
> @@ -102,9 +159,22 @@ static const struct dm_rng_ops meson_rng_ops = {
>   	.read = meson_rng_read,
>   };
>   
> +static const struct meson_rng_priv meson_rng_priv = {
> +	.read = meson_common_rng_read,
> +};
> +
> +static const struct meson_rng_priv meson_rng_priv_s4 = {
> +	.read = meson_s4_rng_read,
> +};
> +
>   static const struct udevice_id meson_rng_match[] = {
>   	{
>   		.compatible = "amlogic,meson-rng",
> +		.data = (ulong)&meson_rng_priv,
> +	},
> +	{
> +		.compatible = "amlogic,meson-s4-rng",
> +		.data = (ulong)&meson_rng_priv_s4,
>   	},
>   	{},
>   };

Reviewed-by: Neil Armstrong <neil.armstrong at linaro.org>


More information about the U-Boot mailing list