[PATCH v1] drivers: rng: add check status bit feature
Alexey Romanov
AVRomanov at sberdevices.ru
Fri Jun 23 12:53:43 CEST 2023
Hello!
On Thu, Jun 22, 2023 at 06:18:28PM +0200, neil.armstrong at linaro.org wrote:
> 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,
> > },
> > {},
> > };
>
Sure, I will prepare patches and send them in LKML next week.
--
Thank you,
Alexey
More information about the U-Boot
mailing list