[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