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 16bc85b25eSAlessandro Rubini static int nmk_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) 17bc85b25eSAlessandro Rubini { 18bc85b25eSAlessandro Rubini void __iomem *base = (void __iomem *)rng->priv; 19bc85b25eSAlessandro Rubini 20bc85b25eSAlessandro Rubini /* 21bc85b25eSAlessandro Rubini * The register is 32 bits and gives 16 random bits (low half). 22bc85b25eSAlessandro Rubini * A subsequent read will delay the core for 400ns, so we just read 23bc85b25eSAlessandro Rubini * once and accept the very unlikely very small delay, even if wait==0. 24bc85b25eSAlessandro Rubini */ 25bc85b25eSAlessandro Rubini *(u16 *)data = __raw_readl(base + 8) & 0xffff; 26bc85b25eSAlessandro Rubini return 2; 27bc85b25eSAlessandro Rubini } 28bc85b25eSAlessandro Rubini 29bc85b25eSAlessandro Rubini /* we have at most one RNG per machine, granted */ 30bc85b25eSAlessandro Rubini static struct hwrng nmk_rng = { 31bc85b25eSAlessandro Rubini .name = "nomadik", 32bc85b25eSAlessandro Rubini .read = nmk_rng_read, 33bc85b25eSAlessandro Rubini }; 34bc85b25eSAlessandro Rubini 35aa25afadSRussell King static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id) 36bc85b25eSAlessandro Rubini { 37*039980deSMartin Kaiser struct clk *rng_clk; 38bc85b25eSAlessandro Rubini void __iomem *base; 39bc85b25eSAlessandro Rubini int ret; 40bc85b25eSAlessandro Rubini 41*039980deSMartin Kaiser rng_clk = devm_clk_get_enabled(&dev->dev, NULL); 421944cc89SSrinidhi Kasagar if (IS_ERR(rng_clk)) { 431944cc89SSrinidhi Kasagar dev_err(&dev->dev, "could not get rng clock\n"); 441944cc89SSrinidhi Kasagar ret = PTR_ERR(rng_clk); 451944cc89SSrinidhi Kasagar return ret; 461944cc89SSrinidhi Kasagar } 471944cc89SSrinidhi Kasagar 48bc85b25eSAlessandro Rubini ret = amba_request_regions(dev, dev->dev.init_name); 49bc85b25eSAlessandro Rubini if (ret) 50*039980deSMartin Kaiser return ret; 51bc85b25eSAlessandro Rubini ret = -ENOMEM; 521655c240SJingoo Han base = devm_ioremap(&dev->dev, dev->res.start, 531655c240SJingoo Han resource_size(&dev->res)); 54bc85b25eSAlessandro Rubini if (!base) 55bc85b25eSAlessandro Rubini goto out_release; 56bc85b25eSAlessandro Rubini nmk_rng.priv = (unsigned long)base; 573e75241bSChuhong Yuan ret = devm_hwrng_register(&dev->dev, &nmk_rng); 58bc85b25eSAlessandro Rubini if (ret) 591655c240SJingoo Han goto out_release; 60bc85b25eSAlessandro Rubini return 0; 61bc85b25eSAlessandro Rubini 62bc85b25eSAlessandro Rubini out_release: 63bc85b25eSAlessandro Rubini amba_release_regions(dev); 64bc85b25eSAlessandro Rubini return ret; 65bc85b25eSAlessandro Rubini } 66bc85b25eSAlessandro Rubini 673fd269e7SUwe Kleine-König static void nmk_rng_remove(struct amba_device *dev) 68bc85b25eSAlessandro Rubini { 69bc85b25eSAlessandro Rubini amba_release_regions(dev); 70bc85b25eSAlessandro Rubini } 71bc85b25eSAlessandro Rubini 72b242973fSRikard Falkeborn static const struct amba_id nmk_rng_ids[] = { 73bc85b25eSAlessandro Rubini { 74bc85b25eSAlessandro Rubini .id = 0x000805e1, 75bc85b25eSAlessandro Rubini .mask = 0x000fffff, /* top bits are rev and cfg: accept all */ 76bc85b25eSAlessandro Rubini }, 77bc85b25eSAlessandro Rubini {0, 0}, 78bc85b25eSAlessandro Rubini }; 79bc85b25eSAlessandro Rubini 804e3f3d53SDave Martin MODULE_DEVICE_TABLE(amba, nmk_rng_ids); 814e3f3d53SDave Martin 82bc85b25eSAlessandro Rubini static struct amba_driver nmk_rng_driver = { 83bc85b25eSAlessandro Rubini .drv = { 84bc85b25eSAlessandro Rubini .owner = THIS_MODULE, 85bc85b25eSAlessandro Rubini .name = "rng", 86bc85b25eSAlessandro Rubini }, 87bc85b25eSAlessandro Rubini .probe = nmk_rng_probe, 88bc85b25eSAlessandro Rubini .remove = nmk_rng_remove, 89bc85b25eSAlessandro Rubini .id_table = nmk_rng_ids, 90bc85b25eSAlessandro Rubini }; 91bc85b25eSAlessandro Rubini 929e5ed094Sviresh kumar module_amba_driver(nmk_rng_driver); 93bc85b25eSAlessandro Rubini 94bc85b25eSAlessandro Rubini MODULE_LICENSE("GPL"); 95