Message ID | 20230621102401.76646-1-avromanov@sberdevices.ru |
---|---|
State | Deferred |
Delegated to: | Tom Rini |
Headers | show |
Series | [v1] drivers: rng: add check status bit feature | expand |
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@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, > }, > {}, > };
Hello! On Thu, Jun 22, 2023 at 06:18:28PM +0200, neil.armstrong@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@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.
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, }, {}, };
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. Signed-off-by: Alexey Romanov <avromanov@sberdevices.ru> --- drivers/rng/meson-rng.c | 73 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 6 deletions(-)