1bc85b25eSAlessandro Rubini /* 2bc85b25eSAlessandro Rubini * Nomadik RNG support 3bc85b25eSAlessandro Rubini * Copyright 2009 Alessandro Rubini 4bc85b25eSAlessandro Rubini * 5bc85b25eSAlessandro Rubini * This program is free software; you can redistribute it and/or modify 6bc85b25eSAlessandro Rubini * it under the terms of the GNU General Public License as published by 7bc85b25eSAlessandro Rubini * the Free Software Foundation; either version 2 of the License, or 8bc85b25eSAlessandro Rubini * (at your option) any later version. 9bc85b25eSAlessandro Rubini */ 10bc85b25eSAlessandro Rubini 11bc85b25eSAlessandro Rubini #include <linux/kernel.h> 12bc85b25eSAlessandro Rubini #include <linux/module.h> 13bc85b25eSAlessandro Rubini #include <linux/init.h> 14bc85b25eSAlessandro Rubini #include <linux/device.h> 15bc85b25eSAlessandro Rubini #include <linux/amba/bus.h> 16bc85b25eSAlessandro Rubini #include <linux/hw_random.h> 17bc85b25eSAlessandro Rubini #include <linux/io.h> 181944cc89SSrinidhi Kasagar #include <linux/clk.h> 191944cc89SSrinidhi Kasagar #include <linux/err.h> 201944cc89SSrinidhi Kasagar 211944cc89SSrinidhi Kasagar static struct clk *rng_clk; 22bc85b25eSAlessandro Rubini 23bc85b25eSAlessandro Rubini static int nmk_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) 24bc85b25eSAlessandro Rubini { 25bc85b25eSAlessandro Rubini void __iomem *base = (void __iomem *)rng->priv; 26bc85b25eSAlessandro Rubini 27bc85b25eSAlessandro Rubini /* 28bc85b25eSAlessandro Rubini * The register is 32 bits and gives 16 random bits (low half). 29bc85b25eSAlessandro Rubini * A subsequent read will delay the core for 400ns, so we just read 30bc85b25eSAlessandro Rubini * once and accept the very unlikely very small delay, even if wait==0. 31bc85b25eSAlessandro Rubini */ 32bc85b25eSAlessandro Rubini *(u16 *)data = __raw_readl(base + 8) & 0xffff; 33bc85b25eSAlessandro Rubini return 2; 34bc85b25eSAlessandro Rubini } 35bc85b25eSAlessandro Rubini 36bc85b25eSAlessandro Rubini /* we have at most one RNG per machine, granted */ 37bc85b25eSAlessandro Rubini static struct hwrng nmk_rng = { 38bc85b25eSAlessandro Rubini .name = "nomadik", 39bc85b25eSAlessandro Rubini .read = nmk_rng_read, 40bc85b25eSAlessandro Rubini }; 41bc85b25eSAlessandro Rubini 42bc85b25eSAlessandro Rubini static int nmk_rng_probe(struct amba_device *dev, struct amba_id *id) 43bc85b25eSAlessandro Rubini { 44bc85b25eSAlessandro Rubini void __iomem *base; 45bc85b25eSAlessandro Rubini int ret; 46bc85b25eSAlessandro Rubini 471944cc89SSrinidhi Kasagar rng_clk = clk_get(&dev->dev, NULL); 481944cc89SSrinidhi Kasagar if (IS_ERR(rng_clk)) { 491944cc89SSrinidhi Kasagar dev_err(&dev->dev, "could not get rng clock\n"); 501944cc89SSrinidhi Kasagar ret = PTR_ERR(rng_clk); 511944cc89SSrinidhi Kasagar return ret; 521944cc89SSrinidhi Kasagar } 531944cc89SSrinidhi Kasagar 541944cc89SSrinidhi Kasagar clk_enable(rng_clk); 551944cc89SSrinidhi Kasagar 56bc85b25eSAlessandro Rubini ret = amba_request_regions(dev, dev->dev.init_name); 57bc85b25eSAlessandro Rubini if (ret) 58bc85b25eSAlessandro Rubini return ret; 59bc85b25eSAlessandro Rubini ret = -ENOMEM; 60bc85b25eSAlessandro Rubini base = ioremap(dev->res.start, resource_size(&dev->res)); 61bc85b25eSAlessandro Rubini if (!base) 62bc85b25eSAlessandro Rubini goto out_release; 63bc85b25eSAlessandro Rubini nmk_rng.priv = (unsigned long)base; 64bc85b25eSAlessandro Rubini ret = hwrng_register(&nmk_rng); 65bc85b25eSAlessandro Rubini if (ret) 66bc85b25eSAlessandro Rubini goto out_unmap; 67bc85b25eSAlessandro Rubini return 0; 68bc85b25eSAlessandro Rubini 69bc85b25eSAlessandro Rubini out_unmap: 70bc85b25eSAlessandro Rubini iounmap(base); 71bc85b25eSAlessandro Rubini out_release: 72bc85b25eSAlessandro Rubini amba_release_regions(dev); 731944cc89SSrinidhi Kasagar clk_disable(rng_clk); 741944cc89SSrinidhi Kasagar clk_put(rng_clk); 75bc85b25eSAlessandro Rubini return ret; 76bc85b25eSAlessandro Rubini } 77bc85b25eSAlessandro Rubini 78bc85b25eSAlessandro Rubini static int nmk_rng_remove(struct amba_device *dev) 79bc85b25eSAlessandro Rubini { 80bc85b25eSAlessandro Rubini void __iomem *base = (void __iomem *)nmk_rng.priv; 81bc85b25eSAlessandro Rubini hwrng_unregister(&nmk_rng); 82bc85b25eSAlessandro Rubini iounmap(base); 83bc85b25eSAlessandro Rubini amba_release_regions(dev); 841944cc89SSrinidhi Kasagar clk_disable(rng_clk); 851944cc89SSrinidhi Kasagar clk_put(rng_clk); 86bc85b25eSAlessandro Rubini return 0; 87bc85b25eSAlessandro Rubini } 88bc85b25eSAlessandro Rubini 89bc85b25eSAlessandro Rubini static struct amba_id nmk_rng_ids[] = { 90bc85b25eSAlessandro Rubini { 91bc85b25eSAlessandro Rubini .id = 0x000805e1, 92bc85b25eSAlessandro Rubini .mask = 0x000fffff, /* top bits are rev and cfg: accept all */ 93bc85b25eSAlessandro Rubini }, 94bc85b25eSAlessandro Rubini {0, 0}, 95bc85b25eSAlessandro Rubini }; 96bc85b25eSAlessandro Rubini 97bc85b25eSAlessandro Rubini static struct amba_driver nmk_rng_driver = { 98bc85b25eSAlessandro Rubini .drv = { 99bc85b25eSAlessandro Rubini .owner = THIS_MODULE, 100bc85b25eSAlessandro Rubini .name = "rng", 101bc85b25eSAlessandro Rubini }, 102bc85b25eSAlessandro Rubini .probe = nmk_rng_probe, 103bc85b25eSAlessandro Rubini .remove = nmk_rng_remove, 104bc85b25eSAlessandro Rubini .id_table = nmk_rng_ids, 105bc85b25eSAlessandro Rubini }; 106bc85b25eSAlessandro Rubini 107bc85b25eSAlessandro Rubini static int __init nmk_rng_init(void) 108bc85b25eSAlessandro Rubini { 109bc85b25eSAlessandro Rubini return amba_driver_register(&nmk_rng_driver); 110bc85b25eSAlessandro Rubini } 111bc85b25eSAlessandro Rubini 112bc85b25eSAlessandro Rubini static void __devexit nmk_rng_exit(void) 113bc85b25eSAlessandro Rubini { 114bc85b25eSAlessandro Rubini amba_driver_unregister(&nmk_rng_driver); 115bc85b25eSAlessandro Rubini } 116bc85b25eSAlessandro Rubini 117bc85b25eSAlessandro Rubini module_init(nmk_rng_init); 118bc85b25eSAlessandro Rubini module_exit(nmk_rng_exit); 119bc85b25eSAlessandro Rubini 120bc85b25eSAlessandro Rubini MODULE_LICENSE("GPL"); 121