On 24/10/2019 20:04:52+0300, Codrin Ciubotariu wrote: > Add platform support for the new IP found on sam9x60 SoC. For this > version, if the peripheral clk is above 100MHz, the HALFR bit must be > set. This bit is available only if the IP can generate a random number > every 168 cycles (instead of 84). > > Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@xxxxxxxxxxxxx> > --- > drivers/char/hw_random/atmel-rng.c | 39 ++++++++++++++++++++++++++++-- > 1 file changed, 37 insertions(+), 2 deletions(-) > > diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c > index e55705745d5e..0aa9425e6c3e 100644 > --- a/drivers/char/hw_random/atmel-rng.c > +++ b/drivers/char/hw_random/atmel-rng.c > @@ -14,14 +14,22 @@ > #include <linux/clk.h> > #include <linux/io.h> > #include <linux/hw_random.h> > +#include <linux/of_device.h> > #include <linux/platform_device.h> > > #define TRNG_CR 0x00 > +#define TRNG_MR 0x04 > #define TRNG_ISR 0x1c > #define TRNG_ODATA 0x50 > > #define TRNG_KEY 0x524e4700 /* RNG */ > > +#define TRNG_HALFR BIT(0) /* generate RN every 168 cycles */ > + > +struct atmel_trng_pdata { Could that be just atmel_trng_data? There is no platform data in this driver and it is DT only. > + bool has_half_rate; > +}; > + > struct atmel_trng { > struct clk *clk; > void __iomem *base; > @@ -63,6 +71,7 @@ static int atmel_trng_probe(struct platform_device *pdev) > { > struct atmel_trng *trng; > struct resource *res; > + const struct atmel_trng_pdata *pdata; > int ret; > > trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL); > @@ -77,6 +86,17 @@ static int atmel_trng_probe(struct platform_device *pdev) > trng->clk = devm_clk_get(&pdev->dev, NULL); > if (IS_ERR(trng->clk)) > return PTR_ERR(trng->clk); > + pdata = of_device_get_match_data(&pdev->dev); > + if (!pdata) > + return -ENODEV; > + > + if (pdata->has_half_rate) { > + unsigned long rate = clk_get_rate(trng->clk); > + > + /* if peripheral clk is above 100MHz, set HALFR */ > + if (rate > 100000000) > + writel(TRNG_HALFR, trng->base + TRNG_MR); > + } > > ret = clk_prepare_enable(trng->clk); > if (ret) > @@ -141,9 +161,24 @@ static const struct dev_pm_ops atmel_trng_pm_ops = { > }; > #endif /* CONFIG_PM */ > > +static struct atmel_trng_pdata at91sam9g45_config = { > + .has_half_rate = false, > +}; > + > +static struct atmel_trng_pdata sam9x60_config = { > + .has_half_rate = true, > +}; > + > static const struct of_device_id atmel_trng_dt_ids[] = { > - { .compatible = "atmel,at91sam9g45-trng" }, > - { /* sentinel */ } > + { > + .compatible = "atmel,at91sam9g45-trng", > + .data = &at91sam9g45_config, > + }, { > + .compatible = "microchip,sam9x60-trng", > + .data = &sam9x60_config, > + }, { > + /* sentinel */ > + } > }; > MODULE_DEVICE_TABLE(of, atmel_trng_dt_ids); > > -- > 2.20.1 > -- Alexandre Belloni, Bootlin Embedded Linux and Kernel engineering https://bootlin.com