0001
0002
0003
0004
0005
0006
0007 #include <linux/kernel.h>
0008 #include <linux/module.h>
0009 #include <linux/device.h>
0010 #include <linux/amba/bus.h>
0011 #include <linux/hw_random.h>
0012 #include <linux/io.h>
0013 #include <linux/clk.h>
0014 #include <linux/err.h>
0015
0016 static struct clk *rng_clk;
0017
0018 static int nmk_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
0019 {
0020 void __iomem *base = (void __iomem *)rng->priv;
0021
0022
0023
0024
0025
0026
0027 *(u16 *)data = __raw_readl(base + 8) & 0xffff;
0028 return 2;
0029 }
0030
0031
0032 static struct hwrng nmk_rng = {
0033 .name = "nomadik",
0034 .read = nmk_rng_read,
0035 };
0036
0037 static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id)
0038 {
0039 void __iomem *base;
0040 int ret;
0041
0042 rng_clk = devm_clk_get(&dev->dev, NULL);
0043 if (IS_ERR(rng_clk)) {
0044 dev_err(&dev->dev, "could not get rng clock\n");
0045 ret = PTR_ERR(rng_clk);
0046 return ret;
0047 }
0048
0049 clk_prepare_enable(rng_clk);
0050
0051 ret = amba_request_regions(dev, dev->dev.init_name);
0052 if (ret)
0053 goto out_clk;
0054 ret = -ENOMEM;
0055 base = devm_ioremap(&dev->dev, dev->res.start,
0056 resource_size(&dev->res));
0057 if (!base)
0058 goto out_release;
0059 nmk_rng.priv = (unsigned long)base;
0060 ret = devm_hwrng_register(&dev->dev, &nmk_rng);
0061 if (ret)
0062 goto out_release;
0063 return 0;
0064
0065 out_release:
0066 amba_release_regions(dev);
0067 out_clk:
0068 clk_disable_unprepare(rng_clk);
0069 return ret;
0070 }
0071
0072 static void nmk_rng_remove(struct amba_device *dev)
0073 {
0074 amba_release_regions(dev);
0075 clk_disable_unprepare(rng_clk);
0076 }
0077
0078 static const struct amba_id nmk_rng_ids[] = {
0079 {
0080 .id = 0x000805e1,
0081 .mask = 0x000fffff,
0082 },
0083 {0, 0},
0084 };
0085
0086 MODULE_DEVICE_TABLE(amba, nmk_rng_ids);
0087
0088 static struct amba_driver nmk_rng_driver = {
0089 .drv = {
0090 .owner = THIS_MODULE,
0091 .name = "rng",
0092 },
0093 .probe = nmk_rng_probe,
0094 .remove = nmk_rng_remove,
0095 .id_table = nmk_rng_ids,
0096 };
0097
0098 module_amba_driver(nmk_rng_driver);
0099
0100 MODULE_LICENSE("GPL");