powernv-rng.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /*
  2. * Copyright 2013 Michael Ellerman, Guo Chao, IBM Corp.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version
  7. * 2 of the License, or (at your option) any later version.
  8. */
  9. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  10. #include <linux/module.h>
  11. #include <linux/mod_devicetable.h>
  12. #include <linux/kernel.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/random.h>
  15. #include <linux/hw_random.h>
  16. static int powernv_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
  17. {
  18. unsigned long *buf;
  19. int i, len;
  20. /* We rely on rng_buffer_size() being >= sizeof(unsigned long) */
  21. len = max / sizeof(unsigned long);
  22. buf = (unsigned long *)data;
  23. for (i = 0; i < len; i++)
  24. powernv_get_random_long(buf++);
  25. return len * sizeof(unsigned long);
  26. }
  27. static struct hwrng powernv_hwrng = {
  28. .name = "powernv-rng",
  29. .read = powernv_rng_read,
  30. };
  31. static int powernv_rng_remove(struct platform_device *pdev)
  32. {
  33. hwrng_unregister(&powernv_hwrng);
  34. return 0;
  35. }
  36. static int powernv_rng_probe(struct platform_device *pdev)
  37. {
  38. int rc;
  39. rc = hwrng_register(&powernv_hwrng);
  40. if (rc) {
  41. /* We only register one device, ignore any others */
  42. if (rc == -EEXIST)
  43. rc = -ENODEV;
  44. return rc;
  45. }
  46. pr_info("Registered powernv hwrng.\n");
  47. return 0;
  48. }
  49. static const struct of_device_id powernv_rng_match[] = {
  50. { .compatible = "ibm,power-rng",},
  51. {},
  52. };
  53. MODULE_DEVICE_TABLE(of, powernv_rng_match);
  54. static struct platform_driver powernv_rng_driver = {
  55. .driver = {
  56. .name = "powernv_rng",
  57. .of_match_table = powernv_rng_match,
  58. },
  59. .probe = powernv_rng_probe,
  60. .remove = powernv_rng_remove,
  61. };
  62. module_platform_driver(powernv_rng_driver);
  63. MODULE_LICENSE("GPL");
  64. MODULE_DESCRIPTION("Bare metal HWRNG driver for POWER7+ and above");