diff options
author | Tom Rini <trini@konsulko.com> | 2023-10-16 09:09:54 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2023-10-16 09:09:54 -0400 |
commit | 2e1577e8360d8e467bf28009f6763a2ac511f743 (patch) | |
tree | cf05b376e7b46e4b5b4b61d04f6976de85ab31d4 /drivers/rng/meson-rng.c | |
parent | 3c3f1626919cd93cbe6c56e3849937de5be18dbb (diff) | |
parent | 7cd53e0d5203f8e25bb69d2e675769888fcbc754 (diff) |
Merge tag 'u-boot-amlogic-20231015' of https://source.denx.de/u-boot/custodians/u-boot-amlogic
- add Amlogic A1 clock driver
- add Amlogic A1 reset support
- add USB Device support for Amlogic A1
- enable RNG on Amlogic A1 & Amlogic S4
- move Amlogic Secure Monitor to standalone driver
Diffstat (limited to 'drivers/rng/meson-rng.c')
-rw-r--r-- | drivers/rng/meson-rng.c | 72 |
1 files changed, 71 insertions, 1 deletions
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, }, {}, }; |