12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2bc85b25eSAlessandro Rubini /* 3bc85b25eSAlessandro Rubini * Nomadik RNG support 4bc85b25eSAlessandro Rubini * Copyright 2009 Alessandro Rubini 5bc85b25eSAlessandro Rubini */ 6bc85b25eSAlessandro Rubini 7bc85b25eSAlessandro Rubini #include <linux/kernel.h> 8bc85b25eSAlessandro Rubini #include <linux/module.h> 9bc85b25eSAlessandro Rubini #include <linux/device.h> 10bc85b25eSAlessandro Rubini #include <linux/amba/bus.h> 11bc85b25eSAlessandro Rubini #include <linux/hw_random.h> 12bc85b25eSAlessandro Rubini #include <linux/io.h> 131944cc89SSrinidhi Kasagar #include <linux/clk.h> 141944cc89SSrinidhi Kasagar #include <linux/err.h> 151944cc89SSrinidhi Kasagar 161944cc89SSrinidhi Kasagar static struct clk *rng_clk; 17bc85b25eSAlessandro Rubini 18bc85b25eSAlessandro Rubini static int nmk_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) 19bc85b25eSAlessandro Rubini { 20bc85b25eSAlessandro Rubini void __iomem *base = (void __iomem *)rng->priv; 21bc85b25eSAlessandro Rubini 22bc85b25eSAlessandro Rubini /* 23bc85b25eSAlessandro Rubini * The register is 32 bits and gives 16 random bits (low half). 24bc85b25eSAlessandro Rubini * A subsequent read will delay the core for 400ns, so we just read 25bc85b25eSAlessandro Rubini * once and accept the very unlikely very small delay, even if wait==0. 26bc85b25eSAlessandro Rubini */ 27bc85b25eSAlessandro Rubini *(u16 *)data = __raw_readl(base + 8) & 0xffff; 28bc85b25eSAlessandro Rubini return 2; 29bc85b25eSAlessandro Rubini } 30bc85b25eSAlessandro Rubini 31bc85b25eSAlessandro Rubini /* we have at most one RNG per machine, granted */ 32bc85b25eSAlessandro Rubini static struct hwrng nmk_rng = { 33bc85b25eSAlessandro Rubini .name = "nomadik", 34bc85b25eSAlessandro Rubini .read = nmk_rng_read, 35bc85b25eSAlessandro Rubini }; 36bc85b25eSAlessandro Rubini 37aa25afadSRussell King static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id) 38bc85b25eSAlessandro Rubini { 39bc85b25eSAlessandro Rubini void __iomem *base; 40bc85b25eSAlessandro Rubini int ret; 41bc85b25eSAlessandro Rubini 421655c240SJingoo Han rng_clk = devm_clk_get(&dev->dev, NULL); 431944cc89SSrinidhi Kasagar if (IS_ERR(rng_clk)) { 441944cc89SSrinidhi Kasagar dev_err(&dev->dev, "could not get rng clock\n"); 451944cc89SSrinidhi Kasagar ret = PTR_ERR(rng_clk); 461944cc89SSrinidhi Kasagar return ret; 471944cc89SSrinidhi Kasagar } 481944cc89SSrinidhi Kasagar 49beca35d0SLinus Walleij clk_prepare_enable(rng_clk); 501944cc89SSrinidhi Kasagar 51bc85b25eSAlessandro Rubini ret = amba_request_regions(dev, dev->dev.init_name); 52bc85b25eSAlessandro Rubini if (ret) 532725ae17SJulia Lawall goto out_clk; 54bc85b25eSAlessandro Rubini ret = -ENOMEM; 551655c240SJingoo Han base = devm_ioremap(&dev->dev, dev->res.start, 561655c240SJingoo Han resource_size(&dev->res)); 57bc85b25eSAlessandro Rubini if (!base) 58bc85b25eSAlessandro Rubini goto out_release; 59bc85b25eSAlessandro Rubini nmk_rng.priv = (unsigned long)base; 603e75241bSChuhong Yuan ret = devm_hwrng_register(&dev->dev, &nmk_rng); 61bc85b25eSAlessandro Rubini if (ret) 621655c240SJingoo Han goto out_release; 63bc85b25eSAlessandro Rubini return 0; 64bc85b25eSAlessandro Rubini 65bc85b25eSAlessandro Rubini out_release: 66bc85b25eSAlessandro Rubini amba_release_regions(dev); 672725ae17SJulia Lawall out_clk: 681944cc89SSrinidhi Kasagar clk_disable(rng_clk); 69bc85b25eSAlessandro Rubini return ret; 70bc85b25eSAlessandro Rubini } 71bc85b25eSAlessandro Rubini 72bc85b25eSAlessandro Rubini static int nmk_rng_remove(struct amba_device *dev) 73bc85b25eSAlessandro Rubini { 74bc85b25eSAlessandro Rubini amba_release_regions(dev); 751944cc89SSrinidhi Kasagar clk_disable(rng_clk); 76bc85b25eSAlessandro Rubini return 0; 77bc85b25eSAlessandro Rubini } 78bc85b25eSAlessandro Rubini 79b242973fSRikard Falkeborn static const struct amba_id nmk_rng_ids[] = { 80bc85b25eSAlessandro Rubini { 81bc85b25eSAlessandro Rubini .id = 0x000805e1, 82bc85b25eSAlessandro Rubini .mask = 0x000fffff, /* top bits are rev and cfg: accept all */ 83bc85b25eSAlessandro Rubini }, 84bc85b25eSAlessandro Rubini {0, 0}, 85bc85b25eSAlessandro Rubini }; 86bc85b25eSAlessandro Rubini 874e3f3d53SDave Martin MODULE_DEVICE_TABLE(amba, nmk_rng_ids); 884e3f3d53SDave Martin 89bc85b25eSAlessandro Rubini static struct amba_driver nmk_rng_driver = { 90bc85b25eSAlessandro Rubini .drv = { 91bc85b25eSAlessandro Rubini .owner = THIS_MODULE, 92bc85b25eSAlessandro Rubini .name = "rng", 93bc85b25eSAlessandro Rubini }, 94bc85b25eSAlessandro Rubini .probe = nmk_rng_probe, 95bc85b25eSAlessandro Rubini .remove = nmk_rng_remove, 96bc85b25eSAlessandro Rubini .id_table = nmk_rng_ids, 97bc85b25eSAlessandro Rubini }; 98bc85b25eSAlessandro Rubini 999e5ed094Sviresh kumar module_amba_driver(nmk_rng_driver); 100bc85b25eSAlessandro Rubini 101bc85b25eSAlessandro Rubini MODULE_LICENSE("GPL"); 102