lkml.org 
[lkml]   [2023]   [Sep]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v5 1/3] drivers: rng: meson: add support for S4
    Date
    From: Alexey Romanov <avromanov@sberdevices.ru>

    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@sberdevices.ru>
    ---
    drivers/char/hw_random/meson-rng.c | 80 ++++++++++++++++++++++++++++--
    1 file changed, 77 insertions(+), 3 deletions(-)

    diff --git a/drivers/char/hw_random/meson-rng.c b/drivers/char/hw_random/meson-rng.c
    index a4eb8e35f13d..75225eb9fef6 100644
    --- a/drivers/char/hw_random/meson-rng.c
    +++ b/drivers/char/hw_random/meson-rng.c
    @@ -13,12 +13,23 @@
    #include <linux/types.h>
    #include <linux/of.h>
    #include <linux/clk.h>
    +#include <linux/iopoll.h>

    -#define RNG_DATA 0x00
    +#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 {
    + int (*read)(struct hwrng *rng, void *buf, size_t max, bool wait);
    +};

    struct meson_rng_data {
    void __iomem *base;
    struct hwrng rng;
    + struct device *dev;
    };

    static int meson_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
    @@ -31,16 +42,62 @@ static int meson_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
    return sizeof(u32);
    }

    +static int meson_rng_wait_status(void __iomem *cfg_addr, int bit)
    +{
    + u32 status = 0;
    + int ret;
    +
    + ret = readl_relaxed_poll_timeout_atomic(cfg_addr,
    + status, !(status & bit),
    + 10, 10000);
    + if (ret)
    + return -EBUSY;
    +
    + return 0;
    +}
    +
    +static int meson_s4_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
    +{
    + struct meson_rng_data *data =
    + container_of(rng, struct meson_rng_data, rng);
    +
    + void __iomem *cfg_addr = data->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) {
    + dev_err(data->dev, "Seed isn't ready, try again\n");
    + return err;
    + }
    +
    + err = meson_rng_wait_status(cfg_addr, RUN_BIT);
    + if (err) {
    + dev_err(data->dev, "Can't get random number, try again\n");
    + return err;
    + }
    +
    + *(u32 *)buf = readl_relaxed(data->base + RNG_S4_DATA);
    +
    + return sizeof(u32);
    +}
    +
    static int meson_rng_probe(struct platform_device *pdev)
    {
    struct device *dev = &pdev->dev;
    struct meson_rng_data *data;
    struct clk *core_clk;
    + const struct meson_rng_priv *priv;

    data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
    if (!data)
    return -ENOMEM;

    + priv = device_get_match_data(&pdev->dev);
    + if (!priv)
    + return -ENODEV;
    +
    data->base = devm_platform_ioremap_resource(pdev, 0);
    if (IS_ERR(data->base))
    return PTR_ERR(data->base);
    @@ -51,13 +108,30 @@ static int meson_rng_probe(struct platform_device *pdev)
    "Failed to get core clock\n");

    data->rng.name = pdev->name;
    - data->rng.read = meson_rng_read;
    + data->rng.read = priv->read;
    +
    + data->dev = &pdev->dev;

    return devm_hwrng_register(dev, &data->rng);
    }

    +static const struct meson_rng_priv meson_rng_priv = {
    + .read = meson_rng_read,
    +};
    +
    +static const struct meson_rng_priv meson_rng_priv_s4 = {
    + .read = meson_s4_rng_read,
    +};
    +
    static const struct of_device_id meson_rng_of_match[] = {
    - { .compatible = "amlogic,meson-rng", },
    + {
    + .compatible = "amlogic,meson-rng",
    + .data = (void *)&meson_rng_priv,
    + },
    + {
    + .compatible = "amlogic,meson-s4-rng",
    + .data = (void *)&meson_rng_priv_s4,
    + },
    {},
    };
    MODULE_DEVICE_TABLE(of, meson_rng_of_match);
    --
    2.25.1
    \
     
     \ /
      Last update: 2023-09-29 12:34    [W:3.396 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site