^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Nomadik RNG support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright 2009 Alessandro Rubini
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/amba/bus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/hw_random.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static struct clk *rng_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static int nmk_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) void __iomem *base = (void __iomem *)rng->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * The register is 32 bits and gives 16 random bits (low half).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * A subsequent read will delay the core for 400ns, so we just read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * once and accept the very unlikely very small delay, even if wait==0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *(u16 *)data = __raw_readl(base + 8) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* we have at most one RNG per machine, granted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static struct hwrng nmk_rng = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) .name = "nomadik",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) .read = nmk_rng_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) rng_clk = devm_clk_get(&dev->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (IS_ERR(rng_clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) dev_err(&dev->dev, "could not get rng clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) ret = PTR_ERR(rng_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) clk_prepare_enable(rng_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) ret = amba_request_regions(dev, dev->dev.init_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) goto out_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) base = devm_ioremap(&dev->dev, dev->res.start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) resource_size(&dev->res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (!base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) goto out_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) nmk_rng.priv = (unsigned long)base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) ret = devm_hwrng_register(&dev->dev, &nmk_rng);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) goto out_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) out_release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) amba_release_regions(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) out_clk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) clk_disable_unprepare(rng_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static void nmk_rng_remove(struct amba_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) amba_release_regions(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) clk_disable_unprepare(rng_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static const struct amba_id nmk_rng_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .id = 0x000805e1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .mask = 0x000fffff, /* top bits are rev and cfg: accept all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) MODULE_DEVICE_TABLE(amba, nmk_rng_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static struct amba_driver nmk_rng_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .name = "rng",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .probe = nmk_rng_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .remove = nmk_rng_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .id_table = nmk_rng_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) module_amba_driver(nmk_rng_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) MODULE_LICENSE("GPL");