0001
0002
0003
0004
0005
0006 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0007
0008 #include <linux/module.h>
0009 #include <linux/mod_devicetable.h>
0010 #include <linux/kernel.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/random.h>
0013 #include <linux/hw_random.h>
0014
0015 static int powernv_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
0016 {
0017 unsigned long *buf;
0018 int i, len;
0019
0020
0021 len = max / sizeof(unsigned long);
0022
0023 buf = (unsigned long *)data;
0024
0025 for (i = 0; i < len; i++)
0026 pnv_get_random_long(buf++);
0027
0028 return len * sizeof(unsigned long);
0029 }
0030
0031 static struct hwrng powernv_hwrng = {
0032 .name = "powernv-rng",
0033 .read = powernv_rng_read,
0034 };
0035
0036 static int powernv_rng_probe(struct platform_device *pdev)
0037 {
0038 int rc;
0039
0040 rc = devm_hwrng_register(&pdev->dev, &powernv_hwrng);
0041 if (rc) {
0042
0043 if (rc == -EEXIST)
0044 rc = -ENODEV;
0045
0046 return rc;
0047 }
0048
0049 pr_info("Registered powernv hwrng.\n");
0050
0051 return 0;
0052 }
0053
0054 static const struct of_device_id powernv_rng_match[] = {
0055 { .compatible = "ibm,power-rng",},
0056 {},
0057 };
0058 MODULE_DEVICE_TABLE(of, powernv_rng_match);
0059
0060 static struct platform_driver powernv_rng_driver = {
0061 .driver = {
0062 .name = "powernv_rng",
0063 .of_match_table = powernv_rng_match,
0064 },
0065 .probe = powernv_rng_probe,
0066 };
0067 module_platform_driver(powernv_rng_driver);
0068
0069 MODULE_LICENSE("GPL");
0070 MODULE_DESCRIPTION("Bare metal HWRNG driver for POWER7+ and above");